mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-23 15:18:16 +02:00
feat: highlight notes created via API with red background
- Add created_via column to notes table (values: 'web' or 'api') - Mark notes created via POST /api/notes/full as 'api' - Display light red background for API-created notes in dashboard - Add "API" badge with lightning icon for visual identification
This commit is contained in:
4 files changed
+24
-5
No files matched your search
@@ -123,11 +123,22 @@ async function initDatabase() {
|
|||||||
archived BOOLEAN DEFAULT FALSE,
|
archived BOOLEAN DEFAULT FALSE,
|
||||||
archived_at TIMESTAMP,
|
archived_at TIMESTAMP,
|
||||||
priority INTEGER DEFAULT 0,
|
priority INTEGER DEFAULT 0,
|
||||||
|
created_via VARCHAR(20) DEFAULT 'web',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
// Migration: ajouter la colonne created_via si elle n'existe pas
|
||||||
|
await client.query(`
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'notes' AND column_name = 'created_via') THEN
|
||||||
|
ALTER TABLE notes ADD COLUMN created_via VARCHAR(20) DEFAULT 'web';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
`);
|
||||||
|
|
||||||
// Table note_todos
|
// Table note_todos
|
||||||
await client.query(`
|
await client.query(`
|
||||||
CREATE TABLE IF NOT EXISTS note_todos (
|
CREATE TABLE IF NOT EXISTS note_todos (
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ router.get('/', async (req, res) => {
|
|||||||
const notes = await getAll(`
|
const notes = await getAll(`
|
||||||
SELECT
|
SELECT
|
||||||
n.id, n.title, n.content, n.image_filename, n.archived, n.priority,
|
n.id, n.title, n.content, n.image_filename, n.archived, n.priority,
|
||||||
n.created_at, n.updated_at,
|
n.created_via, n.created_at, n.updated_at,
|
||||||
(SELECT COUNT(*) FROM note_todos WHERE note_id = n.id) as todos_count,
|
(SELECT COUNT(*) FROM note_todos WHERE note_id = n.id) as todos_count,
|
||||||
(SELECT COUNT(*) FROM note_todos WHERE note_id = n.id AND completed = TRUE) as todos_completed
|
(SELECT COUNT(*) FROM note_todos WHERE note_id = n.id AND completed = TRUE) as todos_completed
|
||||||
FROM notes n
|
FROM notes n
|
||||||
@@ -242,10 +242,10 @@ router.post('/full',
|
|||||||
|
|
||||||
logger.info(`[CREATE NOTE FULL] Début création - user_id: ${req.user.id}, title: "${title}", todos: ${todos.length}, tags: ${tags.length}`);
|
logger.info(`[CREATE NOTE FULL] Début création - user_id: ${req.user.id}, title: "${title}", todos: ${todos.length}, tags: ${tags.length}`);
|
||||||
|
|
||||||
// 1. Créer la note
|
// 1. Créer la note (marquée comme créée via API)
|
||||||
const noteResult = await runQuery(`
|
const noteResult = await runQuery(`
|
||||||
INSERT INTO notes (user_id, title, content)
|
INSERT INTO notes (user_id, title, content, created_via)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3, 'api')
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`, [req.user.id, title, content || '']);
|
`, [req.user.id, title, content || '']);
|
||||||
|
|
||||||
@@ -325,6 +325,7 @@ router.post('/full',
|
|||||||
image_filename: null,
|
image_filename: null,
|
||||||
archived: false,
|
archived: false,
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
created_via: 'api',
|
||||||
todos: createdTodos,
|
todos: createdTodos,
|
||||||
tags: createdTags,
|
tags: createdTags,
|
||||||
images: [],
|
images: [],
|
||||||
|
|||||||
+7
-1
@@ -1397,7 +1397,7 @@ const Index = () => {
|
|||||||
paginatedNotes.map(note => (
|
paginatedNotes.map(note => (
|
||||||
<Card
|
<Card
|
||||||
key={note.id}
|
key={note.id}
|
||||||
className="cursor-pointer hover:shadow-md transition-all group relative"
|
className={`cursor-pointer hover:shadow-md transition-all group relative ${note.created_via === 'api' ? 'bg-red-50 dark:bg-red-950/30 border-red-200 dark:border-red-900' : ''}`}
|
||||||
onClick={() => handleOpenNote(note)}
|
onClick={() => handleOpenNote(note)}
|
||||||
>
|
>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
@@ -1451,6 +1451,12 @@ const Index = () => {
|
|||||||
{note.content ? cleanHtmlContent(note.content) : "Note vide"}
|
{note.content ? cleanHtmlContent(note.content) : "Note vide"}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-2 flex-wrap mb-2">
|
<div className="flex gap-2 flex-wrap mb-2">
|
||||||
|
{note.created_via === 'api' && (
|
||||||
|
<Badge className="bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300 text-xs">
|
||||||
|
<Zap className="h-3 w-3 mr-1" />
|
||||||
|
API
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
{note.todos && note.todos.length > 0 && (
|
{note.todos && note.todos.length > 0 && (
|
||||||
<Badge variant="secondary">
|
<Badge variant="secondary">
|
||||||
<CheckSquare className="h-3 w-3 mr-1" />
|
<CheckSquare className="h-3 w-3 mr-1" />
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export interface Note {
|
|||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
archived?: boolean;
|
archived?: boolean;
|
||||||
|
created_via?: 'web' | 'api';
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
todos: Todo[];
|
todos: Todo[];
|
||||||
|
|||||||
Reference in new issue
Block a user