Skip to content

Commit

Permalink
export svg first approach
Browse files Browse the repository at this point in the history
  • Loading branch information
brauliodiez committed Jan 14, 2024
1 parent f208e4b commit 081dda1
Show file tree
Hide file tree
Showing 12 changed files with 530 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/pods/canvas/canvas-svg.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const CanvasSvgComponent: React.FC<Props> = props => {
updatePosition={onUpdateTablePosition}
onToggleCollapse={onToggleCollapse}
onEditTable={onEditTable}
canvasSize={canvasSize}
/>
))}
<DatabaseRelationCollectionComponent schema={canvasSchema} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface Props {
) => void;
onToggleCollapse: (tableId: GUID, fieldId: GUID) => void;
onEditTable: (tableInfo: TableVm) => void;
canvasSize: Size;
}

const HEADER_TITLE_GAP = 15;
Expand All @@ -26,6 +27,7 @@ export const DatabaseTable: React.FC<Props> = ({
onEditTable,
updatePosition,
onToggleCollapse,
canvasSize,
}) => {
const rowHeight = TABLE_CONST.FONT_SIZE + TABLE_CONST.ROW_PADDING;

Expand Down Expand Up @@ -85,7 +87,8 @@ export const DatabaseTable: React.FC<Props> = ({
tableInfo.x,
tableInfo.y,
updatePosition,
totalHeight
totalHeight,
canvasSize
);

const handleDoubleClick = () => {
Expand Down
8 changes: 4 additions & 4 deletions src/pods/canvas/components/table/table-drag.hook.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useCallback } from 'react';
import { useCanvasViewSettingsContext } from '@/core/providers';
import { Coords, Size } from '@/core/model';

export const useDraggable = (
Expand All @@ -12,12 +11,13 @@ export const useDraggable = (
totalHeight: number,
canvasSize: Size
) => void,
totalHeight: number
totalHeight: number,
canvasSize: Size
) => {
const [isDragging, setIsDragging] = useState(false);
const [startDragPosition, setStartDragPosition] = useState({ x: 0, y: 0 });
const { canvasViewSettings } = useCanvasViewSettingsContext();
const { canvasSize } = canvasViewSettings;
//const { canvasViewSettings } = useCanvasViewSettingsContext();
//const { canvasSize } = canvasViewSettings;

const onMouseDown = useCallback(
(event: React.MouseEvent) => {
Expand Down
49 changes: 49 additions & 0 deletions src/pods/export/canvas-export-svg.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Coords, GUID, Size } from '@/core/model';
import { DatabaseSchemaVm, TableVm } from '@/core/providers/canvas-schema';
import { DatabaseTable } from './components/table/database-table.component';
import { DatabaseRelationCollectionComponent } from './components/relation';

interface Props {
viewBoxSize: Size;
canvasSize: Size;
canvasSchema: DatabaseSchemaVm;
onUpdateTablePosition: (
id: string,
position: Coords,
totalHeight: number,
canvasSize: Size
) => void;
onToggleCollapse: (tableId: GUID, fieldId: GUID) => void;
onEditTable: (tableInfo: TableVm) => void;
}

export const CanvasExportSvgComponent: React.FC<Props> = props => {
const {
viewBoxSize,
canvasSize,
canvasSchema,
onUpdateTablePosition,
onToggleCollapse,
onEditTable,
} = props;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox={`0 0 ${viewBoxSize.width} ${viewBoxSize.height}`}
width={canvasSize.width}
height={canvasSize.height}
>
{canvasSchema.tables.map(table => (
<DatabaseTable
key={table.id}
tableInfo={table}
updatePosition={onUpdateTablePosition}
onToggleCollapse={onToggleCollapse}
onEditTable={onEditTable}
canvasSize={canvasSize}
/>
))}
<DatabaseRelationCollectionComponent schema={canvasSchema} />
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { Coords } from '@/core/model';
import { DatabaseSchemaVm, RelationVm } from '@/core/providers/canvas-schema';
import DatabaseRelationshipComponent from './database-relation.component';
import {
calculateRelationXCoordinate,
calculateRelationYCoordinate,
} from '@/core/providers/canvas-schema/canvas.business';

interface DatabaseRelationCollectionProps {
schema: DatabaseSchemaVm;
}

export const DatabaseRelationCollectionComponent: React.FC<
DatabaseRelationCollectionProps
> = ({ schema }) => {
const renderRelation = (relation: RelationVm) => {
const fromTable = schema.tables.find(
table => table.id === relation.fromTableId
);
const toTable = schema.tables.find(
table => table.id === relation.toTableId
);

if (!fromTable || !toTable) {
return null;
}

const YCoords = calculateRelationYCoordinate(
relation.fromFieldId,
relation.toFieldId,
fromTable,
toTable
);
const XCoords = calculateRelationXCoordinate(fromTable, toTable);

const startCoords: Coords = {
x: XCoords.xOrigin,
y: YCoords.yOrigin,
};

const endCoords: Coords = {
x: XCoords.xDestination,
y: YCoords.yDestination,
};

return (
<DatabaseRelationshipComponent
key={`${relation.fromTableId}-${relation.fromFieldId}-${relation.toTableId}-${relation.toFieldId}`}
relationType={relation.type}
startCoords={startCoords}
endCoords={endCoords}
/>
);
};

return <g>{schema.relations.map(relation => renderRelation(relation))}</g>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from 'react';
import { RelationType } from '@/core/providers/canvas-schema';
import { Coords } from '@/core/model';

interface DatabaseRelationshipProps {
relationType: RelationType;
startCoords: Coords;
endCoords: Coords;
}

const FORK_WIDTH = 10;
const FORK_LINE_SPACING = 5;

const DatabaseRelationshipComponent: React.FC<DatabaseRelationshipProps> = ({
relationType,
startCoords,
endCoords,
}) => {
const drawFork = (forkCoords: Coords, drawLeftToRight: boolean) => {
const direction = drawLeftToRight ? 1 : -1;

// TODO: Teresa replace all the stroke "white" to work with the theme
return (
<g>
{/* Fork lines */}
<line
x1={forkCoords.x}
y1={forkCoords.y}
x2={forkCoords.x + FORK_WIDTH * direction}
y2={forkCoords.y}
stroke="#ffae42"
/>
<line
x1={forkCoords.x}
y1={forkCoords.y}
x2={forkCoords.x + FORK_WIDTH * direction}
y2={forkCoords.y - FORK_LINE_SPACING}
stroke="#ffae42"
/>
<line
x1={forkCoords.x}
y1={forkCoords.y}
x2={forkCoords.x + FORK_WIDTH * direction}
y2={forkCoords.y + FORK_LINE_SPACING}
stroke="#ffae42"
/>
</g>
);
};

// Determine the direction of the fork
const isDrawLeftToRight =
relationType === '1:M'
? startCoords.x < endCoords.x
: startCoords.x > endCoords.x;

const originXMinusFork =
relationType === 'M:1' ? startCoords.x - FORK_WIDTH : startCoords.x;
const destinationXMinusFork =
relationType === '1:M'
? endCoords.x + (isDrawLeftToRight ? -1 : 1) * FORK_WIDTH
: endCoords.x;

return (
<svg>
{/* Base line of the relationship */}
<line
x1={originXMinusFork}
y1={startCoords.y}
x2={destinationXMinusFork}
y2={endCoords.y}
strokeWidth={2}
stroke="#ffae42"
/>

{/* Draw the fork */}
{relationType === '1:M' &&
drawFork(
{ x: destinationXMinusFork, y: endCoords.y },
isDrawLeftToRight
)}
{relationType === 'M:1' &&
drawFork({ x: originXMinusFork, y: startCoords.y }, !isDrawLeftToRight)}
</svg>
);
};

export default DatabaseRelationshipComponent;
1 change: 1 addition & 0 deletions src/pods/export/components/relation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './database-relation-collection.component';
76 changes: 76 additions & 0 deletions src/pods/export/components/table/database-table-row.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { GUID } from '@/core/model';
import { FieldVm, TableVm } from '@/core/providers/canvas-schema';
import { TABLE_CONST } from '@/core/providers/canvas-schema/canvas.const';
import { calculateDBColumnsWidth } from '@/pods/edit-table/edit-table.business';
import { exportStylesVariables } from '../../export-variables.const';

interface Props {
tableInfo: TableVm;
field: FieldVm;
level: number;
currentY: number;
onToggleCollapse: (tableId: GUID, fieldId: GUID) => void;
}

const FIELD_NAME_WIDTH_PERCENTAGE = 70;
const FIELD_TYPE_WIDTH_PERCENTAGE = 30;
const MARGIN_LEFT = 10;
const MARGIN_RIGHT = 80;
const TABLE_CLEAN_WIDTH =
TABLE_CONST.DEFAULT_TABLE_WIDTH - MARGIN_LEFT - MARGIN_RIGHT;

export const DatabaseTableRow: React.FC<Props> = props => {
const { field, tableInfo, level, currentY, onToggleCollapse } = props;

const isExpandable =
field.type === 'object' && (field.children?.length ?? 0) > 0;
const isExpanded = !field.isCollapsed;
const columnWidths = calculateDBColumnsWidth(
[FIELD_NAME_WIDTH_PERCENTAGE, FIELD_TYPE_WIDTH_PERCENTAGE],
TABLE_CLEAN_WIDTH
);

return (
<g key={field.id} transform={`translate(${MARGIN_LEFT}, ${currentY})`}>
<g transform={`translate(${level * TABLE_CONST.LEVEL_INDENTATION}, 0)`}>
{isExpandable && (
<text
x={TABLE_CONST.COLLAPSE_ICON_X}
y={TABLE_CONST.FONT_SIZE}
style={{
fill: exportStylesVariables.TEXT_COLOR,
fontFamily: "'Arial', sans-serif",
fontSize: '14px',
}}
onClick={() => onToggleCollapse(tableInfo.id, field.id)}
>
{isExpanded ? '▼' : '►'}
</text>
)}
<text
x={TABLE_CONST.FIELD_NAME_X_OFFSET + (isExpandable ? 15 : 0)}
y={TABLE_CONST.FONT_SIZE}
style={{
fill: exportStylesVariables.TEXT_COLOR,
fontFamily: 'Arial',
fontSize: '14px',
}}
>
{field.name}
</text>
</g>
<text
x={columnWidths[0] + columnWidths[1]}
y={TABLE_CONST.FONT_SIZE}
style={{
fill: exportStylesVariables.TEXT_COLOR,
fontFamily: 'Arial',
fontSize: '14px',
}}
>
{field.type}
{field.isArray ? `[]` : null}
</text>
</g>
);
};
Loading

0 comments on commit 081dda1

Please sign in to comment.