Skip to content

Commit 519a484

Browse files
committed
refactor: migrated from JavaScript to TypeScript
WIP, not done yet, build is currently broken
1 parent b79f745 commit 519a484

92 files changed

Lines changed: 1117 additions & 795 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ indent_style = space
99
indent_size = 4
1010

1111
# HTML, SCSS, JS, YAML and JSON files
12-
[{*.html,*.twig,*.scss,*.js,*.json,*.yml}]
12+
[{*.html,*.twig,*.scss,*.js,*.ts,*.json,*.yml}]
1313
indent_size = 2

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This is a log of major user-visible changes in each phpMyFAQ release.
1414
- added plugin administration backend (Thorsten)
1515
- improved online update feature (Thorsten)
1616
- migrated from WYSIWYG editor from TinyMCE to Jodit Editor (Thorsten)
17+
- WIP: migrated from JavaScript to TypeScript (Thorsten)
1718
- migrated from Webpack to Vite v6 (Thorsten)
1819
- migrated from Jest to Vitest v3 (Thorsten)
1920

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
"@babel/preset-env": "^7.26.0",
5050
"@commitlint/cli": "^19.6.1",
5151
"@commitlint/config-conventional": "^19.6.0",
52+
"@types/bootstrap": "^5.2.10",
53+
"@types/highlightjs": "^9.12.6",
54+
"@types/masonry-layout": "^4.2.8",
5255
"@types/node": "^20.17.14",
5356
"@vitest/coverage-v8": "2.1.5",
5457
"autoprefixer": "^10.4.20",
@@ -61,6 +64,7 @@
6164
"rollup-plugin-sbom": "^1.1.1",
6265
"sass": "^1.83.4",
6366
"sigmund": "^1.0.1",
67+
"typescript": "^5.7.3",
6468
"vite": "^6.0.7",
6569
"vite-plugin-compression": "^0.5.1",
6670
"vite-plugin-html": "^3.2.2",

phpmyfaq/admin/assets/src/api/attachment.js renamed to phpmyfaq/admin/assets/src/api/attachment.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* @since 2024-05-01
1414
*/
1515

