Skip to content

Commit c1062b9

Browse files
committed
refactor: migrated from JavaScript to TypeScript (Part 3)
WIP, not done yet, build is currently broken
1 parent 02cae85 commit c1062b9

File tree

8 files changed

+167
-148
lines changed

8 files changed

+167
-148
lines changed

phpmyfaq/admin/assets/src/user/autocomplete.js renamed to phpmyfaq/admin/assets/src/user/autocomplete.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,44 @@
1313
* @since 2022-03-23
1414
*/
1515

16-
import autocomplete from 'autocompleter';
16+
import autocomplete, { AutocompleteItem } from 'autocompleter';
1717
import { updateUser } from './users';
1818
import { fetchUsers } from '../api';
1919
import { addElement } from '../../../../assets/src/utils';
2020

21+
interface User {
22+
label: string;
23+
value: string;
24+
}
25+
26+
type UserSuggestion = User & AutocompleteItem;
27+
2128
document.addEventListener('DOMContentLoaded', () => {
22-
const autoComplete = document.getElementById('pmf-user-list-autocomplete');
29+
const autoComplete = document.getElementById('pmf-user-list-autocomplete') as HTMLInputElement;
2330

2431
if (autoComplete) {
25-
autocomplete({
32+
autocomplete<UserSuggestion>({
2633
input: autoComplete,
2734
minLength: 1,
28-
onSelect: async (item, input) => {
35+
onSelect: async (item: UserSuggestion, input: HTMLInputElement | HTMLTextAreaElement) => {
2936
input.value = item.label;
3037
await updateUser(item.value);
3138
},
32-
fetch: async (text, callback) => {
39+
fetch: async (text: string, callback: (items: UserSuggestion[]) => void) => {
3340
const match = text.toLowerCase();
3441
const users = await fetchUsers(match);
3542
callback(
36-
users.filter((n) => {
43+
users?.filter((n: UserSuggestion) => {
3744
return n.label.toLowerCase().indexOf(match) !== -1;
3845
})
3946
);
4047
},
41-
render: (item, value) => {
42-
const regex = new RegExp(value, 'gi');
48+
render: (item: UserSuggestion, currentValue: string): HTMLDivElement => {
49+
const regex = new RegExp(currentValue, 'gi');
4350
return addElement('div', {
4451
classList: 'pmf-user-list-result border',
45-
innerHTML: item.label.replace(regex, function (match) {
46-
return `<strong>${match}</strong>`;
47-
}),
48-
});
52+
innerHTML: item.label.replace(regex, (match) => `<strong>${match}</strong>`),
53+
}) as HTMLDivElement;
4954
},
5055
emptyMsg: 'No users found',
5156
});

phpmyfaq/admin/assets/src/user/user-list.js renamed to phpmyfaq/admin/assets/src/user/user-list.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Functions for handling user management
33
*
4-
* @todo move fetch() functionality to api.js
4+
* @todo move fetch() functionality to api functions
55
*
66
* This Source Code Form is subject to the terms of the Mozilla Public License,
77
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -15,12 +15,11 @@
1515
* @since 2022-03-23
1616
*/
1717

18-
import { addElement } from '../../../../assets/src/utils';
19-
import { pushErrorNotification, pushNotification } from '../utils';
18+
import { addElement, pushErrorNotification, pushNotification } from '../../../../assets/src/utils';
2019
import { deleteUser } from '../api';
2120
import { Modal } from 'bootstrap';
2221

23-
const activateUser = async (userId, csrfToken) => {
22+
const activateUser = async (userId: string, csrfToken: string): Promise<void> => {
2423
try {
2524
const response = await fetch('./api/user/activate', {
2625
method: 'POST',
@@ -36,24 +35,24 @@ const activateUser = async (userId, csrfToken) => {
3635

3736
if (response.status === 200) {
3837
await response.json();
39-
const icon = document.querySelector(`.icon_user_id_${userId}`);
38+
const icon = document.querySelector(`.icon_user_id_${userId}`) as HTMLElement;
4039
icon.classList.remove('bi-ban');
4140
icon.classList.add('bi-check-circle-o');
42-
const button = document.getElementById(`btn_activate_user_id_${userId}`);
41+
const button = document.getElementById(`btn_activate_user_id_${userId}`) as HTMLElement;
4342
button.remove();
4443
} else {
4544
throw new Error('Network response was not ok.');
4645
}
4746
} catch (error) {
48-
const message = document.getElementById('pmf-user-message');
47+
const message = document.getElementById('pmf-user-message') as HTMLElement;
4948
message.insertAdjacentElement(
5049
'afterend',
51-
addElement('div', { classList: 'alert alert-danger', innerText: error.message })
50+
addElement('div', { classList: 'alert alert-danger', innerText: (error as Error).message })
5251
);
5352
}
5453
};
5554

56-
export const handleUserList = () => {
55+
export const handleUserList = (): void => {
5756
const activateButtons = document.querySelectorAll('.btn-activate-user');
5857
const deleteButtons = document.querySelectorAll('.btn-delete-user');
5958

@@ -62,8 +61,9 @@ export const handleUserList = () => {
6261
button.addEventListener('click', async (event) => {
6362
event.preventDefault();
6463

65-
const csrfToken = event.target.getAttribute('data-csrf-token');
66-
const userId = event.target.getAttribute('data-user-id');
64+
const target = event.target as HTMLElement;
65+
const csrfToken = target.getAttribute('data-csrf-token')!;
66+
const userId = target.getAttribute('data-user-id')!;
6767

6868
await activateUser(userId, csrfToken);
6969
});
@@ -75,27 +75,30 @@ export const handleUserList = () => {
7575
button.addEventListener('click', (event) => {
7676
event.preventDefault();
7777

78-
const deleteModal = new Modal(document.getElementById('pmf-modal-user-confirm-delete'));
78+
const deleteModal = new Modal(document.getElementById('pmf-modal-user-confirm-delete') as HTMLElement);
7979
deleteModal.show();
80-
document.getElementById('pmf-username-delete').innerText = button.getAttribute('data-username');
81-
document.getElementById('pmf-user-id-delete').value = button.getAttribute('data-user-id');
82-
document.getElementById('source_page').value = 'user-list';
80+
const usernameDelete = document.getElementById('pmf-username-delete') as HTMLElement;
81+
usernameDelete.innerText = button.getAttribute('data-username')!;
82+
const userIdDelete = document.getElementById('pmf-user-id-delete') as HTMLInputElement;
83+
userIdDelete.value = button.getAttribute('data-user-id')!;
84+
const sourcePage = document.getElementById('source_page') as HTMLInputElement;
85+
sourcePage.value = 'user-list';
8386
});
8487
});
8588

8689
const deleteUserConfirm = document.getElementById('pmf-delete-user-yes');
8790
if (deleteUserConfirm) {
8891
deleteUserConfirm.addEventListener('click', async (event) => {
8992
event.preventDefault();
90-
const source = document.getElementById('source_page');
93+
const source = document.getElementById('source_page') as HTMLInputElement;
9194
if (source.value === 'user-list') {
92-
const userId = document.getElementById('pmf-user-id-delete').value;
93-
const csrfToken = document.getElementById('csrf-token-delete-user').value;
95+
const userId = (document.getElementById('pmf-user-id-delete') as HTMLInputElement).value;
96+
const csrfToken = (document.getElementById('csrf-token-delete-user') as HTMLInputElement).value;
9497
const response = await deleteUser(userId, csrfToken);
9598
const json = await response.json();
9699
if (json.success) {
97100
pushNotification(json.success);
98-
const row = document.getElementById('row_user_id_' + userId);
101+
const row = document.getElementById('row_user_id_' + userId) as HTMLElement;
99102
row.remove();
100103
}
101104
if (json.error) {

0 commit comments

Comments
 (0)