Skip to content

Commit

Permalink
Add system vault navigation (#6750)
Browse files Browse the repository at this point in the history
* Add system vault navigation

* Move DataSourceOrView to type.
  • Loading branch information
flvndvd authored and albandum committed Aug 28, 2024
1 parent 612089f commit 6f78071
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 12 deletions.
115 changes: 105 additions & 10 deletions front/components/vaults/VaultSideBarMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Tree,
} from "@dust-tt/sparkle";
import type {
DataSourceOrView,
DataSourceOrViewInfo,
LightWorkspaceType,
VaultType,
Expand Down Expand Up @@ -85,7 +86,7 @@ const renderVaultItems = (vaults: VaultType[], owner: LightWorkspaceType) =>
vaults.map((vault) => (
<Fragment key={`vault-${vault.sId}`}>
{vault.kind === "system" ? (
<SystemVaultMenu />
<SystemVaultMenu owner={owner} vault={vault} />
) : (
<VaultMenuItem owner={owner} vault={vault} />
)}
Expand Down Expand Up @@ -122,9 +123,102 @@ const SubItemIconItemWrapper = (

// System vault.

const SystemVaultMenu = () => {
// TODO(Groups UI) Implement system vault menu.
return <></>;
const SYSTEM_VAULTS_ITEMS = [
{
label: "Connection Management",
visual: RootItemIconWrapper(CloudArrowLeftRightIcon),
category: "managed",
},
{
label: "Files",
visual: RootItemIconWrapper(FolderIcon),
category: "files",
},
// TODO(GROUPS_UI) Add support for Dust apps.
];

const SystemVaultMenu = ({
owner,
vault,
}: {
owner: LightWorkspaceType;
vault: VaultType;
}) => {
return (
<>
{SYSTEM_VAULTS_ITEMS.map((item) => (
<SystemVaultItem
category={item.category}
key={item.label}
label={item.label}
owner={owner}
vault={vault}
visual={item.visual}
/>
))}
</>
);
};

const SystemVaultItem = ({
category,
label,
owner,
vault,
visual,
}: {
category: string;
label: string;
owner: LightWorkspaceType;
vault: VaultType;
visual: ReactElement;
}) => {
const router = useRouter();

const itemPath = `/w/${owner.sId}/data-sources/vaults/${vault.sId}/categories/${category}/data_sources`;
const isAncestorToCurrentPage = router.asPath.includes(itemPath);

// Unfold the item if it's an ancestor of the current page.
const [isExpanded, setIsExpanded] = useState(isAncestorToCurrentPage);

const { isVaultDataSourceOrViewsLoading, vaultDataSourceOrViews } =
useVaultDataSourceOrViews({
workspaceId: owner.sId,
vaultId: vault.sId,
category,
// System vault only has data sources.
type: "data_sources",
disabled: !isExpanded,
});

return (
<Tree.Item
label={label}
collapsed={!isExpanded}
onItemClick={() => router.push(itemPath)}
isSelected={router.asPath === itemPath}
onChevronClick={() => setIsExpanded(!isExpanded)}
visual={visual}
size="md"
areActionsFading={false}
>
{isExpanded && (
<Tree isLoading={isVaultDataSourceOrViewsLoading}>
{vaultDataSourceOrViews &&
vaultDataSourceOrViews.map((ds) => (
<VaultDataSourceOrViewItem
item={ds}
key={ds.sId}
owner={owner}
vault={vault}
// System vault only has data sources.
viewType="data_sources"
/>
))}
</Tree>
)}
</Tree.Item>
);
};

// Global + regular vaults.
Expand Down Expand Up @@ -191,7 +285,7 @@ const DATA_SOURCE_OR_VIEW_SUB_ITEMS: {
icon: ReactElement<{
className?: string;
}>;
dataSourceOrView: "data_sources" | "data_source_views";
dataSourceOrView: DataSourceOrView;
};
} = {
managed: {
Expand All @@ -217,13 +311,15 @@ const DATA_SOURCE_OR_VIEW_SUB_ITEMS: {
};

const VaultDataSourceOrViewItem = ({
item,
owner,
vault,
item,
viewType,
}: {
item: DataSourceOrViewInfo;
owner: LightWorkspaceType;
vault: VaultType;
item: DataSourceOrViewInfo;
viewType: "data_sources" | "data_source_views";
}): ReactElement => {
const router = useRouter();
const configuration = item.connectorProvider
Expand All @@ -232,8 +328,6 @@ const VaultDataSourceOrViewItem = ({

const LogoComponent = configuration?.logoComponent ?? FolderIcon;
const label = configuration?.name ?? item.name;
const viewType =
DATA_SOURCE_OR_VIEW_SUB_ITEMS[item.category].dataSourceOrView;
const dataSourceOrViewPath = `/w/${owner.sId}/data-sources/vaults/${vault.sId}/categories/${item.category}/${viewType}/${item.sId}`;

return (
Expand Down Expand Up @@ -293,10 +387,11 @@ const VaultCategoryItem = ({
{vaultDataSourceOrViews &&
vaultDataSourceOrViews.map((ds) => (
<VaultDataSourceOrViewItem
item={ds}
key={ds.sId}
owner={owner}
vault={vault}
item={ds}
viewType={categoryDetails.dataSourceOrView}
/>
))}
</Tree>
Expand Down
3 changes: 1 addition & 2 deletions front/lib/swr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
ContentNodesViewType,
ConversationMessageReactions,
ConversationType,
DataSourceOrView,
DataSourceType,
GetDataSourceOrViewContentResponseBody,
RunRunType,
Expand Down Expand Up @@ -1341,8 +1342,6 @@ export function useVaultDataSourceOrViews({
};
}

type DataSourceOrView = "data_sources" | "data_source_views";

export function useVaultDataSourceOrViewContent({
workspaceId,
vaultId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type {
DataSourceOrViewCategory,
UserType,
VaultType,
} from "@dust-tt/types";
import { isDataSourceOrViewCategory } from "@dust-tt/types";
import type { InferGetServerSidePropsType } from "next";
import type { ReactElement } from "react";

import type { VaultLayoutProps } from "@app/components/vaults/VaultLayout";
import { VaultLayout } from "@app/components/vaults/VaultLayout";
import config from "@app/lib/api/config";
import { withDefaultUserAuthRequirements } from "@app/lib/iam/session";
import { VaultResource } from "@app/lib/resources/vault_resource";

export const getServerSideProps = withDefaultUserAuthRequirements<
VaultLayoutProps & {
category: DataSourceOrViewCategory;
user: UserType;
vault: VaultType;
}
>(async (context, auth) => {
const owner = auth.getNonNullableWorkspace();
const user = auth.getNonNullableUser();
const subscription = auth.subscription();

if (!subscription) {
return {
notFound: true,
};
}

const vault = await VaultResource.fetchById(
auth,
context.query.vaultId as string
);
if (!vault) {
return {
notFound: true,
};
}

const dataSourceOrViewCategory = context.query.category;
if (
typeof dataSourceOrViewCategory !== "string" ||
!isDataSourceOrViewCategory(dataSourceOrViewCategory)
) {
return {
notFound: true,
};
}

return {
props: {
category: dataSourceOrViewCategory,
gaTrackingId: config.getGaTrackingId(),
owner,
subscription,
user,
vault: vault.toJSON(),
},
};
});

export default function Vault({
category,
vault,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<>
Manage {category} connections in vault {vault.name}
</>
);
}

Vault.getLayout = (page: ReactElement, pageProps: any) => {
return <VaultLayout pageProps={pageProps}>{page}</VaultLayout>;
};
8 changes: 8 additions & 0 deletions types/src/front/api_handlers/public/vaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export const DATA_SOURCE_OR_VIEW_CATEGORIES = [
export type DataSourceOrViewCategory =
(typeof DATA_SOURCE_OR_VIEW_CATEGORIES)[number];

export function isDataSourceOrViewCategory(
category: string
): category is DataSourceOrViewCategory {
return DATA_SOURCE_OR_VIEW_CATEGORIES.includes(
category as DataSourceOrViewCategory
);
}

export type DataSourceOrViewInfo = {
createdAt: number;
sId: string;
Expand Down
2 changes: 2 additions & 0 deletions types/src/front/data_source_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export interface DataSourceViewType {
sId: string;
updatedAt: number;
}

export type DataSourceOrView = "data_sources" | "data_source_views";

0 comments on commit 6f78071

Please sign in to comment.