Skip to content

Commit

Permalink
refactor: migrated open questions page to controller (#3257)
Browse files Browse the repository at this point in the history
  • Loading branch information
thorsten committed Dec 2, 2024
1 parent 39cdf8d commit 0058aac
Show file tree
Hide file tree
Showing 19 changed files with 292 additions and 183 deletions.
2 changes: 1 addition & 1 deletion nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ server {
rewrite admin/api/(.*) /admin/api/index.php last;

# Administration pages
rewrite admin/(attachments|backup|comments|configuration|elasticsearch|export|glossary|group|import|instance|instances|news|password|session-keep-alive|statistics|stopwords|system|tags|update|user) /admin/front.php last;
rewrite admin/(attachments|backup|comments|configuration|elasticsearch|export|glossary|group|import|instance|instances|news|password|questions|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;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"type": "module",
"scripts": {
"build": "vite build",
"build:watch": "vite build --watch -d",
"build:watch": "vite build --watch",
"build:prod": "vite build",
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
Expand Down
2 changes: 1 addition & 1 deletion phpmyfaq/.htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -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|comments|configuration|elasticsearch|export|glossary|group|import|instance|instances|password|news|session-keep-alive|statistics|stopwords|system|tags|update|user) admin/front.php [L,QSA]
RewriteRule ^admin/(attachments|backup|comments|configuration|elasticsearch|export|glossary|group|import|instance|instances|news|password|questions|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
Expand Down
1 change: 1 addition & 0 deletions phpmyfaq/admin/assets/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './faqs';
export * from './glossary';
export * from './group';
export * from './news';
export * from './question';
export * from './statistics';
export * from './tags';
export * from './upgrade';
Expand Down
34 changes: 34 additions & 0 deletions phpmyfaq/admin/assets/src/api/question.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Fetch data for open questions management
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at https://mozilla.org/MPL/2.0/.
*
* @package phpMyFAQ
* @author Thorsten Rinne <[email protected]>
* @copyright 2024 phpMyFAQ Team
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
* @link https://www.phpmyfaq.de
* @since 2024-12-02
*/

export const toggleQuestionVisibility = async (questionId, visibility, csrfToken) => {
try {
const response = await fetch(`./api/question/visibility/toggle`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
questionId: questionId,
visibility: visibility,
csrfToken: csrfToken,
}),
});

return await response.json();
} catch (error) {
console.error(error);
}
};
29 changes: 29 additions & 0 deletions phpmyfaq/admin/assets/src/content/question.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
* @link https://www.phpmyfaq.de
* @since 2023-03-04
*/

import { addElement, serialize } from '../../../../assets/src/utils';
import { toggleQuestionVisibility } from '../api/index.js';
import { pushErrorNotification } from '../utils/index.js';

export const handleOpenQuestions = () => {
const deleteButton = document.getElementById('pmf-delete-questions');
Expand Down Expand Up @@ -62,3 +65,29 @@ export const handleOpenQuestions = () => {
});
}
};

