From 980abad17fb1a407e86715d2c4ecc5360083b78b Mon Sep 17 00:00:00 2001 From: Jamie Rasmussen <112953339+jamie-rasmussen@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:21:01 -0600 Subject: [PATCH 1/9] chore(ui): show object version timestamp in header metadata (#3464) --- .../Home/Browse3/datasets/DatasetVersionPage.tsx | 10 +++++++++- .../Browse3/pages/ObjectsPage/ObjectVersionPage.tsx | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/datasets/DatasetVersionPage.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/datasets/DatasetVersionPage.tsx index 488f5170fe14..68112d9b904a 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/datasets/DatasetVersionPage.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/datasets/DatasetVersionPage.tsx @@ -5,6 +5,7 @@ import React, {useMemo} from 'react'; import {Icon} from '../../../../Icon'; import {LoadingDots} from '../../../../LoadingDots'; import {Tailwind} from '../../../../Tailwind'; +import {Timestamp} from '../../../../Timestamp'; import {WeaveCHTableSourceRefContext} from '../pages/CallPage/DataTableView'; import {ObjectViewerSection} from '../pages/CallPage/ObjectViewerSection'; import {objectVersionText} from '../pages/common/Links'; @@ -30,6 +31,7 @@ export const DatasetVersionPage: React.FC<{ const projectName = objectVersion.project; const objectName = objectVersion.objectId; const objectVersionIndex = objectVersion.versionIndex; + const {createdAtMs} = objectVersion; const objectVersions = useRootObjectVersions( entityName, @@ -76,7 +78,7 @@ export const DatasetVersionPage: React.FC<{ } headerContent={ -
+

Name

Version

{objectVersionIndex}

+
+

Created

+

+ +

+
{objectVersion.userId && (

Created by

diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectVersionPage.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectVersionPage.tsx index d4702509c0dc..be9cc8e69e77 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectVersionPage.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectVersionPage.tsx @@ -7,6 +7,7 @@ import {maybePluralizeWord} from '../../../../../../core/util/string'; import {Icon, IconName} from '../../../../../Icon'; import {LoadingDots} from '../../../../../LoadingDots'; import {Tailwind} from '../../../../../Tailwind'; +import {Timestamp} from '../../../../../Timestamp'; import {Tooltip} from '../../../../../Tooltip'; import {DatasetVersionPage} from '../../datasets/DatasetVersionPage'; import {NotFoundPanel} from '../../NotFoundPanel'; @@ -121,7 +122,7 @@ const ObjectVersionPageInner: React.FC<{ const projectName = objectVersion.project; const objectName = objectVersion.objectId; const objectVersionIndex = objectVersion.versionIndex; - const refExtra = objectVersion.refExtra; + const {refExtra, createdAtMs} = objectVersion; const objectVersions = useRootObjectVersions( entityName, projectName, @@ -231,7 +232,7 @@ const ObjectVersionPageInner: React.FC<{ } headerContent={ -
+

Name

@@ -266,6 +267,12 @@ const ObjectVersionPageInner: React.FC<{

Version

{objectVersionIndex}

+
+

Created

+

+ +

+
{objectVersion.userId && (

Created by

From 679f092e34e015b18fdcfe0859aa93168930c1d9 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 22 Jan 2025 16:04:10 -0500 Subject: [PATCH 2/9] perf(weave): Speed up json object parsing #3447 --- weave/trace_server_bindings/remote_http_trace_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weave/trace_server_bindings/remote_http_trace_server.py b/weave/trace_server_bindings/remote_http_trace_server.py index 966bf92a8151..ad7b86759182 100644 --- a/weave/trace_server_bindings/remote_http_trace_server.py +++ b/weave/trace_server_bindings/remote_http_trace_server.py @@ -232,7 +232,7 @@ def _generic_stream_request( r = self._generic_request_executor(url, req, stream=True) for line in r.iter_lines(): if line: - yield res_model.model_validate(json.loads(line)) + yield res_model.model_validate_json(line) @tenacity.retry( stop=tenacity.stop_after_delay(REMOTE_REQUEST_RETRY_DURATION), From f5635cf2239507fff373fe21c9e0161fafc9a62b Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 22 Jan 2025 16:04:23 -0500 Subject: [PATCH 3/9] chore(weave): Remove Ref from Object repr #3436 --- weave/flow/obj.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/weave/flow/obj.py b/weave/flow/obj.py index 2720da8d6066..4eaaa4c5b4a4 100644 --- a/weave/flow/obj.py +++ b/weave/flow/obj.py @@ -4,6 +4,7 @@ from pydantic import ( BaseModel, ConfigDict, + Field, ValidationInfo, ValidatorFunctionWrapHandler, model_validator, @@ -41,7 +42,7 @@ def setter(self: Any, value: T) -> None: class Object(BaseModel): name: Optional[str] = None description: Optional[str] = None - ref: Optional[ObjectRef] = None + ref: Optional[ObjectRef] = Field(None, repr=False) # Allow Op attributes model_config = ConfigDict( From c5e37dd24b83304cc9ba9c69ec423a2cf4f777d8 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 22 Jan 2025 16:04:35 -0500 Subject: [PATCH 4/9] chore(weave): Add tests for other expected behaviours in objectify (#3420) --- .../{test_uri_get.py => test_objectify.py} | 67 +++++++++++++++++++ weave/trace/objectify.py | 5 +- 2 files changed, 71 insertions(+), 1 deletion(-) rename tests/trace/{test_uri_get.py => test_objectify.py} (58%) diff --git a/tests/trace/test_uri_get.py b/tests/trace/test_objectify.py similarity index 58% rename from tests/trace/test_uri_get.py rename to tests/trace/test_objectify.py index 55c5595c3ac9..f57915a92269 100644 --- a/tests/trace/test_uri_get.py +++ b/tests/trace/test_objectify.py @@ -1,9 +1,18 @@ +from concurrent.futures import Future +from dataclasses import replace +from typing import TypeVar + import pytest import weave +from weave.flow.obj import Object from weave.flow.prompt.prompt import EasyPrompt +from weave.trace.objectify import register_object +from weave.trace.refs import RefWithExtra from weave.trace_server.trace_server_interface import ObjectVersionFilter, ObjQueryReq +T = TypeVar("T") + @pytest.fixture( params=[ @@ -94,3 +103,61 @@ def model(a: int) -> int: for obj in res.objs: assert obj.version_index == 0 assert obj.is_latest == 1 + + +def resolve_ref_futures(ref: RefWithExtra) -> RefWithExtra: + """This is a bit of a hack to resolve futures in an initally unsaved object's extra fields. + + Currently, the extras are still a Future and not yet replaced with the actual value. + This function resolves the futures and replaces them with the actual values. + """ + extras = ref._extra + new_extras = [] + for name, val in zip(extras[::2], extras[1::2]): + if isinstance(val, Future): + val = val.result() + new_extras.append(name) + new_extras.append(val) + ref = replace(ref, _extra=tuple(new_extras)) + return ref + + +def test_drill_down_dataset_refs_same_after_publishing(client): + ds = weave.Dataset( + name="test", + rows=[{"a": {"b": 1}}, {"a": {"b": 2}}, {"a": {"b": 3}}], + ) + ref = weave.publish(ds) + ds2 = ref.get() + ref2 = weave.publish(ds2) + ds3 = ref2.get() + + assert resolve_ref_futures(ds.rows.ref) == ds2.rows.ref + for row, row2 in zip(ds.rows, ds2.rows): + assert resolve_ref_futures(row.ref) == row2.ref + assert resolve_ref_futures(row["a"].ref) == row2["a"].ref + assert resolve_ref_futures(row["a"]["b"].ref) == row2["a"]["b"].ref + + assert ds2.ref == ds3.ref + for row2, row3 in zip(ds2.rows, ds3.rows): + assert row2.ref == row3.ref + assert row2["a"].ref == row3["a"].ref + assert row2["a"]["b"].ref == row3["a"]["b"].ref + + assert ds3.rows == [{"a": {"b": 1}}, {"a": {"b": 2}}, {"a": {"b": 3}}] + for i, row in enumerate(ds3.rows, 1): + assert row == {"a": {"b": i}} + assert row["a"] == {"b": i} + assert row["a"]["b"] == i + + +def test_registration(): + # This is a second class named Dataset. The first has already been registered + # in weave.flow.obj. This should raise an error. + + with pytest.raises(ValueError, match="Class Dataset already registered as"): + + @register_object + class Dataset(Object): + anything: str + doesnt_matter: int diff --git a/weave/trace/objectify.py b/weave/trace/objectify.py index 1cf9444391ad..d9fa26db46cd 100644 --- a/weave/trace/objectify.py +++ b/weave/trace/objectify.py @@ -19,7 +19,10 @@ def from_obj(cls, obj: WeaveObject) -> T_co: ... def register_object(cls: type[T_co]) -> type[T_co]: - _registry[cls.__name__] = cls + cls_name = cls.__name__ + if (existing_cls := _registry.get(cls_name)) is not None: + raise ValueError(f"Class {cls_name} already registered as {existing_cls}") + _registry[cls_name] = cls return cls From b267e279ac59602f16afd05c6e9d2f3074d70057 Mon Sep 17 00:00:00 2001 From: Andrew Truong Date: Wed, 22 Jan 2025 16:04:50 -0500 Subject: [PATCH 5/9] feat(weave): Allow Dataset to be constructed from Calls (#3382) --- docs/docs/guides/core-types/datasets.md | 29 +++++++++++++++++- tests/trace/test_call_object.py | 25 ++++++++++++++++ tests/trace/test_dataset.py | 21 +++++++++++++ weave/flow/dataset.py | 8 ++++- weave/trace/weave_client.py | 39 +++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tests/trace/test_call_object.py diff --git a/docs/docs/guides/core-types/datasets.md b/docs/docs/guides/core-types/datasets.md index 30e571fb8a28..3388fd9c425b 100644 --- a/docs/docs/guides/core-types/datasets.md +++ b/docs/docs/guides/core-types/datasets.md @@ -11,7 +11,7 @@ This guide will show you how to: - Download the latest version - Iterate over examples -## Sample code +## Quickstart @@ -68,3 +68,30 @@ This guide will show you how to: + +## Alternate constructors + + + + Datasets can also be constructed from common Weave objects like `list[Call]`, which is useful if you want to run an evaluation on a handful of examples. + +```python +@weave.op +def model(task: str) -> str: + return f"Now working on {task}" + +res1, call1 = model.call(task="fetch") +res2, call2 = model.call(task="parse") + +dataset = Dataset.from_calls([call1, call2]) +# Now you can use the dataset to evaluate the model, etc. +``` + + + + + ```typescript + This feature is not available in TypeScript yet. Stay tuned! + ``` + + diff --git a/tests/trace/test_call_object.py b/tests/trace/test_call_object.py new file mode 100644 index 000000000000..51d6c2d97be1 --- /dev/null +++ b/tests/trace/test_call_object.py @@ -0,0 +1,25 @@ +import weave + + +def test_call_to_dict(client): + @weave.op + def greet(name: str, age: int) -> str: + return f"Hello {name}, you are {age}!" + + _, call = greet.call("Alice", 30) + assert call.to_dict() == { + "op_name": call.op_name, + "display_name": call.display_name, + "inputs": call.inputs, + "output": call.output, + "exception": call.exception, + "summary": call.summary, + "attributes": call.attributes, + "started_at": call.started_at, + "ended_at": call.ended_at, + "deleted_at": call.deleted_at, + "id": call.id, + "parent_id": call.parent_id, + "trace_id": call.trace_id, + "project_id": call.project_id, + } diff --git a/tests/trace/test_dataset.py b/tests/trace/test_dataset.py index ff4056fdbd73..3054bef1a4c0 100644 --- a/tests/trace/test_dataset.py +++ b/tests/trace/test_dataset.py @@ -33,3 +33,24 @@ def test_pythonic_access(client): with pytest.raises(IndexError): ds[-1] + + +def test_dataset_from_calls(client): + @weave.op + def greet(name: str, age: int) -> str: + return f"Hello {name}, you are {age}!" + + greet("Alice", 30) + greet("Bob", 25) + + calls = client.get_calls() + dataset = weave.Dataset.from_calls(calls) + rows = list(dataset.rows) + + assert len(rows) == 2 + assert rows[0]["inputs"]["name"] == "Alice" + assert rows[0]["inputs"]["age"] == 30 + assert rows[0]["output"] == "Hello Alice, you are 30!" + assert rows[1]["inputs"]["name"] == "Bob" + assert rows[1]["inputs"]["age"] == 25 + assert rows[1]["output"] == "Hello Bob, you are 25!" diff --git a/weave/flow/dataset.py b/weave/flow/dataset.py index d8090d6d27a8..65d691da5ad6 100644 --- a/weave/flow/dataset.py +++ b/weave/flow/dataset.py @@ -1,4 +1,4 @@ -from collections.abc import Iterator +from collections.abc import Iterable, Iterator from typing import Any from pydantic import field_validator @@ -8,6 +8,7 @@ from weave.flow.obj import Object from weave.trace.objectify import register_object from weave.trace.vals import WeaveObject, WeaveTable +from weave.trace.weave_client import Call def short_str(obj: Any, limit: int = 25) -> str: @@ -54,6 +55,11 @@ def from_obj(cls, obj: WeaveObject) -> Self: rows=obj.rows, ) + @classmethod + def from_calls(cls, calls: Iterable[Call]) -> Self: + rows = [call.to_dict() for call in calls] + return cls(rows=rows) + @field_validator("rows", mode="before") def convert_to_table(cls, rows: Any) -> weave.Table: if not isinstance(rows, weave.Table): diff --git a/weave/trace/weave_client.py b/weave/trace/weave_client.py index c278f41c5715..f3e5ef8363f6 100644 --- a/weave/trace/weave_client.py +++ b/weave/trace/weave_client.py @@ -16,6 +16,7 @@ Callable, Generic, Protocol, + TypedDict, TypeVar, cast, overload, @@ -384,6 +385,23 @@ def map_to_refs(obj: Any) -> Any: return obj +class CallDict(TypedDict): + op_name: str + trace_id: str + project_id: str + parent_id: str | None + inputs: dict + id: str | None + output: Any + exception: str | None + summary: dict | None + display_name: str | None + attributes: dict | None + started_at: datetime.datetime | None + ended_at: datetime.datetime | None + deleted_at: datetime.datetime | None + + @dataclasses.dataclass class Call: """A Call represents a single operation that was executed as part of a trace.""" @@ -582,6 +600,27 @@ class ApplyScorerSuccess: wc._send_score_call(self, score_call, scorer_ref_uri) return apply_scorer_result + def to_dict(self) -> CallDict: + if callable(display_name := self.display_name): + display_name = "Callable Display Name (not called yet)" + + return CallDict( + op_name=self.op_name, + trace_id=self.trace_id, + project_id=self.project_id, + parent_id=self.parent_id, + inputs=self.inputs, + id=self.id, + output=self.output, + exception=self.exception, + summary=self.summary, + display_name=display_name, + attributes=self.attributes, + started_at=self.started_at, + ended_at=self.ended_at, + deleted_at=self.deleted_at, + ) + def make_client_call( entity: str, project: str, server_call: CallSchema, server: TraceServerInterface From 60cf461aa9f1fe54344d4715f5142b4e81c33d6c Mon Sep 17 00:00:00 2001 From: Griffin Tarpenning Date: Wed, 22 Jan 2025 13:15:02 -0800 Subject: [PATCH 6/9] fix(ui): links dont push to history twice (#3446) --- .../Home/Browse3/pages/common/Links.tsx | 35 +++---------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/Links.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/Links.tsx index 8d52fc8052ca..143c896f5bc4 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/Links.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/Links.tsx @@ -6,7 +6,7 @@ import { } from '@wandb/weave/common/css/color.styles'; import {WeaveObjectRef} from '@wandb/weave/react'; import React from 'react'; -import {Link as LinkComp, useHistory} from 'react-router-dom'; +import {Link as LinkComp} from 'react-router-dom'; import styled, {css} from 'styled-components'; import {TargetBlank} from '../../../../../../common/util/links'; @@ -161,7 +161,6 @@ export const ObjectVersionLink: React.FC<{ color?: string; hideVersionSuffix?: boolean; }> = props => { - const history = useHistory(); const {peekingRouter} = useWeaveflowRouteContext(); // const text = props.hideName // ? props.version @@ -177,15 +176,9 @@ export const ObjectVersionLink: React.FC<{ props.filePath, props.refExtra ); - const onClick = () => { - history.push(to); - }; return ( - + = props => { - const history = useHistory(); const {peekingRouter} = useWeaveflowRouteContext(); // const text = props.hideName // ? props.version @@ -256,14 +248,8 @@ export const OpVersionLink: React.FC<{ props.opName, props.version ); - const onClick = () => { - history.push(to); - }; return ( - + {text} @@ -276,7 +262,6 @@ export const OpVersionLink: React.FC<{ export const CallRefLink: React.FC<{ callRef: WeaveObjectRef; }> = props => { - const history = useHistory(); const {peekingRouter} = useWeaveflowRouteContext(); const callId = props.callRef.artifactName; const to = peekingRouter.callUIUrl( @@ -285,16 +270,13 @@ export const CallRefLink: React.FC<{ '', callId ); - const onClick = () => { - history.push(to); - }; if (props.callRef.weaveKind !== 'call') { return null; } return ( - + = props => { - const history = useHistory(); const {peekingRouter} = useWeaveflowRouteContext(); const opName = opNiceName(props.opName); @@ -360,15 +341,9 @@ export const CallLink: React.FC<{ showTraceTree, showFeedbackExpand ); - const onClick = () => { - history.push(to); - }; return ( - + Date: Wed, 22 Jan 2025 16:17:21 -0500 Subject: [PATCH 7/9] feat(weave): Provide helper methods to bridge pandas and weave datasets (#3384) --- docs/docs/guides/core-types/datasets.md | 54 ++++++++++++++----- tests/integrations/pandas-test/test_pandas.py | 36 +++++++++++++ weave/flow/dataset.py | 18 ++++++- 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/docs/docs/guides/core-types/datasets.md b/docs/docs/guides/core-types/datasets.md index 3388fd9c425b..eb8741dcd4fa 100644 --- a/docs/docs/guides/core-types/datasets.md +++ b/docs/docs/guides/core-types/datasets.md @@ -73,25 +73,51 @@ This guide will show you how to: - Datasets can also be constructed from common Weave objects like `list[Call]`, which is useful if you want to run an evaluation on a handful of examples. + Datasets can also be constructed from common Weave objects like `Call`s, and popular python objects like `pandas.DataFrame`s. + + + This can be useful if you want to create an example from specific examples. -```python -@weave.op -def model(task: str) -> str: - return f"Now working on {task}" + ```python + @weave.op + def model(task: str) -> str: + return f"Now working on {task}" -res1, call1 = model.call(task="fetch") -res2, call2 = model.call(task="parse") + res1, call1 = model.call(task="fetch") + res2, call2 = model.call(task="parse") -dataset = Dataset.from_calls([call1, call2]) -# Now you can use the dataset to evaluate the model, etc. -``` + dataset = Dataset.from_calls([call1, call2]) + # Now you can use the dataset to evaluate the model, etc. + ``` + + + + You can also freely convert between `Dataset`s and `pandas.DataFrame`s. + + ```python + import pandas as pd + + df = pd.DataFrame([ + {'id': '0', 'sentence': "He no likes ice cream.", 'correction': "He doesn't like ice cream."}, + {'id': '1', 'sentence': "She goed to the store.", 'correction': "She went to the store."}, + {'id': '2', 'sentence': "They plays video games all day.", 'correction': "They play video games all day."} + ]) + dataset = Dataset.from_pandas(df) + df2 = dataset.to_pandas() + + assert df.equals(df2) + ``` + + + + - - ```typescript - This feature is not available in TypeScript yet. Stay tuned! - ``` + +```typescript +This feature is not available in TypeScript yet. Stay tuned! +``` + diff --git a/tests/integrations/pandas-test/test_pandas.py b/tests/integrations/pandas-test/test_pandas.py index 9f07fb6a51bd..cf4160547744 100644 --- a/tests/integrations/pandas-test/test_pandas.py +++ b/tests/integrations/pandas-test/test_pandas.py @@ -1,6 +1,7 @@ import pandas as pd import weave +from weave import Dataset def test_op_save_with_global_df(client): @@ -20,3 +21,38 @@ def my_op(a: str) -> str: call = list(my_op.calls())[0] assert call.inputs == {"a": "d"} assert call.output == "a" + + +def test_dataset(client): + rows = [{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}] + ds = Dataset(rows=rows) + df = ds.to_pandas() + assert df["a"].tolist() == [1, 3, 5] + assert df["b"].tolist() == [2, 4, 6] + + df2 = pd.DataFrame(rows) + ds2 = Dataset.from_pandas(df2) + assert ds2.rows == rows + assert df.equals(df2) + assert ds.rows == ds2.rows + + +def test_calls_to_dataframe(client): + @weave.op + def greet(name: str, age: int) -> str: + return f"Hello, {name}! You are {age} years old." + + greet("Alice", 30) + greet("Bob", 25) + + calls = greet.calls() + dataset = Dataset.from_calls(calls) + df = dataset.to_pandas() + assert df["inputs"].tolist() == [ + {"name": "Alice", "age": 30}, + {"name": "Bob", "age": 25}, + ] + assert df["output"].tolist() == [ + "Hello, Alice! You are 30 years old.", + "Hello, Bob! You are 25 years old.", + ] diff --git a/weave/flow/dataset.py b/weave/flow/dataset.py index 65d691da5ad6..340047abcb8f 100644 --- a/weave/flow/dataset.py +++ b/weave/flow/dataset.py @@ -1,5 +1,5 @@ from collections.abc import Iterable, Iterator -from typing import Any +from typing import TYPE_CHECKING, Any from pydantic import field_validator from typing_extensions import Self @@ -10,6 +10,9 @@ from weave.trace.vals import WeaveObject, WeaveTable from weave.trace.weave_client import Call +if TYPE_CHECKING: + import pandas as pd + def short_str(obj: Any, limit: int = 25) -> str: str_val = str(obj) @@ -60,6 +63,19 @@ def from_calls(cls, calls: Iterable[Call]) -> Self: rows = [call.to_dict() for call in calls] return cls(rows=rows) + @classmethod + def from_pandas(cls, df: "pd.DataFrame") -> Self: + rows = df.to_dict(orient="records") + return cls(rows=rows) + + def to_pandas(self) -> "pd.DataFrame": + try: + import pandas as pd + except ImportError: + raise ImportError("pandas is required to use this method") + + return pd.DataFrame(self.rows) + @field_validator("rows", mode="before") def convert_to_table(cls, rows: Any) -> weave.Table: if not isinstance(rows, weave.Table): From 62ad53d5698a58080fdf1c71cc4bfa998b2b6814 Mon Sep 17 00:00:00 2001 From: Griffin Tarpenning Date: Wed, 22 Jan 2025 13:30:42 -0800 Subject: [PATCH 8/9] fix(weave): navigate properly when deleting obj/op version fullscreen (#3465) --- .../pages/ObjectsPage/ObjectDeleteButtons.tsx | 30 +++++++++++++++++-- .../Browse3/pages/OpsPage/OpVersionPage.tsx | 30 +++++++++++++++++-- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectDeleteButtons.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectDeleteButtons.tsx index 7d9aaf4cee99..f86d40c6f873 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectDeleteButtons.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ObjectsPage/ObjectDeleteButtons.tsx @@ -1,8 +1,13 @@ import {Button} from '@wandb/weave/components/Button'; import {maybePluralizeWord} from '@wandb/weave/core/util/string'; -import React, {useState} from 'react'; +import React, {useContext, useState} from 'react'; +import {useHistory} from 'react-router-dom'; -import {useClosePeek} from '../../context'; +import { + useClosePeek, + useWeaveflowCurrentRouteContext, + WeaveflowPeekContext, +} from '../../context'; import {DeleteModal} from '../common/DeleteModal'; import {useWFHooks} from '../wfReactInterface/context'; import {ObjectVersionSchema} from '../wfReactInterface/wfDataModelHooksInterface'; @@ -13,6 +18,9 @@ export const DeleteObjectButtonWithModal: React.FC<{ }> = ({objVersionSchema, overrideDisplayStr}) => { const {useObjectDeleteFunc} = useWFHooks(); const closePeek = useClosePeek(); + const {isPeeking} = useContext(WeaveflowPeekContext); + const routerContext = useWeaveflowCurrentRouteContext(); + const history = useHistory(); const {objectVersionsDelete} = useObjectDeleteFunc(); const [deleteModalOpen, setDeleteModalOpen] = useState(false); @@ -20,6 +28,22 @@ export const DeleteObjectButtonWithModal: React.FC<{ overrideDisplayStr ?? `${objVersionSchema.objectId}:v${objVersionSchema.versionIndex}`; + const onSuccess = () => { + if (isPeeking) { + closePeek(); + } else { + history.push( + routerContext.objectVersionsUIUrl( + objVersionSchema.entity, + objVersionSchema.project, + { + objectName: objVersionSchema.objectId, + } + ) + ); + } + }; + return ( <>