Skip to content

Commit

Permalink
Overhaul the explorer view (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
macjuul authored Feb 16, 2024
1 parent 95247c5 commit 8ec68ab
Show file tree
Hide file tree
Showing 35 changed files with 1,163 additions and 823 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["--cfg", "surrealdb_unstable"]
6 changes: 3 additions & 3 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h1>Contributor Covenant Code of Conduct</h1>
<h1>:purple_heart: Contributor Covenant Code of Conduct</h1>

## Our Pledge

Expand Down Expand Up @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by contacting the project team at info@surrealdb.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by contacting the community team at community@surrealdb.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The community team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

Expand All @@ -50,4 +50,4 @@ Thank you for helping make this a welcoming and friendly community for everyone!

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html). For answers to common questions about this code of conduct, see [FAQs](https://www.contributor-covenant.org/faq).
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html). For answers to common questions about this code of conduct, see [FAQs](https://www.contributor-covenant.org/faq).
229 changes: 200 additions & 29 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Security Policy

## Reporting a Vulnerability

We take the security of SurrealDB code, software, and cloud platform very
seriously. If you believe you have found a security vulnerability in
SurrealDB, we encourage you to let us know right away. We will investigate
all legitimate reports and do our best to quickly fix the problem.

Please report any issues or vulnerabilities to [email protected],
instead of posting a public issue in GitHub. Please include the version
identifier, by running `surrealdb version` on the command-line, and
details on how the vulnerability can be exploited.
1 change: 1 addition & 0 deletions src-embed/Cargo.lock

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

2 changes: 1 addition & 1 deletion src-embed/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4.37"
serde-wasm-bindgen = "0.6.0"
concat-string = "1.0.1"
surrealdb = { version = "1.2.0", features = ["kv-mem", "kv-indxdb"], package = "surrealdb" }
surrealdb = { version = "1.2.0", features = ["kv-mem", "kv-indxdb", "sql2", "jwks"], package = "surrealdb" }
regex = "1.9.5"
serde_json = "1.0"
tokio = { version = "1", features = ["time"] }
Expand Down
15 changes: 9 additions & 6 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ErrorBoundary, FallbackProps } from "react-error-boundary";
import { MANTINE_THEME } from "~/util/mantine";
import { useColorScheme, useIsLight } from "~/hooks/theme";
import { ContextMenuProvider } from "mantine-contextmenu";
import { InspectorProvider } from "~/providers/Inspector";

