Skip to content

Commit b64c0bb

Browse files
committed
O| and O< notation working
1 parent 146e0cc commit b64c0bb

File tree

3 files changed

+76
-28
lines changed

3 files changed

+76
-28
lines changed

SchemaMagic.Core/CoreSchemaAnalysisService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,8 @@ private static List<PropertyInfo> ExtractProperties(ClassDeclarationSyntax entit
674674
var propertyName = property.Identifier.Text;
675675
var propertyType = property.Type.ToString();
676676

677-
// Clean up the type string
678-
propertyType = propertyType.Replace("?", "").Trim();
677+
// FIXED: DO NOT remove the nullable marker - preserve it for JavaScript analysis
678+
propertyType = propertyType.Trim(); // Only trim whitespace, keep '?'
679679

680680
// Check if this property is a foreign key (from EF snapshot OR heuristic detection)
681681
var isForeignKey = entityForeignKeys.Contains(propertyName) || IsHeuristicForeignKey(propertyName, propertyType);
@@ -686,7 +686,7 @@ private static List<PropertyInfo> ExtractProperties(ClassDeclarationSyntax entit
686686
var propertyInfo = new PropertyInfo
687687
{
688688
Name = propertyName,
689-
Type = propertyType,
689+
Type = propertyType, // Now includes '?' if nullable
690690
IsKey = IsKeyProperty(propertyName, entityName),
691691
IsForeignKey = isForeignKey,
692692
Comment = comment

Templates/relationships.js

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,14 @@ function createCrowsFootRelationshipLine(svg, fromEntityName, toEntityName, prop
242242
}
243243

244244
function drawCrowsFootNotation(svg, x, y, direction, relationship, isFromSide) {
245-
const CROW_SIZE = 35; // Size of crow's foot
246-
const ONE_SIDE_OFFSET = 20; // Offset from table edge for "one" side notation
247-
const CIRCLE_RADIUS = 10; // Radius for optional indicator
248-
const CIRCLE_OFFSET = -20; // CHANGED: Negative offset to place circle BEFORE the crow's foot (closer to table)
245+
const CROW_SIZE = 35; // Size of crow's foot (distance from table edge to tip)
246+
const CIRCLE_RADIUS = 20; // Radius for optional indicator
247+
const GAP = 5; // Small gap between circle and notation
248+
const CIRCLE_OFFSET = CROW_SIZE + CIRCLE_RADIUS + GAP; // Position circle with gap from notation
249249

250-
// Use the same blue color as relationship lines for consistency
251-
const color = '#2563eb'; // Blue color matching relationship lines
250+
// Use exact same blue color as relationship lines from CSS (.relationship-line)
251+
const color = '#2563eb'; // Must match CSS .relationship-line stroke color
252+
const strokeWidth = 8; // Must match CSS .relationship-line stroke-width
252253

253254
// Determine what notation to draw based on relationship type and side
254255
let notationType;
@@ -286,52 +287,52 @@ function drawCrowsFootNotation(svg, x, y, direction, relationship, isFromSide) {
286287

287288
// Draw notation based on type
288289
if (notationType.includes('many')) {
289-
// Draw circle for optional relationships FIRST (positioned between table and crow's foot)
290+
// Draw circle for optional relationships FIRST (positioned with gap from crow's foot)
290291
if (notationType.includes('optional')) {
291292
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
292293
circle.setAttribute('cx', CIRCLE_OFFSET);
293294
circle.setAttribute('cy', '0');
294295
circle.setAttribute('r', CIRCLE_RADIUS);
295296
circle.setAttribute('stroke', color);
296-
circle.setAttribute('stroke-width', '5');
297-
circle.setAttribute('fill', 'none'); // FIXED: Transparent fill so circle is visible
297+
circle.setAttribute('stroke-width', strokeWidth);
298+
circle.setAttribute('fill', 'white'); // White fill so circle is visible against any background
298299
group.appendChild(circle);
299-
console.log(`⭕ Drew optional circle for many side at cx=${CIRCLE_OFFSET}`);
300+
console.log(`⭕ Drew optional circle for many side at cx=${CIRCLE_OFFSET}, r=${CIRCLE_RADIUS}`);
300301
}
301302

302303
// Draw crow's foot as a path with two segments forming a > shape
303304
// The path should point AWAY from the table (to the right in unrotated state)
304-
// So: toe at x=0, legs extend to the right and up/down
305+
// Tip at x=CROW_SIZE (same distance as "one" side vertical line)
305306
const crowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
306307
const pathData = `M 0,${-CROW_SIZE} L ${CROW_SIZE},0 L 0,${CROW_SIZE}`;
307308
crowPath.setAttribute('d', pathData);
308309
crowPath.setAttribute('stroke', color);
309-
crowPath.setAttribute('stroke-width', '8');
310+
crowPath.setAttribute('stroke-width', strokeWidth);
310311
crowPath.setAttribute('fill', 'none');
311312
crowPath.setAttribute('stroke-linejoin', 'miter');
312313
group.appendChild(crowPath);
313314
} else {
314-
// Draw circle for optional relationships FIRST
315+
// Draw circle for optional relationships FIRST (positioned with gap from vertical line)
315316
if (notationType.includes('optional')) {
316317
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
317-
circle.setAttribute('cx', 0);
318+
circle.setAttribute('cx', CIRCLE_OFFSET);
318319
circle.setAttribute('cy', '0');
319320
circle.setAttribute('r', CIRCLE_RADIUS);
320321
circle.setAttribute('stroke', color);
321-
circle.setAttribute('stroke-width', '5');
322-
circle.setAttribute('fill', 'none'); // FIXED: Transparent fill so circle is visible
322+
circle.setAttribute('stroke-width', strokeWidth);
323+
circle.setAttribute('fill', 'white'); // White fill so circle is visible against any background
323324
group.appendChild(circle);
324-
console.log(`⭕ Drew optional circle for one side at cx=0`);
325+
console.log(`⭕ Drew optional circle for one side at cx=${CIRCLE_OFFSET}, r=${CIRCLE_RADIUS}`);
325326
}
326327

327-
// One side - vertical line with offset from table edge (drawn AFTER circle so it appears in front)
328+
// One side - vertical line at CROW_SIZE distance (same as crow's foot tip)
328329
const verticalLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
329-
verticalLine.setAttribute('x1', ONE_SIDE_OFFSET);
330+
verticalLine.setAttribute('x1', CROW_SIZE); // Same distance as crow's foot tip
330331
verticalLine.setAttribute('y1', -CROW_SIZE);
331-
verticalLine.setAttribute('x2', ONE_SIDE_OFFSET);
332+
verticalLine.setAttribute('x2', CROW_SIZE);
332333
verticalLine.setAttribute('y2', CROW_SIZE);
333334
verticalLine.setAttribute('stroke', color);
334-
verticalLine.setAttribute('stroke-width', '8');
335+
verticalLine.setAttribute('stroke-width', strokeWidth);
335336
group.appendChild(verticalLine);
336337
}
337338

@@ -524,8 +525,11 @@ function findPropertyConnectionPoint(tableGroup, propertyName, fallbackY) {
524525
for (const propText of propertyTexts) {
525526
if (propText.textContent === propertyName) {
526527
const y = parseFloat(propText.getAttribute('y'));
527-
console.log(`🎯 Found property ${propertyName} at y=${y}`);
528-
return y;
528+
// FIXED: Adjust Y to be at the CENTER of the property text/icon, not the baseline
529+
// Property icons are rendered at y-12 (which is the center), so we need to match that
530+
const centerY = y - 12;
531+
console.log(`🎯 Found property ${propertyName} at y=${y}, centerY=${centerY}`);
532+
return centerY;
529533
}
530534
}
531535

Templates/styles.css

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ body {
682682
stroke: #2563eb;
683683
stroke-width: 8;
684684
fill: none;
685-
opacity: 0.8;
685+
/* Removed opacity to ensure consistent color with crow's foot notation */
686686
/* No transition - lines update immediately */
687687
}
688688

@@ -1464,7 +1464,33 @@ body {
14641464

14651465
.crows-foot-notation path,
14661466
.crows-foot-notation line {
1467-
/* Inherits color from parent attributes */
1467+
/* Explicitly set stroke to match relationship lines */
1468+
stroke: #2563eb;
1469+
stroke-width: 8;
1470+
fill: none;
1471+
}
1472+
1473+
@media (prefers-color-scheme: dark) {
1474+
.crows-foot-notation path,
1475+
.crows-foot-notation line {
1476+
stroke: #60a5fa;
1477+
stroke-width: 8;
1478+
}
1479+
}
1480+
1481+
.crows-foot-notation circle {
1482+
/* Ensure circles have white fill in light mode and darker fill in dark mode for contrast */
1483+
fill: white;
1484+
stroke: #2563eb; /* Exact same blue as relationship lines */
1485+
stroke-width: 8; /* Match relationship line stroke-width */
1486+
}
1487+
1488+
@media (prefers-color-scheme: dark) {
1489+
.crows-foot-notation circle {
1490+
fill: #1a202c; /* Dark background for circles in dark mode */
1491+
stroke: #60a5fa;
1492+
stroke-width: 8;
1493+
}
14681494
}
14691495

14701496
/* When relationship is highlighted, crow's feet should also be highlighted */
@@ -1473,11 +1499,19 @@ body {
14731499
stroke: #764ba2 !important; /* Purple to match highlighted relationships */
14741500
}
14751501

1502+
.crows-foot-notation.highlighted circle {
1503+
stroke: #764ba2 !important; /* Purple stroke for circles when highlighted */
1504+
}
1505+
14761506
@media (prefers-color-scheme: dark) {
14771507
.crows-foot-notation.highlighted path,
14781508
.crows-foot-notation.highlighted line {
14791509
stroke: #a78bfa !important;
14801510
}
1511+
1512+
.crows-foot-notation.highlighted circle {
1513+
stroke: #a78bfa !important;
1514+
}
14811515
}
14821516

14831517
.crows-foot-notation.dimmed path,
@@ -1486,10 +1520,20 @@ body {
14861520
opacity: 0.3;
14871521
}
14881522

1523+
.crows-foot-notation.dimmed circle {
1524+
stroke: #d1d5db !important; /* Dimmed stroke for circles */
1525+
opacity: 0.3;
1526+
}
1527+
14891528
@media (prefers-color-scheme: dark) {
14901529
.crows-foot-notation.dimmed path,
14911530
.crows-foot-notation.dimmed line {
14921531
stroke: #4b5563 !important;
14931532
opacity: 0.2;
14941533
}
1534+
1535+
.crows-foot-notation.dimmed circle {
1536+
stroke: #4b5563 !important;
1537+
opacity: 0.2;
1538+
}
14951539
}

0 commit comments

Comments
 (0)