From e9b7f17900299feb8a51ff9484fa990835404a61 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 22 Nov 2025 13:45:34 +0000 Subject: [PATCH] fix: SearXNG printf command + edit site modal SearXNG: - Use proper command list format instead of shell string - Use printf with \n for proper newlines in limiter.toml - Use exec to properly start the entrypoint Edit Site Modal: - Add Dialog component import - Add siteModalOpen and editSiteData state - Create proper modal with form for editing sites - Modal opens when clicking edit button - All site fields editable in modal --- docker-compose.yml | 17 +++--- frontend/src/pages/Settings.jsx | 105 +++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 12 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f30bd08..591f662 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -62,16 +62,13 @@ services: - SEARXNG_SECRET=priceflow-searxng-secret volumes: - ./searxng/settings.yml:/etc/searxng/settings.yml:ro - command: > - sh -c " - rm -rf /etc/searxng/limiter.toml && - echo '[botdetection.ip_limit] - link_token = false - [botdetection.ip_lists] - pass_ip = [\"0.0.0.0/0\", \"127.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\", \"10.0.0.0/8\", \"::/0\"] - block_ip = []' > /etc/searxng/limiter.toml && - /usr/local/searxng/dockerfiles/docker-entrypoint.sh - " + command: + - sh + - -c + - | + rm -rf /etc/searxng/limiter.toml + printf '[botdetection.ip_limit]\nlink_token = false\n\n[botdetection.ip_lists]\npass_ip = ["0.0.0.0/0", "127.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "10.0.0.0/8", "::/0"]\nblock_ip = []\n' > /etc/searxng/limiter.toml + exec /usr/local/searxng/dockerfiles/docker-entrypoint.sh networks: - nginx_default diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 4df1697..dc3d03e 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -9,6 +9,7 @@ import { Switch } from '@/components/ui/switch'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Slider } from '@/components/ui/slider'; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'; import { cn } from '@/lib/utils'; const API_URL = '/api'; @@ -58,6 +59,8 @@ export default function Settings() { const [searchSites, setSearchSites] = useState([]); const [newSite, setNewSite] = useState({ name: '', domain: '', category: '', is_active: true, priority: 0, requires_js: false, price_selector: '' }); const [editingSiteId, setEditingSiteId] = useState(null); + const [siteModalOpen, setSiteModalOpen] = useState(false); + const [editSiteData, setEditSiteData] = useState(null); // OpenRouter state const [openrouterModels, setOpenrouterModels] = useState([]); @@ -260,7 +263,8 @@ export default function Settings() { }; const editSite = (site) => { - setNewSite({ + setEditSiteData({ + id: site.id, name: site.name, domain: site.domain, category: site.category || '', @@ -269,7 +273,21 @@ export default function Settings() { requires_js: site.requires_js, price_selector: site.price_selector || '' }); - setEditingSiteId(site.id); + setSiteModalOpen(true); + }; + + const handleEditSiteSubmit = async (e) => { + e.preventDefault(); + if (!editSiteData) return; + try { + await axios.put(`${API_URL}/search-sites/${editSiteData.id}`, editSiteData); + toast.success('Site mis à jour'); + setSiteModalOpen(false); + setEditSiteData(null); + fetchAll(); + } catch (error) { + toast.error('Erreur lors de la mise à jour'); + } }; const cancelSiteEdit = () => { @@ -836,6 +854,89 @@ export default function Settings() { + + {/* Modal d'édition de site */} + + + + Modifier le site + + {editSiteData && ( +
+
+
+ + setEditSiteData({ ...editSiteData, name: e.target.value })} + /> +
+
+ + setEditSiteData({ ...editSiteData, domain: e.target.value })} + /> +
+
+
+
+ + setEditSiteData({ ...editSiteData, category: e.target.value })} + placeholder="ex: Électronique" + /> +
+
+ + setEditSiteData({ ...editSiteData, priority: parseInt(e.target.value) || 0 })} + /> +
+
+
+ + setEditSiteData({ ...editSiteData, price_selector: e.target.value })} + placeholder="ex: .price, #product-price" + /> +

Sélecteur CSS pour extraire le prix

+
+
+
+ setEditSiteData({ ...editSiteData, is_active: checked })} + /> + +
+
+ setEditSiteData({ ...editSiteData, requires_js: checked })} + /> + +
+
+ + + + +
+ )} +
+
); }