export function App() {
const { toggleWindowPinned, setWindowScale, setEditorScale } = useConfigStore.getState();
Expand Down Expand Up @@ -77,12 +78,14 @@ export function App() {
shadow={isLight ? "xs" : "0 6px 12px 2px rgba(0, 0, 0, 0.25)"}
submenuDelay={250}
>
<ErrorBoundary
FallbackComponent={AppErrorHandler}
onReset={location.reload}
>
<Scaffold />
</ErrorBoundary>
<InspectorProvider>
<ErrorBoundary
FallbackComponent={AppErrorHandler}
onReset={location.reload}
>
<Scaffold />
</ErrorBoundary>
</InspectorProvider>
</ContextMenuProvider>

<Transition
Expand Down
15 changes: 5 additions & 10 deletions src/components/DataTable/datatypes.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import dayjs from "dayjs";
import { Group, HoverCard, Stack, Text } from "@mantine/core";
import { mdiCheck, mdiClockOutline, mdiClose } from "@mdi/js";
import dayjs from "dayjs";
import { ReactNode } from "react";
import { OpenFn } from "~/types";
import { TRUNCATE_STYLE } from "~/util/helpers";
import { Icon } from "../Icon";
import { RecordLink } from "../RecordLink";
Expand All @@ -17,7 +16,6 @@ export interface DataCellType {

export interface DataCellProps {
value: any;
openRecord?: OpenFn;
}

// ----- Data Cell Types -----
Expand Down Expand Up @@ -54,7 +52,7 @@ function NumberCell(props: DataCellProps) {
}

function ThingCell(props: DataCellProps) {
return <RecordLink value={props.value} onRecordClick={props.openRecord} />;
return <RecordLink value={props.value} />;
}

function DateTimeCell(props: DataCellProps) {
Expand Down Expand Up @@ -89,7 +87,7 @@ function ArrayCell(props: DataCellProps) {
<Group wrap="nowrap">
<span style={{ opacity: 0.5 }}>#{i + 1}</span>
<div key={i} style={TRUNCATE_STYLE}>
{renderDataCell(item, props.openRecord)}
{renderDataCell(item)}
</div>
</Group>
))}
Expand Down Expand Up @@ -155,14 +153,11 @@ const DataCellTypes = [
},
];

export function renderDataCell(value: any, openRecord?: OpenFn): ReactNode {
export function renderDataCell(value: any): ReactNode {
for (const type of DataCellTypes) {
// eslint-disable-next-line unicorn/prefer-regexp-test
if (type.match(value)) {
return type.component({
value,
openRecord,
});
return type.component({ value });
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/components/DataTable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import classes from "./style.module.scss";
import { Box, Text, useMantineTheme } from "@mantine/core";
import { Box, Text } from "@mantine/core";
import { ScrollArea, Table } from "@mantine/core";
import { useMemo } from "react";
import { renderDataCell } from "./datatypes";
import { OpenFn, ColumnSort } from "~/types";
import { ColumnSort } from "~/types";
import { useIsLight } from "~/hooks/theme";
import { useStable } from "~/hooks/stable";
import { Icon } from "../Icon";
import { mdiChevronDown, mdiChevronUp } from "@mdi/js";
import { alphabetical, isObject } from "radash";
import { useInspector } from "~/providers/Inspector";

function isRenderable(value: any) {
return Array.isArray(value) && value.every((v) => isObject(v));
Expand All @@ -18,15 +19,13 @@ interface DataTableProps {
data: any;
active?: string | null;
sorting?: ColumnSort | null;
openRecord?: OpenFn;
headers?: string[];
onSortingChange?: (order: ColumnSort | null) => void;
onRowClick?: (value: any) => void;
}

export function DataTable({ data, active, sorting, openRecord, headers, onSortingChange, onRowClick }: DataTableProps) {
const theme = useMantineTheme();
export function DataTable({ data, active, sorting, headers, onSortingChange }: DataTableProps) {
const isLight = useIsLight();
const { inspect } = useInspector();

const handleSortClick = useStable((col: string) => {
if (!onSortingChange) return;
Expand Down Expand Up @@ -112,7 +111,7 @@ export function DataTable({ data, active, sorting, openRecord, headers, onSortin

return (
<Box key={j} component="td" className={classes.tableValue} h={37}>
{renderDataCell(cellValue, openRecord)}
{renderDataCell(cellValue)}
</Box>
);
});
Expand All @@ -123,7 +122,7 @@ export function DataTable({ data, active, sorting, openRecord, headers, onSortin
<Box
key={i}
component="tr"
onClick={() => onRowClick?.(value)}
onClick={() => value.id && inspect(value.id)}
style={{
backgroundColor: `${isActive ? "var(--mantine-color-light-6)" : undefined} !important`,
}}
Expand Down
14 changes: 8 additions & 6 deletions src/components/RecordLink/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { Group, Text } from "@mantine/core";
import { mdiArrowTopRight } from "@mdi/js";
import { ComponentPropsWithoutRef, MouseEvent } from "react";
import { useStable } from "~/hooks/stable";
import { OpenFn } from "~/types";
import { Icon } from "../Icon";
import { useInspector } from "~/providers/Inspector";

export interface RecordLinkProps extends ComponentPropsWithoutRef<"div"> {
value: string;
onRecordClick?: OpenFn;
}

export function RecordLink({ value, onRecordClick, ...rest }: RecordLinkProps) {
export function RecordLink({ value, ...rest }: RecordLinkProps) {
const { inspect } = useInspector();

const handleOpen = useStable((e: MouseEvent) => {
onRecordClick?.(value);
e.stopPropagation();
inspect(value);
});

return (
Expand All @@ -24,11 +25,12 @@ export function RecordLink({ value, onRecordClick, ...rest }: RecordLinkProps) {
gap={0}
onClick={handleOpen}
style={{
cursor: onRecordClick ? "pointer" : undefined,
cursor: "pointer"
}}
>
<Text
ff="JetBrains Mono"
fw={600}
style={{
whiteSpace: "nowrap",
overflow: "hidden",
Expand All @@ -37,7 +39,7 @@ export function RecordLink({ value, onRecordClick, ...rest }: RecordLinkProps) {
}}>
{value}
</Text>
{onRecordClick && <Icon path={mdiArrowTopRight} right />}
<Icon path={mdiArrowTopRight} right />
</Group>
);
}
11 changes: 6 additions & 5 deletions src/components/SaveBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classes from "./style.module.scss";
import { Button, Group, Notification, Portal } from "@mantine/core";
import { Button, Group, GroupProps, Notification, Portal } from "@mantine/core";
import { mdiCheck, mdiInformationOutline } from "@mdi/js";
import { Icon } from "../Icon";
import { SaveableHandle } from "~/hooks/save";
Expand All @@ -11,6 +11,7 @@ import { clsx } from "clsx";
export interface SaveBoxProps {
handle: SaveableHandle<any>;
inline?: boolean;
inlineProps?: GroupProps;
position?: "left" | "center" | "right";
saveText?: ReactNode;
revertText?: ReactNode;
Expand All @@ -20,11 +21,12 @@ export interface SaveBoxProps {
* Used to present the managed state of a `useSaveable` hook
* in the form of a save box.
*/
export function SaveBox({ handle, inline, position, saveText, revertText }: SaveBoxProps) {
export function SaveBox({ handle, inline, inlineProps, position, saveText, revertText }: SaveBoxProps) {

const saveButton = (
<Button
rightSection={<Icon path={mdiCheck} size="md" />}
variant="gradient"
loading={handle.isSaving}
disabled={!handle.isSaveable}
onClick={handle.save}
Expand All @@ -35,9 +37,8 @@ export function SaveBox({ handle, inline, position, saveText, revertText }: Save

const revertButton = (
<Button
disabled={!handle.isSaveable}
onClick={handle.revert}
color="dark.4"
color="slate"
>
{revertText ?? 'Revert'}
</Button>
Expand All @@ -46,7 +47,7 @@ export function SaveBox({ handle, inline, position, saveText, revertText }: Save

if (inline) {
return (
<Group gap={10} align="center" justify="apart">
<Group gap={10} align="center" justify="apart" {...inlineProps}>
{revertButton}
{saveButton}
</Group>
Expand Down
6 changes: 5 additions & 1 deletion src/components/Scaffold/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const PROTOCOLS: Selectable<Protocol>[] = [
{ label: "HTTPS", value: "https" },
{ label: "WS", value: "ws" },
{ label: "WSS", value: "wss" },
{ label: "Memory", value: "mem" },
// { label: "IndexDB", value: "idxdb" },
];

Expand Down Expand Up @@ -134,6 +135,8 @@ export function ConnectionEditor() {
}
}, [opened]);

const isMemory = details.connection.protocol === "mem";

return (
<Modal
opened={opened}
Expand Down Expand Up @@ -167,9 +170,10 @@ export function ConnectionEditor() {
/>
<TextInput
flex={1}
placeholder="localhost:8000"
value={details.connection.hostname}
onPaste={handleHostnamePaste}
disabled={isMemory}
placeholder={isMemory ? "Not applicable" : "localhost:8000"}
onChange={(e) =>
setDetails((draft) => {
draft.connection.hostname = e.target.value;
Expand Down
25 changes: 20 additions & 5 deletions src/components/Scaffold/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ import { AuthenticationView } from "~/views/authentication/AuthenticationView";
import { LiveView } from "~/views/live/LiveView";
import { useConfigStore } from "~/stores/config";
import { useInterfaceStore } from "~/stores/interface";
import { VIEW_MODES } from "~/constants";
import { SANDBOX, VIEW_MODES } from "~/constants";
import { updateTitle } from "~/util/helpers";
import { Icon } from "../Icon";
import { Spacer } from "../Spacer";
import { mdiCog } from "@mdi/js";
import { Settings } from "../Settings";
import { useIsLight } from "~/hooks/theme";
import { themeColor } from "~/util/mantine";
import { surrealIcon } from "~/util/icons";

const PORTAL_ATTRS = {
attributes: {
Expand Down Expand Up @@ -87,7 +88,7 @@ export function Scaffold() {

// TODO Implement bottom console drawer

const { setActiveView } = useConfigStore.getState();
const { setActiveView, setActiveConnection } = useConfigStore.getState();
const { openConnectionCreator } = useInterfaceStore.getState();

const activeConnection = useConfigStore((s) => s.activeConnection);
Expand All @@ -114,6 +115,10 @@ export function Scaffold() {
setActiveView(id);
});

const openSandbox = useStable(() => {
setActiveConnection(SANDBOX);
});

return (
<div
className={classes.root}
Expand Down Expand Up @@ -196,9 +201,19 @@ export function Scaffold() {
Open or create a new connection to continue
</Text>
<Center mt="lg">
<Button size="xs" onClick={openConnectionCreator}>
Create connection
</Button>
<Stack>
<Button size="xs" onClick={openConnectionCreator}>
Create connection
</Button>
<Button
size="xs"
variant="light"
onClick={openSandbox}
leftSection={<Icon path={surrealIcon} color="surreal" />}
>
Open the sandbox
</Button>
</Stack>
</Center>
</div>
</Center>
Expand Down
6 changes: 0 additions & 6 deletions src/components/Toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { Spacer } from "../Spacer";
import { ViewMode } from "~/types";
import { adapter } from "~/adapter";
import { useConnection } from "~/hooks/connection";
import { Exporter } from "./Exporter";
import { useConfigStore } from "~/stores/config";
import { Importer } from "./Importer";
import { closeConnection, openConnection } from "~/database";
import { useDatabaseStore } from "~/stores/database";
import { Connections } from "./connections";
Expand Down Expand Up @@ -125,10 +123,6 @@ export function Toolbar(props: ToolbarProps) {
/>
)}

<Importer />

<Exporter />

<Modal
opened={!!editingTab}
onClose={closeEditingTab}
Expand Down
Loading

0 comments on commit 8ec68ab

Please sign in to comment.