Skip to content

Commit

Permalink
Fixing bugs - resizing, section ordering and importation
Browse files Browse the repository at this point in the history
  • Loading branch information
bcd00 committed Jan 3, 2024
1 parent 17e5b65 commit 81893d8
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 55 deletions.
2 changes: 2 additions & 0 deletions apps/ove-core-ui/src/pages/project-editor/actions/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Save,
Upload
} from "react-bootstrap-icons";
import { toast } from "sonner";
import { type ReactNode } from "react";
import { type Actions } from "../hooks";

Expand Down Expand Up @@ -60,6 +61,7 @@ const Actions = ({ setAction, save }: ActionsProps) => {
const handler = (action: Actions | null) => {
if (action === null) {
save();
toast("Project saved successfully!");
return;
}

Expand Down
20 changes: 10 additions & 10 deletions apps/ove-core-ui/src/pages/project-editor/canvas/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { dataTypes } from "../utils";

type PreviewProps = {
sections: Section[]
space: { width: number, height: number, rows: number, columns: number }
container: { width: number, height: number, cells: Geometry[] }
space: { width: number, height: number, rows: number, columns: number, cells: Geometry[] }
container: { width: number, height: number }
dragSection: (id: string, x: number, y: number) => void
select: (id: string) => void
selected: string | null
Expand Down Expand Up @@ -38,13 +38,13 @@ function drawSpaces({
svg.selectAll("*").remove();

svg.selectAll("rect")
.data(() => container.cells)
.data(() => space.cells)
.enter()
.append("rect")
.attr("x", d => d.x)
.attr("y", d => d.y)
.attr("width", d => d.width)
.attr("height", d => d.height)
.attr("x", d => x(d.x))
.attr("y", d => y(d.y))
.attr("width", d => x(d.width))
.attr("height", d => y(d.height))
.classed(styles.cell, true)
.append("title")
.text((_d, i) => `Cell No: ${i}`);
Expand All @@ -62,7 +62,7 @@ function drawSpaces({
.style("fill", d => dataTypes.find(({name}) => name === d.dataType.toLowerCase())!.color)
.classed(styles.section, true)
.append("title")
.text(d => `Section Id: ${d.id}`);
.text(d => `Section No.: ${d.ordering}\nAsset URL: ${d.asset}`);

function dragStart(this: Element) {
const section = d3.select(this);
Expand All @@ -71,7 +71,7 @@ function drawSpaces({
}

const clampX = (x: number, w: number) => {
for (const cell of container.cells) {
for (const cell of space.cells) {
if (Math.abs(cell.x - x) < ((space.width / space.columns) * THRESHOLDX)) return cell.x;
if (Math.abs((cell.x + cell.width) - (x + w)) < ((space.width / space.columns) * THRESHOLDX)) return (cell.x + cell.width) - w;
}
Expand All @@ -80,7 +80,7 @@ function drawSpaces({
};

const clampY = (y: number, h: number) => {
for (const cell of container.cells) {
for (const cell of space.cells) {
if (Math.abs(cell.y - y) < ((space.height / space.rows) * THRESHOLDY)) return cell.y;
if (Math.abs((cell.y + cell.height) - (y + h)) < ((space.height / space.rows) * THRESHOLDY)) return (cell.y + cell.height) - h;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ type ResizeContainerProps = {
height: number | string,
update: (contentRect?: { width: number, height: number }) => void
}
useContentRect: boolean
}

const ResizeContainer = ({
children,
container
container,
useContentRect
}: ResizeContainerProps) => {
useEffect(() => {
const observer = new ResizeObserver(entries => {
container.update(entries[0].contentRect);
container.update(useContentRect ? entries[0].contentRect : undefined);
});

if (container.ref.current === null) return;
Expand All @@ -28,7 +30,7 @@ const ResizeContainer = ({
if (container.ref.current === null) return;
observer.unobserve(container.ref.current);
};
}, []);
}, [container.update, container.ref.current]);

return <div className={styles["resize-container"]} ref={container.ref}>
<div style={{
Expand Down
22 changes: 7 additions & 15 deletions apps/ove-core-ui/src/pages/project-editor/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,28 @@ export const useContainer = (space: Space) => {
const [height, setHeight] = useState(100);
const ref = useRef<HTMLDivElement | null>(null);

const update = (contentRect?: Rect) => {
const update = useCallback((contentRect?: Rect) => {
if (ref.current === null) return;
const contentRect_ = contentRect ?? ref.current.getBoundingClientRect();
const multiple = Math.min(contentRect_.width / space.width, contentRect_.height / space.height);
setWidth(multiple * space.width);
setHeight(multiple * space.height);
};
}, [space.width, space.height, ref.current]);

useEffect(update, [space.width, space.height]);

const cells = Array.from({ length: space.rows }, (_x, row) => Array.from({ length: space.columns }, (_y, col) => ({
x: (width / space.columns) * col,
y: (height / space.rows) * row,
width: space.width / space.columns,
height: space.height / space.rows
}))).flat();

return { width, height, ref, update, cells };
return { width, height, ref, update };
};

export const useSpace = () => {
const [rows, setRows] = useState(2);
const [columns, setColumns] = useState(2);
const [width, setWidth] = useState(3840);
const [height, setHeight] = useState(2160);
const [width, setWidth] = useState(16);
const [height, setHeight] = useState(9);

const update = (space: Space) => {
setHeight(space.height || 4320);
setWidth(space.width || 30720);
setHeight(space.height || 4);
setWidth(space.width || 64);
setColumns(space.columns || 16);
setRows(space.rows || 4);
};
Expand Down Expand Up @@ -409,7 +402,6 @@ export const useCollaboration = (project: Project, username: string) => {
recipientId,
status
}) => recipientId === user.id && status === "pending") === undefined);
console.log(project.collaboratorIds);
const accepted = project.collaboratorIds.map(id => users.find(user => user.id === id)!);
const invited = invites.filter(({ status }) => status === "pending").map(({ recipientId }) => users.find(({ id }) => id === recipientId)!);

Expand Down
10 changes: 5 additions & 5 deletions apps/ove-core-ui/src/pages/project-editor/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const ProjectEditor = ({
updateState={states.updateState}
setState={states.select}
currentState={states.selected} />
<ResizeContainer container={container}>
<ResizeContainer container={container} useContentRect={false}>
<Canvas sections={sections.getSections(states.selected)}
space={space}
container={container}
Expand All @@ -185,7 +185,7 @@ const ProjectEditor = ({
selected={sections.selected} />
</ResizeContainer>
</ResizablePanel>
<ResizableHandle withHandle={true} />
<ResizableHandle withHandle={!isOpen} />
<ResizablePanel defaultSize={25}>
<Sections sections={sections.getSections(states.selected)}
generateSection={sections.generateSection}
Expand All @@ -198,13 +198,13 @@ const ProjectEditor = ({
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle withHandle={true} />
<ResizableHandle withHandle={!isOpen} />
<ResizablePanel defaultSize={40}>
<ResizablePanelGroup direction="horizontal">
<ResizablePanel defaultSize={40}>
<SpaceConfig space={space} presets={observatories} />
</ResizablePanel>
<ResizableHandle withHandle={true} />
<ResizableHandle withHandle={!isOpen} />
<ResizablePanel defaultSize={60}>
<SectionConfig sections={sections.getSections(states.selected)}
setAction={setAction} files={assets}
Expand All @@ -219,7 +219,7 @@ const ProjectEditor = ({
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle withHandle={true} />
<ResizableHandle withHandle={!isOpen} />
<ResizablePanel defaultSize={5}>
<Actions setAction={setAction}
save={() => toProject(project, sections.all)} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@
width: 100%;
min-height: 1.75rem;
text-align: left;

& span {
font-weight: 700;
margin: 0 0.25rem;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { X } from "react-bootstrap-icons";
import { type Section } from "@prisma/client";

import styles from "./section-importer.module.scss";
import { Json } from "@ove/ove-utils";

type SectionImporterProps = {
states: string[]
Expand All @@ -28,6 +29,13 @@ const SectionImporter = ({
}: SectionImporterProps) => {
const [selected, setSelected] = useState(states[0]);
const sections = getSections(selected, selectedState);

const sort = (a: string, b: string) => {
if (b === "__default__" || a > b) return 1;
if (a === "__default__" || b > a) return -1;
return 0;
};

return <section id={styles["import"]}>
<header>
<h2>Import Section</h2>
Expand All @@ -37,13 +45,14 @@ const SectionImporter = ({
<div id={styles["states"]}>
<h4>From State</h4>
<ul>
{sections.flatMap(({ states }) => states).filter((x, i, arr) => arr.indexOf(x) === i).map((state, i) =>
<li key={state}
style={{ backgroundColor: actionColors[i % actionColors.length] }}>
{Json.copy(states).sort(sort).map((state, i) => {
return <li key={state}
style={{ backgroundColor: actionColors[i % actionColors.length] }}>
<button
onClick={() => setSelected(state)}
style={{ fontWeight: state === selected ? 700 : 400 }}>{formatState(state)}</button>
</li>)}
</li>;
})}
</ul>
</div>
<div id={styles["sections"]}>
Expand All @@ -56,7 +65,7 @@ const SectionImporter = ({
onClick={() => {
setAction(null);
addToState(section.id, selectedState);
}}>{section.asset.length < 25 ? section.asset : `${section.asset.slice(0, 24)}...`}</button>
}}><span>{section.ordering}</span>{section.asset.length < 25 ? section.asset : `${section.asset.slice(0, 24)}...`}</button>
</li>)}
</ul>
</div>
Expand Down
36 changes: 29 additions & 7 deletions apps/ove-core-ui/src/pages/project-editor/sections/sections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ReorderableItem, ReorderableList } from "@ove/ui-reorderable-list";

import styles from "./sections.module.scss";
import { dataTypes } from "../utils";
import { Json } from "@ove/ove-utils";

type SectionsProps = {
sections: Section[]
Expand Down Expand Up @@ -41,6 +42,26 @@ const Sections = ({
setCharacterLimit(Math.floor((bounds.width - (4 * rem)) / (rem * 0.5)));
};

const setSectionsHandler = (curList: Section[], newList: Section[]) => {
const newListOldOrder = Json.copy(newList).sort((a, b) => a.ordering - b.ordering);
let startOrder: number | null = null;
let endOrder: number | null = null;
newList.forEach((section, i) => {
const oldOrder = newListOldOrder[i].ordering;
if (oldOrder !== section.ordering) {
if (endOrder === null && startOrder === null) {
endOrder = section.ordering;
startOrder = oldOrder;
}
}
});

return curList.slice(0, startOrder!).concat([curList[endOrder!]].concat(curList.slice(startOrder!, endOrder!)).map((section, i) => ({
...section,
ordering: i
}))).concat(curList.slice(endOrder! + 1));
};

return <section id={styles["sections"]}>
<h2>Sections</h2>
<ul>
Expand All @@ -49,21 +70,22 @@ const Sections = ({
width: "100%",
height: "100%",
update: getCharacterLimit
}}>
}} useContentRect={true}>
<ReorderableList
onListUpdate={newList => setSections(() => (newList as Section[]).map((section, i) => ({
...section,
ordering: i
})))} list={sections} style={{}}>
onListUpdate={newList => setSections(curList => setSectionsHandler(curList, newList))}
list={sections} style={{}}>
{sections.map(section => (
<ReorderableItem key={section.id}>
<li key={section.id} style={{
backgroundColor: dataTypes.find(({name}) => name === section.dataType.toLowerCase())!.color,
backgroundColor: dataTypes.find(({ name }) => name === section.dataType.toLowerCase())!.color,
borderWidth: selected === section.id ? "2px" : "1px"
}}>
<button className={styles.container} style={{ flexGrow: 1 }}
onClick={() => select(section.id)}>
<span style={{ fontWeight: 700, fontSize: "1.25rem" }}>{section.ordering}</span>
<span style={{
fontWeight: 700,
fontSize: "1.25rem"
}}>{section.ordering}</span>
<span className={styles.asset}
style={{ fontWeight: selected === section.id ? 700 : 400 }}>{section.asset.length <= characterLimit ? section.asset : `${section.asset.slice(0, characterLimit)}...`}</span>
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { z } from "zod";
import { Json } from "@ove/ove-utils";
import { useForm } from "react-hook-form";
import { type Rect, type Space } from "../types";
import { type Geometry, type Rect, type Space } from "../types";
import { type NativeEvent } from "@ove/ove-types";
import { zodResolver } from "@hookform/resolvers/zod";
import { type BaseSyntheticEvent, useRef } from "react";
import { type BaseSyntheticEvent, useEffect, useRef } from "react";

import styles from "./space-config.module.scss";
import { toast } from "sonner";

type SpaceConfigProps = {
space: Space & { update: (space: Space) => void }
space: Space & { cells: Geometry[], update: (space: Space) => void }
presets: { [key: string]: Space }
}

Expand Down Expand Up @@ -38,14 +39,15 @@ const SpaceConfigSchema = z.strictObject({
});

const SpaceConfig = ({
space: { update, ...curSpace },
space: { update, cells, ...curSpace },
presets
}: SpaceConfigProps) => {
const ref = useRef<HTMLFormElement | null>(null);
const {
register,
handleSubmit,
setValue
setValue,
formState: {errors}
} = useForm<Space & { preset: string | null }>({
resolver: zodResolver(SpaceConfigSchema),
defaultValues: {
Expand All @@ -54,11 +56,17 @@ const SpaceConfig = ({
}
});

useEffect(() => {
Object.values(errors).forEach(error => {
toast.error(error?.message);
});
}, [errors]);

const onSubmit = (config: Space & {
preset: string | null
}, e: BaseSyntheticEvent<object> | undefined) => {
const { preset, ...newSpace } = config;
if ((e?.nativeEvent as unknown as NativeEvent)?.submitter?.name === styles["custom-submit"]) {
if ((e?.nativeEvent as unknown as NativeEvent)?.submitter?.name !== undefined) {
if (!Json.equals(newSpace, curSpace)) {
setValue("preset", getPreset(presets, newSpace));
}
Expand Down Expand Up @@ -88,6 +96,7 @@ const SpaceConfig = ({
<p>:</p>
<input {...register("height", { valueAsNumber: true })}
type="number" />
<button type="submit" style={{display: "none"}}></button>
</fieldset>
</label>
<label htmlFor="presets">Presets:</label>
Expand Down
Loading

0 comments on commit 81893d8

Please sign in to comment.