Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Canvas: GridStack Layout #6325

Closed
wants to merge 57 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
21d15b2
12 cols in cavnas, fix new spawn width
lovincyrus Dec 12, 2024
caf695c
fix deleting from dashboard
lovincyrus Dec 12, 2024
b3cfe6c
handy button to insert new markdown component
lovincyrus Dec 12, 2024
2cc25d5
update index for last inserted component
lovincyrus Dec 12, 2024
5589760
remove unused grid lines
lovincyrus Dec 12, 2024
38c2ac6
comment out squares from the resize handle
lovincyrus Dec 12, 2024
b8d3042
clean up lingering
lovincyrus Dec 12, 2024
0335e6f
remove showGrid, grid toggle
lovincyrus Dec 18, 2024
eb185c8
initial gridstack
lovincyrus Dec 18, 2024
dcb60d9
grid stack item
lovincyrus Dec 19, 2024
06fb886
static grid in preview
lovincyrus Dec 19, 2024
ac290e9
canvas bg
lovincyrus Dec 19, 2024
c4bc05b
tweak grid opt
lovincyrus Dec 19, 2024
0483b95
clean up
lovincyrus Dec 19, 2024
aa13beb
centralize grid stack manager
lovincyrus Dec 19, 2024
7405fc4
clean up
lovincyrus Dec 19, 2024
4d922e7
rename canvas dashboard wrapper
lovincyrus Dec 19, 2024
f613adf
use preview element in stack item
lovincyrus Dec 19, 2024
3fbbba7
apply component to embed
lovincyrus Dec 19, 2024
9480b03
encapsulate grid stack item for clarity
lovincyrus Dec 19, 2024
2936605
fix w, h of component when wrapped in grid stack item
lovincyrus Dec 19, 2024
34800d8
track resize events from gridstack
lovincyrus Dec 19, 2024
3675bfa
wip
lovincyrus Dec 19, 2024
85559ab
rename, clean up
lovincyrus Dec 19, 2024
f6855ff
fix initialized gridstack
lovincyrus Dec 19, 2024
8318a7f
clean up
lovincyrus Dec 19, 2024
3ffc99f
before resize stop
lovincyrus Dec 19, 2024
8a7b98e
remove grid stack manager
lovincyrus Dec 19, 2024
818cf07
update on dragstop and resizestop
lovincyrus Dec 20, 2024
247432a
fix selected index in preview elemenet
lovincyrus Dec 20, 2024
ccd73bd
clean up, use x, y, width, height when dispatching events
lovincyrus Dec 20, 2024
5cb4153
clean up
lovincyrus Dec 20, 2024
2bc7d82
logs, wip
lovincyrus Dec 20, 2024
fad4dae
data-highlight
lovincyrus Dec 20, 2024
a15a0ad
expose grid to parent
lovincyrus Dec 20, 2024
0f05695
pointerenter, pointerleave
lovincyrus Dec 21, 2024
9815edb
remove pointer events to preview element
lovincyrus Dec 21, 2024
3360597
fix
lovincyrus Dec 21, 2024
65adabc
remove unused columns, gap from spec
lovincyrus Dec 21, 2024
bdb5d55
options
lovincyrus Dec 21, 2024
267a850
centralize gridstack to canvas store
lovincyrus Dec 21, 2024
7e91e93
click event listener to set selected index
lovincyrus Dec 21, 2024
804a436
remove unused mousedown on preview element
lovincyrus Dec 21, 2024
413ba77
rebase fix
lovincyrus Dec 22, 2024
c2eb705
remove unused
lovincyrus Dec 22, 2024
7969a45
lint
lovincyrus Dec 22, 2024
1c5203d
use pointerdown for selecting component
lovincyrus Dec 22, 2024
288d8f4
lint
lovincyrus Dec 22, 2024
40250eb
remove columns, gap from canvas embed, lint
lovincyrus Dec 22, 2024
6645ae8
lint unused
lovincyrus Dec 22, 2024
da34fbb
add embed to svelte grid stack, disable data-highlight
lovincyrus Dec 22, 2024
8b1de08
centralize grid stack options
lovincyrus Dec 22, 2024
93f6465
change default size, logs, clean up
lovincyrus Dec 22, 2024
79a1a2a
comments
lovincyrus Dec 23, 2024
e1b0ce7
style tweak
lovincyrus Dec 23, 2024
ff7a325
disable auto position
lovincyrus Dec 23, 2024
19e5483
add size full to grid stack item content item
lovincyrus Dec 23, 2024
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
18 changes: 18 additions & 0 deletions package-lock.json

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

7 changes: 2 additions & 5 deletions web-admin/src/features/embeds/CanvasEmbed.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@
export let instanceId: string;
export let canvasName: string;

