@vertesia/ui 0.73.0 → 0.76.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 (157) hide show
  1. package/lib/esm/core/components/Center.js +1 -1
  2. package/lib/esm/core/components/Center.js.map +1 -1
  3. package/lib/esm/core/components/Overlay.js +57 -0
  4. package/lib/esm/core/components/Overlay.js.map +1 -0
  5. package/lib/esm/core/components/SidePanel.js +6 -6
  6. package/lib/esm/core/components/SidePanel.js.map +1 -1
  7. package/lib/esm/core/components/index.js +1 -0
  8. package/lib/esm/core/components/index.js.map +1 -1
  9. package/lib/esm/core/components/shadcn/tabs.js +43 -5
  10. package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
  11. package/lib/esm/features/agent/PayloadBuilder.js +9 -2
  12. package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
  13. package/lib/esm/features/facets/DocumentsFacetsNav.js +4 -2
  14. package/lib/esm/features/facets/DocumentsFacetsNav.js.map +1 -1
  15. package/lib/esm/features/facets/VTypeFacet.js +2 -1
  16. package/lib/esm/features/facets/VTypeFacet.js.map +1 -1
  17. package/lib/esm/features/magic-pdf/DownloadPopover.js +17 -2
  18. package/lib/esm/features/magic-pdf/DownloadPopover.js.map +1 -1
  19. package/lib/esm/features/magic-pdf/MagicPdfView.js +26 -3
  20. package/lib/esm/features/magic-pdf/MagicPdfView.js.map +1 -1
  21. package/lib/esm/features/magic-pdf/PageSlider.js +21 -8
  22. package/lib/esm/features/magic-pdf/PageSlider.js.map +1 -1
  23. package/lib/esm/features/magic-pdf/PdfPageProvider.js +55 -0
  24. package/lib/esm/features/magic-pdf/PdfPageProvider.js.map +1 -1
  25. package/lib/esm/features/magic-pdf/TextPageView.js +20 -2
  26. package/lib/esm/features/magic-pdf/TextPageView.js.map +1 -1
  27. package/lib/esm/features/store/collections/CreateCollection.js +1 -1
  28. package/lib/esm/features/store/collections/CreateCollection.js.map +1 -1
  29. package/lib/esm/features/store/objects/DocumentPreviewPanel.js +2 -4
  30. package/lib/esm/features/store/objects/DocumentPreviewPanel.js.map +1 -1
  31. package/lib/esm/features/store/objects/DocumentSearchResults.js +19 -21
  32. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  33. package/lib/esm/features/store/objects/components/ContentOverview.js +2 -4
  34. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  35. package/lib/esm/features/store/objects/components/VectorSearchWidget.js +51 -46
  36. package/lib/esm/features/store/objects/components/VectorSearchWidget.js.map +1 -1
  37. package/lib/esm/features/store/objects/layout/documentLayout.js +1 -1
  38. package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
  39. package/lib/esm/features/store/objects/search/DocumentSearchContext.js +50 -34
  40. package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  41. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +1 -3
  42. package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -1
  43. package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js +4 -11
  44. package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
  45. package/lib/esm/features/user/UserInfo.js +2 -2
  46. package/lib/esm/features/user/UserInfo.js.map +1 -1
  47. package/lib/esm/session/UserSessionProvider.js +6 -3
  48. package/lib/esm/session/UserSessionProvider.js.map +1 -1
  49. package/lib/esm/session/auth/composable.js +3 -3
  50. package/lib/esm/session/auth/composable.js.map +1 -1
  51. package/lib/esm/session/auth/firebase.js +7 -0
  52. package/lib/esm/session/auth/firebase.js.map +1 -1
  53. package/lib/esm/session/auth/useAuthState.js +0 -3
  54. package/lib/esm/session/auth/useAuthState.js.map +1 -1
  55. package/lib/esm/shell/apps/StandaloneApp.js +1 -1
  56. package/lib/esm/shell/apps/StandaloneApp.js.map +1 -1
  57. package/lib/esm/shell/login/EnterpriseSigninButton.js +3 -0
  58. package/lib/esm/shell/login/EnterpriseSigninButton.js.map +1 -1
  59. package/lib/esm/shell/login/InviteAcceptModal.js +1 -1
  60. package/lib/esm/shell/login/InviteAcceptModal.js.map +1 -1
  61. package/lib/esm/widgets/form/ManagedObject.js +1 -1
  62. package/lib/esm/widgets/index.js +1 -0
  63. package/lib/esm/widgets/index.js.map +1 -1
  64. package/lib/esm/widgets/markdown/MarkdownRenderer.js +24 -0
  65. package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -0
  66. package/lib/esm/widgets/markdown/index.js +2 -0
  67. package/lib/esm/widgets/markdown/index.js.map +1 -0
  68. package/lib/tsconfig.tsbuildinfo +1 -1
  69. package/lib/types/core/components/Overlay.d.ts +25 -0
  70. package/lib/types/core/components/Overlay.d.ts.map +1 -0
  71. package/lib/types/core/components/SidePanel.d.ts +3 -1
  72. package/lib/types/core/components/SidePanel.d.ts.map +1 -1
  73. package/lib/types/core/components/index.d.ts +1 -0
  74. package/lib/types/core/components/index.d.ts.map +1 -1
  75. package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
  76. package/lib/types/env/index.d.ts +2 -2
  77. package/lib/types/env/index.d.ts.map +1 -1
  78. package/lib/types/features/agent/PayloadBuilder.d.ts.map +1 -1
  79. package/lib/types/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  80. package/lib/types/features/facets/VTypeFacet.d.ts.map +1 -1
  81. package/lib/types/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
  82. package/lib/types/features/magic-pdf/PageSlider.d.ts +2 -1
  83. package/lib/types/features/magic-pdf/PageSlider.d.ts.map +1 -1
  84. package/lib/types/features/magic-pdf/PdfPageProvider.d.ts +10 -0
  85. package/lib/types/features/magic-pdf/PdfPageProvider.d.ts.map +1 -1
  86. package/lib/types/features/magic-pdf/TextPageView.d.ts.map +1 -1
  87. package/lib/types/features/magic-pdf/types.d.ts +1 -1
  88. package/lib/types/features/magic-pdf/types.d.ts.map +1 -1
  89. package/lib/types/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
  90. package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  91. package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  92. package/lib/types/features/store/objects/components/VectorSearchWidget.d.ts +4 -3
  93. package/lib/types/features/store/objects/components/VectorSearchWidget.d.ts.map +1 -1
  94. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +5 -2
  95. package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  96. package/lib/types/features/store/objects/search/DocumentSearchProvider.d.ts +2 -4
  97. package/lib/types/features/store/objects/search/DocumentSearchProvider.d.ts.map +1 -1
  98. package/lib/types/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  99. package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
  100. package/lib/types/session/auth/composable.d.ts +1 -1
  101. package/lib/types/session/auth/composable.d.ts.map +1 -1
  102. package/lib/types/session/auth/firebase.d.ts.map +1 -1
  103. package/lib/types/session/auth/useAuthState.d.ts.map +1 -1
  104. package/lib/types/shell/login/EnterpriseSigninButton.d.ts.map +1 -1
  105. package/lib/types/widgets/index.d.ts +1 -0
  106. package/lib/types/widgets/index.d.ts.map +1 -1
  107. package/lib/types/widgets/markdown/MarkdownRenderer.d.ts +9 -0
  108. package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -0
  109. package/lib/types/widgets/markdown/index.d.ts +2 -0
  110. package/lib/types/widgets/markdown/index.d.ts.map +1 -0
  111. package/lib/vertesia-ui-core.js +1 -1
  112. package/lib/vertesia-ui-core.js.map +1 -1
  113. package/lib/vertesia-ui-features.js +1 -1
  114. package/lib/vertesia-ui-features.js.map +1 -1
  115. package/lib/vertesia-ui-session.js +1 -1
  116. package/lib/vertesia-ui-session.js.map +1 -1
  117. package/lib/vertesia-ui-shell.js +1 -1
  118. package/lib/vertesia-ui-shell.js.map +1 -1
  119. package/lib/vertesia-ui-widgets.js +1 -1
  120. package/lib/vertesia-ui-widgets.js.map +1 -1
  121. package/package.json +6 -4
  122. package/src/core/components/Center.tsx +1 -1
  123. package/src/core/components/Overlay.tsx +129 -0
  124. package/src/core/components/SidePanel.tsx +38 -33
  125. package/src/core/components/index.ts +1 -0
  126. package/src/core/components/shadcn/tabs.tsx +48 -5
  127. package/src/env/index.ts +1 -1
  128. package/src/features/agent/PayloadBuilder.tsx +8 -2
  129. package/src/features/facets/DocumentsFacetsNav.tsx +4 -2
  130. package/src/features/facets/VTypeFacet.tsx +2 -1
  131. package/src/features/magic-pdf/DownloadPopover.tsx +38 -5
  132. package/src/features/magic-pdf/MagicPdfView.tsx +31 -5
  133. package/src/features/magic-pdf/PageSlider.tsx +44 -14
  134. package/src/features/magic-pdf/PdfPageProvider.tsx +81 -0
  135. package/src/features/magic-pdf/TextPageView.tsx +29 -2
  136. package/src/features/magic-pdf/types.ts +1 -1
  137. package/src/features/store/collections/CreateCollection.tsx +1 -1
  138. package/src/features/store/objects/DocumentPreviewPanel.tsx +2 -4
  139. package/src/features/store/objects/DocumentSearchResults.tsx +24 -26
  140. package/src/features/store/objects/components/ContentOverview.tsx +3 -6
  141. package/src/features/store/objects/components/VectorSearchWidget.tsx +88 -60
  142. package/src/features/store/objects/layout/documentLayout.tsx +1 -1
  143. package/src/features/store/objects/search/DocumentSearchContext.ts +57 -36
  144. package/src/features/store/objects/search/DocumentSearchProvider.tsx +2 -6
  145. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +6 -12
  146. package/src/features/user/UserInfo.tsx +2 -2
  147. package/src/session/UserSessionProvider.tsx +5 -3
  148. package/src/session/auth/composable.ts +3 -3
  149. package/src/session/auth/firebase.ts +8 -0
  150. package/src/session/auth/useAuthState.ts +0 -4
  151. package/src/shell/apps/StandaloneApp.tsx +1 -1
  152. package/src/shell/login/EnterpriseSigninButton.tsx +3 -0
  153. package/src/shell/login/InviteAcceptModal.tsx +1 -1
  154. package/src/widgets/form/ManagedObject.ts +1 -1
  155. package/src/widgets/index.ts +1 -0
  156. package/src/widgets/markdown/MarkdownRenderer.tsx +45 -0
  157. package/src/widgets/markdown/index.ts +1 -0
