ocean-brain 0.6.1 → 0.6.2

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.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/server/client/dist/assets/{Calendar-BJHLksEZ.js → Calendar-DbPut8EU.js} +1 -1
  3. package/server/client/dist/assets/{Callout-wFx9oCas.js → Callout-DfX-gIUB.js} +1 -1
  4. package/server/client/dist/assets/{Graph-9piERaNR.js → Graph-yHE9m5fy.js} +1 -1
  5. package/server/client/dist/assets/{Image.es-Be7par_j.js → Image.es-CtMc7BW4.js} +1 -1
  6. package/server/client/dist/assets/{Note-CC9ybxXL.js → Note-BECn-AoI.js} +2 -2
  7. package/server/client/dist/assets/{Plus.es-BKm7uDYu.js → Plus.es-BGVIIQtM.js} +1 -1
  8. package/server/client/dist/assets/{Reminders-DRxA8v98.js → Reminders-CvEJf0eQ.js} +1 -1
  9. package/server/client/dist/assets/{Search-BunSQrqv.js → Search-CKZhztuV.js} +1 -1
  10. package/server/client/dist/assets/{SurfaceCard-FhlC8VSR.js → SurfaceCard-Bnfo5EOl.js} +1 -1
  11. package/server/client/dist/assets/{Tag-z_crJ5JP.js → Tag-C4oAwjs0.js} +1 -1
  12. package/server/client/dist/assets/{TagNotes-D7wIJ4jy.js → TagNotes-Rl1ZSJP6.js} +1 -1
  13. package/server/client/dist/assets/{Trash.es-ByMVwx0d.js → Trash.es-BcwUz2yM.js} +1 -1
  14. package/server/client/dist/assets/ViewNotes-B9Yc0A87.js +1 -0
  15. package/server/client/dist/assets/ViewSectionTableRenderer-C5yJBO7C.js +102 -0
  16. package/server/client/dist/assets/Views-Bqq0pUEE.js +1 -0
  17. package/server/client/dist/assets/{image.api-B5Qi-Txv.js → image.api-CuGTgzyQ.js} +1 -1
  18. package/server/client/dist/assets/{index-nYj7BL3a.js → index-B43ulIPo.js} +3 -3
  19. package/server/client/dist/assets/{index-cHJQCo8V.js → index-BQDR6hIA.js} +1 -1
  20. package/server/client/dist/assets/{index-Cd81UxEh.css → index-CDjYEIVf.css} +1 -1
  21. package/server/client/dist/assets/{manage-image-glbtBibn.js → manage-image-Bs4Kmevx.js} +1 -1
  22. package/server/client/dist/assets/{manage-image-detail-DcZggB1M.js → manage-image-detail-WARala-v.js} +1 -1
  23. package/server/client/dist/assets/{mcp-BBUpQdS9.js → mcp-C0Z3vKBa.js} +1 -1
  24. package/server/client/dist/assets/{placeholder-B_qb_qkc.js → placeholder-D080guzn.js} +3 -3
  25. package/server/client/dist/assets/{properties-CiyQv6Tb.js → properties-DbnmfbT5.js} +1 -1
  26. package/server/client/dist/assets/trash-D5ZiZfTk.js +1 -0
  27. package/server/client/dist/assets/{useReminderMutate-CSKliBcc.js → useReminderMutate-h7d_S_X2.js} +2 -2
  28. package/server/client/dist/index.html +2 -2
  29. package/server/dist/features/view/graphql/view.type-defs.js +22 -0
  30. package/server/dist/features/view/graphql/view.type-defs.js.map +1 -1
  31. package/server/dist/features/view/services/workspace.js +77 -16
  32. package/server/dist/features/view/services/workspace.js.map +1 -1
  33. package/server/prisma/schema.prisma +1 -0
  34. package/server/client/dist/assets/ViewNotes-Duo9XmcJ.js +0 -1
  35. package/server/client/dist/assets/Views-D4Z_O9Kd.js +0 -1
  36. package/server/client/dist/assets/trash-CQnj4Rmv.js +0 -1
  37. package/server/client/dist/assets/view-dashboard-B5fKgvk_.js +0 -99
@@ -15,6 +15,7 @@ const MAX_VIEW_PROPERTY_FILTERS = 10;
15
15
  const DEFAULT_VIEW_DISPLAY_TYPE = "list";
16
16
  const DEFAULT_VIEW_SORT_BY = "updatedAt";
17
17
  const DEFAULT_VIEW_SORT_ORDER = "desc";
18
+ const DEFAULT_VIEW_TABLE_COLUMNS = ["title", "tags", "properties", "createdAt", "updatedAt"];
18
19
  const orderedViewSectionTagsInclude = {
19
20
  tags: {
20
21
  orderBy: [{ order: "asc" }, { createdAt: "asc" }]
@@ -44,13 +45,19 @@ const normalizeViewTagNames = (values) => {
44
45
  return Array.from(new Set(normalizedTagNames.map(normalizeTagName).filter(Boolean)));
45
46
  };
46
47
  const isViewPropertyFilterOperator = (value) => {
47
- return value === "equals" || value === "before" || value === "after" || value === "exists" || value === "notExists";
48
+ return value === "equals" || value === "notEquals" || value === "contains" || value === "notContains" || value === "before" || value === "after" || value === "exists" || value === "notExists";
48
49
  };
49
50
  const isPropertyValueType = (value) => {
50
51
  return value === "text" || value === "url" || value === "number" || value === "date" || value === "boolean" || value === "select";
51
52
  };
53
+ const isViewTableColumn = (value) => {
54
+ return value === "title" || value === "tags" || value === "properties" || value === "createdAt" || value === "updatedAt";
55
+ };
52
56
  const normalizeViewDisplayType = (value) => {
53
- return value === "calendar" ? "calendar" : DEFAULT_VIEW_DISPLAY_TYPE;
57
+ if (value === "table" || value === "calendar") {
58
+ return value;
59
+ }
60
+ return DEFAULT_VIEW_DISPLAY_TYPE;
54
61
  };
55
62
  const normalizeViewSortBy = (value) => {
56
63
  return value === "createdAt" || value === "title" ? value : DEFAULT_VIEW_SORT_BY;
@@ -58,6 +65,19 @@ const normalizeViewSortBy = (value) => {
58
65
  const normalizeViewSortOrder = (value) => {
59
66
  return value === "asc" ? "asc" : DEFAULT_VIEW_SORT_ORDER;
60
67
  };
68
+ const normalizeViewTableColumns = (columns) => {
69
+ const normalizedColumns = (columns ?? []).filter(isViewTableColumn);
70
+ const uniqueColumns = Array.from(new Set(normalizedColumns));
71
+ if (uniqueColumns.length === 0) {
72
+ return [...DEFAULT_VIEW_TABLE_COLUMNS];
73
+ }
74
+ return uniqueColumns.includes("title") ? uniqueColumns : ["title", ...uniqueColumns];
75
+ };
76
+ const normalizeViewDisplayOptions = (options) => {
77
+ return {
78
+ tableColumns: normalizeViewTableColumns(options?.tableColumns)
79
+ };
80
+ };
61
81
  const normalizeFilterValue = ({
62
82
  value,
63
83
  valueType,
@@ -88,7 +108,10 @@ const normalizeFilterValue = ({
88
108
  if ((operator === "before" || operator === "after") && valueType !== "date" && valueType !== "number") {
89
109
  throw new InvalidNotePropertyInputError("Before and after filters require date or number properties.");
90
110
  }
91
- if (valueType === "url") {
111
+ if ((operator === "contains" || operator === "notContains") && valueType !== "text" && valueType !== "url") {
112
+ throw new InvalidNotePropertyInputError("Contains filters require text or url properties.");
113
+ }
114
+ if (valueType === "url" && operator !== "contains" && operator !== "notContains") {
92
115
  return normalizeUrlValue(normalizedValue);
93
116
  }
94
117
  return normalizedValue;
@@ -128,7 +151,8 @@ const parseStoredViewQuery = (value) => {
128
151
  return {
129
152
  propertyFilters: [],
130
153
  sortBy: DEFAULT_VIEW_SORT_BY,
131
- sortOrder: DEFAULT_VIEW_SORT_ORDER
154
+ sortOrder: DEFAULT_VIEW_SORT_ORDER,
155
+ displayOptions: normalizeViewDisplayOptions(null)
132
156
  };
133
157
  }
134
158
  try {
@@ -136,21 +160,24 @@ const parseStoredViewQuery = (value) => {
136
160
  return {
137
161
  propertyFilters: normalizeViewPropertyFilters(parsed.propertyFilters ?? []),
138
162
  sortBy: normalizeViewSortBy(parsed.sortBy),
139
- sortOrder: normalizeViewSortOrder(parsed.sortOrder)
163
+ sortOrder: normalizeViewSortOrder(parsed.sortOrder),
164
+ displayOptions: normalizeViewDisplayOptions(parsed.displayOptions)
140
165
  };
141
166
  } catch {
142
167
  return {
143
168
  propertyFilters: [],
144
169
  sortBy: DEFAULT_VIEW_SORT_BY,
145
- sortOrder: DEFAULT_VIEW_SORT_ORDER
170
+ sortOrder: DEFAULT_VIEW_SORT_ORDER,
171
+ displayOptions: normalizeViewDisplayOptions(null)
146
172
  };
147
173
  }
148
174
  };
149
- const serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder }) => {
175
+ const serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder, displayOptions }) => {
150
176
  return JSON.stringify({
151
177
  propertyFilters,
152
178
  sortBy,
153
- sortOrder
179
+ sortOrder,
180
+ displayOptions
154
181
  });
155
182
  };
156
183
  const clampViewSectionLimit = (value) => {
@@ -179,9 +206,11 @@ const normalizeViewSectionInput = (input) => {
179
206
  const trimmedTitle = input.title?.trim() ?? "";
180
207
  const sortBy = normalizeViewSortBy(input.sortBy);
181
208
  const sortOrder = normalizeViewSortOrder(input.sortOrder);
209
+ const displayOptions = normalizeViewDisplayOptions(input.displayOptions);
182
210
  return {
183
211
  title: trimmedTitle || buildDefaultSectionTitle(tagNames, propertyFilters),
184
212
  displayType: normalizeViewDisplayType(input.displayType),
213
+ displayOptions,
185
214
  tagNames,
186
215
  mode: input.mode === "or" ? "or" : "and",
187
216
  propertyFilters,
@@ -245,6 +274,7 @@ const serializeViewSection = (section) => {
245
274
  tabId: String(section.tabId),
246
275
  title: section.title,
247
276
  displayType: normalizeViewDisplayType(section.displayType),
277
+ displayOptions: query.displayOptions,
248
278
  tagNames: section.tags.map((tag) => tag.name),
249
279
  mode: section.mode,
250
280
  propertyFilters: query.propertyFilters,
@@ -331,7 +361,8 @@ const buildStoredViewQuery = async (db, section) => {
331
361
  return serializeStoredViewQuery({
332
362
  propertyFilters,
333
363
  sortBy: section.sortBy,
334
- sortOrder: section.sortOrder
364
+ sortOrder: section.sortOrder,
365
+ displayOptions: section.displayOptions
335
366
  });
336
367
  };
337
368
  const getNextTabOrder = async (db) => {
@@ -397,6 +428,9 @@ const buildPropertyFilterValueWhere = (filter) => {
397
428
  if (filter.operator === "after") {
398
429
  return { numberValue: { gt: numberValue } };
399
430
  }
431
+ if (filter.operator === "notEquals") {
432
+ return { numberValue: { not: numberValue } };
433
+ }
400
434
  return { numberValue };
401
435
  }
402
436
  case "date": {
@@ -407,16 +441,37 @@ const buildPropertyFilterValueWhere = (filter) => {
407
441
  if (filter.operator === "after") {
408
442
  return { dateValue: { gt: dateValue } };
409
443
  }
444
+ if (filter.operator === "notEquals") {
445
+ return { dateValue: { not: dateValue } };
446
+ }
410
447
  return { dateValue };
411
448
  }
412
- case "boolean":
449
+ case "boolean": {
450
+ if (filter.operator === "notEquals") {
451
+ return { boolValue: { not: filter.value === "true" } };
452
+ }
413
453
  return { boolValue: filter.value === "true" };
454
+ }
414
455
  case "select":
456
+ if (filter.operator === "notEquals") {
457
+ return { option: { is: { value: { not: normalizeSelectFilterValue(filter.value ?? "") } } } };
458
+ }
415
459
  return { option: { is: { value: normalizeSelectFilterValue(filter.value ?? "") } } };
416
460
  case "url":
417
461
  case "text":
418
- default:
419
- return { textValueNormalized: filter.value?.toLowerCase() ?? "" };
462
+ default: {
463
+ const textValue = filter.value?.toLowerCase() ?? "";
464
+ if (filter.operator === "notEquals") {
465
+ return { textValueNormalized: { not: textValue } };
466
+ }
467
+ if (filter.operator === "contains") {
468
+ return { textValueNormalized: { contains: textValue } };
469
+ }
470
+ if (filter.operator === "notContains") {
471
+ return { textValueNormalized: { not: { contains: textValue } } };
472
+ }
473
+ return { textValueNormalized: textValue };
474
+ }
420
475
  }
421
476
  };
422
477
  const buildPropertyFilterWhere = (filter) => {
@@ -496,22 +551,22 @@ const getViewSectionNotes = async (id, pagination) => {
496
551
  notes
497
552
  };
498
553
  };
499
- const getNotesByProperties = async (input, pagination) => {
554
+ const getNotesByPropertiesWithDb = async (db, input, pagination) => {
500
555
  const normalizedQuery = normalizeViewNotesQueryInput(input);
501
556
  if (normalizedQuery.propertyFilters.length === 0) {
502
557
  throw new InvalidNotePropertyInputError("At least one property filter is required.");
503
558
  }
504
559
  const query = {
505
560
  ...normalizedQuery,
506
- propertyFilters: await hydratePropertyFilters(models, normalizedQuery.propertyFilters, {
561
+ propertyFilters: await hydratePropertyFilters(db, normalizedQuery.propertyFilters, {
507
562
  validateSelectOptions: true
508
563
  })
509
564
  };
510
565
  const normalizedPagination = normalizeViewNotesPagination(pagination);
511
566
  const where = buildViewNotesWhere(query);
512
567
  const [totalCount, notes] = await Promise.all([
513
- models.note.count({ where }),
514
- models.note.findMany({
568
+ db.note.count({ where }),
569
+ db.note.findMany({
515
570
  orderBy: buildViewNotesOrderBy(query),
516
571
  where,
517
572
  take: normalizedPagination.limit,
@@ -523,6 +578,9 @@ const getNotesByProperties = async (input, pagination) => {
523
578
  notes
524
579
  };
525
580
  };
581
+ const getNotesByProperties = async (input, pagination) => {
582
+ return getNotesByPropertiesWithDb(models, input, pagination);
583
+ };
526
584
  const createViewTab = async (title) => {
527
585
  return models.$transaction(async (tx) => {
528
586
  const workspace = await ensureViewWorkspace(tx);
@@ -736,15 +794,18 @@ export {
736
794
  deleteViewSection,
737
795
  deleteViewTab,
738
796
  getNotesByProperties,
797
+ getNotesByPropertiesWithDb,
739
798
  getViewSectionById,
740
799
  getViewSectionNotes,
741
800
  getViewWorkspace,
742
801
  hydratePropertyFilters,
802
+ normalizeViewDisplayOptions,
743
803
  normalizeViewNotesPagination,
744
804
  normalizeViewNotesQueryInput,
745
805
  normalizeViewPropertyFilters,
746
806
  normalizeViewSectionInput,
747
807
  normalizeViewTabTitle,
808
+ normalizeViewTableColumns,
748
809
  normalizeViewTagNames,
749
810
  pickNextActiveViewTabId,
750
811
  reorderViewSections,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/features/view/services/workspace.ts"],"sourcesContent":["import type { Note, Prisma, PropertyValueType } from '@prisma/client';\nimport {\n InvalidNotePropertyInputError,\n normalizePropertyKey,\n normalizeUrlValue,\n} from '~/features/note/services/properties.js';\nimport { buildNoteTagNamesWhere, type NoteTagMatchMode } from '~/features/note/services/tag-filter.js';\nimport models from '~/models.js';\n\nexport type ViewTagMatchMode = NoteTagMatchMode;\nexport type ViewDisplayType = 'list' | 'calendar';\nexport type ViewPropertyFilterOperator = 'equals' | 'before' | 'after' | 'exists' | 'notExists';\nexport type ViewSortBy = 'updatedAt' | 'createdAt' | 'title';\nexport type ViewSortOrder = 'asc' | 'desc';\n\nexport interface ViewPropertyFilterRecord {\n key: string;\n name: string;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n value: string | null;\n}\n\nexport interface ViewSectionRecord {\n id: string;\n tabId: string;\n title: string;\n displayType: ViewDisplayType;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n order: number;\n}\n\nexport interface ViewTabRecord {\n id: string;\n title: string;\n order: number;\n sections: ViewSectionRecord[];\n}\n\nexport interface ViewWorkspaceRecord {\n activeTabId: string | null;\n tabs: ViewTabRecord[];\n}\n\nexport interface ViewSectionInput {\n title?: string;\n displayType?: ViewDisplayType;\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n limit?: number;\n}\n\nexport interface ViewNotesQueryInput {\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nexport interface ViewNotesQueryRecord {\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n}\n\nexport interface ViewPropertyFilterInput {\n key: string;\n operator: ViewPropertyFilterOperator;\n value?: string | null;\n valueType?: PropertyValueType | null;\n}\n\nexport interface ViewSectionNotesResult {\n totalCount: number;\n notes: Note[];\n}\n\nconst VIEW_WORKSPACE_ID = 1;\n\nexport const DEFAULT_VIEW_SECTION_LIMIT = 5;\nexport const MIN_VIEW_SECTION_LIMIT = 1;\nexport const MAX_VIEW_SECTION_LIMIT = 20;\nexport const DEFAULT_VIEW_NOTES_QUERY_LIMIT = 20;\nexport const MAX_VIEW_NOTES_QUERY_LIMIT = 50;\nconst MAX_VIEW_PROPERTY_FILTERS = 10;\nconst DEFAULT_VIEW_DISPLAY_TYPE: ViewDisplayType = 'list';\nconst DEFAULT_VIEW_SORT_BY: ViewSortBy = 'updatedAt';\nconst DEFAULT_VIEW_SORT_ORDER: ViewSortOrder = 'desc';\n\ntype ViewDbClient = typeof models | Prisma.TransactionClient;\n\nconst orderedViewSectionTagsInclude = {\n tags: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n },\n} satisfies Prisma.ViewSectionInclude;\n\nconst orderedViewTabSectionsInclude = {\n sections: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n },\n} satisfies Prisma.ViewTabInclude;\n\ntype DbViewSection = Prisma.ViewSectionGetPayload<{\n include: typeof orderedViewSectionTagsInclude;\n}>;\n\ntype DbViewTab = Prisma.ViewTabGetPayload<{\n include: typeof orderedViewTabSectionsInclude;\n}>;\n\nconst normalizeTagName = (value: string) => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n return '';\n }\n\n if (trimmedValue.startsWith('@')) {\n return trimmedValue;\n }\n\n if (trimmedValue.startsWith('#')) {\n return `@${trimmedValue.slice(1)}`;\n }\n\n return `@${trimmedValue}`;\n};\n\nexport const normalizeViewTagNames = (values: string[]) => {\n const normalizedTagNames = values.flatMap((value) => value.split(','));\n\n return Array.from(new Set(normalizedTagNames.map(normalizeTagName).filter(Boolean)));\n};\n\ninterface StoredViewQuery {\n propertyFilters?: ViewPropertyFilterRecord[];\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nconst isViewPropertyFilterOperator = (value: unknown): value is ViewPropertyFilterOperator => {\n return value === 'equals' || value === 'before' || value === 'after' || value === 'exists' || value === 'notExists';\n};\n\nconst isPropertyValueType = (value: unknown): value is PropertyValueType => {\n return (\n value === 'text' ||\n value === 'url' ||\n value === 'number' ||\n value === 'date' ||\n value === 'boolean' ||\n value === 'select'\n );\n};\n\nconst normalizeViewDisplayType = (value: ViewDisplayType | undefined): ViewDisplayType => {\n return value === 'calendar' ? 'calendar' : DEFAULT_VIEW_DISPLAY_TYPE;\n};\n\nconst normalizeViewSortBy = (value: ViewSortBy | undefined): ViewSortBy => {\n return value === 'createdAt' || value === 'title' ? value : DEFAULT_VIEW_SORT_BY;\n};\n\nconst normalizeViewSortOrder = (value: ViewSortOrder | undefined): ViewSortOrder => {\n return value === 'asc' ? 'asc' : DEFAULT_VIEW_SORT_ORDER;\n};\n\nconst normalizeFilterValue = ({\n value,\n valueType,\n operator,\n}: {\n value?: string | null;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n}) => {\n if (operator === 'exists' || operator === 'notExists') {\n return null;\n }\n\n const normalizedValue = String(value ?? '').trim();\n\n if (!normalizedValue) {\n throw new InvalidNotePropertyInputError('Property filter value is required.');\n }\n\n if (valueType === 'number' && !Number.isFinite(Number(normalizedValue))) {\n throw new InvalidNotePropertyInputError('Number property filter value must be finite.');\n }\n\n if (valueType === 'boolean' && normalizedValue !== 'true' && normalizedValue !== 'false') {\n throw new InvalidNotePropertyInputError('Boolean property filter value must be true or false.');\n }\n\n if (valueType === 'date') {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(normalizedValue)) {\n throw new InvalidNotePropertyInputError('Date property filter values must use YYYY-MM-DD.');\n }\n\n const date = new Date(`${normalizedValue}T00:00:00.000Z`);\n\n if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== normalizedValue) {\n throw new InvalidNotePropertyInputError('Date property filter value is invalid.');\n }\n }\n\n if ((operator === 'before' || operator === 'after') && valueType !== 'date' && valueType !== 'number') {\n throw new InvalidNotePropertyInputError('Before and after filters require date or number properties.');\n }\n\n if (valueType === 'url') {\n return normalizeUrlValue(normalizedValue);\n }\n\n return normalizedValue;\n};\n\nexport const normalizeViewPropertyFilters = (filters: ViewPropertyFilterInput[] | null | undefined) => {\n const normalizedFilters = filters ?? [];\n\n if (normalizedFilters.length > MAX_VIEW_PROPERTY_FILTERS) {\n throw new InvalidNotePropertyInputError(`A view can have up to ${MAX_VIEW_PROPERTY_FILTERS} property filters.`);\n }\n\n return normalizedFilters\n .map((filter): ViewPropertyFilterRecord | null => {\n const key = normalizePropertyKey(filter.key);\n const valueType = filter.valueType;\n const operator = filter.operator;\n\n if (!isPropertyValueType(valueType)) {\n throw new InvalidNotePropertyInputError('Property filter value type is required.');\n }\n\n if (!isViewPropertyFilterOperator(operator)) {\n throw new InvalidNotePropertyInputError('Property filter operator is invalid.');\n }\n\n const storedName = (filter as { name?: unknown }).name;\n const name = typeof storedName === 'string' && storedName.trim() ? storedName.trim() : key;\n\n return {\n key,\n name,\n valueType,\n operator,\n value: normalizeFilterValue({\n value: filter.value,\n valueType,\n operator,\n }),\n };\n })\n .filter((filter): filter is ViewPropertyFilterRecord => filter !== null);\n};\n\nconst parseStoredViewQuery = (value: string | null): Required<StoredViewQuery> => {\n if (!value) {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n };\n }\n\n try {\n const parsed = JSON.parse(value) as Partial<StoredViewQuery>;\n\n return {\n propertyFilters: normalizeViewPropertyFilters(parsed.propertyFilters ?? []),\n sortBy: normalizeViewSortBy(parsed.sortBy),\n sortOrder: normalizeViewSortOrder(parsed.sortOrder),\n };\n } catch {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n };\n }\n};\n\nconst serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder }: Required<StoredViewQuery>) => {\n return JSON.stringify({\n propertyFilters,\n sortBy,\n sortOrder,\n });\n};\n\nexport const clampViewSectionLimit = (value: number | undefined) => {\n const numericValue = typeof value === 'number' ? value : Number.NaN;\n\n if (!Number.isInteger(numericValue)) {\n return DEFAULT_VIEW_SECTION_LIMIT;\n }\n\n return Math.min(MAX_VIEW_SECTION_LIMIT, Math.max(MIN_VIEW_SECTION_LIMIT, numericValue));\n};\n\nexport const normalizeViewTabTitle = (title: string) => {\n const trimmedTitle = title.trim();\n\n return trimmedTitle || 'Untitled View';\n};\n\nconst buildDefaultSectionTitle = (tagNames: string[], propertyFilters: ViewPropertyFilterRecord[]) => {\n if (tagNames.length > 0) {\n return tagNames.slice(0, 2).join(' + ');\n }\n\n if (propertyFilters.length > 0) {\n return propertyFilters\n .slice(0, 2)\n .map((filter) => filter.name)\n .join(' + ');\n }\n\n return 'All notes';\n};\n\nexport const normalizeViewSectionInput = (input: ViewSectionInput) => {\n const tagNames = normalizeViewTagNames(input.tagNames ?? []);\n const propertyFilters = normalizeViewPropertyFilters(input.propertyFilters);\n const trimmedTitle = input.title?.trim() ?? '';\n const sortBy = normalizeViewSortBy(input.sortBy);\n const sortOrder = normalizeViewSortOrder(input.sortOrder);\n\n return {\n title: trimmedTitle || buildDefaultSectionTitle(tagNames, propertyFilters),\n displayType: normalizeViewDisplayType(input.displayType),\n tagNames,\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters,\n sortBy,\n sortOrder,\n limit: clampViewSectionLimit(input.limit),\n } satisfies {\n title: string;\n displayType: ViewDisplayType;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n };\n};\n\nexport const normalizeViewNotesQueryInput = (input: ViewNotesQueryInput): ViewNotesQueryRecord => {\n return {\n tagNames: normalizeViewTagNames(input.tagNames ?? []),\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters: normalizeViewPropertyFilters(input.propertyFilters),\n sortBy: normalizeViewSortBy(input.sortBy),\n sortOrder: normalizeViewSortOrder(input.sortOrder),\n };\n};\n\nexport const normalizeViewNotesPagination = (pagination?: { limit?: number; offset?: number }) => {\n const numericLimit = Number(pagination?.limit ?? DEFAULT_VIEW_NOTES_QUERY_LIMIT);\n const limit = Number.isInteger(numericLimit)\n ? Math.min(MAX_VIEW_NOTES_QUERY_LIMIT, Math.max(1, numericLimit))\n : DEFAULT_VIEW_NOTES_QUERY_LIMIT;\n const numericOffset = Number(pagination?.offset ?? 0);\n const offset = Number.isInteger(numericOffset) ? Math.max(0, numericOffset) : 0;\n\n return { limit, offset };\n};\n\nexport const pickNextActiveViewTabId = (tabIds: number[], deletedTabId: number, currentActiveTabId: number | null) => {\n const remainingTabIds = tabIds.filter((tabId) => tabId !== deletedTabId);\n\n if (remainingTabIds.length === 0) {\n return null;\n }\n\n if (currentActiveTabId !== deletedTabId) {\n return currentActiveTabId;\n }\n\n return remainingTabIds[0] ?? null;\n};\n\nconst ensureValidReorderIds = (currentIds: number[], nextIds: number[]) => {\n if (currentIds.length !== nextIds.length) {\n throw new Error('Reorder payload must include every item exactly once.');\n }\n\n const currentIdSet = new Set(currentIds);\n const nextIdSet = new Set(nextIds);\n\n if (currentIdSet.size !== currentIds.length || nextIdSet.size !== nextIds.length) {\n throw new Error('Reorder payload contains duplicate ids.');\n }\n\n for (const id of currentIdSet) {\n if (!nextIdSet.has(id)) {\n throw new Error('Reorder payload must match the current item set.');\n }\n }\n};\n\nconst parseViewId = (id: string) => {\n const numericId = Number(id);\n\n if (!Number.isInteger(numericId) || numericId <= 0) {\n throw new Error('A valid id is required.');\n }\n\n return numericId;\n};\n\nconst serializeViewSection = (section: DbViewSection): ViewSectionRecord => {\n const query = parseStoredViewQuery(section.query);\n\n return {\n id: String(section.id),\n tabId: String(section.tabId),\n title: section.title,\n displayType: normalizeViewDisplayType(section.displayType as ViewDisplayType),\n tagNames: section.tags.map((tag) => tag.name),\n mode: section.mode as ViewTagMatchMode,\n propertyFilters: query.propertyFilters,\n sortBy: query.sortBy,\n sortOrder: query.sortOrder,\n limit: section.limit,\n order: section.order,\n };\n};\n\nconst serializeViewTab = (tab: DbViewTab): ViewTabRecord => ({\n id: String(tab.id),\n title: tab.title,\n order: tab.order,\n sections: tab.sections.map(serializeViewSection),\n});\n\nconst getOrderedViewTabs = async (db: ViewDbClient) => {\n return db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewTabSectionsInclude,\n });\n};\n\nconst ensureViewWorkspace = async (db: ViewDbClient) => {\n return db.viewWorkspace.upsert({\n where: { id: VIEW_WORKSPACE_ID },\n update: {},\n create: { id: VIEW_WORKSPACE_ID },\n });\n};\n\nconst readViewWorkspace = async (db: ViewDbClient): Promise<ViewWorkspaceRecord> => {\n const [workspace, tabs] = await Promise.all([ensureViewWorkspace(db), getOrderedViewTabs(db)]);\n\n const activeTabId =\n workspace.activeTabId !== null && tabs.some((tab) => tab.id === workspace.activeTabId)\n ? String(workspace.activeTabId)\n : tabs[0]\n ? String(tabs[0].id)\n : null;\n\n return {\n activeTabId,\n tabs: tabs.map(serializeViewTab),\n };\n};\n\nconst readViewSection = async (db: ViewDbClient, id: number): Promise<ViewSectionRecord | null> => {\n const section = await db.viewSection.findUnique({\n where: { id },\n include: orderedViewSectionTagsInclude,\n });\n\n return section ? serializeViewSection(section) : null;\n};\n\nexport const hydratePropertyFilters = async (\n db: ViewDbClient,\n filters: ViewPropertyFilterRecord[],\n options: { validateSelectOptions?: boolean } = {},\n) => {\n if (filters.length === 0) {\n return [];\n }\n\n const definitions = await db.propertyDefinition.findMany({\n where: { key: { in: filters.map((filter) => filter.key) } },\n select: {\n key: true,\n name: true,\n valueType: true,\n options: {\n select: {\n value: true,\n },\n },\n },\n });\n const definitionByKey = new Map(definitions.map((definition) => [definition.key, definition]));\n\n return filters.map((filter) => {\n const definition = definitionByKey.get(filter.key);\n\n if (!definition) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} is not defined.`);\n }\n\n if (definition.valueType !== filter.valueType) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} uses ${definition.valueType} values.`);\n }\n\n if (\n options.validateSelectOptions &&\n filter.valueType === 'select' &&\n filter.operator !== 'exists' &&\n filter.operator !== 'notExists'\n ) {\n const optionValue = normalizeSelectFilterValue(filter.value ?? '');\n\n if (!definition.options.some((option) => option.value === optionValue)) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} option ${optionValue} is not defined.`);\n }\n }\n\n return {\n ...filter,\n name: definition.name,\n };\n });\n};\n\nconst buildStoredViewQuery = async (db: ViewDbClient, section: ReturnType<typeof normalizeViewSectionInput>) => {\n const propertyFilters = await hydratePropertyFilters(db, section.propertyFilters, { validateSelectOptions: true });\n\n return serializeStoredViewQuery({\n propertyFilters,\n sortBy: section.sortBy,\n sortOrder: section.sortOrder,\n });\n};\n\nconst getNextTabOrder = async (db: ViewDbClient) => {\n const lastTab = await db.viewTab.findFirst({\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastTab ? lastTab.order + 1 : 0;\n};\n\nconst getNextSectionOrder = async (db: ViewDbClient, tabId: number) => {\n const lastSection = await db.viewSection.findFirst({\n where: { tabId },\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastSection ? lastSection.order + 1 : 0;\n};\n\nconst resequenceViewTabs = async (db: ViewDbClient) => {\n const tabs = await db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n tabs.map((tab, index) =>\n db.viewTab.update({\n where: { id: tab.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nconst resequenceViewSections = async (db: ViewDbClient, tabId: number) => {\n const sections = await db.viewSection.findMany({\n where: { tabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n sections.map((section, index) =>\n db.viewSection.update({\n where: { id: section.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nexport const getViewWorkspace = async () => {\n return readViewWorkspace(models);\n};\n\nexport const getViewSectionById = async (id: string) => {\n return readViewSection(models, parseViewId(id));\n};\n\nconst normalizeSelectFilterValue = (value: string) => {\n return value.trim().toLowerCase().replace(/\\s+/g, '-');\n};\n\nconst buildPropertyFilterValueWhere = (filter: ViewPropertyFilterRecord): Prisma.NotePropertyWhereInput => {\n switch (filter.valueType) {\n case 'number': {\n const numberValue = Number(filter.value);\n\n if (filter.operator === 'before') {\n return { numberValue: { lt: numberValue } };\n }\n\n if (filter.operator === 'after') {\n return { numberValue: { gt: numberValue } };\n }\n\n return { numberValue };\n }\n case 'date': {\n const dateValue = new Date(`${filter.value}T00:00:00.000Z`);\n\n if (filter.operator === 'before') {\n return { dateValue: { lt: dateValue } };\n }\n\n if (filter.operator === 'after') {\n return { dateValue: { gt: dateValue } };\n }\n\n return { dateValue };\n }\n case 'boolean':\n return { boolValue: filter.value === 'true' };\n case 'select':\n return { option: { is: { value: normalizeSelectFilterValue(filter.value ?? '') } } };\n case 'url':\n case 'text':\n default:\n return { textValueNormalized: filter.value?.toLowerCase() ?? '' };\n }\n};\n\nexport const buildPropertyFilterWhere = (filter: ViewPropertyFilterRecord): Prisma.NoteWhereInput => {\n const definitionWhere = {\n definition: {\n is: {\n key: filter.key,\n },\n },\n } satisfies Prisma.NotePropertyWhereInput;\n\n if (filter.operator === 'notExists') {\n return {\n properties: {\n none: definitionWhere,\n },\n };\n }\n\n if (filter.operator === 'exists') {\n return {\n properties: {\n some: definitionWhere,\n },\n };\n }\n\n return {\n properties: {\n some: {\n ...definitionWhere,\n ...buildPropertyFilterValueWhere(filter),\n },\n },\n };\n};\n\nexport const buildViewNotesWhere = (\n query: Pick<ViewNotesQueryRecord, 'tagNames' | 'mode' | 'propertyFilters'>,\n): Prisma.NoteWhereInput => {\n const clauses: Prisma.NoteWhereInput[] = [];\n\n if (query.tagNames.length > 0) {\n clauses.push(buildNoteTagNamesWhere(query.tagNames, query.mode as NoteTagMatchMode));\n }\n\n for (const filter of query.propertyFilters) {\n clauses.push(buildPropertyFilterWhere(filter));\n }\n\n if (clauses.length === 0) {\n return {};\n }\n\n return { AND: clauses };\n};\n\nexport const buildViewSectionWhere = (section: ViewSectionRecord): Prisma.NoteWhereInput => {\n return buildViewNotesWhere(section);\n};\n\nconst buildViewNotesOrderBy = (\n query: Pick<ViewNotesQueryRecord, 'sortBy' | 'sortOrder'>,\n): Prisma.NoteOrderByWithRelationInput[] => {\n return [{ [query.sortBy]: query.sortOrder }, { id: 'asc' }];\n};\n\nconst buildViewSectionOrderBy = (section: ViewSectionRecord): Prisma.NoteOrderByWithRelationInput[] => {\n return buildViewNotesOrderBy(section);\n};\n\nexport const getViewSectionNotes = async (\n id: string,\n pagination: {\n limit: number;\n offset: number;\n },\n): Promise<ViewSectionNotesResult | null> => {\n const section = await models.viewSection.findUnique({\n where: { id: parseViewId(id) },\n include: orderedViewSectionTagsInclude,\n });\n\n if (!section) {\n return null;\n }\n\n const serializedSection = serializeViewSection(section);\n const where = buildViewSectionWhere(serializedSection);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewSectionOrderBy(serializedSection),\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset),\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByProperties = async (\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n const normalizedQuery = normalizeViewNotesQueryInput(input);\n\n if (normalizedQuery.propertyFilters.length === 0) {\n throw new InvalidNotePropertyInputError('At least one property filter is required.');\n }\n\n const query = {\n ...normalizedQuery,\n propertyFilters: await hydratePropertyFilters(models, normalizedQuery.propertyFilters, {\n validateSelectOptions: true,\n }),\n };\n const normalizedPagination = normalizeViewNotesPagination(pagination);\n const where = buildViewNotesWhere(query);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewNotesOrderBy(query),\n where,\n take: normalizedPagination.limit,\n skip: normalizedPagination.offset,\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const createViewTab = async (title: string) => {\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const nextTabOrder = await getNextTabOrder(tx);\n const createdTab = await tx.viewTab.create({\n data: {\n title: normalizeViewTabTitle(title),\n order: nextTabOrder,\n },\n include: orderedViewTabSectionsInclude,\n });\n\n if (workspace.activeTabId === null) {\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: createdTab.id },\n });\n }\n\n return serializeViewTab(createdTab);\n });\n};\n\nexport const updateViewTab = async (id: string, title: string) => {\n const updatedTab = await models.viewTab.update({\n where: { id: parseViewId(id) },\n data: {\n title: normalizeViewTabTitle(title),\n },\n include: orderedViewTabSectionsInclude,\n });\n\n return serializeViewTab(updatedTab);\n};\n\nexport const deleteViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n if (!tabs.some((tab) => tab.id === tabId)) {\n return false;\n }\n\n await tx.viewTab.delete({ where: { id: tabId } });\n await resequenceViewTabs(tx);\n\n const nextActiveTabId = pickNextActiveViewTabId(\n tabs.map((tab) => tab.id),\n tabId,\n workspace.activeTabId,\n );\n\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: nextActiveTabId },\n });\n\n return true;\n });\n};\n\nexport const setActiveViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tab = await tx.viewTab.findUnique({\n where: { id: tabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n await tx.viewWorkspace.update({\n where: { id: workspace.id },\n data: { activeTabId: tabId },\n });\n\n return readViewWorkspace(tx);\n });\n};\n\nexport const reorderViewTabs = async (tabIds: string[]) => {\n const nextTabIds = tabIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentTabIds = tabs.map((tab) => tab.id);\n\n ensureValidReorderIds(currentTabIds, nextTabIds);\n\n await Promise.all(\n nextTabIds.map((tabId, index) =>\n tx.viewTab.update({\n where: { id: tabId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedTabs = await getOrderedViewTabs(tx);\n return reorderedTabs.map(serializeViewTab);\n });\n};\n\nexport const createViewSection = async (tabId: string, input: ViewSectionInput) => {\n const numericTabId = parseViewId(tabId);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const tab = await tx.viewTab.findUnique({\n where: { id: numericTabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n const nextSectionOrder = await getNextSectionOrder(tx, numericTabId);\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const createdSection = await tx.viewSection.create({\n data: {\n tabId: numericTabId,\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n order: nextSectionOrder,\n tags: {\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(createdSection);\n });\n};\n\nexport const updateViewSection = async (id: string, input: ViewSectionInput) => {\n const sectionId = parseViewId(id);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const updatedSection = await tx.viewSection.update({\n where: { id: sectionId },\n data: {\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n tags: {\n deleteMany: {},\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(updatedSection);\n });\n};\n\nexport const deleteViewSection = async (id: string) => {\n const sectionId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const section = await tx.viewSection.findUnique({\n where: { id: sectionId },\n select: { id: true, tabId: true },\n });\n\n if (!section) {\n return false;\n }\n\n await tx.viewSection.delete({\n where: { id: sectionId },\n });\n await resequenceViewSections(tx, section.tabId);\n\n return true;\n });\n};\n\nexport const reorderViewSections = async (tabId: string, sectionIds: string[]) => {\n const numericTabId = parseViewId(tabId);\n const nextSectionIds = sectionIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const sections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentSectionIds = sections.map((section) => section.id);\n\n ensureValidReorderIds(currentSectionIds, nextSectionIds);\n\n await Promise.all(\n nextSectionIds.map((sectionId, index) =>\n tx.viewSection.update({\n where: { id: sectionId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedSections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n });\n\n return reorderedSections.map(serializeViewSection);\n });\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/features/view/services/workspace.ts"],"sourcesContent":["import type { Note, Prisma, PropertyValueType } from '@prisma/client';\nimport {\n InvalidNotePropertyInputError,\n normalizePropertyKey,\n normalizeUrlValue,\n} from '~/features/note/services/properties.js';\nimport { buildNoteTagNamesWhere, type NoteTagMatchMode } from '~/features/note/services/tag-filter.js';\nimport models from '~/models.js';\n\nexport type ViewTagMatchMode = NoteTagMatchMode;\nexport type ViewDisplayType = 'list' | 'table' | 'calendar';\nexport type ViewTableColumn = 'title' | 'tags' | 'properties' | 'createdAt' | 'updatedAt';\nexport type ViewPropertyFilterOperator =\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'before'\n | 'after'\n | 'exists'\n | 'notExists';\nexport type ViewSortBy = 'updatedAt' | 'createdAt' | 'title';\nexport type ViewSortOrder = 'asc' | 'desc';\n\nexport interface ViewDisplayOptionsRecord {\n tableColumns: ViewTableColumn[];\n}\n\nexport interface ViewPropertyFilterRecord {\n key: string;\n name: string;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n value: string | null;\n}\n\nexport interface ViewSectionRecord {\n id: string;\n tabId: string;\n title: string;\n displayType: ViewDisplayType;\n displayOptions: ViewDisplayOptionsRecord;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n order: number;\n}\n\nexport interface ViewTabRecord {\n id: string;\n title: string;\n order: number;\n sections: ViewSectionRecord[];\n}\n\nexport interface ViewWorkspaceRecord {\n activeTabId: string | null;\n tabs: ViewTabRecord[];\n}\n\nexport interface ViewSectionInput {\n title?: string;\n displayType?: ViewDisplayType;\n displayOptions?: ViewDisplayOptionsInput | null;\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n limit?: number;\n}\n\nexport interface ViewNotesQueryInput {\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nexport interface ViewNotesQueryRecord {\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n}\n\nexport interface ViewPropertyFilterInput {\n key: string;\n operator: ViewPropertyFilterOperator;\n value?: string | null;\n valueType?: PropertyValueType | null;\n}\n\nexport interface ViewDisplayOptionsInput {\n tableColumns?: ViewTableColumn[] | null;\n}\n\nexport interface ViewSectionNotesResult {\n totalCount: number;\n notes: Note[];\n}\n\nconst VIEW_WORKSPACE_ID = 1;\n\nexport const DEFAULT_VIEW_SECTION_LIMIT = 5;\nexport const MIN_VIEW_SECTION_LIMIT = 1;\nexport const MAX_VIEW_SECTION_LIMIT = 20;\nexport const DEFAULT_VIEW_NOTES_QUERY_LIMIT = 20;\nexport const MAX_VIEW_NOTES_QUERY_LIMIT = 50;\nconst MAX_VIEW_PROPERTY_FILTERS = 10;\nconst DEFAULT_VIEW_DISPLAY_TYPE: ViewDisplayType = 'list';\nconst DEFAULT_VIEW_SORT_BY: ViewSortBy = 'updatedAt';\nconst DEFAULT_VIEW_SORT_ORDER: ViewSortOrder = 'desc';\nconst DEFAULT_VIEW_TABLE_COLUMNS: ViewTableColumn[] = ['title', 'tags', 'properties', 'createdAt', 'updatedAt'];\n\ntype ViewDbClient = typeof models | Prisma.TransactionClient;\n\nconst orderedViewSectionTagsInclude = {\n tags: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n },\n} satisfies Prisma.ViewSectionInclude;\n\nconst orderedViewTabSectionsInclude = {\n sections: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n },\n} satisfies Prisma.ViewTabInclude;\n\ntype DbViewSection = Prisma.ViewSectionGetPayload<{\n include: typeof orderedViewSectionTagsInclude;\n}>;\n\ntype DbViewTab = Prisma.ViewTabGetPayload<{\n include: typeof orderedViewTabSectionsInclude;\n}>;\n\nconst normalizeTagName = (value: string) => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n return '';\n }\n\n if (trimmedValue.startsWith('@')) {\n return trimmedValue;\n }\n\n if (trimmedValue.startsWith('#')) {\n return `@${trimmedValue.slice(1)}`;\n }\n\n return `@${trimmedValue}`;\n};\n\nexport const normalizeViewTagNames = (values: string[]) => {\n const normalizedTagNames = values.flatMap((value) => value.split(','));\n\n return Array.from(new Set(normalizedTagNames.map(normalizeTagName).filter(Boolean)));\n};\n\ninterface StoredViewQuery {\n propertyFilters?: ViewPropertyFilterRecord[];\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n displayOptions?: Partial<ViewDisplayOptionsRecord>;\n}\n\ninterface ParsedStoredViewQuery {\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n displayOptions: ViewDisplayOptionsRecord;\n}\n\nconst isViewPropertyFilterOperator = (value: unknown): value is ViewPropertyFilterOperator => {\n return (\n value === 'equals' ||\n value === 'notEquals' ||\n value === 'contains' ||\n value === 'notContains' ||\n value === 'before' ||\n value === 'after' ||\n value === 'exists' ||\n value === 'notExists'\n );\n};\n\nconst isPropertyValueType = (value: unknown): value is PropertyValueType => {\n return (\n value === 'text' ||\n value === 'url' ||\n value === 'number' ||\n value === 'date' ||\n value === 'boolean' ||\n value === 'select'\n );\n};\n\nconst isViewTableColumn = (value: unknown): value is ViewTableColumn => {\n return (\n value === 'title' ||\n value === 'tags' ||\n value === 'properties' ||\n value === 'createdAt' ||\n value === 'updatedAt'\n );\n};\n\nconst normalizeViewDisplayType = (value: ViewDisplayType | undefined): ViewDisplayType => {\n if (value === 'table' || value === 'calendar') {\n return value;\n }\n\n return DEFAULT_VIEW_DISPLAY_TYPE;\n};\n\nconst normalizeViewSortBy = (value: ViewSortBy | undefined): ViewSortBy => {\n return value === 'createdAt' || value === 'title' ? value : DEFAULT_VIEW_SORT_BY;\n};\n\nconst normalizeViewSortOrder = (value: ViewSortOrder | undefined): ViewSortOrder => {\n return value === 'asc' ? 'asc' : DEFAULT_VIEW_SORT_ORDER;\n};\n\nexport const normalizeViewTableColumns = (columns: ViewTableColumn[] | null | undefined): ViewTableColumn[] => {\n const normalizedColumns = (columns ?? []).filter(isViewTableColumn);\n const uniqueColumns = Array.from(new Set(normalizedColumns));\n\n if (uniqueColumns.length === 0) {\n return [...DEFAULT_VIEW_TABLE_COLUMNS];\n }\n\n return uniqueColumns.includes('title') ? uniqueColumns : ['title' as const, ...uniqueColumns];\n};\n\nexport const normalizeViewDisplayOptions = (\n options: ViewDisplayOptionsInput | Partial<ViewDisplayOptionsRecord> | null | undefined,\n): ViewDisplayOptionsRecord => {\n return {\n tableColumns: normalizeViewTableColumns(options?.tableColumns),\n };\n};\n\nconst normalizeFilterValue = ({\n value,\n valueType,\n operator,\n}: {\n value?: string | null;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n}) => {\n if (operator === 'exists' || operator === 'notExists') {\n return null;\n }\n\n const normalizedValue = String(value ?? '').trim();\n\n if (!normalizedValue) {\n throw new InvalidNotePropertyInputError('Property filter value is required.');\n }\n\n if (valueType === 'number' && !Number.isFinite(Number(normalizedValue))) {\n throw new InvalidNotePropertyInputError('Number property filter value must be finite.');\n }\n\n if (valueType === 'boolean' && normalizedValue !== 'true' && normalizedValue !== 'false') {\n throw new InvalidNotePropertyInputError('Boolean property filter value must be true or false.');\n }\n\n if (valueType === 'date') {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(normalizedValue)) {\n throw new InvalidNotePropertyInputError('Date property filter values must use YYYY-MM-DD.');\n }\n\n const date = new Date(`${normalizedValue}T00:00:00.000Z`);\n\n if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== normalizedValue) {\n throw new InvalidNotePropertyInputError('Date property filter value is invalid.');\n }\n }\n\n if ((operator === 'before' || operator === 'after') && valueType !== 'date' && valueType !== 'number') {\n throw new InvalidNotePropertyInputError('Before and after filters require date or number properties.');\n }\n\n if ((operator === 'contains' || operator === 'notContains') && valueType !== 'text' && valueType !== 'url') {\n throw new InvalidNotePropertyInputError('Contains filters require text or url properties.');\n }\n\n if (valueType === 'url' && operator !== 'contains' && operator !== 'notContains') {\n return normalizeUrlValue(normalizedValue);\n }\n\n return normalizedValue;\n};\n\nexport const normalizeViewPropertyFilters = (filters: ViewPropertyFilterInput[] | null | undefined) => {\n const normalizedFilters = filters ?? [];\n\n if (normalizedFilters.length > MAX_VIEW_PROPERTY_FILTERS) {\n throw new InvalidNotePropertyInputError(`A view can have up to ${MAX_VIEW_PROPERTY_FILTERS} property filters.`);\n }\n\n return normalizedFilters\n .map((filter): ViewPropertyFilterRecord | null => {\n const key = normalizePropertyKey(filter.key);\n const valueType = filter.valueType;\n const operator = filter.operator;\n\n if (!isPropertyValueType(valueType)) {\n throw new InvalidNotePropertyInputError('Property filter value type is required.');\n }\n\n if (!isViewPropertyFilterOperator(operator)) {\n throw new InvalidNotePropertyInputError('Property filter operator is invalid.');\n }\n\n const storedName = (filter as { name?: unknown }).name;\n const name = typeof storedName === 'string' && storedName.trim() ? storedName.trim() : key;\n\n return {\n key,\n name,\n valueType,\n operator,\n value: normalizeFilterValue({\n value: filter.value,\n valueType,\n operator,\n }),\n };\n })\n .filter((filter): filter is ViewPropertyFilterRecord => filter !== null);\n};\n\nconst parseStoredViewQuery = (value: string | null): ParsedStoredViewQuery => {\n if (!value) {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n displayOptions: normalizeViewDisplayOptions(null),\n };\n }\n\n try {\n const parsed = JSON.parse(value) as Partial<StoredViewQuery>;\n\n return {\n propertyFilters: normalizeViewPropertyFilters(parsed.propertyFilters ?? []),\n sortBy: normalizeViewSortBy(parsed.sortBy),\n sortOrder: normalizeViewSortOrder(parsed.sortOrder),\n displayOptions: normalizeViewDisplayOptions(parsed.displayOptions),\n };\n } catch {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n displayOptions: normalizeViewDisplayOptions(null),\n };\n }\n};\n\nconst serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder, displayOptions }: ParsedStoredViewQuery) => {\n return JSON.stringify({\n propertyFilters,\n sortBy,\n sortOrder,\n displayOptions,\n });\n};\n\nexport const clampViewSectionLimit = (value: number | undefined) => {\n const numericValue = typeof value === 'number' ? value : Number.NaN;\n\n if (!Number.isInteger(numericValue)) {\n return DEFAULT_VIEW_SECTION_LIMIT;\n }\n\n return Math.min(MAX_VIEW_SECTION_LIMIT, Math.max(MIN_VIEW_SECTION_LIMIT, numericValue));\n};\n\nexport const normalizeViewTabTitle = (title: string) => {\n const trimmedTitle = title.trim();\n\n return trimmedTitle || 'Untitled View';\n};\n\nconst buildDefaultSectionTitle = (tagNames: string[], propertyFilters: ViewPropertyFilterRecord[]) => {\n if (tagNames.length > 0) {\n return tagNames.slice(0, 2).join(' + ');\n }\n\n if (propertyFilters.length > 0) {\n return propertyFilters\n .slice(0, 2)\n .map((filter) => filter.name)\n .join(' + ');\n }\n\n return 'All notes';\n};\n\nexport const normalizeViewSectionInput = (input: ViewSectionInput) => {\n const tagNames = normalizeViewTagNames(input.tagNames ?? []);\n const propertyFilters = normalizeViewPropertyFilters(input.propertyFilters);\n const trimmedTitle = input.title?.trim() ?? '';\n const sortBy = normalizeViewSortBy(input.sortBy);\n const sortOrder = normalizeViewSortOrder(input.sortOrder);\n const displayOptions = normalizeViewDisplayOptions(input.displayOptions);\n\n return {\n title: trimmedTitle || buildDefaultSectionTitle(tagNames, propertyFilters),\n displayType: normalizeViewDisplayType(input.displayType),\n displayOptions,\n tagNames,\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters,\n sortBy,\n sortOrder,\n limit: clampViewSectionLimit(input.limit),\n } satisfies {\n title: string;\n displayType: ViewDisplayType;\n displayOptions: ViewDisplayOptionsRecord;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n };\n};\n\nexport const normalizeViewNotesQueryInput = (input: ViewNotesQueryInput): ViewNotesQueryRecord => {\n return {\n tagNames: normalizeViewTagNames(input.tagNames ?? []),\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters: normalizeViewPropertyFilters(input.propertyFilters),\n sortBy: normalizeViewSortBy(input.sortBy),\n sortOrder: normalizeViewSortOrder(input.sortOrder),\n };\n};\n\nexport const normalizeViewNotesPagination = (pagination?: { limit?: number; offset?: number }) => {\n const numericLimit = Number(pagination?.limit ?? DEFAULT_VIEW_NOTES_QUERY_LIMIT);\n const limit = Number.isInteger(numericLimit)\n ? Math.min(MAX_VIEW_NOTES_QUERY_LIMIT, Math.max(1, numericLimit))\n : DEFAULT_VIEW_NOTES_QUERY_LIMIT;\n const numericOffset = Number(pagination?.offset ?? 0);\n const offset = Number.isInteger(numericOffset) ? Math.max(0, numericOffset) : 0;\n\n return { limit, offset };\n};\n\nexport const pickNextActiveViewTabId = (tabIds: number[], deletedTabId: number, currentActiveTabId: number | null) => {\n const remainingTabIds = tabIds.filter((tabId) => tabId !== deletedTabId);\n\n if (remainingTabIds.length === 0) {\n return null;\n }\n\n if (currentActiveTabId !== deletedTabId) {\n return currentActiveTabId;\n }\n\n return remainingTabIds[0] ?? null;\n};\n\nconst ensureValidReorderIds = (currentIds: number[], nextIds: number[]) => {\n if (currentIds.length !== nextIds.length) {\n throw new Error('Reorder payload must include every item exactly once.');\n }\n\n const currentIdSet = new Set(currentIds);\n const nextIdSet = new Set(nextIds);\n\n if (currentIdSet.size !== currentIds.length || nextIdSet.size !== nextIds.length) {\n throw new Error('Reorder payload contains duplicate ids.');\n }\n\n for (const id of currentIdSet) {\n if (!nextIdSet.has(id)) {\n throw new Error('Reorder payload must match the current item set.');\n }\n }\n};\n\nconst parseViewId = (id: string) => {\n const numericId = Number(id);\n\n if (!Number.isInteger(numericId) || numericId <= 0) {\n throw new Error('A valid id is required.');\n }\n\n return numericId;\n};\n\nconst serializeViewSection = (section: DbViewSection): ViewSectionRecord => {\n const query = parseStoredViewQuery(section.query);\n\n return {\n id: String(section.id),\n tabId: String(section.tabId),\n title: section.title,\n displayType: normalizeViewDisplayType(section.displayType as ViewDisplayType),\n displayOptions: query.displayOptions,\n tagNames: section.tags.map((tag) => tag.name),\n mode: section.mode as ViewTagMatchMode,\n propertyFilters: query.propertyFilters,\n sortBy: query.sortBy,\n sortOrder: query.sortOrder,\n limit: section.limit,\n order: section.order,\n };\n};\n\nconst serializeViewTab = (tab: DbViewTab): ViewTabRecord => ({\n id: String(tab.id),\n title: tab.title,\n order: tab.order,\n sections: tab.sections.map(serializeViewSection),\n});\n\nconst getOrderedViewTabs = async (db: ViewDbClient) => {\n return db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewTabSectionsInclude,\n });\n};\n\nconst ensureViewWorkspace = async (db: ViewDbClient) => {\n return db.viewWorkspace.upsert({\n where: { id: VIEW_WORKSPACE_ID },\n update: {},\n create: { id: VIEW_WORKSPACE_ID },\n });\n};\n\nconst readViewWorkspace = async (db: ViewDbClient): Promise<ViewWorkspaceRecord> => {\n const [workspace, tabs] = await Promise.all([ensureViewWorkspace(db), getOrderedViewTabs(db)]);\n\n const activeTabId =\n workspace.activeTabId !== null && tabs.some((tab) => tab.id === workspace.activeTabId)\n ? String(workspace.activeTabId)\n : tabs[0]\n ? String(tabs[0].id)\n : null;\n\n return {\n activeTabId,\n tabs: tabs.map(serializeViewTab),\n };\n};\n\nconst readViewSection = async (db: ViewDbClient, id: number): Promise<ViewSectionRecord | null> => {\n const section = await db.viewSection.findUnique({\n where: { id },\n include: orderedViewSectionTagsInclude,\n });\n\n return section ? serializeViewSection(section) : null;\n};\n\nexport const hydratePropertyFilters = async (\n db: ViewDbClient,\n filters: ViewPropertyFilterRecord[],\n options: { validateSelectOptions?: boolean } = {},\n) => {\n if (filters.length === 0) {\n return [];\n }\n\n const definitions = await db.propertyDefinition.findMany({\n where: { key: { in: filters.map((filter) => filter.key) } },\n select: {\n key: true,\n name: true,\n valueType: true,\n options: {\n select: {\n value: true,\n },\n },\n },\n });\n const definitionByKey = new Map(definitions.map((definition) => [definition.key, definition]));\n\n return filters.map((filter) => {\n const definition = definitionByKey.get(filter.key);\n\n if (!definition) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} is not defined.`);\n }\n\n if (definition.valueType !== filter.valueType) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} uses ${definition.valueType} values.`);\n }\n\n if (\n options.validateSelectOptions &&\n filter.valueType === 'select' &&\n filter.operator !== 'exists' &&\n filter.operator !== 'notExists'\n ) {\n const optionValue = normalizeSelectFilterValue(filter.value ?? '');\n\n if (!definition.options.some((option) => option.value === optionValue)) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} option ${optionValue} is not defined.`);\n }\n }\n\n return {\n ...filter,\n name: definition.name,\n };\n });\n};\n\nconst buildStoredViewQuery = async (db: ViewDbClient, section: ReturnType<typeof normalizeViewSectionInput>) => {\n const propertyFilters = await hydratePropertyFilters(db, section.propertyFilters, { validateSelectOptions: true });\n\n return serializeStoredViewQuery({\n propertyFilters,\n sortBy: section.sortBy,\n sortOrder: section.sortOrder,\n displayOptions: section.displayOptions,\n });\n};\n\nconst getNextTabOrder = async (db: ViewDbClient) => {\n const lastTab = await db.viewTab.findFirst({\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastTab ? lastTab.order + 1 : 0;\n};\n\nconst getNextSectionOrder = async (db: ViewDbClient, tabId: number) => {\n const lastSection = await db.viewSection.findFirst({\n where: { tabId },\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastSection ? lastSection.order + 1 : 0;\n};\n\nconst resequenceViewTabs = async (db: ViewDbClient) => {\n const tabs = await db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n tabs.map((tab, index) =>\n db.viewTab.update({\n where: { id: tab.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nconst resequenceViewSections = async (db: ViewDbClient, tabId: number) => {\n const sections = await db.viewSection.findMany({\n where: { tabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n sections.map((section, index) =>\n db.viewSection.update({\n where: { id: section.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nexport const getViewWorkspace = async () => {\n return readViewWorkspace(models);\n};\n\nexport const getViewSectionById = async (id: string) => {\n return readViewSection(models, parseViewId(id));\n};\n\nconst normalizeSelectFilterValue = (value: string) => {\n return value.trim().toLowerCase().replace(/\\s+/g, '-');\n};\n\nconst buildPropertyFilterValueWhere = (filter: ViewPropertyFilterRecord): Prisma.NotePropertyWhereInput => {\n switch (filter.valueType) {\n case 'number': {\n const numberValue = Number(filter.value);\n\n if (filter.operator === 'before') {\n return { numberValue: { lt: numberValue } };\n }\n\n if (filter.operator === 'after') {\n return { numberValue: { gt: numberValue } };\n }\n\n if (filter.operator === 'notEquals') {\n return { numberValue: { not: numberValue } };\n }\n\n return { numberValue };\n }\n case 'date': {\n const dateValue = new Date(`${filter.value}T00:00:00.000Z`);\n\n if (filter.operator === 'before') {\n return { dateValue: { lt: dateValue } };\n }\n\n if (filter.operator === 'after') {\n return { dateValue: { gt: dateValue } };\n }\n\n if (filter.operator === 'notEquals') {\n return { dateValue: { not: dateValue } };\n }\n\n return { dateValue };\n }\n case 'boolean': {\n if (filter.operator === 'notEquals') {\n return { boolValue: { not: filter.value === 'true' } };\n }\n\n return { boolValue: filter.value === 'true' };\n }\n case 'select':\n if (filter.operator === 'notEquals') {\n return { option: { is: { value: { not: normalizeSelectFilterValue(filter.value ?? '') } } } };\n }\n\n return { option: { is: { value: normalizeSelectFilterValue(filter.value ?? '') } } };\n case 'url':\n case 'text':\n default: {\n const textValue = filter.value?.toLowerCase() ?? '';\n\n if (filter.operator === 'notEquals') {\n return { textValueNormalized: { not: textValue } };\n }\n\n if (filter.operator === 'contains') {\n return { textValueNormalized: { contains: textValue } };\n }\n\n if (filter.operator === 'notContains') {\n return { textValueNormalized: { not: { contains: textValue } } };\n }\n\n return { textValueNormalized: textValue };\n }\n }\n};\n\nexport const buildPropertyFilterWhere = (filter: ViewPropertyFilterRecord): Prisma.NoteWhereInput => {\n const definitionWhere = {\n definition: {\n is: {\n key: filter.key,\n },\n },\n } satisfies Prisma.NotePropertyWhereInput;\n\n if (filter.operator === 'notExists') {\n return {\n properties: {\n none: definitionWhere,\n },\n };\n }\n\n if (filter.operator === 'exists') {\n return {\n properties: {\n some: definitionWhere,\n },\n };\n }\n\n return {\n properties: {\n some: {\n ...definitionWhere,\n ...buildPropertyFilterValueWhere(filter),\n },\n },\n };\n};\n\nexport const buildViewNotesWhere = (\n query: Pick<ViewNotesQueryRecord, 'tagNames' | 'mode' | 'propertyFilters'>,\n): Prisma.NoteWhereInput => {\n const clauses: Prisma.NoteWhereInput[] = [];\n\n if (query.tagNames.length > 0) {\n clauses.push(buildNoteTagNamesWhere(query.tagNames, query.mode as NoteTagMatchMode));\n }\n\n for (const filter of query.propertyFilters) {\n clauses.push(buildPropertyFilterWhere(filter));\n }\n\n if (clauses.length === 0) {\n return {};\n }\n\n return { AND: clauses };\n};\n\nexport const buildViewSectionWhere = (section: ViewSectionRecord): Prisma.NoteWhereInput => {\n return buildViewNotesWhere(section);\n};\n\nconst buildViewNotesOrderBy = (\n query: Pick<ViewNotesQueryRecord, 'sortBy' | 'sortOrder'>,\n): Prisma.NoteOrderByWithRelationInput[] => {\n return [{ [query.sortBy]: query.sortOrder }, { id: 'asc' }];\n};\n\nconst buildViewSectionOrderBy = (section: ViewSectionRecord): Prisma.NoteOrderByWithRelationInput[] => {\n return buildViewNotesOrderBy(section);\n};\n\nexport const getViewSectionNotes = async (\n id: string,\n pagination: {\n limit: number;\n offset: number;\n },\n): Promise<ViewSectionNotesResult | null> => {\n const section = await models.viewSection.findUnique({\n where: { id: parseViewId(id) },\n include: orderedViewSectionTagsInclude,\n });\n\n if (!section) {\n return null;\n }\n\n const serializedSection = serializeViewSection(section);\n const where = buildViewSectionWhere(serializedSection);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewSectionOrderBy(serializedSection),\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset),\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByPropertiesWithDb = async (\n db: ViewDbClient,\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n const normalizedQuery = normalizeViewNotesQueryInput(input);\n\n if (normalizedQuery.propertyFilters.length === 0) {\n throw new InvalidNotePropertyInputError('At least one property filter is required.');\n }\n\n const query = {\n ...normalizedQuery,\n propertyFilters: await hydratePropertyFilters(db, normalizedQuery.propertyFilters, {\n validateSelectOptions: true,\n }),\n };\n const normalizedPagination = normalizeViewNotesPagination(pagination);\n const where = buildViewNotesWhere(query);\n\n const [totalCount, notes] = await Promise.all([\n db.note.count({ where }),\n db.note.findMany({\n orderBy: buildViewNotesOrderBy(query),\n where,\n take: normalizedPagination.limit,\n skip: normalizedPagination.offset,\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByProperties = async (\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n return getNotesByPropertiesWithDb(models, input, pagination);\n};\n\nexport const createViewTab = async (title: string) => {\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const nextTabOrder = await getNextTabOrder(tx);\n const createdTab = await tx.viewTab.create({\n data: {\n title: normalizeViewTabTitle(title),\n order: nextTabOrder,\n },\n include: orderedViewTabSectionsInclude,\n });\n\n if (workspace.activeTabId === null) {\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: createdTab.id },\n });\n }\n\n return serializeViewTab(createdTab);\n });\n};\n\nexport const updateViewTab = async (id: string, title: string) => {\n const updatedTab = await models.viewTab.update({\n where: { id: parseViewId(id) },\n data: {\n title: normalizeViewTabTitle(title),\n },\n include: orderedViewTabSectionsInclude,\n });\n\n return serializeViewTab(updatedTab);\n};\n\nexport const deleteViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n if (!tabs.some((tab) => tab.id === tabId)) {\n return false;\n }\n\n await tx.viewTab.delete({ where: { id: tabId } });\n await resequenceViewTabs(tx);\n\n const nextActiveTabId = pickNextActiveViewTabId(\n tabs.map((tab) => tab.id),\n tabId,\n workspace.activeTabId,\n );\n\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: nextActiveTabId },\n });\n\n return true;\n });\n};\n\nexport const setActiveViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tab = await tx.viewTab.findUnique({\n where: { id: tabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n await tx.viewWorkspace.update({\n where: { id: workspace.id },\n data: { activeTabId: tabId },\n });\n\n return readViewWorkspace(tx);\n });\n};\n\nexport const reorderViewTabs = async (tabIds: string[]) => {\n const nextTabIds = tabIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentTabIds = tabs.map((tab) => tab.id);\n\n ensureValidReorderIds(currentTabIds, nextTabIds);\n\n await Promise.all(\n nextTabIds.map((tabId, index) =>\n tx.viewTab.update({\n where: { id: tabId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedTabs = await getOrderedViewTabs(tx);\n return reorderedTabs.map(serializeViewTab);\n });\n};\n\nexport const createViewSection = async (tabId: string, input: ViewSectionInput) => {\n const numericTabId = parseViewId(tabId);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const tab = await tx.viewTab.findUnique({\n where: { id: numericTabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n const nextSectionOrder = await getNextSectionOrder(tx, numericTabId);\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const createdSection = await tx.viewSection.create({\n data: {\n tabId: numericTabId,\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n order: nextSectionOrder,\n tags: {\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(createdSection);\n });\n};\n\nexport const updateViewSection = async (id: string, input: ViewSectionInput) => {\n const sectionId = parseViewId(id);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const updatedSection = await tx.viewSection.update({\n where: { id: sectionId },\n data: {\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n tags: {\n deleteMany: {},\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(updatedSection);\n });\n};\n\nexport const deleteViewSection = async (id: string) => {\n const sectionId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const section = await tx.viewSection.findUnique({\n where: { id: sectionId },\n select: { id: true, tabId: true },\n });\n\n if (!section) {\n return false;\n }\n\n await tx.viewSection.delete({\n where: { id: sectionId },\n });\n await resequenceViewSections(tx, section.tabId);\n\n return true;\n });\n};\n\nexport const reorderViewSections = async (tabId: string, sectionIds: string[]) => {\n const numericTabId = parseViewId(tabId);\n const nextSectionIds = sectionIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const sections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentSectionIds = sections.map((section) => section.id);\n\n ensureValidReorderIds(currentSectionIds, nextSectionIds);\n\n await Promise.all(\n nextSectionIds.map((sectionId, index) =>\n tx.viewSection.update({\n where: { id: sectionId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedSections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n });\n\n return reorderedSections.map(serializeViewSection);\n });\n};\n"],"mappings":"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","names":[]}
@@ -289,5 +289,6 @@ enum ViewTagMatchMode {
289
289
 
290
290
  enum ViewDisplayType {
291
291
  list
292
+ table
292
293
  calendar
293
294
  }
@@ -1 +0,0 @@
1
- import{j as e}from"./note-vendor-uuJO2MTD.js";import{P as p,G as j,a0 as F,i as r,j as P,V as C,av as T,u as k,q as f,a6 as q,ac as m,aM as R,a1 as $,T as D}from"./index-nYj7BL3a.js";import{v as E,f as A,a as K,d as y}from"./view-dashboard-B5fKgvk_.js";import"./graph-vendor-CUxe67Lr.js";import"./note-core-DMZcZ4yV.js";const h=P(C);function M(){const o=h.useNavigate(),{page:i,sectionId:n}=h.useSearch(),{onDelete:w,onPinned:v,deleteWarningDialog:N}=T(),a=25,{data:l}=k({queryKey:f.views.section(n),async queryFn(){const t=await E(n);if(t.type==="error")throw t;return t.viewSection}}),{data:s}=q({queryKey:f.views.sectionNotes(n,{limit:a,offset:(i-1)*a}),async queryFn(){const t=await A(n,{limit:a,offset:(i-1)*a});if(t.type==="error")throw t;return t.viewSectionNotes}}),d=l?.title||"View Notes",c=l?.tagNames??[],x=l?.mode??"and",u=l?.propertyFilters??[],b=c.length>0,g=u.length>0,V=b?g?`Property and tag filters · ${y(x)}`:`Tag filters · ${y(x)}`:g?"Property filters":"All notes";return e.jsxs(p,{title:d,heading:s.totalCount>0?`${d} (${s.totalCount})`:d,description:e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(D,{as:"span",variant:"meta",tone:"tertiary",children:V}),e.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[c.map(t=>e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle bg-hover-subtle px-2.5 py-1 text-xs font-medium text-fg-secondary",children:t},t)),u.map(t=>e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle bg-hover-subtle px-2.5 py-1 text-xs font-medium text-fg-secondary",children:K(t)},`${t.key}-${t.operator}-${t.value??""}`)),c.length===0&&u.length===0&&e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle bg-hover-subtle px-2.5 py-1 text-xs font-medium text-fg-secondary",children:"All notes"})]})]}),children:[e.jsx(m,{fallback:e.jsx(j,{title:"No notes match this saved view",description:"Adjust this view's filters or keep writing until matching notes appear."}),children:s.notes.length>0&&e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("div",{className:"grid-auto-cards grid gap-5",children:s.notes.map(t=>e.jsx(R,{...t,onPinned:()=>v(t.id,t.pinned),onDelete:()=>w(t.id)},t.id))}),e.jsx(m,{fallback:null,children:s.totalCount&&a<s.totalCount&&e.jsx($,{page:i,last:Math.ceil(s.totalCount/a),onChange:t=>{o({search:S=>({...S,page:t})})}})})]})}),N]})}function _(){const{sectionId:o,page:i}=h.useSearch();return o?e.jsx(F,{fallback:e.jsx(p,{title:"View Notes",heading:e.jsx(r,{width:180,height:24,className:"rounded-full"}),description:e.jsx(r,{width:220,height:16,className:"rounded-full"}),children:e.jsxs("div",{className:"grid-auto-cards grid gap-5",children:[e.jsx(r,{height:"112px"}),e.jsx(r,{height:"112px"}),e.jsx(r,{height:"112px"})]})}),errorTitle:"Failed to load view notes",errorDescription:"Retry loading notes for this saved view section",resetKeys:[i,o],children:e.jsx(M,{})}):e.jsx(p,{title:"View Notes",description:"Saved view note lists require a section id.",children:e.jsx(j,{title:"No section selected",description:"Return to Views and open a section from there."})})}export{_ as default};
@@ -1 +0,0 @@
1
- import{j as e}from"./note-vendor-uuJO2MTD.js";import{p as Le,u as G,q as D,T as c,L as te,V as le,D as Te,k as Se,B as k,N as Me,t as Re,M as L,l as A,I as ie,S as q,e as v,m as Ie,n as qe,o as oe,r as Ce,v as Oe,w as We,x as _e,y as Pe,z as de,A as He,K as Ke,E as $e,F as Be,P as Ue,i as se,G as ce,H as me,J as Ze,O as ue,Q as xe,R as Qe,U as Ye,W as Ge,X as Je,Y as Ve,Z as Fe,c as J,_ as Ee}from"./index-nYj7BL3a.js";import{a as r}from"./graph-vendor-CUxe67Lr.js";import{b as Xe,f as et,g as tt,a as st,n as pe,c as at,d as he,e as rt,h as nt,E as it,s as lt,i as ot,r as dt,j as ct,k as mt,l as ut,m as xt,u as pt,o as ht,p as gt,q as ft,t as bt}from"./view-dashboard-B5fKgvk_.js";import{S as H}from"./SurfaceCard-FhlC8VSR.js";import{n as ae}from"./Plus.es-BKm7uDYu.js";import"./note-core-DMZcZ4yV.js";const vt=new Map([["bold",r.createElement(r.Fragment,null,r.createElement("path",{d:"M224.49,136.49l-72,72a12,12,0,0,1-17-17L187,140H40a12,12,0,0,1,0-24H187L135.51,64.48a12,12,0,0,1,17-17l72,72A12,12,0,0,1,224.49,136.49Z"}))],["duotone",r.createElement(r.Fragment,null,r.createElement("path",{d:"M216,128l-72,72V56Z",opacity:"0.2"}),r.createElement("path",{d:"M221.66,122.34l-72-72A8,8,0,0,0,136,56v64H40a8,8,0,0,0,0,16h96v64a8,8,0,0,0,13.66,5.66l72-72A8,8,0,0,0,221.66,122.34ZM152,180.69V75.31L204.69,128Z"}))],["fill",r.createElement(r.Fragment,null,r.createElement("path",{d:"M221.66,133.66l-72,72A8,8,0,0,1,136,200V136H40a8,8,0,0,1,0-16h96V56a8,8,0,0,1,13.66-5.66l72,72A8,8,0,0,1,221.66,133.66Z"}))],["light",r.createElement(r.Fragment,null,r.createElement("path",{d:"M220.24,132.24l-72,72a6,6,0,0,1-8.48-8.48L201.51,134H40a6,6,0,0,1,0-12H201.51L139.76,60.24a6,6,0,0,1,8.48-8.48l72,72A6,6,0,0,1,220.24,132.24Z"}))],["regular",r.createElement(r.Fragment,null,r.createElement("path",{d:"M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"}))],["thin",r.createElement(r.Fragment,null,r.createElement("path",{d:"M218.83,130.83l-72,72a4,4,0,0,1-5.66-5.66L206.34,132H40a4,4,0,0,1,0-8H206.34L141.17,58.83a4,4,0,0,1,5.66-5.66l72,72A4,4,0,0,1,218.83,130.83Z"}))]]),De=r.forwardRef((t,i)=>r.createElement(Le,{ref:i,...t,weights:vt}));De.displayName="ArrowRightIcon";const yt=De,jt="flex items-start justify-between gap-3 rounded-[14px] border border-border-subtle/70 px-3 py-2.5 transition-colors hover:border-border-secondary hover:bg-hover-subtle";function wt({section:t,onEdit:i,onDelete:n,dragHandle:u}){const x=Xe(t),{data:p,isPending:g,isError:f,refetch:V}=G({queryKey:D.views.sectionNotes(t.id,{limit:t.limit,offset:0}),async queryFn(){const h=await et(t.id,{limit:t.limit,offset:0});if(h.type==="error")throw h;return h.viewSectionNotes}}),j=p?.notes??[],O=p?.totalCount??0,N=tt(t.mode),l=t.tagNames.length>0||t.propertyFilters.length>0;return e.jsxs(H,{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[u&&e.jsx("div",{className:"-mr-1 shrink-0 self-center",children:u}),e.jsx("div",{className:"min-w-0",children:e.jsx(c,{as:"h2",variant:"subheading",weight:"semibold",tracking:"tight",className:"min-w-0",children:e.jsx(te,{to:le,search:x,className:"truncate hover:text-fg-default/85",children:t.title})})})]}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-1.5",children:[t.tagNames.map((h,M)=>e.jsxs("div",{className:"flex items-center gap-1.5",children:[M>0&&e.jsx("span",{className:"px-0.5 text-[10px] font-semibold tracking-[0.08em] text-fg-tertiary/85",children:N}),e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle/80 bg-transparent px-2.5 py-1 text-xs font-medium text-fg-secondary",children:h})]},h)),t.propertyFilters.map(h=>e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle/80 bg-subtle px-2.5 py-1 text-xs font-medium text-fg-secondary",children:st(h)},`${h.key}-${h.operator}-${h.value??""}`)),!l&&e.jsx("span",{className:"inline-flex items-center rounded-full border border-border-subtle/80 bg-transparent px-2.5 py-1 text-xs font-medium text-fg-tertiary",children:"All notes"})]})]}),e.jsx("div",{className:"shrink-0",children:e.jsx(Te,{button:e.jsx(Se,{label:"Section actions"}),items:[{name:"Edit section",onClick:i},{type:"separator"},{name:"Delete section",onClick:n}]})})]}),e.jsxs("div",{className:"flex flex-1 flex-col gap-2.5",children:[g&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"h-14 animate-pulse rounded-[14px] bg-hover-subtle"}),e.jsx("div",{className:"h-14 animate-pulse rounded-[14px] bg-hover-subtle"}),e.jsx("div",{className:"h-14 animate-pulse rounded-[14px] bg-hover-subtle"})]}),f&&e.jsxs("div",{className:"rounded-[16px] border border-border-subtle bg-hover-subtle/70 p-4",children:[e.jsx(c,{as:"p",variant:"body",weight:"semibold",children:"Failed to load this section"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Retry to refresh this saved query."}),e.jsx("div",{className:"mt-3",children:e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:()=>V(),children:"Retry"})})]}),!g&&!f&&j.length===0&&e.jsxs("div",{className:"rounded-[16px] border border-dashed border-border-subtle px-4 py-5",children:[e.jsx(c,{as:"p",variant:"body",weight:"semibold",children:"No notes match yet"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Add matching notes, or edit this view query."})]}),!g&&!f&&j.map(h=>e.jsxs(te,{to:Me,params:{id:h.id},className:jt,children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx(c,{as:"div",variant:"body",weight:"semibold",className:"line-clamp-1",children:h.title||"Untitled"}),e.jsxs(c,{as:"div",variant:"meta",tone:"tertiary",className:"mt-1",children:["Updated ",Re(Number(h.updatedAt))]})]}),e.jsx(yt,{className:"mt-0.5 h-4 w-4 shrink-0 text-fg-tertiary"})]},h.id))]}),e.jsxs("div",{className:"flex items-center justify-between gap-3 border-t border-border-subtle/70 pt-4",children:[e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",children:g?"Loading notes...":`Showing ${j.length} of ${O} notes`}),e.jsx(k,{asChild:!0,variant:"subtle",size:"sm",children:e.jsx(te,{to:le,search:x,children:"Open list"})})]})]})}const re="__choose_property__",ge=t=>String(t?.limit??5),fe=t=>t?.mode??"and",be=t=>t?t.tagNames.join(", "):"",ve=t=>t?.title??"",ye=t=>t?.sortBy??"updatedAt",je=t=>t?.sortOrder??"desc",Ae=t=>`property-filter-${Date.now()}-${t}`,we=t=>(t?.propertyFilters??[]).map((i,n)=>({id:Ae(n),key:i.key,operator:i.operator,value:i.value??""})),Ne=t=>t?t.valueType==="date"||t.valueType==="number"?["equals","before","after","exists","notExists"]:["equals","exists","notExists"]:["exists","notExists"],ke=t=>t?"equals":"exists",Nt=t=>t?t.valueType==="boolean"?"true":t.valueType==="select"?t.options[0]?.value??"":"":"",ne=t=>t!=="exists"&&t!=="notExists";function kt({open:t,mode:i,initialSection:n=null,availableTags:u,availableProperties:x,isTagsLoading:p=!1,isPropertiesLoading:g=!1,onClose:f,onSubmit:V}){const[j,O]=r.useState(ve(n)),[N,l]=r.useState(be(n)),[h,M]=r.useState(fe(n)),[K,Z]=r.useState(ye(n)),[Q,Y]=r.useState(je(n)),[$,C]=r.useState(ge(n)),[y,W]=r.useState(we(n)),[X,B]=r.useState((n?.tagNames.length??0)>0),[U,w]=r.useState(""),_=r.useMemo(()=>new Map(x.map(a=>[a.key,a])),[x]);r.useEffect(()=>{t&&(O(ve(n)),l(be(n)),M(fe(n)),Z(ye(n)),Y(je(n)),C(ge(n)),W(we(n)),B((n?.tagNames.length??0)>0),w(""))},[n,t]);const F=pe([N]),P=X||F.length>0,s=F.length===0&&y.length===0,d=a=>{const m=F.includes(a)?F.filter(z=>z!==a):[...F,a];l(m.join(", ")),w("")},E=()=>{B(!0),w("")},T=()=>{l(""),M("and"),B(!1),w("")},R=()=>{if(x.length===0){w("Create a shared property before adding a filter.");return}W(a=>[...a,{id:Ae(a.length),key:"",operator:"exists",value:""}]),w("")},S=(a,m)=>{W(z=>z.map(o=>{if(o.id!==a)return o;const I={...o,...m},b=_.get(I.key);return Ne(b).includes(I.operator)||(I.operator=ke(b)),"key"in m&&(I.value=Nt(b),I.operator=ke(b)),I})),w("")},ze=a=>{W(m=>m.filter(z=>z.id!==a)),w("")};return e.jsxs(L,{isOpen:t,onClose:f,variant:"form",className:"sm:max-w-[720px]",children:[e.jsx(L.Header,{title:i==="create"?"Create view":"Edit view",onClose:f}),e.jsx(L.Body,{children:e.jsxs("form",{id:"view-section-form",className:"flex flex-col gap-5",onSubmit:a=>{a.preventDefault();const m=pe([N]);if(P&&m.length===0){w("Choose at least one tag, or remove this tag filter.");return}if(y.find(b=>!b.key||!_.has(b.key))){w("Choose a property for every filter.");return}const o=y.map(b=>{const ee=_.get(b.key);return{key:ee?.key??b.key,valueType:ee?.valueType??"text",operator:b.operator,value:ne(b.operator)?b.value:null}});if(o.some(b=>ne(b.operator)&&!b.value?.trim())){w("Fill every filter value, or switch it to is set / is empty.");return}V({title:j,displayType:"list",tagNames:m,mode:h,propertyFilters:o,sortBy:K,sortOrder:Q,limit:Number($)})},children:[e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-section-title",size:"md",children:"View name"}),e.jsx(ie,{id:"view-section-title",value:j,onChange:a=>O(a.target.value),placeholder:"Doing notes",autoFocus:!0})]}),e.jsxs("section",{className:"flex flex-col gap-3 rounded-[20px] border border-border-subtle bg-subtle/40 p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx(A,{size:"md",children:"Filters"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Use properties for structured fields, and tags for loose topics or context."})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(k,{type:"button",variant:"subtle",size:"sm",onClick:R,children:"Add property filter"}),!P&&e.jsx(k,{type:"button",variant:"subtle",size:"sm",onClick:E,children:"Add tag filter"})]})]}),y.length===0&&!P?e.jsxs("div",{className:"rounded-[16px] border border-dashed border-border-subtle bg-elevated/60 px-4 py-3",children:[e.jsx(c,{as:"p",variant:"label",tone:"default",children:s?"All notes":"No filters"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Add a property filter, a tag filter, or leave this view open to all notes."})]}):null,y.length>0?e.jsx("div",{className:"flex flex-col gap-2.5",children:y.map(a=>{const m=_.get(a.key),z=Ne(m);return e.jsxs("div",{className:"grid gap-2 rounded-[16px] border border-border-subtle bg-elevated p-3 md:grid-cols-[minmax(0,1fr)_150px_minmax(0,1fr)_auto] md:items-center",children:[e.jsxs(q,{value:a.key||re,onValueChange:o=>{o!==re&&S(a.id,{key:o})},children:[e.jsx(v,{value:re,disabled:!0,children:"Choose property"}),x.map(o=>e.jsx(v,{value:o.key,children:o.name},o.key))]}),e.jsx(q,{value:a.operator,disabled:!m,onValueChange:o=>S(a.id,{operator:o}),children:z.map(o=>e.jsx(v,{value:o,children:at(o)},o))}),ne(a.operator)&&m?m.valueType==="select"?e.jsx(q,{value:a.value,onValueChange:o=>S(a.id,{value:o}),children:m.options.map(o=>e.jsx(v,{value:o.value,children:o.label},o.value))}):m.valueType==="boolean"?e.jsxs(q,{value:a.value||"true",onValueChange:o=>S(a.id,{value:o}),children:[e.jsx(v,{value:"true",children:"True"}),e.jsx(v,{value:"false",children:"False"})]}):e.jsx(ie,{type:m.valueType==="date"?"date":m.valueType==="number"?"number":m.valueType==="url"?"url":"text",value:a.value,onChange:o=>S(a.id,{value:o.target.value}),placeholder:m.valueType==="url"?"https://example.com":m.valueType==="text"?"Value":void 0}):e.jsx(c,{as:"span",variant:"label",tone:"tertiary",children:m?"No value needed":"Choose a property first"}),e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:()=>ze(a.id),children:"Remove"})]},a.id)})}):null,P?e.jsxs("div",{className:"flex flex-col gap-3 rounded-[16px] border border-border-subtle bg-elevated p-3",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx(c,{as:"p",variant:"label",tone:"default",children:"Tag filter"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Match notes by selected tags."})]}),e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:T,children:"Remove"})]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-section-tags",size:"sm",children:"Tag names"}),e.jsx(Ie,{id:"view-section-tags",value:N,onChange:a=>{l(a.target.value),w("")},placeholder:"@OceanBrain, @todo",size:"sm"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",children:"You can use tags only, properties only, both together, or no filters."})]}),F.length>1?e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{size:"sm",children:"When multiple tags are selected"}),e.jsxs(qe,{type:"single",value:h,onValueChange:a=>{(a==="and"||a==="or")&&M(a)},variant:"quiet",size:"sm",className:"self-start",children:[e.jsx(oe,{value:"and","aria-label":he("and"),children:"Match all"}),e.jsx(oe,{value:"or","aria-label":he("or"),children:"Match any"})]})]}):null,e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(A,{size:"sm",children:"Existing tags"}),e.jsx(c,{as:"span",variant:"meta",tone:"tertiary",children:p?"Loading...":`${u.length} available`})]}),u.length>0?e.jsx("div",{className:"max-h-44 overflow-y-auto rounded-[16px] border border-border-subtle bg-hover-subtle/60 p-3",children:e.jsx("div",{className:"flex flex-wrap gap-2",children:u.map(a=>{const m=F.includes(a.name);return e.jsx("button",{type:"button",className:`inline-flex items-center rounded-full border px-3 py-1.5 text-sm font-medium transition-colors ${m?"border-border-secondary bg-elevated text-fg-default":"border-border-subtle bg-transparent text-fg-secondary hover:border-border-secondary hover:bg-elevated hover:text-fg-default"}`,onClick:()=>d(a.name),children:a.name},a.id)})})}):e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",children:"No tags yet. You can still type tag names manually."})]}):null,e.jsx(c,{as:"p",variant:"meta",tone:U?"default":"tertiary",className:U?"text-fg-error":void 0,children:U||(g||p?"Loading filter options...":`${x.length} properties · ${u.length} tags available`)})]}),e.jsxs("details",{className:"group rounded-[18px] border border-border-subtle bg-elevated px-4 py-3",children:[e.jsx("summary",{className:"cursor-pointer list-none",children:e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx(c,{as:"span",variant:"label",tone:"default",children:"Sort and limit"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Defaults to recently updated notes."})]}),e.jsxs(c,{as:"span",variant:"meta",tone:"tertiary",children:[$," notes"]})]})}),e.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-3",children:[e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-section-sort-by",size:"sm",children:"Sort by"}),e.jsxs(q,{value:K,onValueChange:a=>Z(a),children:[e.jsx(v,{value:"updatedAt",children:"Updated time"}),e.jsx(v,{value:"createdAt",children:"Created time"}),e.jsx(v,{value:"title",children:"Title"})]})]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-section-sort-order",size:"sm",children:"Order"}),e.jsxs(q,{value:Q,onValueChange:a=>Y(a),children:[e.jsx(v,{value:"desc",children:"Descending"}),e.jsx(v,{value:"asc",children:"Ascending"})]})]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-section-limit",size:"sm",children:"Max notes"}),e.jsxs(q,{value:$,onValueChange:C,children:[e.jsx(v,{value:"3",children:"3 notes"}),e.jsx(v,{value:"5",children:"5 notes"}),e.jsx(v,{value:"8",children:"8 notes"}),e.jsx(v,{value:"10",children:"10 notes"}),e.jsx(v,{value:"12",children:"12 notes"})]})]})]})]})]})}),e.jsx(L.Footer,{children:e.jsxs(Ce,{children:[e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:f,children:"Cancel"}),e.jsx(k,{type:"submit",size:"sm",form:"view-section-form",children:i==="create"?"Create view":"Save view"})]})})]})}function Tt({open:t,mode:i,initialTitle:n="",onClose:u,onSubmit:x}){const[p,g]=r.useState(n);return r.useEffect(()=>{t&&g(n)},[n,t]),e.jsxs(L,{isOpen:t,onClose:u,variant:"form",className:"sm:max-w-[480px]",children:[e.jsx(L.Header,{title:i==="create"?"Create view tab":"Rename view tab",onClose:u}),e.jsx(L.Body,{children:e.jsxs("form",{id:"view-tab-form",className:"flex flex-col gap-4",onSubmit:f=>{f.preventDefault(),x(p)},children:[e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(A,{htmlFor:"view-tab-title",size:"md",children:"Tab name"}),e.jsx(ie,{id:"view-tab-title",value:p,onChange:f=>g(f.target.value),placeholder:"Now",autoFocus:!0})]}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",children:"Each tab is one saved view inside the Views page."})]})}),e.jsx(L.Footer,{children:e.jsxs(Ce,{children:[e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:u,children:"Cancel"}),e.jsx(k,{type:"submit",size:"sm",form:"view-tab-form",children:i==="create"?"Create tab":"Save tab"})]})})]})}const St="Save reusable note queries with tags, shared properties, and sorting.",Ct="focus-ring-soft inline-flex h-8 w-8 items-center justify-center rounded-[10px] text-fg-default/70 outline-none transition-colors hover:bg-hover-subtle hover:text-fg-default touch-none",Vt="group relative -mb-px flex h-10 min-w-[92px] max-w-[118px] shrink-0 items-center gap-0.5 rounded-t-[12px] border border-b-0 px-1.5 transition-[background-color,border-color,color,box-shadow]",Ft="focus-ring-soft inline-flex min-w-0 flex-1 items-center gap-1 rounded-[9px] px-0.5 py-1.5 text-[13px] font-medium outline-none",Et="focus-ring-soft inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-[8px] text-current/55 outline-none transition-[background-color,color,opacity] hover:bg-hover-subtle hover:text-current touch-none",Dt="focus-ring-soft relative mb-0.5 inline-flex h-9 shrink-0 items-center gap-1 rounded-[10px] px-2.5 text-[13px] font-medium text-fg-secondary outline-none transition-colors hover:bg-hover-subtle/85 hover:text-fg-default",At=({tab:t,isActive:i,onSelect:n})=>{const{attributes:u,listeners:x,setNodeRef:p,setActivatorNodeRef:g,transform:f,transition:V,isDragging:j}=Ve({id:t.id});return e.jsxs("div",{ref:p,style:{transform:Ee.Transform.toString(f),transition:V,opacity:j?.6:1},className:J(Vt,i?"z-10 border-border-secondary/75 bg-elevated text-fg-default shadow-[0_10px_18px_-20px_rgba(15,18,24,0.24)]":"border-transparent bg-hover-subtle/45 text-fg-secondary hover:bg-hover-subtle/75 hover:text-fg-default"),children:[e.jsx("button",{type:"button",ref:g,"aria-label":`Reorder view tab ${t.title}`,...u,...x,className:J(Et,j?"cursor-grabbing opacity-100":"cursor-grab opacity-70 group-hover:opacity-100"),children:e.jsx(Fe,{className:"size-4"})}),e.jsxs("button",{type:"button",role:"tab","aria-selected":i,className:J(Ft,i?"text-fg-default":"text-fg-secondary group-hover:text-fg-default"),onClick:n,children:[e.jsx("span",{className:"min-w-0 flex-1 truncate",children:t.title}),e.jsx("span",{className:"inline-flex min-w-4 shrink-0 items-center justify-center rounded-full bg-hover-subtle/75 px-1 py-0 text-[10px] leading-4 text-current/70",children:t.sections.length})]})]})},zt=({section:t,onEdit:i,onDelete:n})=>{const{attributes:u,listeners:x,setNodeRef:p,setActivatorNodeRef:g,transform:f,transition:V,isDragging:j}=Ve({id:t.id});return e.jsx("div",{ref:p,style:{transform:Ee.Transform.toString(f),transition:V,opacity:j?.6:1},children:e.jsx(wt,{section:t,onEdit:i,onDelete:n,dragHandle:e.jsx("button",{type:"button",ref:g,"aria-label":`Reorder section ${t.title}`,...u,...x,className:J(Ct,j?"cursor-grabbing":"cursor-grab"),children:e.jsx(Fe,{className:"size-4"})})})})};function _t(){const t=Oe(),i=Je(),n=We(),[u,x]=r.useState(null),[p,g]=r.useState(null),{data:f,isPending:V,isError:j,refetch:O}=G({queryKey:D.views.workspace(),async queryFn(){const s=await rt();if(s.type==="error")throw s;return s.viewWorkspace}}),N=f??it,l=nt(N),{data:h,isPending:M}=G({queryKey:D.tags.list({limit:200}),async queryFn(){const s=await _e({limit:200});if(s.type==="error")throw s;return s.allTags}}),K=Pe(de($e,{activationConstraint:{distance:8}}),de(Ke,{coordinateGetter:He})),Z=h?.tags??[],{data:Q,isPending:Y}=G({queryKey:D.notes.propertyKeys({limit:100}),async queryFn(){const s=await Be({limit:100});if(s.type==="error")throw s;return s.notePropertyKeys}}),$=Q?.keys??[],C=s=>{n.setQueryData(D.views.workspace(),s)},y=async()=>{await n.invalidateQueries({queryKey:D.views.all(),exact:!1})},W=async({active:s,over:d})=>{if(!d||s.id===d.id)return;const E=n.getQueryData(D.views.workspace())??N,T=dt(E,String(s.id),String(d.id));C(T);const R=await ct(T.tabs.map(S=>S.id));if(R.type==="error"){C(E),i(R.errors[0].message);return}await y()},X=async({active:s,over:d})=>{if(!l||!d||s.id===d.id)return;const E=n.getQueryData(D.views.workspace())??N,T=mt(E,l.id,String(s.id),String(d.id));C(T);const R=await ut(l.id,T.tabs.find(S=>S.id===l.id)?.sections.map(S=>S.id)??[]);if(R.type==="error"){C(E),i(R.errors[0].message);return}await y()},B=async s=>{const d=await xt(s);if(d.type==="error"){i(d.errors[0].message);return}await y(),x(null)},U=async s=>{if(!l)return;const d=await pt(l.id,s);if(d.type==="error"){i(d.errors[0].message);return}await y(),x(null)},w=async()=>{if(!l||!await t("Delete this view tab and all of its sections?"))return;const s=await ht(l.id);if(s.type==="error"){i(s.errors[0].message);return}await y()},_=async s=>{if(!l)return;const d=await gt(l.id,s);if(d.type==="error"){i(d.errors[0].message);return}await y(),g(null)},F=async s=>{if(!l||!p||p.mode!=="edit")return;const d=await ft(p.section.id,s);if(d.type==="error"){i(d.errors[0].message);return}await y(),g(null)},P=async s=>{if(!l||!await t("Delete this section from the current view tab?"))return;const d=await bt(s);if(d.type==="error"){i(d.errors[0].message);return}await y()};return e.jsxs(e.Fragment,{children:[e.jsx(Ue,{title:"Views",description:St,children:V&&!f?e.jsx(H,{className:"px-6 py-8 sm:px-8 sm:py-10",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(se,{height:20,width:180,className:"rounded-full"}),e.jsx(se,{height:16,width:260,className:"rounded-full"}),e.jsx(se,{height:44,width:140,className:"rounded-[12px]"})]})}):j?e.jsxs(H,{className:"px-6 py-8 sm:px-8 sm:py-10",children:[e.jsx(c,{as:"p",variant:"body",weight:"semibold",children:"Failed to load saved views"}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:"Retry loading your saved view tabs."}),e.jsx("div",{className:"mt-4",children:e.jsx(k,{type:"button",variant:"ghost",size:"sm",onClick:()=>{O()},children:"Retry"})})]}):N.tabs.length===0?e.jsxs(H,{className:"px-6 py-8 sm:px-8 sm:py-10",children:[e.jsx(ce,{title:"Create your first view tab",description:"Start with a saved view tab, then add sections that query notes by tags, properties, or both."}),e.jsx("div",{className:"mt-6 flex justify-center",children:e.jsxs(k,{type:"button",onClick:()=>x({mode:"create"}),children:[e.jsx(ae,{className:"h-4 w-4"}),"Create first tab"]})})]}):e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx("div",{className:"border-b border-border-secondary/75",children:e.jsx(me,{sensors:K,collisionDetection:ue,modifiers:[Ze],onDragEnd:W,children:e.jsxs("div",{className:"flex items-end gap-1 overflow-x-auto overflow-y-hidden pb-px",children:[e.jsx(xe,{items:N.tabs.map(s=>s.id),strategy:Qe,children:e.jsx("div",{role:"tablist","aria-label":"Views tab list",className:"flex min-w-0 items-end gap-1",children:N.tabs.map(s=>e.jsx(At,{tab:s,isActive:s.id===l?.id,onSelect:async()=>{const d=n.getQueryData(D.views.workspace())??N,E=lt(d,s.id);C(E);const T=await ot(s.id);if(T.type==="error"){C(d),i(T.errors[0].message);return}C(T.setActiveViewTab)}},s.id))})}),e.jsxs("button",{type:"button",className:Dt,onClick:()=>x({mode:"create"}),children:[e.jsx(ae,{className:"size-4"}),"Add tab"]})]})})}),l&&e.jsxs("div",{className:"flex flex-col gap-5",children:[e.jsxs(H,{className:"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{children:[e.jsx(c,{as:"h2",variant:"heading",weight:"bold",tracking:"tight",children:l.title}),e.jsx(c,{as:"p",variant:"meta",tone:"tertiary",className:"mt-1",children:l.sections.length>0?`${l.sections.length} section${l.sections.length===1?"":"s"} in this view`:"Add sections to build this view"})]}),e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsxs(k,{type:"button",size:"sm",onClick:()=>g({mode:"create"}),children:[e.jsx(ae,{className:"h-4 w-4"}),"Add section"]}),e.jsx(Te,{button:e.jsx(Se,{label:"View tab actions"}),items:[{name:"Rename",onClick:()=>x({mode:"edit",tab:l})},{type:"separator"},{name:"Delete tab",onClick:()=>{w()}}]})]})]}),l.sections.length===0?e.jsx(H,{className:"px-6 py-8 sm:px-8 sm:py-10",children:e.jsx(ce,{title:"Add the first section to this tab",description:"Sections can pull notes by tags, properties, or both."})}):e.jsx("div",{className:"flex flex-col",children:e.jsx(me,{sensors:K,collisionDetection:ue,modifiers:[Ye],onDragEnd:X,children:e.jsx(xe,{items:l.sections.map(s=>s.id),strategy:Ge,children:e.jsx("div",{className:"flex flex-col gap-4",children:l.sections.map(s=>e.jsx(zt,{section:s,onEdit:()=>g({mode:"edit",section:s}),onDelete:()=>{P(s.id)}},s.id))})})})})]})]})}),e.jsx(Tt,{open:u!==null,mode:u?.mode??"create",initialTitle:u?.mode==="edit"?u.tab.title:"",onClose:()=>x(null),onSubmit:s=>{if(u?.mode==="edit"){U(s);return}B(s)}}),e.jsx(kt,{open:p!==null,mode:p?.mode??"create",initialSection:p?.mode==="edit"?p.section:null,availableTags:Z,availableProperties:$,isTagsLoading:M,isPropertiesLoading:Y,onClose:()=>g(null),onSubmit:s=>{if(p?.mode==="edit"){F(s);return}_(s)}})]})}export{_t as default};
@@ -1 +0,0 @@
1
- import{j as e}from"./note-vendor-uuJO2MTD.js";import{a0 as M,j as Q,aw as F,w as L,v as _,a6 as I,aT as K,q as i,ah as E,aU as B,N as O,aV as W,P as N,G,T as d,ax as H,B as j,a1 as U,aW as V,i as l,X as Y,d as $,ak as z,u as X,aX as Z,M as y}from"./index-nYj7BL3a.js";import{a as k}from"./graph-vendor-CUxe67Lr.js";import{S as C}from"./SurfaceCard-FhlC8VSR.js";import"./note-core-DMZcZ4yV.js";const m=25,v=Q(F),S=30,R=`Deleted notes stay here for ${S} days before permanent removal`,g={title:"Permanently delete note?",description:"This note is referenced by the notes below. If you permanently delete it, those links will stay broken. Other notes will not be edited automatically.",confirmLabel:"Delete now",confirmVariant:"danger"},P=a=>$(a).format("YYYY-MM-DD HH:mm"),J=({note:a,onClose:o})=>{const s=a?.id??"",c=a?.title||"Untitled note",r=X({queryKey:i.notes.trashDetail(s),enabled:!!a,queryFn:async()=>{const h=await Z(s);if(h.type==="error")throw h;if(!h.trashedNote)throw new Error("Trashed note not found");return h.trashedNote}}),f=r.data?.contentAsMarkdown.trim()??"";return e.jsxs(y,{isOpen:!!a,onClose:o,variant:"inspect",children:[e.jsx(y.Header,{title:c,onClose:o}),e.jsx(y.Body,{children:e.jsxs("div",{className:"flex flex-col gap-3",children:[a&&e.jsxs(d,{as:"p",variant:"meta",tone:"secondary",children:["Deleted ",P(a.deletedAt)]}),r.isLoading&&e.jsx(d,{as:"p",variant:"meta",tone:"secondary",children:"Loading deleted note content..."}),r.isError&&e.jsx(d,{as:"p",variant:"meta",tone:"error",children:"Failed to load deleted note content."}),!r.isLoading&&!r.isError&&f&&e.jsx("pre",{className:"max-h-[60vh] overflow-auto whitespace-pre-wrap break-words rounded-[14px] border border-border-subtle bg-hover-subtle/50 px-4 py-3 text-sm leading-6 text-fg-secondary",children:f}),!r.isLoading&&!r.isError&&!f&&e.jsx(d,{as:"p",variant:"meta",tone:"secondary",className:"rounded-[14px] border border-border-subtle bg-hover-subtle/50 px-4 py-3",children:"No readable content was found for this deleted note."})]})}),e.jsx(y.Footer,{children:e.jsx(j,{variant:"ghost",size:"sm",onClick:o,children:"Close"})})]})},ee=()=>e.jsx(N,{title:"Trash",variant:"default",heading:e.jsx(l,{width:118,height:24,className:"rounded-full"}),description:e.jsx(l,{width:352,height:16,className:"rounded-full"}),children:e.jsx("div",{className:"grid gap-3",children:Array.from({length:3},(a,o)=>e.jsx(C,{padding:"compact",children:e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{className:"min-w-0 flex-1 space-y-2",children:[e.jsx(l,{width:"40%",height:18,className:"rounded-full"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(l,{width:168,height:14,className:"rounded-full"}),e.jsx(l,{width:176,height:14,className:"rounded-full"})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(l,{width:56,height:24,className:"rounded-full"}),e.jsx(l,{width:72,height:24,className:"rounded-full"})]})]}),e.jsx(l,{width:92,height:32,className:"rounded-[12px]"})]})},o))})}),te=()=>{const{page:a}=v.useSearch(),o=v.useNavigate(),s=L(),c=Y(),r=_(),[f,h]=k.useState(null),[x,b]=k.useState(null),{data:u}=I({queryKey:i.notes.trash({limit:m,offset:(a-1)*m}),queryFn:async()=>{const t=await K({limit:m,offset:(a-1)*m});if(t.type==="error")throw t;return t.trashedNotes}}),w=E({mutationFn:B,onSuccess:async t=>{if(t.type==="error")throw t;await Promise.all([s.invalidateQueries({queryKey:i.notes.all(),exact:!1}),s.invalidateQueries({queryKey:i.tags.all(),exact:!1}),s.invalidateQueries({queryKey:i.reminders.all(),exact:!1}),s.invalidateQueries({queryKey:i.images.all(),exact:!1}),s.invalidateQueries({queryKey:i.calendar.all(),exact:!1})]),c("The note has been restored."),o({to:O,params:{id:t.restoreTrashedNote.id}})},onError:()=>{c("Failed to restore the note.")}}),p=E({mutationFn:W,onSuccess:async t=>{if(t.type==="error")throw t;await s.invalidateQueries({queryKey:i.notes.trashAll(),exact:!1}),c("The note has been permanently deleted.")},onError:()=>{c("Failed to permanently delete the note.")}}),D=()=>{if(!x)return;const{id:t}=x;b(null),p.mutate(t)},q=async t=>{const n=await z(t);if(n.type==="error"){c("Failed to check linked notes before permanently deleting this note.");return}if(s.setQueryData(i.notes.backReferences(t),n.backReferences),n.backReferences.length>0){b({id:t,backReferences:n.backReferences});return}await r("Permanently delete this note? This cannot be undone.")&&p.mutate(t)},T=u.totalCount>0?`Trash (${u.totalCount})`:void 0,A=u.notes.find(t=>t.id===f)??null;return u.notes.length===0?e.jsx(N,{title:"Trash",variant:"default",heading:T,description:R,children:e.jsx(G,{title:"Trash is empty",description:`Delete a note and you can restore it here for ${S} days before permanent removal`})}):e.jsxs(N,{title:"Trash",variant:"default",heading:T,description:R,children:[e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("div",{className:"grid gap-3",children:u.notes.map(t=>e.jsx(C,{padding:"compact",children:e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex min-w-0 items-start gap-1.5",children:[e.jsx(d,{as:"h2",variant:"body",weight:"medium",className:"min-w-0 flex-1 break-words leading-[1.25]",children:t.title||"Untitled note"}),t.pinned&&e.jsx("span",{title:"Pinned",className:"inline-flex h-5 w-5 shrink-0 items-center justify-center text-fg-tertiary",children:e.jsx(H,{className:"h-3.5 w-3.5"})})]}),e.jsx("div",{className:"mt-1 flex flex-wrap items-center gap-x-3 gap-y-1",children:e.jsxs(d,{as:"div",variant:"meta",weight:"medium",tone:"secondary",children:["Deleted ",P(t.deletedAt)]})}),t.tagNames.length>0&&e.jsx("div",{className:"mt-2 flex flex-wrap gap-1.5",children:t.tagNames.map(n=>e.jsx(d,{as:"span",variant:"label",weight:"medium",tone:"tertiary",className:"rounded-full border border-border-subtle bg-hover-subtle px-2 py-0.5",children:n},`${t.id}-${n}`))}),t.contentPreview&&e.jsx("div",{className:"mt-3 rounded-[14px] border border-border-subtle bg-hover-subtle/50 px-3 py-2",children:e.jsx(d,{as:"p",variant:"meta",tone:"secondary",className:"line-clamp-3 whitespace-pre-wrap break-words",children:t.contentPreview})})]}),e.jsxs("div",{className:"flex shrink-0 flex-wrap gap-2 sm:justify-end",children:[e.jsx(j,{variant:"subtle",size:"sm",onClick:()=>h(t.id),children:"View content"}),e.jsx(j,{variant:"subtle",size:"sm",isLoading:w.isPending&&w.variables===t.id,onClick:()=>w.mutate(t.id),children:"Restore"}),e.jsx(j,{variant:"soft-danger",size:"sm",isLoading:p.isPending&&p.variables===t.id,onClick:()=>q(t.id),children:"Delete now"})]})]})},t.id))}),u.totalCount>m&&e.jsx(U,{page:a,last:Math.ceil(u.totalCount/m),onChange:t=>{o({search:n=>({...n,page:t})})}})]}),e.jsx(J,{note:A,onClose:()=>h(null)}),e.jsx(V,{isOpen:!!x,title:g.title,description:g.description,references:x?.backReferences??[],confirmLabel:g.confirmLabel,confirmVariant:g.confirmVariant,onClose:()=>b(null),onConfirm:D})]})},oe=()=>{const{page:a}=v.useSearch();return e.jsx(M,{fallback:e.jsx(ee,{}),errorTitle:"Failed to load trash",errorDescription:"Retry loading deleted notes",resetKeys:[a],children:e.jsx(te,{})})};export{oe as default};