File tree 7 files changed +67
-7
lines changed
7 files changed +67
-7
lines changed Original file line number Diff line number Diff line change @@ -1248,8 +1248,12 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
1248
1248
1249
1249
if opts .LabelIDs != nil {
1250
1250
for i , labelID := range opts .LabelIDs {
1251
- sess .Join ("INNER" , fmt .Sprintf ("issue_label il%d" , i ),
1252
- fmt .Sprintf ("issue.id = il%[1]d.issue_id AND il%[1]d.label_id = %[2]d" , i , labelID ))
1251
+ if labelID > 0 {
1252
+ sess .Join ("INNER" , fmt .Sprintf ("issue_label il%d" , i ),
1253
+ fmt .Sprintf ("issue.id = il%[1]d.issue_id AND il%[1]d.label_id = %[2]d" , i , labelID ))
1254
+ } else {
1255
+ sess .Where ("issue.id not in (select issue_id from issue_label where label_id = ?)" , - labelID )
1256
+ }
1253
1257
}
1254
1258
}
1255
1259
}
Original file line number Diff line number Diff line change @@ -72,6 +72,7 @@ type Label struct {
72
72
IsChecked bool `xorm:"-"`
73
73
QueryString string `xorm:"-"`
74
74
IsSelected bool `xorm:"-"`
75
+ IsExcluded bool `xorm:"-"`
75
76
}
76
77
77
78
// APIFormat converts a Label to the api.Label format
@@ -97,7 +98,10 @@ func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64)
97
98
for _ , s := range currentSelectedLabels {
98
99
if s == label .ID {
99
100
labelSelected = true
100
- } else if s > 0 {
101
+ } else if - s == label .ID {
102
+ labelSelected = true
103
+ label .IsExcluded = true
104
+ } else if s != 0 {
101
105
labelQuerySlice = append (labelQuerySlice , strconv .FormatInt (s , 10 ))
102
106
}
103
107
}
Original file line number Diff line number Diff line change @@ -802,6 +802,7 @@ issues.delete_branch_at = `deleted branch <b>%s</b> %s`
802
802
issues.open_tab = %d Open
803
803
issues.close_tab = %d Closed
804
804
issues.filter_label = Label
805
+ issues.filter_label_exclude = `Use <code>alt</code> + <code>click/enter</code> to exclude labels`
805
806
issues.filter_label_no_select = All labels
806
807
issues.filter_milestone = Milestone
807
808
issues.filter_milestone_no_select = All milestones
Original file line number Diff line number Diff line change @@ -458,6 +458,8 @@ i.icon.centerlock{top:1.5em}
458
458
.repository .filter .menu .label .color {border-radius : 3px ;margin-left : 15px ;padding : 0 8px }
459
459
.repository .filter .menu .octicon {float : left;margin : 5px -7px 0 -5px ;width : 16px }
460
460
.repository .filter .menu .labels .octicon {margin : -2px -7px 0 -5px }
461
+ .repository .filter .menu .labels .label-filter .menu .info {display : inline-block;padding : 9px 7px 7px 7px ;text-align : center;border-bottom : 1px solid # ccc ;font-size : 12px }
462
+ .repository .filter .menu .labels .label-filter .menu .info code {border : 1px solid # ccc ;border-radius : 3px ;padding : 3px 2px 1px 2px ;font-size : 11px }
461
463
.repository .filter .menu .text {margin-left : .9em }
462
464
.repository .filter .menu .menu {max-height : 300px ;overflow-x : auto;right : 0 !important ;left : auto!important }
463
465
.repository .filter .menu .dropdown .item {margin : 1px ;padding-right : 0 }
Original file line number Diff line number Diff line change @@ -3278,8 +3278,39 @@ function initIssueList() {
3278
3278
} ,
3279
3279
3280
3280
fullTextSearch : true
3281
- } )
3282
- ;
3281
+ } ) ;
3282
+
3283
+ $ ( ".menu a.label-filter-item" ) . each ( function ( ) {
3284
+ $ ( this ) . click ( function ( e ) {
3285
+ if ( e . altKey ) {
3286
+ const href = $ ( this ) . attr ( "href" ) ;
3287
+ const id = $ ( this ) . data ( "label-id" ) ;
3288
+
3289
+ const regStr = "labels=(-?[0-9]+%2c)*(" + id + ")(%2c-?[0-9]+)*&" ;
3290
+ const newStr = "labels=$1-$2$3&" ;
3291
+
3292
+ window . location = href . replace ( new RegExp ( regStr ) , newStr ) ;
3293
+ }
3294
+ } ) ;
3295
+ } ) ;
3296
+
3297
+ $ ( ".menu .ui.dropdown.label-filter" ) . keydown ( function ( e ) {
3298
+ if ( e . altKey && e . keyCode == 13 ) {
3299
+ const selectedItems = $ ( ".menu .ui.dropdown.label-filter .menu .item.selected" ) ;
3300
+
3301
+ if ( selectedItems . length > 0 ) {
3302
+ const item = $ ( selectedItems [ 0 ] ) ;
3303
+
3304
+ const href = item . attr ( "href" ) ;
3305
+ const id = item . data ( "label-id" ) ;
3306
+
3307
+ const regStr = "labels=(-?[0-9]+%2c)*(" + id + ")(%2c-?[0-9]+)*&" ;
3308
+ const newStr = "labels=$1-$2$3&" ;
3309
+
3310
+ window . location = href . replace ( new RegExp ( regStr ) , newStr ) ;
3311
+ }
3312
+ }
3313
+ } ) ;
3283
3314
}
3284
3315
function cancelCodeComment ( btn ) {
3285
3316
const form = $ ( btn ) . closest ( "form" ) ;
Original file line number Diff line number Diff line change 158
158
margin : -2px -7px 0 -5px ;
159
159
}
160
160
161
+ & .labels {
162
+ .label-filter .menu .info {
163
+ display : inline-block ;
164
+ padding : 9px 7px 7px 7px ;
165
+ text-align : center ;
166
+ border-bottom : 1px solid #cccccc ;
167
+ font-size : 12px ;
168
+
169
+ code {
170
+ border : 1px solid #cccccc ;
171
+ border-radius : 3px ;
172
+ padding : 3px 2px 1px 2px ;
173
+ font-size : 11px ;
174
+ }
175
+ }
176
+ }
177
+
161
178
.text {
162
179
margin-left : 0.9em ;
163
180
}
Original file line number Diff line number Diff line change 42
42
<div class="ten wide right aligned column">
43
43
<div class="ui secondary filter stackable menu labels">
44
44
<!-- Label -->
45
- <div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item" style="margin-left: auto">
45
+ <div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item label-filter " style="margin-left: auto">
46
46
<span class="text">
47
47
{{.i18n.Tr "repo.issues.filter_label"}}
48
48
<i class="dropdown icon"></i>
49
49
</span>
50
50
<div class="menu">
51
+ <span class="info">{{.i18n.Tr "repo.issues.filter_label_exclude" | Safe}}</span>
51
52
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}">{{.i18n.Tr "repo.issues.filter_label_no_select"}}</a>
52
53
{{range .Labels}}
53
- <a class="item has-emoji" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}"><span class="octicon {{if .IsSelected}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a>
54
+ <a class="item has-emoji label-filter-item " href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" data-label-id="{{.ID}}" ><span class="octicon {{if .IsExcluded}}octicon-circle-slash{{else if .IsSelected}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a>
54
55
{{end}}
55
56
</div>
56
57
</div>
You can’t perform that action at this time.
0 commit comments