16-
export const deleteAttachments = async (attachmentId, csrfToken) => {
16+
import { Response } from '../interfaces';
17+
18+
export const deleteAttachments = async (attachmentId: string, csrfToken: string): Promise<Response | undefined> => {
1719
try {
1820
const response = await fetch('./api/content/attachments', {
1921
method: 'DELETE',
@@ -30,7 +32,7 @@ export const deleteAttachments = async (attachmentId, csrfToken) => {
3032
}
3133
};
3234

33-
export const refreshAttachments = async (attachmentId, csrfToken) => {
35+
export const refreshAttachments = async (attachmentId: string, csrfToken: string): Promise<Response | undefined> => {
3436
try {
3537
const response = await fetch('./api/content/attachments/refresh', {
3638
method: 'POST',
Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
* @link https://www.phpmyfaq.de
1313
* @since 2023-12-28
1414
*/
15+
import { Response } from '../interfaces';
1516

16-
export const fetchCategoryTranslations = async (categoryId) => {
17+
export const fetchCategoryTranslations = async (categoryId: string): Promise<Response | undefined> => {
1718
try {
1819
const response = await fetch(`./api/category/translations/${categoryId}`, {
1920
method: 'GET',
@@ -25,17 +26,17 @@ export const fetchCategoryTranslations = async (categoryId) => {
2526
referrerPolicy: 'no-referrer',
2627
});
2728

28-
if (response.ok) {
29-
return await response.json();
30-
} else {
31-
return await response.json();
32-
}
29+
return await response.json();
3330
} catch (error) {
3431
console.error(error);
3532
}
3633
};
3734

38-
export const deleteCategory = async (categoryId, language, csrfToken) => {
35+
export const deleteCategory = async (
36+
categoryId: string,
37+
language: string,
38+
csrfToken: string
39+
): Promise<Response | undefined> => {
3940
try {
4041
const response = await fetch(`./api/category/delete`, {
4142
method: 'DELETE',
@@ -52,17 +53,17 @@ export const deleteCategory = async (categoryId, language, csrfToken) => {
5253
referrerPolicy: 'no-referrer',
5354
});
5455

55-
if (response.ok) {
56-
return await response.json();
57-
} else {
58-
return await response.json();
59-
}
56+
return await response.json();
6057
} catch (error) {
6158
console.error(error);
6259
}
6360
};
6461

65-
export const setCategoryTree = async (categoryTree, categoryId, csrfToken) => {
62+
export const setCategoryTree = async (
63+
categoryTree: any,
64+
categoryId: string,
65+
csrfToken: string
66+
): Promise<Response | undefined> => {
6667
try {
6768
const response = await fetch('./api/category/update-order', {
6869
method: 'POST',
@@ -79,11 +80,7 @@ export const setCategoryTree = async (categoryTree, categoryId, csrfToken) => {
7980
referrerPolicy: 'no-referrer',
8081
});
8182

82-
if (response.ok) {
83-
return await response.json();
84-
} else {
85-
return await response.json();
86-
}
83+
return await response.json();
8784
} catch (error) {
8885
console.error(error);
8986
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* @since 2024-05-05
1414
*/
1515

16-
export const createReport = async (data, csrfToken) => {
16+
import { Response } from '../interfaces';
17+
18+
export const createReport = async (data: any, csrfToken: string): Promise<Blob | Response | undefined> => {
1719
try {
1820
const response = await fetch('./api/export/report', {
1921
method: 'POST',
Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
* @since 2023-12-27
1414
*/
1515

16-
export const fetchAllFaqsByCategory = async (categoryId, language, onlyInactive, onlyNew) => {
16+
import { Response } from '../interfaces';
17+
18+
export const fetchAllFaqsByCategory = async (
19+
categoryId: string,
20+
language: string,
21+
onlyInactive?: string,
22+
onlyNew?: string
23+
): Promise<Response | undefined> => {
1724
try {
1825
let currentUrl = window.location.protocol + '//' + window.location.host;
1926
let pathname = window.location.pathname;
@@ -51,7 +58,7 @@ export const fetchAllFaqsByCategory = async (categoryId, language, onlyInactive,
5158
}
5259
};
5360

54-
export const fetchFaqsByAutocomplete = async (searchTerm, csrfToken) => {
61+
export const fetchFaqsByAutocomplete = async (searchTerm: string, csrfToken: string): Promise<Response | undefined> => {
5562
try {
5663
const response = await fetch(`./api/faq/search`, {
5764
method: 'POST',
@@ -76,7 +83,7 @@ export const fetchFaqsByAutocomplete = async (searchTerm, csrfToken) => {
7683
}
7784
};
7885

79-
export const deleteFaq = async (faqId, faqLanguage, token) => {
86+
export const deleteFaq = async (faqId: string, faqLanguage: string, token: string): Promise<Response | undefined> => {
8087
try {
8188
const response = await fetch('./api/faq/delete', {
8289
method: 'DELETE',
@@ -102,7 +109,7 @@ export const deleteFaq = async (faqId, faqLanguage, token) => {
102109
}
103110
};
104111

105-
export const create = async (formData) => {
112+
export const create = async (formData: any): Promise<Response | undefined> => {
106113
try {
107114
const response = await fetch('./api/faq/create', {
108115
method: 'POST',
@@ -121,7 +128,7 @@ export const create = async (formData) => {
121128
}
122129
};
123130

124-
export const update = async (formData) => {
131+
export const update = async (formData: any): Promise<Response | undefined> => {
125132
try {
126133
const response = await fetch('./api/faq/update', {
127134
method: 'PUT',
Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,15 @@
1414
* @since 2014-03-21
1515
*/
1616

17-
import { pushNotification } from '../utils';
17+
import { pushNotification } from '../../../../assets/src/utils';
18+
import { Response } from '../interfaces';
1819

19-
export const fetchActivateInput = async (csrf, formId, inputId, checked) => {
20+
export const fetchActivateInput = async (
21+
csrf: string,
22+
formId: string,
23+
inputId: string,
24+
checked: boolean
25+
): Promise<void> => {
2026
try {
2127
const response = await fetch('api/forms/activate', {
2228
method: 'POST',
@@ -33,22 +39,27 @@ export const fetchActivateInput = async (csrf, formId, inputId, checked) => {
3339
});
3440

3541
if (response.ok) {
36-
const result = await response.json();
42+
const result: Response = await response.json();
3743
if (result.success) {
38-
pushNotification(result.success);
44+
pushNotification(result.success); // @todo move that to the forms.ts file in the content folder
3945
} else {
4046
console.error(result.error);
4147
}
4248
} else {
43-
throw new Error('Network response was not ok: ', response.text());
49+
throw new Error('Network response was not ok: ' + (await response.text()));
4450
}
4551
} catch (error) {
4652
console.error('Error activating/deactivating input:', error);
4753
throw error;
4854
}
4955
};
5056

51-
export const fetchSetInputAsRequired = async (csrf, formId, inputId, checked) => {
57+
export const fetchSetInputAsRequired = async (
58+
csrf: string,
59+
formId: string,
60+
inputId: string,
61+
checked: boolean
62+
): Promise<void> => {
5263
try {
5364
const response = await fetch('api/forms/required', {
5465
method: 'POST',
@@ -65,22 +76,28 @@ export const fetchSetInputAsRequired = async (csrf, formId, inputId, checked) =>
6576
});
6677

6778
if (response.ok) {
68-
const result = await response.json();
79+
const result: Response = await response.json();
6980
if (result.success) {
70-
pushNotification(result.success);
81+
pushNotification(result.success); // @todo move that to the forms.ts file in the content folder
7182
} else {
7283
console.error(result.error);
7384
}
7485
} else {
75-
throw new Error('Network response was not ok: ', response.text());
86+
throw new Error('Network response was not ok: ' + (await response.text()));
7687
}
7788
} catch (error) {
7889
console.error('Error setting input as required:', error);
7990
throw error;
8091
}
8192
};
8293

83-
export const fetchEditTranslation = async (csrf, formId, inputId, label, lang) => {
94+
export const fetchEditTranslation = async (
95+
csrf: string,
96+
formId: string,
97+
inputId: string,
98+
label: string,
99+
lang: string
100+
): Promise<void> => {
84101
try {
85102
const response = await fetch('api/forms/translation-edit', {
86103
method: 'POST',
@@ -98,22 +115,28 @@ export const fetchEditTranslation = async (csrf, formId, inputId, label, lang) =
98115
});
99116

100117
if (response.ok) {
101-
const result = await response.json();
118+
const result: Response = await response.json();
102119
if (result.success) {
103-
pushNotification(result.success);
120+
pushNotification(result.success); // @todo move that to the forms.ts file in the content folder
104121
} else {
105122
console.error(result.error);
106123
}
107124
} else {
108-
throw new Error('Network response was not ok: ', response.text());
125+
throw new Error('Network response was not ok: ' + (await response.text()));
109126
}
110127
} catch (error) {
111128
console.error('Error editing translation:', error);
112129
throw error;
113130
}
114131
};
115132

116-
export const fetchDeleteTranslation = async (csrf, formId, inputId, lang, element) => {
133+
export const fetchDeleteTranslation = async (
134+
csrf: string,
135+
formId: string,
136+
inputId: string,
137+
lang: string,
138+
element: HTMLElement
139+
): Promise<void> => {
117140
try {
118141
const response = await fetch('api/forms/translation-delete', {
119142
method: 'POST',
@@ -130,26 +153,33 @@ export const fetchDeleteTranslation = async (csrf, formId, inputId, lang, elemen
130153
});
131154

132155
if (response.ok) {
133-
const result = await response.json();
156+
const result: Response = await response.json();
134157
if (result.success) {
158+
// @todo move that to the forms.ts file in the content folder
135159
pushNotification(result.success);
136-
document.getElementById('item_' + element.getAttribute('data-pmf-lang')).remove();
160+
document.getElementById('item_' + element.getAttribute('data-pmf-lang'))?.remove();
137161
const option = document.createElement('option');
138-
option.innerText = element.getAttribute('data-pmf-langname');
139-
document.getElementById('languageSelect').appendChild(option);
162+
option.innerText = element.getAttribute('data-pmf-langname')!;
163+
document.getElementById('languageSelect')?.appendChild(option);
140164
} else {
141165
console.error(result.error);
142166
}
143167
} else {
144-
throw new Error('Network response was not ok: ', response.text());
168+
throw new Error('Network response was not ok: ' + (await response.text()));
145169
}
146170
} catch (error) {
147171
console.error('Error deleting translation:', error);
148172
throw error;
149173
}
150174
};
151175

152-
export const fetchAddTranslation = async (csrf, formId, inputId, lang, translation) => {
176+
export const fetchAddTranslation = async (
177+
csrf: string,
178+
formId: string,
179+
inputId: string,
180+
lang: string,
181+
translation: string
182+
): Promise<void> => {
153183
try {
154184
const response = await fetch('api/forms/translation-add', {
155185
method: 'POST',
@@ -167,8 +197,9 @@ export const fetchAddTranslation = async (csrf, formId, inputId, lang, translati
167197
});
168198

169199
if (response.ok) {
170-
const result = await response.json();
200+
const result: Response = await response.json();
171201
if (result.success) {
202+
// @todo move that to the forms.ts file in the content folder
172203
pushNotification(result.success);
173204
setTimeout(function () {
174205
window.location.reload();
@@ -177,9 +208,9 @@ export const fetchAddTranslation = async (csrf, formId, inputId, lang, translati
177208
console.error(result.error);
178209
}
179210
} else {
180-
throw new Error('Network response was not ok: ', response.text());
211+
throw new Error('Network response was not ok: ' + (await response.text()));
181212
}
182-
} catch {
213+
} catch (error) {
183214
console.error('Error adding translation:', error);
184215
throw error;
185216
}

0 commit comments

Comments
 (0)