Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
<!doctype html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting rid of the visjs include

<link
href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css"
rel="stylesheet"
type="text/css"
/>

<script src="/wasm_exec.js"></script>

<meta charset="utf-8" />
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@
"@tanstack/react-router": "^1.119.0",
"@tanstack/react-router-devtools": "^1.119.1",
"@vercel/node": "^5.2.0",
"@xyflow/react": "^12.10.0",
"ajv": "6.12.6",
"ansi-to-html": "^0.7.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"d3-scale-chromatic": "^2.0.0",
"dagre": "^0.8.5",
"dequal": "^2.0.2",
"file-saver": "^2.0.5",
"file-select-dialog": "^1.5.4",
Expand Down Expand Up @@ -82,6 +84,7 @@
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/dagre": "^0.7.53",
"@types/file-saver": "^2.0.5",
"@types/jest": "^29.5.0",
"@types/line-column": "^1.0.0",
Expand Down
18 changes: 10 additions & 8 deletions src/components/DatastoreRelationshipEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
import { useCallback, useMemo, useState } from "react";
import useDeepCompareEffect from "use-deep-compare-effect";

import {
DeveloperError,
DeveloperError_Source,
} from "@/spicedb-common/protodefs/developer/v1/developer_pb";

import { DataStore, DataStoreItemKind } from "../services/datastore";
import { Services } from "../services/services";
import { CommentCellPrefix } from "../spicedb-common/components/relationshipeditor/columns";
import { RelationshipOrComment, parseRelationshipsAndComments } from "../spicedb-common/parsing";

import { CommentCellPrefix } from "./relationshipeditor/columns";
import {
RelationshipDatum,
relationshipToDatum,
toFullRelationshipString,
} from "../spicedb-common/components/relationshipeditor/data";
} from "./relationshipeditor/data";
import {
RelationTupleHighlight,
RelationshipEditor,
} from "../spicedb-common/components/relationshipeditor/RelationshipEditor";
import { RelationshipOrComment, parseRelationshipsAndComments } from "../spicedb-common/parsing";
import {
DeveloperError,
DeveloperError_Source,
} from "../spicedb-common/protodefs/developer/v1/developer_pb";
} from "./relationshipeditor/RelationshipEditor";

const partialRelationshipCommentPrefix = "partial relationship: ";

Expand Down
4 changes: 2 additions & 2 deletions src/components/EditorDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "react-reflex/styles.css";

import { TextRange } from "@authzed/spicedb-parser-js";
import Editor, { DiffEditor, useMonaco } from "@monaco-editor/react";
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
import { useNavigate, useLocation } from "@tanstack/react-router";
Expand All @@ -14,7 +15,6 @@ import { ScrollLocation, useCookieService } from "../services/cookieservice";
import { DataStore, DataStoreItem, DataStoreItemKind } from "../services/datastore";
import { LocalParseState } from "../services/localparse";
import { Services } from "../services/services";
import { TextRange } from "../spicedb-common/include/protobuf-parser";
import registerDSLanguage, {
DS_DARK_THEME_NAME,
DS_LANGUAGE_NAME,
Expand All @@ -31,7 +31,7 @@ import registerTupleLanguage, {
TUPLE_DARK_THEME_NAME,
TUPLE_LANGUAGE_NAME,
TUPLE_THEME_NAME,
} from "./tuplelang";
} from "./relationshipeditor/tuplelang";

