Skip to content

Commit

Permalink
Scan through revision history, show node changes
Browse files Browse the repository at this point in the history
  • Loading branch information
abrenneke committed Aug 7, 2024
1 parent 41b9e39 commit 9639ef5
Show file tree
Hide file tree
Showing 32 changed files with 939 additions and 55 deletions.
43 changes: 41 additions & 2 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 changes: 3 additions & 2 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@
"core-js": "^3.33.1",
"csv-parse": "^5.5.2",
"csv-stringify": "^6.4.4",
"emittery": "^1.0.1",
"emittery": "^1.0.3",
"esbuild": "^0.19.5",
"eslint": "^8.52.0",
"eslint-config-react-app": "^7.0.1",
"fast-deep-equal": "^3.1.3",
"fuse.js": "^6.6.2",
"immer": "^10.0.3",
"jest-diff": "^29.7.0",
"jsonpath-plus": "^7.2.0",
"lodash-es": "^4.17.21",
"lru-cache": "^11.0.0",
Expand Down Expand Up @@ -154,7 +156,6 @@
"@types/semver": "^7.5.4",
"@types/wicg-file-system-access": "^2023.10.2",
"@typescript-eslint/eslint-plugin": "^6.9.0",
"chalk": "^5.3.0",
"enquirer": "^2.4.1",
"eslint-config-standard-with-typescript": "^39.1.1",
"eslint-plugin-import": "^2.29.0",
Expand Down
6 changes: 6 additions & 0 deletions packages/app/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
"args": true,
"cmd": "pnpm",
"sidecar": true
},
{
"name": "git",
"args": true,
"cmd": "git",
"sidecar": false
}
]
},
Expand Down
23 changes: 20 additions & 3 deletions packages/app/src/components/GraphBuilder.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type FC, useEffect, useMemo, useState, type MouseEvent } from 'react';
import { NodeCanvas } from './NodeCanvas.js';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { connectionsState, nodesByIdState, nodesState } from '../state/graph.js';
import { connectionsState, isReadOnlyGraphState, nodesByIdState, nodesState } from '../state/graph.js';
import { editingNodeState, selectedNodesState } from '../state/graphBuilder.js';
import { NodeEditorRenderer } from './NodeEditor.js';
import styled from '@emotion/styled';
Expand All @@ -22,6 +22,8 @@ import { projectState } from '../state/savedGraphs';
import { useDatasets } from '../hooks/useDatasets';
import { overlayOpenState } from '../state/ui';
import { GraphExecutionSelectorBar } from './GraphExecutionSelectorBar';
import { HistoricalGraphNotice } from './HistoricalGraphNotice';
import { NodeChangesModal, NodeChangesModalRenderer } from './NodeChangesModal';

