diff --git a/apps/squareone/package.json b/apps/squareone/package.json
index fb6f4d82..822d86d5 100644
--- a/apps/squareone/package.json
+++ b/apps/squareone/package.json
@@ -46,6 +46,7 @@
"@reach/alert": "^0.17.0",
"@reach/menu-button": "^0.17.0",
"ajv": "^8.11.0",
+ "date-fns": "^3.6.0",
"formik": "^2.2.9",
"js-yaml": "^4.1.0",
"next": "^12.2.4",
diff --git a/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.js b/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.js
new file mode 100644
index 00000000..94869ddd
--- /dev/null
+++ b/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.js
@@ -0,0 +1,54 @@
+/*
+ * ExecStats provides a summary of the execution status and timing of the
+ * notebook execution. It also provides a button to request the recomputation
+ * of the already-executed notebook.
+ */
+
+import React from 'react';
+import styled from 'styled-components';
+import { parseISO, formatDistanceToNow } from 'date-fns';
+
+import { TimesSquareHtmlEventsContext } from '../TimesSquareHtmlEventsProvider';
+import { GhostButton } from '../Button';
+
+export default function ExecStats({}) {
+ const htmlEvent = React.useContext(TimesSquareHtmlEventsContext);
+
+ if (htmlEvent.executionStatus == 'complete') {
+ const dateFinished = parseISO(htmlEvent.dateFinished);
+ return (
+
+
+ Computed{' '}
+ {' '}
+ in {htmlEvent.executionDuration} seconds.
+
+ console.log('Recompute')}>
+ Recompute
+
+
+ );
+ }
+
+ if (htmlEvent.executionStatus == 'in_progress') {
+ return (
+
+ Computing…
+
+ );
+ }
+
+ return null;
+}
+
+const StyledContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ margin-top: 1rem;
+`;
diff --git a/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.stories.js b/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.stories.js
new file mode 100644
index 00000000..00b6a35c
--- /dev/null
+++ b/apps/squareone/src/components/TimesSquareGitHubPagePanel/ExecStats.stories.js
@@ -0,0 +1,56 @@
+import React from 'react';
+
+import { TimesSquareHtmlEventsContext } from '../TimesSquareHtmlEventsProvider';
+import ExecStats from './ExecStats';
+
+export default {
+ component: ExecStats,
+ title: 'Components/TimesSquare/ExecStats',
+ parameters: {
+ viewport: {
+ viewports: {
+ sidebar: {
+ name: 'Sidebar',
+ styles: {
+ width: '280px',
+ height: '900px',
+ },
+ },
+ },
+ },
+ defaultViewport: 'sidebar',
+ },
+};
+
+const Template = (args) => (
+
+
+
+);
+
+export const Default = Template.bind({});
+Default.args = {
+ dateSubmitted: '2021-09-01T12:00:00Z',
+ dateStarted: '2021-09-01T12:00:01Z',
+ dateFinished: '2021-09-01T12:00:10Z',
+ executionStatus: 'complete',
+ executionDuration: 10.12,
+};
+
+export const InProgressNew = Template.bind({});
+InProgressNew.args = {
+ dateSubmitted: '2021-09-01T12:00:10Z',
+ dateStarted: null,
+ dateFinished: null,
+ executionStatus: 'in_progress',
+ executionDuration: null,
+};
+
+export const InProgressExisting = Template.bind({});
+InProgressExisting.args = {
+ dateSubmitted: '2021-09-01T12:00:00Z',
+ dateStarted: '2021-09-01T12:00:01Z',
+ dateFinished: '2021-09-01T12:00:10Z',
+ executionStatus: 'in_progress',
+ executionDuration: 10.12,
+};
diff --git a/apps/squareone/src/components/TimesSquareGitHubPagePanel/TimesSquareGitHubPagePanel.js b/apps/squareone/src/components/TimesSquareGitHubPagePanel/TimesSquareGitHubPagePanel.js
index 288d0035..d8ec2a6e 100644
--- a/apps/squareone/src/components/TimesSquareGitHubPagePanel/TimesSquareGitHubPagePanel.js
+++ b/apps/squareone/src/components/TimesSquareGitHubPagePanel/TimesSquareGitHubPagePanel.js
@@ -12,14 +12,12 @@ import Error from 'next/error';
import useTimesSquarePage from '../../hooks/useTimesSquarePage';
import TimesSquareParameters from '../TimesSquareParameters';
-import { TimesSquareHtmlEventsContext } from '../TimesSquareHtmlEventsProvider';
+import ExecStats from './ExecStats';
export default function TimesSquareGitHubPagePanel({}) {
const { publicRuntimeConfig } = getConfig();
const pageData = useTimesSquarePage();
- const htmlEvent = React.useContext(TimesSquareHtmlEventsContext);
-
if (pageData.loading) {
return
Loading...
;
}
@@ -40,15 +38,8 @@ export default function TimesSquareGitHubPagePanel({}) {
)}
- {htmlEvent.executionStatus != 'complete' && (
- {htmlEvent.executionStatus}
- )}
- {htmlEvent.executionStatus == 'complete' && (
- <>
- Computed {htmlEvent.dateFinished}
- Executed in {htmlEvent.executionDuration} seconds
- >
- )}
+
+
);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4a6087e1..0fc7ff48 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -68,6 +68,9 @@ importers:
ajv:
specifier: ^8.11.0
version: 8.11.0
+ date-fns:
+ specifier: ^3.6.0
+ version: 3.6.0
formik:
specifier: ^2.2.9
version: 2.2.9(react@17.0.2)
@@ -9960,6 +9963,10 @@ packages:
resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==}
dev: true
+ /date-fns@3.6.0:
+ resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
+ dev: false
+
/debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies: