categories
This commit is contained in:
parent
f604713529
commit
b5ae307f55
@ -26,6 +26,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$orders = $json['orders'] ?? []; // Array of {id, position, category_id}
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
// Debug log
|
||||
file_put_contents('debug_reorder.log', date('Y-m-d H:i:s') . " - Server: $server_id - Orders: " . json_encode($orders) . "\n", FILE_APPEND);
|
||||
|
||||
if (Permissions::hasPermission($user_id, $server_id, Permissions::MANAGE_CHANNELS)) {
|
||||
$stmt = db()->prepare("UPDATE channels SET position = ?, category_id = ? WHERE id = ? AND server_id = ?");
|
||||
foreach ($orders as $o) {
|
||||
@ -61,7 +64,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
if ($chan && Permissions::hasPermission($user_id, $chan['server_id'], Permissions::MANAGE_CHANNELS)) {
|
||||
if ($type === 'separator' && !$name) $name = 'separator';
|
||||
$name = strtolower(preg_replace('/[^a-zA-Z0-9\-]/', '-', $name));
|
||||
// Allow spaces, accents and mixed case
|
||||
$name = trim($name);
|
||||
// Explicitly exclude position from update to prevent jumping to bottom
|
||||
$stmt = db()->prepare("UPDATE channels SET name = ?, type = ?, status = ?, allow_file_sharing = ?, message_limit = ?, icon = ?, category_id = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $type, $status, $allow_file_sharing, $message_limit, $icon, $category_id, $channel_id]);
|
||||
}
|
||||
@ -91,16 +96,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (Permissions::hasPermission($user_id, $server_id, Permissions::MANAGE_CHANNELS) && ($name || $type === 'separator')) {
|
||||
try {
|
||||
if ($type === 'separator' && !$name) $name = 'separator';
|
||||
// Basic sanitization for channel name
|
||||
$name = strtolower(preg_replace('/[^a-zA-Z0-9\-]/', '-', $name));
|
||||
// Allow spaces, accents and mixed case
|
||||
$name = trim($name);
|
||||
$allow_file_sharing = isset($_POST['allow_file_sharing']) ? 1 : 0;
|
||||
$message_limit = !empty($_POST['message_limit']) ? (int)$_POST['message_limit'] : null;
|
||||
$icon = $_POST['icon'] ?? null;
|
||||
if ($icon === '') $icon = null;
|
||||
$category_id = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null;
|
||||
|
||||
$stmt = db()->prepare("INSERT INTO channels (server_id, name, type, allow_file_sharing, message_limit, icon, category_id) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$server_id, $name, $type, $allow_file_sharing, $message_limit, $icon, $category_id]);
|
||||
// Get next position
|
||||
$stmtPos = db()->prepare("SELECT MAX(position) as max_pos FROM channels WHERE server_id = ?");
|
||||
$stmtPos->execute([$server_id]);
|
||||
$maxPos = $stmtPos->fetch();
|
||||
$nextPos = ($maxPos['max_pos'] ?? -1) + 1;
|
||||
|
||||
$stmt = db()->prepare("INSERT INTO channels (server_id, name, type, allow_file_sharing, message_limit, icon, category_id, position) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$server_id, $name, $type, $allow_file_sharing, $message_limit, $icon, $category_id, $nextPos]);
|
||||
$channel_id = db()->lastInsertId();
|
||||
|
||||
header('Location: index.php?server_id=' . $server_id . '&channel_id=' . $channel_id);
|
||||
|
||||
@ -134,7 +134,9 @@ body {
|
||||
|
||||
/* Channels Sidebar */
|
||||
.channels-sidebar {
|
||||
width: 240px;
|
||||
width: auto;
|
||||
min-width: 240px;
|
||||
max-width: 400px;
|
||||
background-color: var(--bg-channels);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -166,6 +168,7 @@ body {
|
||||
gap: 8px;
|
||||
margin-bottom: 2px;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.channel-item:hover {
|
||||
@ -189,7 +192,7 @@ body {
|
||||
|
||||
.channel-category {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.75em;
|
||||
font-size: 0.85em;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
@ -197,6 +200,7 @@ body {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.channel-category .channel-settings-btn,
|
||||
|
||||
4
debug_reorder.log
Normal file
4
debug_reorder.log
Normal file
@ -0,0 +1,4 @@
|
||||
2026-02-15 23:32:05 - Server: 1 - Orders: [{"id":"1","position":0,"category_id":null},{"id":"6","position":1,"category_id":null},{"id":"10","position":2,"category_id":null},{"id":"2","position":3,"category_id":null},{"id":"9","position":4,"category_id":null},{"id":"3","position":5,"category_id":null}]
|
||||
2026-02-15 23:35:48 - Server: 1 - Orders: [{"id":"10","position":0,"category_id":null},{"id":"1","position":1,"category_id":null},{"id":"6","position":2,"category_id":null},{"id":"2","position":3,"category_id":null},{"id":"9","position":4,"category_id":null},{"id":"3","position":5,"category_id":null}]
|
||||
2026-02-15 23:36:25 - Server: 1 - Orders: [{"id":"10","position":0,"category_id":null},{"id":"1","position":1,"category_id":"10"},{"id":"6","position":2,"category_id":"10"},{"id":"2","position":3,"category_id":null},{"id":"9","position":4,"category_id":null},{"id":"3","position":5,"category_id":null}]
|
||||
2026-02-15 23:36:28 - Server: 1 - Orders: [{"id":"10","position":0,"category_id":null},{"id":"1","position":1,"category_id":"10"},{"id":"6","position":2,"category_id":"10"},{"id":"2","position":3,"category_id":"10"},{"id":"9","position":4,"category_id":null},{"id":"3","position":5,"category_id":null}]
|
||||
134
index.php
134
index.php
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
// Request log
|
||||
file_put_contents('requests.log', date('Y-m-d H:i:s') . " - " . $_SERVER['REQUEST_METHOD'] . " " . $_SERVER['REQUEST_URI'] . " - POST: " . json_encode($_POST) . "\n", FILE_APPEND);
|
||||
require_once 'auth/session.php';
|
||||
|
||||
function renderRoleIcon($icon, $size = '12px') {
|
||||
@ -330,12 +332,6 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
// Separate categories and channels
|
||||
$categories = array_filter($channels, function($c) { return $c['type'] === 'category'; });
|
||||
$top_level_channels = array_filter($channels, function($c) use ($channels) {
|
||||
return $c['type'] !== 'category' && (empty($c['category_id']) || !in_array($c['category_id'], array_column($channels, 'id')));
|
||||
});
|
||||
|
||||
// Helper to render a channel item
|
||||
function renderChannelItem($c, $active_channel_id, $active_server_id, $can_manage_channels) {
|
||||
if ($c['type'] === 'separator') {
|
||||
@ -351,7 +347,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
data-files="0"
|
||||
data-limit="0"
|
||||
data-status=""
|
||||
data-icon=""
|
||||
data-icon="<?php echo htmlspecialchars($c['icon'] ?? ''); ?>"
|
||||
data-category="<?php echo $c['category_id'] ?? ''; ?>">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82 1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
</span>
|
||||
@ -401,47 +397,55 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<?php
|
||||
}
|
||||
|
||||
// Render top level channels
|
||||
if (!empty($top_level_channels)) {
|
||||
foreach($top_level_channels as $c) {
|
||||
renderChannelItem($c, $active_channel_id, $active_server_id, $can_manage_channels);
|
||||
}
|
||||
}
|
||||
$category_ids = array_column(array_filter($channels, function($c) { return $c['type'] === 'category'; }), 'id');
|
||||
|
||||
// Render categories and their channels
|
||||
foreach($categories as $cat) {
|
||||
?>
|
||||
<div class="category-wrapper" data-id="<?php echo $cat['id']; ?>">
|
||||
<div class="channel-category d-flex align-items-center mt-3" data-id="<?php echo $cat['id']; ?>">
|
||||
<span class="category-name flex-grow-1 text-uppercase fw-bold" style="font-size: 0.7em; cursor: pointer; color: var(--text-muted);"><?php echo htmlspecialchars($cat['name']); ?></span>
|
||||
<?php if ($can_manage_channels): ?>
|
||||
<span class="channel-settings-btn ms-1" style="cursor: pointer; color: var(--text-muted);"
|
||||
data-bs-toggle="modal" data-bs-target="#editChannelModal"
|
||||
data-id="<?php echo $cat['id']; ?>"
|
||||
data-name="<?php echo htmlspecialchars($cat['name']); ?>"
|
||||
data-type="category"
|
||||
data-files="0"
|
||||
data-limit="0"
|
||||
data-status=""
|
||||
data-icon=""
|
||||
data-category=""
|
||||
data-theme="">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82 1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
</span>
|
||||
<span class="add-channel-btn ms-1" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="chat" data-category-id="<?php echo $cat['id']; ?>">+</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="category-group" data-category-id="<?php echo $cat['id']; ?>">
|
||||
<?php
|
||||
foreach($channels as $c) {
|
||||
if ($c['type'] !== 'category' && $c['category_id'] == $cat['id']) {
|
||||
renderChannelItem($c, $active_channel_id, $active_server_id, $can_manage_channels);
|
||||
foreach($channels as $item) {
|
||||
// Skip channels that have a parent category (they will be rendered inside their category)
|
||||
if ($item['type'] !== 'category' && !empty($item['category_id']) && in_array($item['category_id'], $category_ids)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($item['type'] === 'category') {
|
||||
// Render category and its children
|
||||
?>
|
||||
<div class="category-wrapper" data-id="<?php echo $item['id']; ?>">
|
||||
<div class="channel-category d-flex align-items-center mt-3" data-id="<?php echo $item['id']; ?>">
|
||||
<?php if (!empty($item['icon'])): ?>
|
||||
<span class="me-1" style="font-size: 14px;"><?php echo renderRoleIcon($item['icon'], '14px'); ?></span>
|
||||
<?php endif; ?>
|
||||
<span class="category-name flex-grow-1 text-uppercase fw-bold" style="font-size: 0.85em; cursor: pointer; color: var(--text-muted);"><?php echo htmlspecialchars($item['name']); ?></span>
|
||||
<?php if ($can_manage_channels): ?>
|
||||
<span class="channel-settings-btn ms-1" style="cursor: pointer; color: var(--text-muted);"
|
||||
data-bs-toggle="modal" data-bs-target="#editChannelModal"
|
||||
data-id="<?php echo $item['id']; ?>"
|
||||
data-name="<?php echo htmlspecialchars($item['name']); ?>"
|
||||
data-type="category"
|
||||
data-files="0"
|
||||
data-limit="0"
|
||||
data-status=""
|
||||
data-icon="<?php echo htmlspecialchars($item['icon'] ?? ''); ?>"
|
||||
data-category=""
|
||||
data-theme="">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82 1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
</span>
|
||||
<span class="add-channel-btn ms-1" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="chat" data-category-id="<?php echo $item['id']; ?>">+</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="category-group" data-category-id="<?php echo $item['id']; ?>">
|
||||
<?php
|
||||
foreach($channels as $c) {
|
||||
if ($c['type'] !== 'category' && $c['category_id'] == $item['id']) {
|
||||
renderChannelItem($c, $active_channel_id, $active_server_id, $can_manage_channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
<?php
|
||||
} else {
|
||||
// Render top level channel
|
||||
renderChannelItem($item, $active_channel_id, $active_server_id, $can_manage_channels);
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?php endif; ?>
|
||||
@ -458,7 +462,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
<div class="user-actions">
|
||||
<a href="#" title="Settings" style="color: var(--text-muted); margin-right: 8px;" data-bs-toggle="modal" data-bs-target="#userSettingsModal">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82 1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33 1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
</a>
|
||||
<a href="auth/logout.php" title="Logout" style="color: var(--text-muted);"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg></a>
|
||||
</div>
|
||||
@ -1543,24 +1547,34 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
function updatePrefix(typeSelect, iconSelect, prefixSpan) {
|
||||
if (!prefixSpan || !typeSelect) return;
|
||||
|
||||
// Handle name input visibility for separator
|
||||
// Handle name input visibility for separator and category
|
||||
const modal = typeSelect.closest('.modal');
|
||||
const nameInputContainer = modal.querySelector('input[name="name"]')?.closest('.mb-3');
|
||||
const iconSelectContainer = modal.querySelector('select[name="icon"]')?.closest('.mb-3');
|
||||
const fileSharingContainer = modal.querySelector('input[name="allow_file_sharing"]')?.closest('.mb-3') || modal.querySelector('input[name="allow_file_sharing"]')?.closest('.form-check');
|
||||
const limitContainer = modal.querySelector('input[name="message_limit"]')?.closest('.mb-3');
|
||||
const categoryContainer = modal.querySelector('select[name="category_id"]')?.closest('.mb-3');
|
||||
|
||||
if (typeSelect.value === 'separator') {
|
||||
if (nameInputContainer) nameInputContainer.style.display = 'none';
|
||||
if (iconSelectContainer) iconSelectContainer.style.display = 'none';
|
||||
if (fileSharingContainer) fileSharingContainer.style.display = 'none';
|
||||
if (limitContainer) limitContainer.style.display = 'none';
|
||||
if (categoryContainer) categoryContainer.style.display = 'none';
|
||||
if (modal.querySelector('input[name="name"]')) modal.querySelector('input[name="name"]').required = false;
|
||||
} else if (typeSelect.value === 'category') {
|
||||
if (nameInputContainer) nameInputContainer.style.display = 'block';
|
||||
if (iconSelectContainer) iconSelectContainer.style.display = 'block';
|
||||
if (fileSharingContainer) fileSharingContainer.style.display = 'none';
|
||||
if (limitContainer) limitContainer.style.display = 'none';
|
||||
if (categoryContainer) categoryContainer.style.display = 'none';
|
||||
if (modal.querySelector('input[name="name"]')) modal.querySelector('input[name="name"]').required = true;
|
||||
} else {
|
||||
if (nameInputContainer) nameInputContainer.style.display = 'block';
|
||||
if (iconSelectContainer) iconSelectContainer.style.display = 'block';
|
||||
if (fileSharingContainer) fileSharingContainer.style.display = 'block';
|
||||
if (limitContainer) limitContainer.style.display = 'block';
|
||||
if (categoryContainer) categoryContainer.style.display = 'block';
|
||||
if (modal.querySelector('input[name="name"]')) modal.querySelector('input[name="name"]').required = true;
|
||||
}
|
||||
|
||||
@ -1649,6 +1663,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
groups.forEach(group => {
|
||||
new Sortable(group, {
|
||||
group: 'channels',
|
||||
draggable: '.channel-item-container',
|
||||
animation: 150,
|
||||
ghostClass: 'sortable-ghost',
|
||||
onEnd: function() {
|
||||
@ -1660,6 +1675,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
// Sortable for categories themselves and top-level channels
|
||||
const sidebar = document.getElementById('sidebar-channels-list');
|
||||
new Sortable(sidebar, {
|
||||
group: 'channels',
|
||||
animation: 150,
|
||||
draggable: '.category-wrapper, .channel-item-container:not(.category-group .channel-item-container)',
|
||||
ghostClass: 'sortable-ghost',
|
||||
@ -1679,11 +1695,13 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
const topLevelItems = sidebar.children;
|
||||
|
||||
Array.from(topLevelItems).forEach(item => {
|
||||
const itemId = item.dataset.id;
|
||||
if (!itemId) return;
|
||||
|
||||
if (item.classList.contains('category-wrapper')) {
|
||||
// It's a category
|
||||
const catId = item.dataset.id;
|
||||
orders.push({
|
||||
id: catId,
|
||||
id: itemId,
|
||||
position: position++,
|
||||
category_id: null
|
||||
});
|
||||
@ -1691,16 +1709,18 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
// Now add all channels inside this category
|
||||
const subChannels = item.querySelectorAll('.category-group .channel-item-container');
|
||||
subChannels.forEach(sub => {
|
||||
orders.push({
|
||||
id: sub.dataset.id,
|
||||
position: position++,
|
||||
category_id: catId
|
||||
});
|
||||
if (sub.dataset.id) {
|
||||
orders.push({
|
||||
id: sub.dataset.id,
|
||||
position: position++,
|
||||
category_id: itemId
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (item.classList.contains('channel-item-container')) {
|
||||
// It's a top level channel
|
||||
// It's a top level channel or separator
|
||||
orders.push({
|
||||
id: item.dataset.id,
|
||||
id: itemId,
|
||||
position: position++,
|
||||
category_id: null
|
||||
});
|
||||
@ -1713,7 +1733,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'reorder',
|
||||
server_id: <?php echo $active_server_id; ?>,
|
||||
server_id: "<?php echo $active_server_id; ?>",
|
||||
orders: orders
|
||||
})
|
||||
});
|
||||
|
||||
12
requests.log
Normal file
12
requests.log
Normal file
@ -0,0 +1,12 @@
|
||||
2026-02-15 23:22:04 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-15 23:27:59 - GET / - POST: []
|
||||
2026-02-15 23:28:03 - HEAD / - POST: []
|
||||
2026-02-15 23:28:16 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-15 23:31:59 - GET /index.php?server_id=1&channel_id=10 - POST: []
|
||||
2026-02-15 23:32:07 - GET /index.php?server_id=1&channel_id=10 - POST: []
|
||||
2026-02-15 23:32:12 - GET /index.php?server_id=1&channel_id=10 - POST: []
|
||||
2026-02-15 23:36:00 - GET /index.php?server_id=1&channel_id=10 - POST: []
|
||||
2026-02-15 23:36:17 - GET /index.php?server_id=1&channel_id=1 - POST: []
|
||||
2026-02-15 23:36:35 - GET /index.php?server_id=1&channel_id=2 - POST: []
|
||||
2026-02-15 23:38:20 - GET /index.php?server_id=1&channel_id=6 - POST: []
|
||||
2026-02-15 23:38:22 - GET /index.php?server_id=1&channel_id=1 - POST: []
|
||||
17
test_reorder.php
Normal file
17
test_reorder.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
require 'db/config.php';
|
||||
$orders = [
|
||||
['id' => 1, 'position' => 1, 'category_id' => null],
|
||||
['id' => 10, 'position' => 0, 'category_id' => null],
|
||||
['id' => 6, 'position' => 2, 'category_id' => null],
|
||||
['id' => 2, 'position' => 3, 'category_id' => null],
|
||||
['id' => 9, 'position' => 4, 'category_id' => null],
|
||||
['id' => 3, 'position' => 5, 'category_id' => null]
|
||||
];
|
||||
$server_id = 1;
|
||||
$stmt = db()->prepare("UPDATE channels SET position = ?, category_id = ? WHERE id = ? AND server_id = ?");
|
||||
foreach ($orders as $o) {
|
||||
$stmt->execute([$o['position'], $o['category_id'], $o['id'], $server_id]);
|
||||
echo "Updated ID {$o['id']} to position {$o['position']}\n";
|
||||
}
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user