@@ -2,11 +2,12 @@ import { displayGitHubIssues, searchDisplayGitHubIssues } from "../fetch-github/
2
2
import { renderErrorInModal } from "../rendering/display-popup-modal" ;
3
3
import { proposalViewToggle } from "../rendering/render-github-issues" ;
4
4
import { Sorting } from "./generate-sorting-buttons" ;
5
+ import { isFilteringAvailableIssues , swapAvailabilityFilter } from "../fetch-github/fetch-and-display-previews" ;
5
6
6
7
export class SortingManager {
7
8
private _lastChecked : HTMLInputElement | null = null ;
8
9
private _toolBarFilters : HTMLElement ;
9
- private _filterTextBox : HTMLInputElement ;
10
+ private _filtersDiv : HTMLElement ;
10
11
private _sortingButtons : HTMLElement ;
11
12
private _instanceId : string ;
12
13
private _sortingState : { [ key : string ] : "unsorted" | "ascending" | "descending" } = { } ; // Track state for each sorting option
@@ -20,8 +21,12 @@ export class SortingManager {
20
21
21
22
// Initialize sorting buttons first
22
23
this . _sortingButtons = this . _generateSortingButtons ( sortingOptions ) ;
23
- // Then initialize filter text box
24
- this . _filterTextBox = this . _generateFilterTextBox ( ) ;
24
+ // Initialize filters div
25
+ this . _filtersDiv = this . _generateFiltersDiv ( ) ;
26
+ // Add filter search box to filters div
27
+ this . _filtersDiv . appendChild ( this . _generateFilterTextBox ( ) ) ;
28
+ // Add filter available issues button to filters div
29
+ this . _filtersDiv . appendChild ( this . _generateFilterAvailableIssuesButton ( ) ) ;
25
30
26
31
// Initialize sorting states to 'unsorted' for all options
27
32
sortingOptions . forEach ( ( option ) => {
@@ -30,10 +35,16 @@ export class SortingManager {
30
35
}
31
36
32
37
public render ( ) {
33
- this . _toolBarFilters . appendChild ( this . _filterTextBox ) ;
38
+ this . _toolBarFilters . appendChild ( this . _filtersDiv ) ;
34
39
this . _toolBarFilters . appendChild ( this . _sortingButtons ) ;
35
40
}
36
41
42
+ private _generateFiltersDiv ( ) {
43
+ const div = document . createElement ( "div" ) ;
44
+ div . className = "filters" ;
45
+ return div ;
46
+ }
47
+
37
48
private _generateFilterTextBox ( ) {
38
49
const textBox = document . createElement ( "input" ) ;
39
50
textBox . type = "text" ;
@@ -115,10 +126,19 @@ export class SortingManager {
115
126
return textBox ;
116
127
}
117
128
129
+ private _resetSearchBar ( ) {
130
+ const filterTextBox = this . _filtersDiv . querySelector ( 'input[type="text"]' ) as HTMLInputElement ;
131
+ filterTextBox . value = "" ;
132
+ const newURL = new URL ( window . location . href ) ;
133
+ newURL . searchParams . delete ( "search" ) ;
134
+ window . history . replaceState ( { } , "" , newURL . toString ( ) ) ;
135
+ }
136
+
118
137
private _resetSortButtons ( ) {
119
138
this . _sortingButtons . querySelectorAll ( 'input[type="radio"]' ) . forEach ( ( input ) => {
120
139
if ( input instanceof HTMLInputElement ) {
121
140
input . checked = false ;
141
+ this . _sortingState [ input . value ] = "unsorted" ;
122
142
input . setAttribute ( "data-ordering" , "" ) ;
123
143
}
124
144
} ) ;
@@ -148,6 +168,54 @@ export class SortingManager {
148
168
return buttons ;
149
169
}
150
170
171
+ private _generateFilterAvailableIssuesButton ( ) {
172
+ const input = document . createElement ( "input" ) ;
173
+ input . type = "button" ;
174
+ input . value = "Unassigned" ;
175
+ input . id = `filter-availability-${ this . _instanceId } ` ;
176
+
177
+ input . addEventListener ( "click" , ( ) => {
178
+ swapAvailabilityFilter ( ) ;
179
+ input . value = isFilteringAvailableIssues ? "Unassigned" : "All Issues" ;
180
+
181
+ try {
182
+ // Clear search when applying the filter
183
+ this . _resetSearchBar ( ) ;
184
+
185
+ const { sortingOption, sortingOrder } = this . _detectSortingState ( ) ;
186
+ void displayGitHubIssues ( {
187
+ sorting : sortingOption as Sorting ,
188
+ options : { ordering : sortingOrder } ,
189
+ } ) ;
190
+ } catch ( error ) {
191
+ renderErrorInModal ( error as Error ) ;
192
+ }
193
+ } ) ;
194
+
195
+ return input ;
196
+ }
197
+
198
+ private _detectSortingState ( ) {
199
+ let sortingOption ;
200
+ let sortingOrder = "normal" ;
201
+
202
+ for ( const option of Object . keys ( this . _sortingState ) ) {
203
+ const order = this . _sortingState [ option ] ;
204
+
205
+ if ( order !== "unsorted" ) {
206
+ sortingOption = option ;
207
+
208
+ if ( order === "descending" ) {
209
+ sortingOrder = "normal" ;
210
+ } else if ( order === "ascending" ) {
211
+ sortingOrder = "reverse" ;
212
+ }
213
+ break ;
214
+ }
215
+ }
216
+ return { sortingOption, sortingOrder } ;
217
+ }
218
+
151
219
private _createRadioButton ( option : string ) : HTMLInputElement {
152
220
const input = document . createElement ( "input" ) ;
153
221
input . type = "radio" ;
@@ -168,35 +236,26 @@ export class SortingManager {
168
236
const currentOrdering = input . getAttribute ( "data-ordering" ) ;
169
237
let newOrdering : string ;
170
238
239
+ // Reset sort buttons
240
+ this . _resetSortButtons ( ) ;
241
+
171
242
// Determine the new ordering based on the current state
172
243
if ( currentOrdering === "normal" ) {
173
244
newOrdering = "reverse" ;
245
+ this . _sortingState [ option ] = "ascending" ;
174
246
} else if ( currentOrdering === "reverse" ) {
175
247
newOrdering = "disabled" ;
248
+ this . _sortingState [ option ] = "unsorted" ;
176
249
} else {
177
250
newOrdering = "normal" ;
251
+ this . _sortingState [ option ] = "descending" ;
178
252
}
179
253
180
254
// Apply the new ordering state
181
255
input . setAttribute ( "data-ordering" , newOrdering ) ;
182
- input . parentElement ?. childNodes . forEach ( ( node ) => {
183
- if ( node instanceof HTMLInputElement ) {
184
- node . setAttribute ( "data-ordering" , "" ) ;
185
- }
186
- } ) ;
187
256
188
257
// Clear search when applying a different sort
189
- this . _filterTextBox . value = "" ;
190
- const newURL = new URL ( window . location . href ) ;
191
- newURL . searchParams . delete ( "search" ) ;
192
- window . history . replaceState ( { } , "" , newURL . toString ( ) ) ;
193
-
194
- // Reset other buttons
195
- input . parentElement ?. childNodes . forEach ( ( node ) => {
196
- if ( node instanceof HTMLInputElement ) {
197
- node . setAttribute ( "data-ordering" , "" ) ;
198
- }
199
- } ) ;
258
+ this . _resetSearchBar ( ) ;
200
259
201
260
if ( newOrdering === "disabled" ) {
202
261
this . _lastChecked = null ;
@@ -209,7 +268,10 @@ export class SortingManager {
209
268
210
269
// Apply the sorting based on the new state (normal or reverse)
211
270
try {
212
- void displayGitHubIssues ( { sorting : option as Sorting , options : { ordering : newOrdering } } ) ;
271
+ void displayGitHubIssues ( {
272
+ sorting : option as Sorting ,
273
+ options : { ordering : newOrdering } ,
274
+ } ) ;
213
275
} catch ( error ) {
214
276
renderErrorCatch ( error as ErrorEvent ) ;
215
277
}
0 commit comments