Skip to content

feat: add internal notes for collection attributes (#11945)#2984

Open
AviArora02-commits wants to merge 8 commits intoappwrite:mainfrom
AviArora02-commits:feat/attribute-notes-11945
Open

feat: add internal notes for collection attributes (#11945)#2984
AviArora02-commits wants to merge 8 commits intoappwrite:mainfrom
AviArora02-commits:feat/attribute-notes-11945

Conversation

@AviArora02-commits
Copy link
Copy Markdown

Summary

Adds support for internal notes on collection attributes, allowing better documentation and context management within the console.

Changes

  • Added AttributeNote.svelte component for displaying and managing notes
  • Created attributeNotes.ts store for handling state and logic
  • Integrated notes functionality into attribute-related UI

Testing

  • Verified UI renders correctly for attributes with and without notes
  • Ensured notes persist and update properly through the store

Related Issue

Closes #11945

Notes

  • This introduces a new UI component and store for attribute-level notes
  • No breaking changes observed

Copilot AI review requested due to automatic review settings April 20, 2026 12:01
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 20, 2026

Greptile Summary

Adds a new AttributeNote component and attributeNotes localStorage store to let users annotate collection columns with inline notes. Two P1 issues need attention before merging:

  • The attributeKey prop is derived as column.$id || column.key, which can produce different storage keys across renders and silently lose a saved note if $id is not consistently present — column.key should be used unconditionally.
  • deleteColumn.svelte doesn't call attributeNotes.deleteNote() on deletion, leaving orphaned entries in localStorage for every deleted column.

Confidence Score: 4/5

Not safe to merge until the storage key inconsistency and missing cleanup on column deletion are resolved.

Two P1 findings: the $id || key storage key can silently mismatch across renders, and notes are never cleaned up when columns are deleted. Both have straightforward fixes.

+page.svelte (storage key), deleteColumn.svelte (missing deleteNote call)

Important Files Changed

Filename Overview
src/lib/components/AttributeNote.svelte New component for inline attribute notes; uses manual local state updates as a workaround for the non-reactive getNote pattern, which is fragile for external store changes.
src/lib/stores/attributeNotes.ts New localStorage-backed store for attribute notes; isNotesMap type guard doesn't validate string values, and getNote bypasses in-memory store state.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte Integrates AttributeNote into the columns list; uses column.$id
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/deleteColumn.svelte Column deletion flow never calls attributeNotes.deleteNote(), leaving orphaned note entries in localStorage.

Comments Outside Diff (1)

  1. src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/deleteColumn.svelte, line 43-51 (link)

    P1 Notes not cleaned up on column deletion

    deleteNote is defined in the store but never called here. When a column is deleted its note remains in localStorage indefinitely, slowly accumulating orphaned entries. Call attributeNotes.deleteNote() for each deleted key after the API call succeeds.

Reviews (4): Last reviewed commit: "Potential fix for pull request finding" | Re-trigger Greptile

Comment thread src/lib/components/AttributeNote.svelte
Comment thread src/lib/components/AttributeNote.svelte Outdated
Comment thread src/lib/stores/attributeNotes.ts
Comment on lines +66 to +69
getNote(databaseId: string, collectionId: string, attributeKey: string): string {
const notes = loadFromStorage();
return notes[buildNoteKey(databaseId, collectionId, attributeKey)] ?? '';
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 getNote reads localStorage directly, bypassing in-memory store state

getNote calls loadFromStorage() rather than reading from the writable store's current value. This means it always does a fresh synchronous localStorage parse on every call and is architecturally inconsistent — the store maintains an in-memory copy precisely to avoid this. The component also calls this once at mount time (line 30 of AttributeNote.svelte) and never re-reads it, creating a stale-read risk for any caller that doesn't already subscribe. Reading from the in-memory store value (via svelte/store's get) would be consistent with how the rest of the codebase handles writable stores.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a console-only “internal notes” capability for database collection attributes by introducing a localStorage-backed store and a reusable UI component to view/edit notes.

Changes:

  • Added attributeNotes store to persist attribute notes in localStorage
  • Added AttributeNote.svelte inline editor/display component for notes

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/lib/stores/attributeNotes.ts New localStorage-backed Svelte store for attribute notes (get/set/delete/reload).
src/lib/components/AttributeNote.svelte New UI component to view/add/edit/remove an attribute note.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +43
function loadFromStorage(): NotesMap {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return {};
return JSON.parse(raw) as NotesMap;
} catch {
return {};
}
Comment on lines +36 to +55
function loadFromStorage(): NotesMap {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return {};
return JSON.parse(raw) as NotesMap;
} catch {
return {};
}
}

/**
* Persist notes map to localStorage.
*/
function saveToStorage(notes: NotesMap): void {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(notes));
} catch {
// Silently ignore storage errors (e.g. private browsing quota)
}
}
Comment thread src/lib/stores/attributeNotes.ts Outdated
Comment on lines +83 to +84
if (note.trim()) {
updated[key] = note;
Comment on lines +19 to +30
import { attributeNotes } from '$lib/stores/attributeNotes';

interface Props {
databaseId: string;
collectionId: string;
attributeKey: string;
}

let { databaseId, collectionId, attributeKey }: Props = $props();

// Current persisted note value
let note = $state(attributeNotes.getNote(databaseId, collectionId, attributeKey));
Comment on lines +27 to +37
let { databaseId, collectionId, attributeKey }: Props = $props();

// Current persisted note value
let note = $state(attributeNotes.getNote(databaseId, collectionId, attributeKey));

// Whether the inline editor is open
let editing = $state(false);

// Draft copy while the user types
let draft = $state(note);

Comment thread src/lib/components/AttributeNote.svelte Outdated
maxlength="500"
onkeydown={handleKeydown}></textarea>
<div class="attribute-note__editor-actions">
<span class="attribute-note__hint">Ctrl+Enter to save · Esc to cancel</span>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a console-only “internal notes” feature for database collection attributes/columns, backed by a localStorage store and surfaced inline in the columns UI.

Changes:

  • Added AttributeNote.svelte inline editor/display component for per-attribute notes
  • Created attributeNotes.ts store to persist notes in localStorage
  • Integrated the note component into the table columns page

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/columns/+page.svelte Renders the new AttributeNote UI for each column in the columns list
src/lib/stores/attributeNotes.ts Introduces a localStorage-backed store for reading/writing notes keyed by database/collection/attribute
src/lib/components/AttributeNote.svelte New reusable inline note editor/display component
bun.lock Lockfile updates (adds integrity hashes for existing dependencies)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +74 to +77
getNote(databaseId: string, collectionId: string, attributeKey: string): string {
const notes = loadFromStorage();
return notes[buildNoteKey(databaseId, collectionId, attributeKey)] ?? '';
},
* Load notes map from localStorage, returning an empty object on any error.
*/
function isNotesMap(value: unknown): value is NotesMap {
return typeof value === 'object' && value !== null && !Array.isArray(value);
Comment thread src/lib/components/AttributeNote.svelte
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants