mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-24 15:48:16 +02:00
Merge pull request #57 from R0m1k3/claude/integrate-google-calendar-api-011CV44Nie9HB7U35ArSUnNa
Feature: Flux RSS avec 14 articles et pagination
This commit is contained in:
2 files changed
+15
-78
No files matched your search
@@ -157,15 +157,17 @@ const ARTICLES_CACHE_DURATION = 30000; // 30 secondes
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/rss/articles
|
* GET /api/rss/articles
|
||||||
* Récupérer les 5 derniers articles (avec cache)
|
* Récupérer les articles RSS (avec cache et paramètre limit)
|
||||||
*/
|
*/
|
||||||
router.get('/articles', async (req, res) => {
|
router.get('/articles', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
const limit = parseInt(req.query.limit) || 5;
|
||||||
|
|
||||||
// Utiliser le cache si disponible et récent
|
// Utiliser le cache si disponible et récent
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (articlesCache && (now - articlesCacheTime) < ARTICLES_CACHE_DURATION) {
|
if (articlesCache && (now - articlesCacheTime) < ARTICLES_CACHE_DURATION) {
|
||||||
logger.debug('Articles RSS servis depuis le cache');
|
logger.debug('Articles RSS servis depuis le cache');
|
||||||
return res.json(articlesCache);
|
return res.json(articlesCache.slice(0, limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
const articles = await getAll(`
|
const articles = await getAll(`
|
||||||
@@ -176,8 +178,8 @@ router.get('/articles', async (req, res) => {
|
|||||||
LEFT JOIN rss_feeds f ON a.feed_id = f.id
|
LEFT JOIN rss_feeds f ON a.feed_id = f.id
|
||||||
WHERE a.pub_date IS NOT NULL
|
WHERE a.pub_date IS NOT NULL
|
||||||
ORDER BY a.pub_date DESC
|
ORDER BY a.pub_date DESC
|
||||||
LIMIT 5
|
LIMIT ?
|
||||||
`);
|
`, [limit]);
|
||||||
|
|
||||||
// Mettre en cache
|
// Mettre en cache
|
||||||
articlesCache = articles || [];
|
articlesCache = articles || [];
|
||||||
|
|||||||
+9
-74
@@ -223,16 +223,15 @@ const Index = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loadOpenRouterModels = async () => {
|
const loadOpenRouterModels = async () => {
|
||||||
if (settings.openrouter_api_key) {
|
setLoadingModels(true);
|
||||||
setLoadingModels(true);
|
try {
|
||||||
try {
|
const models = await OpenRouterService.getModels();
|
||||||
const models = await OpenRouterService.getModels();
|
setOpenRouterModels(models);
|
||||||
setOpenRouterModels(models);
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error("Erreur lors du chargement des modèles:", error);
|
||||||
console.error("Erreur lors du chargement des modèles:", error);
|
setOpenRouterModels([]); // Vider en cas d'erreur
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingModels(false);
|
setLoadingModels(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1934,70 +1933,6 @@ const Index = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Label htmlFor="ai-model">Modèle IA</Label>
|
|
||||||
{settings.openrouter_api_key && (
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={async () => {
|
|
||||||
try {
|
|
||||||
setLoadingModels(true);
|
|
||||||
const models = await OpenRouterService.refreshModels();
|
|
||||||
setOpenRouterModels(models);
|
|
||||||
showSuccess(`${models.length} modèles chargés`);
|
|
||||||
} catch (error) {
|
|
||||||
showError("Erreur lors du chargement des modèles");
|
|
||||||
} finally {
|
|
||||||
setLoadingModels(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={loadingModels}
|
|
||||||
>
|
|
||||||
<RefreshCw className={`h-4 w-4 mr-2 ${loadingModels ? 'animate-spin' : ''}`} />
|
|
||||||
Actualiser les modèles
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{settings.openrouter_api_key && openRouterModels.length > 0 ? (
|
|
||||||
<Select
|
|
||||||
value={settings.ai_model || ''}
|
|
||||||
onValueChange={(value) => setSettings({ ...settings, ai_model: value })}
|
|
||||||
>
|
|
||||||
<SelectTrigger id="ai-model">
|
|
||||||
<SelectValue placeholder="Sélectionnez un modèle" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{openRouterModels.map((model) => (
|
|
||||||
<SelectItem key={model.id} value={model.id}>
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<span className="font-medium">{model.name}</span>
|
|
||||||
{model.description && (
|
|
||||||
<span className="text-xs text-muted-foreground line-clamp-1">
|
|
||||||
{model.description}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
) : (
|
|
||||||
<Input
|
|
||||||
id="ai-model"
|
|
||||||
placeholder="anthropic/claude-3-sonnet"
|
|
||||||
value={settings.ai_model || ''}
|
|
||||||
onChange={(e) => setSettings({ ...settings, ai_model: e.target.value })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
{settings.openrouter_api_key
|
|
||||||
? `${openRouterModels.length} modèles disponibles. Cliquez sur "Actualiser" pour charger la liste.`
|
|
||||||
: "Ajoutez d'abord une clé API pour voir les modèles disponibles."}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button onClick={handleSaveSettings} className="flex items-center gap-2">
|
<Button onClick={handleSaveSettings} className="flex items-center gap-2">
|
||||||
<Zap className="h-4 w-4" />
|
<Zap className="h-4 w-4" />
|
||||||
|
|||||||
Reference in new issue
Block a user