425 lines
24 KiB
PHP
425 lines
24 KiB
PHP
<?php
|
|
$enablePrototypeComments = true;
|
|
include '../../header-invoice.php';
|
|
?>
|
|
|
|
<div class="container-xxl flex-grow-1 container-p-y">
|
|
|
|
<h4 class="fw-bold py-3 mb-4">
|
|
<span class="text-muted fw-light">Zarządzanie zespołem / <a href="app-permissions.php"
|
|
class="text-muted text-decoration-none">Uprawnienia</a> /</span> invoice.magico (ACL)
|
|
</h4>
|
|
|
|
<!-- Nagłówek kontekstu -->
|
|
<div class="card mb-4">
|
|
<div class="card-body d-flex flex-column flex-md-row align-items-md-center justify-content-between">
|
|
<div class="d-flex align-items-center mb-3 mb-md-0">
|
|
<div
|
|
class="avatar avatar-lg bg-label-primary rounded p-2 me-3 d-flex align-items-center justify-content-center">
|
|
<i class="bx bx-receipt fs-2"></i>
|
|
</div>
|
|
<div>
|
|
<h5 class="mb-1 fw-bold">invoice.magico</h5>
|
|
<p class="text-muted small mb-0">Zarządzaj macierzą uprawnień systemowych (ACL) dla modułu
|
|
księgowego. Każda kolumna to Grupa a każdy wiersz to konkretna funkcja dostępna w aplikacji.
|
|
Właściciel posiada niemodyfikowalny, pełny dostęp.</p>
|
|
</div>
|
|
</div>
|
|
<div class="ms-md-4">
|
|
<button class="btn btn-outline-secondary" onclick="window.location.href='app-groups.php'">
|
|
<i class="bx bx-group me-1"></i> Zarządzaj grupami
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tabela Macierzy (ACL Matrix) -->
|
|
<div class="card">
|
|
<div
|
|
class="card-header border-bottom d-flex flex-column flex-md-row justify-content-between align-items-md-center">
|
|
<h5 class="m-0 mb-3 mb-md-0">Macierz uprawnień</h5>
|
|
<div class="d-flex flex-wrap gap-2 flex-grow-1 ms-md-4 justify-content-end">
|
|
<div class="dropdown flex-grow-1" style="max-width: 250px;">
|
|
<button
|
|
class="btn btn-outline-secondary dropdown-toggle w-100 text-start d-flex justify-content-between align-items-center"
|
|
type="button" id="columnFilterDropdown" data-bs-toggle="dropdown" data-bs-auto-close="outside"
|
|
aria-expanded="false">
|
|
<span><i class="bx bx-filter-alt me-1"></i> Wybierz grupy</span>
|
|
</button>
|
|
<div class="dropdown-menu p-3" aria-labelledby="columnFilterDropdown" style="min-width: 250px;">
|
|
<h6 class="dropdown-header px-0 text-uppercase fw-bold pt-0">Wyświetlane kolumny (max 5)</h6>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input column-toggle" type="checkbox" value="1" id="col_1" checked>
|
|
<label class="form-check-label" for="col_1">Właściciel </label>
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input column-toggle" type="checkbox" value="2" id="col_2" checked>
|
|
<label class="form-check-label" for="col_2">Kadra Kierownicza</label>
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input column-toggle" type="checkbox" value="3" id="col_3" checked>
|
|
<label class="form-check-label" for="col_3">Dział Marketingu</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input column-toggle" type="checkbox" value="4" id="col_4" checked>
|
|
<label class="form-check-label" for="col_4">Dział Obsługi Klienta</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="input-group input-group-merge" style="max-width: 250px;">
|
|
<span class="input-group-text"><i class="bx bx-search"></i></span>
|
|
<input type="text" class="form-control form-control-sm" placeholder="Szukaj uprawnienia...">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-responsive text-nowrap pb-2">
|
|
<!-- Dodana klasa acl-table dla łatwiejszego stylowania przez JS -->
|
|
<table class="table table-hover table-bordered mb-0 acl-table">
|
|
<thead class="table-light align-middle sticky-top" style="z-index: 10;">
|
|
<tr>
|
|
<th style="min-width: 250px;">Moduł i Nazwa Uprawnienia</th>
|
|
<th class="text-center" style="width: 150px;">
|
|
<i class="bx bx-crown text-warning fs-5 mb-1 d-block"></i>
|
|
Właściciel <br>
|
|
<span class="badge bg-label-secondary mt-1">N/D</span>
|
|
</th>
|
|
<th class="text-center" style="width: 150px;">
|
|
<i class="bx bx-briefcase text-primary fs-5 mb-1 d-block"></i>
|
|
Kadra Kierownicza
|
|
</th>
|
|
<th class="text-center" style="width: 150px;">
|
|
<i class="bx bx-broadcast text-info fs-5 mb-1 d-block"></i>
|
|
Dział Marketingu
|
|
</th>
|
|
<th class="text-center" style="width: 150px;">
|
|
<i class="bx bx-support text-success fs-5 mb-1 d-block"></i>
|
|
Dział Obsługi Klienta
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="table-border-bottom-0">
|
|
|
|
<!-- SEKCJA: GŁÓWNE -->
|
|
<tr class="table-secondary border-top-2 border-bottom-2">
|
|
<td colspan="5" class="fw-bold fs-6 text-uppercase tracking-wider">
|
|
<i class="bx bx-power-off me-2 text-muted"></i> Dostęp do modułu
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="global-access-row">
|
|
<td>
|
|
<h6 class="mb-0 text-body">Dostęp do aplikacji</h6>
|
|
<small class="text-muted">Główny włącznik modułu dla tej grupy. Wyłączenie blokuje poniższe
|
|
opcje.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0 global-access-checkbox" type="checkbox" checked
|
|
style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0 global-access-checkbox" type="checkbox"
|
|
style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0 global-access-checkbox" type="checkbox" checked
|
|
style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- SEKCJA: FAKTURY -->
|
|
<tr class="table-secondary border-top-2 border-bottom-2">
|
|
<td colspan="5" class="fw-bold fs-6 text-uppercase tracking-wider">
|
|
<i class="bx bx-file me-2 text-muted"></i> Dokumenty Sprzedaży (Faktury)
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Odczyt plików i listy faktur</h6>
|
|
<small class="text-muted">Pozwala m.in przeglądać ekran głównego listingu.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Wystawianie nowych</h6>
|
|
<small class="text-muted">Ręczne kreowanie faktur przez formularz.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Trwałe usunięcie (Delete)</h6>
|
|
<small class="text-muted">Prawo do kasacji dokumentów z bazy danych.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- SEKCJA: BAZA KONTRAHENTÓW -->
|
|
<tr class="table-secondary border-top-2 border-bottom-2">
|
|
<td colspan="5" class="fw-bold fs-6 text-uppercase tracking-wider">
|
|
<i class="bx bx-buildings me-2 text-muted"></i> Baza Kontrahentów (CRM)
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Przeglądanie kontrahentów</h6>
|
|
<small class="text-muted">Podstawowy dostęp do modułu z listą firm.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Dodawanie i Edycja</h6>
|
|
<small class="text-muted">Aktualizowanie adresów i nr NIP klientów.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- SEKCJA: USTAWIENIA KSIĘGOWE -->
|
|
<tr class="table-secondary border-top-2 border-bottom-2">
|
|
<td colspan="5" class="fw-bold fs-6 text-uppercase tracking-wider text-danger">
|
|
<i class="bx bx-cog me-2 text-danger"></i> Krytyczne (Ustawienia Główne)
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Edycja numeracji i rejestrów</h6>
|
|
<small class="text-muted">Pozwala edytować schematy np: FV/2026/XX.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<h6 class="mb-0 text-body">Eksport pliku JPK_V7</h6>
|
|
<small class="text-muted">Przesyłanie danych do Urzędu Skarbowego.</small>
|
|
</td>
|
|
<td class="text-center align-middle bg-label-secondary"><i
|
|
class="bx bx-check text-muted fs-4"></i></td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" checked style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
<td class="text-center align-middle">
|
|
<div class="d-flex justify-content-center align-items-center"><input
|
|
class="form-check-input m-0" type="checkbox" style="cursor: pointer;"></div>
|
|
</td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sticky Save Footer -->
|
|
<div id="footer" class="footer" style="background: #e7e7ff; position: sticky; bottom: 0px; right: 0px; z-index: 1000;">
|
|
<footer class="content-footer footer border-top">
|
|
<div class="container-xxl d-flex py-3 justify-content-center">
|
|
<a href="app-permissions.php" class="btn btn-label-secondary btn-lg me-3">Anuluj</a>
|
|
<button class="btn btn-primary btn-lg px-5">Zapisz</button>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
|
|
<div class="content-backdrop fade"></div>
|
|
|
|
<?php include '../../footer.php'; ?>
|
|
|
|
<!-- Scripts -->
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
// Podobnie jak z członkami grup, uczyńmy całe komórki klikalnymi!
|
|
const aclTds = document.querySelectorAll('.acl-table tbody tr td.text-center');
|
|
|
|
aclTds.forEach(td => {
|
|
// Pomijamy komórki szare/zablokowane (Oznaczyliśmy Właściciela jako bg-label-secondary)
|
|
if (!td.classList.contains('bg-label-secondary')) {
|
|
td.style.cursor = 'pointer';
|
|
td.addEventListener('click', function (e) {
|
|
if (e.target.tagName !== 'INPUT') {
|
|
const checkbox = this.querySelector('.form-check-input');
|
|
// Zmieniamy tylko jeśli checkbox nie jest zablokowany (disabled)
|
|
if (checkbox && !checkbox.disabled) {
|
|
checkbox.checked = !checkbox.checked;
|
|
checkbox.dispatchEvent(new Event('change'));
|
|
}
|
|
}
|
|
});
|
|
|
|
// Sprawdzanie czy w komórce jest Główny Włącznik, aby odciąć resztę w dół
|
|
const accessCheckbox = td.querySelector('.form-check-input.global-access-checkbox');
|
|
if (accessCheckbox) {
|
|
accessCheckbox.addEventListener('change', function () {
|
|
toggleColumnAccess(td.cellIndex, this.checked);
|
|
});
|
|
|
|
// Wymuś stan po wczytaniu strony, jeśli aplikacja jest odznaczona (np. marketing)
|
|
if (!accessCheckbox.checked) {
|
|
toggleColumnAccess(td.cellIndex, false);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Funkcja blokowania/odblokowania całej kolumny
|
|
function toggleColumnAccess(colIndex, isEnabled) {
|
|
const allRows = document.querySelectorAll('.acl-table tbody tr');
|
|
allRows.forEach(row => {
|
|
// Pomijamy szare wiersze podziału oraz sam wiersz głównego włącznika
|
|
if (!row.classList.contains('table-secondary') && !row.classList.contains('global-access-row') && row.cells.length > colIndex) {
|
|
const cell = row.cells[colIndex];
|
|
const checkbox = cell.querySelector('.form-check-input');
|
|
|
|
if (checkbox && !cell.classList.contains('bg-label-secondary')) {
|
|
if (!isEnabled) {
|
|
checkbox.checked = false;
|
|
checkbox.disabled = true;
|
|
cell.style.opacity = '0.4';
|
|
cell.style.pointerEvents = 'none'; // cała komórka staje się nieklikalna
|
|
} else {
|
|
checkbox.disabled = false;
|
|
cell.style.opacity = '1';
|
|
cell.style.pointerEvents = 'auto'; // przywraca klikalność
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Logika wyświetlania/ukrywania kolumn grupowych
|
|
const maxColumns = 5; // Mamy w sumie 1(nazwa) + 4 (grupy). Limit 5 grup oznacza max 6 kolumn tabeli. Zostawiłem zmienną na przyszłość.
|
|
const columnToggles = document.querySelectorAll('.column-toggle:not(:disabled)');
|
|
|
|
columnToggles.forEach(toggle => {
|
|
toggle.addEventListener('change', function () {
|
|
const checkedCount = document.querySelectorAll('.column-toggle:checked').length;
|
|
|
|
// Zabezpieczenie limitu 5 (wliczając właściciela)
|
|
if (this.checked && checkedCount > 5) {
|
|
this.checked = false;
|
|
alert('Możesz wybrać maksymalnie 5 grup do jednoczesnego wyświetlania.');
|
|
return;
|
|
}
|
|
|
|
const colIndex = parseInt(this.value);
|
|
const isVisible = this.checked;
|
|
|
|
// Ukrywamy nagłówek
|
|
const theadRow = document.querySelector('.acl-table thead tr');
|
|
if (theadRow && theadRow.cells[colIndex]) {
|
|
theadRow.cells[colIndex].style.display = isVisible ? '' : 'none';
|
|
}
|
|
|
|
// Ukrywamy komórki w ciele tabeli
|
|
const tbodyRows = document.querySelectorAll('.acl-table tbody tr');
|
|
tbodyRows.forEach(row => {
|
|
// Wiersze sekcji (szare) mają colspan=5, trzeba go dynamicznie zaktualizować
|
|
if (row.classList.contains('table-secondary')) {
|
|
const th = row.querySelector('td');
|
|
// Liczymy widoczne kolumny (nagłówek)
|
|
const visibleCols = document.querySelectorAll('.acl-table thead th:not([style*="display: none"])').length;
|
|
if (th) th.setAttribute('colspan', visibleCols || 2);
|
|
} else if (row.cells[colIndex]) {
|
|
row.cells[colIndex].style.display = isVisible ? '' : 'none';
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|