export const handleToggleVisibility = () => {
const toggleVisibility = document.querySelectorAll('.pmf-toggle-visibility');

if (toggleVisibility) {
toggleVisibility.forEach((element) => {
element.addEventListener('click', async (event) => {
event.preventDefault();

const questionId = element.getAttribute('data-pmf-question-id');
const visibility = element.getAttribute('data-pmf-visibility');
const csrfToken = element.getAttribute('data-pmf-csrf');

const response = await toggleQuestionVisibility(questionId, visibility, csrfToken);

if (response.success) {
element.innerText = response.success;
} else {
pushErrorNotification(response.error);
}

console.log(questionId, visibility, csrfToken);
});
});
}
};
2 changes: 2 additions & 0 deletions phpmyfaq/admin/assets/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
handleSaveFaqData,
handleUpdateQuestion,
handleRefreshAttachments,
handleToggleVisibility,
} from './content';
import { handleUserList, handleUsers } from './user';
import { handleGroups } from './group';
Expand Down Expand Up @@ -111,6 +112,7 @@ document.addEventListener('DOMContentLoaded', async () => {

// Content → Open questions
handleOpenQuestions();
handleToggleVisibility();

// Content → Attachments
handleDeleteAttachments();
Expand Down
2 changes: 1 addition & 1 deletion phpmyfaq/admin/header.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
'stickyfaqs',
'stickyRecordsHeader'
);
$secLevelEntries['content'] .= $adminHelper->addMenuEntry('delquestion', 'question', 'ad_menu_open');
$secLevelEntries['content'] .= $adminHelper->addMenuEntry('delquestion', 'question', 'ad_menu_open', 'questions');
$secLevelEntries['content'] .= $adminHelper->addMenuEntry('delcomment', 'comments', 'ad_menu_comments', 'comments');
$secLevelEntries['content'] .= $adminHelper->addMenuEntry(
'addattachment+editattachment+delattachment',
Expand Down
3 changes: 0 additions & 3 deletions phpmyfaq/admin/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,6 @@
case 'copyentry':
require 'faqs.editor.php';
break;
case 'question':
require 'open-questions.php';
break;
case 'stickyfaqs':
require 'stickyfaqs.php';
break;
Expand Down
88 changes: 0 additions & 88 deletions phpmyfaq/admin/open-questions.php

This file was deleted.

140 changes: 71 additions & 69 deletions phpmyfaq/assets/templates/admin/content/open-questions.twig
Original file line number Diff line number Diff line change
@@ -1,78 +1,80 @@
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">
<i aria-hidden="true" class="bi bi-question-circle"></i>
{{ msgOpenQuestions }}
</h1>
</div>
{% extends '@admin/index.twig' %}

<div class="row">
<div class="col-lg-12">
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">
<i aria-hidden="true" class="bi bi-question-circle"></i>
{{ msgOpenQuestions }}
</h1>
</div>

<div class="row">
<div class="col-lg-12">

<div id="returnMessage"></div>
<div id="returnMessage"></div>

<form id="phpmyfaq-open-questions" name="phpmyfaq-open-questions" method="post" accept-charset="utf-8">
<input type="hidden" id="pmf-csrf-token" name="pmf-csrf-token" value="{{ csrfTokenDeleteQuestion }}">
<form id="phpmyfaq-open-questions" name="phpmyfaq-open-questions" method="post" accept-charset="utf-8">
<input type="hidden" id="pmf-csrf-token" name="pmf-csrf-token" value="{{ csrfTokenDeleteQuestion }}">

<table class="table table-striped align-middle border shadow">
<thead>
<tr>
<th></th>
<th>{{ msgAuthor }}</th>
<th>{{ msgQuestion }}</th>
<th colspan="2">{{ msgVisibility }}?</th>
</tr>
</thead>
<tbody>
{% for question in questions %}
<table class="table table-striped align-middle border shadow">
<thead>
<tr>
<td>
<label>
<input id="questions[]" name="questions[]" value="{{ question.id }}" type="checkbox">
</label>
</td>
<td>
{{ question.created | format_datetime(locale=currentLocale) }}
<br>
<a href="mailto:{{ question.email }}">
{{ question.username }}
</a>
</td>
<td>
<strong>
{{ question.categoryId | categoryName }}
</strong>
<br>
{{ question.question }}
</td>
<td>
<a href="?action=question&id={{ question.id }}&is_visible=toggle&csrf={{ csrfTokenToggleVisibility }}"
class="btn btn-info">
{{ question.isVisible == 'Y' ? yes : no }}
</a>
</td>
<td>
{% if enableCloseQuestion and question.answerId %}
<a href="?action=editentry&amp;id={{ question.answerId }}&amp;lang={{ currentLocale }}"
class="btn btn-success">
{{ msg2answerFAQ }}
</a>
{% else %}
<a href="?action=takequestion&amp;id={{ question.id }}" class="btn btn-success">
{{ msgTakeQuestion }}
</a>
{% endif %}
</td>
<th></th>
<th>{{ msgAuthor }}</th>
<th>{{ msgQuestion }}</th>
<th colspan="2">{{ msgVisibility }}?</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for question in questions %}
<tr>
<td>
<label>
<input id="questions[]" name="questions[]" value="{{ question.id }}" type="checkbox">
</label>
</td>
<td>
{{ question.created | format_datetime(locale=currentLocale) }}
<br>
<a href="mailto:{{ question.email }}">
{{ question.username }}
</a>
</td>
<td>
<h6>{{ question.categoryId | categoryName }}</h6>
{{ question.question }}
</td>
<td>
<button type="button" class="btn btn-info pmf-toggle-visibility"
data-pmf-visibility="{{ question.isVisible == 'Y' ? 'no' : 'yes' }}"
data-pmf-question-id="{{ question.id }}" data-pmf-csrf="{{ csrfTokenToggleVisibility }}">
{{ question.isVisible == 'Y' ? yes : no }}
</button>
</td>
<td>
{% if enableCloseQuestion and question.answerId %}
<a href="./faq/edit/{{ question.answerId }}/{{ currentLocale }}"
class="btn btn-success">
{{ msg2answerFAQ }}
</a>
{% else %}
<a href="./faq/add/{{ question.id }}" class="btn btn-success">
{{ msgTakeQuestion }}
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>

<div class="text-end">
<button class="btn btn-danger" id="pmf-delete-questions" type="button">
{{ msgDeleteAllOpenQuestions }}
</button>
</div>
<div class="text-end my-4">
<button class="btn btn-danger" id="pmf-delete-questions" type="button">
{{ msgDeleteAllOpenQuestions }}
</button>
</div>

</form>
</form>
</div>
</div>
</div>
{% endblock %}
5 changes: 5 additions & 0 deletions phpmyfaq/src/admin-api-routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@
'controller' => [QuestionController::class, 'delete'],
'methods' => 'DELETE'
],
'admin.api.question.toggle' => [
'path' => '/question/visibility/toggle',
'controller' => [QuestionController::class, 'toggle'],
'methods' => 'PUT'
],
// Search API
'admin.api.search.term' => [
'path' => '/search/term',
Expand Down
Loading

0 comments on commit 0058aac

Please sign in to comment.