hazo_notes 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -12
- package/SETUP_CHECKLIST.md +28 -12
- package/dist/api/create_notes_handler.d.ts.map +1 -1
- package/dist/api/create_notes_handler.js +40 -21
- package/dist/api/create_notes_handler.js.map +1 -1
- package/dist/components/hazo_notes_entry.d.ts +1 -1
- package/dist/components/hazo_notes_entry.d.ts.map +1 -1
- package/dist/components/hazo_notes_entry.js +6 -31
- package/dist/components/hazo_notes_entry.js.map +1 -1
- package/dist/components/hazo_notes_file_preview.d.ts +2 -2
- package/dist/components/hazo_notes_file_preview.d.ts.map +1 -1
- package/dist/components/hazo_notes_file_preview.js +8 -6
- package/dist/components/hazo_notes_file_preview.js.map +1 -1
- package/dist/components/hazo_notes_icon.js +8 -8
- package/dist/components/hazo_notes_icon.js.map +1 -1
- package/dist/components/hazo_notes_panel.d.ts.map +1 -1
- package/dist/components/hazo_notes_panel.js +6 -59
- package/dist/components/hazo_notes_panel.js.map +1 -1
- package/dist/hooks/use_notes.js +2 -2
- package/dist/hooks/use_notes.js.map +1 -1
- package/dist/index.client.d.ts +3 -0
- package/dist/index.client.d.ts.map +1 -1
- package/dist/index.client.js +2 -0
- package/dist/index.client.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/types/index.d.ts +36 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/avatar_utils.d.ts +13 -0
- package/dist/utils/avatar_utils.d.ts.map +1 -0
- package/dist/utils/avatar_utils.js +34 -0
- package/dist/utils/avatar_utils.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/theme_utils.d.ts +30 -0
- package/dist/utils/theme_utils.d.ts.map +1 -0
- package/dist/utils/theme_utils.js +204 -0
- package/dist/utils/theme_utils.js.map +1 -0
- package/migrations/002_grant_api_user_hazo_notes.sql +24 -0
- package/package.json +12 -15
package/README.md
CHANGED
|
@@ -70,21 +70,24 @@ Create `app/api/hazo_notes/[ref_id]/route.ts`:
|
|
|
70
70
|
```typescript
|
|
71
71
|
import { createNotesHandler } from 'hazo_notes/api';
|
|
72
72
|
import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
73
|
-
|
|
74
|
-
import { getSession } from '@/lib/auth'; // Replace with your auth
|
|
73
|
+
import { hazo_get_tenant_auth } from 'hazo_auth/server-lib';
|
|
75
74
|
import { getUserById } from '@/lib/users'; // Replace with your user lookup
|
|
75
|
+
import type { NextRequest } from 'next/server';
|
|
76
76
|
|
|
77
77
|
export const dynamic = 'force-dynamic';
|
|
78
78
|
|
|
79
79
|
const { GET, POST } = createNotesHandler({
|
|
80
80
|
getHazoConnect: () => getHazoConnectSingleton(),
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
81
|
+
// Preferred: hazo_auth@6.x tenant auth. Used by both GET and POST.
|
|
82
|
+
getAuth: async (req) => {
|
|
83
|
+
const auth = await hazo_get_tenant_auth(req as NextRequest);
|
|
84
|
+
if (!auth.authenticated || !auth.user?.id) return null;
|
|
85
|
+
return {
|
|
86
|
+
user_id: auth.user.id,
|
|
87
|
+
scope_id: auth.selected_scope_id ?? null,
|
|
88
|
+
};
|
|
85
89
|
},
|
|
86
90
|
getUserProfile: async (userId) => {
|
|
87
|
-
// IMPORTANT: Replace with your user profile lookup
|
|
88
91
|
const user = await getUserById(userId);
|
|
89
92
|
return {
|
|
90
93
|
id: userId,
|
|
@@ -98,6 +101,15 @@ const { GET, POST } = createNotesHandler({
|
|
|
98
101
|
export { GET, POST };
|
|
99
102
|
```
|
|
100
103
|
|
|
104
|
+
> **GET requires auth.** Starting in `1.2.0`, GET responds `401` when the auth
|
|
105
|
+
> resolver returns `null`, matching POST. Older releases left GET anonymous.
|
|
106
|
+
> If you're still on `hazo_auth@5.x`, use `getUserIdFromRequest` instead of
|
|
107
|
+
> `getAuth` — the package falls back to it for backward compatibility.
|
|
108
|
+
|
|
109
|
+
> **Error detail.** On `500` responses the underlying error message is
|
|
110
|
+
> included as `cause` in dev (when `NODE_ENV !== 'production'`). Set
|
|
111
|
+
> `expose_error_cause: false` to suppress, or `true` to force it on in prod.
|
|
112
|
+
|
|
101
113
|
### 3. Set Up Database
|
|
102
114
|
|
|
103
115
|
Run the migration:
|
|
@@ -114,6 +126,11 @@ CREATE TABLE hazo_notes (
|
|
|
114
126
|
);
|
|
115
127
|
|
|
116
128
|
CREATE INDEX idx_hazo_notes_ref_id ON hazo_notes(ref_id);
|
|
129
|
+
|
|
130
|
+
-- REQUIRED for PostgREST consumers — without this, GET/POST return 500 with
|
|
131
|
+
-- cause "permission denied for table hazo_notes" (PostgREST error 42501).
|
|
132
|
+
-- Shipped as migrations/002_grant_api_user_hazo_notes.sql.
|
|
133
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON hazo_notes TO api_user;
|
|
117
134
|
```
|
|
118
135
|
|
|
119
136
|
**SQLite:**
|
|
@@ -216,13 +233,23 @@ export default function FormPage() {
|
|
|
216
233
|
<HazoNotesIcon
|
|
217
234
|
ref_id="styled-notes"
|
|
218
235
|
label="Styled Notes"
|
|
219
|
-
background_color="bg-blue-
|
|
236
|
+
background_color="bg-blue-100"
|
|
220
237
|
icon_size={24}
|
|
221
238
|
show_border={false}
|
|
222
239
|
className="ml-2"
|
|
223
240
|
/>
|
|
224
241
|
```
|
|
225
242
|
|
|
243
|
+
**Supported color themes**: yellow (default), amber, green, blue, red, orange, purple, pink, teal, gray. The `background_color` prop accepts any Tailwind `bg-{color}-{shade}` class — matching colors from the supported list will apply a full coordinated theme (header, text, borders, buttons). Unknown colors fall back to yellow.
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
{/* Blue-themed notes */}
|
|
247
|
+
<HazoNotesIcon ref_id="blue-notes" background_color="bg-blue-100" />
|
|
248
|
+
|
|
249
|
+
{/* Green-themed notes */}
|
|
250
|
+
<HazoNotesIcon ref_id="green-notes" background_color="bg-green-100" />
|
|
251
|
+
```
|
|
252
|
+
|
|
226
253
|
### Controlled Mode (Notes State)
|
|
227
254
|
|
|
228
255
|
```tsx
|
|
@@ -662,17 +689,43 @@ getUserProfile: async (userId) => {
|
|
|
662
689
|
|
|
663
690
|
### Authentication errors
|
|
664
691
|
|
|
665
|
-
**Problem**:
|
|
692
|
+
**Problem**: `401 Unauthorized` on GET or POST.
|
|
693
|
+
|
|
694
|
+
**Solution**: Wire `getAuth` (preferred, hazo_auth@6.x) or `getUserIdFromRequest`
|
|
695
|
+
(hazo_auth@5.x). GET and POST both require a non-null user; both return `401`
|
|
696
|
+
if the resolver returns `null`.
|
|
666
697
|
|
|
667
|
-
**Solution**: Implement `getUserIdFromRequest` to return authenticated user ID:
|
|
668
698
|
```typescript
|
|
699
|
+
// hazo_auth@6.x — preferred
|
|
700
|
+
getAuth: async (req) => {
|
|
701
|
+
const auth = await hazo_get_tenant_auth(req as NextRequest);
|
|
702
|
+
if (!auth.authenticated || !auth.user?.id) return null;
|
|
703
|
+
return { user_id: auth.user.id, scope_id: auth.selected_scope_id ?? null };
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// hazo_auth@5.x — backward-compatible fallback
|
|
669
707
|
getUserIdFromRequest: async (req) => {
|
|
670
708
|
const session = await getSession(req);
|
|
671
|
-
|
|
672
|
-
return session.user.id;
|
|
709
|
+
return session?.user?.id ?? null;
|
|
673
710
|
}
|
|
674
711
|
```
|
|
675
712
|
|
|
713
|
+
### PostgREST `permission denied for table hazo_notes` (500 with cause 42501)
|
|
714
|
+
|
|
715
|
+
**Problem**: GET/POST return 500. Response includes
|
|
716
|
+
`"cause": "permission denied for table hazo_notes"` (when `expose_error_cause`
|
|
717
|
+
is enabled).
|
|
718
|
+
|
|
719
|
+
**Solution**: Apply `migrations/002_grant_api_user_hazo_notes.sql`. It grants
|
|
720
|
+
`SELECT, INSERT, UPDATE, DELETE` on `hazo_notes` to the `api_user` role used
|
|
721
|
+
by PostgREST. Reproducing the underlying error directly:
|
|
722
|
+
|
|
723
|
+
```bash
|
|
724
|
+
curl "$POSTGREST_URL/hazo_notes?limit=1"
|
|
725
|
+
# Before grant: 401 / "permission denied for table hazo_notes"
|
|
726
|
+
# After grant: [] or rows
|
|
727
|
+
```
|
|
728
|
+
|
|
676
729
|
## Examples
|
|
677
730
|
|
|
678
731
|
See the `test-app/` directory for complete working examples:
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -66,15 +66,25 @@ CREATE TABLE IF NOT EXISTS hazo_notes (
|
|
|
66
66
|
CREATE INDEX IF NOT EXISTS idx_hazo_notes_ref_id ON hazo_notes(ref_id);
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
**Alternative**: Use the provided migration
|
|
69
|
+
**Alternative**: Use the provided migration files:
|
|
70
70
|
```bash
|
|
71
|
-
# PostgreSQL
|
|
71
|
+
# PostgreSQL — apply both files in order
|
|
72
72
|
psql -d your_database -f node_modules/hazo_notes/migrations/001_create_hazo_notes_table.sql
|
|
73
|
+
psql -d your_database -f node_modules/hazo_notes/migrations/002_grant_api_user_hazo_notes.sql
|
|
73
74
|
|
|
74
|
-
# SQLite
|
|
75
|
+
# SQLite — only 001 (SQLite has no role system, skip 002)
|
|
75
76
|
sqlite3 your_database.db < node_modules/hazo_notes/migrations/001_create_hazo_notes_table.sql
|
|
76
77
|
```
|
|
77
78
|
|
|
79
|
+
> **PostgREST consumers MUST apply migration 002.** Without it, PostgREST
|
|
80
|
+
> returns `42501 / permission denied for table hazo_notes` and the API
|
|
81
|
+
> surfaces a generic 500. Migration 002 grants
|
|
82
|
+
> `SELECT, INSERT, UPDATE, DELETE` on `hazo_notes` to `api_user`. Verify with:
|
|
83
|
+
>
|
|
84
|
+
> ```bash
|
|
85
|
+
> curl "$POSTGREST_URL/hazo_notes?limit=1" # should return [] not 401
|
|
86
|
+
> ```
|
|
87
|
+
|
|
78
88
|
## API Routes
|
|
79
89
|
|
|
80
90
|
### 4. Create the notes API route
|
|
@@ -84,25 +94,27 @@ Create `app/api/hazo_notes/[ref_id]/route.ts`:
|
|
|
84
94
|
```typescript
|
|
85
95
|
import { createNotesHandler } from 'hazo_notes/api';
|
|
86
96
|
import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
87
|
-
|
|
88
|
-
import { getSession } from '@/lib/auth';
|
|
97
|
+
import { hazo_get_tenant_auth } from 'hazo_auth/server-lib';
|
|
89
98
|
import { getUserById } from '@/lib/users';
|
|
99
|
+
import type { NextRequest } from 'next/server';
|
|
90
100
|
|
|
91
101
|
export const dynamic = 'force-dynamic';
|
|
92
102
|
|
|
93
103
|
const { GET, POST } = createNotesHandler({
|
|
94
104
|
getHazoConnect: () => getHazoConnectSingleton(),
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return
|
|
106
|
+
// Preferred (hazo_auth@6.x). Used by BOTH GET and POST — both require auth.
|
|
107
|
+
getAuth: async (req) => {
|
|
108
|
+
const auth = await hazo_get_tenant_auth(req as NextRequest);
|
|
109
|
+
if (!auth.authenticated || !auth.user?.id) return null;
|
|
110
|
+
return {
|
|
111
|
+
user_id: auth.user.id,
|
|
112
|
+
scope_id: auth.selected_scope_id ?? null,
|
|
113
|
+
};
|
|
101
114
|
},
|
|
102
115
|
|
|
103
116
|
getUserProfile: async (userId) => {
|
|
104
117
|
// IMPORTANT: Replace this with your actual user profile lookup
|
|
105
|
-
// This function fetches user details for attribution
|
|
106
118
|
const user = await getUserById(userId);
|
|
107
119
|
return {
|
|
108
120
|
id: userId,
|
|
@@ -117,9 +129,13 @@ export { GET, POST };
|
|
|
117
129
|
```
|
|
118
130
|
|
|
119
131
|
**Important Notes**:
|
|
120
|
-
-
|
|
132
|
+
- Either `getAuth` (hazo_auth@6.x) or `getUserIdFromRequest` (hazo_auth@5.x)
|
|
133
|
+
MUST be provided. GET and POST both return `401` if the resolver returns
|
|
134
|
+
`null`. GET-anonymous behavior from `1.1.x` is gone in `1.2.0`.
|
|
121
135
|
- The `getUserProfile` function enriches notes with user information
|
|
122
136
|
- If you don't have user profiles, you can omit `getUserProfile`
|
|
137
|
+
- On a 500 response, the underlying error message is included as `cause`
|
|
138
|
+
in non-production. Set `expose_error_cause: false` to suppress.
|
|
123
139
|
|
|
124
140
|
### 5. (Optional) Create the files API route for file attachments
|
|
125
141
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_notes_handler.d.ts","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACV,yBAAyB,
|
|
1
|
+
{"version":3,"file":"create_notes_handler.d.ts","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACV,yBAAyB,EAKzB,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,mBAAmB,CAAC;AAiD3B;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB;mBAmCxD,OAAO,WACP;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC/C,OAAO,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;oBA4E/B,OAAO,WACP;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC/C,OAAO,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;EAkJ7C"}
|
|
@@ -40,17 +40,14 @@ const DEFAULT_MAX_FILES_PER_NOTE = 5;
|
|
|
40
40
|
// ============================================================================
|
|
41
41
|
/** Generate a UUID v4 */
|
|
42
42
|
function generateUUID() {
|
|
43
|
-
return
|
|
44
|
-
const r = (Math.random() * 16) | 0;
|
|
45
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
46
|
-
return v.toString(16);
|
|
47
|
-
});
|
|
43
|
+
return crypto.randomUUID();
|
|
48
44
|
}
|
|
49
45
|
/** Create a standardized error response */
|
|
50
|
-
function createErrorResponse(error, status) {
|
|
46
|
+
function createErrorResponse(error, status, cause) {
|
|
51
47
|
return NextResponse.json({
|
|
52
48
|
success: false,
|
|
53
49
|
error,
|
|
50
|
+
...(cause ? { cause } : {}),
|
|
54
51
|
}, { status });
|
|
55
52
|
}
|
|
56
53
|
/** No-op logger */
|
|
@@ -60,6 +57,8 @@ const noopLogger = {
|
|
|
60
57
|
info: () => { },
|
|
61
58
|
debug: () => { },
|
|
62
59
|
};
|
|
60
|
+
/** True when running outside production. Used as the default for exposing error causes. */
|
|
61
|
+
const isNonProduction = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';
|
|
63
62
|
/**
|
|
64
63
|
* Creates GET and POST handlers for notes
|
|
65
64
|
*
|
|
@@ -67,8 +66,24 @@ const noopLogger = {
|
|
|
67
66
|
* @returns Object with GET and POST handlers
|
|
68
67
|
*/
|
|
69
68
|
export function createNotesHandler(options) {
|
|
70
|
-
const { getHazoConnect, getLogger, getUserIdFromRequest, getUserProfile } = options;
|
|
69
|
+
const { getHazoConnect, getLogger, getAuth, getUserIdFromRequest, getUserProfile, expose_error_cause, } = options;
|
|
71
70
|
const logger = getLogger?.() || noopLogger;
|
|
71
|
+
const exposeCause = expose_error_cause ?? isNonProduction;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve auth context for a request. Prefers `getAuth`, falls back to
|
|
74
|
+
* `getUserIdFromRequest` for backward compatibility. Returns `null` when
|
|
75
|
+
* the request is unauthenticated or no resolver is wired.
|
|
76
|
+
*/
|
|
77
|
+
async function resolveAuth(req) {
|
|
78
|
+
if (getAuth) {
|
|
79
|
+
return (await getAuth(req)) ?? null;
|
|
80
|
+
}
|
|
81
|
+
if (getUserIdFromRequest) {
|
|
82
|
+
const user_id = await getUserIdFromRequest(req);
|
|
83
|
+
return user_id ? { user_id, scope_id: null } : null;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
72
87
|
/**
|
|
73
88
|
* GET handler - Fetch notes for a ref_id
|
|
74
89
|
*
|
|
@@ -81,7 +96,11 @@ export function createNotesHandler(options) {
|
|
|
81
96
|
if (!ref_id) {
|
|
82
97
|
return createErrorResponse('ref_id is required', 400);
|
|
83
98
|
}
|
|
84
|
-
|
|
99
|
+
const auth = await resolveAuth(request);
|
|
100
|
+
if (!auth) {
|
|
101
|
+
return createErrorResponse('Unauthorized - user not authenticated', 401);
|
|
102
|
+
}
|
|
103
|
+
logger.debug('[hazo_notes] GET request', { ref_id, user_id: auth.user_id });
|
|
85
104
|
const hazoConnect = await getHazoConnect();
|
|
86
105
|
// Query the hazo_notes table using PostgREST-style query
|
|
87
106
|
const result = await hazoConnect.rawQuery(`/hazo_notes?ref_id=eq.${ref_id}`);
|
|
@@ -121,10 +140,9 @@ export function createNotesHandler(options) {
|
|
|
121
140
|
});
|
|
122
141
|
}
|
|
123
142
|
catch (error) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return createErrorResponse('Failed to fetch notes', 500);
|
|
143
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
144
|
+
logger.error('[hazo_notes] GET error', { error: message });
|
|
145
|
+
return createErrorResponse('Failed to fetch notes', 500, exposeCause ? message : undefined);
|
|
128
146
|
}
|
|
129
147
|
}
|
|
130
148
|
/**
|
|
@@ -139,13 +157,11 @@ export function createNotesHandler(options) {
|
|
|
139
157
|
if (!ref_id) {
|
|
140
158
|
return NextResponse.json({ success: false, error: 'ref_id is required' }, { status: 400 });
|
|
141
159
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
? await getUserIdFromRequest(request)
|
|
145
|
-
: null;
|
|
146
|
-
if (!userId) {
|
|
160
|
+
const auth = await resolveAuth(request);
|
|
161
|
+
if (!auth) {
|
|
147
162
|
return NextResponse.json({ success: false, error: 'Unauthorized - user not authenticated' }, { status: 401 });
|
|
148
163
|
}
|
|
164
|
+
const userId = auth.user_id;
|
|
149
165
|
// Parse request body
|
|
150
166
|
const body = await request.json();
|
|
151
167
|
const { note_text, note_files } = body;
|
|
@@ -231,10 +247,13 @@ export function createNotesHandler(options) {
|
|
|
231
247
|
});
|
|
232
248
|
}
|
|
233
249
|
catch (error) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
250
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
251
|
+
logger.error('[hazo_notes] POST error', { error: message });
|
|
252
|
+
return NextResponse.json({
|
|
253
|
+
success: false,
|
|
254
|
+
error: 'Failed to add note',
|
|
255
|
+
...(exposeCause ? { cause: message } : {}),
|
|
256
|
+
}, { status: 500 });
|
|
238
257
|
}
|
|
239
258
|
}
|
|
240
259
|
return { GET, POST };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_notes_handler.js","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"create_notes_handler.js","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,5 @@ import type { HazoNotesEntryProps } from '../types/index.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Single note entry display component
|
|
4
4
|
*/
|
|
5
|
-
export declare function HazoNotesEntry({ note, ProfileStampComponent }: HazoNotesEntryProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare function HazoNotesEntry({ note, ProfileStampComponent, background_color }: HazoNotesEntryProps): import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
//# sourceMappingURL=hazo_notes_entry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_notes_entry.d.ts","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"hazo_notes_entry.d.ts","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAuB7D;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,EAAE,mBAAmB,2CAqEpG"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../utils/cn.js';
|
|
3
4
|
import { render_note_with_files } from './hazo_notes_file_preview.js';
|
|
5
|
+
import { get_initials, get_avatar_color } from '../utils/avatar_utils.js';
|
|
6
|
+
import { get_theme_classes } from '../utils/theme_utils.js';
|
|
4
7
|
/**
|
|
5
8
|
* Format timestamp for display
|
|
6
9
|
*/
|
|
@@ -18,40 +21,12 @@ function format_timestamp(iso_timestamp) {
|
|
|
18
21
|
return iso_timestamp;
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Get initials from name for avatar
|
|
23
|
-
*/
|
|
24
|
-
function get_initials(name) {
|
|
25
|
-
if (!name)
|
|
26
|
-
return '??';
|
|
27
|
-
const parts = name.trim().split(/\s+/);
|
|
28
|
-
if (parts.length >= 2) {
|
|
29
|
-
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
30
|
-
}
|
|
31
|
-
return name.substring(0, 2).toUpperCase();
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Generate consistent hex color from name for avatar background
|
|
35
|
-
*/
|
|
36
|
-
function get_avatar_color(name) {
|
|
37
|
-
const colors = [
|
|
38
|
-
'#ef4444', '#f97316', '#d97706', '#22c55e',
|
|
39
|
-
'#14b8a6', '#3b82f6', '#6366f1', '#a855f7',
|
|
40
|
-
'#ec4899', '#f43f5e',
|
|
41
|
-
];
|
|
42
|
-
if (!name)
|
|
43
|
-
return colors[0]; // default to first color
|
|
44
|
-
let hash = 0;
|
|
45
|
-
for (let i = 0; i < name.length; i++) {
|
|
46
|
-
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
47
|
-
}
|
|
48
|
-
return colors[Math.abs(hash) % colors.length];
|
|
49
|
-
}
|
|
50
24
|
/**
|
|
51
25
|
* Single note entry display component
|
|
52
26
|
*/
|
|
53
|
-
export function HazoNotesEntry({ note, ProfileStampComponent }) {
|
|
27
|
+
export function HazoNotesEntry({ note, ProfileStampComponent, background_color }) {
|
|
54
28
|
const { user_name, user_avatar, created_at, note_text, note_files } = note;
|
|
29
|
+
const theme = get_theme_classes(background_color ?? '');
|
|
55
30
|
// Render avatar
|
|
56
31
|
const render_avatar = () => {
|
|
57
32
|
if (ProfileStampComponent) {
|
|
@@ -69,6 +44,6 @@ export function HazoNotesEntry({ note, ProfileStampComponent }) {
|
|
|
69
44
|
color: '#ffffff',
|
|
70
45
|
}, title: display_name, children: get_initials(user_name) }));
|
|
71
46
|
};
|
|
72
|
-
return (_jsxs("div", { className: "cls_hazo_notes_entry p-3", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [render_avatar(), !ProfileStampComponent && (_jsx("span", { className:
|
|
47
|
+
return (_jsxs("div", { className: "cls_hazo_notes_entry p-3", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [render_avatar(), !ProfileStampComponent && (_jsx("span", { className: cn('text-xs flex-shrink-0', theme.text_secondary), children: format_timestamp(created_at) }))] }), _jsx("div", { className: "cls_hazo_notes_entry_content ml-9 overflow-hidden", children: _jsx("div", { className: cn('w-full min-h-[40px] rounded-md border px-3 py-2 text-sm overflow-hidden', theme.border_accent, theme.text_primary), style: { backgroundColor: theme.content_bg }, children: render_note_with_files(note_text, note_files, background_color) }) })] }));
|
|
73
48
|
}
|
|
74
49
|
//# sourceMappingURL=hazo_notes_entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_notes_entry.js","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAUb,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"hazo_notes_entry.js","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAUb,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;GAEG;AACH,SAAS,gBAAgB,CAAC,aAAqB;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;YAClC,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,aAAa,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,gBAAgB,EAAuB;IACnG,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAC3E,MAAM,KAAK,GAAG,iBAAiB,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAExD,gBAAgB;IAChB,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,aAAa,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACjF,OAAO,CACL,KAAC,qBAAqB,IACpB,IAAI,EAAC,IAAI,EACT,SAAS,EAAE,KAAK,EAChB,UAAU,EAAE,KAAK,EACjB,aAAa,EAAE,aAAa,GAC5B,CACH,CAAC;QACJ,CAAC;QAED,gCAAgC;QAChC,MAAM,YAAY,GAAG,SAAS,IAAI,cAAc,CAAC;QACjD,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CACL,cACE,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,YAAY,EACjB,SAAS,EAAC,iDAAiD,EAC3D,KAAK,EAAE,YAAY,GACnB,CACH,CAAC;QACJ,CAAC;QAED,kBAAkB;QAClB,OAAO,CACL,eACE,SAAS,EAAC,8FAA8F,EACxG,KAAK,EAAE;gBACL,eAAe,EAAE,gBAAgB,CAAC,SAAS,CAAC;gBAC5C,KAAK,EAAE,SAAS;aACjB,EACD,KAAK,EAAE,YAAY,YAElB,YAAY,CAAC,SAAS,CAAC,GACnB,CACR,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,0BAA0B,aAEvC,eAAK,SAAS,EAAC,8BAA8B,aAC1C,aAAa,EAAE,EACf,CAAC,qBAAqB,IAAI,CACzB,eAAM,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,KAAK,CAAC,cAAc,CAAC,YAC/D,gBAAgB,CAAC,UAAU,CAAC,GACxB,CACR,IACG,EAGN,cAAK,SAAS,EAAC,mDAAmD,YAChE,cACE,SAAS,EAAE,EAAE,CAAC,yEAAyE,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,EACjI,KAAK,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,UAAU,EAAE,YAE3C,sBAAsB,CAAC,SAAS,EAAE,UAAU,EAAE,gBAAgB,CAAC,GAC5D,GACF,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -8,9 +8,9 @@ import type { HazoNotesFilePreviewProps, NoteFile } from '../types/index.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Render a file preview based on display mode and file type
|
|
10
10
|
*/
|
|
11
|
-
export declare function HazoNotesFilePreview({ file, display_mode, }: HazoNotesFilePreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function HazoNotesFilePreview({ file, display_mode, background_color, }: HazoNotesFilePreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
12
12
|
/**
|
|
13
13
|
* Parse note text and render with inline file previews
|
|
14
14
|
*/
|
|
15
|
-
export declare function render_note_with_files(note_text: string, note_files?: NoteFile[]): React.ReactNode;
|
|
15
|
+
export declare function render_note_with_files(note_text: string, note_files?: NoteFile[], background_color?: string): React.ReactNode;
|
|
16
16
|
//# sourceMappingURL=hazo_notes_file_preview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_notes_file_preview.d.ts","sourceRoot":"","sources":["../../src/components/hazo_notes_file_preview.tsx"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,yBAAyB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"hazo_notes_file_preview.d.ts","sourceRoot":"","sources":["../../src/components/hazo_notes_file_preview.tsx"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,yBAAyB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK7E;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,gBAAgB,GACjB,EAAE,yBAAyB,2CAiD3B;AA8CD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,QAAQ,EAAE,EACvB,gBAAgB,CAAC,EAAE,MAAM,GACxB,KAAK,CAAC,SAAS,CAwDjB"}
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { cn } from '../utils/cn.js';
|
|
4
4
|
import { format_file_size, is_image_file } from '../utils/file_utils.js';
|
|
5
|
+
import { get_theme_classes } from '../utils/theme_utils.js';
|
|
5
6
|
/**
|
|
6
7
|
* Render a file preview based on display mode and file type
|
|
7
8
|
*/
|
|
8
|
-
export function HazoNotesFilePreview({ file, display_mode, }) {
|
|
9
|
+
export function HazoNotesFilePreview({ file, display_mode, background_color, }) {
|
|
10
|
+
const theme = get_theme_classes(background_color ?? '');
|
|
9
11
|
const is_image = is_image_file(file.filename);
|
|
10
12
|
// For embedded images
|
|
11
13
|
if (display_mode === 'embed' && is_image) {
|
|
12
14
|
const src = file.filedata.startsWith('/')
|
|
13
15
|
? file.filedata // Filesystem path
|
|
14
16
|
: `data:${file.mime_type || 'image/png'};base64,${file.filedata}`; // Base64
|
|
15
|
-
return (_jsxs("div", { className: "cls_hazo_notes_file_embed my-2", children: [_jsx("img", { src: src, alt: file.filename, className:
|
|
17
|
+
return (_jsxs("div", { className: "cls_hazo_notes_file_embed my-2", children: [_jsx("img", { src: src, alt: file.filename, className: cn('max-w-full max-h-64 rounded-md border', theme.border), loading: "lazy" }), _jsx("p", { className: cn('text-xs mt-1', theme.text_secondary), children: file.filename })] }));
|
|
16
18
|
}
|
|
17
19
|
// For attachments or non-image embeds
|
|
18
20
|
return (_jsx("div", { className: "cls_hazo_notes_file_attachment my-2 overflow-hidden", children: _jsxs("a", { href: file.filedata.startsWith('/')
|
|
19
21
|
? file.filedata
|
|
20
|
-
: `data:${file.mime_type || 'application/octet-stream'};base64,${file.filedata}`, download: file.filename, className: cn('flex items-center gap-2 px-3 py-2 rounded-md text-sm max-w-full',
|
|
22
|
+
: `data:${file.mime_type || 'application/octet-stream'};base64,${file.filedata}`, download: file.filename, className: cn('flex items-center gap-2 px-3 py-2 rounded-md text-sm max-w-full', theme.file_bg, theme.file_bg_hover, theme.file_text, 'border', theme.border_accent, 'transition-colors'), children: [_jsx(FileIcon, { mime_type: file.mime_type }), _jsx("span", { className: "font-medium truncate min-w-0 flex-1", children: file.filename }), file.file_size && (_jsxs("span", { className: cn(theme.text_secondary, 'text-xs whitespace-nowrap flex-shrink-0'), children: ["(", format_file_size(file.file_size), ")"] }))] }) }));
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* File icon based on MIME type
|
|
@@ -38,7 +40,7 @@ function FileIcon({ mime_type }) {
|
|
|
38
40
|
/**
|
|
39
41
|
* Parse note text and render with inline file previews
|
|
40
42
|
*/
|
|
41
|
-
export function render_note_with_files(note_text, note_files) {
|
|
43
|
+
export function render_note_with_files(note_text, note_files, background_color) {
|
|
42
44
|
if (!note_files || note_files.length === 0) {
|
|
43
45
|
return note_text;
|
|
44
46
|
}
|
|
@@ -60,11 +62,11 @@ export function render_note_with_files(note_text, note_files) {
|
|
|
60
62
|
const [, type, file_no] = match;
|
|
61
63
|
const file = file_map.get(file_no);
|
|
62
64
|
if (file) {
|
|
63
|
-
parts.push(_jsx(HazoNotesFilePreview, { file: file, display_mode: type }, key++));
|
|
65
|
+
parts.push(_jsx(HazoNotesFilePreview, { file: file, display_mode: type, background_color: background_color }, key++));
|
|
64
66
|
}
|
|
65
67
|
else {
|
|
66
68
|
// File not found - show placeholder
|
|
67
|
-
parts.push(_jsxs("span", { className:
|
|
69
|
+
parts.push(_jsxs("span", { className: cn(get_theme_classes(background_color ?? '').text_muted, 'italic'), children: ["[File not found: ", file_no, "]"] }, key++));
|
|
68
70
|
}
|
|
69
71
|
last_index = match.index + match[0].length;
|
|
70
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hazo_notes_file_preview.js","sourceRoot":"","sources":["../../src/components/hazo_notes_file_preview.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAUb,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"hazo_notes_file_preview.js","sourceRoot":"","sources":["../../src/components/hazo_notes_file_preview.tsx"],"names":[],"mappings":"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"}
|
|
@@ -21,13 +21,6 @@ function DocumentIcon({ className, style }) {
|
|
|
21
21
|
*/
|
|
22
22
|
export function HazoNotesIcon({ ref_id, label = 'Notes', has_notes: has_notes_prop, note_count: note_count_prop, notes: controlled_notes, on_notes_change, current_user, panel_style, save_mode, background_color, enable_files = true, max_files_per_note = 5, allowed_file_types = ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx'], max_file_size_mb = 10, on_open, on_close, open: controlled_open, onOpenChange: controlled_onOpenChange, default_open = false, disabled, className, icon_size = 28, show_border = true, }) {
|
|
23
23
|
const logger = use_logger();
|
|
24
|
-
// Validate ref_id
|
|
25
|
-
if (!ref_id) {
|
|
26
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
27
|
-
console.warn('[HazoNotesIcon] ref_id is required. Component will not render without a valid ref_id.');
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
24
|
// Apply defaults with nullish coalescing - handles explicit undefined from wrapper components
|
|
32
25
|
const effective_panel_style = panel_style ?? 'popover';
|
|
33
26
|
const effective_save_mode = save_mode ?? 'explicit';
|
|
@@ -66,7 +59,7 @@ export function HazoNotesIcon({ ref_id, label = 'Notes', has_notes: has_notes_pr
|
|
|
66
59
|
const [HazoNotesPanelComponent, setHazoNotesPanelComponent] = useState(null);
|
|
67
60
|
// Use the notes hook for uncontrolled mode
|
|
68
61
|
const { notes: fetched_notes, note_count, add_note, loading, error, } = use_notes(ref_id, {
|
|
69
|
-
skip: !!controlled_notes,
|
|
62
|
+
skip: !!controlled_notes || !!disabled,
|
|
70
63
|
});
|
|
71
64
|
const notes = controlled_notes ?? fetched_notes;
|
|
72
65
|
const has_notes = has_notes_prop ?? (notes.length > 0);
|
|
@@ -125,6 +118,13 @@ export function HazoNotesIcon({ ref_id, label = 'Notes', has_notes: has_notes_pr
|
|
|
125
118
|
loadPanel();
|
|
126
119
|
}, []);
|
|
127
120
|
const effective_user = current_user || fetched_user;
|
|
121
|
+
// Validate ref_id (after all hooks to comply with Rules of Hooks)
|
|
122
|
+
if (!ref_id) {
|
|
123
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
124
|
+
console.warn('[HazoNotesIcon] ref_id is required. Component will not render without a valid ref_id.');
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
128
|
// Handle open/close
|
|
129
129
|
const handle_open_change = (open) => {
|
|
130
130
|
if (is_controlled_open) {
|