2022-01-28 13:00:11 -08:00
import $ from 'jquery' ;
2021-10-21 15:37:43 +08:00
const { csrfToken } = window . config ;
2020-08-17 04:07:38 +01:00
2022-03-09 00:42:28 +08:00
function updateIssueCount ( cards ) {
const parent = cards . parentElement ;
const cnt = parent . getElementsByClassName ( 'board-card' ) . length ;
parent . getElementsByClassName ( 'board-card-cnt' ) [ 0 ] . innerText = cnt ;
}
2021-12-08 07:57:18 +01:00
function moveIssue ( { item , from , to , oldIndex } ) {
const columnCards = to . getElementsByClassName ( 'board-card' ) ;
2022-03-09 00:42:28 +08:00
updateIssueCount ( from ) ;
updateIssueCount ( to ) ;
2021-12-08 07:57:18 +01:00
const columnSorting = {
issues : [ ... columnCards ] . map ( ( card , i ) => ( {
issueID : parseInt ( $ ( card ) . attr ( 'data-issue' ) ) ,
sorting : i
} ) )
} ;
$ . ajax ( {
url : ` ${ to . getAttribute ( 'data-url' ) } /move ` ,
data : JSON . stringify ( columnSorting ) ,
headers : {
'X-Csrf-Token' : csrfToken ,
} ,
contentType : 'application/json' ,
type : 'POST' ,
error : ( ) => {
from . insertBefore ( item , from . children [ oldIndex ] ) ;
}
} ) ;
}
2021-11-09 17:27:25 +08:00
async function initRepoProjectSortable ( ) {
2021-11-22 19:40:17 +08:00
const els = document . querySelectorAll ( '#project-board > .board' ) ;
2021-11-19 00:45:00 +08:00
if ( ! els . length ) return ;
2020-08-17 04:07:38 +01:00
const { Sortable } = await import ( /* webpackChunkName: "sortable" */ 'sortablejs' ) ;
2021-02-11 17:32:27 +01:00
2021-11-22 19:40:17 +08:00
// the HTML layout is: #project-board > .board > .board-column .board.cards > .board-card.card .content
const mainBoard = els [ 0 ] ;
let boardColumns = mainBoard . getElementsByClassName ( 'board-column' ) ;
new Sortable ( mainBoard , {
2021-11-22 09:19:01 +01:00
group : 'board-column' ,
draggable : '.board-column' ,
2021-11-22 19:40:17 +08:00
filter : '[data-id="0"]' ,
2021-11-22 09:19:01 +01:00
animation : 150 ,
ghostClass : 'card-ghost' ,
onSort : ( ) => {
2021-11-22 19:40:17 +08:00
boardColumns = mainBoard . getElementsByClassName ( 'board-column' ) ;
for ( let i = 0 ; i < boardColumns . length ; i ++ ) {
const column = boardColumns [ i ] ;
2021-11-22 09:19:01 +01:00
if ( parseInt ( $ ( column ) . data ( 'sorting' ) ) !== i ) {
$ . ajax ( {
url : $ ( column ) . data ( 'url' ) ,
data : JSON . stringify ( { sorting : i , color : rgbToHex ( $ ( column ) . css ( 'backgroundColor' ) ) } ) ,
2020-08-17 04:07:38 +01:00
headers : {
2021-10-21 15:37:43 +08:00
'X-Csrf-Token' : csrfToken ,
2020-08-17 04:07:38 +01:00
} ,
contentType : 'application/json' ,
2021-11-22 09:19:01 +01:00
method : 'PUT' ,
2020-08-17 04:07:38 +01:00
} ) ;
2021-11-22 09:19:01 +01:00
}
}
} ,
} ) ;
2021-11-22 19:40:17 +08:00
for ( const boardColumn of boardColumns ) {
const boardCardList = boardColumn . getElementsByClassName ( 'board' ) [ 0 ] ;
new Sortable ( boardCardList , {
2021-11-22 09:19:01 +01:00
group : 'shared' ,
animation : 150 ,
ghostClass : 'card-ghost' ,
2021-12-08 07:57:18 +01:00
onAdd : moveIssue ,
onUpdate : moveIssue ,
2021-11-22 09:19:01 +01:00
} ) ;
2020-08-17 04:07:38 +01:00
}
2021-11-09 17:27:25 +08:00
}
export default function initRepoProject ( ) {
if ( ! $ ( '.repository.projects' ) . length ) {
return ;
}
2021-11-12 20:37:45 +08:00
const _promise = initRepoProjectSortable ( ) ;
2020-08-17 04:07:38 +01:00
$ ( '.edit-project-board' ) . each ( function ( ) {
2021-09-29 22:53:12 +02:00
const projectHeader = $ ( this ) . closest ( '.board-column-header' ) ;
const projectTitleLabel = projectHeader . find ( '.board-label' ) ;
2020-08-17 04:07:38 +01:00
const projectTitleInput = $ ( this ) . find (
2021-01-15 21:29:32 +01:00
'.content > .form > .field > .project-board-title' ,
2020-08-17 04:07:38 +01:00
) ;
2021-09-29 22:53:12 +02:00
const projectColorInput = $ ( this ) . find ( '.content > .form > .field #new_board_color' ) ;
const boardColumn = $ ( this ) . closest ( '.board-column' ) ;
if ( boardColumn . css ( 'backgroundColor' ) ) {
setLabelColor ( projectHeader , rgbToHex ( boardColumn . css ( 'backgroundColor' ) ) ) ;
}
2020-08-17 04:07:38 +01:00
$ ( this )
. find ( '.content > .form > .actions > .red' )
. on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
$ . ajax ( {
url : $ ( this ) . data ( 'url' ) ,
2021-09-29 22:53:12 +02:00
data : JSON . stringify ( { title : projectTitleInput . val ( ) , color : projectColorInput . val ( ) } ) ,
2020-08-17 04:07:38 +01:00
headers : {
2021-10-21 15:37:43 +08:00
'X-Csrf-Token' : csrfToken ,
2020-08-17 04:07:38 +01:00
} ,
contentType : 'application/json' ,
method : 'PUT' ,
} ) . done ( ( ) => {
projectTitleLabel . text ( projectTitleInput . val ( ) ) ;
projectTitleInput . closest ( 'form' ) . removeClass ( 'dirty' ) ;
2021-09-29 22:53:12 +02:00
if ( projectColorInput . val ( ) ) {
setLabelColor ( projectHeader , projectColorInput . val ( ) ) ;
}
boardColumn . attr ( 'style' , ` background: ${ projectColorInput . val ( ) } !important ` ) ;
2020-08-17 04:07:38 +01:00
$ ( '.ui.modal' ) . modal ( 'hide' ) ;
} ) ;
} ) ;
} ) ;
2021-01-15 21:29:32 +01:00
$ ( document ) . on ( 'click' , '.set-default-project-board' , async function ( e ) {
e . preventDefault ( ) ;
await $ . ajax ( {
method : 'POST' ,
url : $ ( this ) . data ( 'url' ) ,
headers : {
2021-10-21 15:37:43 +08:00
'X-Csrf-Token' : csrfToken ,
2021-01-15 21:29:32 +01:00
} ,
contentType : 'application/json' ,
} ) ;
window . location . reload ( ) ;
} ) ;
2021-02-11 17:32:27 +01:00
2020-08-17 04:07:38 +01:00
$ ( '.delete-project-board' ) . each ( function ( ) {
$ ( this ) . click ( function ( e ) {
e . preventDefault ( ) ;
$ . ajax ( {
url : $ ( this ) . data ( 'url' ) ,
headers : {
2021-10-21 15:37:43 +08:00
'X-Csrf-Token' : csrfToken ,
2020-08-17 04:07:38 +01:00
} ,
contentType : 'application/json' ,
method : 'DELETE' ,
} ) . done ( ( ) => {
2021-01-15 21:29:32 +01:00
window . location . reload ( ) ;
2020-08-17 04:07:38 +01:00
} ) ;
} ) ;
} ) ;
$ ( '#new_board_submit' ) . click ( function ( e ) {
e . preventDefault ( ) ;
const boardTitle = $ ( '#new_board' ) ;
2021-09-29 22:53:12 +02:00
const projectColorInput = $ ( '#new_board_color_picker' ) ;
2020-08-17 04:07:38 +01:00
$ . ajax ( {
url : $ ( this ) . data ( 'url' ) ,
2021-09-29 22:53:12 +02:00
data : JSON . stringify ( { title : boardTitle . val ( ) , color : projectColorInput . val ( ) } ) ,
2020-08-17 04:07:38 +01:00
headers : {
2021-10-21 15:37:43 +08:00
'X-Csrf-Token' : csrfToken ,
2020-08-17 04:07:38 +01:00
} ,
contentType : 'application/json' ,
method : 'POST' ,
} ) . done ( ( ) => {
boardTitle . closest ( 'form' ) . removeClass ( 'dirty' ) ;
2021-01-15 21:29:32 +01:00
window . location . reload ( ) ;
2020-08-17 04:07:38 +01:00
} ) ;
} ) ;
}
2021-09-29 22:53:12 +02:00
function setLabelColor ( label , color ) {
2022-02-18 07:50:36 +01:00
const red = getRelativeColor ( parseInt ( color . slice ( 1 , 3 ) , 16 ) ) ;
const green = getRelativeColor ( parseInt ( color . slice ( 3 , 5 ) , 16 ) ) ;
const blue = getRelativeColor ( parseInt ( color . slice ( 5 , 7 ) , 16 ) ) ;
2021-09-29 22:53:12 +02:00
const luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue ;
if ( luminance > 0.179 ) {
label . removeClass ( 'light-label' ) . addClass ( 'dark-label' ) ;
} else {
label . removeClass ( 'dark-label' ) . addClass ( 'light-label' ) ;
}
}
/ * *
Fix various typos (#20338)
* Fix various typos
Found via `codespell -q 3 -S ./options/locale,./options/license,./public/vendor -L actived,allways,attachements,ba,befores,commiter,pullrequest,pullrequests,readby,splitted,te,unknwon`
Co-authored-by: zeripath <art27@cantab.net>
2022-07-12 17:32:37 -04:00
* Inspired by W3C recommendation https : //www.w3.org/TR/WCAG20/#relativeluminancedef
2021-09-29 22:53:12 +02:00
* /
function getRelativeColor ( color ) {
color /= 255 ;
return color <= 0.03928 ? color / 12.92 : ( ( color + 0.055 ) / 1.055 ) * * 2.4 ;
}
function rgbToHex ( rgb ) {
rgb = rgb . match ( /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/ ) ;
return ` # ${ hex ( rgb [ 1 ] ) } ${ hex ( rgb [ 2 ] ) } ${ hex ( rgb [ 3 ] ) } ` ;
}
function hex ( x ) {
const hexDigits = [ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ] ;
return Number . isNaN ( x ) ? '00' : hexDigits [ ( x - x % 16 ) / 16 ] + hexDigits [ x % 16 ] ;
}