diff options
author | JakobDev <jakobdev@gmx.de> | 2023-05-25 15:17:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-25 15:17:19 +0200 |
commit | aaa109466350c531b9238a61115b2877daca57d3 (patch) | |
tree | 4f5759d3591d6424d80e44e5b8ee97bdd0c7c9ac /web_src/js | |
parent | 79087bdb2676ac383f4bd21137d4454f7a26c8c4 (diff) | |
download | gitea-aaa109466350c531b9238a61115b2877daca57d3.tar.gz gitea-aaa109466350c531b9238a61115b2877daca57d3.zip |
Add the ability to pin Issues (#24406)
This adds the ability to pin important Issues and Pull Requests. You can
also move pinned Issues around to change their Position. Resolves #2175.
## Screenshots
![grafik](https://user-images.githubusercontent.com/15185051/235123207-0aa39869-bb48-45c3-abe2-ba1e836046ec.png)
![grafik](https://user-images.githubusercontent.com/15185051/235123297-152a16ea-a857-451d-9a42-61f2cd54dd75.png)
![grafik](https://user-images.githubusercontent.com/15185051/235640782-cbfe25ec-6254-479a-a3de-133e585d7a2d.png)
The Design was mostly copied from the Projects Board.
## Implementation
This uses a new `pin_order` Column in the `issue` table. If the value is
set to 0, the Issue is not pinned. If it's set to a bigger value, the
value is the Position. 1 means it's the first pinned Issue, 2 means it's
the second one etc. This is dived into Issues and Pull requests for each
Repo.
## TODO
- [x] You can currently pin as many Issues as you want. Maybe we should
add a Limit, which is configurable. GitHub uses 3, but I prefer 6, as
this is better for bigger Projects, but I'm open for suggestions.
- [x] Pin and Unpin events need to be added to the Issue history.
- [x] Tests
- [x] Migration
**The feature itself is currently fully working, so tester who may find
weird edge cases are very welcome!**
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Giteabot <teabot@gitea.io>
Diffstat (limited to 'web_src/js')
-rw-r--r-- | web_src/js/features/repo-issue-list.js | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js index af0e80af81..cc50ec5f88 100644 --- a/web_src/js/features/repo-issue-list.js +++ b/web_src/js/features/repo-issue-list.js @@ -2,6 +2,7 @@ import $ from 'jquery'; import {updateIssuesMeta} from './repo-issue.js'; import {toggleElem} from '../utils/dom.js'; import {htmlEscape} from 'escape-goat'; +import {Sortable} from 'sortablejs'; function initRepoIssueListCheckboxes() { const $issueSelectAll = $('.issue-checkbox-all'); @@ -119,8 +120,67 @@ function initRepoIssueListAuthorDropdown() { }; } +function initPinRemoveButton() { + for (const button of document.getElementsByClassName('pinned-issue-unpin')) { + button.addEventListener('click', async (event) => { + const el = event.currentTarget; + const id = Number(el.getAttribute('data-issue-id')); + + // Send the unpin request + const response = await fetch(el.getAttribute('data-unpin-url'), { + method: 'delete', + headers: { + 'X-Csrf-Token': window.config.csrfToken, + 'Content-Type': 'application/json', + }, + }); + if (response.ok) { + // Delete the tooltip + el._tippy.destroy(); + // Remove the Card + el.closest(`div.pinned-issue-card[data-issue-id="${id}"]`).remove(); + } + }); + } +} + +async function pinMoveEnd(e) { + const url = e.item.getAttribute('data-move-url'); + const id = Number(e.item.getAttribute('data-issue-id')); + await fetch(url, { + method: 'post', + body: JSON.stringify({id, position: e.newIndex + 1}), + headers: { + 'X-Csrf-Token': window.config.csrfToken, + 'Content-Type': 'application/json', + }, + }); +} + +function initIssuePinSort() { + const pinDiv = document.getElementById('issue-pins'); + + if (pinDiv === null) return; + + // If the User is not a Repo Admin, we don't need to proceed + if (!pinDiv.hasAttribute('data-is-repo-admin')) return; + + initPinRemoveButton(); + + // If only one issue pinned, we don't need to make this Sortable + if (pinDiv.children.length < 2) return; + + new Sortable(pinDiv, { + group: 'shared', + animation: 150, + ghostClass: 'card-ghost', + onEnd: pinMoveEnd, + }); +} + export function initRepoIssueList() { if (!document.querySelectorAll('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list').length) return; initRepoIssueListCheckboxes(); initRepoIssueListAuthorDropdown(); + initIssuePinSort(); } |