mirror of
https://github.com/R0m1k3/Priceflow.git
synced 2026-10-11 17:29:14 +02:00
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
This commit is contained in:
2 files changed
+110
-12
No files matched your search
+7
-10
@@ -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
|
||||
|
||||
|
||||
@@ -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() {
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Modal d'édition de site */}
|
||||
<Dialog open={siteModalOpen} onOpenChange={setSiteModalOpen}>
|
||||
<DialogContent className="sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Modifier le site</DialogTitle>
|
||||
</DialogHeader>
|
||||
{editSiteData && (
|
||||
<form onSubmit={handleEditSiteSubmit} className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Nom du site</Label>
|
||||
<Input
|
||||
required
|
||||
value={editSiteData.name}
|
||||
onChange={(e) => setEditSiteData({ ...editSiteData, name: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Domaine</Label>
|
||||
<Input
|
||||
required
|
||||
value={editSiteData.domain}
|
||||
onChange={(e) => setEditSiteData({ ...editSiteData, domain: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Catégorie</Label>
|
||||
<Input
|
||||
value={editSiteData.category}
|
||||
onChange={(e) => setEditSiteData({ ...editSiteData, category: e.target.value })}
|
||||
placeholder="ex: Électronique"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Priorité</Label>
|
||||
<Input
|
||||
type="number"
|
||||
min="0"
|
||||
value={editSiteData.priority}
|
||||
onChange={(e) => setEditSiteData({ ...editSiteData, priority: parseInt(e.target.value) || 0 })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Sélecteur CSS (prix)</Label>
|
||||
<Input
|
||||
value={editSiteData.price_selector}
|
||||
onChange={(e) => setEditSiteData({ ...editSiteData, price_selector: e.target.value })}
|
||||
placeholder="ex: .price, #product-price"
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">Sélecteur CSS pour extraire le prix</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
checked={editSiteData.is_active}
|
||||
onCheckedChange={(checked) => setEditSiteData({ ...editSiteData, is_active: checked })}
|
||||
/>
|
||||
<Label>Actif</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
checked={editSiteData.requires_js}
|
||||
onCheckedChange={(checked) => setEditSiteData({ ...editSiteData, requires_js: checked })}
|
||||
/>
|
||||
<Label>Nécessite JavaScript</Label>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setSiteModalOpen(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button type="submit">
|
||||
Enregistrer
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user