2022-01-29 00:00:11 +03:00
import $ from 'jquery' ;
2021-10-16 20:28:04 +03:00
import { stripTags } from '../utils.js' ;
2021-10-21 10:37:43 +03:00
const { appSubUrl , csrfToken } = window . config ;
2021-10-16 20:28:04 +03:00
export function initRepoTopicBar ( ) {
const mgrBtn = $ ( '#manage_topic' ) ;
const editDiv = $ ( '#topic_edit' ) ;
const viewDiv = $ ( '#repo-topics' ) ;
const saveBtn = $ ( '#save_topic' ) ;
const topicDropdown = $ ( '#topic_edit .dropdown' ) ;
const topicForm = $ ( '#topic_edit.ui.form' ) ;
const topicPrompts = getPrompts ( ) ;
mgrBtn . on ( 'click' , ( ) => {
viewDiv . hide ( ) ;
editDiv . css ( 'display' , '' ) ; // show Semantic UI Grid
} ) ;
function getPrompts ( ) {
const hidePrompt = $ ( 'div.hide#validate_prompt' ) ;
const prompts = {
countPrompt : hidePrompt . children ( '#count_prompt' ) . text ( ) ,
formatPrompt : hidePrompt . children ( '#format_prompt' ) . text ( )
} ;
hidePrompt . remove ( ) ;
return prompts ;
}
saveBtn . on ( 'click' , ( ) => {
const topics = $ ( 'input[name=topics]' ) . val ( ) ;
$ . post ( saveBtn . data ( 'link' ) , {
2021-10-21 10:37:43 +03:00
_csrf : csrfToken ,
2021-10-16 20:28:04 +03:00
topics
} , ( _data , _textStatus , xhr ) => {
if ( xhr . responseJSON . status === 'ok' ) {
viewDiv . children ( '.topic' ) . remove ( ) ;
if ( topics . length ) {
const topicArray = topics . split ( ',' ) ;
const last = viewDiv . children ( 'a' ) . last ( ) ;
for ( let i = 0 ; i < topicArray . length ; i ++ ) {
const link = $ ( '<a class="ui repo-topic large label topic"></a>' ) ;
2021-10-21 10:37:43 +03:00
link . attr ( 'href' , ` ${ appSubUrl } /explore/repos?q= ${ encodeURIComponent ( topicArray [ i ] ) } &topic=1 ` ) ;
2021-10-16 20:28:04 +03:00
link . text ( topicArray [ i ] ) ;
link . insertBefore ( last ) ;
}
}
editDiv . css ( 'display' , 'none' ) ;
viewDiv . show ( ) ;
}
} ) . fail ( ( xhr ) => {
if ( xhr . status === 422 ) {
if ( xhr . responseJSON . invalidTopics . length > 0 ) {
topicPrompts . formatPrompt = xhr . responseJSON . message ;
const { invalidTopics } = xhr . responseJSON ;
const topicLables = topicDropdown . children ( 'a.ui.label' ) ;
2021-11-22 11:19:01 +03:00
for ( const [ index , value ] of topics . split ( ',' ) . entries ( ) ) {
2021-10-16 20:28:04 +03:00
for ( let i = 0 ; i < invalidTopics . length ; i ++ ) {
if ( invalidTopics [ i ] === value ) {
topicLables . eq ( index ) . removeClass ( 'green' ) . addClass ( 'red' ) ;
}
}
2021-11-22 11:19:01 +03:00
}
2021-10-16 20:28:04 +03:00
} else {
topicPrompts . countPrompt = xhr . responseJSON . message ;
}
}
} ) . always ( ( ) => {
topicForm . form ( 'validate form' ) ;
} ) ;
} ) ;
topicDropdown . dropdown ( {
allowAdditions : true ,
forceSelection : false ,
fullTextSearch : 'exact' ,
fields : { name : 'description' , value : 'data-value' } ,
saveRemoteData : false ,
label : {
transition : 'horizontal flip' ,
duration : 200 ,
variation : false ,
} ,
className : {
label : 'ui small label'
} ,
apiSettings : {
2022-04-07 21:59:56 +03:00
url : ` ${ appSubUrl } /explore/topics/search?q={query} ` ,
2021-10-16 20:28:04 +03:00
throttle : 500 ,
cache : false ,
onResponse ( res ) {
const formattedResponse = {
success : false ,
results : [ ] ,
} ;
const query = stripTags ( this . urlData . query . trim ( ) ) ;
let found _query = false ;
const current _topics = [ ] ;
2021-11-22 11:19:01 +03:00
topicDropdown . find ( 'div.label.visible.topic,a.label.visible' ) . each ( ( _ , el ) => {
current _topics . push ( el . getAttribute ( 'data-value' ) ) ;
} ) ;
2021-10-16 20:28:04 +03:00
if ( res . topics ) {
let found = false ;
for ( let i = 0 ; i < res . topics . length ; i ++ ) {
// skip currently added tags
if ( current _topics . includes ( res . topics [ i ] . topic _name ) ) {
continue ;
}
if ( res . topics [ i ] . topic _name . toLowerCase ( ) === query . toLowerCase ( ) ) {
found _query = true ;
}
formattedResponse . results . push ( { description : res . topics [ i ] . topic _name , 'data-value' : res . topics [ i ] . topic _name } ) ;
found = true ;
}
formattedResponse . success = found ;
}
if ( query . length > 0 && ! found _query ) {
formattedResponse . success = true ;
formattedResponse . results . unshift ( { description : query , 'data-value' : query } ) ;
} else if ( query . length > 0 && found _query ) {
formattedResponse . results . sort ( ( a , b ) => {
if ( a . description . toLowerCase ( ) === query . toLowerCase ( ) ) return - 1 ;
if ( b . description . toLowerCase ( ) === query . toLowerCase ( ) ) return 1 ;
if ( a . description > b . description ) return - 1 ;
if ( a . description < b . description ) return 1 ;
return 0 ;
} ) ;
}
return formattedResponse ;
} ,
} ,
onLabelCreate ( value ) {
value = value . toLowerCase ( ) . trim ( ) ;
this . attr ( 'data-value' , value ) . contents ( ) . first ( ) . replaceWith ( value ) ;
return $ ( this ) ;
} ,
onAdd ( addedValue , _addedText , $addedChoice ) {
addedValue = addedValue . toLowerCase ( ) . trim ( ) ;
$ ( $addedChoice ) . attr ( 'data-value' , addedValue ) ;
$ ( $addedChoice ) . attr ( 'data-text' , addedValue ) ;
}
} ) ;
$ . fn . form . settings . rules . validateTopic = function ( _values , regExp ) {
const topics = topicDropdown . children ( 'a.ui.label' ) ;
const status = topics . length === 0 || topics . last ( ) . attr ( 'data-value' ) . match ( regExp ) ;
if ( ! status ) {
topics . last ( ) . removeClass ( 'green' ) . addClass ( 'red' ) ;
}
return status && topicDropdown . children ( 'a.ui.label.red' ) . length === 0 ;
} ;
topicForm . form ( {
on : 'change' ,
inline : true ,
fields : {
topics : {
identifier : 'topics' ,
rules : [
{
type : 'validateTopic' ,
value : /^[a-z0-9][a-z0-9-]{0,35}$/ ,
prompt : topicPrompts . formatPrompt
} ,
{
type : 'maxCount[25]' ,
prompt : topicPrompts . countPrompt
}
]
} ,
}
} ) ;
}