1
1
import $ from 'jquery' ;
2
2
import { stripTags } from '../utils.js' ;
3
- import { hideElem , showElem } from '../utils/dom.js' ;
3
+ import { hideElem , queryElemChildren , showElem } from '../utils/dom.js' ;
4
4
import { POST } from '../modules/fetch.js' ;
5
+ import { showErrorToast } from '../modules/toast.js' ;
5
6
6
7
const { appSubUrl} = window . config ;
7
8
8
9
export function initRepoTopicBar ( ) {
9
10
const mgrBtn = document . getElementById ( 'manage_topic' ) ;
10
11
if ( ! mgrBtn ) return ;
12
+
11
13
const editDiv = document . getElementById ( 'topic_edit' ) ;
12
14
const viewDiv = document . getElementById ( 'repo-topics' ) ;
13
- const saveBtn = document . getElementById ( 'save_topic' ) ;
14
- const topicDropdown = editDiv . querySelector ( '.dropdown' ) ;
15
- const $topicDropdown = $ ( topicDropdown ) ;
16
- const $topicForm = $ ( editDiv ) ;
17
- const $topicDropdownSearch = $topicDropdown . find ( 'input.search' ) ;
18
- const topicPrompts = {
19
- countPrompt : topicDropdown . getAttribute ( 'data-text-count-prompt' ) ?? undefined ,
20
- formatPrompt : topicDropdown . getAttribute ( 'data-text-format-prompt' ) ?? undefined ,
21
- } ;
15
+ const topicDropdown = editDiv . querySelector ( '.ui.dropdown' ) ;
16
+ let lastErrorToast ;
22
17
23
18
mgrBtn . addEventListener ( 'click' , ( ) => {
24
19
hideElem ( viewDiv ) ;
25
20
showElem ( editDiv ) ;
26
- $topicDropdownSearch . trigger ( 'focus' ) ;
21
+ topicDropdown . querySelector ( 'input.search' ) . focus ( ) ;
27
22
} ) ;
28
23
29
- $ ( '#cancel_topic_edit' ) . on ( 'click' , ( ) => {
24
+ document . querySelector ( '#cancel_topic_edit' ) . addEventListener ( 'click' , ( ) => {
25
+ lastErrorToast ?. hideToast ( ) ;
30
26
hideElem ( editDiv ) ;
31
27
showElem ( viewDiv ) ;
32
28
mgrBtn . focus ( ) ;
33
29
} ) ;
34
30
35
- saveBtn . addEventListener ( 'click' , async ( ) => {
36
- const topics = $ ( 'input[name=topics]' ) . val ( ) ;
31
+ document . getElementById ( 'save_topic' ) . addEventListener ( 'click' , async ( e ) => {
32
+ lastErrorToast ?. hideToast ( ) ;
33
+ const topics = editDiv . querySelector ( 'input[name=topics]' ) . value ;
37
34
38
35
const data = new FormData ( ) ;
39
36
data . append ( 'topics' , topics ) ;
40
37
41
- const response = await POST ( saveBtn . getAttribute ( 'data-link' ) , { data} ) ;
38
+ const response = await POST ( e . target . getAttribute ( 'data-link' ) , { data} ) ;
42
39
43
40
if ( response . ok ) {
44
41
const responseData = await response . json ( ) ;
45
42
if ( responseData . status === 'ok' ) {
46
- $ ( viewDiv ) . children ( '. topic') . remove ( ) ;
43
+ queryElemChildren ( viewDiv , '.repo- topic', ( el ) => el . remove ( ) ) ;
47
44
if ( topics . length ) {
48
45
const topicArray = topics . split ( ',' ) ;
49
46
topicArray . sort ( ) ;
50
47
for ( const topic of topicArray ) {
48
+ // it should match the code in repo/home.tmpl
51
49
const link = document . createElement ( 'a' ) ;
52
- link . classList . add ( 'ui' , ' repo-topic', 'large ' , 'label ' , 'topic' , 'tw-m-0 ') ;
50
+ link . classList . add ( 'repo-topic' , 'ui ' , 'large ' , 'label ' ) ;
53
51
link . href = `${ appSubUrl } /explore/repos?q=${ encodeURIComponent ( topic ) } &topic=1` ;
54
52
link . textContent = topic ;
55
53
mgrBtn . parentNode . insertBefore ( link , mgrBtn ) ; // insert all new topics before manage button
@@ -59,27 +57,23 @@ export function initRepoTopicBar() {
59
57
showElem ( viewDiv ) ;
60
58
}
61
59
} else if ( response . status === 422 ) {
60
+ // how to test: input topic like " invalid topic " (with spaces), and select it from the list, then "Save"
62
61
const responseData = await response . json ( ) ;
62
+ lastErrorToast = showErrorToast ( responseData . message , { duration : 5000 } ) ;
63
63
if ( responseData . invalidTopics . length > 0 ) {
64
- topicPrompts . formatPrompt = responseData . message ;
65
-
66
64
const { invalidTopics} = responseData ;
67
- const $ topicLabels = $topicDropdown . children ( 'a.ui.label' ) ;
65
+ const topicLabels = queryElemChildren ( topicDropdown , 'a.ui.label' ) ;
68
66
for ( const [ index , value ] of topics . split ( ',' ) . entries ( ) ) {
69
67
if ( invalidTopics . includes ( value ) ) {
70
- $topicLabels . eq ( index ) . removeClass ( 'green' ) . addClass ( 'red' ) ;
68
+ topicLabels [ index ] . classList . remove ( 'green' ) ;
69
+ topicLabels [ index ] . classList . add ( 'red' ) ;
71
70
}
72
71
}
73
- } else {
74
- topicPrompts . countPrompt = responseData . message ;
75
72
}
76
73
}
77
-
78
- // Always validate the form
79
- $topicForm . form ( 'validate form' ) ;
80
74
} ) ;
81
75
82
- $topicDropdown . dropdown ( {
76
+ $ ( topicDropdown ) . dropdown ( {
83
77
allowAdditions : true ,
84
78
forceSelection : false ,
85
79
fullTextSearch : 'exact' ,
@@ -102,9 +96,9 @@ export function initRepoTopicBar() {
102
96
const query = stripTags ( this . urlData . query . trim ( ) ) ;
103
97
let found_query = false ;
104
98
const current_topics = [ ] ;
105
- $topicDropdown . find ( 'a.label.visible' ) . each ( ( _ , el ) => {
99
+ for ( const el of queryElemChildren ( topicDropdown , 'a.ui. label.visible' ) ) {
106
100
current_topics . push ( el . getAttribute ( 'data-value' ) ) ;
107
- } ) ;
101
+ }
108
102
109
103
if ( res . topics ) {
110
104
let found = false ;
@@ -146,38 +140,8 @@ export function initRepoTopicBar() {
146
140
} ,
147
141
onAdd ( addedValue , _addedText , $addedChoice ) {
148
142
addedValue = addedValue . toLowerCase ( ) . trim ( ) ;
149
- $ ( $addedChoice ) [ 0 ] . setAttribute ( 'data-value' , addedValue ) ;
150
- $ ( $addedChoice ) [ 0 ] . setAttribute ( 'data-text' , addedValue ) ;
151
- } ,
152
- } ) ;
153
-
154
- $ . fn . form . settings . rules . validateTopic = function ( _values , regExp ) {
155
- const $topics = $topicDropdown . children ( 'a.ui.label' ) ;
156
- const status = ! $topics . length || $topics . last ( ) [ 0 ] . getAttribute ( 'data-value' ) . match ( regExp ) ;
157
- if ( ! status ) {
158
- $topics . last ( ) . removeClass ( 'green' ) . addClass ( 'red' ) ;
159
- }
160
- return status && ! $topicDropdown . children ( 'a.ui.label.red' ) . length ;
161
- } ;
162
-
163
- $topicForm . form ( {
164
- on : 'change' ,
165
- inline : true ,
166
- fields : {
167
- topics : {
168
- identifier : 'topics' ,
169
- rules : [
170
- {
171
- type : 'validateTopic' ,
172
- value : / ^ \s * [ a - z 0 - 9 ] [ - . a - z 0 - 9 ] { 0 , 35 } \s * $ / ,
173
- prompt : topicPrompts . formatPrompt ,
174
- } ,
175
- {
176
- type : 'maxCount[25]' ,
177
- prompt : topicPrompts . countPrompt ,
178
- } ,
179
- ] ,
180
- } ,
143
+ $addedChoice [ 0 ] . setAttribute ( 'data-value' , addedValue ) ;
144
+ $addedChoice [ 0 ] . setAttribute ( 'data-text' , addedValue ) ;
181
145
} ,
182
146
} ) ;
183
147
}
0 commit comments