@vertesia/ui 0.65.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/lib/esm/core/components/EmptyCollection.js +2 -2
  2. package/lib/esm/core/components/EmptyCollection.js.map +1 -1
  3. package/lib/esm/core/components/InputList.js +2 -2
  4. package/lib/esm/core/components/InputList.js.map +1 -1
  5. package/lib/esm/core/components/SidePanel.js +1 -1
  6. package/lib/esm/core/components/SidePanel.js.map +1 -1
  7. package/lib/esm/core/components/Switch.js +2 -2
  8. package/lib/esm/core/components/Switch.js.map +1 -1
  9. package/lib/esm/core/components/shadcn/calendar.js +0 -1
  10. package/lib/esm/core/components/shadcn/calendar.js.map +1 -1
  11. package/lib/esm/core/components/shadcn/checkbox.js +0 -1
  12. package/lib/esm/core/components/shadcn/checkbox.js.map +1 -1
  13. package/lib/esm/core/components/shadcn/command.js +0 -1
  14. package/lib/esm/core/components/shadcn/command.js.map +1 -1
  15. package/lib/esm/core/components/shadcn/dialog.js +0 -1
  16. package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
  17. package/lib/esm/core/components/shadcn/filters/comboBox.js +18 -0
  18. package/lib/esm/core/components/shadcn/filters/comboBox.js.map +1 -1
  19. package/lib/esm/core/components/shadcn/filters/filterBar.js +38 -17
  20. package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
  21. package/lib/esm/core/components/shadcn/filters/filters.js +11 -5
  22. package/lib/esm/core/components/shadcn/filters/filters.js.map +1 -1
  23. package/lib/esm/core/components/shadcn/filters/selectFilter.js +1 -1
  24. package/lib/esm/core/components/shadcn/filters/selectFilter.js.map +1 -1
  25. package/lib/esm/core/components/shadcn/filters/stringListFilter.js +24 -0
  26. package/lib/esm/core/components/shadcn/filters/stringListFilter.js.map +1 -0
  27. package/lib/esm/core/components/shadcn/filters/textFilter.js +2 -1
  28. package/lib/esm/core/components/shadcn/filters/textFilter.js.map +1 -1
  29. package/lib/esm/core/components/shadcn/label.js +0 -1
  30. package/lib/esm/core/components/shadcn/label.js.map +1 -1
  31. package/lib/esm/features/agent/PayloadBuilder.js +27 -0
  32. package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
  33. package/lib/esm/features/agent/chat/ModernAgentConversation.js +1 -1
  34. package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
  35. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -3
  36. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  37. package/lib/esm/features/facets/VEnvironmentFacet.js +24 -0
  38. package/lib/esm/features/facets/VEnvironmentFacet.js.map +1 -0
  39. package/lib/esm/features/facets/VFacetsNav.js +69 -26
  40. package/lib/esm/features/facets/VFacetsNav.js.map +1 -1
  41. package/lib/esm/features/facets/VInteractionFacet.js +45 -0
  42. package/lib/esm/features/facets/VInteractionFacet.js.map +1 -0
  43. package/lib/esm/features/facets/VStringFacet.js +6 -5
  44. package/lib/esm/features/facets/VStringFacet.js.map +1 -1
  45. package/lib/esm/features/facets/VUserFacet.js +6 -6
  46. package/lib/esm/features/facets/VUserFacet.js.map +1 -1
  47. package/lib/esm/features/layout/GenericPageNavHeader.js +1 -1
  48. package/lib/esm/features/magic-pdf/TextPageView.js +1 -2
  49. package/lib/esm/features/magic-pdf/TextPageView.js.map +1 -1
  50. package/lib/esm/features/store/collections/CollectionsTable.js +9 -5
  51. package/lib/esm/features/store/collections/CollectionsTable.js.map +1 -1
  52. package/lib/esm/features/store/collections/{CollectionsView.js → CreateCollection.js} +6 -14
  53. package/lib/esm/features/store/collections/CreateCollection.js.map +1 -0
  54. package/lib/esm/features/store/collections/EditCollectionView.js +1 -1
  55. package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
  56. package/lib/esm/features/store/collections/SelectCollection.js +24 -0
  57. package/lib/esm/features/store/collections/SelectCollection.js.map +1 -0
  58. package/lib/esm/features/store/collections/index.js +2 -2
  59. package/lib/esm/features/store/collections/index.js.map +1 -1
  60. package/lib/esm/features/store/objects/DocumentSearchResults.js +6 -3
  61. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  62. package/lib/esm/features/store/objects/components/ContentOverview.js +17 -16
  63. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  64. package/lib/esm/features/store/objects/components/DocumentIcon.js +7 -10
  65. package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
  66. package/lib/esm/features/store/objects/components/DocumentInput.js +1 -2
  67. package/lib/esm/features/store/objects/components/DocumentInput.js.map +1 -1
  68. package/lib/esm/features/store/objects/components/PropertiesEditorModal.js +4 -2
  69. package/lib/esm/features/store/objects/components/PropertiesEditorModal.js.map +1 -1
  70. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +1 -2
  71. package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
  72. package/lib/esm/features/store/objects/components/SelectDocument.js +9 -3
  73. package/lib/esm/features/store/objects/components/SelectDocument.js.map +1 -1
  74. package/lib/esm/features/store/objects/components/SelectDocumentModal.js +2 -2
  75. package/lib/esm/features/store/objects/components/SelectDocumentModal.js.map +1 -1
  76. package/lib/esm/features/store/objects/layout/documentLayout.js +2 -2
  77. package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
  78. package/lib/esm/features/store/objects/search/DocumentSearchContext.js +4 -2
  79. package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  80. package/lib/esm/features/store/objects/selection/SelectionActions.js +1 -1
  81. package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
  82. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +7 -10
  83. package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
  84. package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js +1 -1
  85. package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js.map +1 -1
  86. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +2 -2
  87. package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
  88. package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js +1 -1
  89. package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js.map +1 -1
  90. package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js +1 -1
  91. package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js.map +1 -1
  92. package/lib/esm/features/store/types/ContentObjectTypesSearch.js +2 -3
  93. package/lib/esm/features/store/types/ContentObjectTypesSearch.js.map +1 -1
  94. package/lib/esm/features/store/types/ContentObjectTypesTable.js +1 -1
  95. package/lib/esm/features/store/types/ContentObjectTypesTable.js.map +1 -1
  96. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +2 -2
  97. package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
  98. package/lib/esm/features/store/types/ObjectSchemaEditor.js +2 -3
  99. package/lib/esm/features/store/types/ObjectSchemaEditor.js.map +1 -1
  100. package/lib/esm/features/store/types/TableLayoutEditor.js +1 -1
  101. package/lib/esm/features/store/types/TableLayoutEditor.js.map +1 -1
  102. package/lib/esm/features/store/types/index.js +0 -2
  103. package/lib/esm/features/store/types/index.js.map +1 -1
  104. package/lib/esm/features/user/UserInfo.js +1 -2
  105. package/lib/esm/features/user/UserInfo.js.map +1 -1
  106. package/lib/esm/features/utils/rendition.js +22 -2
  107. package/lib/esm/features/utils/rendition.js.map +1 -1
  108. package/lib/esm/layout/FullHeightLayout.js +2 -4
  109. package/lib/esm/layout/FullHeightLayout.js.map +1 -1
  110. package/lib/esm/session/UserSession.js +2 -2
  111. package/lib/esm/session/UserSession.js.map +1 -1
  112. package/lib/esm/session/auth/composable.js +1 -1
  113. package/lib/esm/session/auth/composable.js.map +1 -1
  114. package/lib/esm/session/constants.js +3 -0
  115. package/lib/esm/session/constants.js.map +1 -0
  116. package/lib/esm/widgets/codemirror/CodeMirrorEditor.js +2 -2
  117. package/lib/esm/widgets/codemirror/CodeMirrorEditor.js.map +1 -1
  118. package/lib/esm/widgets/properties/PropertiesView.js +4 -2
  119. package/lib/esm/widgets/properties/PropertiesView.js.map +1 -1
  120. package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js +1 -1
  121. package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js.map +1 -1
  122. package/lib/tsconfig.tsbuildinfo +1 -1
  123. package/lib/types/core/components/InputList.d.ts +2 -1
  124. package/lib/types/core/components/Switch.d.ts +2 -1
  125. package/lib/types/core/components/shadcn/filters/comboBox.d.ts +5 -0
  126. package/lib/types/core/components/shadcn/filters/stringListFilter.d.ts +10 -0
  127. package/lib/types/core/components/shadcn/filters/types.d.ts +3 -3
  128. package/lib/types/features/agent/PayloadBuilder.d.ts +8 -1
  129. package/lib/types/features/facets/VEnvironmentFacet.d.ts +11 -0
  130. package/lib/types/features/facets/VFacetsNav.d.ts +9 -1
  131. package/lib/types/features/facets/VInteractionFacet.d.ts +14 -0
  132. package/lib/types/features/facets/VStringFacet.d.ts +3 -2
  133. package/lib/types/features/facets/VUserFacet.d.ts +3 -2
  134. package/lib/types/features/store/collections/{CollectionsView.d.ts → CreateCollection.d.ts} +5 -3
  135. package/lib/types/features/store/collections/SelectCollection.d.ts +14 -0
  136. package/lib/types/features/store/collections/index.d.ts +2 -2
  137. package/lib/types/features/store/objects/components/ContentOverview.d.ts +2 -1
  138. package/lib/types/features/store/objects/components/DocumentIcon.d.ts +2 -1
  139. package/lib/types/features/store/objects/components/PropertiesEditorModal.d.ts +2 -1
  140. package/lib/types/features/store/objects/layout/documentLayout.d.ts +1 -1
  141. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +3 -2
  142. package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +2 -1
  143. package/lib/types/features/store/objects/selection/actions/RemoveFromCollectionAction.d.ts +2 -1
  144. package/lib/types/features/store/types/index.d.ts +0 -2
  145. package/lib/types/features/utils/rendition.d.ts +1 -1
  146. package/lib/types/session/UserSession.d.ts +2 -2
  147. package/lib/types/session/constants.d.ts +2 -0
  148. package/lib/vertesia-ui-core.js +1 -1
  149. package/lib/vertesia-ui-core.js.map +1 -1
  150. package/lib/vertesia-ui-features.js +1 -1
  151. package/lib/vertesia-ui-features.js.map +1 -1
  152. package/lib/vertesia-ui-layout.js +1 -1
  153. package/lib/vertesia-ui-layout.js.map +1 -1
  154. package/lib/vertesia-ui-session.js +1 -1
  155. package/lib/vertesia-ui-session.js.map +1 -1
  156. package/lib/vertesia-ui-widgets.js +1 -1
  157. package/lib/vertesia-ui-widgets.js.map +1 -1
  158. package/package.json +4 -4
  159. package/src/core/components/EmptyCollection.tsx +26 -24
  160. package/src/core/components/InputList.tsx +3 -1
  161. package/src/core/components/SidePanel.tsx +2 -2
  162. package/src/core/components/Switch.tsx +4 -3
  163. package/src/core/components/shadcn/calendar.tsx +0 -2
  164. package/src/core/components/shadcn/checkbox.tsx +0 -2
  165. package/src/core/components/shadcn/command.tsx +0 -2
  166. package/src/core/components/shadcn/dialog.tsx +0 -2
  167. package/src/core/components/shadcn/filters/comboBox.tsx +73 -0
  168. package/src/core/components/shadcn/filters/filterBar.tsx +41 -17
  169. package/src/core/components/shadcn/filters/filters.tsx +30 -14
  170. package/src/core/components/shadcn/filters/selectFilter.tsx +3 -3
  171. package/src/core/components/shadcn/filters/stringListFilter.tsx +58 -0
  172. package/src/core/components/shadcn/filters/textFilter.tsx +2 -1
  173. package/src/core/components/shadcn/filters/types.ts +3 -3
  174. package/src/core/components/shadcn/label.tsx +0 -2
  175. package/src/features/agent/PayloadBuilder.tsx +34 -1
  176. package/src/features/agent/chat/ModernAgentConversation.tsx +639 -639
  177. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +12 -13
  178. package/src/features/facets/VEnvironmentFacet.tsx +42 -0
  179. package/src/features/facets/VFacetsNav.tsx +87 -29
  180. package/src/features/facets/VInteractionFacet.tsx +73 -0
  181. package/src/features/facets/VStringFacet.tsx +7 -6
  182. package/src/features/facets/VUserFacet.tsx +7 -6
  183. package/src/features/layout/GenericPageNavHeader.tsx +1 -1
  184. package/src/features/magic-pdf/TextPageView.tsx +1 -2
  185. package/src/features/store/collections/CollectionsTable.tsx +49 -40
  186. package/src/features/store/collections/{CollectionsView.tsx → CreateCollection.tsx} +15 -42
  187. package/src/features/store/collections/EditCollectionView.tsx +1 -1
  188. package/src/features/store/collections/SelectCollection.tsx +46 -0
  189. package/src/features/store/collections/index.ts +2 -2
  190. package/src/features/store/objects/DocumentSearchResults.tsx +6 -3
  191. package/src/features/store/objects/components/ContentOverview.tsx +38 -98
  192. package/src/features/store/objects/components/DocumentIcon.tsx +27 -14
  193. package/src/features/store/objects/components/DocumentInput.tsx +1 -2
  194. package/src/features/store/objects/components/PropertiesEditorModal.tsx +7 -3
  195. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +2 -2
  196. package/src/features/store/objects/components/SelectDocument.tsx +18 -3
  197. package/src/features/store/objects/components/SelectDocumentModal.tsx +6 -6
  198. package/src/features/store/objects/layout/documentLayout.tsx +2 -2
  199. package/src/features/store/objects/search/DocumentSearchContext.ts +6 -3
  200. package/src/features/store/objects/selection/ObjectsActionContext.tsx +1 -1
  201. package/src/features/store/objects/selection/SelectionActions.tsx +0 -1
  202. package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +10 -21
  203. package/src/features/store/objects/selection/actions/ChangeTypeAction.tsx +1 -1
  204. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +2 -2
  205. package/src/features/store/objects/selection/actions/ExportPropertiesAction.tsx +1 -1
  206. package/src/features/store/objects/selection/actions/RemoveFromCollectionAction.tsx +1 -1
  207. package/src/features/store/types/ContentObjectTypesSearch.tsx +3 -4
  208. package/src/features/store/types/ContentObjectTypesTable.tsx +3 -1
  209. package/src/features/store/types/CreateOrUpdateTypeModal.tsx +2 -9
  210. package/src/features/store/types/ObjectSchemaEditor.tsx +4 -5
  211. package/src/features/store/types/TableLayoutEditor.tsx +4 -4
  212. package/src/features/store/types/index.ts +0 -2
  213. package/src/features/user/UserInfo.tsx +1 -2
  214. package/src/features/utils/rendition.ts +23 -1
  215. package/src/layout/FullHeightLayout.tsx +2 -2
  216. package/src/session/UserSession.ts +2 -2
  217. package/src/session/auth/composable.ts +1 -1
  218. package/src/session/constants.ts +2 -0
  219. package/src/widgets/codemirror/CodeMirrorEditor.tsx +2 -2
  220. package/src/widgets/properties/PropertiesView.tsx +10 -2
  221. package/src/widgets/schema-editor/editor/SchemaEditor.tsx +1 -1
  222. package/lib/esm/features/store/collections/CollectionView.js +0 -53
  223. package/lib/esm/features/store/collections/CollectionView.js.map +0 -1
  224. package/lib/esm/features/store/collections/CollectionsView.js.map +0 -1
  225. package/lib/esm/features/store/types/ContentObjectTypeView.js +0 -158
  226. package/lib/esm/features/store/types/ContentObjectTypeView.js.map +0 -1
  227. package/lib/esm/features/store/types/ContentObjectTypesView.js +0 -55
  228. package/lib/esm/features/store/types/ContentObjectTypesView.js.map +0 -1
  229. package/lib/types/features/store/collections/CollectionView.d.ts +0 -5
  230. package/lib/types/features/store/types/ContentObjectTypeView.d.ts +0 -5
  231. package/lib/types/features/store/types/ContentObjectTypesView.d.ts +0 -8
  232. package/src/features/store/collections/CollectionView.tsx +0 -94
  233. package/src/features/store/types/ContentObjectTypeView.tsx +0 -244
  234. package/src/features/store/types/ContentObjectTypesView.tsx +0 -71
