mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 03:18:24 +00:00 
			
		
		
		
	Drag-and-drop improvements for projects and issue pins (#29875)
1. Add "grabbing" cursor while dragging items:  2. Make project board only drag via their header, not via their whole body.  3. Fix some cursor problems in projects 4. Move shared options into `createSortable`.
This commit is contained in:
		| @@ -67,7 +67,7 @@ | ||||
| 	<div class="board {{if .CanWriteProjects}}sortable{{end}}"> | ||||
| 		{{range .Columns}} | ||||
| 			<div class="ui segment project-column" style="background: {{.Color}} !important;" data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}"> | ||||
| 				<div class="project-column-header"> | ||||
| 				<div class="project-column-header{{if $canWriteProject}} tw-cursor-grab{{end}}"> | ||||
| 					<div class="ui large label project-column-title tw-py-1"> | ||||
| 						<div class="ui small circular grey label project-column-issue-count"> | ||||
| 							{{.NumIssues ctx}} | ||||
| @@ -156,7 +156,7 @@ | ||||
|  | ||||
| 				<div class="divider"></div> | ||||
|  | ||||
| 				<div class="ui cards{{if $canWriteProject}} tw-cursor-grab{{end}}" data-url="{{$.Link}}/{{.ID}}" data-project="{{$.Project.ID}}" data-board="{{.ID}}" id="board_{{.ID}}"> | ||||
| 				<div class="ui cards" data-url="{{$.Link}}/{{.ID}}" data-project="{{$.Project.ID}}" data-board="{{.ID}}" id="board_{{.ID}}"> | ||||
| 					{{range (index $.IssuesMap .ID)}} | ||||
| 						<div class="issue-card gt-word-break {{if $canWriteProject}}tw-cursor-grab{{end}}" data-issue="{{.ID}}"> | ||||
| 							{{template "repo/issue/card" (dict "Issue" . "Page" $)}} | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
|   overflow: visible; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   cursor: default; | ||||
| } | ||||
|  | ||||
| .project-column-header { | ||||
| @@ -46,6 +47,7 @@ | ||||
| .project-column-title { | ||||
|   background: none !important; | ||||
|   line-height: 1.25 !important; | ||||
|   cursor: inherit; | ||||
| } | ||||
|  | ||||
| .project-column > .cards { | ||||
| @@ -92,6 +94,7 @@ | ||||
| } | ||||
|  | ||||
| .card-ghost { | ||||
|   border-color: var(--color-secondary-dark-4) !important; | ||||
|   border-style: dashed !important; | ||||
|   background: none !important; | ||||
| } | ||||
|   | ||||
| @@ -19,3 +19,7 @@ | ||||
|   font-size: 14px; | ||||
|   margin-left: 4px; | ||||
| } | ||||
|  | ||||
| .issue-card.sortable-chosen .issue-card-title { | ||||
|   cursor: inherit; | ||||
| } | ||||
|   | ||||
| @@ -188,8 +188,6 @@ async function initIssuePinSort() { | ||||
|  | ||||
|   createSortable(pinDiv, { | ||||
|     group: 'shared', | ||||
|     animation: 150, | ||||
|     ghostClass: 'card-ghost', | ||||
|     onEnd: pinMoveEnd, | ||||
|   }); | ||||
| } | ||||
|   | ||||
| @@ -58,8 +58,7 @@ async function initRepoProjectSortable() { | ||||
|   createSortable(mainBoard, { | ||||
|     group: 'project-column', | ||||
|     draggable: '.project-column', | ||||
|     animation: 150, | ||||
|     ghostClass: 'card-ghost', | ||||
|     handle: '.project-column-header', | ||||
|     delayOnTouchOnly: true, | ||||
|     delay: 500, | ||||
|     onSort: async () => { | ||||
| @@ -86,8 +85,6 @@ async function initRepoProjectSortable() { | ||||
|     const boardCardList = boardColumn.getElementsByClassName('cards')[0]; | ||||
|     createSortable(boardCardList, { | ||||
|       group: 'shared', | ||||
|       animation: 150, | ||||
|       ghostClass: 'card-ghost', | ||||
|       onAdd: moveIssue, | ||||
|       onUpdate: moveIssue, | ||||
|       delayOnTouchOnly: true, | ||||
|   | ||||
| @@ -1,4 +1,19 @@ | ||||
| export async function createSortable(...args) { | ||||
| export async function createSortable(el, opts = {}) { | ||||
|   const {Sortable} = await import(/* webpackChunkName: "sortablejs" */'sortablejs'); | ||||
|   return new Sortable(...args); | ||||
|  | ||||
|   return new Sortable(el, { | ||||
|     animation: 150, | ||||
|     ghostClass: 'card-ghost', | ||||
|     onChoose: (e) => { | ||||
|       const handle = opts.handle ? e.item.querySelector(opts.handle) : e.item; | ||||
|       handle.classList.add('tw-cursor-grabbing'); | ||||
|       opts.onChoose?.(e); | ||||
|     }, | ||||
|     onUnchoose: (e) => { | ||||
|       const handle = opts.handle ? e.item.querySelector(opts.handle) : e.item; | ||||
|       handle.classList.remove('tw-cursor-grabbing'); | ||||
|       opts.onUnchoose?.(e); | ||||
|     }, | ||||
|     ...opts, | ||||
|   }); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user