diff --git a/demo-project/data/session_store.db b/demo-project/data/session_store.db
index 66efab11a4..493003d0cf 100644
Binary files a/demo-project/data/session_store.db and b/demo-project/data/session_store.db differ
diff --git a/src/components/experiment-tracking/details/details.js b/src/components/experiment-tracking/details/details.js
index ef1c0cba44..6077340080 100644
--- a/src/components/experiment-tracking/details/details.js
+++ b/src/components/experiment-tracking/details/details.js
@@ -3,6 +3,8 @@ import classnames from 'classnames';
import RunMetadata from '../run-metadata';
import RunDataset from '../run-dataset';
import RunDetailsModal from '../run-details-modal';
+import RunExportModal from '../run-export-modal.js';
+import { ButtonTimeoutContextProvider } from '../../../utils/button-timeout-context';
import './details.css';
@@ -21,6 +23,8 @@ const Details = ({
sidebarVisible,
theme,
trackingDataError,
+ showRunExportModal,
+ setShowRunExportModal,
}) => {
const [runMetadataToEdit, setRunMetadataToEdit] = useState(null);
@@ -40,13 +44,22 @@ const Details = ({
return (
<>
-
+
+
+
+
{
const { updateRunDetails } = useUpdateRunDetails();
- const [exportData, setExportData] = useState([]);
const toggleBookmark = () => {
updateRunDetails({
@@ -33,10 +29,6 @@ export const ExperimentPrimaryToolbar = ({
});
};
- const updateExportData = useCallback(() => {
- setExportData(constructExportData(runMetadata, runTrackingData));
- }, [runMetadata, runTrackingData]);
-
return (
-
-
-
+
setShowRunExportModal(true)}
+ />
);
};
diff --git a/src/components/experiment-tracking/run-details-modal/run-details-modal.js b/src/components/experiment-tracking/run-details-modal/run-details-modal.js
index e01830fcca..8b9a81910e 100644
--- a/src/components/experiment-tracking/run-details-modal/run-details-modal.js
+++ b/src/components/experiment-tracking/run-details-modal/run-details-modal.js
@@ -1,6 +1,8 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useContext } from 'react';
import { useUpdateRunDetails } from '../../../apollo/mutations';
+import { ButtonTimeoutContext } from '../../../utils/button-timeout-context';
+
import Button from '../../ui/button';
import Modal from '../../ui/modal';
import Input from '../../ui/input';
@@ -15,9 +17,15 @@ const RunDetailsModal = ({
visible,
}) => {
const [valuesToUpdate, setValuesToUpdate] = useState({});
- const [hasNotInteracted, setHasNotInteracted] = useState(true);
- const [editsAreSuccessful, setEditsAreSuccessful] = useState(false);
const { updateRunDetails, error, reset } = useUpdateRunDetails();
+ const {
+ handleClick,
+ hasNotInteracted,
+ isSuccessful,
+ setHasNotInteracted,
+ setIsSuccessful,
+ showModal,
+ } = useContext(ButtonTimeoutContext);
const onApplyChanges = () => {
updateRunDetails({
@@ -25,8 +33,10 @@ const RunDetailsModal = ({
runInput: { notes: valuesToUpdate.notes, title: valuesToUpdate.title },
});
+ handleClick();
+
if (!error) {
- setEditsAreSuccessful(true);
+ setIsSuccessful(true);
}
};
@@ -39,30 +49,12 @@ const RunDetailsModal = ({
setHasNotInteracted(false);
};
- const resetState = () => {
- setHasNotInteracted(true);
- setEditsAreSuccessful(false);
- };
-
+ // only if the component is visible first, then apply isSuccessful to show or hide modal
useEffect(() => {
- let modalTimeout, resetTimeout;
-
- if (editsAreSuccessful) {
- modalTimeout = setTimeout(() => {
- setShowRunDetailsModal(false);
- }, 1500);
-
- // Delay the reset so the user can't see the button text change.
- resetTimeout = setTimeout(() => {
- resetState();
- }, 2000);
+ if (visible && isSuccessful) {
+ setShowRunDetailsModal(showModal);
}
-
- return () => {
- clearTimeout(modalTimeout);
- clearTimeout(resetTimeout);
- };
- }, [editsAreSuccessful, setShowRunDetailsModal]);
+ }, [showModal, setShowRunDetailsModal, isSuccessful, visible]);
useEffect(() => {
setValuesToUpdate({
@@ -78,8 +70,7 @@ const RunDetailsModal = ({
* the next time the modal opens.
*/
reset();
- setHasNotInteracted(true);
- }, [reset, runMetadataToEdit, visible]);
+ }, [runMetadataToEdit, visible, setHasNotInteracted, reset]);
return (
@@ -124,10 +115,10 @@ const RunDetailsModal = ({
diff --git a/src/utils/button-timeout-context.js b/src/utils/button-timeout-context.js
new file mode 100644
index 0000000000..5481336ff0
--- /dev/null
+++ b/src/utils/button-timeout-context.js
@@ -0,0 +1,54 @@
+import React, { createContext, useState } from 'react';
+
+export const ButtonTimeoutContext = createContext(null);
+
+/**
+ * Provides a way to pass different states to a button depending on whether
+ * it's successful or not.
+ * {@returns hasNotInteracted and setHasNotInteracted} these 2 are only used for modal with editable fields
+ */
+export const ButtonTimeoutContextProvider = ({ children }) => {
+ const [isSuccessful, setIsSuccessful] = useState(false);
+ const [showModal, setShowModal] = useState(false);
+ const [hasNotInteracted, setHasNotInteracted] = useState(true);
+
+ const handleClick = () => {
+ setShowModal(true);
+
+ const localStateTimeout = setTimeout(() => {
+ setIsSuccessful(true);
+ }, 500);
+
+ // so user is able to see the success message on the button first before the modal goes away
+ const modalTimeout = setTimeout(() => {
+ setShowModal(false);
+ }, 1500);
+
+ // Delay the reset so the user can't see the button text change.
+ const resetTimeout = setTimeout(() => {
+ setIsSuccessful(false);
+ setHasNotInteracted(true);
+ }, 2000);
+
+ return () => {
+ clearTimeout(localStateTimeout);
+ clearTimeout(modalTimeout);
+ clearTimeout(resetTimeout);
+ };
+ };
+
+ return (
+ setHasNotInteracted(state),
+ setIsSuccessful: (state) => setIsSuccessful(state),
+ showModal,
+ }}
+ >
+ {children}
+
+ );
+};