const Container = styled.div`
position: relative;
Expand All @@ -35,14 +37,25 @@ const Container = styled.div`
.recording-border {
position: absolute;
top: 0;
top: var(--project-selector-height);
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 100;
z-index: 500;
box-shadow: inset 0 0 2px 3px var(--warning-dark);
}
.read-only-border {
position: absolute;
top: var(--project-selector-height);
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 500;
box-shadow: inset 0 0 2px 3px var(--grey-light);
}
`;

export const GraphBuilder: FC = () => {
Expand Down Expand Up @@ -123,6 +136,7 @@ export const GraphBuilder: FC = () => {
);

const overlay = useRecoilValue(overlayOpenState);
const isReadOnly = useRecoilValue(isReadOnlyGraphState);

return (
<Container onMouseDown={containerMouseDown}>
Expand All @@ -138,6 +152,7 @@ export const GraphBuilder: FC = () => {
onContextMenuItemSelected={contextMenuHandler}
/>
{loadedRecording && <div className="recording-border" />}
{isReadOnly && <div className="read-only-border" />}
<NodeEditorRenderer />
{firstNodeQuestions && firstNodeQuestions.length > 0 && (
<Button onClick={handleOpenUserInputModal} className="user-input-modal-open" appearance="primary">
Expand All @@ -146,13 +161,15 @@ export const GraphBuilder: FC = () => {
)}
{overlay === undefined && <NavigationBar />}
<GraphExecutionSelectorBar />
<HistoricalGraphNotice />
<UserInputModal
open={isUserInputModalOpen}
questions={lastQuestions}
questionsNodeId={questionsNodeId}
onSubmit={handleSubmitUserInputModal}
onClose={handleCloseUserInputModal}
/>
<NodeChangesModalRenderer />
</ErrorBoundary>
</Container>
);
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/components/GraphInfoSidebarTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { graphState } from '../state/graph.js';
import { savedGraphsState } from '../state/savedGraphs.js';
import { InlineEditableTextfield } from '@atlaskit/inline-edit';
import { type NodeGraph } from '@ironclad/rivet-core';
import { Label } from '@atlaskit/form';
import { GraphRevisions } from './GraphRevisionList';

export const GraphInfoSidebarTab: FC = () => {
const [graph, setGraph] = useRecoilState(graphState);
Expand Down Expand Up @@ -34,6 +36,8 @@ export const GraphInfoSidebarTab: FC = () => {
}
readViewFitContainerWidth
/>
<Label htmlFor="">Revisions</Label>
<GraphRevisions />
</div>
);
};
136 changes: 136 additions & 0 deletions packages/app/src/components/GraphRevisionList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { useState, type FC } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { loadedProjectState } from '../state/savedGraphs';
import { useGraphRevisions } from '../hooks/useGraphRevisions';
import { css } from '@emotion/react';
import Button from '@atlaskit/button';
import { type CalculatedRevision } from '../utils/ProjectRevisionCalculator';
import { graphState, historicalGraphState, isReadOnlyGraphState } from '../state/graph';
import { GraphId } from '@ironclad/rivet-core';

const styles = css`
.revisions {
max-height: 800px;
overflow: auto;
display: flex;
flex-direction: column;
margin-right: -12px;
margin-left: -12px;
}
.revision {
border-bottom: 1px solid var(--grey);
padding: 8px;
padding-left: 12px;
cursor: pointer;
&:hover {
background-color: var(--grey-darkish);
}
}
.hash {
border-radius: 8px;
background-color: black;
display: inline-flex;
padding: 2px 4px;
font-size: 11px;
}
.message {
font-size: 12px;
}
.loading-area {
padding: 8px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.loaded-area {
padding: 8px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
`;

export const GraphRevisions: FC = () => {
const projectState = useRecoilValue(loadedProjectState);
const [enabled, setEnabled] = useState(false);

if (!projectState.loaded || !projectState.path) {
return <div>No git history</div>;
}

if (!enabled) {
return (
<div css={styles}>
<Button onClick={() => setEnabled(true)}>Show Revisions</Button>
</div>
);
}

return (
<div css={styles}>
<GraphRevisionList />
</div>
);
};

export const GraphRevisionList: FC = () => {
const { revisions, isLoading, stop, resume, numTotalRevisions, numProcessedRevisions } = useGraphRevisions();

return (
<div css={styles}>
<div className="revisions">
{revisions.map((revision) => (
<GraphRevisionListEntry key={revision.hash} revision={revision} />
))}
{isLoading ? (
<div className="loading-area">
<div>
Loading... ({numProcessedRevisions} / {numTotalRevisions})
</div>
<Button onClick={() => stop()}>Stop Loading</Button>
</div>
) : (
<div className="loaded-area">
<span>Searched {numProcessedRevisions} revisions for changes to graph.</span>
{(numProcessedRevisions < numTotalRevisions || numTotalRevisions === 0) && (
<Button onClick={() => resume()}>Load More</Button>
)}
</div>
)}
</div>
</div>
);
};

export const GraphRevisionListEntry: FC<{
revision: CalculatedRevision;
}> = ({ revision }) => {
const currentGraphId = useRecoilValue(graphState).metadata!.id!;
const setGraph = useSetRecoilState(graphState);
const setIsReadOnlyGraph = useSetRecoilState(isReadOnlyGraphState);
const setHistoricalGraph = useSetRecoilState(historicalGraphState);

function chooseGraph() {
setGraph(revision.projectAtRevision!.graphs[currentGraphId]!);
setIsReadOnlyGraph(true);
setHistoricalGraph(revision);
}

return (
<div className="revision" onClick={chooseGraph}>
<div className="hash">
<span>{revision.hash.slice(0, 6)}</span>
</div>
<div className="message">{revision.message}</div>
</div>
);
};
Loading

0 comments on commit 9639ef5

Please sign in to comment.