aboutsummaryrefslogtreecommitdiffstats
path: root/web_src
diff options
context:
space:
mode:
Diffstat (limited to 'web_src')
-rw-r--r--web_src/js/features/repo-issue-list.ts6
-rw-r--r--web_src/js/features/repo-settings-branches.test.ts71
-rw-r--r--web_src/js/features/repo-settings-branches.ts32
-rw-r--r--web_src/js/features/repo-settings.ts2
-rw-r--r--web_src/js/svg.ts2
5 files changed, 112 insertions, 1 deletions
diff --git a/web_src/js/features/repo-issue-list.ts b/web_src/js/features/repo-issue-list.ts
index 931122db3c..a7185e5f99 100644
--- a/web_src/js/features/repo-issue-list.ts
+++ b/web_src/js/features/repo-issue-list.ts
@@ -196,7 +196,11 @@ async function initIssuePinSort() {
createSortable(pinDiv, {
group: 'shared',
- onEnd: pinMoveEnd, // eslint-disable-line @typescript-eslint/no-misused-promises
+ onEnd: (e) => {
+ (async () => {
+ await pinMoveEnd(e);
+ })();
+ },
});
}
diff --git a/web_src/js/features/repo-settings-branches.test.ts b/web_src/js/features/repo-settings-branches.test.ts
new file mode 100644
index 0000000000..023039334f
--- /dev/null
+++ b/web_src/js/features/repo-settings-branches.test.ts
@@ -0,0 +1,71 @@
+import {beforeEach, describe, expect, test, vi} from 'vitest';
+import {initRepoBranchesSettings} from './repo-settings-branches.ts';
+import {POST} from '../modules/fetch.ts';
+import {createSortable} from '../modules/sortable.ts';
+
+vi.mock('../modules/fetch.ts', () => ({
+ POST: vi.fn(),
+}));
+
+vi.mock('../modules/sortable.ts', () => ({
+ createSortable: vi.fn(),
+}));
+
+describe('Repository Branch Settings', () => {
+ beforeEach(() => {
+ document.body.innerHTML = `
+ <div id="protected-branches-list" data-update-priority-url="some/repo/branches/priority">
+ <div class="flex-item tw-items-center item" data-id="1" >
+ <div class="drag-handle"></div>
+ </div>
+ <div class="flex-item tw-items-center item" data-id="2" >
+ <div class="drag-handle"></div>
+ </div>
+ <div class="flex-item tw-items-center item" data-id="3" >
+ <div class="drag-handle"></div>
+ </div>
+ </div>
+ `;
+
+ vi.clearAllMocks();
+ });
+
+ test('should initialize sortable for protected branches list', () => {
+ initRepoBranchesSettings();
+
+ expect(createSortable).toHaveBeenCalledWith(
+ document.querySelector('#protected-branches-list'),
+ expect.objectContaining({
+ handle: '.drag-handle',
+ animation: 150,
+ }),
+ );
+ });
+
+ test('should not initialize if protected branches list is not present', () => {
+ document.body.innerHTML = '';
+
+ initRepoBranchesSettings();
+
+ expect(createSortable).not.toHaveBeenCalled();
+ });
+
+ test('should post new order after sorting', async () => {
+ vi.mocked(POST).mockResolvedValue({ok: true} as Response);
+
+ // Mock createSortable to capture and execute the onEnd callback
+ vi.mocked(createSortable).mockImplementation((_el, options) => {
+ options.onEnd();
+ return {destroy: vi.fn()};
+ });
+
+ initRepoBranchesSettings();
+
+ expect(POST).toHaveBeenCalledWith(
+ 'some/repo/branches/priority',
+ expect.objectContaining({
+ data: {ids: [1, 2, 3]},
+ }),
+ );
+ });
+});
diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts
new file mode 100644
index 0000000000..43b98f79b3
--- /dev/null
+++ b/web_src/js/features/repo-settings-branches.ts
@@ -0,0 +1,32 @@
+import {createSortable} from '../modules/sortable.ts';
+import {POST} from '../modules/fetch.ts';
+import {showErrorToast} from '../modules/toast.ts';
+import {queryElemChildren} from '../utils/dom.ts';
+
+export function initRepoBranchesSettings() {
+ const protectedBranchesList = document.querySelector('#protected-branches-list');
+ if (!protectedBranchesList) return;
+
+ createSortable(protectedBranchesList, {
+ handle: '.drag-handle',
+ animation: 150,
+
+ onEnd: () => {
+ (async () => {
+ const itemElems = queryElemChildren(protectedBranchesList, '.item[data-id]');
+ const itemIds = Array.from(itemElems, (el) => parseInt(el.getAttribute('data-id')));
+
+ try {
+ await POST(protectedBranchesList.getAttribute('data-update-priority-url'), {
+ data: {
+ ids: itemIds,
+ },
+ });
+ } catch (err) {
+ const errorMessage = String(err);
+ showErrorToast(`Failed to update branch protection rule priority:, error: ${errorMessage}`);
+ }
+ })();
+ },
+ });
+}
diff --git a/web_src/js/features/repo-settings.ts b/web_src/js/features/repo-settings.ts
index 72213f794a..5a009cfea4 100644
--- a/web_src/js/features/repo-settings.ts
+++ b/web_src/js/features/repo-settings.ts
@@ -3,6 +3,7 @@ import {minimatch} from 'minimatch';
import {createMonaco} from './codeeditor.ts';
import {onInputDebounce, queryElems, toggleElem} from '../utils/dom.ts';
import {POST} from '../modules/fetch.ts';
+import {initRepoBranchesSettings} from './repo-settings-branches.ts';
const {appSubUrl, csrfToken} = window.config;
@@ -154,4 +155,5 @@ export function initRepoSettings() {
initRepoSettingsCollaboration();
initRepoSettingsSearchTeamBox();
initRepoSettingsGitHook();
+ initRepoBranchesSettings();
}
diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts
index d04f63793f..cbb1af4ba1 100644
--- a/web_src/js/svg.ts
+++ b/web_src/js/svg.ts
@@ -34,6 +34,7 @@ import octiconGitCommit from '../../public/assets/img/svg/octicon-git-commit.svg
import octiconGitMerge from '../../public/assets/img/svg/octicon-git-merge.svg';
import octiconGitPullRequest from '../../public/assets/img/svg/octicon-git-pull-request.svg';
import octiconGitPullRequestDraft from '../../public/assets/img/svg/octicon-git-pull-request-draft.svg';
+import octiconGrabber from '../../public/assets/img/svg/octicon-grabber.svg';
import octiconHeading from '../../public/assets/img/svg/octicon-heading.svg';
import octiconHorizontalRule from '../../public/assets/img/svg/octicon-horizontal-rule.svg';
import octiconImage from '../../public/assets/img/svg/octicon-image.svg';
@@ -107,6 +108,7 @@ const svgs = {
'octicon-git-merge': octiconGitMerge,
'octicon-git-pull-request': octiconGitPullRequest,
'octicon-git-pull-request-draft': octiconGitPullRequestDraft,
+ 'octicon-grabber': octiconGrabber,
'octicon-heading': octiconHeading,
'octicon-horizontal-rule': octiconHorizontalRule,
'octicon-image': octiconImage,