diff --git a/nginx.conf b/nginx.conf index 800c4f34c1..f30c231489 100644 --- a/nginx.conf +++ b/nginx.conf @@ -129,7 +129,7 @@ server { rewrite admin/api/(.*) /admin/api/index.php last; # Administration pages - rewrite admin/(attachments|backup|configuration|elasticsearch|export|group|import|instance|instances|password|session-keep-alive|statistics|stopwords|system|update|user) /admin/front.php last; + rewrite admin/(attachments|backup|configuration|elasticsearch|export|group|import|instance|instances|password|session-keep-alive|statistics|stopwords|system|tags|update|user) /admin/front.php last; # REST API v3.0 and v3.1 rewrite ^api/v3\.[01]/(.*) /api/index.php last; diff --git a/package.json b/package.json index fc0f3fd51a..212508491d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "type": "module", "scripts": { "build": "vite build", - "build:watch": "vite build --watch", + "build:watch": "vite build --watch -d", "build:prod": "vite build", "lint": "prettier --check .", "lint:fix": "prettier --write .", diff --git a/phpmyfaq/.htaccess b/phpmyfaq/.htaccess index 07ce5fd43b..dc878ee15e 100644 --- a/phpmyfaq/.htaccess +++ b/phpmyfaq/.htaccess @@ -143,7 +143,7 @@ Header set Access-Control-Allow-Headers "Content-Type, Authorization" # Administration API RewriteRule ^admin/api/(.*) admin/api/index.php [L,QSA] # Administration pages - RewriteRule ^admin/(attachments|backup|configuration|elasticsearch|export|group|import|instance|instances|password|session-keep-alive|statistics|stopwords|system|update|user) admin/front.php [L,QSA] + RewriteRule ^admin/(attachments|backup|configuration|elasticsearch|export|group|import|instance|instances|password|session-keep-alive|statistics|stopwords|system|tags|update|user) admin/front.php [L,QSA] # Private APIs RewriteRule ^api/(autocomplete|bookmark/delete|bookmark/create|user/data/update|user/password/update|user/request-removal|user/remove-twofactor|contact|voting|register|captcha|share|comment/create|faq/create|question/create|webauthn/prepare|webauthn/register|webauthn/prepare-login|webauthn/login) api/index.php [L,QSA] # Setup APIs diff --git a/phpmyfaq/admin/assets/src/api/tags.js b/phpmyfaq/admin/assets/src/api/tags.js index df1064c70d..b50d7c659e 100644 --- a/phpmyfaq/admin/assets/src/api/tags.js +++ b/phpmyfaq/admin/assets/src/api/tags.js @@ -39,3 +39,30 @@ export const fetchTags = async (searchString) => { throw error; } }; + +export const deleteTag = async (tagId) => { + try { + const response = await fetch(`./api/content/tags/${tagId}`, { + method: 'DELETE', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + redirect: 'follow', + referrerPolicy: 'no-referrer', + }); + + if (response.ok) { + return await response.json(); + } else { + throw new Error('Network response was not ok: ', { cause: { response } }); + } + } catch (error) { + console.error('Error deleting tag:', error); + if (error.cause && error.cause.response) { + const errorMessage = await error.cause.response.json(); + console.error(errorMessage); + } + throw error; + } +}; diff --git a/phpmyfaq/admin/assets/src/content/tags.js b/phpmyfaq/admin/assets/src/content/tags.js index d421d01f6d..525708dd93 100644 --- a/phpmyfaq/admin/assets/src/content/tags.js +++ b/phpmyfaq/admin/assets/src/content/tags.js @@ -15,10 +15,12 @@ import autocomplete from 'autocompleter'; import { addElement } from '../../../../assets/src/utils'; -import { fetchTags } from '../api'; +import { deleteTag, fetchTags } from '../api'; +import { pushNotification } from '../utils/index.js'; export const handleTags = () => { const editTagButtons = document.querySelectorAll('.btn-edit'); + const deleteButtons = document.querySelectorAll('.btn-delete'); const tagForm = document.getElementById('tag-form'); const tagsAutocomplete = document.querySelector('.pmf-tags-autocomplete'); @@ -51,6 +53,23 @@ export const handleTags = () => { }); } + if (deleteButtons) { + deleteButtons.forEach((element) => { + element.addEventListener('click', async (event) => { + const tagId = event.target.getAttribute('data-pmf-id'); + + const response = await deleteTag(tagId); + if (response.success) { + pushNotification(response.success); + const row = document.getElementById(`pmf-row-tag-id-${tagId}`); + row.remove(); + } else { + throw new Error('Network response was not ok: ' + JSON.stringify(response.error)); + } + }); + }); + } + if (tagForm) { tagForm.addEventListener('submit', (event) => { event.preventDefault(); diff --git a/phpmyfaq/admin/header.php b/phpmyfaq/admin/header.php index 04fc0475d6..ca921381e0 100644 --- a/phpmyfaq/admin/header.php +++ b/phpmyfaq/admin/header.php @@ -90,7 +90,8 @@ $secLevelEntries['content'] .= $adminHelper->addMenuEntry( PermissionType::FAQ_EDIT->value, 'tags', - 'ad_entry_tags' + 'ad_entry_tags', + 'tags' ); $secLevelEntries['content'] .= $adminHelper->addMenuEntry( 'addglossary+editglossary+delglossary', @@ -201,8 +202,6 @@ case 'takequestion': case 'comments': case 'attachments': - case 'tags': - case 'delete-tag': case 'stickyfaqs': $contentPage = true; break; diff --git a/phpmyfaq/admin/index.php b/phpmyfaq/admin/index.php index 617b9ca019..ecaee48ed1 100755 --- a/phpmyfaq/admin/index.php +++ b/phpmyfaq/admin/index.php @@ -276,11 +276,6 @@ case 'stickyfaqs': require 'stickyfaqs.php'; break; - // functions for tags - case 'tags': - case 'delete-tag': - require 'tags.php'; - break; // news administration case 'news': case 'add-news': diff --git a/phpmyfaq/admin/tags.php b/phpmyfaq/admin/tags.php deleted file mode 100644 index d759419485..0000000000 --- a/phpmyfaq/admin/tags.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @copyright 2003-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2003-02-24 - */ - -use phpMyFAQ\Configuration; -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filter; -use phpMyFAQ\Session\Token; -use phpMyFAQ\Tags; -use phpMyFAQ\Template\TwigWrapper; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -$faqConfig = Configuration::getConfigurationInstance(); -$user = CurrentUser::getCurrentUser($faqConfig); - -$tagId = Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT); - -$twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); -$template = $twig->loadTemplate('@admin/content/tags.twig'); - -$tags = new Tags($faqConfig); - -if ('delete-tag' === $action) { - $tagId = Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT); - if ($tags->delete($tagId)) { - $deleteSuccess = true; - } else { - $deleteSuccess = false; - } -} - -$tagData = $tags->getAllTags(); - -$templateVars = [ - 'adminHeaderTags' => Translation::get('ad_entry_tags'), - 'csrfToken' => Token::getInstance($container->get('session'))->getTokenInput('tags'), - 'isDelete' => 'delete-tag' === $action, - 'isDeleteSuccess' => $deleteSuccess ?? false, - 'msgDeleteSuccess' => Translation::get('ad_tag_delete_success'), - 'msgDeleteError' => Translation::get('ad_tag_delete_error'), - 'tags' => $tagData, - 'noTags' => Translation::get('ad_news_nodata'), - 'buttonEdit' => Translation::get('ad_user_edit'), - 'msgConfirm' => Translation::get('ad_user_del_3'), - 'buttonDelete' => Translation::get('msgDelete'), -]; - -echo $template->render($templateVars); - -if (!$user->perm->hasPermission($user->getUserId(), PermissionType::FAQ_EDIT->value)) { - require __DIR__ . '/no-permission.php'; -} - diff --git a/phpmyfaq/assets/templates/admin/content/tags.twig b/phpmyfaq/assets/templates/admin/content/tags.twig index 6cffd16009..1fdb6ce2fa 100644 --- a/phpmyfaq/assets/templates/admin/content/tags.twig +++ b/phpmyfaq/assets/templates/admin/content/tags.twig @@ -1,58 +1,61 @@ -