// TODO: Remove later
let columns = 20;
let gap = 1;
$: canvasQuery = useResource(instanceId, canvasName, ResourceKind.Canvas);

$: canvas = $canvasQuery.data?.canvas.spec;

$: ({ items = [] } = canvas || { items: [], columns: 24, gap: 2 });
$: ({ items = [] } = canvas || { items: [] });
</script>

<CanvasDashboardEmbed {columns} {items} {gap} />
<CanvasDashboardEmbed {items} />
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@

$: canvas = $canvasQuery.data?.canvas.spec;

// TODO: Remove later
let columns = 20;
let gap = 1;
$: ({ items = [] } = canvas || { items: [], columns: 24, gap: 2 });
$: ({ items = [] } = canvas || { items: [] });
</script>

<CanvasDashboardEmbed {columns} {items} {gap} />
<CanvasDashboardEmbed {items} />
1 change: 1 addition & 0 deletions web-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"d3-shape": "^3.1.0",
"d3-time-format": "^4.1.0",
"dompurify": "^3.1.0",
"gridstack": "^11.1.2",
"jsdom": "^23.0.1",
"json-schema": "^0.4.0",
"lucide-svelte": "^0.298.0",
Expand Down
40 changes: 20 additions & 20 deletions web-common/src/features/canvas/Canvas.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script lang="ts">
import CanvasDashboardPreview from "@rilldata/web-common/features/canvas/CanvasDashboardPreview.svelte";
import { getCanvasStateManagers } from "@rilldata/web-common/features/canvas/state-managers/state-managers";
import type { Vector } from "@rilldata/web-common/features/canvas/types";
import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact";
import type { V1CanvasSpec } from "@rilldata/web-common/runtime-client";
import { parseDocument } from "yaml";
Expand All @@ -11,12 +10,6 @@
const { canvasStore, validSpecStore } = getCanvasStateManagers();
$: selectedIndex = $canvasStore?.selectedComponentIndex;

let showGrid = true;

// TODO: Remove later when we move to new tiling system
const columns = 24;
const gap = 1;

let spec: V1CanvasSpec = {
items: [],
};
Expand All @@ -33,16 +26,19 @@

$: ({ items = [] } = spec);

