mirror of https://github.com/go-gitea/gitea.git
Fix a number of typescript issues (#32459)
Fixes 69 typescript errors found in the `admin` and `markup` folders. --------- Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
parent
f888e45432
commit
f35e2b0cd1
|
@ -5,15 +5,15 @@ import {POST} from '../../modules/fetch.ts';
|
||||||
|
|
||||||
const {appSubUrl} = window.config;
|
const {appSubUrl} = window.config;
|
||||||
|
|
||||||
function onSecurityProtocolChange() {
|
function onSecurityProtocolChange(): void {
|
||||||
if (Number(document.querySelector('#security_protocol')?.value) > 0) {
|
if (Number(document.querySelector<HTMLInputElement>('#security_protocol')?.value) > 0) {
|
||||||
showElem('.has-tls');
|
showElem('.has-tls');
|
||||||
} else {
|
} else {
|
||||||
hideElem('.has-tls');
|
hideElem('.has-tls');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initAdminCommon() {
|
export function initAdminCommon(): void {
|
||||||
if (!document.querySelector('.page-content.admin')) return;
|
if (!document.querySelector('.page-content.admin')) return;
|
||||||
|
|
||||||
// check whether appUrl(ROOT_URL) is correct, if not, show an error message
|
// check whether appUrl(ROOT_URL) is correct, if not, show an error message
|
||||||
|
@ -21,34 +21,34 @@ export function initAdminCommon() {
|
||||||
|
|
||||||
// New user
|
// New user
|
||||||
if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) {
|
if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) {
|
||||||
document.querySelector('#login_type')?.addEventListener('change', function () {
|
document.querySelector<HTMLInputElement>('#login_type')?.addEventListener('change', function () {
|
||||||
if (this.value?.substring(0, 1) === '0') {
|
if (this.value?.startsWith('0')) {
|
||||||
document.querySelector('#user_name')?.removeAttribute('disabled');
|
document.querySelector<HTMLInputElement>('#user_name')?.removeAttribute('disabled');
|
||||||
document.querySelector('#login_name')?.removeAttribute('required');
|
document.querySelector<HTMLInputElement>('#login_name')?.removeAttribute('required');
|
||||||
hideElem('.non-local');
|
hideElem('.non-local');
|
||||||
showElem('.local');
|
showElem('.local');
|
||||||
document.querySelector('#user_name')?.focus();
|
document.querySelector<HTMLInputElement>('#user_name')?.focus();
|
||||||
|
|
||||||
if (this.getAttribute('data-password') === 'required') {
|
if (this.getAttribute('data-password') === 'required') {
|
||||||
document.querySelector('#password')?.setAttribute('required', 'required');
|
document.querySelector('#password')?.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (document.querySelector('.admin.edit.user')) {
|
if (document.querySelector<HTMLDivElement>('.admin.edit.user')) {
|
||||||
document.querySelector('#user_name')?.setAttribute('disabled', 'disabled');
|
document.querySelector<HTMLInputElement>('#user_name')?.setAttribute('disabled', 'disabled');
|
||||||
}
|
}
|
||||||
document.querySelector('#login_name')?.setAttribute('required', 'required');
|
document.querySelector<HTMLInputElement>('#login_name')?.setAttribute('required', 'required');
|
||||||
showElem('.non-local');
|
showElem('.non-local');
|
||||||
hideElem('.local');
|
hideElem('.local');
|
||||||
document.querySelector('#login_name')?.focus();
|
document.querySelector<HTMLInputElement>('#login_name')?.focus();
|
||||||
|
|
||||||
document.querySelector('#password')?.removeAttribute('required');
|
document.querySelector<HTMLInputElement>('#password')?.removeAttribute('required');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUsePagedSearchChange() {
|
function onUsePagedSearchChange() {
|
||||||
const searchPageSizeElements = document.querySelectorAll('.search-page-size');
|
const searchPageSizeElements = document.querySelectorAll<HTMLDivElement>('.search-page-size');
|
||||||
if (document.querySelector('#use_paged_search').checked) {
|
if (document.querySelector<HTMLInputElement>('#use_paged_search').checked) {
|
||||||
showElem('.search-page-size');
|
showElem('.search-page-size');
|
||||||
for (const el of searchPageSizeElements) {
|
for (const el of searchPageSizeElements) {
|
||||||
el.querySelector('input')?.setAttribute('required', 'required');
|
el.querySelector('input')?.setAttribute('required', 'required');
|
||||||
|
@ -61,20 +61,20 @@ export function initAdminCommon() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOAuth2Change(applyDefaultValues) {
|
function onOAuth2Change(applyDefaultValues: boolean) {
|
||||||
hideElem('.open_id_connect_auto_discovery_url, .oauth2_use_custom_url');
|
hideElem('.open_id_connect_auto_discovery_url, .oauth2_use_custom_url');
|
||||||
for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input[required]')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.open_id_connect_auto_discovery_url input[required]')) {
|
||||||
input.removeAttribute('required');
|
input.removeAttribute('required');
|
||||||
}
|
}
|
||||||
|
|
||||||
const provider = document.querySelector('#oauth2_provider').value;
|
const provider = document.querySelector<HTMLInputElement>('#oauth2_provider').value;
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case 'openidConnect':
|
case 'openidConnect':
|
||||||
document.querySelector('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required');
|
document.querySelector<HTMLInputElement>('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required');
|
||||||
showElem('.open_id_connect_auto_discovery_url');
|
showElem('.open_id_connect_auto_discovery_url');
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`);
|
const elProviderCustomUrlSettings = document.querySelector<HTMLInputElement>(`#${provider}_customURLSettings`);
|
||||||
if (!elProviderCustomUrlSettings) break; // some providers do not have custom URL settings
|
if (!elProviderCustomUrlSettings) break; // some providers do not have custom URL settings
|
||||||
const couldChangeCustomURLs = elProviderCustomUrlSettings.getAttribute('data-available') === 'true';
|
const couldChangeCustomURLs = elProviderCustomUrlSettings.getAttribute('data-available') === 'true';
|
||||||
const mustProvideCustomURLs = elProviderCustomUrlSettings.getAttribute('data-required') === 'true';
|
const mustProvideCustomURLs = elProviderCustomUrlSettings.getAttribute('data-required') === 'true';
|
||||||
|
@ -82,7 +82,7 @@ export function initAdminCommon() {
|
||||||
showElem('.oauth2_use_custom_url'); // show the checkbox
|
showElem('.oauth2_use_custom_url'); // show the checkbox
|
||||||
}
|
}
|
||||||
if (mustProvideCustomURLs) {
|
if (mustProvideCustomURLs) {
|
||||||
document.querySelector('#oauth2_use_custom_url').checked = true; // make the checkbox checked
|
document.querySelector<HTMLInputElement>('#oauth2_use_custom_url').checked = true; // make the checkbox checked
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -91,17 +91,17 @@ export function initAdminCommon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOAuth2UseCustomURLChange(applyDefaultValues) {
|
function onOAuth2UseCustomURLChange(applyDefaultValues) {
|
||||||
const provider = document.querySelector('#oauth2_provider').value;
|
const provider = document.querySelector<HTMLInputElement>('#oauth2_provider').value;
|
||||||
hideElem('.oauth2_use_custom_url_field');
|
hideElem('.oauth2_use_custom_url_field');
|
||||||
for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.oauth2_use_custom_url_field input[required]')) {
|
||||||
input.removeAttribute('required');
|
input.removeAttribute('required');
|
||||||
}
|
}
|
||||||
|
|
||||||
const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`);
|
const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`);
|
||||||
if (elProviderCustomUrlSettings && document.querySelector('#oauth2_use_custom_url').checked) {
|
if (elProviderCustomUrlSettings && document.querySelector<HTMLInputElement>('#oauth2_use_custom_url').checked) {
|
||||||
for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) {
|
for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) {
|
||||||
if (applyDefaultValues) {
|
if (applyDefaultValues) {
|
||||||
document.querySelector(`#oauth2_${custom}`).value = document.querySelector(`#${provider}_${custom}`).value;
|
document.querySelector<HTMLInputElement>(`#oauth2_${custom}`).value = document.querySelector<HTMLInputElement>(`#${provider}_${custom}`).value;
|
||||||
}
|
}
|
||||||
const customInput = document.querySelector(`#${provider}_${custom}`);
|
const customInput = document.querySelector(`#${provider}_${custom}`);
|
||||||
if (customInput && customInput.getAttribute('data-available') === 'true') {
|
if (customInput && customInput.getAttribute('data-available') === 'true') {
|
||||||
|
@ -115,25 +115,26 @@ export function initAdminCommon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEnableLdapGroupsChange() {
|
function onEnableLdapGroupsChange() {
|
||||||
toggleElem(document.querySelector('#ldap-group-options'), $('.js-ldap-group-toggle')[0].checked);
|
const checked = document.querySelector<HTMLInputElement>('.js-ldap-group-toggle')?.checked;
|
||||||
|
toggleElem(document.querySelector('#ldap-group-options'), checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// New authentication
|
// New authentication
|
||||||
if (document.querySelector('.admin.new.authentication')) {
|
if (document.querySelector<HTMLDivElement>('.admin.new.authentication')) {
|
||||||
document.querySelector('#auth_type')?.addEventListener('change', function () {
|
document.querySelector<HTMLInputElement>('#auth_type')?.addEventListener('change', function () {
|
||||||
hideElem('.ldap, .dldap, .smtp, .pam, .oauth2, .has-tls, .search-page-size, .sspi');
|
hideElem('.ldap, .dldap, .smtp, .pam, .oauth2, .has-tls, .search-page-size, .sspi');
|
||||||
|
|
||||||
for (const input of document.querySelectorAll('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required], .sspi input[required]')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required], .sspi input[required]')) {
|
||||||
input.removeAttribute('required');
|
input.removeAttribute('required');
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector('.binddnrequired')?.classList.remove('required');
|
document.querySelector<HTMLDivElement>('.binddnrequired')?.classList.remove('required');
|
||||||
|
|
||||||
const authType = this.value;
|
const authType = this.value;
|
||||||
switch (authType) {
|
switch (authType) {
|
||||||
case '2': // LDAP
|
case '2': // LDAP
|
||||||
showElem('.ldap');
|
showElem('.ldap');
|
||||||
for (const input of document.querySelectorAll('.binddnrequired input, .ldap div.required:not(.dldap) input')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.binddnrequired input, .ldap div.required:not(.dldap) input')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
document.querySelector('.binddnrequired')?.classList.add('required');
|
document.querySelector('.binddnrequired')?.classList.add('required');
|
||||||
|
@ -141,32 +142,32 @@ export function initAdminCommon() {
|
||||||
case '3': // SMTP
|
case '3': // SMTP
|
||||||
showElem('.smtp');
|
showElem('.smtp');
|
||||||
showElem('.has-tls');
|
showElem('.has-tls');
|
||||||
for (const input of document.querySelectorAll('.smtp div.required input, .has-tls')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.smtp div.required input, .has-tls')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '4': // PAM
|
case '4': // PAM
|
||||||
showElem('.pam');
|
showElem('.pam');
|
||||||
for (const input of document.querySelectorAll('.pam input')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.pam input')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '5': // LDAP
|
case '5': // LDAP
|
||||||
showElem('.dldap');
|
showElem('.dldap');
|
||||||
for (const input of document.querySelectorAll('.dldap div.required:not(.ldap) input')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.dldap div.required:not(.ldap) input')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '6': // OAuth2
|
case '6': // OAuth2
|
||||||
showElem('.oauth2');
|
showElem('.oauth2');
|
||||||
for (const input of document.querySelectorAll('.oauth2 div.required:not(.oauth2_use_custom_url,.oauth2_use_custom_url_field,.open_id_connect_auto_discovery_url) input')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.oauth2 div.required:not(.oauth2_use_custom_url,.oauth2_use_custom_url_field,.open_id_connect_auto_discovery_url) input')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
onOAuth2Change(true);
|
onOAuth2Change(true);
|
||||||
break;
|
break;
|
||||||
case '7': // SSPI
|
case '7': // SSPI
|
||||||
showElem('.sspi');
|
showElem('.sspi');
|
||||||
for (const input of document.querySelectorAll('.sspi div.required input')) {
|
for (const input of document.querySelectorAll<HTMLInputElement>('.sspi div.required input')) {
|
||||||
input.setAttribute('required', 'required');
|
input.setAttribute('required', 'required');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -180,39 +181,39 @@ export function initAdminCommon() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('#auth_type').trigger('change');
|
$('#auth_type').trigger('change');
|
||||||
document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange);
|
document.querySelector<HTMLInputElement>('#security_protocol')?.addEventListener('change', onSecurityProtocolChange);
|
||||||
document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
|
document.querySelector<HTMLInputElement>('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
|
||||||
document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
|
document.querySelector<HTMLInputElement>('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
|
||||||
document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true));
|
document.querySelector<HTMLInputElement>('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true));
|
||||||
$('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
|
$('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
|
||||||
}
|
}
|
||||||
// Edit authentication
|
// Edit authentication
|
||||||
if (document.querySelector('.admin.edit.authentication')) {
|
if (document.querySelector<HTMLDivElement>('.admin.edit.authentication')) {
|
||||||
const authType = document.querySelector('#auth_type')?.value;
|
const authType = document.querySelector<HTMLInputElement>('#auth_type')?.value;
|
||||||
if (authType === '2' || authType === '5') {
|
if (authType === '2' || authType === '5') {
|
||||||
document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange);
|
document.querySelector<HTMLInputElement>('#security_protocol')?.addEventListener('change', onSecurityProtocolChange);
|
||||||
$('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
|
$('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange);
|
||||||
onEnableLdapGroupsChange();
|
onEnableLdapGroupsChange();
|
||||||
if (authType === '2') {
|
if (authType === '2') {
|
||||||
document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
|
document.querySelector<HTMLInputElement>('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange);
|
||||||
}
|
}
|
||||||
} else if (authType === '6') {
|
} else if (authType === '6') {
|
||||||
document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
|
document.querySelector<HTMLInputElement>('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true));
|
||||||
document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false));
|
document.querySelector<HTMLInputElement>('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false));
|
||||||
onOAuth2Change(false);
|
onOAuth2Change(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.querySelector('.admin.authentication')) {
|
if (document.querySelector<HTMLDivElement>('.admin.authentication')) {
|
||||||
$('#auth_name').on('input', function () {
|
$('#auth_name').on('input', function () {
|
||||||
// appSubUrl is either empty or is a path that starts with `/` and doesn't have a trailing slash.
|
// appSubUrl is either empty or is a path that starts with `/` and doesn't have a trailing slash.
|
||||||
document.querySelector('#oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent(this.value)}/callback`;
|
document.querySelector('#oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent((this as HTMLInputElement).value)}/callback`;
|
||||||
}).trigger('input');
|
}).trigger('input');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notice
|
// Notice
|
||||||
if (document.querySelector('.admin.notice')) {
|
if (document.querySelector<HTMLDivElement>('.admin.notice')) {
|
||||||
const detailModal = document.querySelector('#detail-modal');
|
const detailModal = document.querySelector<HTMLDivElement>('#detail-modal');
|
||||||
|
|
||||||
// Attach view detail modals
|
// Attach view detail modals
|
||||||
$('.view-detail').on('click', function () {
|
$('.view-detail').on('click', function () {
|
||||||
|
@ -223,7 +224,7 @@ export function initAdminCommon() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select actions
|
// Select actions
|
||||||
const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input');
|
const checkboxes = document.querySelectorAll<HTMLInputElement>('.select.table .ui.checkbox input');
|
||||||
|
|
||||||
$('.select.action').on('click', function () {
|
$('.select.action').on('click', function () {
|
||||||
switch ($(this).data('action')) {
|
switch ($(this).data('action')) {
|
||||||
|
@ -244,7 +245,7 @@ export function initAdminCommon() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.querySelector('#delete-selection')?.addEventListener('click', async function (e) {
|
document.querySelector<HTMLButtonElement>('#delete-selection')?.addEventListener('click', async function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.classList.add('is-loading', 'disabled');
|
this.classList.add('is-loading', 'disabled');
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
|
|
|
@ -3,17 +3,17 @@ import {POST} from '../../modules/fetch.ts';
|
||||||
|
|
||||||
const {appSubUrl} = window.config;
|
const {appSubUrl} = window.config;
|
||||||
|
|
||||||
export function initAdminConfigs() {
|
export function initAdminConfigs(): void {
|
||||||
const elAdminConfig = document.querySelector('.page-content.admin.config');
|
const elAdminConfig = document.querySelector<HTMLDivElement>('.page-content.admin.config');
|
||||||
if (!elAdminConfig) return;
|
if (!elAdminConfig) return;
|
||||||
|
|
||||||
for (const el of elAdminConfig.querySelectorAll('input[type="checkbox"][data-config-dyn-key]')) {
|
for (const el of elAdminConfig.querySelectorAll<HTMLInputElement>('input[type="checkbox"][data-config-dyn-key]')) {
|
||||||
el.addEventListener('change', async () => {
|
el.addEventListener('change', async () => {
|
||||||
try {
|
try {
|
||||||
const resp = await POST(`${appSubUrl}/-/admin/config`, {
|
const resp = await POST(`${appSubUrl}/-/admin/config`, {
|
||||||
data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key'), value: el.checked}),
|
data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key'), value: String(el.checked)}),
|
||||||
});
|
});
|
||||||
const json = await resp.json();
|
const json: Record<string, any> = await resp.json();
|
||||||
if (json.errorMessage) throw new Error(json.errorMessage);
|
if (json.errorMessage) throw new Error(json.errorMessage);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
showTemporaryTooltip(el, ex.toString());
|
showTemporaryTooltip(el, ex.toString());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
export function initAdminEmails() {
|
export function initAdminEmails(): void {
|
||||||
function linkEmailAction(e) {
|
$('.link-email-action').on('click', (e) => {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
$('#form-uid').val($this.data('uid'));
|
$('#form-uid').val($this.data('uid'));
|
||||||
$('#form-email').val($this.data('email'));
|
$('#form-email').val($this.data('email'));
|
||||||
|
@ -9,6 +9,5 @@ export function initAdminEmails() {
|
||||||
$('#form-activate').val($this.data('activate'));
|
$('#form-activate').val($this.data('activate'));
|
||||||
$('#change-email-modal').modal('show');
|
$('#change-email-modal').modal('show');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
});
|
||||||
$('.link-email-action').on('click', linkEmailAction);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ export async function initAdminSelfCheck() {
|
||||||
const elCheckByFrontend = document.querySelector('#self-check-by-frontend');
|
const elCheckByFrontend = document.querySelector('#self-check-by-frontend');
|
||||||
if (!elCheckByFrontend) return;
|
if (!elCheckByFrontend) return;
|
||||||
|
|
||||||
const elContent = document.querySelector('.page-content.admin .admin-setting-content');
|
const elContent = document.querySelector<HTMLDivElement>('.page-content.admin .admin-setting-content');
|
||||||
|
|
||||||
// send frontend self-check request
|
// send frontend self-check request
|
||||||
const resp = await POST(`${appSubUrl}/-/admin/self_check`, {
|
const resp = await POST(`${appSubUrl}/-/admin/self_check`, {
|
||||||
data: new URLSearchParams({
|
data: new URLSearchParams({
|
||||||
location_origin: window.location.origin,
|
location_origin: window.location.origin,
|
||||||
now: Date.now(), // TODO: check time difference between server and client
|
now: String(Date.now()), // TODO: check time difference between server and client
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const json = await resp.json();
|
const json: Record<string, any> = await resp.json();
|
||||||
toggleElem(elCheckByFrontend, Boolean(json.problems?.length));
|
toggleElem(elCheckByFrontend, Boolean(json.problems?.length));
|
||||||
for (const problem of json.problems ?? []) {
|
for (const problem of json.problems ?? []) {
|
||||||
const elProblem = document.createElement('div');
|
const elProblem = document.createElement('div');
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
export function initAdminUserListSearchForm() {
|
export function initAdminUserListSearchForm(): void {
|
||||||
const searchForm = window.config.pageData.adminUserListSearchForm;
|
const searchForm = window.config.pageData.adminUserListSearchForm;
|
||||||
if (!searchForm) return;
|
if (!searchForm) return;
|
||||||
|
|
||||||
const form = document.querySelector('#user-list-search-form');
|
const form = document.querySelector<HTMLFormElement>('#user-list-search-form');
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
for (const button of form.querySelectorAll(`button[name=sort][value="${searchForm.SortType}"]`)) {
|
for (const button of form.querySelectorAll(`button[name=sort][value="${searchForm.SortType}"]`)) {
|
||||||
|
@ -12,23 +12,23 @@ export function initAdminUserListSearchForm() {
|
||||||
if (searchForm.StatusFilterMap) {
|
if (searchForm.StatusFilterMap) {
|
||||||
for (const [k, v] of Object.entries(searchForm.StatusFilterMap)) {
|
for (const [k, v] of Object.entries(searchForm.StatusFilterMap)) {
|
||||||
if (!v) continue;
|
if (!v) continue;
|
||||||
for (const input of form.querySelectorAll(`input[name="status_filter[${k}]"][value="${v}"]`)) {
|
for (const input of form.querySelectorAll<HTMLInputElement>(`input[name="status_filter[${k}]"][value="${v}"]`)) {
|
||||||
input.checked = true;
|
input.checked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const radio of form.querySelectorAll('input[type=radio]')) {
|
for (const radio of form.querySelectorAll<HTMLInputElement>('input[type=radio]')) {
|
||||||
radio.addEventListener('click', () => {
|
radio.addEventListener('click', () => {
|
||||||
form.submit();
|
form.submit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetButtons = form.querySelectorAll('.j-reset-status-filter');
|
const resetButtons = form.querySelectorAll<HTMLAnchorElement>('.j-reset-status-filter');
|
||||||
for (const button of resetButtons) {
|
for (const button of resetButtons) {
|
||||||
button.addEventListener('click', (e) => {
|
button.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
for (const input of form.querySelectorAll('input[type=radio]')) {
|
for (const input of form.querySelectorAll<HTMLInputElement>('input[type=radio]')) {
|
||||||
if (input.name.startsWith('status_filter[')) {
|
if (input.name.startsWith('status_filter[')) {
|
||||||
input.checked = false;
|
input.checked = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import {svg} from '../svg.ts';
|
import {svg} from '../svg.ts';
|
||||||
|
|
||||||
const addPrefix = (str) => `user-content-${str}`;
|
const addPrefix = (str: string): string => `user-content-${str}`;
|
||||||
const removePrefix = (str) => str.replace(/^user-content-/, '');
|
const removePrefix = (str: string): string => str.replace(/^user-content-/, '');
|
||||||
const hasPrefix = (str) => str.startsWith('user-content-');
|
const hasPrefix = (str: string): boolean => str.startsWith('user-content-');
|
||||||
|
|
||||||
// scroll to anchor while respecting the `user-content` prefix that exists on the target
|
// scroll to anchor while respecting the `user-content` prefix that exists on the target
|
||||||
function scrollToAnchor(encodedId) {
|
function scrollToAnchor(encodedId: string): void {
|
||||||
if (!encodedId) return;
|
if (!encodedId) return;
|
||||||
const id = decodeURIComponent(encodedId);
|
const id = decodeURIComponent(encodedId);
|
||||||
const prefixedId = addPrefix(id);
|
const prefixedId = addPrefix(id);
|
||||||
|
@ -24,7 +24,7 @@ function scrollToAnchor(encodedId) {
|
||||||
el?.scrollIntoView();
|
el?.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initMarkupAnchors() {
|
export function initMarkupAnchors(): void {
|
||||||
const markupEls = document.querySelectorAll('.markup');
|
const markupEls = document.querySelectorAll('.markup');
|
||||||
if (!markupEls.length) return;
|
if (!markupEls.length) return;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ export function initMarkupAnchors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove `user-content-` prefix from links so they don't show in url bar when clicked
|
// remove `user-content-` prefix from links so they don't show in url bar when clicked
|
||||||
for (const a of markupEl.querySelectorAll('a[href^="#"]')) {
|
for (const a of markupEl.querySelectorAll<HTMLAnchorElement>('a[href^="#"]')) {
|
||||||
const href = a.getAttribute('href');
|
const href = a.getAttribute('href');
|
||||||
if (!href.startsWith('#user-content-')) continue;
|
if (!href.startsWith('#user-content-')) continue;
|
||||||
a.setAttribute('href', `#${removePrefix(href.substring(1))}`);
|
a.setAttribute('href', `#${removePrefix(href.substring(1))}`);
|
||||||
|
@ -47,15 +47,15 @@ export function initMarkupAnchors() {
|
||||||
|
|
||||||
// add `user-content-` prefix to user-generated `a[name]` link targets
|
// add `user-content-` prefix to user-generated `a[name]` link targets
|
||||||
// TODO: this prefix should be added in backend instead
|
// TODO: this prefix should be added in backend instead
|
||||||
for (const a of markupEl.querySelectorAll('a[name]')) {
|
for (const a of markupEl.querySelectorAll<HTMLAnchorElement>('a[name]')) {
|
||||||
const name = a.getAttribute('name');
|
const name = a.getAttribute('name');
|
||||||
if (!name) continue;
|
if (!name) continue;
|
||||||
a.setAttribute('name', addPrefix(a.name));
|
a.setAttribute('name', addPrefix(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const a of markupEl.querySelectorAll('a[href^="#"]')) {
|
for (const a of markupEl.querySelectorAll<HTMLAnchorElement>('a[href^="#"]')) {
|
||||||
a.addEventListener('click', (e) => {
|
a.addEventListener('click', (e) => {
|
||||||
scrollToAnchor(e.currentTarget.getAttribute('href')?.substring(1));
|
scrollToAnchor((e.currentTarget as HTMLAnchorElement).getAttribute('href')?.substring(1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {svg} from '../svg.ts';
|
import {svg} from '../svg.ts';
|
||||||
|
|
||||||
export function makeCodeCopyButton() {
|
export function makeCodeCopyButton(): HTMLButtonElement {
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
button.classList.add('code-copy', 'ui', 'button');
|
button.classList.add('code-copy', 'ui', 'button');
|
||||||
button.innerHTML = svg('octicon-copy');
|
button.innerHTML = svg('octicon-copy');
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderCodeCopy() {
|
export function renderCodeCopy(): void {
|
||||||
const els = document.querySelectorAll('.markup .code-block code');
|
const els = document.querySelectorAll('.markup .code-block code');
|
||||||
if (!els.length) return;
|
if (!els.length) return;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
export function displayError(el, err) {
|
export function displayError(el: Element, err: Error): void {
|
||||||
el.classList.remove('is-loading');
|
el.classList.remove('is-loading');
|
||||||
const errorNode = document.createElement('pre');
|
const errorNode = document.createElement('pre');
|
||||||
errorNode.setAttribute('class', 'ui message error markup-block-error');
|
errorNode.setAttribute('class', 'ui message error markup-block-error');
|
||||||
errorNode.textContent = err.str || err.message || String(err);
|
errorNode.textContent = err.message || String(err);
|
||||||
el.before(errorNode);
|
el.before(errorNode);
|
||||||
el.setAttribute('data-render-done', 'true');
|
el.setAttribute('data-render-done', 'true');
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {renderAsciicast} from './asciicast.ts';
|
||||||
import {initMarkupTasklist} from './tasklist.ts';
|
import {initMarkupTasklist} from './tasklist.ts';
|
||||||
|
|
||||||
// code that runs for all markup content
|
// code that runs for all markup content
|
||||||
export function initMarkupContent() {
|
export function initMarkupContent(): void {
|
||||||
renderMermaid();
|
renderMermaid();
|
||||||
renderMath();
|
renderMath();
|
||||||
renderCodeCopy();
|
renderCodeCopy();
|
||||||
|
@ -13,6 +13,6 @@ export function initMarkupContent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// code that only runs for comments
|
// code that only runs for comments
|
||||||
export function initCommentContent() {
|
export function initCommentContent(): void {
|
||||||
initMarkupTasklist();
|
initMarkupTasklist();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,20 @@ type ProcessorContext = {
|
||||||
|
|
||||||
function prepareProcessors(ctx:ProcessorContext): Processors {
|
function prepareProcessors(ctx:ProcessorContext): Processors {
|
||||||
const processors = {
|
const processors = {
|
||||||
H1(el) {
|
H1(el: HTMLHeadingElement) {
|
||||||
const level = parseInt(el.tagName.slice(1));
|
const level = parseInt(el.tagName.slice(1));
|
||||||
el.textContent = `${'#'.repeat(level)} ${el.textContent.trim()}`;
|
el.textContent = `${'#'.repeat(level)} ${el.textContent.trim()}`;
|
||||||
},
|
},
|
||||||
STRONG(el) {
|
STRONG(el: HTMLElement) {
|
||||||
return `**${el.textContent}**`;
|
return `**${el.textContent}**`;
|
||||||
},
|
},
|
||||||
EM(el) {
|
EM(el: HTMLElement) {
|
||||||
return `_${el.textContent}_`;
|
return `_${el.textContent}_`;
|
||||||
},
|
},
|
||||||
DEL(el) {
|
DEL(el: HTMLElement) {
|
||||||
return `~~${el.textContent}~~`;
|
return `~~${el.textContent}~~`;
|
||||||
},
|
},
|
||||||
|
A(el: HTMLAnchorElement) {
|
||||||
A(el) {
|
|
||||||
const text = el.textContent || 'link';
|
const text = el.textContent || 'link';
|
||||||
const href = el.getAttribute('href');
|
const href = el.getAttribute('href');
|
||||||
if (/^https?:/.test(text) && text === href) {
|
if (/^https?:/.test(text) && text === href) {
|
||||||
|
@ -34,7 +33,7 @@ function prepareProcessors(ctx:ProcessorContext): Processors {
|
||||||
}
|
}
|
||||||
return href ? `[${text}](${href})` : text;
|
return href ? `[${text}](${href})` : text;
|
||||||
},
|
},
|
||||||
IMG(el) {
|
IMG(el: HTMLImageElement) {
|
||||||
const alt = el.getAttribute('alt') || 'image';
|
const alt = el.getAttribute('alt') || 'image';
|
||||||
const src = el.getAttribute('src');
|
const src = el.getAttribute('src');
|
||||||
const widthAttr = el.hasAttribute('width') ? ` width="${htmlEscape(el.getAttribute('width') || '')}"` : '';
|
const widthAttr = el.hasAttribute('width') ? ` width="${htmlEscape(el.getAttribute('width') || '')}"` : '';
|
||||||
|
@ -44,32 +43,29 @@ function prepareProcessors(ctx:ProcessorContext): Processors {
|
||||||
}
|
}
|
||||||
return `![${alt}](${src})`;
|
return `![${alt}](${src})`;
|
||||||
},
|
},
|
||||||
|
P(el: HTMLParagraphElement) {
|
||||||
P(el) {
|
|
||||||
el.textContent = `${el.textContent}\n`;
|
el.textContent = `${el.textContent}\n`;
|
||||||
},
|
},
|
||||||
BLOCKQUOTE(el) {
|
BLOCKQUOTE(el: HTMLElement) {
|
||||||
el.textContent = `${el.textContent.replace(/^/mg, '> ')}\n`;
|
el.textContent = `${el.textContent.replace(/^/mg, '> ')}\n`;
|
||||||
},
|
},
|
||||||
|
OL(el: HTMLElement) {
|
||||||
OL(el) {
|
|
||||||
const preNewLine = ctx.listNestingLevel ? '\n' : '';
|
const preNewLine = ctx.listNestingLevel ? '\n' : '';
|
||||||
el.textContent = `${preNewLine}${el.textContent}\n`;
|
el.textContent = `${preNewLine}${el.textContent}\n`;
|
||||||
},
|
},
|
||||||
LI(el) {
|
LI(el: HTMLElement) {
|
||||||
const parent = el.parentNode;
|
const parent = el.parentNode;
|
||||||
const bullet = parent.tagName === 'OL' ? `1. ` : '* ';
|
const bullet = (parent as HTMLElement).tagName === 'OL' ? `1. ` : '* ';
|
||||||
const nestingIdentLevel = Math.max(0, ctx.listNestingLevel - 1);
|
const nestingIdentLevel = Math.max(0, ctx.listNestingLevel - 1);
|
||||||
el.textContent = `${' '.repeat(nestingIdentLevel * 4)}${bullet}${el.textContent}${ctx.elementIsLast ? '' : '\n'}`;
|
el.textContent = `${' '.repeat(nestingIdentLevel * 4)}${bullet}${el.textContent}${ctx.elementIsLast ? '' : '\n'}`;
|
||||||
return el;
|
return el;
|
||||||
},
|
},
|
||||||
INPUT(el) {
|
INPUT(el: HTMLInputElement) {
|
||||||
return el.checked ? '[x] ' : '[ ] ';
|
return el.checked ? '[x] ' : '[ ] ';
|
||||||
},
|
},
|
||||||
|
CODE(el: HTMLElement) {
|
||||||
CODE(el) {
|
|
||||||
const text = el.textContent;
|
const text = el.textContent;
|
||||||
if (el.parentNode && el.parentNode.tagName === 'PRE') {
|
if (el.parentNode && (el.parentNode as HTMLElement).tagName === 'PRE') {
|
||||||
el.textContent = `\`\`\`\n${text}\n\`\`\`\n`;
|
el.textContent = `\`\`\`\n${text}\n\`\`\`\n`;
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +82,7 @@ function prepareProcessors(ctx:ProcessorContext): Processors {
|
||||||
return processors;
|
return processors;
|
||||||
}
|
}
|
||||||
|
|
||||||
function processElement(ctx :ProcessorContext, processors: Processors, el: HTMLElement) {
|
function processElement(ctx :ProcessorContext, processors: Processors, el: HTMLElement): string | void {
|
||||||
if (el.hasAttribute('data-markdown-generated-content')) return el.textContent;
|
if (el.hasAttribute('data-markdown-generated-content')) return el.textContent;
|
||||||
if (el.tagName === 'A' && el.children.length === 1 && el.children[0].tagName === 'IMG') {
|
if (el.tagName === 'A' && el.children.length === 1 && el.children[0].tagName === 'IMG') {
|
||||||
return processElement(ctx, processors, el.children[0] as HTMLElement);
|
return processElement(ctx, processors, el.children[0] as HTMLElement);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import {displayError} from './common.ts';
|
import {displayError} from './common.ts';
|
||||||
|
|
||||||
function targetElement(el) {
|
function targetElement(el: Element) {
|
||||||
// The target element is either the current element if it has the
|
// The target element is either the current element if it has the
|
||||||
// `is-loading` class or the pre that contains it
|
// `is-loading` class or the pre that contains it
|
||||||
return el.classList.contains('is-loading') ? el : el.closest('pre');
|
return el.classList.contains('is-loading') ? el : el.closest('pre');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renderMath() {
|
export async function renderMath(): void {
|
||||||
const els = document.querySelectorAll('.markup code.language-math');
|
const els = document.querySelectorAll('.markup code.language-math');
|
||||||
if (!els.length) return;
|
if (!els.length) return;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ body {margin: 0; padding: 0; overflow: hidden}
|
||||||
#mermaid {display: block; margin: 0 auto}
|
#mermaid {display: block; margin: 0 auto}
|
||||||
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {margin: 0}`;
|
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {margin: 0}`;
|
||||||
|
|
||||||
export async function renderMermaid() {
|
export async function renderMermaid(): Promise<void> {
|
||||||
const els = document.querySelectorAll('.markup code.language-mermaid');
|
const els = document.querySelectorAll('.markup code.language-mermaid');
|
||||||
if (!els.length) return;
|
if (!els.length) return;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {POST} from '../modules/fetch.ts';
|
import {POST} from '../modules/fetch.ts';
|
||||||
import {showErrorToast} from '../modules/toast.ts';
|
import {showErrorToast} from '../modules/toast.ts';
|
||||||
|
|
||||||
const preventListener = (e) => e.preventDefault();
|
const preventListener = (e: Event) => e.preventDefault();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches `input` handlers to markdown rendered tasklist checkboxes in comments.
|
* Attaches `input` handlers to markdown rendered tasklist checkboxes in comments.
|
||||||
|
@ -10,10 +10,10 @@ const preventListener = (e) => e.preventDefault();
|
||||||
* is set accordingly and sent to the server. On success it updates the raw-content on
|
* is set accordingly and sent to the server. On success it updates the raw-content on
|
||||||
* error it resets the checkbox to its original value.
|
* error it resets the checkbox to its original value.
|
||||||
*/
|
*/
|
||||||
export function initMarkupTasklist() {
|
export function initMarkupTasklist(): void {
|
||||||
for (const el of document.querySelectorAll(`.markup[data-can-edit=true]`) || []) {
|
for (const el of document.querySelectorAll(`.markup[data-can-edit=true]`) || []) {
|
||||||
const container = el.parentNode;
|
const container = el.parentNode;
|
||||||
const checkboxes = el.querySelectorAll(`.task-list-item input[type=checkbox]`);
|
const checkboxes = el.querySelectorAll<HTMLInputElement>(`.task-list-item input[type=checkbox]`);
|
||||||
|
|
||||||
for (const checkbox of checkboxes) {
|
for (const checkbox of checkboxes) {
|
||||||
if (checkbox.hasAttribute('data-editable')) {
|
if (checkbox.hasAttribute('data-editable')) {
|
||||||
|
@ -52,7 +52,7 @@ export function initMarkupTasklist() {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const editContentZone = container.querySelector('.edit-content-zone');
|
const editContentZone = container.querySelector<HTMLDivElement>('.edit-content-zone');
|
||||||
const updateUrl = editContentZone.getAttribute('data-update-url');
|
const updateUrl = editContentZone.getAttribute('data-update-url');
|
||||||
const context = editContentZone.getAttribute('data-context');
|
const context = editContentZone.getAttribute('data-context');
|
||||||
const contentVersion = editContentZone.getAttribute('data-content-version');
|
const contentVersion = editContentZone.getAttribute('data-content-version');
|
||||||
|
|
|
@ -153,7 +153,7 @@ export type SvgName = keyof typeof svgs;
|
||||||
// most of the SVG icons in assets couldn't be used directly.
|
// most of the SVG icons in assets couldn't be used directly.
|
||||||
|
|
||||||
// retrieve an HTML string for given SVG icon name, size and additional classes
|
// retrieve an HTML string for given SVG icon name, size and additional classes
|
||||||
export function svg(name: SvgName, size = 16, classNames: string|string[]): string {
|
export function svg(name: SvgName, size = 16, classNames?: string|string[]): string {
|
||||||
const className = Array.isArray(classNames) ? classNames.join(' ') : classNames;
|
const className = Array.isArray(classNames) ? classNames.join(' ') : classNames;
|
||||||
if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`);
|
if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`);
|
||||||
if (size === 16 && !className) return svgs[name];
|
if (size === 16 && !className) return svgs[name];
|
||||||
|
|
Loading…
Reference in New Issue