Skip to content

Commit 4803589

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

File tree

14 files changed

+288
-243
lines changed

14 files changed

+288
-243
lines changed
Lines changed: 97 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,55 @@
1+
/**
2+
* Functions for handling group management
3+
*
4+
* @todo move fetch() functionality to api functions
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public License,
7+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
8+
* obtain one at https://mozilla.org/MPL/2.0/.
9+
*
10+
* @package phpMyFAQ
11+
* @author Thorsten Rinne <[email protected]>
12+
* @copyright 2023-2025 phpMyFAQ Team
13+
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14+
* @link https://www.phpmyfaq.de
15+
* @since 2023-01-04
16+
*/
17+
118
import { fetchAllGroups, fetchAllMembers, fetchAllUsersForGroups, fetchGroup, fetchGroupRights } from '../api';
219
import { selectAll, unSelectAll } from '../utils';
320

4-
export const handleGroups = async () => {
21+
interface Group {
22+
group_id: string;
23+
name: string;
24+
description?: string;
25+
auto_join?: string;
26+
}
27+
28+
interface User {
29+
user_id: string;
30+
login: string;
31+
}
32+
33+
interface Member {
34+
user_id: string;
35+
login: string;
36+
}
37+
38+
export const handleGroups = async (): Promise<void> => {
539
clearGroupList();
640

7-
const groupListSelect = document.querySelector('#group_list_select');
41+
const groupListSelect = document.querySelector<HTMLSelectElement>('#group_list_select');
842
if (!groupListSelect) {
943
return;
1044
}
1145

12-
const addMember = document.querySelector('.pmf-add-member');
13-
const removeMember = document.querySelector('.pmf-remove-member');
14-
const selectAllUsers = document.getElementById('select_all_group_user_list');
15-
const unSelectAllUsers = document.getElementById('unselect_all_group_user_list');
16-
const selectAllMembers = document.getElementById('select_all_members');
17-
const unSelectAllMembers = document.getElementById('unselect_all_members');
18-
const groups = await fetchAllGroups();
46+
const addMember = document.querySelector<HTMLButtonElement>('.pmf-add-member') as HTMLButtonElement;
47+
const removeMember = document.querySelector<HTMLButtonElement>('.pmf-remove-member') as HTMLButtonElement;
48+
const selectAllUsers = document.getElementById('select_all_group_user_list') as HTMLButtonElement;
49+
const unSelectAllUsers = document.getElementById('unselect_all_group_user_list') as HTMLButtonElement;
50+
const selectAllMembers = document.getElementById('select_all_members') as HTMLButtonElement;
51+
const unSelectAllMembers = document.getElementById('unselect_all_members') as HTMLButtonElement;
52+
const groups: Group[] = await fetchAllGroups();
1953

2054
groups.forEach((group) => {
2155
const option = document.createElement('option');
@@ -27,7 +61,7 @@ export const handleGroups = async () => {
2761
await processGroupList();
2862

2963
// Events
30-
groupListSelect.addEventListener('change', (event) => {
64+
groupListSelect.addEventListener('change', (event: Event) => {
3165
handleGroupSelect(event);
3266
});
3367

@@ -58,8 +92,8 @@ export const handleGroups = async () => {
5892
});
5993
};
6094

61-
const handleGroupSelect = async (event) => {
62-
const groupId = event.target?.value;
95+
const handleGroupSelect = async (event: Event): Promise<void> => {
96+
const groupId = (event.target as HTMLSelectElement)?.value;
6397

6498
if (groupId) {
6599
clearGroupData();
@@ -72,12 +106,12 @@ const handleGroupSelect = async (event) => {
72106
await getMemberList(groupId);
73107

74108
// Activate user inputs
75-
const saveGroupDetails = document.getElementById('saveGroupDetails');
76-
const saveMembersList = document.getElementById('saveMembersList');
77-
const saveGroupRights = document.getElementById('saveGroupRights');
78-
const deleteGroup = document.getElementById('deleteGroup');
79-
const groupAddMember = document.getElementById('groupAddMember');
80-
const groupRemoveMember = document.getElementById('groupRemoveMember');
109+
const saveGroupDetails = document.getElementById('saveGroupDetails') as HTMLButtonElement;
110+
const saveMembersList = document.getElementById('saveMembersList') as HTMLButtonElement;
111+
const saveGroupRights = document.getElementById('saveGroupRights') as HTMLButtonElement;
112+
const deleteGroup = document.getElementById('deleteGroup') as HTMLButtonElement;
113+
const groupAddMember = document.getElementById('groupAddMember') as HTMLButtonElement;
114+
const groupRemoveMember = document.getElementById('groupRemoveMember') as HTMLButtonElement;
81115

82116
saveGroupDetails.disabled = false;
83117
saveMembersList.disabled = false;
@@ -86,89 +120,89 @@ const handleGroupSelect = async (event) => {
86120
groupAddMember.disabled = false;
87121
groupRemoveMember.disabled = false;
88122

89-
const rightCheckboxes = document.querySelectorAll('.permission').forEach((item) => {
123+
document.querySelectorAll<HTMLInputElement>('.permission').forEach((item) => {
90124
item.disabled = false;
91125
});
92126
}
93127
};
94128

95-
const getGroupData = async (groupId) => {
96-
const groupData = await fetchGroup(groupId);
129+
const getGroupData = async (groupId: string): Promise<void> => {
130+
const groupData: Group = await fetchGroup(groupId);
97131

98-
document.getElementById('update_group_id').value = groupData.group_id;
99-
document.getElementById('update_group_name').value = groupData.name;
100-
document.getElementById('update_group_description').value = groupData.description;
132+
(document.getElementById('update_group_id') as HTMLInputElement).value = groupData.group_id;
133+
(document.getElementById('update_group_name') as HTMLInputElement).value = groupData.name;
134+
(document.getElementById('update_group_description') as HTMLInputElement).value = groupData.description || '';
101135

102-
const autoJoinCheckbox = document.getElementById('update_group_auto_join');
103-
autoJoinCheckbox.checked = 1 === parseInt(groupData.auto_join);
136+
const autoJoinCheckbox = document.getElementById('update_group_auto_join') as HTMLInputElement;
137+
autoJoinCheckbox.checked = 1 === parseInt(groupData.auto_join || '0');
104138
};
105139

106-
const clearGroupList = () => {
107-
const groupList = document.getElementById('group_list_select');
140+
const clearGroupList = (): void => {
141+
const groupList = document.getElementById('group_list_select') as HTMLSelectElement;
108142
if (groupList) {
109143
groupList.textContent = '';
110144
}
111145
};
112146

113-
const processGroupList = async () => {
147+
const processGroupList = async (): Promise<void> => {
114148
clearGroupData();
115149
clearGroupRights();
116150
clearUserList();
117151
await getUserList();
118152
clearMemberList();
119153
};
120154

121-
const clearGroupData = () => {
122-
const updateGroupAutoJoin = document.getElementById('update_group_auto_join');
123-
const updateGroupId = document.getElementById('#update_group_id');
155+
const clearGroupData = (): void => {
156+
const updateGroupAutoJoin = document.getElementById('update_group_auto_join') as HTMLInputElement;
157+
const updateGroupId = document.getElementById('update_group_id') as HTMLInputElement;
124158
if (updateGroupId) {
125159
updateGroupId.value = '';
126160
}
127-
const updateGroupName = document.getElementById('#update_group_name');
161+
const updateGroupName = document.getElementById('update_group_name') as HTMLInputElement;
128162
if (updateGroupName) {
129163
updateGroupName.value = '';
130164
}
131-
const updateGroupDescription = document.getElementById('#update_group_description');
165+
const updateGroupDescription = document.getElementById('update_group_description') as HTMLInputElement;
132166
if (updateGroupDescription) {
133167
updateGroupDescription.value = '';
134168
}
135-
if ('checked' === updateGroupAutoJoin.getAttribute('checked')) {
136-
updateGroupAutoJoin.setAttribute('checked', '');
169+
if (updateGroupAutoJoin.checked) {
170+
updateGroupAutoJoin.checked = false;
137171
}
138172
};
139173

140-
const clearGroupRights = () => {
141-
const groupRightsCheckboxes = document.querySelectorAll('#groupRights input[type=checkbox]');
174+
const clearGroupRights = (): void => {
175+
const groupRightsCheckboxes = document.querySelectorAll<HTMLInputElement>('#groupRights input[type=checkbox]');
142176
if (groupRightsCheckboxes) {
143177
groupRightsCheckboxes.forEach((checkbox) => {
144178
checkbox.checked = false;
145179
});
146180
}
147181
};
148182

149-
const getGroupRights = async (groupId) => {
150-
const groupRights = await fetchGroupRights(groupId);
183+
const getGroupRights = async (groupId: string): Promise<void> => {
184+
const groupRights: string[] = await fetchGroupRights(groupId);
151185

152186
if (groupRights) {
153-
document.getElementById('rights_group_id').value = groupId;
187+
(document.getElementById('rights_group_id') as HTMLInputElement).value = groupId;
154188
groupRights.forEach((right) => {
155-
document.getElementById(`group_right_${right}`).checked = true;
189+
(document.getElementById(`group_right_${right}`) as HTMLInputElement).checked = true;
156190
});
157191
}
158192
};
159193

160-
const clearUserList = () => {
161-
const groupUserListOptions = document.querySelectorAll('#group_user_list option');
194+
const clearUserList = (): void => {
195+
const groupUserListOptions = document.querySelectorAll<HTMLSelectElement>('#group_user_list option');
162196
if (groupUserListOptions) {
163197
groupUserListOptions.forEach((option) => {
164198
option.value = '';
165199
});
166200
}
167201
};
168202

169-
const getUserList = async () => {
170-
const groupUserList = document.querySelector('#group_user_list');
171-
const allUsers = await fetchAllUsersForGroups();
203+
const getUserList = async (): Promise<void> => {
204+
const groupUserList = document.querySelector<HTMLSelectElement>('#group_user_list');
205+
const allUsers: User[] = await fetchAllUsersForGroups();
172206

173207
groupUserList.textContent = '';
174208
allUsers.forEach((user) => {
@@ -179,14 +213,14 @@ const getUserList = async () => {
179213
});
180214
};
181215

182-
const clearMemberList = () => {
183-
const groupMemberList = document.querySelector('#group_member_list');
216+
const clearMemberList = (): void => {
217+
const groupMemberList = document.querySelector<HTMLSelectElement>('#group_member_list');
184218
groupMemberList.textContent = '';
185219
};
186220

187-
const getMemberList = async (groupId) => {
188-
const groupMemberList = document.querySelector('#group_member_list');
189-
const members = await fetchAllMembers(groupId);
221+
const getMemberList = async (groupId: string): Promise<void> => {
222+
const groupMemberList = document.querySelector<HTMLSelectElement>('#group_member_list');
223+
const members: Member[] = await fetchAllMembers(groupId);
190224

191225
groupMemberList.textContent = '';
192226
members.forEach((member) => {
@@ -196,24 +230,25 @@ const getMemberList = async (groupId) => {
196230
option.selected = true;
197231
groupMemberList.appendChild(option);
198232
});
199-
document.getElementById('update_member_group_id').value = groupId;
233+
(document.getElementById('update_member_group_id') as HTMLInputElement).value = groupId;
200234
};
201235

202-
const addGroupMembers = () => {
236+
const addGroupMembers = (): void => {
203237
// make sure that a group is selected
204-
const selectedGroup = document.querySelector('#group_list_select option:checked');
238+
const selectedGroup = document.querySelector<HTMLSelectElement>('#group_list_select option:checked');
205239
if (selectedGroup === null) {
206240
// @todo refactor alert() to something more beautiful.
207241
alert('Please choose a group.');
242+
return;
208243
}
209244

210-
const allUsers = document.getElementById('group_user_list');
245+
const allUsers = document.getElementById('group_user_list') as HTMLSelectElement;
211246
const selectedUsers = [...allUsers.options]
212247
.filter((option) => option.selected)
213248
.map((option) => {
214249
return { value: option.value, login: option.innerText };
215250
});
216-
const allMembers = document.getElementById('group_member_list');
251+
const allMembers = document.getElementById('group_member_list') as HTMLSelectElement;
217252
const members = [...allMembers.options].map((option) => {
218253
return { value: option.value, login: option.innerText };
219254
});
@@ -227,7 +262,7 @@ const addGroupMembers = () => {
227262
});
228263

229264
if (isMember === false) {
230-
const groupMemberList = document.getElementById('group_member_list');
265+
const groupMemberList = document.getElementById('group_member_list') as HTMLSelectElement;
231266
const option = document.createElement('option');
232267
option.value = user.value;
233268
option.textContent = user.login;
@@ -238,19 +273,17 @@ const addGroupMembers = () => {
238273
}
239274
};
240275

241-
const removeGroupMembers = () => {
242-
console.log('removeGroupMembers');
243-
244-
const memberList = document.getElementById('group_member_list');
245-
const allMembers = [...memberList.options].map((option) => option.value);
276+
const removeGroupMembers = (): void => {
277+
const memberList = document.getElementById('group_member_list') as HTMLSelectElement;
246278
const selectedMembers = [...memberList.options].filter((option) => option.selected).map((option) => option.value);
247279

248280
if (selectedMembers.length === 0) {
249281
// @todo refactor alert() to something more beautiful.
250282
alert('Please choose a member.');
283+
return;
251284
}
252285

253-
for (const member of [...document.querySelector('#group_member_list').options]) {
286+
for (const member of [...document.querySelectorAll<HTMLSelectElement>('#group_member_list option')]) {
254287
if (selectedMembers.includes(member.value)) {
255288
member.remove();
256289
}

phpmyfaq/admin/assets/src/plugins/code-snippet/code-snippet.svg.js renamed to phpmyfaq/admin/assets/src/plugins/code-snippet/code-snippet.svg.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const codeSnippet = `<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"
1+
const codeSnippet: string = `<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"
22
preserveAspectRatio="xMidYMid meet">
33
44
<rect width="100%" height="100%" fill="none" />

phpmyfaq/admin/assets/src/plugins/code-snippet/code-snippet.js renamed to phpmyfaq/admin/assets/src/plugins/code-snippet/code-snippet.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,18 @@ import codeSnippet from '../code-snippet/code-snippet.svg.js';
1818

1919
Jodit.modules.Icon.set('codeSnippet', codeSnippet);
2020

21-
Jodit.plugins.add('codeSnippet', (editor) => {
21+
Jodit.plugins.add('codeSnippet', (editor: Jodit): void => {
2222
// Register the button
2323
editor.registerButton({
2424
name: 'codeSnippet',
2525
group: 'insert',
26-
icon: 'codeSnippet',
2726
options: {
2827
tooltip: 'Insert Source Code Snippet',
2928
},
3029
});
3130

3231
// Register the command
33-
editor.registerCommand('codeSnippet', () => {
32+
editor.registerCommand('codeSnippet', (): void => {
3433
const dialog = editor.dlg({ closeOnClickOverlay: true });
3534

3635
const content = `<form class="row m-4">
@@ -73,11 +72,11 @@ Jodit.plugins.add('codeSnippet', (editor) => {
7372

7473
dialog.open();
7574

76-
const addCodeSnippetButton = document.getElementById('add-code-snippet-button');
77-
const language = document.getElementById('programming-language');
78-
const code = document.getElementById('code');
75+
const addCodeSnippetButton = document.getElementById('add-code-snippet-button') as HTMLButtonElement;
76+
const language = document.getElementById('programming-language') as HTMLSelectElement;
77+
const code = document.getElementById('code') as HTMLTextAreaElement;
7978

80-
const encodeHTML = (str) => {
79+
const encodeHTML = (str: string): string => {
8180
return str
8281
.replace(/&/g, '&amp;')
8382
.replace(/</g, '&lt;')
@@ -86,7 +85,7 @@ Jodit.plugins.add('codeSnippet', (editor) => {
8685
.replace(/'/g, '&#039;');
8786
};
8887

89-
addCodeSnippetButton.addEventListener('click', () => {
88+
addCodeSnippetButton.addEventListener('click', (): void => {
9089
const selectedLanguage = language.value;
9190
const selectedCode = code.value;
9291
const codeSnippet = `<pre><code class="language-${selectedLanguage}">${encodeHTML(selectedCode)}</code></pre>`;

phpmyfaq/admin/assets/src/plugins/phpmyfaq/phpmyfaq.svg.js renamed to phpmyfaq/admin/assets/src/plugins/phpmyfaq/phpmyfaq.svg.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const phpmyfaq = `
1+
const phpmyfaq: string = `
22
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1500"
33
preserveAspectRatio="xMidYMid meet">
44

0 commit comments

Comments
 (0)