@@ -2,13 +2,14 @@ import { createContext, useContext } from 'react';
2
2
 
3
3
  import { SharedState, useWatchSharedState } from '@vertesia/ui/core';
4
4
  import { ComputeFacetsResponse, ZenoClient } from '@vertesia/client';
5
- import { ComplexSearchQuery, ContentObjectItem, FacetBucket, FacetSpec, ObjectSearchQuery } from '@vertesia/common';
5
+ import { ComplexSearchPayload, ComplexSearchQuery, ComputeObjectFacetPayload, ContentObjectItem, FacetBucket, FacetSpec, ObjectSearchQuery } from '@vertesia/common';
6
6
  import { SearchInterface } from '@vertesia/ui/features'
7
7
 
8
8
  interface DocumentSearchResult {
9
9
  objects: ContentObjectItem[],
10
10
  error?: Error;
11
11
  isLoading: boolean;
12
+ hasMore?: boolean;
12
13
  }
13
14
 
14
15
 
@@ -36,10 +37,14 @@ export class DocumentSearch implements SearchInterface {
36
37
  return this.result.value.error;
37
38
  }
38
39
 
39
- get isRunning() {
40
+ get isRunning(): boolean {
40
41
  return this.result.value.isLoading;
41
42
  }
42
43
 
44
+ get hasMore(): boolean {
45
+ return this.result.value.hasMore || false;
46
+ }
47
+
43
48
  getFilterValue(name: string) {
44
49
  return (this.query as any)[name];
45
50
  }
@@ -51,9 +56,16 @@ export class DocumentSearch implements SearchInterface {
51
56
  }
52
57
 
53
58
  clearFilters(autoSearch: boolean = true) {
54
- const parent = this.query.parent;
59
+ // Preserve search-related fields when clearing filters
60
+ const { parent, full_text, vector, weights, score_aggregation, dynamic_scaling, limit } = this.query;
55
61
  this.query = {
56
- parent
62
+ parent,
63
+ ...(full_text !== undefined && { full_text }),
64
+ ...(vector !== undefined && { vector }),
65
+ ...(weights !== undefined && { weights }),
66
+ ...(score_aggregation !== undefined && { score_aggregation }),
67
+ ...(dynamic_scaling !== undefined && { dynamic_scaling }),
68
+ ...(limit !== undefined && { limit })
57
69
  };
58
70
 
59
71
  if (autoSearch) {
@@ -72,7 +84,8 @@ export class DocumentSearch implements SearchInterface {
72
84
  reset(isLoading = false) {
73
85
  this.result.value = {
74
86
  objects: [],
75
- isLoading
87
+ isLoading,
88
+ hasMore: true
76
89
  };
77
90
  }
78
91
 
@@ -81,34 +94,29 @@ export class DocumentSearch implements SearchInterface {
81
94
  this.result.value = {
82
95
  objects: prev.objects,
83
96
  isLoading: value,
84
- error: prev.error
97
+ error: prev.error,
98
+ hasMore: prev.hasMore
85
99
  }
86
100
  }
87
101
 
88
- _searchRequest(query: ComplexSearchQuery, limit: number, offset: number) {
102
+ _searchRequest(query: ComplexSearchQuery, limit: number, offset: number, includeFacets: boolean = true) {
103
+ const payload: ComplexSearchPayload = {
104
+ limit,
105
+ offset,
106
+ query,
107
+ facets: includeFacets ? this.facetSpecs : undefined
108
+ };
109
+
89
110
  return this.collectionId ?
90
- this.client.collections.searchMembers(this.collectionId, {
91
- limit,
92
- offset,
93
- query
94
- })
95
- : this.client.objects.search({
96
- limit,
97
- offset,
98
- query
99
- });
111
+ this.client.collections.searchMembers(this.collectionId, payload)
112
+ : this.client.objects.search(payload);
100
113
  }
101
114
 
102
115
  _facetsRequest() {
116
+ const payload: ComputeObjectFacetPayload = { facets: this.facetSpecs, query: this.query }
103
117
  return this.collectionId ?
104
- this.client.collections.computeFacets(this.collectionId, {
105
- facets: this.facetSpecs,
106
- query: this.query
107
- })
108
- : this.client.objects.computeFacets({
109
- facets: this.facetSpecs,
110
- query: this.query
111
- });
118
+ this.client.collections.computeFacets(this.collectionId, payload)
119
+ : this.client.objects.computeFacets(payload);
112
120
  }
113
121
 
114
122
  computeFacets(_query: ObjectSearchQuery) {
@@ -117,27 +125,40 @@ export class DocumentSearch implements SearchInterface {
117
125
  });
118
126
  }
119
127
 
120
- _search(loadMore = false) {
128
+ _search(loadMore = false, noFacets = false) {
121
129
  if (this.isRunning) { // avoid searching when a search is pending
122
130
  return Promise.resolve(false);
123
131
  }
124
132
  this.result.value = {
125
133
  isLoading: true,
126
134
  objects: loadMore ? this.objects : [],
135
+ hasMore: loadMore ? this.result.value.hasMore : true
127
136
  }
128
137
  const limit = this.limit;
129
- const offset = this.objects.length;
130
- return this._searchRequest(this.query, limit, offset).then(async (res) => {
138
+ const offset = loadMore ? this.objects.length : 0;
139
+ return this._searchRequest(this.query, limit, offset, !noFacets).then(async (res) => {
140
+ // Handle the new format with results and facets
141
+ const results = res.results || [];
142
+ const facets = res.facets || {};
143
+
131
144
  this.result.value = {
132
145
  isLoading: false,
133
- objects: this.objects.concat(res)
146
+ objects: loadMore ? this.objects.concat(results) : results,
147
+ hasMore: results.length === limit
134
148
  }
149
+
150
+ // Update facets if they were requested and returned
151
+ if (!noFacets && facets && Object.keys(facets).length > 0) {
152
+ this.facets.value = facets;
153
+ }
154
+
135
155
  return true;
136
156
  }).catch((err) => {
137
157
  this.result.value = {
138
158
  error: err,
139
159
  isLoading: false,
140
- objects: this.objects
160
+ objects: this.objects,
161
+ hasMore: this.result.value.hasMore
141
162
  }
142
163
  throw err;
143
164
  })
@@ -145,16 +166,16 @@ export class DocumentSearch implements SearchInterface {
145
166
 
146
167
  search(noFacets = false) {
147
168
  if (this.isRunning) return Promise.resolve(false);
148
- !noFacets && this.computeFacets(this.query);
149
- return this._search(false);
169
+ return this._search(false, noFacets);
150
170
  }
151
171
 
152
172
  loadMore(noFacets = false) {
153
- if (this.isRunning) return Promise.resolve(false);
154
- if (this.objects.length === 0) {
155
- !noFacets && this.computeFacets(this.query);
173
+ if (this.isRunning || !this.hasMore) return Promise.resolve(false);
174
+ if (this.query.vector) return Promise.resolve(false); //Load more not supported on vector queries
175
+ if (this.objects.length > 0) {
176
+ noFacets = true; //Only reload facets on loadMore if there are no results.
156
177
  }
157
- return this._search(true);
178
+ return this._search(true, noFacets);
158
179
  }
159
180
  }
160
181
 
@@ -1,5 +1,5 @@
1
1
  import { useUserSession } from "@vertesia/ui/session";
2
- import { FacetSpec, SupportedEmbeddingTypes } from "@vertesia/common";
2
+ import { FacetSpec } from "@vertesia/common";
3
3
  import React, { useMemo } from "react";
4
4
  import { DocumentSearch, SearchContext } from "./DocumentSearchContext";
5
5
 
@@ -9,12 +9,10 @@ interface DocumentSearchProviderProps {
9
9
  typeId?: string;
10
10
  parent?: string;
11
11
  facets?: FacetSpec[];
12
- similarTo?: string; //vector search similarity
13
- embeddingType?: SupportedEmbeddingTypes; //vector search similarity
14
12
  collectionId?: string;
15
13
  name?: string;
16
14
  }
17
- export function DocumentSearchProvider({ children, limit, parent, typeId, facets, similarTo, embeddingType, name, collectionId }: DocumentSearchProviderProps) {
15
+ export function DocumentSearchProvider({ children, limit, parent, typeId, facets, name, collectionId }: DocumentSearchProviderProps) {
18
16
  const { store } = useUserSession();
19
17
  const search = useMemo(() => {
20
18
  let facetSpecs: FacetSpec[];
@@ -42,8 +40,6 @@ export function DocumentSearchProvider({ children, limit, parent, typeId, facets
42
40
  search.collectionId = collectionId;
43
41
  search.query.type = typeId;
44
42
  search.query.parent = parent;
45
- search.query.similarTo = similarTo;
46
- search.query.embeddingType = embeddingType;
47
43
  search.query.name = name;
48
44
  return search;
49
45
  }, [typeId, limit]);
@@ -1,4 +1,4 @@
1
- import { ContentObjectItem } from "@vertesia/common";
1
+ import { ComplexSearchPayload, ContentObjectItem } from "@vertesia/common";
2
2
  import { useToast } from "@vertesia/ui/core";
3
3
  import { useUserSession } from "@vertesia/ui/session";
4
4
  import { Md5 } from "ts-md5";
@@ -134,18 +134,12 @@ export function useSmartFileUploadProcessing() {
134
134
 
135
135
  let res: ContentObjectItem[];
136
136
 
137
+ const payload: ComplexSearchPayload = {query: {match: query}, select: undefined}
138
+
137
139
  if (limitToCollectionId) {
138
- res = await client.store.collections.searchMembers(limitToCollectionId, {
139
- query: {
140
- match: query,
141
- },
142
- select: undefined,
143
- });
140
+ res = (await client.store.collections.searchMembers(limitToCollectionId, payload)).results;
144
141
  } else {
145
- res = await client.store.objects.search({
146
- query: { match: query },
147
- select: undefined,
148
- });
142
+ res = (await client.store.objects.search(payload)).results;
149
143
  }
150
144
 
151
145
  for (const doc of res) {
@@ -180,7 +174,7 @@ export function useSmartFileUploadProcessing() {
180
174
  match: query,
181
175
  },
182
176
  select: undefined,
183
- });
177
+ }).then((response) => response.results);
184
178
  queries.push(res);
185
179
  } else {
186
180
  const res = client.store.objects.find({
@@ -180,7 +180,7 @@ export function ApiKeyAvatar({ keyId, showTitle = false, size = "md" }: ApiKeyAv
180
180
  </tr>
181
181
  <tr>
182
182
  <td className="font-semibold w-20">Project:</td>
183
- <td className="truncate max-w-0">{data?.project}</td>
183
+ <td className="truncate max-w-0">{data?.project.name}</td>
184
184
  </tr>
185
185
  </Table>
186
186
  );
@@ -189,7 +189,7 @@ export function ApiKeyAvatar({ keyId, showTitle = false, size = "md" }: ApiKeyAv
189
189
  <UserPopoverPanel title={title} description={description}>
190
190
  <div className="flex flex-row items-center gap-2">
191
191
  {avatar}
192
- {showTitle && <div className="text-sm font-semibold">{data?.name || data?.account || data?.project || "unknown"}</div>}
192
+ {showTitle && <div className="text-sm font-semibold">{data?.name || data?.account || data?.project.name || "unknown"}</div>}
193
193
  </div>
194
194
  </UserPopoverPanel >
195
195
  )
@@ -26,7 +26,7 @@ export function UserSessionProvider({ children }: UserSessionProviderProps) {
26
26
  const token = hashParams.get("token");
27
27
  const state = hashParams.get("state");
28
28
  const [session, setSession] = useState<UserSession>(new UserSession());
29
- const { generateState, verifyState } = useAuthState();
29
+ const { generateState, verifyState, clearState } = useAuthState();
30
30
 
31
31
  const redirectToCentralAuth = (projectId?: string, accountId?: string) => {
32
32
  const url = new URL(CENTRAL_AUTH_REDIRECT);
@@ -68,8 +68,10 @@ export function UserSessionProvider({ children }: UserSessionProviderProps) {
68
68
  },
69
69
  });
70
70
  redirectToCentralAuth();
71
+ } else {
72
+ clearState()
71
73
  }
72
- getComposableToken(selectedAccount, selectedProject, token)
74
+ getComposableToken(selectedAccount, selectedProject, token, false, shouldRedirectToCentralAuth())
73
75
  .then((res) => {
74
76
  session.login(res.rawToken).then(() => {
75
77
  setSession(session.clone());
@@ -132,7 +134,7 @@ export function UserSessionProvider({ children }: UserSessionProviderProps) {
132
134
  },
133
135
  });
134
136
  session.setSession = setSession;
135
- await getComposableToken(selectedAccount, selectedProject)
137
+ await getComposableToken(selectedAccount, selectedProject, undefined, false, shouldRedirectToCentralAuth())
136
138
  .then((res) => {
137
139
  session.login(res.rawToken).then(() => setSession(session.clone()));
138
140
  })
@@ -134,7 +134,7 @@ export async function fetchComposableTokenFromFirebaseToken(accountId?: string,
134
134
  return fetchComposableToken(getFirebaseAuthToken, accountId, projectId, ttl);
135
135
  }
136
136
 
137
- export async function getComposableToken(accountId?: string, projectId?: string, initToken?: string, forceRefresh = false): Promise<ComposableTokenResponse> {
137
+ export async function getComposableToken(accountId?: string, projectId?: string, initToken?: string, forceRefresh = false, useInternalAuth = false): Promise<ComposableTokenResponse> {
138
138
 
139
139
  const selectedAccount = accountId ?? localStorage.getItem(LastSelectedAccountId_KEY) ?? undefined
140
140
  const selectedProject = projectId ?? localStorage.getItem(LastSelectedProjectId_KEY + '-' + selectedAccount) ?? undefined
@@ -145,11 +145,11 @@ export async function getComposableToken(accountId?: string, projectId?: string,
145
145
  }
146
146
 
147
147
  //token is close to expire, refresh it
148
- if (getFirebaseAuth().currentUser) {
148
+ if (!useInternalAuth && getFirebaseAuth().currentUser) {
149
149
  //we have a firebase user, get the token from there
150
150
  AUTH_TOKEN_RAW = await fetchComposableTokenFromFirebaseToken(selectedAccount, selectedProject);
151
151
  } else if (initToken || AUTH_TOKEN_RAW) {
152
- //we have a token already and no firebase user, refresh it
152
+ // we have a token already and no firebase user, refresh it
153
153
  AUTH_TOKEN_RAW = await fetchComposableToken(() => Promise.resolve(initToken ?? AUTH_TOKEN_RAW), selectedAccount, selectedProject);
154
154
  }
155
155
 
@@ -13,6 +13,9 @@ let _firebaseAuth: Auth | null = null;
13
13
  export function getFirebaseApp(): FirebaseApp {
14
14
  if (!_firebaseApp) {
15
15
  try {
16
+ if (!Env.firebase) {
17
+ throw new Error("Firebase configuration is not available in the environment");
18
+ }
16
19
  _firebaseApp = initializeApp(Env.firebase);
17
20
  } catch (error) {
18
21
  console.error("Failed to initialize Firebase app:", error);
@@ -43,6 +46,11 @@ export async function setFirebaseTenant(tenantEmail?: string) {
43
46
  return;
44
47
  }
45
48
 
49
+ if (!Env.firebase) {
50
+ console.log("Firebase configuration is not available in the environment");
51
+ return;
52
+ }
53
+
46
54
  try {
47
55
  if (tenantEmail) console.log(`Resolving tenant ID from email: ${tenantEmail}`);
48
56
 
@@ -44,10 +44,6 @@ export function useAuthState() {
44
44
  reason = undefined; // No errors
45
45
  }
46
46
 
47
- // Clear stored state regardless of outcome
48
- sessionStorage.removeItem(AUTH_STATE_KEY);
49
- sessionStorage.removeItem(STATE_EXPIRY_KEY);
50
-
51
47
  return reason;
52
48
  }, []);
53
49
 
@@ -101,7 +101,7 @@ function UnknownAppName() {
101
101
  Before starting to code a Vertesia application you must register an application manifest
102
102
  in Vertesia Studio then install it in one or more projects.
103
103
  <p />
104
- Then use the created app name as a parameter to <code>&lt;StandaloneApp name=&quot;your-app-name&quot;&gt;</code> in the <code>src/main.ts</code> file.
104
+ Then use the created app name as a parameter to <code>&lt;StandaloneApp name=&quot;your-app-name&quot;&gt;</code> in the <code>src/main.tsx</code> file.
105
105
  </div>
106
106
  </Center>
107
107
  )
@@ -6,6 +6,9 @@ import { useState } from "react";
6
6
 
7
7
 
8
8
  function getProvider(redirectTo?: string) {
9
+ if (!Env.firebase) {
10
+ throw new Error("Firebase configuration is not available in the environment");
11
+ }
9
12
  const providerType = Env.firebase.providerType;
10
13
  switch (providerType) {
11
14
  case "oidc":
@@ -68,7 +68,7 @@ export function InviteAcceptModal() {
68
68
  <div className="w-full font-semibold">{invite.data.account.name ?? invite.data.account}</div>
69
69
  {invite.data.project && <div className="w-full text-base">- {invite.data.project.name}</div>}
70
70
  <div className="text-xs">Role: {invite.data.role}</div>
71
- <div className="text-xs">by {invite.data.invited_by.name}</div>
71
+ {invite.data.invited_by &&<div className="text-xs">by {invite.data.invited_by.name ?? invite.data.invited_by}</div>}
72
72
  </div>
73
73
  <div className="flex flex-col gap-4">
74
74
  <Button size={'xs'} onClick={() => accept(invite)}>Accept</Button> <Button size={'xs'} variant="secondary" onClick={() => reject(invite)}>Reject</Button>
@@ -237,7 +237,7 @@ export class ManagedListProperty extends Node<ArrayPropertySchema, JSONSchemaArr
237
237
  }
238
238
  if (Array.isArray(value) && index >= 0 && index < value.length) {
239
239
  value.splice(index, 1);
240
- // TODO trigger onCHnage only if this item isn't transient
240
+ // TODO trigger onChange only if this item isn't transient
241
241
  this.onChange(this);
242
242
  }
243
243
  }
@@ -1,6 +1,7 @@
1
1
  export * from "./codemirror/index.js";
2
2
  export * from "./form/index.js";
3
3
  export * from "./json-view/index.js";
4
+ export * from "./markdown/index.js";
4
5
  export * from "./popover/index.js";
5
6
  export * from "./Progress.js";
6
7
  export * from "./properties/index.js";
@@ -0,0 +1,45 @@
1
+ import Markdown from "react-markdown";
2
+ import remarkGfm from "remark-gfm";
3
+ import { visit, SKIP } from 'unist-util-visit';
4
+
5
+ function remarkRemoveComments() {
6
+ return (tree: any) => {
7
+ visit(tree, 'html', (node: any, index: number | undefined, parent: any) => {
8
+ if (node.value && /<!--[\s\S]*?-->/.test(node.value)) {
9
+ if (parent && typeof index === 'number' && parent.children) {
10
+ parent.children.splice(index, 1);
11
+ return [SKIP, index];
12
+ }
13
+ }
14
+ });
15
+ };
16
+ }
17
+
18
+ interface MarkdownRendererProps {
19
+ children: string;
20
+ components?: any;
21
+ remarkPlugins?: any[];
22
+ removeComments?: boolean;
23
+ }
24
+
25
+ export function MarkdownRenderer({
26
+ children,
27
+ components,
28
+ remarkPlugins = [],
29
+ removeComments = true
30
+ }: MarkdownRendererProps) {
31
+ const plugins = [remarkGfm, ...remarkPlugins];
32
+
33
+ if (removeComments) {
34
+ plugins.push(remarkRemoveComments);
35
+ }
36
+
37
+ return (
38
+ <Markdown
39
+ remarkPlugins={plugins}
40
+ components={components}
41
+ >
42
+ {children}
43
+ </Markdown>
44
+ );
45
+ }
@@ -0,0 +1 @@
1
+ export { MarkdownRenderer } from './MarkdownRenderer';