diff --git a/web_src/js/components/RepoContributors.vue b/web_src/js/components/RepoContributors.vue
index e79fc80d8e..5d2c74b6a9 100644
--- a/web_src/js/components/RepoContributors.vue
+++ b/web_src/js/components/RepoContributors.vue
@@ -1,4 +1,5 @@
diff --git a/web_src/js/features/common-organization.ts b/web_src/js/features/common-organization.ts
index 47a61ece22..a1f19bedea 100644
--- a/web_src/js/features/common-organization.ts
+++ b/web_src/js/features/common-organization.ts
@@ -6,7 +6,7 @@ export function initCommonOrganization() {
return;
}
- document.querySelector('.organization.settings.options #org_name')?.addEventListener('input', function () {
+ document.querySelector('.organization.settings.options #org_name')?.addEventListener('input', function () {
const nameChanged = this.value.toLowerCase() !== this.getAttribute('data-org-name').toLowerCase();
toggleElem('#org-name-change-prompt', nameChanged);
});
diff --git a/web_src/js/features/comp/WebHookEditor.ts b/web_src/js/features/comp/WebHookEditor.ts
index 203396af80..794b3c99ca 100644
--- a/web_src/js/features/comp/WebHookEditor.ts
+++ b/web_src/js/features/comp/WebHookEditor.ts
@@ -6,7 +6,7 @@ export function initCompWebHookEditor() {
return;
}
- for (const input of document.querySelectorAll('.events.checkbox input')) {
+ for (const input of document.querySelectorAll('.events.checkbox input')) {
input.addEventListener('change', function () {
if (this.checked) {
showElem('.events.fields');
@@ -14,7 +14,7 @@ export function initCompWebHookEditor() {
});
}
- for (const input of document.querySelectorAll('.non-events.checkbox input')) {
+ for (const input of document.querySelectorAll('.non-events.checkbox input')) {
input.addEventListener('change', function () {
if (this.checked) {
hideElem('.events.fields');
@@ -34,7 +34,7 @@ export function initCompWebHookEditor() {
}
// Test delivery
- document.querySelector('#test-delivery')?.addEventListener('click', async function () {
+ document.querySelector('#test-delivery')?.addEventListener('click', async function () {
this.classList.add('is-loading', 'disabled');
await POST(this.getAttribute('data-link'));
setTimeout(() => {
diff --git a/web_src/js/features/dashboard.ts b/web_src/js/features/dashboard.ts
new file mode 100644
index 0000000000..71a0df3a64
--- /dev/null
+++ b/web_src/js/features/dashboard.ts
@@ -0,0 +1,9 @@
+import {createApp} from 'vue';
+import DashboardRepoList from '../components/DashboardRepoList.vue';
+
+export function initDashboardRepoList() {
+ const el = document.querySelector('#dashboard-repo-list');
+ if (el) {
+ createApp(DashboardRepoList).mount(el);
+ }
+}
diff --git a/web_src/js/features/install.ts b/web_src/js/features/install.ts
index 725dcafab0..dddeb1e954 100644
--- a/web_src/js/features/install.ts
+++ b/web_src/js/features/install.ts
@@ -27,7 +27,7 @@ function initPreInstall() {
const dbName = document.querySelector('#db_name');
// Database type change detection.
- document.querySelector('#db_type').addEventListener('change', function () {
+ document.querySelector('#db_type').addEventListener('change', function () {
const dbType = this.value;
hideElem('div[data-db-setting-for]');
showElem(`div[data-db-setting-for=${dbType}]`);
@@ -59,26 +59,26 @@ function initPreInstall() {
}
// TODO: better handling of exclusive relations.
- document.querySelector('#offline-mode input').addEventListener('change', function () {
+ document.querySelector('#offline-mode input').addEventListener('change', function () {
if (this.checked) {
document.querySelector('#disable-gravatar input').checked = true;
document.querySelector('#federated-avatar-lookup input').checked = false;
}
});
- document.querySelector('#disable-gravatar input').addEventListener('change', function () {
+ document.querySelector('#disable-gravatar input').addEventListener('change', function () {
if (this.checked) {
document.querySelector('#federated-avatar-lookup input').checked = false;
} else {
document.querySelector('#offline-mode input').checked = false;
}
});
- document.querySelector('#federated-avatar-lookup input').addEventListener('change', function () {
+ document.querySelector('#federated-avatar-lookup input').addEventListener('change', function () {
if (this.checked) {
document.querySelector('#disable-gravatar input').checked = false;
document.querySelector('#offline-mode input').checked = false;
}
});
- document.querySelector('#enable-openid-signin input').addEventListener('change', function () {
+ document.querySelector('#enable-openid-signin input').addEventListener('change', function () {
if (this.checked) {
if (!document.querySelector('#disable-registration input').checked) {
document.querySelector('#enable-openid-signup input').checked = true;
@@ -87,7 +87,7 @@ function initPreInstall() {
document.querySelector('#enable-openid-signup input').checked = false;
}
});
- document.querySelector('#disable-registration input').addEventListener('change', function () {
+ document.querySelector('#disable-registration input').addEventListener('change', function () {
if (this.checked) {
document.querySelector('#enable-captcha input').checked = false;
document.querySelector('#enable-openid-signup input').checked = false;
@@ -95,7 +95,7 @@ function initPreInstall() {
document.querySelector('#enable-openid-signup input').checked = true;
}
});
- document.querySelector('#enable-captcha input').addEventListener('change', function () {
+ document.querySelector('#enable-captcha input').addEventListener('change', function () {
if (this.checked) {
document.querySelector('#disable-registration input').checked = false;
}
diff --git a/web_src/js/features/pull-view-file.ts b/web_src/js/features/pull-view-file.ts
index 36fe4bc4df..5202d84b28 100644
--- a/web_src/js/features/pull-view-file.ts
+++ b/web_src/js/features/pull-view-file.ts
@@ -38,7 +38,7 @@ export function initViewedCheckboxListenerFor() {
// The checkbox consists of a div containing the real checkbox with its label and the CSRF token,
// hence the actual checkbox first has to be found
- const checkbox = form.querySelector('input[type=checkbox]');
+ const checkbox = form.querySelector('input[type=checkbox]');
checkbox.addEventListener('input', function() {
// Mark the file as viewed visually - will especially change the background
if (this.checked) {
diff --git a/web_src/js/features/repo-actions.ts b/web_src/js/features/repo-actions.ts
new file mode 100644
index 0000000000..cbd0429c04
--- /dev/null
+++ b/web_src/js/features/repo-actions.ts
@@ -0,0 +1,47 @@
+import {createApp} from 'vue';
+import RepoActionView from '../components/RepoActionView.vue';
+
+export function initRepositoryActionView() {
+ const el = document.querySelector('#repo-action-view');
+ if (!el) return;
+
+ // TODO: the parent element's full height doesn't work well now,
+ // but we can not pollute the global style at the moment, only fix the height problem for pages with this component
+ const parentFullHeight = document.querySelector('body > div.full.height');
+ if (parentFullHeight) parentFullHeight.style.paddingBottom = '0';
+
+ const view = createApp(RepoActionView, {
+ runIndex: el.getAttribute('data-run-index'),
+ jobIndex: el.getAttribute('data-job-index'),
+ actionsURL: el.getAttribute('data-actions-url'),
+ locale: {
+ approve: el.getAttribute('data-locale-approve'),
+ cancel: el.getAttribute('data-locale-cancel'),
+ rerun: el.getAttribute('data-locale-rerun'),
+ rerun_all: el.getAttribute('data-locale-rerun-all'),
+ scheduled: el.getAttribute('data-locale-runs-scheduled'),
+ commit: el.getAttribute('data-locale-runs-commit'),
+ pushedBy: el.getAttribute('data-locale-runs-pushed-by'),
+ artifactsTitle: el.getAttribute('data-locale-artifacts-title'),
+ areYouSure: el.getAttribute('data-locale-are-you-sure'),
+ confirmDeleteArtifact: el.getAttribute('data-locale-confirm-delete-artifact'),
+ showTimeStamps: el.getAttribute('data-locale-show-timestamps'),
+ showLogSeconds: el.getAttribute('data-locale-show-log-seconds'),
+ showFullScreen: el.getAttribute('data-locale-show-full-screen'),
+ downloadLogs: el.getAttribute('data-locale-download-logs'),
+ status: {
+ unknown: el.getAttribute('data-locale-status-unknown'),
+ waiting: el.getAttribute('data-locale-status-waiting'),
+ running: el.getAttribute('data-locale-status-running'),
+ success: el.getAttribute('data-locale-status-success'),
+ failure: el.getAttribute('data-locale-status-failure'),
+ cancelled: el.getAttribute('data-locale-status-cancelled'),
+ skipped: el.getAttribute('data-locale-status-skipped'),
+ blocked: el.getAttribute('data-locale-status-blocked'),
+ },
+ logsAlwaysAutoScroll: el.getAttribute('data-locale-logs-always-auto-scroll'),
+ logsAlwaysExpandRunning: el.getAttribute('data-locale-logs-always-expand-running'),
+ },
+ });
+ view.mount(el);
+}
diff --git a/web_src/js/features/repo-commit.ts b/web_src/js/features/repo-commit.ts
index 56493443d9..8994a57f4a 100644
--- a/web_src/js/features/repo-commit.ts
+++ b/web_src/js/features/repo-commit.ts
@@ -2,7 +2,7 @@ import {createTippy} from '../modules/tippy.ts';
import {toggleElem} from '../utils/dom.ts';
export function initRepoEllipsisButton() {
- for (const button of document.querySelectorAll('.js-toggle-commit-body')) {
+ for (const button of document.querySelectorAll('.js-toggle-commit-body')) {
button.addEventListener('click', function (e) {
e.preventDefault();
const expanded = this.getAttribute('aria-expanded') === 'true';
diff --git a/web_src/js/features/repo-home.ts b/web_src/js/features/repo-home.ts
index 9c1e317486..763f8e503f 100644
--- a/web_src/js/features/repo-home.ts
+++ b/web_src/js/features/repo-home.ts
@@ -89,7 +89,7 @@ export function initRepoTopicBar() {
url: `${appSubUrl}/explore/topics/search?q={query}`,
throttle: 500,
cache: false,
- onResponse(res) {
+ onResponse(this: any, res: any) {
const formattedResponse = {
success: false,
results: [],
diff --git a/web_src/js/features/repo-issue.ts b/web_src/js/features/repo-issue.ts
index d74d3f7700..d2a89682e8 100644
--- a/web_src/js/features/repo-issue.ts
+++ b/web_src/js/features/repo-issue.ts
@@ -216,7 +216,7 @@ export function initRepoIssueCodeCommentCancel() {
export function initRepoPullRequestUpdate() {
// Pull Request update button
- const pullUpdateButton = document.querySelector('.update-button > button');
+ const pullUpdateButton = document.querySelector('.update-button > button');
if (!pullUpdateButton) return;
pullUpdateButton.addEventListener('click', async function (e) {
diff --git a/web_src/js/features/repo-settings.ts b/web_src/js/features/repo-settings.ts
index 90b0219f3e..7b3ab504cb 100644
--- a/web_src/js/features/repo-settings.ts
+++ b/web_src/js/features/repo-settings.ts
@@ -79,21 +79,21 @@ function initRepoSettingsGitHook() {
function initRepoSettingsBranches() {
if (!document.querySelector('.repository.settings.branches')) return;
- for (const el of document.querySelectorAll('.toggle-target-enabled')) {
+ for (const el of document.querySelectorAll('.toggle-target-enabled')) {
el.addEventListener('change', function () {
const target = document.querySelector(this.getAttribute('data-target'));
target?.classList.toggle('disabled', !this.checked);
});
}
- for (const el of document.querySelectorAll('.toggle-target-disabled')) {
+ for (const el of document.querySelectorAll('.toggle-target-disabled')) {
el.addEventListener('change', function () {
const target = document.querySelector(this.getAttribute('data-target'));
if (this.checked) target?.classList.add('disabled'); // only disable, do not auto enable
});
}
- document.querySelector('#dismiss_stale_approvals')?.addEventListener('change', function () {
+ document.querySelector('#dismiss_stale_approvals')?.addEventListener('change', function () {
document.querySelector('#ignore_stale_approvals_box')?.classList.toggle('disabled', this.checked);
});
diff --git a/web_src/js/features/sshkey-helper.ts b/web_src/js/features/sshkey-helper.ts
index 9234e3ec44..860bc5b294 100644
--- a/web_src/js/features/sshkey-helper.ts
+++ b/web_src/js/features/sshkey-helper.ts
@@ -1,6 +1,6 @@
export function initSshKeyFormParser() {
// Parse SSH Key
- document.querySelector('#ssh-key-content')?.addEventListener('input', function () {
+ document.querySelector('#ssh-key-content')?.addEventListener('input', function () {
const arrays = this.value.split(' ');
const title = document.querySelector('#ssh-key-title');
if (!title.value && arrays.length === 3 && arrays[2] !== '') {
diff --git a/web_src/js/features/user-settings.ts b/web_src/js/features/user-settings.ts
index c097df7b6c..6312a8b682 100644
--- a/web_src/js/features/user-settings.ts
+++ b/web_src/js/features/user-settings.ts
@@ -13,7 +13,7 @@ export function initUserSettings() {
initUserSettingsAvatarCropper();
- const usernameInput = document.querySelector('#username');
+ const usernameInput = document.querySelector('#username');
if (!usernameInput) return;
usernameInput.addEventListener('input', function () {
const prompt = document.querySelector('#name-change-prompt');
diff --git a/web_src/js/index.ts b/web_src/js/index.ts
index 022be033da..b89e596047 100644
--- a/web_src/js/index.ts
+++ b/web_src/js/index.ts
@@ -2,8 +2,7 @@
import './bootstrap.ts';
import './htmx.ts';
-import {initDashboardRepoList} from './components/DashboardRepoList.vue';
-
+import {initDashboardRepoList} from './features/dashboard.ts';
import {initGlobalCopyToClipboardListener} from './features/clipboard.ts';
import {initContextPopups} from './features/contextpopup.ts';
import {initRepoGraphGit} from './features/repo-graph.ts';
@@ -53,7 +52,7 @@ import {initRepoWikiForm} from './features/repo-wiki.ts';
import {initRepository, initBranchSelectorTabs} from './features/repo-legacy.ts';
import {initCopyContent} from './features/copycontent.ts';
import {initCaptcha} from './features/captcha.ts';
-import {initRepositoryActionView} from './components/RepoActionView.vue';
+import {initRepositoryActionView} from './features/repo-actions.ts';
import {initGlobalTooltips} from './modules/tippy.ts';
import {initGiteaFomantic} from './modules/fomantic.ts';
import {initSubmitEventPolyfill, onDomReady} from './utils/dom.ts';
diff --git a/web_src/js/modules/fomantic/dimmer.ts b/web_src/js/modules/fomantic/dimmer.ts
index 4e05cac0cd..cbdfac23cb 100644
--- a/web_src/js/modules/fomantic/dimmer.ts
+++ b/web_src/js/modules/fomantic/dimmer.ts
@@ -3,7 +3,7 @@ import {queryElemChildren} from '../../utils/dom.ts';
export function initFomanticDimmer() {
// stand-in for removed dimmer module
- $.fn.dimmer = function (arg0: string, arg1: any) {
+ $.fn.dimmer = function (this: any, arg0: string, arg1: any) {
if (arg0 === 'add content') {
const $el = arg1;
const existingDimmer = document.querySelector('body > .ui.dimmer');
diff --git a/web_src/js/modules/fomantic/dropdown.ts b/web_src/js/modules/fomantic/dropdown.ts
index 9bdc9bfc33..e479c79ee6 100644
--- a/web_src/js/modules/fomantic/dropdown.ts
+++ b/web_src/js/modules/fomantic/dropdown.ts
@@ -17,7 +17,7 @@ export function initAriaDropdownPatch() {
// the patched `$.fn.dropdown` function, it passes the arguments to Fomantic's `$.fn.dropdown` function, and:
// * it does the one-time attaching on the first call
// * it delegates the `onLabelCreate` to the patched `onLabelCreate` to add necessary aria attributes
-function ariaDropdownFn(...args: Parameters) {
+function ariaDropdownFn(this: any, ...args: Parameters) {
const ret = fomanticDropdownFn.apply(this, args);
// if the `$().dropdown()` call is without arguments, or it has non-string (object) argument,
@@ -76,18 +76,18 @@ function delegateOne($dropdown: any) {
const oldFocusSearch = dropdownCall('internal', 'focusSearch');
const oldBlurSearch = dropdownCall('internal', 'blurSearch');
// * If the "dropdown icon" is clicked, Fomantic calls "focusSearch", so show the menu
- dropdownCall('internal', 'focusSearch', function () { dropdownCall('show'); oldFocusSearch.call(this) });
+ dropdownCall('internal', 'focusSearch', function (this: any) { dropdownCall('show'); oldFocusSearch.call(this) });
// * If the "dropdown icon" is clicked again when the menu is visible, Fomantic calls "blurSearch", so hide the menu
- dropdownCall('internal', 'blurSearch', function () { oldBlurSearch.call(this); dropdownCall('hide') });
+ dropdownCall('internal', 'blurSearch', function (this: any) { oldBlurSearch.call(this); dropdownCall('hide') });
const oldFilterItems = dropdownCall('internal', 'filterItems');
- dropdownCall('internal', 'filterItems', function (...args: any[]) {
+ dropdownCall('internal', 'filterItems', function (this: any, ...args: any[]) {
oldFilterItems.call(this, ...args);
processMenuItems($dropdown, dropdownCall);
});
const oldShow = dropdownCall('internal', 'show');
- dropdownCall('internal', 'show', function (...args: any[]) {
+ dropdownCall('internal', 'show', function (this: any, ...args: any[]) {
oldShow.call(this, ...args);
processMenuItems($dropdown, dropdownCall);
});
@@ -110,7 +110,7 @@ function delegateOne($dropdown: any) {
// the `onLabelCreate` is used to add necessary aria attributes for dynamically created selection labels
const dropdownOnLabelCreateOld = dropdownCall('setting', 'onLabelCreate');
- dropdownCall('setting', 'onLabelCreate', function(value: any, text: string) {
+ dropdownCall('setting', 'onLabelCreate', function(this: any, value: any, text: string) {
const $label = dropdownOnLabelCreateOld.call(this, value, text);
updateSelectionLabel($label[0]);
return $label;
diff --git a/web_src/js/modules/fomantic/modal.ts b/web_src/js/modules/fomantic/modal.ts
index fb80047d01..6a2c558890 100644
--- a/web_src/js/modules/fomantic/modal.ts
+++ b/web_src/js/modules/fomantic/modal.ts
@@ -12,7 +12,7 @@ export function initAriaModalPatch() {
// the patched `$.fn.modal` modal function
// * it does the one-time attaching on the first call
-function ariaModalFn(...args: Parameters) {
+function ariaModalFn(this: any, ...args: Parameters) {
const ret = fomanticModalFn.apply(this, args);
if (args[0] === 'show' || args[0]?.autoShow) {
for (const el of this) {
diff --git a/web_src/js/modules/tippy.ts b/web_src/js/modules/tippy.ts
index aaaf580de1..bc6d5bfdd6 100644
--- a/web_src/js/modules/tippy.ts
+++ b/web_src/js/modules/tippy.ts
@@ -121,7 +121,7 @@ function switchTitleToTooltip(target: Element): void {
* Some browsers like PaleMoon don't support "addEventListener('mouseenter', capture)"
* The tippy by default uses "mouseenter" event to show, so we use "mouseover" event to switch to tippy
*/
-function lazyTooltipOnMouseHover(e: Event): void {
+function lazyTooltipOnMouseHover(this: HTMLElement, e: Event): void {
e.target.removeEventListener('mouseover', lazyTooltipOnMouseHover, true);
attachTooltip(this);
}
diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts
index 6a8246fa1b..b074fecd04 100644
--- a/web_src/js/svg.ts
+++ b/web_src/js/svg.ts
@@ -1,4 +1,4 @@
-import {h} from 'vue';
+import {defineComponent, h, type PropType} from 'vue';
import {parseDom, serializeXml} from './utils.ts';
import giteaDoubleChevronLeft from '../../public/assets/img/svg/gitea-double-chevron-left.svg';
import giteaDoubleChevronRight from '../../public/assets/img/svg/gitea-double-chevron-right.svg';
@@ -194,10 +194,10 @@ export function svgParseOuterInner(name: SvgName) {
return {svgOuter, svgInnerHtml};
}
-export const SvgIcon = {
+export const SvgIcon = defineComponent({
name: 'SvgIcon',
props: {
- name: {type: String, required: true},
+ name: {type: String as PropType, required: true},
size: {type: Number, default: 16},
className: {type: String, default: ''},
symbolId: {type: String},
@@ -215,7 +215,7 @@ export const SvgIcon = {
attrs[`^height`] = this.size;
// make the classes work together
- const classes = [];
+ const classes: Array = [];
for (const cls of svgOuter.classList) {
classes.push(cls);
}
@@ -234,4 +234,4 @@ export const SvgIcon = {
innerHTML: svgInnerHtml,
});
},
-};
+});