1
1
mirror of https://github.com/go-gitea/gitea synced 2025-01-05 15:34:25 +00:00

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`
This commit is contained in:
wxiaoguang 2025-01-02 01:21:13 +08:00 committed by GitHub
parent 85c756e279
commit c1167709ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 69 additions and 57 deletions

View File

@ -1,10 +1,53 @@
import {hideElem, showElem} from '../utils/dom.ts';
import {hideElem, showElem, toggleElem} from '../utils/dom.ts';
import {htmlEscape} from 'escape-goat';
import {fomanticQuery} from '../modules/fomantic/base.ts';
const {appSubUrl} = window.config;
function initRepoNewTemplateSearch(form: HTMLFormElement) {
const inputRepoOwnerUid = form.querySelector<HTMLInputElement>('#uid');
const elRepoTemplateDropdown = form.querySelector<HTMLInputElement>('#repo_template_search');
const inputRepoTemplate = form.querySelector<HTMLInputElement>('#repo_template');
const elTemplateUnits = form.querySelector('#template_units');
const elNonTemplate = form.querySelector('#non_template');
const checkTemplate = function () {
const hasSelectedTemplate = inputRepoTemplate.value !== '' && inputRepoTemplate.value !== '0';
toggleElem(elTemplateUnits, hasSelectedTemplate);
toggleElem(elNonTemplate, !hasSelectedTemplate);
};
inputRepoTemplate.addEventListener('change', checkTemplate);
checkTemplate();
const $dropdown = fomanticQuery(elRepoTemplateDropdown);
const onChangeOwner = function () {
$dropdown.dropdown('setting', {
apiSettings: {
url: `${appSubUrl}/repo/search?q={query}&template=true&priority_owner_id=${inputRepoOwnerUid.value}`,
onResponse(response) {
const results = [];
results.push({name: '', value: ''}); // empty item means not using template
for (const tmplRepo of response.data) {
results.push({
name: htmlEscape(tmplRepo.repository.full_name),
value: String(tmplRepo.repository.id),
});
}
$dropdown.fomanticExt.onResponseKeepSelectedItem($dropdown, inputRepoTemplate.value);
return {results};
},
cache: false,
},
});
};
inputRepoOwnerUid.addEventListener('change', onChangeOwner);
onChangeOwner();
}
export function initRepoNew() {
const pageContent = document.querySelector('.page-content.repository.new-repo');
if (!pageContent) return;
const form = document.querySelector('.new-repo-form');
const form = document.querySelector<HTMLFormElement>('.new-repo-form');
const inputGitIgnores = form.querySelector<HTMLInputElement>('input[name="gitignores"]');
const inputLicense = form.querySelector<HTMLInputElement>('input[name="license"]');
const inputAutoInit = form.querySelector<HTMLInputElement>('input[name="auto_init"]');
@ -32,4 +75,6 @@ export function initRepoNew() {
};
inputRepoName.addEventListener('input', updateUiRepoName);
updateUiRepoName();
initRepoNewTemplateSearch(form);
}

View File

@ -1,51 +0,0 @@
import $ from 'jquery';
import {htmlEscape} from 'escape-goat';
import {hideElem, showElem} from '../utils/dom.ts';
const {appSubUrl} = window.config;
export function initRepoTemplateSearch() {
const $repoTemplate = $('#repo_template');
const checkTemplate = function () {
const $templateUnits = $('#template_units');
const $nonTemplate = $('#non_template');
if ($repoTemplate.val() !== '' && $repoTemplate.val() !== '0') {
showElem($templateUnits);
hideElem($nonTemplate);
} else {
hideElem($templateUnits);
showElem($nonTemplate);
}
};
$repoTemplate.on('change', checkTemplate);
checkTemplate();
const changeOwner = function () {
$('#repo_template_search')
.dropdown({
apiSettings: {
url: `${appSubUrl}/repo/search?q={query}&template=true&priority_owner_id=${$('#uid').val()}`,
onResponse(response) {
const filteredResponse = {success: true, results: []};
filteredResponse.results.push({
name: '',
value: '',
});
// Parse the response from the api to work with our dropdown
$.each(response.data, (_r, repo) => {
filteredResponse.results.push({
name: htmlEscape(repo.repository.full_name),
value: repo.repository.id,
});
});
return filteredResponse;
},
cache: false,
},
fullTextSearch: true,
});
};
$('#uid').on('change', changeOwner);
changeOwner();
}

View File

@ -36,8 +36,9 @@ declare module 'swagger-ui-dist/swagger-ui-es-bundle.js' {
}
interface JQuery {
api: any, // fomantic
areYouSure: any, // jquery.are-you-sure
fomanticExt: any; // fomantic extension
api: any, // fomantic
dimmer: any, // fomantic
dropdown: any; // fomantic
modal: any; // fomantic

View File

@ -34,7 +34,6 @@ import {
import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts';
import {initRepoTopicBar} from './features/repo-home.ts';
import {initAdminCommon} from './features/admin/common.ts';
import {initRepoTemplateSearch} from './features/repo-template.ts';
import {initRepoCodeView} from './features/repo-code.ts';
import {initSshKeyFormParser} from './features/sshkey-helper.ts';
import {initUserSettings} from './features/user-settings.ts';
@ -193,7 +192,6 @@ onDomReady(() => {
initRepoPullRequestReview,
initRepoRelease,
initRepoReleaseNew,
initRepoTemplateSearch,
initRepoTopicBar,
initRepoWikiForm,
initRepository,

View File

@ -11,9 +11,10 @@ import {svg} from '../svg.ts';
export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');
export function initGiteaFomantic() {
// our extensions
$.fn.fomanticExt = {};
// Silence fomantic's error logging when tabs are used without a target content element
$.fn.tab.settings.silent = true;
// By default, use "exact match" for full text search
$.fn.dropdown.settings.fullTextSearch = 'exact';
// Do not use "cursor: pointer" for dropdown labels

View File

@ -1,6 +1,7 @@
import $ from 'jquery';
import {generateAriaId} from './base.ts';
import type {FomanticInitFunction} from '../../types.ts';
import {queryElems} from '../../utils/dom.ts';
const ariaPatchKey = '_giteaAriaPatchDropdown';
const fomanticDropdownFn = $.fn.dropdown;
@ -9,6 +10,7 @@ const fomanticDropdownFn = $.fn.dropdown;
export function initAriaDropdownPatch() {
if ($.fn.dropdown === ariaDropdownFn) throw new Error('initAriaDropdownPatch could only be called once');
$.fn.dropdown = ariaDropdownFn;
$.fn.fomanticExt.onResponseKeepSelectedItem = onResponseKeepSelectedItem;
(ariaDropdownFn as FomanticInitFunction).settings = fomanticDropdownFn.settings;
}
@ -351,3 +353,19 @@ export function hideScopedEmptyDividers(container: Element) {
if (item.nextElementSibling?.matches('.divider')) hideDivider(item);
}
}
function onResponseKeepSelectedItem(dropdown: typeof $|HTMLElement, selectedValue: string) {
// There is a bug in fomantic dropdown when using "apiSettings" to fetch data
// * when there is a selected item, the dropdown insists on hiding the selected one from the list:
// * in the "filter" function: ('[data-value="'+value+'"]').addClass(className.filtered)
//
// When user selects one item, and click the dropdown again,
// then the dropdown only shows other items and will select another (wrong) one.
// It can't be easily fix by using setTimeout(patch, 0) in `onResponse` because the `onResponse` is called before another `setTimeout(..., timeLeft)`
// Fortunately, the "timeLeft" is controlled by "loadingDuration" which is always zero at the moment, so we can use `setTimeout(..., 10)`
const elDropdown = (dropdown instanceof HTMLElement) ? dropdown : dropdown[0];
setTimeout(() => {
queryElems(elDropdown, `.menu .item[data-value="${CSS.escape(selectedValue)}"].filtered`, (el) => el.classList.remove('filtered'));
$(elDropdown).dropdown('set selected', selectedValue ?? '');
}, 10);
}