async function handleDeleteEvent(
async function handleDelete(
e: CustomEvent<{
index: number;
}>,
) {
console.log("Canvas handleComponentDelete");
if (!e.detail.index) return;
await deleteComponent(e.detail.index);
}

async function deleteComponent(index: number) {
console.log("Canvas deleteComponent");

const parsedDocument = parseDocument(
$editorContent ?? $remoteContent ?? "",
);
Expand All @@ -51,27 +47,34 @@
if (!items) return;
items.delete(index);
updateEditorContent(parsedDocument.toString(), true);
// updateLocalContent(parsedDocument.toString(), true);
// FIXME: need to rerender gridstack after node removal
if ($autoSave) await updateComponentFile();
}

async function handlePreviewUpdate(
async function handleUpdate(
e: CustomEvent<{
index: number;
position: Vector;
dimensions: Vector;
x: number;
y: number;
w: number;
h: number;
}>,
) {
console.log("handlePreviewUpdate: ", e.detail);

const parsedDocument = parseDocument(
$editorContent ?? $remoteContent ?? "",
);
const items = parsedDocument.get("items") as any;

const node = items.get(e.detail.index);

node.set("width", e.detail.dimensions[0]);
node.set("height", e.detail.dimensions[1]);
node.set("x", e.detail.position[0]);
node.set("y", e.detail.position[1]);
// NOTE: V1CanvasItem uses width, height, x, y
node.set("width", e.detail.w);
node.set("height", e.detail.h);
node.set("x", e.detail.x);
node.set("y", e.detail.y);

updateEditorContent(parsedDocument.toString(), true);

Expand All @@ -80,13 +83,10 @@
</script>

<CanvasDashboardPreview
{gap}
{items}
{columns}
{showGrid}
bind:selectedIndex
on:update={handlePreviewUpdate}
on:delete={handleDeleteEvent}
on:update={handleUpdate}
on:delete={handleDelete}
/>

<svelte:window
Expand Down
84 changes: 84 additions & 0 deletions web-common/src/features/canvas/CanvasComponent.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<script lang="ts" context="module">
import { builderActions, getAttrs, type Builder } from "bits-ui";
import {
ResourceKind,
useResource,
} from "../entity-management/resource-selectors";
import ComponentRenderer from "@rilldata/web-common/features/canvas/components/ComponentRenderer.svelte";
</script>

<script lang="ts">
export let i: number;
export let builders: Builder[] = [];
export let embed = false;
// export let selected = false;
export let interacting = false;
// export let width: number;
// export let height: number;
// export let top: number;
// export let left: number;
export let localZIndex = 0;
export let componentName: string;
export let instanceId: string;

$: resourceQuery = useResource(
instanceId,
componentName,
ResourceKind.Component,
);
$: ({ data: componentResource } = $resourceQuery);

$: ({ renderer, rendererProperties } =
componentResource?.component?.spec ?? {});

$: title = rendererProperties?.title;
$: description = rendererProperties?.description;
</script>

<div
{...getAttrs(builders)}
use:builderActions={{ builders }}
role="presentation"
data-index={i}
class="canvas-component hover:cursor-pointer active:cursor-grab pointer-events-auto size-full"
class:!cursor-default={embed}
style:z-index={renderer === "select" ? 100 : localZIndex}
on:contextmenu
on:pointerenter
on:pointerleave
>
<div class="size-full relative">
<div
class="size-full overflow-hidden flex flex-col flex-none"
class:shadow-lg={interacting}
>
<div class="size-full overflow-hidden flex flex-col gap-y-1 flex-none">
{#if title || description}
<div class="w-full h-fit flex flex-col border-b bg-white p-2">
{#if title}
<h1 class="text-slate-700">{title}</h1>
{/if}
{#if description}
<h2 class="text-slate-600 leading-none">{description}</h2>
{/if}
</div>
{/if}
{#if renderer && rendererProperties}
<ComponentRenderer {renderer} {componentName} />
{/if}
</div>
</div>
</div>
</div>

<style lang="postcss">
h1 {
font-size: 16px;
font-weight: 500;
}

h2 {
font-size: 12px;
font-weight: 400;
}
</style>
63 changes: 24 additions & 39 deletions web-common/src/features/canvas/CanvasDashboardEmbed.svelte
Original file line number Diff line number Diff line change
@@ -1,58 +1,43 @@
<script lang="ts">
import { type V1CanvasItem } from "@rilldata/web-common/runtime-client";
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
import Component from "./Component.svelte";
import * as defaults from "./constants";
import DashboardWrapper from "./DashboardWrapper.svelte";
import CanvasComponent from "./CanvasComponent.svelte";
import CanvasDashboardWrapper from "./CanvasDashboardWrapper.svelte";
import SvelteGridStack from "./SvelteGridStack.svelte";
import type { GridStack } from "gridstack";

export let columns = 20;
export let items: V1CanvasItem[];
export let gap = 1;
export let chartView = false;
// export let chartView = false;

let contentRect: DOMRectReadOnly = new DOMRectReadOnly(0, 0, 0, 0);
let grid: GridStack;

$: instanceId = $runtime.instanceId;

const dashboardWidth = chartView
? defaults.DASHBOARD_WIDTH / 2
: defaults.DASHBOARD_WIDTH;
// const dashboardWidth = chartView
// ? defaults.DASHBOARD_WIDTH / 2
// : defaults.DASHBOARD_WIDTH;

$: gridWidth = contentRect.width;
$: scale = gridWidth / dashboardWidth;
$: gapSize = dashboardWidth * (gap / 1000);
$: gridCell = dashboardWidth / columns;
$: radius = gridCell * defaults.COMPONENT_RADIUS;
// $: gridWidth = contentRect.width;
// $: scale = gridWidth / dashboardWidth;
// $: gridCell = dashboardWidth / columns;
// $: gridCell = defaults.DASHBOARD_WIDTH / defaults.COLUMN_COUNT;

$: maxBottom = items.reduce((max, el) => {
const bottom = Number(el.height) + Number(el.y);
return Math.max(max, bottom);
}, 0);

// $: if (variables.length && canvasName) {
// canvasVariablesStore.init(canvasName, variables);
// }
</script>

<DashboardWrapper
bind:contentRect
{scale}
height={maxBottom * gridCell * scale}
width={dashboardWidth}
>
{#each items as component, i (i)}
{@const componentName = component.component}
<CanvasDashboardWrapper bind:contentRect height={maxBottom}>
<SvelteGridStack bind:grid {items} let:index let:item embed>
{@const componentName = item.component}
{#if componentName}
<Component
embed
{i}
{instanceId}
{componentName}
{chartView}
{scale}
{radius}
padding={gapSize}
width={Number(component.width ?? defaults.COMPONENT_WIDTH) * gridCell}
height={Number(component.height ?? defaults.COMPONENT_HEIGHT) *
gridCell}
left={Number(component.x) * gridCell}
top={Number(component.y) * gridCell}
/>
<CanvasComponent embed i={index} {instanceId} {componentName} />
{/if}
{/each}
</DashboardWrapper>
</SvelteGridStack>
</CanvasDashboardWrapper>
Loading
Loading