export type EditorDisplayProps = {
datastore: DataStore;
Expand Down
4 changes: 3 additions & 1 deletion src/components/InlinePlayground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import LaunchIcon from "@material-ui/icons/Launch";
import clsx from "clsx";
import React, { useState } from "react";

// TODO: rename
import TenantGraph from "@/components/visualizer/TenantGraph";

import TabLabel from "../playground-ui/TabLabel";
import { useLiveCheckService } from "../services/check";
import { DataStore, DataStoreItemKind, useReadonlyDatastore } from "../services/datastore";
import { useLocalParseService } from "../services/localparse";
import { useProblemService } from "../services/problem";
import { useValidationService } from "../services/validation";
import TenantGraph from "../spicedb-common/components/graph/TenantGraph";
import { parseRelationships } from "../spicedb-common/parsing";
import { useDeveloperService } from "../spicedb-common/services/developerservice";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";

import { RelationTuple as Relationship } from "../protodefs/core/v1/core_pb";
import { RelationTuple as Relationship } from "@/spicedb-common/protodefs/core/v1/core_pb";

const useStyles = makeStyles((theme: Theme) =>
createStyles({
Expand Down
83 changes: 16 additions & 67 deletions src/components/panels/visualizer.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,20 @@
import "react-reflex/styles.css";

import { createStyles, darken, makeStyles, Theme } from "@material-ui/core/styles";
import BubbleChartIcon from "@material-ui/icons/BubbleChart";
import { useNavigate } from "@tanstack/react-router";
import { Bubbles } from "lucide-react";
import monaco from "monaco-editor";

// TODO: rename
import TenantGraph from "@/components/visualizer/TenantGraph";

import TabLabel from "../../playground-ui/TabLabel";
import { DataStoreItem, DataStoreItemKind, DataStorePaths } from "../../services/datastore";
import TenantGraph from "../../spicedb-common/components/graph/TenantGraph";
import { TextRange } from "../../spicedb-common/include/protobuf-parser";
import { DataStoreItem } from "../../services/datastore";
import { ParseRelationshipError } from "../../spicedb-common/parsing";
import { RelationTuple } from "../../spicedb-common/protodefs/core/v1/core_pb";

import { PanelProps } from "./base/common";

declare module "@tanstack/react-router" {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the history state binding, so this went away.

interface HistoryState {
range?: TextRange;
}
}

const useStyles = makeStyles((theme: Theme) =>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Styling is tailwind now

createStyles({
tenantGraphContainer: {
width: "100%",
height: "100%",
backgroundColor: theme.palette.background.default,
backgroundSize: "20px 20px",
backgroundImage: `
linear-gradient(to right, ${darken(
theme.palette.background.default,
0.1,
)} 1px, transparent 1px),
linear-gradient(to bottom, ${darken(
theme.palette.background.default,
0.1,
)} 1px, transparent 1px)
`,
},
}),
);

export function VisualizerSummary() {
return <TabLabel icon={<BubbleChartIcon />} title="System Visualization" />;
return <TabLabel icon={<Bubbles />} title="System Visualization" />;
}

function isRelationship(
Expand All @@ -52,49 +24,26 @@ function isRelationship(
}

export function VisualizerPanel({
location,
services,
dimensions,
editorPosition,
currentItem,
}: PanelProps & {
dimensions?: { width: number; height: number };
editorPosition?: monaco.Position | undefined;
currentItem?: DataStoreItem | undefined;
editorPosition?: monaco.Position;
currentItem?: DataStoreItem;
}) {
const classes = useStyles();
const navigate = useNavigate();

const handleBrowseRequested = (range?: TextRange) => {
// TODO: make this functionality use querystrings instead of history state
navigate({
to: DataStorePaths.Schema(),
state: {
range,
},
});
};

const relationships = services.localParseService.state.relationships
.map((relFound) => relFound.parsed)
.filter(isRelationship);

return (
<div className={classes.tenantGraphContainer} style={{ height: dimensions?.height ?? 0 }}>
<TenantGraph
key={location}
schema={services.localParseService.state.parsed}
relationships={relationships}
onBrowseRequested={handleBrowseRequested}
active={
editorPosition
? {
isSchema: currentItem?.kind === DataStoreItemKind.SCHEMA,
position: editorPosition,
}
: undefined
}
/>
<div
className="w-full h-full"
// NOTE: this style is to allow the reflexed pane to control the height of the container.
// Without this it doesn't render correctly, though there may be a different way
// to get the same behavior.
style={dimensions?.height ? { height: dimensions.height } : undefined}
>
<TenantGraph schema={services.localParseService.state.parsed} relationships={relationships} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
ParseRelationshipError,
parseRelationshipsWithComments,
parseRelationshipWithError,
} from "../../parsing";
import { RelationTuple as Relationship } from "../../protodefs/core/v1/core_pb";
import { useRelationshipsService } from "../../services/relationshipsservice";
} from "@/spicedb-common/parsing";
import { RelationTuple as Relationship } from "@/spicedb-common/protodefs/core/v1/core_pb";
import { useRelationshipsService } from "@/spicedb-common/services/relationshipsservice";

import {
Column,
Expand Down Expand Up @@ -174,7 +174,7 @@
// NOTE: we do not want to rerun this if the dataUpdated callback has changed (which it should
// not, ideally).
// TODO: dataUpdated is currently changing on every render because the debouncer isn't memoized.
}, [data]);

Check warning on line 177 in src/components/relationshipeditor/RelationshipEditor.tsx

View workflow job for this annotation

GitHub Actions / Run Linters and Typechecking

React Hook useEffect has a missing dependency: 'dataUpdated'. Either include it or remove the dependency array. If 'dataUpdated' changes too often, find the parent component that defines it and wrap that definition in useCallback

// relationships holds a filtered form of the grid, containing only valid relationships.
const relationships = useDeepCompareMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
RELATION_REGEX,
RESOURCE_ID_REGEX,
SUBJECT_ID_REGEX,
} from "../../parsing";
} from "@/spicedb-common/parsing";

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved these components, so I updated their imports to be non-relative


/**
* DataKind defines the different kinds of data that can be found in columns.
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "@glideapps/glide-data-grid";
import { useMemo, useRef } from "react";

import { RelationshipsService } from "../../services/relationshipsservice";
import { RelationshipsService } from "@/spicedb-common/services/relationshipsservice";

import { COLUMNS, Column, DataKind } from "./columns";
import { CommentCell, CommentCellRenderer } from "./commentcell";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { timestampDate } from "@bufbuild/protobuf/wkt";

import { RelationshipWithComments } from "../../parsing";
import { RelationTuple as Relationship } from "../../protodefs/core/v1/core_pb";
import { RelationshipWithComments } from "@/spicedb-common/parsing";
import { RelationTuple as Relationship } from "@/spicedb-common/protodefs/core/v1/core_pb";

import { COLUMNS } from "./columns";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Autocomplete, { type AutocompleteRenderInputParams } from "@material-ui/l
import { MutableRefObject, useRef } from "react";
import stc from "string-to-color";

import { RelationshipsService } from "../../services/relationshipsservice";
import { RelationshipsService } from "@/spicedb-common/services/relationshipsservice";

import { COLUMNS, Column, DataKind, DataTitle, RelationshipSection } from "./columns";
import { AnnotatedData } from "./data";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { editor, Position } from "monaco-editor";
import * as monacoEditor from "monaco-editor";

import { LocalParseState } from "../services/localparse";
import { LocalParseState } from "@/services/localparse";
import {
getCaveatDefinitions,
getRelatableDefinitions,
getStorableRelations,
getSubjectDefinitions,
StorableRelation,
SubjectDefinition,
} from "../services/semantics";
} from "@/services/semantics";

export const TUPLE_LANGUAGE_NAME = "tuple";
export const TUPLE_THEME_NAME = "tuple-theme";
Expand Down
64 changes: 64 additions & 0 deletions src/components/visualizer/CustomEdge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { BaseEdge, EdgeLabelRenderer, getBezierPath, EdgeProps, Edge } from "@xyflow/react";
import { ReactNode } from "react";

export type CustomEdgeType = Edge<{
type?: string;
relationName?: string;
relationNames?: string[];
permissionNames?: string[];
label?: ReactNode; // JSX label content
}>;

export default function CustomEdge({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style,
markerEnd,
data,
}: EdgeProps<CustomEdgeType>) {
// Calculate bezier path and label position
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
});

return (
<>
{/* Render the edge line */}
<BaseEdge id={id} path={edgePath} markerEnd={markerEnd} style={style} />

{/* Render complex label using EdgeLabelRenderer if label exists */}
{data?.label && (
<EdgeLabelRenderer>
<div
// TODO: Make this use Tailwind
style={{
position: "absolute",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to make these use tailwind instead.

transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
background: "var(--card)",
color: "var(--card-foreground)",
padding: "4px 8px",
borderRadius: "4px",
border: "1px solid var(--border)",
fontSize: "10px",
lineHeight: "1.2",
pointerEvents: "all",
}}
className="nodrag nopan"
>
{data.label}
</div>
</EdgeLabelRenderer>
)}
</>
);
}
Loading
Loading