Skip to content

Commit e9ed01d

Browse files
committed
Add test page to debug rendering issue
1 parent 4d21e4b commit e9ed01d

File tree

1 file changed

+18
-289
lines changed

1 file changed

+18
-289
lines changed

index.html

Lines changed: 18 additions & 289 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,22 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>FIP Lifecycle Management</title>
6+
<title>FIP Lifecycle Management - Test</title>
77
<style>
88
body {
99
font-family: 'Segoe UI', Arial, sans-serif;
1010
background: #f8fbfd;
1111
margin: 0;
12-
padding: 0;
12+
padding: 20px;
1313
color: #234;
1414
}
1515
.container {
16-
width: 100vw;
17-
min-height: 100vh;
18-
margin: 0;
16+
max-width: 1200px;
17+
margin: 0 auto;
1918
background: #fff;
20-
border-radius: 0;
21-
box-shadow: none;
22-
padding: 32px 0 0 0;
23-
display: flex;
24-
flex-direction: column;
25-
align-items: center;
26-
justify-content: flex-start;
19+
padding: 20px;
20+
border-radius: 10px;
21+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
2722
}
2823
h1 {
2924
text-align: center;
@@ -36,296 +31,30 @@
3631
margin-bottom: 32px;
3732
font-size: 1.1em;
3833
}
39-
.flowchart-area {
40-
width: 100vw;
41-
overflow-x: auto;
42-
overflow-y: visible;
43-
display: block;
44-
margin-bottom: 0px;
45-
-webkit-overflow-scrolling: touch;
46-
background: none;
47-
position: relative;
48-
}
49-
.flowchart-svg {
50-
display: block;
51-
background: none;
52-
/* width and height will be set dynamically */
53-
}
54-
.fip-box {
55-
fill: #eaf3fc;
56-
stroke: #b3d1f7;
57-
stroke-width: 2;
58-
rx: 10;
59-
cursor: pointer;
60-
filter: drop-shadow(0 1px 4px #0001);
61-
}
62-
.fip-label {
63-
font-size: 1.05em;
64-
font-weight: 600;
65-
fill: #2a5d9f;
66-
pointer-events: none;
67-
font-family: 'Segoe UI', Arial, sans-serif;
68-
}
69-
.fip-role {
70-
font-size: 0.95em;
71-
fill: #3a7d3a;
72-
font-style: italic;
73-
font-family: 'Segoe UI', Arial, sans-serif;
74-
font-weight: 400;
75-
pointer-events: none;
76-
}
77-
.fip-arrow {
78-
stroke: #2a5d9f;
79-
stroke-width: 2.5;
80-
marker-end: url(#arrowhead);
81-
fill: none;
82-
}
83-
.fip-box.selected {
84-
fill: #d2e7fa;
85-
stroke: #2a5d9f;
86-
}
87-
.fip-details {
88-
display: none;
89-
position: fixed;
90-
background: #f3f8fd;
91-
border-left: 3px solid #b3d1f7;
92-
padding: 14px 18px;
93-
border-radius: 6px;
94-
color: #234;
95-
font-size: 0.98em;
96-
box-shadow: 0 1px 4px #0001;
97-
max-width: 340px;
98-
z-index: 1000;
99-
left: 0;
100-
top: 0;
101-
pointer-events: auto;
102-
min-width: 220px;
103-
}
104-
.fip-details.visible {
105-
display: block;
106-
animation: fadeIn 0.3s;
107-
}
108-
@keyframes fadeIn {
109-
from { opacity: 0; }
110-
to { opacity: 1; }
111-
}
112-
.feedback-section {
113-
margin: 12px auto 24px auto;
114-
padding: 24px 24px 18px 24px;
115-
background: #f3f8fd;
116-
border-radius: 10px;
117-
box-shadow: 0 1px 8px #0001;
118-
max-width: 700px;
34+
.test-content {
11935
text-align: center;
120-
color: #234;
121-
font-size: 1.05em;
122-
}
123-
.feedback-section b {
124-
color: #2a5d9f;
125-
font-size: 1.13em;
126-
display: block;
127-
margin-bottom: 6px;
128-
}
129-
@media (max-width: 1200px) {
130-
.flowchart-svg {
131-
/* height will be set dynamically */
132-
}
133-
}
134-
@media (max-width: 700px) {
135-
.container {
136-
padding: 10px 0 0 0;
137-
}
138-
.flowchart-area {
139-
width: 100vw;
140-
}
141-
.flowchart-svg {
142-
/* height will be set dynamically */
143-
}
144-
.fip-details {
145-
max-width: 95vw;
146-
padding: 10px 4px;
147-
}
148-
.feedback-section {
149-
padding: 12px 4vw 10px 4vw;
150-
font-size: 0.98em;
151-
}
36+
padding: 40px;
37+
background: #eaf3fc;
38+
border-radius: 8px;
39+
margin: 20px 0;
15240
}
15341
</style>
15442
</head>
15543
<body>
15644
<div class="container">
15745
<h1>FIP Lifecycle Management</h1>
15846
<div class="subtitle">Interactive horizontal flowchart of the Filecoin Improvement Proposal (FIP) Lifecycle</div>
159-
<div class="flowchart-area" id="flowchart-area">
160-
<svg class="flowchart-svg" id="fip-svg"></svg>
47+
48+
<div class="test-content">
49+
<h2>Test Page Working!</h2>
50+
<p>If you can see this, the basic HTML structure is working correctly.</p>
51+
<p>The issue might be with the SVG rendering or JavaScript.</p>
16152
</div>
53+
16254
<div class="feedback-section">
16355
<b>Community Invitation for Feedback</b>
16456
This framework is designed to empower robust governance, prioritizing clarity, transparency, and community agency. We warmly invite feedback, suggestions, or concerns regarding any aspect of this lifecycle. Community collaboration is essential in evolving this governance process, ensuring it remains responsive, fair, and effective for the Filecoin ecosystem.
16557
</div>
166-
<div id="fip-details-popup" class="fip-details"></div>
16758
</div>
168-
<script>
169-
// --- FLOWCHART DATA ---
170-
const nodes = [
171-
{ id: 'discussion', label: 'Discussion', x: 80, y: 180, width: 140, height: 48, details: `<b>Discussion Stage</b><br>This initial phase is meant to facilitate open dialogue, ensuring that any potential proposals are thoroughly debated within the community before formalizing a FIP.<br><i>Rationale:</i> Encourages early collaboration, reducing redundancy and increasing alignment with community priorities.`, roleLabel: 'Governance Facilitator' },
172-
{ id: 'no-fip', label: 'NO FIP', x: 80, y: 320, width: 120, height: 48, details: `<b>No FIP</b><br>The discussion does not result in a formal FIP proposal.` },
173-
{ id: 'fip-draft', label: 'FIP DRAFT', x: 320, y: 180, width: 140, height: 48, details: `<b>FIP Draft</b><br>Formalizes ideas from discussions into structured proposals clearly outlining intent, implementation details, and anticipated impacts.<br><i>Rationale:</i> Enhances proposal quality and readability, setting clear expectations and standards.` },
174-
{ id: 'fip-editors', label: 'FIP Editors', x: 500, y: 180, width: 140, height: 48, details: `<b>FIP Editors</b><br>Subject matter experts or dedicated editors analyze drafts to provide critical and constructive feedback.<br><i>Rationale:</i> Maintains high-quality proposals, reducing future complications or ambiguities.`, roleLabel: 'FIP Editors' },
175-
{ id: 'fip-assigned', label: 'FIP ASSIGNED', x: 700, y: 180, width: 140, height: 48, details: `<b>FIP Assigned</b><br>Formally assigns the FIP a unique identifier and places it in an official governance pipeline.<br><i>Rationale:</i> Provides traceability, clarity, and structure to the lifecycle management.` },
176-
{ id: 'timelock', label: 'TIMELOCK', x: 900, y: 180, width: 140, height: 48, details: `<b>Timelock</b><br>Introduces a deliberate delay before implementation, allowing community and stakeholders sufficient time for comprehensive review.<br><i>Rationale:</i> Prevents rash or inadequately vetted changes, improving decision-making quality.` },
177-
{ id: 'community-veto', label: 'Community Veto', x: 1150, y: 100, width: 140, height: 48, details: `<b>Community Veto</b><br>Enables community-driven rejection through an adaptive quorum model rather than traditional thresholds.<br><i>Rationale:</i> Reduces voter fatigue and apathy, ensuring that significant opposition (rather than inactivity) stops proposals.` },
178-
{ id: 'security-veto', label: 'Security Veto', x: 1150, y: 260, width: 140, height: 48, details: `<b>Security Veto</b><br>The Security Council holds veto power over proposals posing substantial network security risks, requiring supermajority consensus.<br><i>Rationale:</i> Prioritizes network security and stability, ensuring technical integrity takes precedence.` },
179-
{ id: 'veto-outcome', label: 'Veto Outcome', x: 1400, y: 180, width: 160, height: 48, details: `Veto is a governance block that halts a proposal. After the timelock, votes are tallied, quorum checked, then veto counts are compared against community or security council thresholds. It represents a formal blockade—either by the broader community or by a specialized Security Council—signaling that critical concerns remain unresolved.` },
180-
{ id: 'veto-successful', label: 'Veto Successful', x: 1650, y: 100, width: 140, height: 48, details: `<b>Veto Successful</b><br>Proposal is transparently communicated as rejected, ending the process clearly.<br><i>Rationale:</i> Offers transparency and definitive resolution, reducing confusion or repeated proposal iterations.` },
181-
{ id: 'no-veto', label: 'No Veto', x: 1650, y: 260, width: 140, height: 48, details: `<b>No Veto</b><br>If no significant concerns are raised during the veto period, the proposal proceeds to acceptance.<br><i>Rationale:</i> Streamlines the process for uncontroversial proposals while maintaining the safety net of the veto period.` },
182-
{ id: 'fip-rejected', label: 'FIP Rejected', x: 1850, y: 100, width: 140, height: 48, details: `<b>FIP Rejected</b><br>The proposal is rejected and the process ends here.` },
183-
{ id: 'fip-accepted', label: 'FIP Accepted', x: 1850, y: 260, width: 140, height: 48, details: `<b>FIP Accepted</b><br>The proposal is accepted and moves to the implementation stage.` },
184-
{ id: 'implementers-call', label: "Implementers' Call", x: 2050, y: 260, width: 160, height: 48, details: `<b>Implementers' Call</b><br>Ensures alignment and understanding among those tasked with implementing the accepted FIP.<br><i>Rationale:</i> Secures efficient, coherent execution of proposals, avoiding misinterpretation or misalignment.` },
185-
{ id: 'fip-final', label: 'FIP Final', x: 2250, y: 260, width: 140, height: 48, details: `<b>FIP Final</b><br>Finalized proposals are clearly documented and archived for community reference, ensuring historical clarity and accountability.<br><i>Rationale:</i> Preserves institutional knowledge, facilitating ongoing transparency and accountability.` }
186-
];
187-
188-
const arrows = [
189-
{ from: 'discussion', to: 'no-fip', custom: true },
190-
{ from: 'discussion', to: 'fip-draft' },
191-
{ from: 'fip-draft', to: 'fip-editors' },
192-
{ from: 'fip-editors', to: 'fip-assigned' },
193-
{ from: 'fip-assigned', to: 'timelock' },
194-
{ from: 'timelock', to: 'community-veto' },
195-
{ from: 'timelock', to: 'security-veto' },
196-
{ from: 'community-veto', to: 'veto-outcome' },
197-
{ from: 'security-veto', to: 'veto-outcome' },
198-
{ from: 'veto-outcome', to: 'veto-successful' },
199-
{ from: 'veto-outcome', to: 'no-veto' },
200-
{ from: 'veto-successful', to: 'fip-rejected' },
201-
{ from: 'no-veto', to: 'fip-accepted' },
202-
{ from: 'fip-accepted', to: 'implementers-call' },
203-
{ from: 'implementers-call', to: 'fip-final' }
204-
];
205-
206-
const svg = document.getElementById('fip-svg');
207-
const detailsPopup = document.getElementById('fip-details-popup');
208-
const flowchartArea = document.getElementById('flowchart-area');
209-
210-
// Dynamically set SVG width and height based on node positions
211-
function getDiagramBounds(nodes) {
212-
let maxX = 0, maxY = 0;
213-
for (const n of nodes) {
214-
if (!n.label) continue;
215-
if (n.x + n.width > maxX) maxX = n.x + n.width;
216-
if (n.y + n.height > maxY) maxY = n.y + n.height;
217-
}
218-
return { width: maxX + 60, height: maxY + 40 };
219-
}
220-
221-
function renderFlowchart() {
222-
const bounds = getDiagramBounds(nodes);
223-
svg.setAttribute('width', bounds.width);
224-
svg.setAttribute('height', bounds.height);
225-
svg.innerHTML = `
226-
<defs>
227-
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto" markerUnits="strokeWidth">
228-
<polygon points="0 0, 10 3.5, 0 7" fill="#2a5d9f" />
229-
</marker>
230-
</defs>
231-
`;
232-
for (const arrow of arrows) {
233-
const from = nodes.find(n => n.id === arrow.from);
234-
const to = nodes.find(n => n.id === arrow.to);
235-
if (!from || !to) continue;
236-
let startX = from.x + from.width;
237-
let startY = from.y + from.height / 2;
238-
let endX = to.x;
239-
let endY = to.y + to.height / 2;
240-
// Custom arrow for 'no-fip' to avoid overlap
241-
if (arrow.custom && arrow.from === 'discussion' && arrow.to === 'no-fip') {
242-
svg.innerHTML += `<path d="M${startX},${startY} C${startX+30},${startY+60} ${endX-30},${endY-20} ${endX},${endY}" class="fip-arrow" />`;
243-
continue;
244-
}
245-
if (from.x === to.x) {
246-
startX = from.x + from.width / 2;
247-
startY = from.y + from.height;
248-
endX = to.x + to.width / 2;
249-
endY = to.y;
250-
}
251-
svg.innerHTML += `<path d="M${startX},${startY} C${startX+30},${startY} ${endX-30},${endY} ${endX},${endY}" class="fip-arrow" />`;
252-
}
253-
for (const node of nodes) {
254-
if (!node.label) continue;
255-
svg.innerHTML += `
256-
<g class="fip-node" data-id="${node.id}" style="cursor:pointer;">
257-
<rect x="${node.x}" y="${node.y}" width="${node.width}" height="${node.height}" class="fip-box" rx="10" />
258-
<text x="${node.x + node.width/2}" y="${node.y + node.height/2 + 6}" text-anchor="middle" class="fip-label">${node.label}</text>
259-
</g>
260-
`;
261-
if (node.roleLabel) {
262-
svg.innerHTML += `<text x="${node.x + node.width/2}" y="${node.y + node.height + 18}" text-anchor="middle" class="fip-role">${node.roleLabel}</text>`;
263-
}
264-
}
265-
}
266-
267-
renderFlowchart();
268-
269-
svg.addEventListener('click', function(e) {
270-
const pt = svg.createSVGPoint();
271-
pt.x = e.clientX;
272-
pt.y = e.clientY;
273-
const svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
274-
let found = false;
275-
for (const node of nodes) {
276-
if (!node.label) continue;
277-
if (
278-
svgP.x >= node.x && svgP.x <= node.x + node.width &&
279-
svgP.y >= node.y && svgP.y <= node.y + node.height
280-
) {
281-
found = true;
282-
detailsPopup.innerHTML = node.details;
283-
// Calculate popup position relative to the SVG and viewport
284-
const svgRect = svg.getBoundingClientRect();
285-
const areaRect = flowchartArea.getBoundingClientRect();
286-
// Box center in SVG coordinates
287-
const boxCenterX = svgRect.left + (node.x + node.width / 2);
288-
const boxBottomY = svgRect.top + node.y + node.height;
289-
// Default popup position: below the box, centered
290-
let popupLeft = boxCenterX - detailsPopup.offsetWidth / 2;
291-
let popupTop = boxBottomY + 12;
292-
// Ensure popup stays within the flowchart area horizontally
293-
const minLeft = areaRect.left + 8;
294-
const maxLeft = areaRect.right - detailsPopup.offsetWidth - 8;
295-
if (popupLeft < minLeft) popupLeft = minLeft;
296-
if (popupLeft > maxLeft) popupLeft = maxLeft;
297-
// If popup would go off the bottom, show above the box
298-
const popupHeight = detailsPopup.offsetHeight || 120;
299-
const maxBottom = window.innerHeight - 24;
300-
if (popupTop + popupHeight > maxBottom) {
301-
popupTop = boxBottomY - node.height - popupHeight - 12;
302-
}
303-
detailsPopup.style.left = popupLeft + 'px';
304-
detailsPopup.style.top = popupTop + 'px';
305-
detailsPopup.classList.add('visible');
306-
document.querySelectorAll('.fip-box').forEach(b => b.classList.remove('selected'));
307-
const allRects = svg.querySelectorAll('rect.fip-box');
308-
for (const rect of allRects) {
309-
const rx = parseFloat(rect.getAttribute('x'));
310-
const ry = parseFloat(rect.getAttribute('y'));
311-
if (rx === node.x && ry === node.y) {
312-
rect.classList.add('selected');
313-
}
314-
}
315-
break;
316-
}
317-
}
318-
if (!found) {
319-
detailsPopup.classList.remove('visible');
320-
document.querySelectorAll('.fip-box').forEach(b => b.classList.remove('selected'));
321-
}
322-
});
323-
document.body.addEventListener('click', function(e) {
324-
if (!svg.contains(e.target)) {
325-
detailsPopup.classList.remove('visible');
326-
document.querySelectorAll('.fip-box').forEach(b => b.classList.remove('selected'));
327-
}
328-
});
329-
</script>
33059
</body>
33160
</html>

0 commit comments

Comments
 (0)