ReleaseV07+Avatars
This commit is contained in:
parent
4388017d2d
commit
923147d500
@ -6,7 +6,8 @@ $action = $_GET['action'] ?? 'search';
|
||||
|
||||
if ($action === 'search') {
|
||||
$q = $_GET['query'] ?? 'avatar';
|
||||
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($q) . '&per_page=12&page=1';
|
||||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($q) . '&per_page=26&page=' . $page;
|
||||
$data = pexels_get($url);
|
||||
if (!$data) {
|
||||
echo json_encode(['error' => 'Failed to fetch images']);
|
||||
|
||||
58
api/upload_avatar.php
Normal file
58
api/upload_avatar.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../auth/session.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$user = getCurrentUser();
|
||||
if (!$user) {
|
||||
echo json_encode(['success' => false, 'error' => 'Non autorisé']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode(['success' => false, 'error' => 'Aucun fichier reçu ou erreur de téléchargement']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['avatar'];
|
||||
$allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
||||
$maxSize = 2 * 1024 * 1024; // 2MB
|
||||
|
||||
if (!in_array($file['type'], $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Format de fichier non supporté (JPG, PNG, WebP, GIF uniquement)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($file['size'] > $maxSize) {
|
||||
echo json_encode(['success' => false, 'error' => 'Le fichier est trop volumineux (max 2Mo)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
if (empty($extension)) {
|
||||
$extensions = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/webp' => 'webp',
|
||||
'image/gif' => 'gif'
|
||||
];
|
||||
$extension = $extensions[$file['type']] ?? 'jpg';
|
||||
}
|
||||
|
||||
$filename = 'avatar_' . $user['id'] . '_' . time() . '.' . $extension;
|
||||
$targetPath = __DIR__ . '/../assets/images/avatars/' . $filename;
|
||||
$relativeUrl = 'assets/images/avatars/' . $filename;
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
|
||||
// Optionally delete old local avatar if it exists
|
||||
if (!empty($user['avatar_url']) && strpos($user['avatar_url'], 'assets/images/avatars/') === 0) {
|
||||
$oldFile = __DIR__ . '/../' . $user['avatar_url'];
|
||||
if (file_exists($oldFile)) {
|
||||
unlink($oldFile);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'url' => $relativeUrl]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Erreur lors de l\'enregistrement du fichier']);
|
||||
}
|
||||
79
api/upload_server_icon.php
Normal file
79
api/upload_server_icon.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../auth/session.php';
|
||||
require_once __DIR__ . '/../includes/permissions.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$user = getCurrentUser();
|
||||
if (!$user) {
|
||||
echo json_encode(['success' => false, 'error' => 'Non autorisé']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$server_id = $_POST['server_id'] ?? 0;
|
||||
if (!$server_id) {
|
||||
echo json_encode(['success' => false, 'error' => 'ID du serveur manquant']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!Permissions::hasPermission($user['id'], $server_id, Permissions::MANAGE_SERVER)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Vous n\'avez pas la permission de gérer ce serveur']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_FILES['icon']) || $_FILES['icon']['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode(['success' => false, 'error' => 'Aucun fichier reçu ou erreur de téléchargement']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['icon'];
|
||||
$allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
||||
$maxSize = 2 * 1024 * 1024; // 2MB
|
||||
|
||||
if (!in_array($file['type'], $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Format de fichier non supporté (JPG, PNG, WebP, GIF uniquement)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($file['size'] > $maxSize) {
|
||||
echo json_encode(['success' => false, 'error' => 'Le fichier est trop volumineux (max 2Mo)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
if (empty($extension)) {
|
||||
$extensions = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/webp' => 'webp',
|
||||
'image/gif' => 'gif'
|
||||
];
|
||||
$extension = $extensions[$file['type']] ?? 'jpg';
|
||||
}
|
||||
|
||||
$filename = 'server_' . $server_id . '_' . time() . '.' . $extension;
|
||||
$dir = __DIR__ . '/../assets/images/servers/';
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
|
||||
$targetPath = $dir . $filename;
|
||||
$relativeUrl = 'assets/images/servers/' . $filename;
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
|
||||
// Optionally fetch old icon to delete it if it's local
|
||||
$stmt = db()->prepare("SELECT icon_url FROM servers WHERE id = ?");
|
||||
$stmt->execute([$server_id]);
|
||||
$server = $stmt->fetch();
|
||||
|
||||
if ($server && !empty($server['icon_url']) && strpos($server['icon_url'], 'assets/images/servers/') === 0) {
|
||||
$oldFile = __DIR__ . '/../' . $server['icon_url'];
|
||||
if (file_exists($oldFile)) {
|
||||
unlink($oldFile);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'url' => $relativeUrl]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Erreur lors de l\'enregistrement du fichier']);
|
||||
}
|
||||
BIN
assets/images/avatars/avatar_2_1771557067.png
Normal file
BIN
assets/images/avatars/avatar_2_1771557067.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
BIN
assets/images/servers/server_1_1771557116.png
Normal file
BIN
assets/images/servers/server_1_1771557116.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
@ -2544,33 +2544,125 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// User Settings - Save logic removed and moved to index.php for reliability
|
||||
|
||||
const avatarSearchBtn = document.getElementById('search-avatar-btn');
|
||||
const avatarRefreshBtn = document.getElementById('refresh-avatar-btn');
|
||||
const avatarSearchQuery = document.getElementById('avatar-search-query');
|
||||
const avatarResults = document.getElementById('avatar-results');
|
||||
const avatarPreview = document.getElementById('settings-avatar-preview');
|
||||
const avatarUrlInput = document.getElementById('settings-avatar-url');
|
||||
const avatarUploadInput = document.getElementById('avatar-upload-input');
|
||||
|
||||
avatarSearchBtn?.addEventListener('click', async () => {
|
||||
const q = avatarSearchQuery.value.trim();
|
||||
avatarUploadInput?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('avatar', file);
|
||||
|
||||
try {
|
||||
avatarPreview.innerHTML = '<div class="spinner-border spinner-border-sm text-light" role="status"></div>';
|
||||
const resp = await fetch('api/upload_avatar.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = await resp.json();
|
||||
avatarPreview.innerHTML = '';
|
||||
|
||||
if (data.success) {
|
||||
avatarUrlInput.value = data.url;
|
||||
avatarPreview.style.backgroundImage = `url('${data.url}')`;
|
||||
} else {
|
||||
alert(data.error || 'Erreur lors de l\'upload');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
avatarPreview.innerHTML = '';
|
||||
alert('Erreur réseau lors de l\'upload');
|
||||
}
|
||||
});
|
||||
|
||||
const serverIconUploadInput = document.getElementById('server-icon-upload-input');
|
||||
// serverIconPreview and serverIconUrlInput are already declared above
|
||||
|
||||
serverIconUploadInput?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('icon', file);
|
||||
formData.append('server_id', window.activeServerId);
|
||||
|
||||
try {
|
||||
serverIconPreview.innerHTML = '<div class="spinner-border spinner-border-sm text-light" role="status"></div>';
|
||||
const resp = await fetch('api/upload_server_icon.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = await resp.json();
|
||||
serverIconPreview.innerHTML = '';
|
||||
|
||||
if (data.success) {
|
||||
serverIconUrlInput.value = data.url;
|
||||
serverIconPreview.style.backgroundImage = `url('${data.url}')`;
|
||||
} else {
|
||||
alert(data.error || 'Erreur lors de l\'upload');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
serverIconPreview.innerHTML = '';
|
||||
alert('Erreur réseau lors de l\'upload');
|
||||
}
|
||||
});
|
||||
|
||||
let currentAvatarPage = 1;
|
||||
|
||||
async function fetchAvatars(q, page = 1) {
|
||||
if (!q) return;
|
||||
avatarResults.innerHTML = '<div class="text-muted small">Searching...</div>';
|
||||
try {
|
||||
const resp = await fetch(`api/pexels.php?action=search&query=${encodeURIComponent(q)}`);
|
||||
const resp = await fetch(`api/pexels.php?action=search&query=${encodeURIComponent(q)}&page=${page}`);
|
||||
const data = await resp.json();
|
||||
avatarResults.innerHTML = '';
|
||||
data.forEach(photo => {
|
||||
const img = document.createElement('img');
|
||||
img.src = photo.url;
|
||||
img.className = 'avatar-pick';
|
||||
img.style.width = '60px';
|
||||
img.style.height = '60px';
|
||||
img.style.cursor = 'pointer';
|
||||
img.onclick = () => {
|
||||
avatarUrlInput.value = photo.url;
|
||||
avatarPreview.style.backgroundImage = `url('${photo.url}')`;
|
||||
};
|
||||
avatarResults.appendChild(img);
|
||||
});
|
||||
} catch (e) { console.error(e); }
|
||||
if (data && Array.isArray(data)) {
|
||||
data.forEach(photo => {
|
||||
const img = document.createElement('img');
|
||||
img.src = photo.url;
|
||||
img.className = 'avatar-pick';
|
||||
img.style.width = '100%';
|
||||
img.style.height = 'auto';
|
||||
img.style.aspectRatio = '1/1';
|
||||
img.style.objectFit = 'cover';
|
||||
img.style.borderRadius = '4px';
|
||||
img.style.cursor = 'pointer';
|
||||
img.onclick = () => {
|
||||
avatarUrlInput.value = photo.url;
|
||||
avatarPreview.style.backgroundImage = `url('${photo.url}')`;
|
||||
};
|
||||
avatarResults.appendChild(img);
|
||||
});
|
||||
} else {
|
||||
avatarResults.innerHTML = '<div class="text-muted small">Aucun résultat trouvé.</div>';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
avatarResults.innerHTML = '<div class="text-danger small">Erreur lors de la récupération.</div>';
|
||||
}
|
||||
}
|
||||
|
||||
avatarSearchBtn?.addEventListener('click', () => {
|
||||
currentAvatarPage = 1;
|
||||
fetchAvatars(avatarSearchQuery.value.trim(), currentAvatarPage);
|
||||
});
|
||||
|
||||
avatarRefreshBtn?.addEventListener('click', () => {
|
||||
currentAvatarPage++;
|
||||
fetchAvatars(avatarSearchQuery.value.trim() || 'avatar', currentAvatarPage);
|
||||
});
|
||||
|
||||
avatarSearchQuery?.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
currentAvatarPage = 1;
|
||||
fetchAvatars(avatarSearchQuery.value.trim(), currentAvatarPage);
|
||||
}
|
||||
});
|
||||
|
||||
// Theme preview
|
||||
|
||||
86
index.php
86
index.php
@ -264,6 +264,18 @@ if ($is_dm_view) {
|
||||
}
|
||||
}
|
||||
|
||||
// Always fetch tags if it's a forum channel
|
||||
if ($channel_type === 'forum') {
|
||||
$stmt_tags = db()->prepare("SELECT * FROM forum_tags WHERE channel_id = ? ORDER BY name ASC");
|
||||
$stmt_tags->execute([$active_channel_id]);
|
||||
$forum_tags = $stmt_tags->fetchAll();
|
||||
|
||||
$selected_tag_ids = [];
|
||||
if (!empty($_GET['tags'])) {
|
||||
$selected_tag_ids = array_filter(explode(',', $_GET['tags']), 'is_numeric');
|
||||
}
|
||||
}
|
||||
|
||||
if ($active_thread) {
|
||||
// Thread messages already fetched above
|
||||
} elseif ($channel_type === 'rules') {
|
||||
@ -275,12 +287,13 @@ if ($is_dm_view) {
|
||||
$stmt->execute([$active_channel_id]);
|
||||
$autoroles = $stmt->fetchAll();
|
||||
} elseif ($channel_type === 'forum') {
|
||||
$filter_status = $_GET['status'] ?? 'all';
|
||||
$status_where = "";
|
||||
if ($filter_status === 'resolved') {
|
||||
$status_where = " AND t.solution_message_id IS NOT NULL";
|
||||
} elseif ($filter_status === 'unresolved') {
|
||||
$status_where = " AND t.solution_message_id IS NULL";
|
||||
$tag_where = "";
|
||||
$query_params = [$active_server_id, $active_server_id, $active_channel_id];
|
||||
|
||||
if (!empty($selected_tag_ids)) {
|
||||
$placeholders = implode(',', array_fill(0, count($selected_tag_ids), '?'));
|
||||
$tag_where = " AND EXISTS (SELECT 1 FROM thread_tags tt WHERE tt.thread_id = t.id AND tt.tag_id IN ($placeholders))";
|
||||
foreach ($selected_tag_ids as $tid) $query_params[] = $tid;
|
||||
}
|
||||
|
||||
$stmt = db()->prepare("
|
||||
@ -291,10 +304,10 @@ if ($is_dm_view) {
|
||||
(SELECT GROUP_CONCAT(CONCAT(ft.name, ':', ft.color) SEPARATOR '|') FROM thread_tags tt JOIN forum_tags ft ON tt.tag_id = ft.id WHERE tt.thread_id = t.id) as tags
|
||||
FROM forum_threads t
|
||||
JOIN users u ON t.user_id = u.id
|
||||
WHERE t.channel_id = ? " . $status_where . "
|
||||
WHERE t.channel_id = ? " . $tag_where . "
|
||||
ORDER BY t.is_pinned DESC, t.last_activity_at DESC, t.created_at DESC
|
||||
");
|
||||
$stmt->execute([$active_server_id, $active_server_id, $active_channel_id]);
|
||||
$stmt->execute($query_params);
|
||||
$threads = $stmt->fetchAll();
|
||||
} else {
|
||||
// Fetch messages for normal chat channels
|
||||
@ -924,20 +937,31 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php elseif($channel_type === 'forum'): ?>
|
||||
<?php elseif($channel_type === 'forum' && !$active_thread): ?>
|
||||
<div class="forum-container p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h2 class="mb-2">🏛️ <?php echo htmlspecialchars($current_channel_name); ?></h2>
|
||||
<div class="btn-group btn-group-sm forum-filters">
|
||||
<div class="btn-group btn-group-sm forum-filters flex-wrap gap-1">
|
||||
<?php
|
||||
$s_id = $active_server_id;
|
||||
$c_id = $active_channel_id;
|
||||
$curr_status = $_GET['status'] ?? 'all';
|
||||
?>
|
||||
<a href="?server_id=<?php echo $s_id; ?>&channel_id=<?php echo $c_id; ?>&status=all" class="btn btn-outline-secondary <?php echo $curr_status === 'all' ? 'active' : ''; ?>">Tous</a>
|
||||
<a href="?server_id=<?php echo $s_id; ?>&channel_id=<?php echo $c_id; ?>&status=unresolved" class="btn btn-outline-secondary <?php echo $curr_status === 'unresolved' ? 'active' : ''; ?>">Non résolus</a>
|
||||
<a href="?server_id=<?php echo $s_id; ?>&channel_id=<?php echo $c_id; ?>&status=resolved" class="btn btn-outline-secondary <?php echo $curr_status === 'resolved' ? 'active' : ''; ?>">Résolus</a>
|
||||
<a href="?server_id=<?php echo $s_id; ?>&channel_id=<?php echo $c_id; ?>" class="btn btn-outline-secondary <?php echo empty($selected_tag_ids) ? 'active' : ''; ?>">Tous</a>
|
||||
<?php foreach($forum_tags as $tag):
|
||||
$is_active = in_array($tag['id'], $selected_tag_ids);
|
||||
if ($is_active) {
|
||||
$new_tags = array_diff($selected_tag_ids, [$tag['id']]);
|
||||
} else {
|
||||
$new_tags = array_merge($selected_tag_ids, [$tag['id']]);
|
||||
}
|
||||
$tags_query = !empty($new_tags) ? '&tags=' . implode(',', $new_tags) : '';
|
||||
$tag_url = "?server_id=$s_id&channel_id=$c_id$tags_query";
|
||||
?>
|
||||
<a href="<?php echo $tag_url; ?>" class="btn btn-outline-secondary <?php echo $is_active ? 'active' : ''; ?>" style="<?php echo $is_active ? "background-color: {$tag['color']}; border-color: {$tag['color']}; color: white;" : ""; ?>">
|
||||
<?php echo htmlspecialchars($tag['name']); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
@ -954,7 +978,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<div class="text-center text-muted mt-5">Pas encore de discussions. Commencez-en une !</div>
|
||||
<?php endif; ?>
|
||||
<?php foreach($threads as $thread): ?>
|
||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?>&thread_id=<?php echo $thread['id']; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="thread-item d-flex align-items-center p-3 mb-2 rounded bg-dark text-decoration-none text-white border-start border-4 <?php echo $thread['is_pinned'] ? 'border-primary' : 'border-secondary'; ?>">
|
||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?>&thread_id=<?php echo $thread['id']; ?><?php echo !empty($selected_tag_ids) ? '&tags='.implode(',', $selected_tag_ids) : ''; ?>" class="thread-item d-flex align-items-center p-3 mb-2 rounded bg-dark text-decoration-none text-white border-start border-4 <?php echo $thread['is_pinned'] ? 'border-primary' : 'border-secondary'; ?>">
|
||||
<div class="thread-icon me-3">
|
||||
<?php if($thread['is_pinned']): ?>
|
||||
<i class="fa-solid fa-thumbtack text-primary"></i>
|
||||
@ -997,6 +1021,23 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php if ($active_thread): ?>
|
||||
<div class="p-3 border-bottom border-secondary d-flex justify-content-between align-items-center bg-dark bg-opacity-25 sticky-top" style="z-index: 10;">
|
||||
<div>
|
||||
<h4 class="mb-0">
|
||||
<?php if($active_thread['is_pinned']): ?><i class="fa-solid fa-thumbtack text-primary me-2 small"></i><?php endif; ?>
|
||||
<?php if($active_thread['is_locked']): ?><i class="fa-solid fa-lock text-warning me-2 small"></i><?php endif; ?>
|
||||
<?php echo htmlspecialchars($active_thread['title']); ?>
|
||||
</h4>
|
||||
<div class="small text-muted mt-1">
|
||||
Par <?php echo htmlspecialchars($active_thread['username']); ?> • Dans #<?php echo htmlspecialchars($current_channel_name); ?>
|
||||
</div>
|
||||
</div>
|
||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?><?php echo !empty($selected_tag_ids) ? '&tags='.implode(',', $selected_tag_ids) : ''; ?>" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="fa-solid fa-arrow-left me-1"></i> Retour au forum
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if(empty($messages)): ?>
|
||||
<div style="text-align: center; color: var(--text-muted); margin-top: 40px;">
|
||||
<h4>Bienvenue dans #<?php echo htmlspecialchars($current_channel_name); ?> !</h4>
|
||||
@ -1239,6 +1280,10 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<div class="col-md-3 text-center">
|
||||
<div class="message-avatar mx-auto mb-2" id="settings-avatar-preview" style="width: 80px; height: 80px; <?php echo $user['avatar_url'] ? "background-image: url('{$user['avatar_url']}');" : ""; ?>"></div>
|
||||
<input type="hidden" name="avatar_url" id="settings-avatar-url" value="<?php echo htmlspecialchars($user['avatar_url'] ?? ''); ?>">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary w-100 mt-2" onclick="document.getElementById('avatar-upload-input').click()">
|
||||
<i class="fas fa-upload me-1"></i> Importer
|
||||
</button>
|
||||
<input type="file" id="avatar-upload-input" style="display: none;" accept="image/*">
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="mb-3">
|
||||
@ -1253,8 +1298,9 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<div class="input-group mb-2 shadow-sm">
|
||||
<input type="text" id="avatar-search-query" class="form-control bg-dark border-0 text-white" placeholder="ex: chat, abstrait, gamer">
|
||||
<button class="btn btn-primary px-3" type="button" id="search-avatar-btn">Rechercher</button>
|
||||
<button class="btn btn-secondary px-3" type="button" id="refresh-avatar-btn" title="Rafraîchir les propositions"><i class="fas fa-sync-alt"></i></button>
|
||||
</div>
|
||||
<div id="avatar-results" class="d-flex flex-wrap gap-2 overflow-auto p-2 rounded settings-inner-bg" style="max-height: 180px;">
|
||||
<div id="avatar-results" class="d-grid gap-2 overflow-auto p-2 rounded settings-inner-bg" style="max-height: 220px; grid-template-columns: repeat(13, 1fr);">
|
||||
<div class="w-100 text-center text-muted py-3 small">Recherchez des images pour changer votre avatar.</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1858,7 +1904,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
?>
|
||||
<div class="message-avatar mx-auto mb-2" id="server-icon-preview" style="width: 80px; height: 80px; <?php echo $active_icon ? "background-image: url('{$active_icon}');" : ""; ?>"></div>
|
||||
<input type="hidden" name="icon_url" id="server-icon-url" value="<?php echo htmlspecialchars($active_icon); ?>">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" id="search-server-icon-btn">Changer l'icône</button>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" id="search-server-icon-btn">Rechercher</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="document.getElementById('server-icon-upload-input').click()">
|
||||
<i class="fas fa-upload me-1"></i> Importer
|
||||
</button>
|
||||
<input type="file" id="server-icon-upload-input" style="display: none;" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user