Skip to content

Commit

Permalink
in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
jamie-rasmussen committed Jan 10, 2025
1 parent 6841aa7 commit 52ee76a
Show file tree
Hide file tree
Showing 35 changed files with 1,968 additions and 90 deletions.
Empty file added tests/trace/test_saved_view.py
Empty file.
1 change: 1 addition & 0 deletions wb_schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ type Project implements Node {
createdAt: DateTime!
updatedAt: DateTime
id: ID!
internalId: ID!
name: String!
runs(filters: JSONString, order: String, first: Int): RunConnection
entity: Entity!
Expand Down
84 changes: 84 additions & 0 deletions weave-js/src/common/hooks/useProjectInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* This is a GraphQL approach to querying project information.
*/

import {gql, useApolloClient} from '@apollo/client';
import {useEffect, useState} from 'react';

// Note: id is the "external" ID, which changes when a project is renamed.
// internalId does not change.
const PROJECT_QUERY = gql`
query Project($entityName: String!, $projectName: String!) {
project(name: $projectName, entityName: $entityName) {
id
internalId
}
}
`;

export type ProjectInfo = {
externalIdEncoded: string;
internalIdEncoded: string;
};
type ProjectInfoResponseLoading = {
loading: true;
projectInfo: {};
};
export type MaybeProjectInfo = ProjectInfo | null;
type ProjectInfoResponseSuccess = {
loading: false;
projectInfo: MaybeProjectInfo;
};
type ProjectInfoResponse =
| ProjectInfoResponseLoading
| ProjectInfoResponseSuccess;

export const useProjectInfo = (
entityName: string,
projectName: string
): ProjectInfoResponse => {
const [response, setResponse] = useState<ProjectInfoResponse>({
loading: true,
projectInfo: {},
});

const apolloClient = useApolloClient();

useEffect(() => {
let mounted = true;
apolloClient
.query({
query: PROJECT_QUERY as any,
variables: {
entityName,
projectName,
},
})
.then(result => {
if (!mounted) {
return;
}
const projectInfo = result.data.project;
if (!projectInfo) {
// Invalid project
setResponse({
loading: false,
projectInfo: null,
});
return;
}
setResponse({
loading: false,
projectInfo: {
externalIdEncoded: projectInfo.id,
internalIdEncoded: projectInfo.internalId,
},
});
});
return () => {
mounted = false;
};
}, [apolloClient, entityName, projectName]);

return response;
};
5 changes: 3 additions & 2 deletions weave-js/src/common/hooks/useViewerInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const VIEWER_QUERY = gql`
`;

// TODO: Would be useful to add admin mode flags
type UserInfo = {
export type UserInfo = {
id: string;
username: string;
teams: string[];
Expand All @@ -35,9 +35,10 @@ type UserInfoResponseLoading = {
loading: true;
userInfo: {};
};
export type MaybeUserInfo = UserInfo | null;
type UserInfoResponseSuccess = {
loading: false;
userInfo: UserInfo | null;
userInfo: MaybeUserInfo;
};
type UserInfoResponse = UserInfoResponseLoading | UserInfoResponseSuccess;

Expand Down
132 changes: 131 additions & 1 deletion weave-js/src/components/PagePanelComponents/Home/Browse3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,20 @@ import {
useParams,
} from 'react-router-dom';

import {
ProjectInfo,
useProjectInfo,
} from '../../../common/hooks/useProjectInfo';
import {
MaybeUserInfo,
useViewerInfo,
} from '../../../common/hooks/useViewerInfo';
import {URL_BROWSE3} from '../../../urls';
// import {useLocalStorage} from '../../../util/useLocalStorage';
import {Alert} from '../../Alert';
import {Button} from '../../Button';
import {ErrorBoundary} from '../../ErrorBoundary';
import {Loading} from '../../Loading';
import {Browse2EntityPage} from './Browse2/Browse2EntityPage';
import {Browse2HomePage} from './Browse2/Browse2HomePage';
import {ComparePage} from './Browse3/compare/ComparePage';
Expand Down Expand Up @@ -59,6 +70,7 @@ import {BoardPage} from './Browse3/pages/BoardPage';
import {BoardsPage} from './Browse3/pages/BoardsPage';
import {CallPage} from './Browse3/pages/CallPage/CallPage';
import {CallsPage} from './Browse3/pages/CallsPage/CallsPage';
import {CallsPageDefaultView} from './Browse3/pages/CallsPage/CallsPageDefaultView';
import {
ALWAYS_PIN_LEFT_CALLS,
DEFAULT_FILTER_CALLS,
Expand Down Expand Up @@ -92,6 +104,7 @@ import {
WFDataModelAutoProvider,
} from './Browse3/pages/wfReactInterface/context';
import {useHasTraceServerClientContext} from './Browse3/pages/wfReactInterface/traceServerClientContext';
import {sanitizeObjectId} from './Browse3/pages/wfReactInterface/traceServerDirectClient';
import {TableRowSelectionProvider} from './TableRowSelectionContext';
import {useDrawerResize} from './useDrawerResize';

Expand Down Expand Up @@ -659,10 +672,123 @@ const CallPageBinding = () => {
);
};

// TODO(tim/weaveflow_improved_nav): Generalize this
const CallsPageBinding = () => {
const {entity, project} = useParamsDecoded<Browse3TabParams>();
const {loading: loadingUserInfo, userInfo} = useViewerInfo();
const {loading: loadingProjectInfo, projectInfo} = useProjectInfo(
entity,
project
);
if (loadingUserInfo || loadingProjectInfo) {
return <Loading />;
}
if (!projectInfo) {
return <Alert severity="error">Invalid project: {project}</Alert>;
}
return (
<CallsPageBindingWithProject
userInfo={userInfo}
projectInfo={projectInfo}
/>
);
};

type ComparePageBindingWithProjectProps = {
projectInfo: ProjectInfo;
userInfo: MaybeUserInfo;
};

const CallsPageBindingWithProject = ({
projectInfo,
userInfo,
}: ComparePageBindingWithProjectProps) => {
const query = useURLSearchParamsDict();
const {entity, project, tab} = useParamsDecoded<Browse3TabParams>();
if (!query.view) {
return (
<CallsPageDefaultView entity={entity} project={project} table={tab} />
);
}
// const {entity, project, tab} = useParamsDecoded<Browse3TabParams>();
// // Using internal ID because it doesn't change across project renames
// const storageKey = `SavedView.lastViewed.${projectInfo.internalIdEncoded}.${tab}`;
// console.log({storageKey, query});
// const [lastView, setLastView] = useLocalStorage(storageKey, 'default');
// if (lastView !== 'default' && Object.keys(query).length === 0) {
// console.log('returning CallsPageBindingLoadView');
// return (
// <CallsPageBindingLoadView
// entity={entity}
// project={project}
// view={lastView}
// />
// );
// }
// console.log('returning CallsPageBindingLoaded');
return (
<CallsPageBindingLoaded projectInfo={projectInfo} userInfo={userInfo} />
);
};

// type CallsPageBindingLoadViewProps = {
// entity: string;
// project: string;
// view: string;
// };

// Load a saved view
// const CallsPageBindingLoadView = ({
// entity,
// project,
// view,
// }: CallsPageBindingLoadViewProps) => {
// const history = useHistory();
// const getTsClient = useGetTraceServerClientContext();
// const tsClient = getTsClient();
// tsClient
// .objRead({
// project_id: projectIdFromParts({
// entity,
// project,
// }),
// object_id: view,
// digest: 'latest',
// })
// .then((res: TraceObjReadRes) => {
// const search = savedViewObjectToQuery(res.obj);
// if (search) {
// history.replace({search});
// } else {
// // TODO: saved view has no description. We don't want to
// // go into an infinite loop of requests. Should have a
// // way to report error.
// }
// });
// return <Loading />;
// };

const CallsPageBindingLoaded = ({
projectInfo,
userInfo,
}: ComparePageBindingWithProjectProps) => {
const {entity, project, tab} = useParamsDecoded<Browse3TabParams>();

const currentViewerId = userInfo ? userInfo.id : null;
const isReadonly = !currentViewerId || !userInfo?.teams.includes(entity);

const query = useURLSearchParamsDict();

// // Using internal ID because it doesn't change across project renames
// const [lastView, setLastView] = useLocalStorage(
// `SavedView.lastViewed.${projectInfo.internalIdEncoded}.${tab}`,
// 'default'
// );
const onRecordLastView = (loadedView: string) => {
// setLastView(loadedView);
};
// const view = query.view ? sanitizeObjectId(query.view) : lastView;
const view = query.view ? sanitizeObjectId(query.view) : 'default';

const initialFilter = useMemo(() => {
if (tab === 'evaluations') {
return {
Expand Down Expand Up @@ -774,8 +900,12 @@ const CallsPageBinding = () => {

return (
<CallsPage
currentViewerId={currentViewerId}
isReadonly={isReadonly}
entity={entity}
project={project}
view={view}
onRecordLastView={onRecordLastView}
initialFilter={initialFilter}
onFilterUpdate={onFilterUpdate}
columnVisibilityModel={columnVisibilityModel}
Expand Down
Loading

0 comments on commit 52ee76a

Please sign in to comment.