Skip to content

Commit c116770

Browse files
authored
Refactor repo-new.ts (#33070)
1. merge `repo-template.ts` into `repo-new.ts` (they are all for "/repo/create") 2. remove jquery 3. fix an anonying fomantic dropdown bug, see the comment of `onResponseKeepSelectedItem`
1 parent 85c756e commit c116770

File tree

6 files changed

+69
-57
lines changed

6 files changed

+69
-57
lines changed

Diff for: web_src/js/features/repo-new.ts

+47-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,53 @@
1-
import {hideElem, showElem} from '../utils/dom.ts';
1+
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
2+
import {htmlEscape} from 'escape-goat';
3+
import {fomanticQuery} from '../modules/fomantic/base.ts';
4+
5+
const {appSubUrl} = window.config;
6+
7+
function initRepoNewTemplateSearch(form: HTMLFormElement) {
8+
const inputRepoOwnerUid = form.querySelector<HTMLInputElement>('#uid');
9+
const elRepoTemplateDropdown = form.querySelector<HTMLInputElement>('#repo_template_search');
10+
const inputRepoTemplate = form.querySelector<HTMLInputElement>('#repo_template');
11+
const elTemplateUnits = form.querySelector('#template_units');
12+
const elNonTemplate = form.querySelector('#non_template');
13+
const checkTemplate = function () {
14+
const hasSelectedTemplate = inputRepoTemplate.value !== '' && inputRepoTemplate.value !== '0';
15+
toggleElem(elTemplateUnits, hasSelectedTemplate);
16+
toggleElem(elNonTemplate, !hasSelectedTemplate);
17+
};
18+
inputRepoTemplate.addEventListener('change', checkTemplate);
19+
checkTemplate();
20+
21+
const $dropdown = fomanticQuery(elRepoTemplateDropdown);
22+
const onChangeOwner = function () {
23+
$dropdown.dropdown('setting', {
24+
apiSettings: {
25+
url: `${appSubUrl}/repo/search?q={query}&template=true&priority_owner_id=${inputRepoOwnerUid.value}`,
26+
onResponse(response) {
27+
const results = [];
28+
results.push({name: '', value: ''}); // empty item means not using template
29+
for (const tmplRepo of response.data) {
30+
results.push({
31+
name: htmlEscape(tmplRepo.repository.full_name),
32+
value: String(tmplRepo.repository.id),
33+
});
34+
}
35+
$dropdown.fomanticExt.onResponseKeepSelectedItem($dropdown, inputRepoTemplate.value);
36+
return {results};
37+
},
38+
cache: false,
39+
},
40+
});
41+
};
42+
inputRepoOwnerUid.addEventListener('change', onChangeOwner);
43+
onChangeOwner();
44+
}
245

346
export function initRepoNew() {
447
const pageContent = document.querySelector('.page-content.repository.new-repo');
548
if (!pageContent) return;
649

7-
const form = document.querySelector('.new-repo-form');
50+
const form = document.querySelector<HTMLFormElement>('.new-repo-form');
851
const inputGitIgnores = form.querySelector<HTMLInputElement>('input[name="gitignores"]');
952
const inputLicense = form.querySelector<HTMLInputElement>('input[name="license"]');
1053
const inputAutoInit = form.querySelector<HTMLInputElement>('input[name="auto_init"]');
@@ -32,4 +75,6 @@ export function initRepoNew() {
3275
};
3376
inputRepoName.addEventListener('input', updateUiRepoName);
3477
updateUiRepoName();
78+
79+
initRepoNewTemplateSearch(form);
3580
}

Diff for: web_src/js/features/repo-template.ts

-51
This file was deleted.

Diff for: web_src/js/globals.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ declare module 'swagger-ui-dist/swagger-ui-es-bundle.js' {
3636
}
3737

3838
interface JQuery {
39-
api: any, // fomantic
4039
areYouSure: any, // jquery.are-you-sure
40+
fomanticExt: any; // fomantic extension
41+
api: any, // fomantic
4142
dimmer: any, // fomantic
4243
dropdown: any; // fomantic
4344
modal: any; // fomantic

Diff for: web_src/js/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts';
3535
import {initRepoTopicBar} from './features/repo-home.ts';
3636
import {initAdminCommon} from './features/admin/common.ts';
37-
import {initRepoTemplateSearch} from './features/repo-template.ts';
3837
import {initRepoCodeView} from './features/repo-code.ts';
3938
import {initSshKeyFormParser} from './features/sshkey-helper.ts';
4039
import {initUserSettings} from './features/user-settings.ts';
@@ -193,7 +192,6 @@ onDomReady(() => {
193192
initRepoPullRequestReview,
194193
initRepoRelease,
195194
initRepoReleaseNew,
196-
initRepoTemplateSearch,
197195
initRepoTopicBar,
198196
initRepoWikiForm,
199197
initRepository,

Diff for: web_src/js/modules/fomantic.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import {svg} from '../svg.ts';
1111
export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');
1212

1313
export function initGiteaFomantic() {
14+
// our extensions
15+
$.fn.fomanticExt = {};
1416
// Silence fomantic's error logging when tabs are used without a target content element
1517
$.fn.tab.settings.silent = true;
16-
1718
// By default, use "exact match" for full text search
1819
$.fn.dropdown.settings.fullTextSearch = 'exact';
1920
// Do not use "cursor: pointer" for dropdown labels

Diff for: web_src/js/modules/fomantic/dropdown.ts

+18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import $ from 'jquery';
22
import {generateAriaId} from './base.ts';
33
import type {FomanticInitFunction} from '../../types.ts';
4+
import {queryElems} from '../../utils/dom.ts';
45

56
const ariaPatchKey = '_giteaAriaPatchDropdown';
67
const fomanticDropdownFn = $.fn.dropdown;
@@ -9,6 +10,7 @@ const fomanticDropdownFn = $.fn.dropdown;
910
export function initAriaDropdownPatch() {
1011
if ($.fn.dropdown === ariaDropdownFn) throw new Error('initAriaDropdownPatch could only be called once');
1112
$.fn.dropdown = ariaDropdownFn;
13+
$.fn.fomanticExt.onResponseKeepSelectedItem = onResponseKeepSelectedItem;
1214
(ariaDropdownFn as FomanticInitFunction).settings = fomanticDropdownFn.settings;
1315
}
1416

@@ -351,3 +353,19 @@ export function hideScopedEmptyDividers(container: Element) {
351353
if (item.nextElementSibling?.matches('.divider')) hideDivider(item);
352354
}
353355
}
356+
357+
function onResponseKeepSelectedItem(dropdown: typeof $|HTMLElement, selectedValue: string) {
358+
// There is a bug in fomantic dropdown when using "apiSettings" to fetch data
359+
// * when there is a selected item, the dropdown insists on hiding the selected one from the list:
360+
// * in the "filter" function: ('[data-value="'+value+'"]').addClass(className.filtered)
361+
//
362+
// When user selects one item, and click the dropdown again,
363+
// then the dropdown only shows other items and will select another (wrong) one.
364+
// It can't be easily fix by using setTimeout(patch, 0) in `onResponse` because the `onResponse` is called before another `setTimeout(..., timeLeft)`
365+
// Fortunately, the "timeLeft" is controlled by "loadingDuration" which is always zero at the moment, so we can use `setTimeout(..., 10)`
366+
const elDropdown = (dropdown instanceof HTMLElement) ? dropdown : dropdown[0];
367+
setTimeout(() => {
368+
queryElems(elDropdown, `.menu .item[data-value="${CSS.escape(selectedValue)}"].filtered`, (el) => el.classList.remove('filtered'));
369+
$(elDropdown).dropdown('set selected', selectedValue ?? '');
370+
}, 10);
371+
}

0 commit comments

Comments
 (0)