feat: Add wiki integration to task management

- Implemented a multi-select dropdown for associating tasks with wiki entries in the task edit form.
- Enhanced task popup to display related wiki entries with visibility controls based on user permissions.
- Updated the wiki main view to support bulk actions for categories, including deletion and search functionality.
- Created a new database migration for establishing many-to-many relationships between tasks and wiki entries.
- Improved styling for wiki components to enhance user experience.
- Added a new AGENTS.md file to outline communication and change management protocols.
This commit is contained in:
2026-03-03 11:52:04 +01:00
parent 447b75bf3e
commit 7c2a42a66f
13 changed files with 747 additions and 98 deletions

View File

@@ -26,6 +26,10 @@
$checklist_count = is_array( $this -> task['actions'] ) ? count( $this -> task['actions'] ) : 0;
$comments_count = is_array( $this -> task['comments'] ) ? count( $this -> task['comments'] ) : 0;
$attachments_count = is_array( $this -> task_attachments ) ? count( $this -> task_attachments ) : 0;
$popup_wiki_data = \factory\Tasks::task_wiki_entries_for_user( (int)$this -> task['id'], (int)$this -> user['id'] );
$task_wiki_entries = isset( $popup_wiki_data['entries'] ) && is_array( $popup_wiki_data['entries'] ) ? $popup_wiki_data['entries'] : [];
$wiki_visible_count = isset( $popup_wiki_data['visible_count'] ) ? (int)$popup_wiki_data['visible_count'] : 0;
$wiki_hidden_count = isset( $popup_wiki_data['hidden_count'] ) ? (int)$popup_wiki_data['hidden_count'] : 0;
?>
<?
$task_description_html = htmlspecialchars_decode( (string)$this -> task['text'] );
@@ -74,6 +78,7 @@
<a href="#" class="js-task-tab-btn" data-tab="checklist" role="tab" aria-selected="false">Lista kontrolna (<?= (int)$checklist_count;?>)</a>
<a href="#" class="js-task-tab-btn" data-tab="comments" role="tab" aria-selected="false">Komentarze (<?= (int)$comments_count;?>)</a>
<a href="#" class="js-task-tab-btn" data-tab="attachments" role="tab" aria-selected="false">Za&#322;&#261;czniki (<?= (int)$attachments_count;?>)</a>
<a href="#" class="js-task-tab-btn" data-tab="wiki" role="tab" aria-selected="false">Wiki (<?= (int)$wiki_visible_count;?>)</a>
<? if ( $this -> user['id'] == 1 ):?>
<a href="#" class="js-task-tab-btn" data-tab="users" role="tab" aria-selected="false">Uczestnicy</a>
<? endif;?>
@@ -177,6 +182,35 @@
</ul>
</div>
</div>
<div class="task-tab-panel" data-tab="wiki">
<div class="box">
<h3>Powiazane wpisy Wiki</h3>
<? if ( $wiki_hidden_count > 0 ):?>
<div class="alert alert-warning" style="margin-bottom: 12px;">
Nie masz dostepu do <?= (int)$wiki_hidden_count;?> powiazanych wpisow Wiki.
</div>
<? endif;?>
<? if ( is_array( $task_wiki_entries ) and count( $task_wiki_entries ) ):?>
<div class="task-wiki-list">
<? foreach ( $task_wiki_entries as $wiki_entry ):?>
<div class="task-wiki-entry">
<h4><?= htmlspecialchars( (string)$wiki_entry['name'] );?></h4>
<div class="task-wiki-content">
<?= (string)$wiki_entry['text'];?>
<? if ( $this -> user['id'] == 1 or $this -> user['id'] == 3 ):?>
<? if ( isset( $wiki_entry['text_admin'] ) and (string)$wiki_entry['text_admin'] !== '' ):?>
<div class="task-wiki-admin"><?= (string)$wiki_entry['text_admin'];?></div>
<? endif;?>
<? endif;?>
</div>
</div>
<? endforeach;?>
</div>
<? else:?>
<div class="task-wiki-empty">Brak widocznych wpisow Wiki dla tego zadania.</div>
<? endif;?>
</div>
</div>
<? if ( $this -> user['id'] == 1 ):?>
<div class="task-tab-panel" data-tab="users">
<div class="task-users-edit">
@@ -407,6 +441,36 @@
font-weight: 600;
}
.task_popup .task_details .task-wiki-list {
display: grid;
gap: 12px;
}
.task_popup .task_details .task-wiki-entry {
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 12px;
background: #fff;
}
.task_popup .task_details .task-wiki-entry h4 {
margin: 0 0 8px 0;
font-size: 14px;
font-weight: 700;
color: #1f3d72;
}
.task_popup .task_details .task-wiki-content {
font-size: 13px;
line-height: 1.5;
}
.task_popup .task_details .task-wiki-admin {
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed #d1d5db;
}
.task_popup .task_details .task-wiki-empty {
color: #6b7280;
font-style: italic;
}
/* Lightbox - powiększanie zdjęć w opisie */
.task_popup .task_details .description img {
cursor: zoom-in;
@@ -676,8 +740,16 @@
if ( !tab_panels.length )
return;
var allowed_tabs = [ 'description', 'checklist', 'comments', 'attachments', 'users' ];
var selected_tab = allowed_tabs.indexOf( tab_name ) >= 0 ? tab_name : 'description';
var available_tabs = [];
tab_buttons.each( function() {
var tab = $( this ).attr( 'data-tab' );
if ( tab )
available_tabs.push( tab );
});
var selected_tab = available_tabs.indexOf( tab_name ) >= 0 ? tab_name : 'description';
if ( available_tabs.indexOf( selected_tab ) < 0 && available_tabs.length )
selected_tab = available_tabs[0];
tab_panels.each( function() {
var panel = $( this );