Revert to version 21fc1b6
This commit is contained in:
parent
779f35f634
commit
4acc5b8118
@ -27,7 +27,7 @@ class WorkflowEngine {
|
|||||||
$where_clauses[] = "p.bni_group_id = :group_id";
|
$where_clauses[] = "p.bni_group_id = :group_id";
|
||||||
$params[':group_id'] = $groupId;
|
$params[':group_id'] = $groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($activeProcessDefinitionId) {
|
if ($activeProcessDefinitionId) {
|
||||||
$terminal_statuses = ['positive', 'negative', 'completed', 'error', 'inactive'];
|
$terminal_statuses = ['positive', 'negative', 'completed', 'error', 'inactive'];
|
||||||
$in_clause = implode(',', array_map([$this->pdo, 'quote'], $terminal_statuses));
|
$in_clause = implode(',', array_map([$this->pdo, 'quote'], $terminal_statuses));
|
||||||
@ -47,7 +47,6 @@ class WorkflowEngine {
|
|||||||
$stmt_people = $this->pdo->prepare($sql_people);
|
$stmt_people = $this->pdo->prepare($sql_people);
|
||||||
$stmt_people->execute($params);
|
$stmt_people->execute($params);
|
||||||
$people = $stmt_people->fetchAll(PDO::FETCH_ASSOC);
|
$people = $stmt_people->fetchAll(PDO::FETCH_ASSOC);
|
||||||
$person_ids = array_column($people, 'id');
|
|
||||||
|
|
||||||
// 4. Fetch all process definitions with their JSON
|
// 4. Fetch all process definitions with their JSON
|
||||||
$stmt_defs = $this->pdo->prepare("SELECT id, name, definition_json, is_active FROM process_definitions WHERE is_active = 1 ORDER BY sort_order, name");
|
$stmt_defs = $this->pdo->prepare("SELECT id, name, definition_json, is_active FROM process_definitions WHERE is_active = 1 ORDER BY sort_order, name");
|
||||||
@ -67,6 +66,7 @@ class WorkflowEngine {
|
|||||||
|
|
||||||
// 5. Fetch instances ONLY for the filtered people
|
// 5. Fetch instances ONLY for the filtered people
|
||||||
$instances = [];
|
$instances = [];
|
||||||
|
$person_ids = array_column($people, 'id');
|
||||||
if (!empty($person_ids)) {
|
if (!empty($person_ids)) {
|
||||||
$placeholders = implode(',', array_fill(0, count($person_ids), '?'));
|
$placeholders = implode(',', array_fill(0, count($person_ids), '?'));
|
||||||
$stmt_instances = $this->pdo->prepare("SELECT * FROM process_instances WHERE person_id IN ($placeholders)");
|
$stmt_instances = $this->pdo->prepare("SELECT * FROM process_instances WHERE person_id IN ($placeholders)");
|
||||||
@ -74,8 +74,47 @@ class WorkflowEngine {
|
|||||||
$instances_data = $stmt_instances->fetchAll(PDO::FETCH_ASSOC);
|
$instances_data = $stmt_instances->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
foreach ($instances_data as $instance) {
|
foreach ($instances_data as $instance) {
|
||||||
// (Omitted enrichment logic for brevity - it's the same as before)
|
$enriched_instance = $instance;
|
||||||
$instances[$instance['person_id']][$instance['process_definition_id']] = $instance;
|
$def_id = $instance['process_definition_id'];
|
||||||
|
$node_id = $instance['current_node_id'];
|
||||||
|
|
||||||
|
$definition = $definition_map[$def_id] ?? null;
|
||||||
|
|
||||||
|
if ($definition && isset($definition['type']) && $definition['type'] === 'checklist') {
|
||||||
|
$tasks = $definition['tasks'] ?? [];
|
||||||
|
$instanceData = $instance['data_json'] ? json_decode($instance['data_json'], true) : [];
|
||||||
|
$totalTasks = count($tasks);
|
||||||
|
$completedTasks = 0;
|
||||||
|
if(is_array($instanceData)) {
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
if (!empty($instanceData[$task['code']])) {
|
||||||
|
$completedTasks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($totalTasks > 0 && $completedTasks === $totalTasks) {
|
||||||
|
$status = 'completed';
|
||||||
|
} elseif ($completedTasks > 0) {
|
||||||
|
$status = 'in_progress';
|
||||||
|
} else {
|
||||||
|
$status = 'inactive';
|
||||||
|
}
|
||||||
|
$enriched_instance['computed_status'] = $status;
|
||||||
|
$enriched_instance['computed_reason'] = "$completedTasks/$totalTasks completed";
|
||||||
|
$enriched_instance['computed_next_step'] = '';
|
||||||
|
} else if ($definition && isset($definition['nodes'][$node_id])) {
|
||||||
|
$node_info = $definition['nodes'][$node_id];
|
||||||
|
$enriched_instance['computed_status'] = $node_info['ui_hints']['status'] ?? $instance['current_status'];
|
||||||
|
$enriched_instance['computed_reason'] = $node_info['ui_hints']['reason'] ?? $instance['current_reason'];
|
||||||
|
$enriched_instance['computed_next_step'] = $node_info['ui_hints']['next_step'] ?? $instance['suggested_next_step'];
|
||||||
|
} else {
|
||||||
|
$enriched_instance['computed_status'] = $instance['current_status'];
|
||||||
|
$enriched_instance['computed_reason'] = $instance['current_reason'];
|
||||||
|
$enriched_instance['computed_next_step'] = $instance['suggested_next_step'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$instances[$instance['person_id']][$def_id] = $enriched_instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +131,19 @@ class WorkflowEngine {
|
|||||||
$stmt_bni_groups = $this->pdo->query("SELECT * FROM bni_groups ORDER BY name");
|
$stmt_bni_groups = $this->pdo->query("SELECT * FROM bni_groups ORDER BY name");
|
||||||
$bni_groups = $stmt_bni_groups->fetchAll(PDO::FETCH_ASSOC);
|
$bni_groups = $stmt_bni_groups->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// 7. Fetch Spotkania columns (upcoming meetings)
|
||||||
|
$today = date('Y-m-d H:i:s');
|
||||||
|
$stmt_meetings = $this->pdo->prepare("
|
||||||
|
SELECT bni_groups.id as group_id, bni_groups.name as group_name, MIN(calendar_events.start_datetime) as next_meeting_date
|
||||||
|
FROM bni_groups
|
||||||
|
LEFT JOIN calendar_event_groups ON bni_groups.id = calendar_event_groups.bni_group_id
|
||||||
|
LEFT JOIN calendar_events ON calendar_event_groups.calendar_event_id = calendar_events.id AND calendar_events.start_datetime >= :today
|
||||||
|
GROUP BY bni_groups.id
|
||||||
|
ORDER BY bni_groups.name
|
||||||
|
");
|
||||||
|
$stmt_meetings->execute(['today' => $today]);
|
||||||
|
$spotkania_cols = $stmt_meetings->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'people' => $people,
|
'people' => $people,
|
||||||
'definitions' => array_values($definitions),
|
'definitions' => array_values($definitions),
|
||||||
@ -99,12 +151,11 @@ class WorkflowEngine {
|
|||||||
'all_functions' => $all_functions,
|
'all_functions' => $all_functions,
|
||||||
'person_functions_map' => $person_functions_map,
|
'person_functions_map' => $person_functions_map,
|
||||||
'bni_groups' => $bni_groups,
|
'bni_groups' => $bni_groups,
|
||||||
'spotkania_cols' => [],
|
'spotkania_cols' => $spotkania_cols, // Add this to the return array
|
||||||
'meetings' => [],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startProcess(string $processCode, int $personId, int $userId): int {
|
public function startProcess(string $processCode, int $personId, int $userId): int {
|
||||||
$this->pdo->beginTransaction();
|
$this->pdo->beginTransaction();
|
||||||
try {
|
try {
|
||||||
// 1. Find active process definition by code.
|
// 1. Find active process definition by code.
|
||||||
@ -677,8 +728,6 @@ class WorkflowEngine {
|
|||||||
$instance['data_json'] = $newDataJson;
|
$instance['data_json'] = $newDataJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function deleteInstance(int $instanceId): void {
|
public function deleteInstance(int $instanceId): void {
|
||||||
$this->pdo->beginTransaction();
|
$this->pdo->beginTransaction();
|
||||||
try {
|
try {
|
||||||
@ -696,5 +745,4 @@ class WorkflowEngine {
|
|||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'db/config.php';
|
|
||||||
$pdo = db();
|
|
||||||
$email = 'testadmin@example.com';
|
|
||||||
$password = 'password';
|
|
||||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO people (first_name, last_name, email, password, role, is_user, active) VALUES ('Test', 'Admin', ?, ?, 'admin', TRUE, TRUE) ON DUPLICATE KEY UPDATE password = VALUES(password)");
|
|
||||||
$stmt->execute([$email, $hashed_password]);
|
|
||||||
|
|
||||||
echo "Created or updated admin user with email: $email and password: $password";
|
|
||||||
?>
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'db/config.php';
|
|
||||||
require_once 'WorkflowEngine.php';
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
$groupId = isset($_GET['group_id']) ? (int)$_GET['group_id'] : 0;
|
|
||||||
$offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
|
|
||||||
|
|
||||||
if (!$groupId) {
|
|
||||||
echo json_encode(['success' => false, 'error' => 'Group ID is required.']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$workflowEngine = new WorkflowEngine();
|
|
||||||
$meetings = $workflowEngine->getGroupMeetings($groupId, $offset, 1);
|
|
||||||
|
|
||||||
if (empty($meetings)) {
|
|
||||||
echo json_encode(['success' => false, 'error' => 'No more meetings found.']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$meeting = $meetings[0];
|
|
||||||
|
|
||||||
// also get group name
|
|
||||||
$stmt = db()->prepare("SELECT name FROM bni_groups WHERE id = ?");
|
|
||||||
$stmt->execute([$groupId]);
|
|
||||||
$group_name = $stmt->fetchColumn();
|
|
||||||
|
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'meeting' => $meeting, 'group_name' => $group_name]);
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'WorkflowEngine.php';
|
|
||||||
|
|
||||||
$personId = $_GET['personId'] ?? null;
|
|
||||||
$meetingId = $_GET['meetingId'] ?? null;
|
|
||||||
|
|
||||||
if (!$personId || !$meetingId) {
|
|
||||||
die('Person ID and Meeting ID are required.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$workflowEngine = new WorkflowEngine();
|
|
||||||
$db = db();
|
|
||||||
|
|
||||||
// Fetch person details
|
|
||||||
$stmt_person = $db->prepare("SELECT * FROM people WHERE id = :id");
|
|
||||||
$stmt_person->execute([':id' => $personId]);
|
|
||||||
$person = $stmt_person->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Fetch meeting details
|
|
||||||
$stmt_meeting = $db->prepare("SELECT m.*, bg.name as group_name FROM meetings m JOIN bni_groups bg ON m.group_id = bg.id WHERE m.id = :id");
|
|
||||||
$stmt_meeting->execute([':id' => $meetingId]);
|
|
||||||
$meeting = $stmt_meeting->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Fetch attendance details
|
|
||||||
$stmt_attendance = $db->prepare("SELECT * FROM meeting_attendance WHERE person_id = :person_id AND meeting_id = :meeting_id");
|
|
||||||
$stmt_attendance->execute([':person_id' => $personId, ':meeting_id' => $meetingId]);
|
|
||||||
$attendance = $stmt_attendance->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
$is_member = $person['bni_group_id'] == $meeting['group_id'];
|
|
||||||
|
|
||||||
if (!$attendance) {
|
|
||||||
$attendance = [
|
|
||||||
'attendance_status' => $is_member ? 'present' : 'n/a',
|
|
||||||
'guest_survey' => null
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<h4>Meeting Attendance</h4>
|
|
||||||
<p><strong>Person:</strong> <?= htmlspecialchars($person['first_name'].' '.$person['last_name']) ?></p>
|
|
||||||
<p><strong>Meeting:</strong> <?= htmlspecialchars($meeting['group_name']) ?> on <?= date('d/m/Y', strtotime($meeting['meeting_date'])) ?></p>
|
|
||||||
|
|
||||||
<form id="meetingAttendanceForm" action="_update_meeting_attendance.php" method="post">
|
|
||||||
<input type="hidden" name="person_id" value="<?= $personId ?>">
|
|
||||||
<input type="hidden" name="meeting_id" value="<?= $meetingId ?>">
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="attendance_status" class="form-label">Attendance Status</label>
|
|
||||||
<select class="form-select" id="attendance_status" name="attendance_status">
|
|
||||||
<option value="present" <?= ($attendance['attendance_status'] == 'present') ? 'selected' : '' ?>>Present</option>
|
|
||||||
<option value="absent" <?= ($attendance['attendance_status'] == 'absent') ? 'selected' : '' ?>>Absent</option>
|
|
||||||
<option value="substitute" <?= ($attendance['attendance_status'] == 'substitute') ? 'selected' : '' ?>>Substitute</option>
|
|
||||||
<option value="n/a" <?= ($attendance['attendance_status'] == 'n/a') ? 'selected' : '' ?>>N/A</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// The guest survey is only applicable if the person is not a member of the group.
|
|
||||||
$is_guest = !$is_member;
|
|
||||||
// The survey div should be visible only if the guest is present.
|
|
||||||
$show_survey = $is_guest && ($attendance['attendance_status'] == 'present');
|
|
||||||
?>
|
|
||||||
<div id="guest_survey_div" class="mb-3" style="display: <?= $show_survey ? 'block' : 'none' ?>;">
|
|
||||||
<label for="guest_survey" class="form-label">Guest Survey</label>
|
|
||||||
<select class="form-select" id="guest_survey" name="guest_survey">
|
|
||||||
<option value="" <?= (is_null($attendance['guest_survey'])) ? 'selected' : '' ?>>Not applicable</option>
|
|
||||||
<option value="1" <?= ($attendance['guest_survey'] == '1') ? 'selected' : '' ?>>1</option>
|
|
||||||
<option value="2" <?= ($attendance['guest_survey'] == '2') ? 'selected' : '' ?>>2</option>
|
|
||||||
<option value="3" <?= ($attendance['guest_survey'] == '3') ? 'selected' : '' ?>>3</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Save</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.getElementById('attendance_status').addEventListener('change', function() {
|
|
||||||
var guestSurveyDiv = document.getElementById('guest_survey_div');
|
|
||||||
var isGuest = <?= json_encode($is_guest) ?>;
|
|
||||||
if (this.value === 'present' && isGuest) {
|
|
||||||
guestSurveyDiv.style.display = 'block';
|
|
||||||
} else {
|
|
||||||
guestSurveyDiv.style.display = 'none';
|
|
||||||
document.getElementById('guest_survey').value = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('meetingAttendanceForm').addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var formData = new FormData(this);
|
|
||||||
fetch('_update_meeting_attendance.php', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
var instanceModal = bootstrap.Modal.getInstance(document.getElementById('instanceModal'));
|
|
||||||
instanceModal.hide();
|
|
||||||
// Find the dot and update its color
|
|
||||||
let dot = document.querySelector(`span[data-person-id='${formData.get('person_id')}'][data-meeting-id='${formData.get('meeting_id')}']`);
|
|
||||||
if (dot) {
|
|
||||||
const status_color_map = {
|
|
||||||
'present': 'success',
|
|
||||||
'absent': 'danger',
|
|
||||||
'substitute': 'warning',
|
|
||||||
'n/a': 'secondary'
|
|
||||||
};
|
|
||||||
dot.className = `badge rounded-circle bg-${status_color_map[formData.get('attendance_status')]}`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert('Failed to save attendance.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'WorkflowEngine.php';
|
|
||||||
|
|
||||||
$personId = $_POST['person_id'] ?? null;
|
|
||||||
$meetingId = $_POST['meeting_id'] ?? null;
|
|
||||||
$attendance_status = $_POST['attendance_status'] ?? null;
|
|
||||||
$guest_survey = $_POST['guest_survey'] ?? null;
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
if (!$personId || !$meetingId || !$attendance_status) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Missing required fields.']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = db();
|
|
||||||
|
|
||||||
// Check if an attendance record already exists
|
|
||||||
$stmt_check = $db->prepare("SELECT id FROM meeting_attendance WHERE person_id = :person_id AND meeting_id = :meeting_id");
|
|
||||||
$stmt_check->execute([':person_id' => $personId, ':meeting_id' => $meetingId]);
|
|
||||||
$existing_id = $stmt_check->fetchColumn();
|
|
||||||
|
|
||||||
if ($existing_id) {
|
|
||||||
// Update existing record
|
|
||||||
$stmt_update = $db->prepare("
|
|
||||||
UPDATE meeting_attendance
|
|
||||||
SET attendance_status = :attendance_status, guest_survey = :guest_survey, updated_at = NOW()
|
|
||||||
WHERE id = :id
|
|
||||||
");
|
|
||||||
$stmt_update->execute([
|
|
||||||
':attendance_status' => $attendance_status,
|
|
||||||
':guest_survey' => $guest_survey,
|
|
||||||
':id' => $existing_id
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
// Insert new record
|
|
||||||
$stmt_insert = $db->prepare("
|
|
||||||
INSERT INTO meeting_attendance (person_id, meeting_id, attendance_status, guest_survey)
|
|
||||||
VALUES (:person_id, :meeting_id, :attendance_status, :guest_survey)
|
|
||||||
");
|
|
||||||
$stmt_insert->execute([
|
|
||||||
':person_id' => $personId,
|
|
||||||
':meeting_id' => $meetingId,
|
|
||||||
':attendance_status' => $attendance_status,
|
|
||||||
':guest_survey' => $guest_survey
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($guest_survey, ['1', '2', '3'])) {
|
|
||||||
session_start();
|
|
||||||
$userId = $_SESSION['user_id'] ?? null;
|
|
||||||
if ($userId) {
|
|
||||||
$workflowEngine = new WorkflowEngine();
|
|
||||||
try {
|
|
||||||
$stmt = $db->prepare("SELECT id FROM process_definitions WHERE code = 'guest_survey_follow_up'");
|
|
||||||
$stmt->execute();
|
|
||||||
$processDefinitionId = $stmt->fetchColumn();
|
|
||||||
if($processDefinitionId) {
|
|
||||||
$workflowEngine->getOrCreateInstanceByDefId($personId, $processDefinitionId, $userId);
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log('Failed to start guest survey follow-up process: ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode(['success' => true]);
|
|
||||||
@ -1,8 +1,142 @@
|
|||||||
.meeting-nav-arrow {
|
body {
|
||||||
cursor: pointer;
|
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
user-select: none;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.meeting-nav-arrow:hover {
|
.sidebar {
|
||||||
color: #007bff;
|
position: fixed;
|
||||||
}
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 48px 0 0;
|
||||||
|
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||||
|
width: 250px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-collapsed {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-collapsed .nav-link-text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-collapsed .nav-link i {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
margin-left: 250px;
|
||||||
|
transition: margin-left 0.3s;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-collapsed {
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link.active {
|
||||||
|
color: #0d6efd;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
padding-top: .75rem;
|
||||||
|
padding-bottom: .75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: rgba(0, 0, 0, .25);
|
||||||
|
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .form-control {
|
||||||
|
padding: .75rem 1rem;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calendar styles */
|
||||||
|
.calendar {
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
.calendar td {
|
||||||
|
height: 120px;
|
||||||
|
vertical-align: top;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.calendar .day-number {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.calendar .not-month {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
.events {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
.event {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-item .nav-link {
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-fullscreen-xl {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 1400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-cell {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-details {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-details .person-group {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #198754;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dots {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|||||||
5
cookie.txt
Normal file
5
cookie.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Netscape HTTP Cookie File
|
||||||
|
# https://curl.se/docs/http-cookies.html
|
||||||
|
# This file was generated by libcurl! Edit at your own risk.
|
||||||
|
|
||||||
|
localhost FALSE / FALSE 0 PHPSESSID rfo6k0p8l4tpnmgek7dkpkopbl
|
||||||
937
dashboard.html
937
dashboard.html
@ -1,937 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>My App - Dashboard</title>
|
|
||||||
<meta name="description" content="A modern web application.">
|
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
<!-- Bootstrap Icons -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
||||||
|
|
||||||
<!-- Google Fonts -->
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom CSS -->
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=1768129608">
|
|
||||||
|
|
||||||
<!-- OG Meta Tags -->
|
|
||||||
<meta property="og:title" content="My App">
|
|
||||||
<meta property="og:description" content="A modern web application.">
|
|
||||||
<meta property="og:image" content="https://via.placeholder.com/1200x630.png?text=Visit+My+App">
|
|
||||||
<meta property="og:url" content="http://localhost">
|
|
||||||
<meta property="og:type" content="website">
|
|
||||||
|
|
||||||
<!-- Twitter Card -->
|
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
|
||||||
<meta name="twitter:title" content="My App">
|
|
||||||
<meta name="twitter:description" content="A modern web application.">
|
|
||||||
<meta name="twitter:image" content="https://via.placeholder.com/1200x630.png?text=Visit+My+App">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
|
|
||||||
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">My App</a>
|
|
||||||
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<ul class="navbar-nav flex-row px-3">
|
|
||||||
<li class="nav-item text-nowrap">
|
|
||||||
<span class="nav-link">Witaj, Test Admin</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item text-nowrap ms-2">
|
|
||||||
<a class="nav-link" href="logout.php">Wyloguj</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<nav id="sidebar" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
|
||||||
<div class="position-sticky pt-3">
|
|
||||||
<ul class="nav flex-column">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" aria-current="page" href="/">
|
|
||||||
<i class="bi bi-kanban"></i>
|
|
||||||
<span class="nav-link-text">Pulpit procesów</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link " href="calendar.php">
|
|
||||||
<i class="bi bi-calendar-event"></i>
|
|
||||||
<span class="nav-link-text">Kalendarz</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#settings-submenu" data-bs-toggle="collapse" aria-expanded="false">
|
|
||||||
<i class="bi bi-gear"></i>
|
|
||||||
<span class="nav-link-text">Ustawienia</span>
|
|
||||||
</a>
|
|
||||||
<ul class="nav flex-column collapse" id="settings-submenu" data-bs-parent="#sidebar">
|
|
||||||
<li class="nav-item submenu-item">
|
|
||||||
<a class="nav-link " href="event_types.php">
|
|
||||||
<i class="bi bi-tags"></i>
|
|
||||||
<span class="nav-link-text">Typy zdarzeń</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item submenu-item">
|
|
||||||
<a class="nav-link " href="bni_groups.php">
|
|
||||||
<i class="bi bi-people"></i>
|
|
||||||
<span class="nav-link-text">Grupy BNI</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item submenu-item">
|
|
||||||
<a class="nav-link " href="functions.php">
|
|
||||||
<i class="bi bi-person-rolodex"></i>
|
|
||||||
<span class="nav-link-text">Funkcje</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
|
|
||||||
<h1 class="h2">Dashboard</h1>
|
|
||||||
<div class="btn-toolbar mb-2 mb-md-0">
|
|
||||||
<div class="btn-group me-2" id="bulk-actions-group" style="display: none;">
|
|
||||||
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
|
||||||
Bulk Actions
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkStatusModal">Bulk Status Update</a></li>
|
|
||||||
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkEventModal">Bulk Add Event</a></li>
|
|
||||||
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkInitModal">Bulk Initialize Instances</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createPersonModal">
|
|
||||||
Create Person
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Filter by Group:</label>
|
|
||||||
<div class="btn-group" role="group" aria-label="Group Filter">
|
|
||||||
<a href="index.php?group_id=" class="btn btn-outline-primary ">All Groups</a>
|
|
||||||
<a href="index.php?group_id=2" class="btn btn-outline-primary ">
|
|
||||||
Premium </a>
|
|
||||||
<a href="index.php?group_id=3" class="btn btn-outline-primary ">
|
|
||||||
Regio </a>
|
|
||||||
<a href="index.php?group_id=1" class="btn btn-outline-primary active-filter">
|
|
||||||
Target </a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered table-sm">
|
|
||||||
<thead class="table-light">
|
|
||||||
<tr class="text-center">
|
|
||||||
<th rowspan="2" class="align-middle"><input type="checkbox" id="selectAll"></th>
|
|
||||||
<th rowspan="2" class="align-middle">Person</th>
|
|
||||||
<th colspan="4">Spotkania</th>
|
|
||||||
<th colspan="5">Inne procesy</th>
|
|
||||||
</tr>
|
|
||||||
<tr class="text-center">
|
|
||||||
<th>
|
|
||||||
Premium<br>
|
|
||||||
<small>22.01.2026</small>
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Regio<br>
|
|
||||||
<small>15.01.2026</small>
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Target<br>
|
|
||||||
<small>14.01.2026</small>
|
|
||||||
</th>
|
|
||||||
<th>Meeting Handling<br><small>11.01.2026</small></th>
|
|
||||||
<th class="">
|
|
||||||
<a href="index.php?group_id=1&active_process_id=4" class="text-decoration-none text-dark">Follow-up</a>
|
|
||||||
</th>
|
|
||||||
<th class="">
|
|
||||||
<a href="index.php?group_id=1&active_process_id=9" class="text-decoration-none text-dark">Obsługa przyjęcia nowego członka</a>
|
|
||||||
</th>
|
|
||||||
<th class="">
|
|
||||||
<a href="index.php?group_id=1&active_process_id=7" class="text-decoration-none text-dark">Wprowadzenie nowego członka</a>
|
|
||||||
</th>
|
|
||||||
<th class="">
|
|
||||||
<a href="index.php?group_id=1&active_process_id=6" class="text-decoration-none text-dark">Szkolenia dla młodego członka</a>
|
|
||||||
</th>
|
|
||||||
<th class="">
|
|
||||||
<a href="index.php?group_id=1&active_process_id=1" class="text-decoration-none text-dark">Mentoring</a>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr data-group-id="1">
|
|
||||||
<td class="text-center align-middle"><input type="checkbox" class="person-checkbox" name="person_ids[]" value="3"></td>
|
|
||||||
<td class="person-cell">
|
|
||||||
<div class="person-main">
|
|
||||||
<div class="person-name">Łukasz Jagliński</div>
|
|
||||||
<div class="person-details">
|
|
||||||
<span class="d-block">Jagliński sp. z o.o.</span>
|
|
||||||
<span class="d-block">Generalny wykonawca kubaturowy</span>
|
|
||||||
<span>Member</span>
|
|
||||||
<span class="person-group">, Grupa: Target</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="person-actions">
|
|
||||||
<div class="status-dots">
|
|
||||||
<span class="status-dot bg-success" title="GAINS Sheet"></span>
|
|
||||||
<span class="status-dot bg-danger" title="Top Wanted Contacts"></span>
|
|
||||||
<span class="status-dot bg-danger" title="Top Owned Contacts"></span>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-sm btn-secondary edit-btn" data-bs-toggle="modal" data-bs-target="#editPersonModal" data-person-id="3" data-person-name="Łukasz Jagliński">
|
|
||||||
Edit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="Status nieokreślony"></span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
<span class="badge rounded-circle bg-success" style="width: 20px; height: 20px; display: inline-block; cursor: pointer;" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-meeting-id="1" data-modal-type="meeting_attendance">
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-process-id="4">
|
|
||||||
<span class="badge rounded-circle bg-success" style="width: 20px; height: 20px; display: inline-block;" title="Positive"> </span>
|
|
||||||
<small class="text-muted d-block">10/01/26</small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-process-id="9">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-process-id="7">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-process-id="6">
|
|
||||||
<span class="badge rounded-circle bg-success" style="width: 20px; height: 20px; display: inline-block;" title="Completed"> </span>
|
|
||||||
<small class="text-muted d-block">10/01/26</small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="3" data-process-id="1">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group-id="1">
|
|
||||||
<td class="text-center align-middle"><input type="checkbox" class="person-checkbox" name="person_ids[]" value="2"></td>
|
|
||||||
<td class="person-cell">
|
|
||||||
<div class="person-main">
|
|
||||||
<div class="person-name">Beata Norkowska</div>
|
|
||||||
<div class="person-details">
|
|
||||||
<span class="d-block">Elena Catering</span>
|
|
||||||
<span class="d-block">Catering i eventy</span>
|
|
||||||
<span>Member</span>
|
|
||||||
<span class="person-group">, Grupa: Target</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="person-actions">
|
|
||||||
<div class="status-dots">
|
|
||||||
<span class="status-dot bg-danger" title="GAINS Sheet"></span>
|
|
||||||
<span class="status-dot bg-danger" title="Top Wanted Contacts"></span>
|
|
||||||
<span class="status-dot bg-danger" title="Top Owned Contacts"></span>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-sm btn-secondary edit-btn" data-bs-toggle="modal" data-bs-target="#editPersonModal" data-person-id="2" data-person-name="Beata Norkowska">
|
|
||||||
Edit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="Status nieokreślony"></span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle">
|
|
||||||
<span class="badge rounded-circle bg-success" style="width: 20px; height: 20px; display: inline-block; cursor: pointer;" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-meeting-id="1" data-modal-type="meeting_attendance">
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-process-id="4">
|
|
||||||
<span class="badge rounded-circle bg-success" style="width: 20px; height: 20px; display: inline-block;" title="Positive"> </span>
|
|
||||||
<small class="text-muted d-block">10/01/26</small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-process-id="9">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-process-id="7">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-process-id="6">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="2" data-process-id="1">
|
|
||||||
<span class="badge rounded-circle bg-secondary" style="width: 20px; height: 20px; display: inline-block;" title="None"> </span>
|
|
||||||
<small class="text-muted d-block"></small>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Edit Person Modal -->
|
|
||||||
<div class="modal fade" id="editPersonModal" tabindex="-1" aria-labelledby="editPersonModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-fullscreen-xl">
|
|
||||||
<div class="modal-content">
|
|
||||||
<form id="editPersonForm" action="_update_person.php" method="post" enctype="multipart/form-data">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="editPersonModalLabel">Edytuj osobę</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<input type="hidden" name="id" id="editPersonId">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editFirstName" class="form-label">Imię</label>
|
|
||||||
<input type="text" class="form-control" id="editFirstName" name="firstName" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editLastName" class="form-label">Nazwisko</label>
|
|
||||||
<input type="text" class="form-control" id="editLastName" name="lastName" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editPhone" class="form-label">Numer telefonu</label>
|
|
||||||
<input type="text" class="form-control" id="editPhone" name="phone">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editEmail" class="form-label">Email (login)</label>
|
|
||||||
<input type="email" class="form-control" id="editEmail" name="email">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editPassword" class="form-label">Nowe hasło</label>
|
|
||||||
<input type="password" class="form-control" id="editPassword" name="password">
|
|
||||||
<small class="form-text text-muted">Pozostaw puste, jeśli nie chcesz zmieniać hasła.</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editRole" class="form-label">Rola</label>
|
|
||||||
<select class="form-select" id="editRole" name="role" required>
|
|
||||||
<option value="admin">Admin</option>
|
|
||||||
<option value="member">Członek</option>
|
|
||||||
<option value="guest">Gość</option>
|
|
||||||
<option value="team_member">Pracownik Biura</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3" id="edit-group-selection-div" style="display: none;">
|
|
||||||
<label for="editBniGroup" class="form-label">Grupa</label>
|
|
||||||
<select class="form-select" id="editBniGroup" name="bni_group_id">
|
|
||||||
<option value="">Wybierz grupę...</option>
|
|
||||||
<option value="2">Premium</option>
|
|
||||||
<option value="3">Regio</option>
|
|
||||||
<option value="1">Target</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editRoles" class="form-label">Funkcje</label>
|
|
||||||
<select class="form-select" id="editRoles" name="functions[]" multiple size="5">
|
|
||||||
<!-- Opcje zostaną wstawione przez JavaScript -->
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editCompanyName" class="form-label">Nazwa firmy</label>
|
|
||||||
<input type="text" class="form-control" id="editCompanyName" name="companyName">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editNip" class="form-label">NIP</label>
|
|
||||||
<input type="text" class="form-control" id="editNip" name="nip">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editIndustry" class="form-label">Branża</label>
|
|
||||||
<input type="text" class="form-control" id="editIndustry" name="industry">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editCompanySize" class="form-label">Wielkość firmy / Przychody</label>
|
|
||||||
<input type="text" class="form-control" id="editCompanySize" name="company_size_revenue">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editBusinessDescription" class="form-label">Opis działalności</label>
|
|
||||||
<textarea class="form-control" id="editBusinessDescription" name="business_description" rows="3"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row member-only-fields" style="display: none;">
|
|
||||||
<hr class="mt-3">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h5>Pliki firmowe</h5>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editCompanyLogo" class="form-label">Logo firmy</label>
|
|
||||||
<input class="form-control" type="file" id="editCompanyLogo" name="company_logo">
|
|
||||||
<small id="editCompanyLogoPath" class="form-text text-muted"></small>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editPersonPhoto" class="form-label">Zdjęcie osoby</label>
|
|
||||||
<input class="form-control" type="file" id="editPersonPhoto" name="person_photo">
|
|
||||||
<small id="editPersonPhotoPath" class="form-text text-muted"></small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h5>Dokumenty członkowskie</h5>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editGainsSheet" class="form-label">Arkusz GAINS</label>
|
|
||||||
<input class="form-control" type="file" id="editGainsSheet" name="gains_sheet">
|
|
||||||
<small id="editGainsSheetPath" class="form-text text-muted"></small>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editTopWanted" class="form-label">Lista TOP poszukiwanych kontaktów</label>
|
|
||||||
<input class="form-control" type="file" id="editTopWanted" name="top_wanted_contacts">
|
|
||||||
<small id="editTopWantedPath" class="form-text text-muted"></small>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="editTopOwned" class="form-label">Lista TOP posiadanych kontaktów</label>
|
|
||||||
<input class="form-control" type="file" id="editTopOwned" name="top_owned_contacts">
|
|
||||||
<small id="editTopOwnedPath" class="form-text text-muted"></small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Zamknij</button>
|
|
||||||
<button type="submit" class="btn btn-primary">Zapisz zmiany</button>
|
|
||||||
<button type="button" class="btn btn-danger ms-auto" id="deleteUserBtn" data-bs-toggle="modal" data-bs-target="#deletePersonModal">Usuń</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Create Person Modal -->
|
|
||||||
<div class="modal fade" id="createPersonModal" tabindex="-1" aria-labelledby="createPersonModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-fullscreen-xl">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="createPersonModalLabel">Create Person</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form id="createPersonForm" action="_create_person.php" method="post" enctype="multipart/form-data">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createFirstName" class="form-label">First Name <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" id="createFirstName" name="firstName" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createLastName" class="form-label">Last Name <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" class="form-control" id="createLastName" name="lastName" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createPhone" class="form-label">Phone Number</label>
|
|
||||||
<input type="text" class="form-control" id="createPhone" name="phone">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createEmail" class="form-label">Email (Login) <span class="text-danger">*</span></label>
|
|
||||||
<input type="email" class="form-control" id="createEmail" name="email" required>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createPassword" class="form-label">Password <span class="text-danger">*</span></label>
|
|
||||||
<input type="password" class="form-control" id="createPassword" name="password" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createRole" class="form-label">Rola</label>
|
|
||||||
<select class="form-select" id="createRole" name="role" required>
|
|
||||||
<option value="admin">Admin</option>
|
|
||||||
<option value="member" selected>Członek</option>
|
|
||||||
<option value="guest">Gość</option>
|
|
||||||
<option value="team_member">Pracownik Biura</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3" id="create-group-selection-div">
|
|
||||||
<label for="createBniGroup" class="form-label">Grupa</label>
|
|
||||||
<select class="form-select" id="createBniGroup" name="bni_group_id">
|
|
||||||
<option value="">Wybierz grupę...</option>
|
|
||||||
<option value="2">Premium</option>
|
|
||||||
<option value="3">Regio</option>
|
|
||||||
<option value="1">Target</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createRoles" class="form-label">Funkcje</label>
|
|
||||||
<select class="form-select" id="createRoles" name="functions[]" multiple size="5">
|
|
||||||
<option value="1">Dyrektor Asystujący Regio</option>
|
|
||||||
<option value="2">Dyrektor Asystujący Target</option>
|
|
||||||
<option value="3">Dyrektor Asystujący Premium</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createCompanyName" class="form-label">Company Name</label>
|
|
||||||
<input type="text" class="form-control" id="createCompanyName" name="companyName">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createNip" class="form-label">NIP</label>
|
|
||||||
<input type="text" class="form-control" id="createNip" name="nip">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createIndustry" class="form-label">Branża</label>
|
|
||||||
<input type="text" class="form-control" id="createIndustry" name="industry">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createCompanySize" class="form-label">Wielkość firmy / Przychody</label>
|
|
||||||
<input type="text" class="form-control" id="createCompanySize" name="company_size_revenue">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createBusinessDescription" class="form-label">Opis działalności</label>
|
|
||||||
<textarea class="form-control" id="createBusinessDescription" name="business_description" rows="3"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row member-only-fields" style="display: none;">
|
|
||||||
<hr class="mt-3">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h5>Pliki firmowe</h5>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createCompanyLogo" class="form-label">Logo firmy</label>
|
|
||||||
<input class="form-control" type="file" id="createCompanyLogo" name="company_logo">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createPersonPhoto" class="form-label">Zdjęcie osoby</label>
|
|
||||||
<input class="form-control" type="file" id="createPersonPhoto" name="person_photo">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h5>Dokumenty członkowskie</h5>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createGainsSheet" class="form-label">Arkusz GAINS</label>
|
|
||||||
<input class="form-control" type="file" id="createGainsSheet" name="gains_sheet">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createTopWanted" class="form-label">Lista TOP poszukiwanych kontaktów</label>
|
|
||||||
<input class="form-control" type="file" id="createTopWanted" name="top_wanted_contacts">
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="createTopOwned" class="form-label">Lista TOP posiadanych kontaktów</label>
|
|
||||||
<input class="form-control" type="file" id="createTopOwned" name="top_owned_contacts">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary mt-3">Create Person</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Delete Person Modal -->
|
|
||||||
<div class="modal fade" id="deletePersonModal" tabindex="-1" aria-labelledby="deletePersonModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="deletePersonModalLabel">Potwierdź usunięcie</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Czy na pewno chcesz usunąć użytkownika <strong id="personNameToDelete"></strong>? Tej operacji nie można cofnąć.
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Anuluj</button>
|
|
||||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">Tak, usuń</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Bootstrap Bundle with Popper -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
||||||
<!-- jQuery -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
||||||
<!-- jQuery UI -->
|
|
||||||
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
|
|
||||||
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
|
|
||||||
|
|
||||||
<!-- Custom JS -->
|
|
||||||
<script src="assets/js/main.js?v=1768129608"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const sidebarLinks = document.querySelectorAll('#sidebar .nav-link');
|
|
||||||
const currentPath = window.location.pathname.split('/').pop();
|
|
||||||
|
|
||||||
sidebarLinks.forEach(link => {
|
|
||||||
const linkPath = link.getAttribute('href').split('/').pop();
|
|
||||||
if (linkPath === currentPath) {
|
|
||||||
link.classList.add('active');
|
|
||||||
} else {
|
|
||||||
link.classList.remove('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<!-- Instance Modal -->
|
|
||||||
<div class="modal fade" id="instanceModal" tabindex="-1" aria-labelledby="instanceModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-lg">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="instanceModalLabel">Process Details</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<!-- Content will be loaded here via AJAX -->
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
var instanceModal = document.getElementById('instanceModal');
|
|
||||||
instanceModal.addEventListener('show.bs.modal', function(event) {
|
|
||||||
var button = event.relatedTarget;
|
|
||||||
var personId = button.dataset.personId;
|
|
||||||
var modalType = button.dataset.modalType;
|
|
||||||
var modalBody = instanceModal.querySelector('.modal-body');
|
|
||||||
var modalTitle = instanceModal.querySelector('.modal-title');
|
|
||||||
|
|
||||||
if (modalType === 'meeting_attendance') {
|
|
||||||
var meetingId = button.dataset.meetingId;
|
|
||||||
modalTitle.textContent = 'Meeting Attendance';
|
|
||||||
fetch(`_get_meeting_attendance_details.php?personId=${personId}&meetingId=${meetingId}`)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
modalBody.innerHTML = html;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var processId = button.dataset.processId;
|
|
||||||
modalTitle.textContent = 'Process Details';
|
|
||||||
fetch(`_get_instance_details.php?personId=${personId}&processId=${processId}`)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
modalBody.innerHTML = html;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bulk actions
|
|
||||||
const selectAll = document.getElementById('selectAll');
|
|
||||||
const checkboxes = document.querySelectorAll('.person-checkbox');
|
|
||||||
const bulkActionsGroup = document.getElementById('bulk-actions-group');
|
|
||||||
|
|
||||||
function toggleBulkActions() {
|
|
||||||
const anyChecked = Array.from(checkboxes).some(c => c.checked);
|
|
||||||
bulkActionsGroup.style.display = anyChecked ? 'block' : 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectAll.addEventListener('change', function() {
|
|
||||||
checkboxes.forEach(c => c.checked = selectAll.checked);
|
|
||||||
toggleBulkActions();
|
|
||||||
});
|
|
||||||
|
|
||||||
checkboxes.forEach(c => c.addEventListener('change', toggleBulkActions));
|
|
||||||
|
|
||||||
// Pass selected people to modals
|
|
||||||
function setupBulkModal(modalId, hiddenInputId) {
|
|
||||||
const modal = document.getElementById(modalId);
|
|
||||||
modal.addEventListener('show.bs.modal', function() {
|
|
||||||
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
|
|
||||||
document.getElementById(hiddenInputId).value = JSON.stringify(selectedIds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setupBulkModal('bulkStatusModal', 'bulkStatusPersonIds');
|
|
||||||
setupBulkModal('bulkEventModal', 'bulkEventPersonIds');
|
|
||||||
setupBulkModal('bulkInitModal', 'bulkInitPersonIds');
|
|
||||||
|
|
||||||
// Populate edit person modal
|
|
||||||
const editPersonModal = document.getElementById('editPersonModal');
|
|
||||||
if (editPersonModal) {
|
|
||||||
editPersonModal.addEventListener('show.bs.modal', function(event) {
|
|
||||||
const button = event.relatedTarget;
|
|
||||||
const personId = button.getAttribute('data-person-id');
|
|
||||||
var personName = button.getAttribute('data-person-name');
|
|
||||||
|
|
||||||
var deleteBtn = document.getElementById('deleteUserBtn');
|
|
||||||
deleteBtn.dataset.personId = personId;
|
|
||||||
deleteBtn.dataset.personName = personName;
|
|
||||||
|
|
||||||
fetch('_get_person_details.php?id=' + personId)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
document.getElementById('editPersonId').value = data.person.id;
|
|
||||||
document.getElementById('editFirstName').value = data.person.firstName;
|
|
||||||
document.getElementById('editLastName').value = data.person.lastName;
|
|
||||||
document.getElementById('editEmail').value = data.person.email;
|
|
||||||
document.getElementById('editCompanyName').value = data.person.companyName;
|
|
||||||
document.getElementById('editPhone').value = data.person.phone;
|
|
||||||
document.getElementById('editRole').value = data.person.role;
|
|
||||||
document.getElementById('editBniGroup').value = data.person.bni_group_id || '';
|
|
||||||
|
|
||||||
document.getElementById('editNip').value = data.person.nip || '';
|
|
||||||
document.getElementById('editIndustry').value = data.person.industry || '';
|
|
||||||
document.getElementById('editCompanySize').value = data.person.company_size_revenue || '';
|
|
||||||
document.getElementById('editBusinessDescription').value = data.person.business_description || '';
|
|
||||||
|
|
||||||
document.getElementById('editCompanyLogoPath').textContent = data.person.company_logo_path || '';
|
|
||||||
document.getElementById('editPersonPhotoPath').textContent = data.person.person_photo_path || '';
|
|
||||||
document.getElementById('editGainsSheetPath').textContent = data.person.gains_sheet_path || '';
|
|
||||||
document.getElementById('editTopWantedPath').textContent = data.person.top_wanted_contacts_path || '';
|
|
||||||
document.getElementById('editTopOwnedPath').textContent = data.person.top_owned_contacts_path || '';
|
|
||||||
|
|
||||||
// Trigger change to show/hide group div and member-only fields
|
|
||||||
const editRoleSelect = document.getElementById('editRole');
|
|
||||||
editRoleSelect.dispatchEvent(new Event('change'));
|
|
||||||
|
|
||||||
const functionsSelect = document.getElementById('editRoles');
|
|
||||||
functionsSelect.innerHTML = ''; // Clear existing options
|
|
||||||
|
|
||||||
// Group functions by group_name
|
|
||||||
const groupedFunctions = data.all_functions.reduce((acc, func) => {
|
|
||||||
const groupName = func.group_name || 'Other';
|
|
||||||
if (!acc[groupName]) {
|
|
||||||
acc[groupName] = [];
|
|
||||||
}
|
|
||||||
acc[groupName].push(func);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// Populate select with optgroups
|
|
||||||
for (const groupName in groupedFunctions) {
|
|
||||||
const optgroup = document.createElement('optgroup');
|
|
||||||
optgroup.label = groupName;
|
|
||||||
groupedFunctions[groupName].forEach(func => {
|
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = func.id;
|
|
||||||
option.textContent = func.name;
|
|
||||||
if (data.person_functions.map(String).includes(String(func.id))) {
|
|
||||||
option.selected = true;
|
|
||||||
}
|
|
||||||
optgroup.appendChild(option);
|
|
||||||
});
|
|
||||||
functionsSelect.appendChild(optgroup);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// When the delete button in the edit modal is clicked, pass the data to the delete confirmation modal
|
|
||||||
document.getElementById('deleteUserBtn').addEventListener('click', function() {
|
|
||||||
var personId = this.dataset.personId;
|
|
||||||
var personName = this.dataset.personName;
|
|
||||||
|
|
||||||
var deletePersonModal = document.getElementById('deletePersonModal');
|
|
||||||
deletePersonModal.querySelector('#personNameToDelete').textContent = personName;
|
|
||||||
deletePersonModal.dataset.personId = personId;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Populate delete person modal
|
|
||||||
var deletePersonModal = document.getElementById('deletePersonModal');
|
|
||||||
deletePersonModal.addEventListener('show.bs.modal', function(event) {
|
|
||||||
var button = event.relatedTarget;
|
|
||||||
if (button.id !== 'deleteUserBtn') {
|
|
||||||
var personId = button.dataset.personId;
|
|
||||||
var personName = button.dataset.personName;
|
|
||||||
document.getElementById('personNameToDelete').textContent = personName;
|
|
||||||
deletePersonModal.dataset.personId = personId;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
|
||||||
let personIdToDelete = deletePersonModal.dataset.personId;
|
|
||||||
if (personIdToDelete) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('person_id', personIdToDelete);
|
|
||||||
|
|
||||||
fetch('_delete_person.php', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
|
||||||
modal.hide();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
window.location.reload();
|
|
||||||
} else {
|
|
||||||
let errorAlert = document.querySelector('.alert-danger');
|
|
||||||
let errorContainer = errorAlert.parentElement;
|
|
||||||
if (!errorAlert) {
|
|
||||||
errorContainer = document.querySelector('main'); // fallback
|
|
||||||
const alertHTML = `
|
|
||||||
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
|
|
||||||
${data.error}
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>`;
|
|
||||||
errorContainer.insertAdjacentHTML('afterbegin', alertHTML);
|
|
||||||
} else {
|
|
||||||
errorAlert.innerHTML = `${data.error} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
|
|
||||||
errorAlert.classList.remove('d-none');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
|
||||||
modal.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle role change for group visibility
|
|
||||||
const createRoleSelect = document.getElementById('createRole');
|
|
||||||
const createGroupDiv = document.getElementById('create-group-selection-div');
|
|
||||||
const createMemberOnlyFields = document.querySelector('#createPersonModal .member-only-fields');
|
|
||||||
|
|
||||||
createRoleSelect.addEventListener('change', function() {
|
|
||||||
const isMember = this.value === 'member';
|
|
||||||
createGroupDiv.style.display = isMember ? 'block' : 'none';
|
|
||||||
createMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
|
||||||
});
|
|
||||||
// Initial check
|
|
||||||
const isMemberCreate = createRoleSelect.value === 'member';
|
|
||||||
createGroupDiv.style.display = isMemberCreate ? 'block' : 'none';
|
|
||||||
createMemberOnlyFields.style.display = isMemberCreate ? 'block' : 'none';
|
|
||||||
|
|
||||||
|
|
||||||
const editRoleSelect = document.getElementById('editRole');
|
|
||||||
const editGroupDiv = document.getElementById('edit-group-selection-div');
|
|
||||||
const editMemberOnlyFields = document.querySelector('#editPersonModal .member-only-fields');
|
|
||||||
|
|
||||||
editRoleSelect.addEventListener('change', function() {
|
|
||||||
const isMember = this.value === 'member';
|
|
||||||
editGroupDiv.style.display = isMember ? 'block' : 'none';
|
|
||||||
editMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Bulk Modals -->
|
|
||||||
<!-- Bulk Status Update Modal -->
|
|
||||||
<div class="modal fade" id="bulkStatusModal" tabindex="-1">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Bulk Status Update</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form action="_bulk_update_status.php" method="post">
|
|
||||||
<input type="hidden" name="person_ids" id="bulkStatusPersonIds">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Process</label>
|
|
||||||
<select name="process_id" class="form-select" required>
|
|
||||||
<option value="4">Follow-up</option>
|
|
||||||
<option value="9">Obsługa przyjęcia nowego członka</option>
|
|
||||||
<option value="7">Wprowadzenie nowego członka</option>
|
|
||||||
<option value="6">Szkolenia dla młodego członka</option>
|
|
||||||
<option value="1">Mentoring</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">New Status</label>
|
|
||||||
<select name="status" class="form-select" required>
|
|
||||||
<option value="none">None</option>
|
|
||||||
<option value="negative">Negative</option>
|
|
||||||
<option value="in_progress">In Progress</option>
|
|
||||||
<option value="positive">Positive</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary">Update Status</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bulk Add Event Modal -->
|
|
||||||
<div class="modal fade" id="bulkEventModal" tabindex="-1">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Bulk Add Event</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form action="_bulk_add_event.php" method="post">
|
|
||||||
<input type="hidden" name="person_ids" id="bulkEventPersonIds">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Process</label>
|
|
||||||
<select name="process_id" class="form-select" required>
|
|
||||||
<option value="4">Follow-up</option>
|
|
||||||
<option value="9">Obsługa przyjęcia nowego członka</option>
|
|
||||||
<option value="7">Wprowadzenie nowego członka</option>
|
|
||||||
<option value="6">Szkolenia dla młodego członka</option>
|
|
||||||
<option value="1">Mentoring</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Event Description</label>
|
|
||||||
<textarea name="description" class="form-control" required></textarea>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary">Add Event</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bulk Initialize Instances Modal -->
|
|
||||||
<div class="modal fade" id="bulkInitModal" tabindex="-1">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Bulk Initialize Instances</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form action="_bulk_init_instances.php" method="post">
|
|
||||||
<input type="hidden" name="person_ids" id="bulkInitPersonIds">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Process</label> <select name="process_id" class="form-select" required>
|
|
||||||
<option value="4">Follow-up</option>
|
|
||||||
<option value="9">Obsługa przyjęcia nowego członka</option>
|
|
||||||
<option value="7">Wprowadzenie nowego członka</option>
|
|
||||||
<option value="6">Szkolenia dla młodego członka</option>
|
|
||||||
<option value="1">Mentoring</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<p>This will initialize this process for all selected people if it is not already initialized.</p>
|
|
||||||
<button type="submit" class="btn btn-primary">Initialize</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../db/config.php';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$db = db();
|
|
||||||
// Create meetings table
|
|
||||||
$db->exec("
|
|
||||||
CREATE TABLE IF NOT EXISTS meetings (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
group_id INT NOT NULL,
|
|
||||||
meeting_date DATE NOT NULL,
|
|
||||||
title VARCHAR(255),
|
|
||||||
created_by INT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
is_active TINYINT(1) DEFAULT 0,
|
|
||||||
FOREIGN KEY (group_id) REFERENCES bni_groups(id) ON DELETE CASCADE
|
|
||||||
)
|
|
||||||
");
|
|
||||||
echo "Migration 030 run successfully: meetings table created.
|
|
||||||
";
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Migration 030 failed: " . $e->getMessage() . "
|
|
||||||
");
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../db/config.php';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$db = db();
|
|
||||||
// Create meeting_attendance table
|
|
||||||
$db->exec("
|
|
||||||
CREATE TABLE IF NOT EXISTS meeting_attendance (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
meeting_id INT NOT NULL,
|
|
||||||
person_id INT NOT NULL,
|
|
||||||
attendance_status ENUM('present', 'absent', 'substitute', 'n/a') NOT NULL DEFAULT 'n/a',
|
|
||||||
guest_survey ENUM('1', '2', '3'),
|
|
||||||
updated_by INT,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
|
|
||||||
UNIQUE KEY (meeting_id, person_id)
|
|
||||||
)
|
|
||||||
");
|
|
||||||
echo "Migration 031 run successfully: meeting_attendance table created.
|
|
||||||
";
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Migration 031 failed: " . $e->getMessage() . "
|
|
||||||
");
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../db/config.php';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$db = db();
|
|
||||||
$db->exec("
|
|
||||||
ALTER TABLE meeting_attendance
|
|
||||||
ADD CONSTRAINT fk_meeting_id FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE CASCADE;
|
|
||||||
");
|
|
||||||
|
|
||||||
echo "Migration 032 run successfully: Added foreign key for meeting_id to meeting_attendance table.\n";
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Migration 032 failed: " . $e->getMessage() . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../db/config.php';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$db = db();
|
|
||||||
$db->exec("
|
|
||||||
ALTER TABLE meeting_attendance
|
|
||||||
MODIFY COLUMN person_id INT(11) UNSIGNED NOT NULL;
|
|
||||||
");
|
|
||||||
|
|
||||||
$db->exec("
|
|
||||||
ALTER TABLE meeting_attendance
|
|
||||||
ADD CONSTRAINT fk_person_id FOREIGN KEY (person_id) REFERENCES people(id) ON DELETE CASCADE;
|
|
||||||
");
|
|
||||||
|
|
||||||
echo "Migration 033 run successfully: Changed person_id to UNSIGNED and added foreign key.\n";
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Migration 033 failed: " . $e->getMessage() . "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../db/config.php';
|
|
||||||
|
|
||||||
function migrate_034()
|
|
||||||
{
|
|
||||||
$pdo = db();
|
|
||||||
|
|
||||||
$process_name = 'Guest Survey Follow-up';
|
|
||||||
$process_code = 'guest_survey_follow_up';
|
|
||||||
|
|
||||||
$json_definition = <<<'EOT'
|
|
||||||
{
|
|
||||||
"start_node_id": "follow_up",
|
|
||||||
"nodes": {
|
|
||||||
"follow_up": {
|
|
||||||
"ui_hints": {
|
|
||||||
"title": "Follow-up with Guest",
|
|
||||||
"status": "active",
|
|
||||||
"reason": "Follow-up with the guest based on their survey feedback.",
|
|
||||||
"next_step": "Log the outcome of the follow-up.",
|
|
||||||
"form_schema": [
|
|
||||||
{ "name": "follow_up_date", "label": "Follow-up Date", "type": "datetime-local", "default": "now", "required": true },
|
|
||||||
{ "name": "note", "label": "Notes", "type": "textarea" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"ui_hints": {
|
|
||||||
"title": "Process Ended",
|
|
||||||
"status": "completed",
|
|
||||||
"reason": "Follow-up completed.",
|
|
||||||
"next_step": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"transitions": [
|
|
||||||
{
|
|
||||||
"id": "complete_follow_up",
|
|
||||||
"from": "follow_up",
|
|
||||||
"to": "end",
|
|
||||||
"name": "Complete Follow-up"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
EOT;
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO process_definitions (name, code, definition_json, is_active, sort_order) VALUES (:name, :code, :json, 1, 99)");
|
|
||||||
$stmt->execute([
|
|
||||||
':name' => $process_name,
|
|
||||||
':code' => $process_code,
|
|
||||||
':json' => $json_definition,
|
|
||||||
]);
|
|
||||||
|
|
||||||
echo "Migration 034 executed successfully: Added 'Guest Survey Follow-up' process definition.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"]))
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
migrate_034();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo "Migration 34 failed: " . $e->getMessage() . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
704
index.php
704
index.php
@ -1,81 +1,73 @@
|
|||||||
<?php
|
<?php
|
||||||
try {
|
require_once 'WorkflowEngine.php';
|
||||||
require_once 'db/config.php';
|
|
||||||
require_once 'WorkflowEngine.php';
|
|
||||||
|
|
||||||
$workflowEngine = new WorkflowEngine();
|
$workflowEngine = new WorkflowEngine();
|
||||||
|
|
||||||
$searchTerm = $_GET['search'] ?? null;
|
$searchTerm = $_GET['search'] ?? null;
|
||||||
$groupId = isset($_GET['group_id']) && $_GET['group_id'] !== '' ? (int)$_GET['group_id'] : null;
|
$groupId = isset($_GET['group_id']) && $_GET['group_id'] !== '' ? (int)$_GET['group_id'] : null;
|
||||||
$activeProcessId = isset($_GET['active_process_id']) && $_GET['active_process_id'] !== '' ? (int)$_GET['active_process_id'] : null;
|
$activeProcessId = isset($_GET['active_process_id']) && $_GET['active_process_id'] !== '' ? (int)$_GET['active_process_id'] : null;
|
||||||
|
|
||||||
// Handle toggling of the active process filter
|
// Handle toggling of the active process filter
|
||||||
if (isset($_GET['active_process_id']) && $_GET['active_process_id'] == @$_SESSION['last_active_process_id']) {
|
if (isset($_GET['active_process_id']) && $_GET['active_process_id'] == @$_SESSION['last_active_process_id']) {
|
||||||
unset($_GET['active_process_id']);
|
unset($_GET['active_process_id']);
|
||||||
$activeProcessId = null;
|
$activeProcessId = null;
|
||||||
$redirectUrl = "index.php";
|
$redirectUrl = "index.php";
|
||||||
$queryParams = [];
|
$queryParams = [];
|
||||||
if ($groupId) {
|
if ($groupId) {
|
||||||
$queryParams['group_id'] = $groupId;
|
$queryParams['group_id'] = $groupId;
|
||||||
}
|
|
||||||
if ($searchTerm) {
|
|
||||||
$queryParams['search'] = $searchTerm;
|
|
||||||
}
|
|
||||||
if (!empty($queryParams)) {
|
|
||||||
$redirectUrl .= "?" . http_build_query($queryParams);
|
|
||||||
}
|
|
||||||
header("Location: " . $redirectUrl);
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
$_SESSION['last_active_process_id'] = $activeProcessId;
|
if ($searchTerm) {
|
||||||
|
$queryParams['search'] = $searchTerm;
|
||||||
|
}
|
||||||
|
if (!empty($queryParams)) {
|
||||||
|
$redirectUrl .= "?" . http_build_query($queryParams);
|
||||||
|
}
|
||||||
|
header("Location: " . $redirectUrl);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$_SESSION['last_active_process_id'] = $activeProcessId;
|
||||||
|
|
||||||
|
|
||||||
$matrixData = $workflowEngine->getDashboardMatrix($searchTerm, $groupId, $activeProcessId);
|
$matrixData = $workflowEngine->getDashboardMatrix($searchTerm, $groupId, $activeProcessId);
|
||||||
$people = $matrixData['people'];
|
$people = $matrixData['people'];
|
||||||
$processes = $matrixData['definitions'];
|
$processes = $matrixData['definitions'];
|
||||||
$instances = $matrixData['instances'];
|
$instances = $matrixData['instances'];
|
||||||
$spotkania_cols = $matrixData['spotkania_cols'];
|
$spotkania_cols = $matrixData['spotkania_cols'];
|
||||||
$bni_groups = $matrixData['bni_groups'];
|
$bni_groups = $matrixData['bni_groups'];
|
||||||
$all_functions = $matrixData['all_functions'];
|
$all_functions = $matrixData['all_functions'];
|
||||||
|
|
||||||
|
|
||||||
|
$status_colors = [
|
||||||
|
'none' => 'secondary',
|
||||||
|
'negative' => 'danger',
|
||||||
|
'in_progress' => 'warning',
|
||||||
|
'positive' => 'success',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
$status_colors = [
|
|
||||||
'none' => 'secondary',
|
|
||||||
'negative' => 'danger',
|
|
||||||
'in_progress' => 'warning',
|
|
||||||
'positive' => 'success',
|
|
||||||
'active' => 'primary',
|
|
||||||
'processing' => 'info',
|
|
||||||
'paused' => 'secondary',
|
|
||||||
'completed' => 'success',
|
|
||||||
'terminated' => 'danger',
|
|
||||||
];
|
|
||||||
|
|
||||||
include '_header.php';
|
|
||||||
include '_navbar.php';
|
|
||||||
?>
|
?>
|
||||||
|
<?php include '_header.php'; ?>
|
||||||
|
<?php include '_navbar.php'; ?>
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php include '_sidebar.php'; ?>
|
<?php include '_sidebar.php'; ?>
|
||||||
|
|
||||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||||
<?php if (isset($_SESSION['success_message'])) : ?>
|
<?php if (isset($_SESSION['success_message'])): ?>
|
||||||
<div class="alert alert-success alert-dismissible fade show mt-3" role="alert">
|
<div class="alert alert-success alert-dismissible fade show mt-3" role="alert">
|
||||||
<?= $_SESSION['success_message']; ?>
|
<?= $_SESSION['success_message']; ?>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<?php unset($_SESSION['success_message']); ?>
|
<?php unset($_SESSION['success_message']); ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (isset($_SESSION['error_message'])) : ?>
|
<?php if (isset($_SESSION['error_message'])): ?>
|
||||||
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
|
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
|
||||||
<?= $_SESSION['error_message']; ?>
|
<?= $_SESSION['error_message']; ?>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<?php unset($_SESSION['error_message']); ?>
|
<?php unset($_SESSION['error_message']); ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||||
@ -101,13 +93,15 @@ try {
|
|||||||
// Define process groups
|
// Define process groups
|
||||||
// Show all processes from the DB directly.
|
// Show all processes from the DB directly.
|
||||||
$inne_procesy_cols = $processes;
|
$inne_procesy_cols = $processes;
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Filter by Group:</label>
|
<label class="form-label">Filter by Group:</label>
|
||||||
<div class="btn-group" role="group" aria-label="Group Filter">
|
<div class="btn-group" role="group" aria-label="Group Filter">
|
||||||
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => ''])) ?>" class="btn btn-outline-primary <?= !$groupId ? 'active-filter' : '' ?>">All Groups</a>
|
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => ''])) ?>" class="btn btn-outline-primary <?= !$groupId ? 'active-filter' : '' ?>">All Groups</a>
|
||||||
<?php foreach ($bni_groups as $group) : ?>
|
<?php foreach ($bni_groups as $group): ?>
|
||||||
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => $group['id']])) ?>" class="btn btn-outline-primary <?= ($groupId == $group['id']) ? 'active-filter' : '' ?>">
|
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => $group['id']])) ?>" class="btn btn-outline-primary <?= ($groupId == $group['id']) ? 'active-filter' : '' ?>">
|
||||||
<?= htmlspecialchars($group['name']) ?>
|
<?= htmlspecialchars($group['name']) ?>
|
||||||
</a>
|
</a>
|
||||||
@ -121,22 +115,21 @@ try {
|
|||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th rowspan="2" class="align-middle"><input type="checkbox" id="selectAll"></th>
|
<th rowspan="2" class="align-middle"><input type="checkbox" id="selectAll"></th>
|
||||||
<th rowspan="2" class="align-middle">Person</th>
|
<th rowspan="2" class="align-middle">Person</th>
|
||||||
<?php if (!empty($spotkania_cols)) : ?>
|
<?php if (!empty($spotkania_cols)): ?>
|
||||||
<th colspan="<?= count($spotkania_cols) ?>">Spotkania</th>
|
<th colspan="<?= count($spotkania_cols) ?>">Spotkania</th>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (!empty($inne_procesy_cols)) : ?>
|
<?php if (!empty($inne_procesy_cols)): ?>
|
||||||
<th colspan="<?= count($processes) ?>">Inne procesy</th>
|
<th colspan="<?= count($processes) ?>">Inne procesy</th>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<?php foreach ($spotkania_cols as $col) : ?>
|
<?php foreach ($spotkania_cols as $col): ?>
|
||||||
<th data-group-id="<?= $col['group_id'] ?>" data-offset="0">
|
<th>
|
||||||
<span class="meeting-nav-arrow left-arrow"><</span>
|
<?= htmlspecialchars($col['group_name']) ?><br>
|
||||||
<span class="meeting-date"><?= htmlspecialchars($col['group_name']) ?><br><small><?= date('d.m.Y', strtotime($col['next_meeting_date'])) ?></small></span>
|
<small><?= $col['next_meeting_date'] ? date('d.m.Y', strtotime($col['next_meeting_date'])) : 'Brak' ?></small>
|
||||||
<span class="meeting-nav-arrow right-arrow">></span>
|
|
||||||
</th>
|
</th>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php foreach ($processes as $col) : ?>
|
<?php foreach ($processes as $col): ?>
|
||||||
<?php
|
<?php
|
||||||
$filterParams = $_GET;
|
$filterParams = $_GET;
|
||||||
$filterParams['active_process_id'] = $col['id'];
|
$filterParams['active_process_id'] = $col['id'];
|
||||||
@ -150,69 +143,68 @@ try {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($people as $person) : ?>
|
<?php foreach ($people as $person): ?>
|
||||||
<tr data-group-id="<?= $person['bni_group_id'] ?>">
|
<tr data-group-id="<?= $person['bni_group_id'] ?>">
|
||||||
<td class="text-center align-middle"><input type="checkbox" class="person-checkbox" name="person_ids[]" value="<?= $person['id'] ?>"></td>
|
<td class="text-center align-middle"><input type="checkbox" class="person-checkbox" name="person_ids[]" value="<?= $person['id'] ?>"></td>
|
||||||
<td class="person-cell">
|
<td class="person-cell">
|
||||||
<div class="person-main">
|
<div class="person-main">
|
||||||
<div class="person-name"><?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?></div>
|
<div class="person-name"><?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?></div>
|
||||||
<div class="person-details">
|
<div class="person-details">
|
||||||
<span class="d-block"><?= htmlspecialchars($person['company_name'] ?? '') ?></span>
|
<span class="d-block"><?= htmlspecialchars($person['company_name'] ?? '') ?></span>
|
||||||
<span class="d-block"><?= htmlspecialchars($person['industry'] ?? '') ?></span>
|
<span class="d-block"><?= htmlspecialchars($person['industry'] ?? '') ?></span>
|
||||||
<span><?= htmlspecialchars(ucfirst($person['role'])) ?></span>
|
<span><?= htmlspecialchars(ucfirst($person['role'])) ?></span>
|
||||||
<?php if ($person['role'] === 'member' && !empty($person['bni_group_name'])) : ?>
|
<?php if ($person['role'] === 'member' && !empty($person['bni_group_name'])): ?>
|
||||||
<span class="person-group">, Grupa: <?= htmlspecialchars($person['bni_group_name']) ?></span>
|
<span class="person-group">, Grupa: <?= htmlspecialchars($person['bni_group_name']) ?></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="person-actions">
|
</div>
|
||||||
<div class="status-dots">
|
<div class="person-actions">
|
||||||
<?php if ($person['role'] === 'member') : ?>
|
<div class="status-dots">
|
||||||
<span class="status-dot <?= !empty($person['gains_sheet_path']) ? 'bg-success' : 'bg-danger' ?>" title="GAINS Sheet"></span>
|
<?php if ($person['role'] === 'member'): ?>
|
||||||
<span class="status-dot <?= !empty($person['top_wanted_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Wanted Contacts"></span>
|
<span class="status-dot <?= !empty($person['gains_sheet_path']) ? 'bg-success' : 'bg-danger' ?>" title="GAINS Sheet"></span>
|
||||||
<span class="status-dot <?= !empty($person['top_owned_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Owned Contacts"></span>
|
<span class="status-dot <?= !empty($person['top_wanted_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Wanted Contacts"></span>
|
||||||
<?php endif; ?>
|
<span class="status-dot <?= !empty($person['top_owned_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Owned Contacts"></span>
|
||||||
</div>
|
<?php endif; ?>
|
||||||
<button class="btn btn-sm btn-secondary edit-btn" data-bs-toggle="modal" data-bs-target="#editPersonModal" data-person-id="<?= $person['id'] ?>" data-person-name="<?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?>">
|
|
||||||
Edit
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-sm btn-secondary edit-btn" data-bs-toggle="modal" data-bs-target="#editPersonModal"
|
||||||
|
data-person-id="<?= $person['id'] ?>"
|
||||||
|
data-person-name="<?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?>">
|
||||||
|
Edit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<?php // Spotkania Columns ?>
|
||||||
|
<?php foreach ($spotkania_cols as $col): ?>
|
||||||
|
<td class="text-center align-middle">
|
||||||
|
<?php
|
||||||
|
// Placeholder Status: Logic for meeting attendance is not yet defined.
|
||||||
|
// Display icon only if the person belongs to the group for that column.
|
||||||
|
if ($person['bni_group_id'] == $col['group_id']) {
|
||||||
|
$status = 'none'; // Default/placeholder status
|
||||||
|
$color = $status_colors[$status];
|
||||||
|
echo "<span class=\"badge rounded-circle bg-$color\" style=\"width: 20px; height: 20px; display: inline-block;\" title=\"Status nieokreślony\"></span>";
|
||||||
|
} else {
|
||||||
|
echo ''; // Empty cell if person is not in this group
|
||||||
|
}
|
||||||
|
?>
|
||||||
</td>
|
</td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php // Spotkania Columns
|
<?php // Inne Procesy Columns ?>
|
||||||
foreach ($spotkania_cols as $col) :
|
<?php foreach ($processes as $process):
|
||||||
$meeting_id = $col['meeting_id'];
|
$instance = $instances[$person['id']][$process['id']] ?? null;
|
||||||
$person_attendance = $meetings[$col['group_id']]['attendance'][$person['id']] ?? null;
|
$status = $instance ? $instance['computed_status'] : 'none';
|
||||||
$status = $person_attendance ? $person_attendance['attendance_status'] : 'n/a';
|
$color = $status_colors[$status] ?? 'secondary';
|
||||||
$status_color_map = [
|
$lastActivity = $instance && $instance['last_activity_at'] ? date('d/m/y', strtotime($instance['last_activity_at'])) : '';
|
||||||
'present' => 'success',
|
?>
|
||||||
'absent' => 'danger',
|
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="<?= $person['id'] ?>" data-process-id="<?= $process['id'] ?>">
|
||||||
'substitute' => 'warning',
|
<span class="badge rounded-circle bg-<?= $color ?>" style="width: 20px; height: 20px; display: inline-block;" title="<?= ucfirst($status) ?>"> </span>
|
||||||
'n/a' => 'secondary'
|
<small class="text-muted d-block"><?= $lastActivity ?></small>
|
||||||
];
|
</td>
|
||||||
$color = $status_color_map[$status];
|
<?php endforeach; ?>
|
||||||
?>
|
</tr>
|
||||||
<td class="text-center align-middle">
|
<?php endforeach; ?>
|
||||||
<span class="badge rounded-circle bg-<?= $color ?>" style="width: 20px; height: 20px; display: inline-block; cursor: pointer;" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="<?= $person['id'] ?>" data-meeting-id="<?= $meeting_id ?>" data-modal-type="meeting_attendance">
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
|
|
||||||
<?php // Inne Procesy Columns
|
|
||||||
?>
|
|
||||||
<?php foreach ($processes as $process) :;
|
|
||||||
$instance = $instances[$person['id']][$process['id']] ?? null;
|
|
||||||
$status = $instance ? $instance['computed_status'] : 'none';
|
|
||||||
$color = $status_colors[$status] ?? 'secondary';
|
|
||||||
$lastActivity = $instance && $instance['last_activity_at'] ? date('d/m/y', strtotime($instance['last_activity_at'])) : '';
|
|
||||||
?>
|
|
||||||
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="<?= $person['id'] ?>" data-process-id="<?= $process['id'] ?>">
|
|
||||||
<span class="badge rounded-circle bg-<?= $color ?>" style="width: 20px; height: 20px; display: inline-block;" title="<?= ucfirst($status) ?>"> </span>
|
|
||||||
<small class="text-muted d-block"><?= $lastActivity ?></small>
|
|
||||||
</td>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -241,7 +233,7 @@ try {
|
|||||||
<label for="editLastName" class="form-label">Nazwisko</label>
|
<label for="editLastName" class="form-label">Nazwisko</label>
|
||||||
<input type="text" class="form-control" id="editLastName" name="lastName" required>
|
<input type="text" class="form-control" id="editLastName" name="lastName" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editPhone" class="form-label">Numer telefonu</label>
|
<label for="editPhone" class="form-label">Numer telefonu</label>
|
||||||
<input type="text" class="form-control" id="editPhone" name="phone">
|
<input type="text" class="form-control" id="editPhone" name="phone">
|
||||||
</div>
|
</div>
|
||||||
@ -256,7 +248,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editRole" class="form-label">Rola</label>
|
<label for="editRole" class="form-label">Rola</label>
|
||||||
<select class="form-select" id="editRole" name="role" required>
|
<select class="form-select" id="editRole" name="role" required>
|
||||||
<option value="admin">Admin</option>
|
<option value="admin">Admin</option>
|
||||||
@ -265,28 +257,28 @@ try {
|
|||||||
<option value="team_member">Pracownik Biura</option>
|
<option value="team_member">Pracownik Biura</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3" id="edit-group-selection-div" style="display: none;">
|
<div class="mb-3" id="edit-group-selection-div" style="display: none;">
|
||||||
<label for="editBniGroup" class="form-label">Grupa</label>
|
<label for="editBniGroup" class="form-label">Grupa</label>
|
||||||
<select class="form-select" id="editBniGroup" name="bni_group_id">
|
<select class="form-select" id="editBniGroup" name="bni_group_id">
|
||||||
<option value="">Wybierz grupę...</option>
|
<option value="">Wybierz grupę...</option>
|
||||||
<?php foreach ($bni_groups as $group) : ?>
|
<?php foreach ($bni_groups as $group): ?>
|
||||||
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
|
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editRoles" class="form-label">Funkcje</label>
|
<label for="editRoles" class="form-label">Funkcje</label>
|
||||||
<select class="form-select" id="editRoles" name="functions[]" multiple size="5">
|
<select class="form-select" id="editRoles" name="functions[]" multiple size="5">
|
||||||
<!-- Opcje zostaną wstawione przez JavaScript -->
|
<!-- Opcje zostaną wstawione przez JavaScript -->
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editCompanyName" class="form-label">Nazwa firmy</label>
|
<label for="editCompanyName" class="form-label">Nazwa firmy</label>
|
||||||
<input type="text" class="form-control" id="editCompanyName" name="companyName">
|
<input type="text" class="form-control" id="editCompanyName" name="companyName">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editNip" class="form-label">NIP</label>
|
<label for="editNip" class="form-label">NIP</label>
|
||||||
<input type="text" class="form-control" id="editNip" name="nip">
|
<input type="text" class="form-control" id="editNip" name="nip">
|
||||||
</div>
|
</div>
|
||||||
@ -321,7 +313,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h5>Dokumenty członkowskie</h5>
|
<h5>Dokumenty członkowskie</h5>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editGainsSheet" class="form-label">Arkusz GAINS</label>
|
<label for="editGainsSheet" class="form-label">Arkusz GAINS</label>
|
||||||
<input class="form-control" type="file" id="editGainsSheet" name="gains_sheet">
|
<input class="form-control" type="file" id="editGainsSheet" name="gains_sheet">
|
||||||
<small id="editGainsSheetPath" class="form-text text-muted"></small>
|
<small id="editGainsSheetPath" class="form-text text-muted"></small>
|
||||||
@ -369,7 +361,7 @@ try {
|
|||||||
<label for="createLastName" class="form-label">Last Name <span class="text-danger">*</span></label>
|
<label for="createLastName" class="form-label">Last Name <span class="text-danger">*</span></label>
|
||||||
<input type="text" class="form-control" id="createLastName" name="lastName" required>
|
<input type="text" class="form-control" id="createLastName" name="lastName" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="createPhone" class="form-label">Phone Number</label>
|
<label for="createPhone" class="form-label">Phone Number</label>
|
||||||
<input type="text" class="form-control" id="createPhone" name="phone">
|
<input type="text" class="form-control" id="createPhone" name="phone">
|
||||||
</div>
|
</div>
|
||||||
@ -383,7 +375,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="createRole" class="form-label">Rola</label>
|
<label for="createRole" class="form-label">Rola</label>
|
||||||
<select class="form-select" id="createRole" name="role" required>
|
<select class="form-select" id="createRole" name="role" required>
|
||||||
<option value="admin">Admin</option>
|
<option value="admin">Admin</option>
|
||||||
@ -396,7 +388,7 @@ try {
|
|||||||
<label for="createBniGroup" class="form-label">Grupa</label>
|
<label for="createBniGroup" class="form-label">Grupa</label>
|
||||||
<select class="form-select" id="createBniGroup" name="bni_group_id">
|
<select class="form-select" id="createBniGroup" name="bni_group_id">
|
||||||
<option value="">Wybierz grupę...</option>
|
<option value="">Wybierz grupę...</option>
|
||||||
<?php foreach ($bni_groups as $group) : ?>
|
<?php foreach ($bni_groups as $group): ?>
|
||||||
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
|
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
@ -404,12 +396,12 @@ try {
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="createRoles" class="form-label">Funkcje</label>
|
<label for="createRoles" class="form-label">Funkcje</label>
|
||||||
<select class="form-select" id="createRoles" name="functions[]" multiple size="5">
|
<select class="form-select" id="createRoles" name="functions[]" multiple size="5">
|
||||||
<?php foreach ($all_functions as $function) : ?>
|
<?php foreach ($all_functions as $function): ?>
|
||||||
<option value="<?= $function['id'] ?>"><?= htmlspecialchars($function['name']) ?></option>
|
<option value="<?= $function['id'] ?>"><?= htmlspecialchars($function['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="createCompanyName" class="form-label">Company Name</label>
|
<label for="createCompanyName" class="form-label">Company Name</label>
|
||||||
<input type="text" class="form-control" id="createCompanyName" name="companyName">
|
<input type="text" class="form-control" id="createCompanyName" name="companyName">
|
||||||
</div>
|
</div>
|
||||||
@ -433,7 +425,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row member-only-fields" style="display: none;">
|
<div class="row member-only-fields" style="display: none;">
|
||||||
<hr class="mt-3">
|
<hr class="mt-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -449,7 +441,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h5>Dokumenty członkowskie</h5>
|
<h5>Dokumenty członkowskie</h5>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="createGainsSheet" class="form-label">Arkusz GAINS</label>
|
<label for="createGainsSheet" class="form-label">Arkusz GAINS</label>
|
||||||
<input class="form-control" type="file" id="createGainsSheet" name="gains_sheet">
|
<input class="form-control" type="file" id="createGainsSheet" name="gains_sheet">
|
||||||
</div>
|
</div>
|
||||||
@ -490,16 +482,7 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php include '_footer.php'; ?>
|
||||||
include '_footer.php';
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
echo "Error: " . $e->getMessage() . "<br>";
|
|
||||||
echo "File: " . $e->getFile() . "<br>";
|
|
||||||
echo "Line: " . $e->getLine() . "<br>";
|
|
||||||
echo "<pre>" . $e->getTraceAsString() . "</pre>";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!-- Instance Modal -->
|
<!-- Instance Modal -->
|
||||||
<div class="modal fade" id="instanceModal" tabindex="-1" aria-labelledby="instanceModalLabel" aria-hidden="true">
|
<div class="modal fade" id="instanceModal" tabindex="-1" aria-labelledby="instanceModalLabel" aria-hidden="true">
|
||||||
@ -520,257 +503,216 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
var instanceModal = document.getElementById('instanceModal');
|
var instanceModal = document.getElementById('instanceModal');
|
||||||
instanceModal.addEventListener('show.bs.modal', function(event) {
|
instanceModal.addEventListener('show.bs.modal', function (event) {
|
||||||
var button = event.relatedTarget;
|
var button = event.relatedTarget;
|
||||||
var personId = button.dataset.personId;
|
var personId = button.dataset.personId;
|
||||||
var modalType = button.dataset.modalType;
|
var processId = button.dataset.processId;
|
||||||
var modalBody = instanceModal.querySelector('.modal-body');
|
var modalBody = instanceModal.querySelector('.modal-body');
|
||||||
var modalTitle = instanceModal.querySelector('.modal-title');
|
|
||||||
|
|
||||||
if (modalType === 'meeting_attendance') {
|
// Load content via AJAX
|
||||||
var meetingId = button.dataset.meetingId;
|
fetch(`_get_instance_details.php?personId=${personId}&processId=${processId}`)
|
||||||
modalTitle.textContent = 'Meeting Attendance';
|
.then(response => response.text())
|
||||||
fetch(`_get_meeting_attendance_details.php?personId=${personId}&meetingId=${meetingId}`)
|
.then(html => {
|
||||||
.then(response => response.text())
|
modalBody.innerHTML = html;
|
||||||
.then(html => {
|
|
||||||
modalBody.innerHTML = html;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var processId = button.dataset.processId;
|
|
||||||
modalTitle.textContent = 'Process Details';
|
|
||||||
fetch(`_get_instance_details.php?personId=${personId}&processId=${processId}`)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
modalBody.innerHTML = html;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bulk actions
|
|
||||||
const selectAll = document.getElementById('selectAll');
|
|
||||||
const checkboxes = document.querySelectorAll('.person-checkbox');
|
|
||||||
const bulkActionsGroup = document.getElementById('bulk-actions-group');
|
|
||||||
|
|
||||||
function toggleBulkActions() {
|
|
||||||
const anyChecked = Array.from(checkboxes).some(c => c.checked);
|
|
||||||
bulkActionsGroup.style.display = anyChecked ? 'block' : 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectAll.addEventListener('change', function() {
|
|
||||||
checkboxes.forEach(c => c.checked = selectAll.checked);
|
|
||||||
toggleBulkActions();
|
|
||||||
});
|
|
||||||
|
|
||||||
checkboxes.forEach(c => c.addEventListener('change', toggleBulkActions));
|
|
||||||
|
|
||||||
// Pass selected people to modals
|
|
||||||
function setupBulkModal(modalId, hiddenInputId) {
|
|
||||||
const modal = document.getElementById(modalId);
|
|
||||||
modal.addEventListener('show.bs.modal', function() {
|
|
||||||
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
|
|
||||||
document.getElementById(hiddenInputId).value = JSON.stringify(selectedIds);
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
setupBulkModal('bulkStatusModal', 'bulkStatusPersonIds');
|
// Bulk actions
|
||||||
setupBulkModal('bulkEventModal', 'bulkEventPersonIds');
|
const selectAll = document.getElementById('selectAll');
|
||||||
setupBulkModal('bulkInitModal', 'bulkInitPersonIds');
|
const checkboxes = document.querySelectorAll('.person-checkbox');
|
||||||
|
const bulkActionsGroup = document.getElementById('bulk-actions-group');
|
||||||
|
|
||||||
// Populate edit person modal
|
function toggleBulkActions() {
|
||||||
const editPersonModal = document.getElementById('editPersonModal');
|
const anyChecked = Array.from(checkboxes).some(c => c.checked);
|
||||||
if (editPersonModal) {
|
bulkActionsGroup.style.display = anyChecked ? 'block' : 'none';
|
||||||
editPersonModal.addEventListener('show.bs.modal', function(event) {
|
}
|
||||||
const button = event.relatedTarget;
|
|
||||||
const personId = button.getAttribute('data-person-id');
|
|
||||||
var personName = button.getAttribute('data-person-name');
|
|
||||||
|
|
||||||
var deleteBtn = document.getElementById('deleteUserBtn');
|
selectAll.addEventListener('change', function () {
|
||||||
deleteBtn.dataset.personId = personId;
|
checkboxes.forEach(c => c.checked = selectAll.checked);
|
||||||
deleteBtn.dataset.personName = personName;
|
toggleBulkActions();
|
||||||
|
});
|
||||||
|
|
||||||
fetch('_get_person_details.php?id=' + personId)
|
checkboxes.forEach(c => c.addEventListener('change', toggleBulkActions));
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
document.getElementById('editPersonId').value = data.person.id;
|
|
||||||
document.getElementById('editFirstName').value = data.person.firstName;
|
|
||||||
document.getElementById('editLastName').value = data.person.lastName;
|
|
||||||
document.getElementById('editEmail').value = data.person.email;
|
|
||||||
document.getElementById('editCompanyName').value = data.person.companyName;
|
|
||||||
document.getElementById('editPhone').value = data.person.phone;
|
|
||||||
document.getElementById('editRole').value = data.person.role;
|
|
||||||
document.getElementById('editBniGroup').value = data.person.bni_group_id || '';
|
|
||||||
|
|
||||||
document.getElementById('editNip').value = data.person.nip || '';
|
// Pass selected people to modals
|
||||||
document.getElementById('editIndustry').value = data.person.industry || '';
|
function setupBulkModal(modalId, hiddenInputId) {
|
||||||
document.getElementById('editCompanySize').value = data.person.company_size_revenue || '';
|
const modal = document.getElementById(modalId);
|
||||||
document.getElementById('editBusinessDescription').value = data.person.business_description || '';
|
modal.addEventListener('show.bs.modal', function() {
|
||||||
|
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
|
||||||
|
document.getElementById(hiddenInputId).value = JSON.stringify(selectedIds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('editCompanyLogoPath').textContent = data.person.company_logo_path || '';
|
setupBulkModal('bulkStatusModal', 'bulkStatusPersonIds');
|
||||||
document.getElementById('editPersonPhotoPath').textContent = data.person.person_photo_path || '';
|
setupBulkModal('bulkEventModal', 'bulkEventPersonIds');
|
||||||
document.getElementById('editGainsSheetPath').textContent = data.person.gains_sheet_path || '';
|
setupBulkModal('bulkInitModal', 'bulkInitPersonIds');
|
||||||
document.getElementById('editTopWantedPath').textContent = data.person.top_wanted_contacts_path || '';
|
|
||||||
document.getElementById('editTopOwnedPath').textContent = data.person.top_owned_contacts_path || '';
|
|
||||||
|
|
||||||
// Trigger change to show/hide group div and member-only fields
|
// Populate edit person modal
|
||||||
const editRoleSelect = document.getElementById('editRole');
|
const editPersonModal = document.getElementById('editPersonModal');
|
||||||
editRoleSelect.dispatchEvent(new Event('change'));
|
if(editPersonModal) {
|
||||||
|
editPersonModal.addEventListener('show.bs.modal', function (event) {
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
const personId = button.getAttribute('data-person-id');
|
||||||
|
var personName = button.getAttribute('data-person-name');
|
||||||
|
|
||||||
const functionsSelect = document.getElementById('editRoles');
|
var deleteBtn = document.getElementById('deleteUserBtn');
|
||||||
functionsSelect.innerHTML = ''; // Clear existing options
|
deleteBtn.dataset.personId = personId;
|
||||||
|
deleteBtn.dataset.personName = personName;
|
||||||
|
|
||||||
// Group functions by group_name
|
fetch('_get_person_details.php?id=' + personId)
|
||||||
const groupedFunctions = data.all_functions.reduce((acc, func) => {
|
.then(response => response.json())
|
||||||
const groupName = func.group_name || 'Other';
|
.then(data => {
|
||||||
if (!acc[groupName]) {
|
document.getElementById('editPersonId').value = data.person.id;
|
||||||
acc[groupName] = [];
|
document.getElementById('editFirstName').value = data.person.firstName;
|
||||||
}
|
document.getElementById('editLastName').value = data.person.lastName;
|
||||||
acc[groupName].push(func);
|
document.getElementById('editEmail').value = data.person.email;
|
||||||
return acc;
|
document.getElementById('editCompanyName').value = data.person.companyName;
|
||||||
}, {});
|
document.getElementById('editPhone').value = data.person.phone;
|
||||||
|
document.getElementById('editRole').value = data.person.role;
|
||||||
|
document.getElementById('editBniGroup').value = data.person.bni_group_id || '';
|
||||||
|
|
||||||
// Populate select with optgroups
|
document.getElementById('editNip').value = data.person.nip || '';
|
||||||
for (const groupName in groupedFunctions) {
|
document.getElementById('editIndustry').value = data.person.industry || '';
|
||||||
const optgroup = document.createElement('optgroup');
|
document.getElementById('editCompanySize').value = data.person.company_size_revenue || '';
|
||||||
optgroup.label = groupName;
|
document.getElementById('editBusinessDescription').value = data.person.business_description || '';
|
||||||
groupedFunctions[groupName].forEach(func => {
|
|
||||||
const option = document.createElement('option');
|
document.getElementById('editCompanyLogoPath').textContent = data.person.company_logo_path || '';
|
||||||
option.value = func.id;
|
document.getElementById('editPersonPhotoPath').textContent = data.person.person_photo_path || '';
|
||||||
option.textContent = func.name;
|
document.getElementById('editGainsSheetPath').textContent = data.person.gains_sheet_path || '';
|
||||||
if (data.person_functions.map(String).includes(String(func.id))) {
|
document.getElementById('editTopWantedPath').textContent = data.person.top_wanted_contacts_path || '';
|
||||||
option.selected = true;
|
document.getElementById('editTopOwnedPath').textContent = data.person.top_owned_contacts_path || '';
|
||||||
}
|
|
||||||
optgroup.appendChild(option);
|
// Trigger change to show/hide group div and member-only fields
|
||||||
});
|
const editRoleSelect = document.getElementById('editRole');
|
||||||
functionsSelect.appendChild(optgroup);
|
editRoleSelect.dispatchEvent(new Event('change'));
|
||||||
|
|
||||||
|
const functionsSelect = document.getElementById('editRoles');
|
||||||
|
functionsSelect.innerHTML = ''; // Clear existing options
|
||||||
|
|
||||||
|
// Group functions by group_name
|
||||||
|
const groupedFunctions = data.all_functions.reduce((acc, func) => {
|
||||||
|
const groupName = func.group_name || 'Other';
|
||||||
|
if (!acc[groupName]) {
|
||||||
|
acc[groupName] = [];
|
||||||
}
|
}
|
||||||
});
|
acc[groupName].push(func);
|
||||||
});
|
return acc;
|
||||||
}
|
}, {});
|
||||||
|
|
||||||
|
// Populate select with optgroups
|
||||||
// When the delete button in the edit modal is clicked, pass the data to the delete confirmation modal
|
for (const groupName in groupedFunctions) {
|
||||||
document.getElementById('deleteUserBtn').addEventListener('click', function() {
|
const optgroup = document.createElement('optgroup');
|
||||||
var personId = this.dataset.personId;
|
optgroup.label = groupName;
|
||||||
var personName = this.dataset.personName;
|
groupedFunctions[groupName].forEach(func => {
|
||||||
|
const option = document.createElement('option');
|
||||||
var deletePersonModal = document.getElementById('deletePersonModal');
|
option.value = func.id;
|
||||||
deletePersonModal.querySelector('#personNameToDelete').textContent = personName;
|
option.textContent = func.name;
|
||||||
deletePersonModal.dataset.personId = personId;
|
if (data.person_functions.map(String).includes(String(func.id))) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
optgroup.appendChild(option);
|
||||||
|
});
|
||||||
|
functionsSelect.appendChild(optgroup);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// When the delete button in the edit modal is clicked, pass the data to the delete confirmation modal
|
||||||
|
document.getElementById('deleteUserBtn').addEventListener('click', function() {
|
||||||
|
var personId = this.dataset.personId;
|
||||||
|
var personName = this.dataset.personName;
|
||||||
|
|
||||||
// Populate delete person modal
|
|
||||||
var deletePersonModal = document.getElementById('deletePersonModal');
|
var deletePersonModal = document.getElementById('deletePersonModal');
|
||||||
deletePersonModal.addEventListener('show.bs.modal', function(event) {
|
deletePersonModal.querySelector('#personNameToDelete').textContent = personName;
|
||||||
var button = event.relatedTarget;
|
deletePersonModal.dataset.personId = personId;
|
||||||
if (button.id !== 'deleteUserBtn') {
|
});
|
||||||
var personId = button.dataset.personId;
|
|
||||||
var personName = button.dataset.personName;
|
|
||||||
document.getElementById('personNameToDelete').textContent = personName;
|
|
||||||
deletePersonModal.dataset.personId = personId;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
// Populate delete person modal
|
||||||
let personIdToDelete = deletePersonModal.dataset.personId;
|
var deletePersonModal = document.getElementById('deletePersonModal');
|
||||||
if (personIdToDelete) {
|
deletePersonModal.addEventListener('show.bs.modal', function (event) {
|
||||||
const formData = new FormData();
|
var button = event.relatedTarget;
|
||||||
formData.append('person_id', personIdToDelete);
|
if (button.id !== 'deleteUserBtn') {
|
||||||
|
var personId = button.dataset.personId;
|
||||||
|
var personName = button.dataset.personName;
|
||||||
|
document.getElementById('personNameToDelete').textContent = personName;
|
||||||
|
deletePersonModal.dataset.personId = personId;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fetch('_delete_person.php', {
|
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
||||||
method: 'POST',
|
let personIdToDelete = deletePersonModal.dataset.personId;
|
||||||
body: formData
|
if (personIdToDelete) {
|
||||||
})
|
const formData = new FormData();
|
||||||
.then(response => response.json())
|
formData.append('person_id', personIdToDelete);
|
||||||
.then(data => {
|
|
||||||
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
|
||||||
modal.hide();
|
|
||||||
|
|
||||||
if (data.success) {
|
fetch('_delete_person.php', {
|
||||||
window.location.reload();
|
method: 'POST',
|
||||||
} else {
|
body: formData
|
||||||
let errorAlert = document.querySelector('.alert-danger');
|
})
|
||||||
let errorContainer = errorAlert.parentElement;
|
.then(response => response.json())
|
||||||
if (!errorAlert) {
|
.then(data => {
|
||||||
errorContainer = document.querySelector('main'); // fallback
|
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
||||||
const alertHTML = `
|
modal.hide();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
let errorAlert = document.querySelector('.alert-danger');
|
||||||
|
let errorContainer = errorAlert.parentElement;
|
||||||
|
if (!errorAlert) {
|
||||||
|
errorContainer = document.querySelector('main'); // fallback
|
||||||
|
const alertHTML = `
|
||||||
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
|
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
|
||||||
${data.error}
|
${data.error}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
</div>`;
|
</div>`;
|
||||||
errorContainer.insertAdjacentHTML('afterbegin', alertHTML);
|
errorContainer.insertAdjacentHTML('afterbegin', alertHTML);
|
||||||
} else {
|
|
||||||
errorAlert.innerHTML = `${data.error} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
|
|
||||||
errorAlert.classList.remove('d-none');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
|
||||||
modal.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle role change for group visibility
|
|
||||||
const createRoleSelect = document.getElementById('createRole');
|
|
||||||
const createGroupDiv = document.getElementById('create-group-selection-div');
|
|
||||||
const createMemberOnlyFields = document.querySelector('#createPersonModal .member-only-fields');
|
|
||||||
|
|
||||||
createRoleSelect.addEventListener('change', function() {
|
|
||||||
const isMember = this.value === 'member';
|
|
||||||
createGroupDiv.style.display = isMember ? 'block' : 'none';
|
|
||||||
createMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
|
||||||
});
|
|
||||||
// Initial check
|
|
||||||
const isMemberCreate = createRoleSelect.value === 'member';
|
|
||||||
createGroupDiv.style.display = isMemberCreate ? 'block' : 'none';
|
|
||||||
createMemberOnlyFields.style.display = isMemberCreate ? 'block' : 'none';
|
|
||||||
|
|
||||||
|
|
||||||
const editRoleSelect = document.getElementById('editRole');
|
|
||||||
const editGroupDiv = document.getElementById('edit-group-selection-div');
|
|
||||||
const editMemberOnlyFields = document.querySelector('#editPersonModal .member-only-fields');
|
|
||||||
|
|
||||||
editRoleSelect.addEventListener('change', function() {
|
|
||||||
const isMember = this.value === 'member';
|
|
||||||
editGroupDiv.style.display = isMember ? 'block' : 'none';
|
|
||||||
editMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Meeting navigation
|
|
||||||
document.querySelectorAll('.meeting-nav-arrow').forEach(arrow => {
|
|
||||||
arrow.addEventListener('click', function() {
|
|
||||||
const th = this.closest('th');
|
|
||||||
const groupId = th.dataset.groupId;
|
|
||||||
let offset = parseInt(th.dataset.offset, 10);
|
|
||||||
|
|
||||||
if (this.classList.contains('left-arrow')) {
|
|
||||||
offset = Math.max(0, offset - 1);
|
|
||||||
} else {
|
} else {
|
||||||
offset += 1;
|
errorAlert.innerHTML = `${data.error} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
|
||||||
|
errorAlert.classList.remove('d-none');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fetch(`_get_group_meetings.php?group_id=${groupId}&offset=${offset}`)
|
})
|
||||||
.then(response => response.json())
|
.catch(error => {
|
||||||
.then(data => {
|
console.error('Error:', error);
|
||||||
if (data.success && data.meeting) {
|
const modal = bootstrap.Modal.getInstance(deletePersonModal);
|
||||||
const meeting = data.meeting;
|
modal.hide();
|
||||||
const meetingDate = new Date(meeting.start_datetime);
|
|
||||||
const formattedDate = meetingDate.toLocaleDateString('pl-PL', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
|
||||||
th.querySelector('.meeting-date').innerHTML = `${data.group_name}<br><small>${formattedDate}</small>`;
|
|
||||||
th.dataset.offset = offset;
|
|
||||||
} else {
|
|
||||||
// Optionally, disable the arrow if there are no more meetings
|
|
||||||
// For now, we do nothing.
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle role change for group visibility
|
||||||
|
const createRoleSelect = document.getElementById('createRole');
|
||||||
|
const createGroupDiv = document.getElementById('create-group-selection-div');
|
||||||
|
const createMemberOnlyFields = document.querySelector('#createPersonModal .member-only-fields');
|
||||||
|
|
||||||
|
createRoleSelect.addEventListener('change', function() {
|
||||||
|
const isMember = this.value === 'member';
|
||||||
|
createGroupDiv.style.display = isMember ? 'block' : 'none';
|
||||||
|
createMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
// Initial check
|
||||||
|
const isMemberCreate = createRoleSelect.value === 'member';
|
||||||
|
createGroupDiv.style.display = isMemberCreate ? 'block' : 'none';
|
||||||
|
createMemberOnlyFields.style.display = isMemberCreate ? 'block' : 'none';
|
||||||
|
|
||||||
|
|
||||||
|
const editRoleSelect = document.getElementById('editRole');
|
||||||
|
const editGroupDiv = document.getElementById('edit-group-selection-div');
|
||||||
|
const editMemberOnlyFields = document.querySelector('#editPersonModal .member-only-fields');
|
||||||
|
|
||||||
|
editRoleSelect.addEventListener('change', function() {
|
||||||
|
const isMember = this.value === 'member';
|
||||||
|
editGroupDiv.style.display = isMember ? 'block' : 'none';
|
||||||
|
editMemberOnlyFields.style.display = isMember ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Bulk Modals -->
|
<!-- Bulk Modals -->
|
||||||
@ -788,7 +730,7 @@ try {
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Process</label>
|
<label class="form-label">Process</label>
|
||||||
<select name="process_id" class="form-select" required>
|
<select name="process_id" class="form-select" required>
|
||||||
<?php foreach ($processes as $process) : ?>
|
<?php foreach($processes as $process): ?>
|
||||||
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
@ -818,12 +760,12 @@ try {
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form action="_bulk_add_event.php" method="post">
|
<form action="_bulk_add_event.php" method="post">
|
||||||
<input type="hidden" name="person_ids" id="bulkEventPersonIds">
|
<input type="hidden" name="person_ids" id="bulkEventPersonIds">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Process</label>
|
<label class="form-label">Process</label>
|
||||||
<select name="process_id" class="form-select" required>
|
<select name="process_id" class="form-select" required>
|
||||||
<?php foreach ($processes as $process) : ?>
|
<?php foreach($processes as $process): ?>
|
||||||
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
@ -850,9 +792,9 @@ try {
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form action="_bulk_init_instances.php" method="post">
|
<form action="_bulk_init_instances.php" method="post">
|
||||||
<input type="hidden" name="person_ids" id="bulkInitPersonIds">
|
<input type="hidden" name="person_ids" id="bulkInitPersonIds">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Process</label> <select name="process_id" class="form-select" required>
|
<label class="form-label">Process</label> <select name="process_id" class="form-select" required>
|
||||||
<?php foreach ($processes as $process) : ?>
|
<?php foreach($processes as $process): ?>
|
||||||
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user