@marimo-team/islands 0.25.3-dev267 → 0.25.3-dev268
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConnectedDataExplorerComponent-C4yCN38h.js → ConnectedDataExplorerComponent-eLHPh6uu.js} +8 -8
- package/dist/{ErrorBoundary-CewXPyL5.js → ErrorBoundary-CQYAoD7X.js} +4 -4
- package/dist/{abnfDiagram-VCTEODGH-o6Ay6Q63.js → abnfDiagram-VCTEODGH-hqd0IBtX.js} +2 -2
- package/dist/{architectureDiagram-5GKGNRK7-BhiwwlVg.js → architectureDiagram-5GKGNRK7-BzLAFcc0.js} +1 -1
- package/dist/{strings-BCKpLFNU.js → assertNever-DIU3JJbt.js} +14 -14
- package/dist/{chat-ui-CbgR5ivy.js → chat-ui-BAnLgpTe.js} +17 -17
- package/dist/{chunk-IMKFNOWR-WMSMf4Nj.js → chunk-IMKFNOWR-DOeVvuyE.js} +1 -1
- package/dist/{chunk-SHT3W25Y-BRfADrzD.js → chunk-SHT3W25Y-DZoFI8wR.js} +1 -1
- package/dist/{chunk-SVP7TREG-CuK5QFre.js → chunk-SVP7TREG-CWu86PSW.js} +1 -1
- package/dist/{chunk-TICWLB2K-Bcun_jhJ.js → chunk-TICWLB2K-BrM0GoP3.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-CgWDbUDT.js → classDiagram-ZZMXUADV-DYi4V2bB.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DYmc9SFU.js → classDiagram-v2-VYDZK3BY-tN7FIk-m.js} +2 -2
- package/dist/{code-visibility-BKBl9Rh6.js → code-visibility-DcZ_RwaH.js} +44 -47
- package/dist/{common-N3Jd_6m9.js → common-BGeQilvh.js} +4866 -4857
- package/dist/{config-CmeG_Pb6.js → config-BsPruWMR.js} +2 -2
- package/dist/{createReducer-C_syF8Td.js → createReducer-DdtT_7ji.js} +1 -1
- package/dist/{cynefinDiagram-5FMLGOSQ-PPKWipjT.js → cynefinDiagram-5FMLGOSQ-D5nCnDc-.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-niRBZh--.js → dagre-GXQ25YYZ-BHkd7f_i.js} +1 -1
- package/dist/{data-grid-overlay-editor-Cp59CrqZ.js → data-grid-overlay-editor-Dc4lW4A3.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-DPiP9rot.js → diagram-S7CK7UJ4-D1ALppT2.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-B0WZuaxV.js → diagram-UQ7AKVKN-DLv0b83L.js} +1 -1
- package/dist/{diagram-VX7I27RA-Rn42WBuN.js → diagram-VX7I27RA-7XJ7J6qg.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BB93--ry.js → diagram-Z3DM3KII-7M7zbHp_.js} +1 -1
- package/dist/{dialog-BtprQCUw.js → dialog-DzCj1qQv.js} +1 -1
- package/dist/{dropdown-menu-BpImEfn3.js → dropdown-menu-CdXE15an.js} +3 -3
- package/dist/{ebnfDiagram-PWID7BFC-V4t5h6mZ.js → ebnfDiagram-PWID7BFC-DHH1qlmV.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-C1MsAKXd.js → erDiagram-RLTQ6QDP-fI_0dGef.js} +1 -1
- package/dist/{error-entries-CJGdD2ky.js → error-entries-CxN-Nq3V.js} +519 -458
- package/dist/{feedback-button-Qc1f9iPq.js → feedback-button-BqaeQcvX.js} +22 -22
- package/dist/{flowDiagram-HODETNUW-DHjeJP96.js → flowDiagram-HODETNUW-Brg9MA6i.js} +2 -2
- package/dist/{formats-gGospKWJ.js → formats-DbSvAPY-.js} +1 -1
- package/dist/{glide-data-editor-hCq3K0sd.js → glide-data-editor-CiijPXA7.js} +11 -11
- package/dist/{glide-utils-DC3sk6EX.js → glide-utils-BSw3SSHF.js} +1 -1
- package/dist/{globals-B2_uMYDY.js → globals-CpmSWKI_.js} +2 -2
- package/dist/{html-to-image-S7spRQCi.js → html-to-image-8sywF4my.js} +5120 -5117
- package/dist/{infoDiagram-27XIBGKW-Dovv6iKx.js → infoDiagram-27XIBGKW-E9e403YT.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-D2nyygsc.js → ishikawaDiagram-5VMMS53U-C-RlYDRo.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-KyVx0uTY.js → kanban-definition-UXKFOSKX-CLFl_uqK.js} +1 -1
- package/dist/main.js +5972 -6003
- package/dist/{mermaid-B-jKSwGt.js → mermaid-rd09e1JL.js} +34 -34
- package/dist/{mindmap-definition-YA3MSWOX-Bz9tKQFl.js → mindmap-definition-YA3MSWOX-BQ8TWtyB.js} +1 -1
- package/dist/{number-overlay-editor-CfNYvbdz.js → number-overlay-editor-Ft4NiAEN.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-C_qpq6Tv.js → pegDiagram-XKGWAZYB-CN8UHFPi.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-Bp9ucgI4.js → pieDiagram-E7YTZNPT-DGuJ0EBd.js} +1 -1
- package/dist/{process-output-f34bkXTm.js → process-output-Dku5POvm.js} +3 -3
- package/dist/{railroadDiagram-O6MQD6OU-tq-VEH6j.js → railroadDiagram-O6MQD6OU-BPDA8wy8.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-DW-vHadb.js → requirementDiagram-BXWQKSXE-ChzLGbGW.js} +1 -1
- package/dist/{reveal-component-CUxv-kkP.js → reveal-component-D0cfwbbl.js} +1094 -1094
- package/dist/{select-C33FVPPN.js → select-OxgozOC8.js} +1 -1
- package/dist/{sequenceDiagram-WJ2MYXX4-Dv9U9qRP.js → sequenceDiagram-WJ2MYXX4-DFX-bE6O.js} +1 -1
- package/dist/{spec-DH1lmF7Q.js → spec-oJn0RhpQ.js} +2 -2
- package/dist/{stateDiagram-D77RDMKH-DTmPQ0EB.js → stateDiagram-D77RDMKH-BR7cI3wK.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-CkCif0Iw.js → stateDiagram-v2-MP3YSRHH-oGqB5UDI.js} +2 -2
- package/dist/{static-state-BldGd99T.js → static-state-CuV6Pc3a.js} +1 -1
- package/dist/{swimlanes-42K2YHIH-21kCq6l8.js → swimlanes-42K2YHIH-DwSZl1yC.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-BpRJP6KU.js → swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js} +2 -2
- package/dist/{timeline-definition-24CTP7MA-Ckgh4lS4.js → timeline-definition-24CTP7MA-DMmP-G2O.js} +1 -1
- package/dist/{toast-DpczUryP.js → toast-DbBHmxmB.js} +1 -1
- package/dist/{useAsyncData-DsZMvNXn.js → useAsyncData-BYIAoMqn.js} +1 -1
- package/dist/{useDateFormatter-Dk_xFci4.js → useDateFormatter-ButWkdcK.js} +1 -1
- package/dist/{useDeepCompareMemoize-KMBBux8C.js → useDeepCompareMemoize-Bz0c5GN6.js} +1 -1
- package/dist/{useTheme-BZ2GGLgm.js → useTheme-DPLobSFs.js} +7 -7
- package/dist/{utils-DXkj82sK.js → utils-EBklsC5R.js} +31 -31
- package/dist/{vega-component-CF9kI6C4.js → vega-component-rxIxAAh9.js} +6 -6
- package/dist/{vennDiagram-4TSXK5OY-CDei2Bt3.js → vennDiagram-4TSXK5OY-Db8GtH1G.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-CXavT601.js → wardleyDiagram-VM6X3IG4-DmIiC3FU.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CvJhcZri.js → xychartDiagram-S5SC5T6Z-DS9OPrNq.js} +1 -1
- package/package.json +1 -1
- package/src/__mocks__/executions.ts +195 -0
- package/src/__mocks__/notebook.ts +0 -1
- package/src/__tests__/CellStatus.test.tsx +19 -20
- package/src/components/dependency-graph/minimap-content.tsx +3 -2
- package/src/components/editor/__tests__/data-attributes.test.tsx +0 -7
- package/src/components/editor/__tests__/output-persistence.test.tsx +2 -2
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +1 -0
- package/src/components/editor/actions/useCellActionButton.tsx +7 -3
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +3 -1
- package/src/components/editor/cell/CellStatus.tsx +23 -19
- package/src/components/editor/cell/RunButton.tsx +16 -6
- package/src/components/editor/cell/__tests__/useRunCells.test.ts +45 -0
- package/src/components/editor/cell/cell-context-menu.tsx +4 -1
- package/src/components/editor/cell/code/cell-editor.tsx +7 -5
- package/src/components/editor/cell/collapse.tsx +4 -0
- package/src/components/editor/cell/useRunCells.ts +18 -3
- package/src/components/editor/chrome/wrapper/sidebar.tsx +2 -4
- package/src/components/editor/header/status.tsx +4 -2
- package/src/components/editor/navigation/navigation.ts +3 -2
- package/src/components/editor/notebook-cell.tsx +82 -83
- package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +22 -16
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +12 -33
- package/src/components/editor/stdin-blocking-alert.tsx +3 -1
- package/src/components/scratchpad/scratchpad.tsx +4 -1
- package/src/components/slides/minimap.tsx +4 -2
- package/src/components/slides/reveal-component.tsx +14 -10
- package/src/components/slides/slide-cell-view.tsx +28 -24
- package/src/components/slides/slide.tsx +3 -4
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -389
- package/src/core/cells/__tests__/cell.test.ts +49 -154
- package/src/core/cells/__tests__/cells.test.ts +18 -127
- package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
- package/src/core/cells/__tests__/utils.test.ts +75 -247
- package/src/core/cells/actions.ts +5 -2
- package/src/core/cells/cell.ts +31 -133
- package/src/core/cells/cells.ts +14 -29
- package/src/core/cells/document.ts +3 -3
- package/src/core/cells/focus.ts +27 -6
- package/src/core/cells/layout.ts +1 -1
- package/src/core/cells/pending-delete-service.ts +5 -7
- package/src/core/cells/types.ts +13 -36
- package/src/core/cells/utils.ts +37 -68
- package/src/core/edit-app.tsx +2 -1
- package/src/core/executions/__tests__/atoms.test.ts +99 -0
- package/src/core/executions/__tests__/select.test.ts +268 -0
- package/src/core/executions/atoms.ts +206 -0
- package/src/core/executions/hooks.ts +31 -0
- package/src/core/executions/index.ts +31 -0
- package/src/core/executions/select.ts +175 -0
- package/src/core/export/__tests__/hooks.test.ts +0 -5
- package/src/core/islands/bootstrap.ts +4 -1
- package/src/core/islands/components/output-wrapper.tsx +5 -5
- package/src/core/kernel/handlers.ts +2 -11
- package/src/core/kernel/state.ts +0 -15
- package/src/core/lifecycle/render-policy.ts +12 -26
- package/src/core/network/__tests__/requests-lazy.test.ts +5 -5
- package/src/core/network/requests-lazy.ts +3 -3
- package/src/core/notebook/operations.ts +1 -1
- package/src/core/run-app.tsx +2 -1
- package/src/core/runtime/__tests__/adapter.test.ts +3 -3
- package/src/core/runtime/adapter.ts +4 -4
- package/src/core/session/useNotebookSession.tsx +3 -3
- package/src/core/wasm/bridge.ts +1 -1
- package/src/plugins/core/registerReactComponent.tsx +4 -13
- package/src/stories/cell-status.stories.tsx +17 -10
- package/src/stories/cell.stories.tsx +0 -31
- package/src/stories/layout/vertical/one-column.stories.tsx +0 -9
- package/src/utils/time.ts +10 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { render } from "@testing-library/react";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
5
5
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
6
|
-
import { formatElapsedTime, type
|
|
6
|
+
import { formatElapsedTime, type Milliseconds } from "@/utils/time";
|
|
7
7
|
import {
|
|
8
8
|
CellStatusComponent,
|
|
9
9
|
ElapsedTime,
|
|
@@ -76,8 +76,8 @@ describe("CellStatusComponent", () => {
|
|
|
76
76
|
status: "idle" as const,
|
|
77
77
|
interrupted: false,
|
|
78
78
|
elapsedTime: null,
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
startedAt: null,
|
|
80
|
+
blocked: false,
|
|
81
81
|
uninstantiated: false,
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -95,7 +95,7 @@ describe("CellStatusComponent", () => {
|
|
|
95
95
|
...baseProps,
|
|
96
96
|
disabled: true,
|
|
97
97
|
staleInputs: true,
|
|
98
|
-
|
|
98
|
+
startedAt: 1_704_096_000_000 as Milliseconds, // Jan 1, 2024 12:00:00
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
const { container } = render(
|
|
@@ -110,7 +110,7 @@ describe("CellStatusComponent", () => {
|
|
|
110
110
|
const props = {
|
|
111
111
|
...baseProps,
|
|
112
112
|
disabled: true,
|
|
113
|
-
|
|
113
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
const { container } = render(
|
|
@@ -124,8 +124,8 @@ describe("CellStatusComponent", () => {
|
|
|
124
124
|
test("renders disabled transitively state", () => {
|
|
125
125
|
const props = {
|
|
126
126
|
...baseProps,
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
blocked: true,
|
|
128
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
const { container } = render(
|
|
@@ -139,9 +139,9 @@ describe("CellStatusComponent", () => {
|
|
|
139
139
|
test("renders stale and disabled transitively state", () => {
|
|
140
140
|
const props = {
|
|
141
141
|
...baseProps,
|
|
142
|
-
|
|
142
|
+
blocked: true,
|
|
143
143
|
staleInputs: true,
|
|
144
|
-
|
|
144
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
145
145
|
};
|
|
146
146
|
|
|
147
147
|
const { container } = render(
|
|
@@ -156,8 +156,7 @@ describe("CellStatusComponent", () => {
|
|
|
156
156
|
const props = {
|
|
157
157
|
...baseProps,
|
|
158
158
|
status: "running" as const,
|
|
159
|
-
|
|
160
|
-
lastRunStartTimestamp: 1_704_096_000 as Seconds,
|
|
159
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
161
160
|
};
|
|
162
161
|
|
|
163
162
|
const { container } = render(
|
|
@@ -172,7 +171,7 @@ describe("CellStatusComponent", () => {
|
|
|
172
171
|
const props = {
|
|
173
172
|
...baseProps,
|
|
174
173
|
status: "queued" as const,
|
|
175
|
-
|
|
174
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
176
175
|
};
|
|
177
176
|
|
|
178
177
|
const { container } = render(
|
|
@@ -201,8 +200,8 @@ describe("CellStatusComponent", () => {
|
|
|
201
200
|
const props = {
|
|
202
201
|
...baseProps,
|
|
203
202
|
interrupted: true,
|
|
204
|
-
elapsedTime: 1500,
|
|
205
|
-
|
|
203
|
+
elapsedTime: 1500 as Milliseconds,
|
|
204
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
206
205
|
};
|
|
207
206
|
|
|
208
207
|
const { container } = render(
|
|
@@ -217,8 +216,8 @@ describe("CellStatusComponent", () => {
|
|
|
217
216
|
const props = {
|
|
218
217
|
...baseProps,
|
|
219
218
|
edited: true,
|
|
220
|
-
elapsedTime: 1500,
|
|
221
|
-
|
|
219
|
+
elapsedTime: 1500 as Milliseconds,
|
|
220
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
222
221
|
};
|
|
223
222
|
|
|
224
223
|
const { container } = render(
|
|
@@ -233,8 +232,8 @@ describe("CellStatusComponent", () => {
|
|
|
233
232
|
const props = {
|
|
234
233
|
...baseProps,
|
|
235
234
|
staleInputs: true,
|
|
236
|
-
elapsedTime: 1500,
|
|
237
|
-
|
|
235
|
+
elapsedTime: 1500 as Milliseconds,
|
|
236
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
238
237
|
};
|
|
239
238
|
|
|
240
239
|
const { container } = render(
|
|
@@ -248,8 +247,8 @@ describe("CellStatusComponent", () => {
|
|
|
248
247
|
test("renders completed run with elapsed time", () => {
|
|
249
248
|
const props = {
|
|
250
249
|
...baseProps,
|
|
251
|
-
elapsedTime: 1500,
|
|
252
|
-
|
|
250
|
+
elapsedTime: 1500 as Milliseconds,
|
|
251
|
+
startedAt: 1_704_096_000_000 as Milliseconds,
|
|
253
252
|
};
|
|
254
253
|
|
|
255
254
|
const { container } = render(
|
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
cellGraphsAtom,
|
|
8
8
|
isVariableAffectedBySelectedCell,
|
|
9
9
|
} from "@/components/editor/chrome/wrapper/minimap-state";
|
|
10
|
-
import { useCellData
|
|
10
|
+
import { useCellData } from "@/core/cells/cells";
|
|
11
11
|
import { useCellActions } from "@/core/cells/actions";
|
|
12
12
|
import { cellFocusAtom, useCellFocusActions } from "@/core/cells/focus";
|
|
13
13
|
import type { CellId } from "@/core/cells/ids";
|
|
14
14
|
import { useLayout } from "@/core/cells/layout";
|
|
15
|
+
import { useCellExecution } from "@/core/executions";
|
|
15
16
|
import { useVariables } from "@/core/variables/state";
|
|
16
17
|
import { cn } from "@/utils/cn";
|
|
17
18
|
import { extractCellPreview } from "./utils/cell-preview";
|
|
@@ -32,7 +33,7 @@ const MinimapCell: React.FC<MinimapCellProps> = (props) => {
|
|
|
32
33
|
id: props.cellId,
|
|
33
34
|
graph: graphs[props.cellId],
|
|
34
35
|
code: useCellData(props.cellId).code,
|
|
35
|
-
hasError:
|
|
36
|
+
hasError: useCellExecution(props.cellId).outcome === "error",
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
let selectedCell: undefined | { id: CellId; graph: CellGraph };
|
|
@@ -104,16 +104,9 @@ describe("Cell data attributes", () => {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
notebook.cellRuntime[cid] = createCellRuntimeState({
|
|
107
|
-
status: "idle",
|
|
108
107
|
output: null,
|
|
109
108
|
consoleOutputs: [],
|
|
110
|
-
interrupted: false,
|
|
111
|
-
errored: false,
|
|
112
|
-
stopped: false,
|
|
113
109
|
staleInputs: false,
|
|
114
|
-
runStartTimestamp: null,
|
|
115
|
-
lastRunStartTimestamp: null,
|
|
116
|
-
runElapsedTimeMs: null,
|
|
117
110
|
debuggerActive: false,
|
|
118
111
|
outline: null,
|
|
119
112
|
});
|
|
@@ -4,6 +4,7 @@ import { createStore, Provider } from "jotai";
|
|
|
4
4
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
5
5
|
import { SetupMocks } from "@/__mocks__/common";
|
|
6
6
|
import { mockDocumentModel } from "@/__mocks__/document";
|
|
7
|
+
import { MockExecutions } from "@/__mocks__/executions";
|
|
7
8
|
import { MockNotebook } from "@/__mocks__/notebook";
|
|
8
9
|
import { MockRequestClient } from "@/__mocks__/requests";
|
|
9
10
|
import { cellId } from "@/__tests__/branded";
|
|
@@ -50,7 +51,6 @@ function seedNotebook(
|
|
|
50
51
|
},
|
|
51
52
|
});
|
|
52
53
|
notebook.cellRuntime[cid] = createCellRuntimeState({
|
|
53
|
-
status: "idle",
|
|
54
54
|
output: {
|
|
55
55
|
channel: "output",
|
|
56
56
|
mimetype: "text/html",
|
|
@@ -207,8 +207,8 @@ describe("output persistence across mode changes", () => {
|
|
|
207
207
|
|
|
208
208
|
it("hides errored cells while presenting without unmounting them", () => {
|
|
209
209
|
const { store, wrapper } = createTestWrapper();
|
|
210
|
+
MockExecutions.seed(store, [MockExecutions.errored(cid)]);
|
|
210
211
|
seedNotebook(store, {
|
|
211
|
-
errored: true,
|
|
212
212
|
output: {
|
|
213
213
|
channel: "marimo-error",
|
|
214
214
|
mimetype: "application/vnd.marimo+error",
|
|
@@ -56,7 +56,8 @@ import {
|
|
|
56
56
|
appWidthAtom,
|
|
57
57
|
autoInstantiateAtom,
|
|
58
58
|
} from "@/core/config/config";
|
|
59
|
-
import type {
|
|
59
|
+
import type { CellRunStatus } from "@/core/executions";
|
|
60
|
+
import type { CellConfig } from "@/core/network/types";
|
|
60
61
|
import { canEditAtom } from "@/core/notebook";
|
|
61
62
|
import { canLinkToCell, createCellLink } from "@/utils/cell-urls";
|
|
62
63
|
import { copyToClipboard } from "@/utils/copy";
|
|
@@ -74,7 +75,9 @@ export interface CellActionButtonProps extends Pick<
|
|
|
74
75
|
"name" | "config"
|
|
75
76
|
> {
|
|
76
77
|
cellId: CellId;
|
|
77
|
-
status:
|
|
78
|
+
status: CellRunStatus;
|
|
79
|
+
/** Whether a cell it depends on is disabled. */
|
|
80
|
+
blocked: boolean;
|
|
78
81
|
hasOutput: boolean;
|
|
79
82
|
hasConsoleOutput: boolean;
|
|
80
83
|
getEditorView: () => EditorView | null;
|
|
@@ -121,6 +124,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
|
|
|
121
124
|
hasOutput,
|
|
122
125
|
hasConsoleOutput,
|
|
123
126
|
status,
|
|
127
|
+
blocked,
|
|
124
128
|
} = cell;
|
|
125
129
|
|
|
126
130
|
const toggleDisabled = () => {
|
|
@@ -155,7 +159,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
|
|
|
155
159
|
hidden:
|
|
156
160
|
status === "running" ||
|
|
157
161
|
status === "queued" ||
|
|
158
|
-
|
|
162
|
+
blocked ||
|
|
159
163
|
config.disabled,
|
|
160
164
|
redundant: true,
|
|
161
165
|
handle: () => runCell(),
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { atom, useAtomValue } from "jotai";
|
|
4
4
|
import { notebookAtom } from "@/core/cells/cells";
|
|
5
|
+
import { cellExecutionInputsAtom, cellExecutionView } from "@/core/executions";
|
|
5
6
|
import { Logger } from "@/utils/Logger";
|
|
6
7
|
import { Button } from "../../ui/button";
|
|
7
8
|
import { Kbd } from "../../ui/kbd";
|
|
@@ -10,12 +11,13 @@ import { FloatingAlert } from "./floating-alert";
|
|
|
10
11
|
// Atom to check if there is a cell with unresolved stdin
|
|
11
12
|
const hasBlockingStdinAtom = atom((get) => {
|
|
12
13
|
const notebook = get(notebookAtom);
|
|
14
|
+
const executions = get(cellExecutionInputsAtom);
|
|
13
15
|
|
|
14
16
|
// Check each cell in order
|
|
15
17
|
for (const cellId of notebook.cellIds) {
|
|
16
18
|
// Check if the cell is idle and has unresolved stdin
|
|
17
19
|
const runtime = notebook.cellRuntime[cellId];
|
|
18
|
-
if (
|
|
20
|
+
if (cellExecutionView(executions, cellId).status === "idle") {
|
|
19
21
|
const hasUnresolvedStdin = runtime.consoleOutputs.some(
|
|
20
22
|
(output) => output.channel === "stdin" && output.response === undefined,
|
|
21
23
|
);
|
|
@@ -7,24 +7,29 @@ import {
|
|
|
7
7
|
} from "lucide-react";
|
|
8
8
|
import { useDateFormatter } from "react-aria";
|
|
9
9
|
import { MultiIcon } from "@/components/icons/multi-icon";
|
|
10
|
+
import type { CellRunStatus } from "@/core/executions";
|
|
10
11
|
import { Logger } from "@/utils/Logger";
|
|
11
|
-
import type { CellRuntimeState } from "../../../core/cells/types";
|
|
12
12
|
import { useElapsedTime } from "../../../hooks/useElapsedTime";
|
|
13
13
|
import { Tooltip } from "../../ui/tooltip";
|
|
14
14
|
|
|
15
15
|
import "./cell-status.css";
|
|
16
16
|
import { formatDistanceToNow } from "date-fns";
|
|
17
|
-
import { formatElapsedTime, Time } from "@/utils/time";
|
|
17
|
+
import { formatElapsedTime, type Milliseconds, Time } from "@/utils/time";
|
|
18
18
|
|
|
19
|
-
export interface CellStatusComponentProps
|
|
20
|
-
CellRuntimeState,
|
|
21
|
-
"status" | "runStartTimestamp" | "interrupted" | "lastRunStartTimestamp"
|
|
22
|
-
> {
|
|
19
|
+
export interface CellStatusComponentProps {
|
|
23
20
|
editing: boolean;
|
|
24
21
|
edited: boolean;
|
|
25
22
|
disabled: boolean;
|
|
23
|
+
/** Whether a cell it depends on is disabled. */
|
|
24
|
+
blocked: boolean;
|
|
26
25
|
staleInputs: boolean;
|
|
27
|
-
|
|
26
|
+
status: CellRunStatus;
|
|
27
|
+
/** Whether the cell's last run was interrupted. */
|
|
28
|
+
interrupted: boolean;
|
|
29
|
+
/** How long the last run took, once it has ended. */
|
|
30
|
+
elapsedTime: Milliseconds | null;
|
|
31
|
+
/** When the current run started, or the last one, since the epoch. */
|
|
32
|
+
startedAt: Milliseconds | null;
|
|
28
33
|
uninstantiated: boolean;
|
|
29
34
|
}
|
|
30
35
|
|
|
@@ -32,20 +37,21 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
|
|
|
32
37
|
editing,
|
|
33
38
|
status,
|
|
34
39
|
disabled,
|
|
40
|
+
blocked,
|
|
35
41
|
staleInputs,
|
|
36
42
|
edited,
|
|
37
43
|
interrupted,
|
|
38
44
|
elapsedTime,
|
|
39
|
-
|
|
40
|
-
lastRunStartTimestamp,
|
|
45
|
+
startedAt,
|
|
41
46
|
uninstantiated,
|
|
42
47
|
}) => {
|
|
43
48
|
if (!editing) {
|
|
44
49
|
return null;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
const
|
|
48
|
-
|
|
52
|
+
const lastRanTime = startedAt ? (
|
|
53
|
+
<LastRanTime lastRanTime={startedAt} />
|
|
54
|
+
) : null;
|
|
49
55
|
|
|
50
56
|
// unexpected states
|
|
51
57
|
if (disabled && status === "running") {
|
|
@@ -103,7 +109,7 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
|
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
// disabled from parent
|
|
106
|
-
if (!staleInputs &&
|
|
112
|
+
if (!staleInputs && blocked) {
|
|
107
113
|
return (
|
|
108
114
|
<Tooltip
|
|
109
115
|
content={
|
|
@@ -131,7 +137,7 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
|
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
// stale from parent being disabled
|
|
134
|
-
if (staleInputs &&
|
|
140
|
+
if (staleInputs && blocked) {
|
|
135
141
|
return (
|
|
136
142
|
<Tooltip
|
|
137
143
|
content={
|
|
@@ -175,9 +181,7 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
|
|
|
175
181
|
data-testid="cell-status"
|
|
176
182
|
data-status="running"
|
|
177
183
|
>
|
|
178
|
-
<CellTimer
|
|
179
|
-
startTime={Time.fromSeconds(runStartTimestamp) || Time.now()}
|
|
180
|
-
/>
|
|
184
|
+
<CellTimer startTime={startedAt ?? Time.now().toMilliseconds()} />
|
|
181
185
|
</div>
|
|
182
186
|
</Tooltip>
|
|
183
187
|
);
|
|
@@ -307,7 +311,7 @@ export const ElapsedTime = (props: { elapsedTime: string }) => {
|
|
|
307
311
|
);
|
|
308
312
|
};
|
|
309
313
|
const LastRanTime = (props: { lastRanTime: number }) => {
|
|
310
|
-
const date = new Date(props.lastRanTime
|
|
314
|
+
const date = new Date(props.lastRanTime);
|
|
311
315
|
const today = new Date();
|
|
312
316
|
|
|
313
317
|
// Looks like HH:MM:SS.SSS AM/PM
|
|
@@ -348,7 +352,7 @@ const LastRanTime = (props: { lastRanTime: number }) => {
|
|
|
348
352
|
);
|
|
349
353
|
};
|
|
350
354
|
|
|
351
|
-
const CellTimer = (props: { startTime:
|
|
352
|
-
const time = useElapsedTime(props.startTime
|
|
355
|
+
const CellTimer = (props: { startTime: Milliseconds }) => {
|
|
356
|
+
const time = useElapsedTime(props.startTime);
|
|
353
357
|
return <span>{formatElapsedTime(time)}</span>;
|
|
354
358
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import { HardDriveDownloadIcon, PlayIcon } from "lucide-react";
|
|
3
3
|
import type { JSX } from "react";
|
|
4
|
-
import type {
|
|
4
|
+
import type { CellRunStatus } from "@/core/executions";
|
|
5
|
+
import type { CellConfig } from "@/core/network/types";
|
|
5
6
|
import {
|
|
6
7
|
getConnectionTooltip,
|
|
7
8
|
isAppInteractionDisabled,
|
|
@@ -35,20 +36,29 @@ function computeColor({
|
|
|
35
36
|
|
|
36
37
|
export const RunButton = (props: {
|
|
37
38
|
edited: boolean;
|
|
38
|
-
status:
|
|
39
|
+
status: CellRunStatus;
|
|
40
|
+
/** Whether a cell it depends on is disabled. */
|
|
41
|
+
blocked: boolean;
|
|
39
42
|
needsRun: boolean;
|
|
40
43
|
connectionState: ConnectionState;
|
|
41
44
|
config: CellConfig;
|
|
42
45
|
onClick?: () => void;
|
|
43
46
|
}): JSX.Element => {
|
|
44
|
-
const {
|
|
47
|
+
const {
|
|
48
|
+
onClick,
|
|
49
|
+
connectionState,
|
|
50
|
+
needsRun,
|
|
51
|
+
status,
|
|
52
|
+
blocked,
|
|
53
|
+
config,
|
|
54
|
+
edited,
|
|
55
|
+
} = props;
|
|
45
56
|
|
|
46
|
-
const blockedStatus = status === "disabled-transitively";
|
|
47
57
|
const loading = status === "running" || status === "queued";
|
|
48
58
|
const inactive =
|
|
49
59
|
isAppInteractionDisabled(connectionState) ||
|
|
50
60
|
loading ||
|
|
51
|
-
(!config.disabled &&
|
|
61
|
+
(!config.disabled && blocked && !edited);
|
|
52
62
|
const variant = computeColor({
|
|
53
63
|
connectionState,
|
|
54
64
|
needsRun,
|
|
@@ -69,7 +79,7 @@ export const RunButton = (props: {
|
|
|
69
79
|
</ToolbarItem>
|
|
70
80
|
);
|
|
71
81
|
}
|
|
72
|
-
if (!config.disabled &&
|
|
82
|
+
if (!config.disabled && blocked && !edited) {
|
|
73
83
|
return (
|
|
74
84
|
<ToolbarItem
|
|
75
85
|
disabled={inactive}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { MockExecutions } from "@/__mocks__/executions";
|
|
5
|
+
import { MockNotebook } from "@/__mocks__/notebook";
|
|
6
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
|
+
import {
|
|
8
|
+
cellExecutionInputsAtom,
|
|
9
|
+
cellExecutionView,
|
|
10
|
+
notebookQueuedOrRunningCountAtom,
|
|
11
|
+
} from "@/core/executions";
|
|
12
|
+
import { store } from "@/core/state/jotai";
|
|
13
|
+
import { runCells } from "../useRunCells";
|
|
14
|
+
|
|
15
|
+
const ENABLED = cellId("enabled");
|
|
16
|
+
const DISABLED = cellId("disabled");
|
|
17
|
+
|
|
18
|
+
describe("runCells", () => {
|
|
19
|
+
it("sends a disabled cell to the kernel without reading it as queued", async () => {
|
|
20
|
+
MockExecutions.seed(store, []);
|
|
21
|
+
const notebook = MockNotebook.notebookState({
|
|
22
|
+
cellData: {
|
|
23
|
+
[ENABLED]: { code: "x = 1" },
|
|
24
|
+
[DISABLED]: { code: "y = 2", config: { disabled: true } },
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const sendRun = vi.fn(async () => null);
|
|
28
|
+
|
|
29
|
+
await runCells({
|
|
30
|
+
cellIds: [ENABLED, DISABLED],
|
|
31
|
+
sendRun,
|
|
32
|
+
prepareForRun: vi.fn(),
|
|
33
|
+
notebook,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(sendRun).toHaveBeenCalledWith({
|
|
37
|
+
cellIds: [ENABLED, DISABLED],
|
|
38
|
+
codes: ["x = 1", "y = 2"],
|
|
39
|
+
});
|
|
40
|
+
const inputs = store.get(cellExecutionInputsAtom);
|
|
41
|
+
expect(cellExecutionView(inputs, ENABLED).status).toBe("queued");
|
|
42
|
+
expect(cellExecutionView(inputs, DISABLED).status).toBe("idle");
|
|
43
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(1);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -23,6 +23,7 @@ import { toast } from "@/components/ui/use-toast";
|
|
|
23
23
|
import { useCellData, useCellRuntime } from "@/core/cells/cells";
|
|
24
24
|
import { CellOutputId } from "@/core/cells/ids";
|
|
25
25
|
import { isOutputEmpty } from "@/core/cells/outputs";
|
|
26
|
+
import { useCellExecution } from "@/core/executions";
|
|
26
27
|
import { goToDefinitionWithLspFallback } from "@/core/codemirror/go-to-definition/utils";
|
|
27
28
|
import { sendToPanelManager } from "@/core/vscode/vscode-bindings";
|
|
28
29
|
import { copyImageToClipboard, copyToClipboard } from "@/utils/copy";
|
|
@@ -54,12 +55,14 @@ export const CellActionsContextMenu = ({
|
|
|
54
55
|
}: Props) => {
|
|
55
56
|
const cellData = useCellData(cellId);
|
|
56
57
|
const cellRuntime = useCellRuntime(cellId);
|
|
58
|
+
const execution = useCellExecution(cellId);
|
|
57
59
|
const actions = useCellActionButtons({
|
|
58
60
|
cell: {
|
|
59
61
|
cellId: cellId,
|
|
60
62
|
name: cellData.name,
|
|
61
63
|
config: cellData.config,
|
|
62
|
-
status:
|
|
64
|
+
status: execution.status,
|
|
65
|
+
blocked: execution.blocked,
|
|
63
66
|
hasOutput: !isOutputEmpty(cellRuntime.output),
|
|
64
67
|
hasConsoleOutput: cellRuntime.consoleOutputs.length > 0,
|
|
65
68
|
getEditorView,
|
|
@@ -19,7 +19,8 @@ import {
|
|
|
19
19
|
useNotebookDocumentEdit,
|
|
20
20
|
} from "@/core/notebook/document";
|
|
21
21
|
import { usePendingDeleteService } from "@/core/cells/pending-delete-service";
|
|
22
|
-
import type { CellData
|
|
22
|
+
import type { CellData } from "@/core/cells/types";
|
|
23
|
+
import type { CellRunStatus } from "@/core/executions";
|
|
23
24
|
import { setupCodeMirror } from "@/core/codemirror/cm";
|
|
24
25
|
import { acceptCompletionOnEnterAtom } from "@/core/codemirror/completion/accept-on-enter-atom";
|
|
25
26
|
import { editorMountScheduler } from "@/core/codemirror/editor-mount-scheduler";
|
|
@@ -54,10 +55,11 @@ import { useSplitCellCallback } from "../useSplitCell";
|
|
|
54
55
|
import { CodePlaceholder } from "./code-placeholder";
|
|
55
56
|
import { LanguageToggles } from "./language-toggle";
|
|
56
57
|
|
|
57
|
-
export interface CellEditorProps
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
export interface CellEditorProps extends Pick<
|
|
59
|
+
CellData,
|
|
60
|
+
"id" | "code" | "config"
|
|
61
|
+
> {
|
|
62
|
+
status: CellRunStatus;
|
|
61
63
|
runCell: () => void;
|
|
62
64
|
theme: Theme;
|
|
63
65
|
showPlaceholder: boolean;
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
RefreshCcw,
|
|
10
10
|
} from "lucide-react";
|
|
11
11
|
import type React from "react";
|
|
12
|
+
import { useAtomValue } from "jotai";
|
|
12
13
|
import { memo } from "react";
|
|
13
14
|
import { Toolbar } from "@/components/layout/toolbar";
|
|
14
15
|
import { Button } from "@/components/ui/button";
|
|
@@ -17,6 +18,7 @@ import { useNotebook } from "@/core/cells/cells";
|
|
|
17
18
|
import { columnOf, useLayout } from "@/core/cells/layout";
|
|
18
19
|
import type { CellId } from "@/core/cells/ids";
|
|
19
20
|
import { getDescendantsStatus } from "@/core/cells/utils";
|
|
21
|
+
import { cellExecutionInputsAtom } from "@/core/executions";
|
|
20
22
|
import { cn } from "@/utils/cn";
|
|
21
23
|
|
|
22
24
|
interface Props {
|
|
@@ -65,9 +67,11 @@ export const CollapsedCellBanner: React.FC<{
|
|
|
65
67
|
count: number;
|
|
66
68
|
}> = memo(({ onClick, count, cellId }) => {
|
|
67
69
|
const notebook = useNotebook();
|
|
70
|
+
const executions = useAtomValue(cellExecutionInputsAtom);
|
|
68
71
|
const layout = useLayout();
|
|
69
72
|
const states = getDescendantsStatus(
|
|
70
73
|
notebook,
|
|
74
|
+
executions,
|
|
71
75
|
columnOf(layout, cellId).folds.get(cellId) ?? [],
|
|
72
76
|
);
|
|
73
77
|
|
|
@@ -7,10 +7,16 @@ import { getNotebook, type NotebookState } from "@/core/cells/cells";
|
|
|
7
7
|
import { useCellActions } from "@/core/cells/actions";
|
|
8
8
|
import type { CellId } from "@/core/cells/ids";
|
|
9
9
|
import { enabledCellIds, staleCellIds } from "@/core/cells/utils";
|
|
10
|
+
import {
|
|
11
|
+
cellExecutionInputsAtom,
|
|
12
|
+
submitCells,
|
|
13
|
+
withdrawCells,
|
|
14
|
+
} from "@/core/executions";
|
|
10
15
|
import { getCurrentLanguageAdapter } from "@/core/codemirror/language/commands";
|
|
11
16
|
import { getEditorCodeAsPython } from "@/core/codemirror/language/utils";
|
|
12
17
|
import { useRequestClient } from "@/core/network/requests";
|
|
13
18
|
import type { ExecuteCellsRequest } from "@/core/network/types";
|
|
19
|
+
import { store } from "@/core/state/jotai";
|
|
14
20
|
import { Logger } from "@/utils/Logger";
|
|
15
21
|
|
|
16
22
|
export const hasRunAnyCellAtom = atom<boolean>(false);
|
|
@@ -20,7 +26,9 @@ export const hasRunAnyCellAtom = atom<boolean>(false);
|
|
|
20
26
|
*/
|
|
21
27
|
export function useRunStaleCells() {
|
|
22
28
|
const runCells = useRunCells();
|
|
23
|
-
const runStaleCells = useEvent(() =>
|
|
29
|
+
const runStaleCells = useEvent(() =>
|
|
30
|
+
runCells(staleCellIds(getNotebook(), store.get(cellExecutionInputsAtom))),
|
|
31
|
+
);
|
|
24
32
|
return runStaleCells;
|
|
25
33
|
}
|
|
26
34
|
|
|
@@ -107,9 +115,16 @@ export async function runCells({
|
|
|
107
115
|
codes.push(code);
|
|
108
116
|
prepareForRun({ cellId });
|
|
109
117
|
}
|
|
110
|
-
|
|
111
|
-
//
|
|
118
|
+
// The kernel sets a disabled cell aside without planning an execution,
|
|
119
|
+
// so a submission for it would never be superseded.
|
|
120
|
+
submitCells(
|
|
121
|
+
store,
|
|
122
|
+
cellIds.filter((cellId) => !cellData[cellId]?.config.disabled),
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// TODO(MO-8346): Submit through the host's `runtime.run`.
|
|
112
126
|
await sendRun({ cellIds: cellIds, codes: codes }).catch((error) => {
|
|
127
|
+
withdrawCells(store, cellIds);
|
|
113
128
|
Logger.error(error);
|
|
114
129
|
});
|
|
115
130
|
}
|
|
@@ -7,10 +7,8 @@ import type { PropsWithChildren } from "react";
|
|
|
7
7
|
import { useEffect, useMemo } from "react";
|
|
8
8
|
import { ReorderableList } from "@/components/ui/reorderable-list";
|
|
9
9
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
notebookQueuedOrRunningCountAtom,
|
|
13
|
-
} from "@/core/cells/cells";
|
|
10
|
+
import { cellErrorCount } from "@/core/cells/cells";
|
|
11
|
+
import { notebookQueuedOrRunningCountAtom } from "@/core/executions";
|
|
14
12
|
import { capabilitiesAtom } from "@/core/config/capabilities";
|
|
15
13
|
import { aiEnabledAtom } from "@/core/config/config";
|
|
16
14
|
import { cn } from "@/utils/cn";
|
|
@@ -5,7 +5,7 @@ import { HourglassIcon, UnlinkIcon } from "lucide-react";
|
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
7
7
|
import { notebookScrollToRunning } from "@/core/cells/actions";
|
|
8
|
-
import {
|
|
8
|
+
import { cellExecutionInputsAtom, onlyScratchRunning } from "@/core/executions";
|
|
9
9
|
import { viewStateAtom } from "@/core/mode";
|
|
10
10
|
import {
|
|
11
11
|
type ConnectionStatus,
|
|
@@ -77,7 +77,9 @@ const DisconnectedIcon: React.FC<{ onReconnect?: () => void }> = ({
|
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
const RunningIcon = () => {
|
|
80
|
-
const scratchpadOnly =
|
|
80
|
+
const scratchpadOnly = onlyScratchRunning(
|
|
81
|
+
useAtomValue(cellExecutionInputsAtom).executions,
|
|
82
|
+
);
|
|
81
83
|
const tooltip = scratchpadOnly
|
|
82
84
|
? "Scratchpad is running"
|
|
83
85
|
: "Jump to running cell";
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
visibleNeighbor,
|
|
23
23
|
} from "@/core/cells/layout";
|
|
24
24
|
import { useCellActions } from "@/core/cells/actions";
|
|
25
|
+
import { cellExecutionInputsAtom, cellExecutionView } from "@/core/executions";
|
|
25
26
|
import { useNotebookDocumentEdit } from "@/core/notebook/document";
|
|
26
27
|
import { useCellFocusActions } from "@/core/cells/focus";
|
|
27
28
|
import type { CellId } from "@/core/cells/ids";
|
|
@@ -582,9 +583,9 @@ export function useCellNavigationProps(
|
|
|
582
583
|
selectedCells.size >= 2 ? [...selectedCells] : [cellId];
|
|
583
584
|
|
|
584
585
|
// Cannot delete running cells
|
|
585
|
-
const
|
|
586
|
+
const executions = store.get(cellExecutionInputsAtom);
|
|
586
587
|
const hasRunningCell = cellIds.some((id) => {
|
|
587
|
-
const { status } =
|
|
588
|
+
const { status } = cellExecutionView(executions, id);
|
|
588
589
|
return status === "running" || status === "queued";
|
|
589
590
|
});
|
|
590
591
|
|