@@ -1,5 +1,5 @@
1
1
  import { AgentMessage, AgentMessageType } from "@vertesia/common";
2
- import { Button, useToast } from "@vertesia/ui/core";
2
+ import { Badge, Button, useToast } from "@vertesia/ui/core";
3
3
  import { NavLink } from "@vertesia/ui/router";
4
4
  import { useUserSession } from "@vertesia/ui/session";
5
5
  import dayjs from "dayjs";
@@ -254,7 +254,7 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
254
254
  components={{
255
255
  a: ({ node, ...props }: { node?: any; href?: string; children?: React.ReactNode }) => {
256
256
  const href = props.href || "";
257
- if (href.startsWith("/store/")) {
257
+ if (href.includes("/store/objects")) {
258
258
  return (
259
259
  <NavLink
260
260
  href={href}
@@ -483,28 +483,27 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
483
483
  <div className={showPulsatingCircle ? "animate-fadeIn" : ""}>
484
484
  {getMessageIcon()}
485
485
  </div>
486
- <span className="text-xs font-medium text-gray-700 ">{messageStyles.sender}</span>
486
+ <span className="text-xs font-medium text-muted ">{messageStyles.sender}</span>
487
487
 
488
488
  {/* Show workstream badge next to sender for better organization */}
489
489
  {workstreamId !== "main" && workstreamId !== "all" && (
490
- <span className="bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded-full text-[10px] font-mono text-muted dark:text-gray-400 border border-gray-200 dark:border-gray-700">
490
+ <Badge variant="default" className="text-xs text-muted">
491
491
  {workstreamId}
492
- </span>
492
+ </Badge>
493
493
  )}
494
494
  </div>
495
495
 
496
496
  <div className="flex items-center gap-2">
497
- <span className="text-xs text-gray-400 dark:text-muted">
497
+ <span className="text-xs text-muted">
498
498
  {dayjs(message.timestamp).format("HH:mm:ss")}
499
499
  </span>
500
500
  <Button
501
- variant="ghost"
502
- size="xs"
501
+ variant="ghost" size="xs"
503
502
  onClick={copyToClipboard}
504
- className="text-gray-400 hover:text-muted dark:text-muted dark:hover:text-muted/30"
503
+ className="text-muted"
505
504
  title="Copy message"
506
505
  >
507
- <CopyIcon className="h-3 w-3" />
506
+ <CopyIcon className="size-3" />
508
507
  </Button>
509
508
  </div>
510
509
  </div>
@@ -529,7 +528,7 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
529
528
  <div className="mt-2">
530
529
  <button
531
530
  onClick={() => setShowDetails(!showDetails)}
532
- className="text-xs text-muted hover:text-gray-700 dark:text-gray-400 dark:hover:text-muted/30 flex items-center"
531
+ className="text-xs text-muted flex items-center"
533
532
  >
534
533
  {showDetails ? "Hide" : "Show"} details
535
534
  <svg
@@ -544,11 +543,11 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
544
543
  </button>
545
544
 
546
545
  {showDetails && (
547
- <div className="mt-2 p-2 bg-gray-50 dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded text-sm">
546
+ <div className="mt-2 p-2 bg-muted border border-mixer-muted/40 rounded text-sm">
548
547
  {typeof message.details === "string" ? (
549
548
  renderContent(message.details)
550
549
  ) : (
551
- <pre className="text-xs font-mono whitespace-pre-wrap overflow-x-auto bg-gray-100 dark:bg-gray-800 p-2 rounded text-gray-700 ">
550
+ <pre className="text-xs font-mono whitespace-pre-wrap overflow-x-auto bg-muted p-2 rounded text-muted ">
552
551
  {JSON.stringify(message.details, null, 2)}
553
552
  </pre>
554
553
  )}
@@ -0,0 +1,42 @@
1
+ import { FacetBucket } from '@vertesia/common';
2
+ import { FilterGroup } from '@vertesia/ui/core';
3
+
4
+ interface EnrichedFacetBucket extends FacetBucket {
5
+ name?: string;
6
+ }
7
+
8
+ interface EnvironmentFacetProps {
9
+ buckets: EnrichedFacetBucket[];
10
+ name: string;
11
+ }
12
+
13
+ export function VEnvironmentFacet({ buckets, name }: EnvironmentFacetProps): FilterGroup {
14
+ const options = buckets.map((bucket) => ({
15
+ label: `(${bucket.count})`,
16
+ value: bucket._id
17
+ }));
18
+
19
+ const filterGroup: FilterGroup = {
20
+ name: name.charAt(0).toUpperCase() + name.slice(1),
21
+ options: options,
22
+ type: "select",
23
+ labelRenderer: (environmentId: string) => {
24
+ const bucket = buckets.find(b => b._id === environmentId);
25
+ const displayName = bucket?.name || environmentId;
26
+
27
+ return (
28
+ <div className="w-full flex items-center">
29
+ <span className="text-sm truncate">{displayName}</span>
30
+ <span className="ml-2 text-xs">({bucket?.count || 0})</span>
31
+ </div>
32
+ );
33
+ },
34
+ filterBy: (optionValue: string, searchText: string) => {
35
+ const bucket = buckets.find(b => b._id === optionValue);
36
+ const searchName = bucket?.name || optionValue;
37
+ return searchName.toLowerCase().includes(searchText.toLowerCase());
38
+ }
39
+ };
40
+
41
+ return filterGroup;
42
+ }
@@ -1,13 +1,24 @@
1
1
  import { Filter as BaseFilter, FilterBar, FilterGroup } from '@vertesia/ui/core';
2
2
  import { useUserSession } from '@vertesia/ui/session';
3
3
  import { useState } from 'react';
4
+ import { VEnvironmentFacet } from './VEnvironmentFacet';
5
+ import { VInteractionFacet } from './VInteractionFacet';
4
6
  import { VStringFacet } from './VStringFacet';
5
7
  import { VTypeFacet } from './VTypeFacet';
6
8
  import { VUserFacet } from './VUserFacet';
7
9
 
10
+ export interface SearchInterface {
11
+ getFilterValue(name: string): any;
12
+ setFilterValue(name: string, value: any): void;
13
+ clearFilters(autoSearch?: boolean): void;
14
+ search(): Promise<boolean | undefined>;
15
+ readonly isRunning: boolean;
16
+ query: Record<string, any>;
17
+ }
18
+
8
19
  interface FacetsNavProps {
9
20
  facets: any;
10
- search: any;
21
+ search: SearchInterface;
11
22
  textSearch?: string;
12
23
  }
13
24
  export function VFacetsNav({ facets, search, textSearch = '' }: FacetsNavProps) {
@@ -67,34 +78,77 @@ export function VFacetsNav({ facets, search, textSearch = '' }: FacetsNavProps)
67
78
  customFilterGroups.push(initiatedByFilterGroup);
68
79
  }
69
80
 
70
- if (facets.start) {
71
- customFilterGroups.push({
72
- name: 'start',
73
- placeholder: 'Date after',
74
- type: 'date' as const,
75
- options: []
81
+ /** Run table */
82
+ if (facets.interactions) {
83
+ const interactionFilterGroup = VInteractionFacet({
84
+ buckets: facets.interactions || [],
85
+ name: 'interaction',
86
+ placeholder: 'Interactions',
76
87
  });
88
+ customFilterGroups.push(interactionFilterGroup);
77
89
  }
78
90
 
79
- if (facets.end) {
80
- customFilterGroups.push({
81
- name: 'end',
82
- placeholder: 'Date before',
83
- type: 'date' as const,
84
- options: []
91
+ if (facets.environments) {
92
+ const environmentFilterGroup = VEnvironmentFacet({
93
+ buckets: facets.environments || [],
94
+ name: 'Environments'
95
+ });
96
+ customFilterGroups.push(environmentFilterGroup);
97
+ }
98
+
99
+ if (facets.models) {
100
+ const modelFilterGroup = VStringFacet({
101
+ search,
102
+ buckets: facets.models || [],
103
+ name: 'Model'
85
104
  });
105
+ customFilterGroups.push(modelFilterGroup);
86
106
  }
87
107
 
88
- // if (facets.tags) {
89
- // customFilterGroups.push({
90
- // name: 'Tags',
91
- // type: 'text',
92
- // options: facets.tags.map((tag: string) => ({
93
- // label: tag,
94
- // value: tag
95
- // }))
96
- // });
97
- // }
108
+ if (facets.statuses) {
109
+ const statusFilterGroup = VStringFacet({
110
+ search,
111
+ buckets: facets.statuses || [],
112
+ name: 'Status'
113
+ });
114
+ customFilterGroups.push(statusFilterGroup);
115
+ }
116
+
117
+ if (facets.finish_reason) {
118
+ const processedFinishReason = facets.finish_reason.map((bucket: any) => ({
119
+ ...bucket,
120
+ _id: bucket._id === null ? 'none' : bucket._id
121
+ }));
122
+
123
+ const finishReasonFilterGroup = VStringFacet({
124
+ search,
125
+ buckets: processedFinishReason,
126
+ name: 'finish_reason',
127
+ placeholder: 'Finish Reason'
128
+ });
129
+ customFilterGroups.push(finishReasonFilterGroup);
130
+ }
131
+
132
+ if (facets.created_by) {
133
+ const createdByFilterGroup = VUserFacet({
134
+ buckets: facets.created_by || [],
135
+ name: 'created_by',
136
+ placeholder: 'Created By'
137
+ });
138
+ customFilterGroups.push(createdByFilterGroup);
139
+ }
140
+
141
+ if (facets.tags) {
142
+ customFilterGroups.push({
143
+ name: 'Tags',
144
+ type: 'stringList',
145
+ options: facets.tags.map((tag: string) => ({
146
+ label: tag,
147
+ value: tag
148
+ }))
149
+ });
150
+ }
151
+ /** Run table */
98
152
 
99
153
  const handleFilterChange: React.Dispatch<React.SetStateAction<BaseFilter[]>> = (value) => {
100
154
 
@@ -106,21 +160,25 @@ export function VFacetsNav({ facets, search, textSearch = '' }: FacetsNavProps)
106
160
  }
107
161
  setFilters(newFilters);
108
162
 
163
+ // Reset the actual query before reapplying filters. Otherwise the removed filters remain.
164
+ search.clearFilters(false);
165
+
109
166
  newFilters.forEach(filter => {
110
167
  if (filter.value && filter.value.length > 0) {
111
168
  const filterName = filter.name.toLowerCase();
112
- const filterValue = filter.value[0].value;
169
+ const filterValue = filter.type === 'stringList'
170
+ ? filter.value.map(v => typeof v === 'string' ? v : v.value)
171
+ : Array.isArray(filter.value) && filter.value[0] && typeof filter.value[0] === 'object'
172
+ ? filter.value[0].value
173
+ : filter.value;
113
174
 
114
- // Map filter names to the expected field names
115
175
  switch (filterName) {
116
176
  case 'name':
117
177
  search.query.search_term = filterValue;
118
- break;
119
- case 'user':
120
- search.query.initiated_by = filterValue === 'Unknown User' ? 'unknown' : filterValue;
178
+ search.query.name = filterValue;
121
179
  break;
122
180
  default:
123
- (search.query as any)[filterName] = filterValue;
181
+ search.query[filterName] = filterValue;
124
182
  break;
125
183
  }
126
184
  }
@@ -0,0 +1,73 @@
1
+ import { FacetBucket, InteractionStatus } from '@vertesia/common';
2
+ import { Badge, FilterGroup } from '@vertesia/ui/core';
3
+
4
+ interface EnrichedFacetBucket extends FacetBucket {
5
+ name?: string;
6
+ status?: string;
7
+ version?: number;
8
+ }
9
+
10
+ interface InteractionFacetProps {
11
+ buckets: EnrichedFacetBucket[];
12
+ name: string;
13
+ placeholder?: string;
14
+ }
15
+
16
+ export function VInteractionFacet({ buckets, name, placeholder }: InteractionFacetProps): FilterGroup {
17
+ const options = buckets.map((bucket) => ({
18
+ label: `(${bucket.count})`,
19
+ value: bucket._id
20
+ }));
21
+
22
+ const filterGroup: FilterGroup = {
23
+ name: name,
24
+ placeholder: placeholder || `${name.charAt(0).toUpperCase() + name.slice(1)}`,
25
+ options: options,
26
+ type: "select",
27
+ labelRenderer: (interactionId: string) => {
28
+ const bucket = buckets.find(b => b._id === interactionId);
29
+ const displayName = bucket?.name || interactionId;
30
+
31
+ // Determine badge variant based on status
32
+ let badgeVariant: "success" | "attention" | "destructive" = "success";
33
+ if (bucket?.status) {
34
+ switch (bucket.status) {
35
+ case InteractionStatus.published:
36
+ badgeVariant = "success";
37
+ break;
38
+ case InteractionStatus.archived:
39
+ badgeVariant = "destructive";
40
+ break;
41
+ default:
42
+ badgeVariant = "attention";
43
+ break;
44
+ }
45
+ }
46
+
47
+ const badgeText = bucket?.version && bucket?.status ?
48
+ `v${bucket.version} ${bucket.status}` :
49
+ bucket?.status || (bucket?.version ? `v${bucket.version}` : '');
50
+
51
+ return (
52
+ <div className="w-full flex items-center justify-between">
53
+ <div className="flex flex-row flex-wrap items-center gap-2 min-w-0 flex-1">
54
+ <span className="text-sm truncate">{displayName}</span>
55
+ {badgeText && (
56
+ <Badge variant={badgeVariant} className="text-xs w-fit">
57
+ {badgeText}
58
+ </Badge>
59
+ )}
60
+ </div>
61
+ <span className="ml-2 text-xs shrink-0">({bucket?.count || 0})</span>
62
+ </div>
63
+ );
64
+ },
65
+ filterBy: (optionValue: string, searchText: string) => {
66
+ const bucket = buckets.find(b => b._id === optionValue);
67
+ const searchName = bucket?.name || optionValue;
68
+ return searchName.toLowerCase().includes(searchText.toLowerCase());
69
+ }
70
+ };
71
+
72
+ return filterGroup;
73
+ }
@@ -5,30 +5,31 @@ import { FilterGroup } from '@vertesia/ui/core';
5
5
  interface StringFacetProps {
6
6
  buckets: FacetBucket[];
7
7
  name: string;
8
+ placeholder?: string;
8
9
  }
9
10
 
10
- export function createStringFilterGroup({ buckets, name }: StringFacetProps): FilterGroup {
11
+ export function createStringFilterGroup({ buckets, name, placeholder }: StringFacetProps): FilterGroup {
11
12
  const options = buckets.map((bucket) => ({
12
13
  label: facetOptionLabel(bucket),
13
14
  value: bucket._id
14
15
  }));
15
16
 
16
17
  const filterGroup: FilterGroup = {
17
- name: name.charAt(0).toUpperCase() + name.slice(1),
18
+ name: name,
18
19
  options: options,
19
- type: "select"
20
-
20
+ type: "select",
21
+ placeholder: `${placeholder ?? `${name.charAt(0).toUpperCase() + name.slice(1)}`}`,
21
22
  };
22
23
 
23
24
  return filterGroup;
24
25
  }
25
26
 
26
- export function VStringFacet({ buckets, name, }: {
27
+ export function VStringFacet({ buckets, name, placeholder}: {
27
28
  search: any;
28
29
  buckets: FacetBucket[];
29
30
  name: string;
30
31
  placeholder?: string;
31
32
  className?: string;
32
33
  }) {
33
- return createStringFilterGroup({ buckets, name });
34
+ return createStringFilterGroup({ buckets, name, placeholder });
34
35
  }
@@ -5,19 +5,20 @@ import { UserInfo } from '../user/UserInfo';
5
5
  interface UserFacetProps {
6
6
  buckets: FacetBucket[];
7
7
  name: string;
8
+ placeholder?: string;
8
9
  }
9
10
 
10
- export function createUserFilterGroup({ buckets, name }: UserFacetProps): FilterGroup {
11
+ export function createUserFilterGroup({ buckets, name, placeholder }: UserFacetProps): FilterGroup {
11
12
  const options = buckets.map((bucket) => {
12
13
  return {
13
14
  value: bucket._id,
14
- // Store the count for use in labelRenderer
15
15
  label: `(${bucket.count})`
16
16
  };
17
17
  });
18
18
 
19
19
  const filterGroup: FilterGroup = {
20
- name: name.charAt(0).toUpperCase() + name.slice(1), // Capitalize first letter
20
+ name: name,
21
+ placeholder: placeholder || `${name.charAt(0).toUpperCase() + name.slice(1)}`,
21
22
  options: options,
22
23
  labelRenderer: (userRef: string) => {
23
24
  const isUnknownUser = userRef === 'Unknown User' || !userRef;
@@ -36,12 +37,12 @@ export function createUserFilterGroup({ buckets, name }: UserFacetProps): Filter
36
37
  <span className="text-muted-foreground ml-2">({bucket?.count || 0})</span>
37
38
  </div>
38
39
  );
39
- }
40
+ },
40
41
  };
41
42
 
42
43
  return filterGroup;
43
44
  }
44
45
 
45
- export function VUserFacet({ buckets, name }: UserFacetProps) {
46
- return createUserFilterGroup({ buckets, name });
46
+ export function VUserFacet({ buckets, name, placeholder }: UserFacetProps) {
47
+ return createUserFilterGroup({ buckets, name, placeholder });
47
48
  }
@@ -40,7 +40,7 @@ export function GenericPageNavHeader({ className, children, title, description,
40
40
  }
41
41
  </div>
42
42
  </div>
43
- <div className="flex gap-x-4 shrink-0">{actions}</div>
43
+ <div className="flex gap-x-2 shrink-0">{actions}</div>
44
44
  </div>
45
45
  {children && <div className="w-full flex items-center">{children}</div>}
46
46
  </div>
@@ -1,5 +1,4 @@
1
- import { JSONCode } from "@vertesia/ui/widgets";
2
- import { Theme, XMLViewer } from '@vertesia/ui/widgets';
1
+ import { JSONCode, Theme, XMLViewer } from '@vertesia/ui/widgets';
3
2
  import { useEffect, useLayoutEffect, useState } from "react";
4
3
  import { usePdfPagesInfo } from "./PdfPageProvider";
5
4
  import { ViewType } from "./types";
@@ -1,11 +1,11 @@
1
1
  import { NavLink } from "@vertesia/ui/router";
2
2
  import { useUserSession } from "@vertesia/ui/session";
3
3
  import { FolderClosed, Search, Trash2 } from "lucide-react";
4
- import { Button, ConfirmModal, ErrorBox, Table, TBody, TR, useToast, VTooltip } from "@vertesia/ui/core";
5
- import { useFetch } from "@vertesia/ui/core";
4
+ import { Button, ConfirmModal, ErrorBox, Table, TBody, TR, useToast, VTooltip, useFetch, EmptyCollection } from "@vertesia/ui/core";
6
5
  import dayjs from 'dayjs';
7
6
  import relativeTime from 'dayjs/plugin/relativeTime';
8
7
  import { useState, useEffect } from "react";
8
+ import { CreateCollectionModal } from "./CreateCollection";
9
9
 
10
10
  dayjs.extend(relativeTime);
11
11
 
@@ -16,9 +16,10 @@ export function CollectionsTable({ }: CollectionsTableProps) {
16
16
  const toast = useToast();
17
17
  const [collectionToDelete, setCollectionToDelete] = useState<string | undefined>();
18
18
  const [isLoading, setIsLoading] = useState(true);
19
+ const [isOpen, setOpen] = useState(false);
19
20
 
20
21
  const { data: collections, error, refetch } = useFetch(() => client.store.collections.list(), []);
21
-
22
+
22
23
  // Update loading state when data is fetched
23
24
  useEffect(() => {
24
25
  if (collections || error) {
@@ -32,7 +33,7 @@ export function CollectionsTable({ }: CollectionsTableProps) {
32
33
 
33
34
  const deleteCollection = async () => {
34
35
  if (!collectionToDelete) return;
35
-
36
+
36
37
  try {
37
38
  await client.store.collections.delete(collectionToDelete);
38
39
  toast({
@@ -56,42 +57,50 @@ export function CollectionsTable({ }: CollectionsTableProps) {
56
57
 
57
58
  return (
58
59
  <>
59
- {collections && <Table className="w-full">
60
- <thead>
61
- <tr>
62
- <th>Name</th>
63
- <th>Type</th>
64
- <th>Created</th>
65
- <th></th>
66
- </tr>
67
- </thead>
68
- <TBody columns={4} isLoading={isLoading}>
69
- {
70
- collections.map((c) => {
71
- return <TR key={c.id}>
72
- <td>
73
- <div className="flex items-center gap-2">
74
- {collectionIcon(c.dynamic)}
75
- <NavLink href={`/collections/${c.id}`}>{c.name}</NavLink>
76
- </div>
77
- </td>
78
- <td>{c.type?.name || "-"}</td>
79
- <td>{dayjs(c.created_at).fromNow()}</td>
80
- <td className="text-right">
81
- <Button
82
- variant="destructive"
83
- size="sm"
84
- onClick={() => setCollectionToDelete(c.id)}
85
- >
86
- <Trash2 className="size-4" />
87
- </Button>
88
- </td>
89
- </TR>
90
- })
91
- }
92
- </TBody>
93
- </Table>}
94
-
60
+ {collections &&
61
+ (collections.length > 0 ?
62
+ (<Table className="w-full">
63
+ <thead>
64
+ <tr>
65
+ <th>Name</th >
66
+ <th>Type</th>
67
+ <th>Created</th>
68
+ <th></th>
69
+ </tr >
70
+ </thead >
71
+ <TBody columns={4} isLoading={isLoading}>
72
+ {
73
+ collections.map((c) => {
74
+ return <TR key={c.id}>
75
+ <td>
76
+ <div className="flex items-center gap-2">
77
+ {collectionIcon(c.dynamic)}
78
+ <NavLink href={`/collections/${c.id}`}>{c.name}</NavLink>
79
+ </div>
80
+ </td>
81
+ <td>{c.type?.name || "-"}</td>
82
+ <td>{dayjs(c.created_at).fromNow()}</td>
83
+ <td className="text-right">
84
+ <Button
85
+ variant="destructive"
86
+ size="sm"
87
+ onClick={() => setCollectionToDelete(c.id)}
88
+ >
89
+ <Trash2 className="size-4" />
90
+ </Button>
91
+ </td>
92
+ </TR>
93
+ })
94
+ }
95
+ </TBody>
96
+ </Table >) :
97
+ <EmptyCollection title="No Collections" buttonLabel='New Collections' onClick={() => setOpen(true)}>
98
+ Get started by creating a new Collections.
99
+ </EmptyCollection>)
100
+ }
101
+
102
+ <CreateCollectionModal isOpen={isOpen} onClose={() => setOpen(false)} />
103
+
95
104
  <ConfirmModal
96
105
  isOpen={!!collectionToDelete}
97
106
  title="Delete Collection"
@@ -1,49 +1,9 @@
1
1
  import { CreateCollectionPayload } from "@vertesia/common";
2
- import {
3
- Button, FormItem, Input, Styles,
4
- Switch, useFlag, useToast, VModal,
5
- VModalBody,
6
- VModalFooter,
7
- VModalTitle
8
- } from "@vertesia/ui/core";
9
- import { FullHeightLayout } from "@vertesia/ui/layout";
2
+ import { useToast, VModalBody, FormItem, Styles, VModalFooter, Input, Switch, Button, VModal, VModalTitle } from "@vertesia/ui/core";
3
+ import { SelectContentType } from "../types/SelectContentType";
10
4
  import { useNavigate } from "@vertesia/ui/router";
11
5
  import { useUserSession } from "@vertesia/ui/session";
12
6
  import { useState } from "react";
13
- import { GenericPageNavHeader } from "../../layout";
14
- import { SelectContentType } from "../../store";
15
- import { CollectionsTable } from "./CollectionsTable";
16
-
17
- interface CollectionsViewProps { }
18
- export function CollectionsView({ }: CollectionsViewProps) {
19
- const actions = [<CreateCollectionButton key="create" />];
20
- return (
21
- <FullHeightLayout>
22
- <GenericPageNavHeader
23
- title="Collections"
24
- breadcrumbs={[<span key="0">Collections</span>]}
25
- description="Group objects together using a collection"
26
- actions={actions}
27
- />
28
- <FullHeightLayout.Body>
29
- <CollectionsTable />
30
- </FullHeightLayout.Body>
31
- </FullHeightLayout>
32
- );
33
- }
34
-
35
- function CreateCollectionButton() {
36
- const { on, off, isOn } = useFlag();
37
- return (
38
- <div>
39
- <VModal onClose={off} isOpen={isOn}>
40
- <VModalTitle>Create a Collection</VModalTitle>
41
- <CreateCollectionForm onClose={off} />
42
- </VModal>
43
- <Button onClick={on}>Create Collection</Button>
44
- </div>
45
- );
46
- }
47
7
 
48
8
  interface CreateCollectionFormProps {
49
9
  onClose: () => void;
@@ -164,3 +124,16 @@ export function CreateCollectionForm({ onClose, redirect = true, onAddToCollecti
164
124
  </form >
165
125
  );
166
126
  }
127
+
128
+ interface CreateCollectionModalProps {
129
+ isOpen: boolean;
130
+ onClose: () => void;
131
+ }
132
+ export function CreateCollectionModal({ isOpen, onClose }: CreateCollectionModalProps) {
133
+ return (
134
+ <VModal onClose={onClose} isOpen={isOpen}>
135
+ <VModalTitle>Create a Collection</VModalTitle>
136
+ <CreateCollectionForm onClose={onClose} />
137
+ </VModal>
138
+ );
139
+ }
@@ -5,7 +5,7 @@ import { useUserSession } from "@vertesia/ui/session";
5
5
  import { CodeMirrorEditor, EditorApi, GeneratedForm, ManagedObject } from "@vertesia/ui/widgets";
6
6
  import { basicSetup } from "codemirror";
7
7
  import { useMemo, useRef, useState } from "react";
8
- import { SelectContentType, stringifyTableLayout } from "../../store";
8
+ import { SelectContentType, stringifyTableLayout } from "../types";
9
9
 
10
10
  const extensions = [basicSetup, json()];
11
11