Skip to content

Commit 3a95446

Browse files
authored
Merge pull request #41 from TsotneMikadze/develop
Refactor SignUp, MainLayout, MetaModelsPanel, ToolsPanel, VsumsPanel,…
2 parents 6aeadbc + 93133fe commit 3a95446

File tree

10 files changed

+743
-54
lines changed

10 files changed

+743
-54
lines changed

src/components/auth/SignUp.tsx

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,19 +214,6 @@ export function SignUp({ onSignUpSuccess, onSwitchToSignIn }: SignUpProps) {
214214
</button>
215215
</p>
216216
</div>
217-
218-
<div className="auth-divider">
219-
<span>or</span>
220-
</div>
221-
222-
<div className="demo-credentials">
223-
<p className="demo-title">API Endpoint</p>
224-
<div className="demo-info">
225-
<p>This application connects to the backend API at:</p>
226-
<p><code>http://localhost:9811/api/v1/users/sign-up</code></p>
227-
<p>Make sure your backend server is running on port 9811.</p>
228-
</div>
229-
</div>
230217
</div>
231218
</div>
232219
);

src/components/layout/MainLayout.tsx

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useEffect, useState, useRef } from 'react';
2+
import { useLocation } from 'react-router-dom';
23
import { Header } from './Header';
34
import { FlowCanvas } from '../flow/FlowCanvas';
45
import { ToolsPanel } from '../ui/ToolsPanel';
@@ -21,6 +22,7 @@ interface MainLayoutProps {
2122
topRightSlot?: React.ReactNode;
2223
showWorkspaceInfo?: boolean;
2324
workspaceTopRightSlot?: React.ReactNode;
25+
workspaceOverlay?: React.ReactNode;
2426
}
2527

2628
interface EcoreFileBox {
@@ -34,7 +36,9 @@ interface EcoreFileBox {
3436
createdAt?: string;
3537
}
3638

37-
export function MainLayout({ onDeploy, onSave, onLoad, onNew, user, onLogout, leftSidebar, leftSidebarWidth = 350, rightSidebar, rightSidebarWidth = 0, topRightSlot, showWorkspaceInfo = true, workspaceTopRightSlot }: MainLayoutProps) {
39+
export function MainLayout({ onDeploy, onSave, onLoad, onNew, user, onLogout, leftSidebar, leftSidebarWidth = 350, rightSidebar, rightSidebarWidth = 0, topRightSlot, showWorkspaceInfo = true, workspaceTopRightSlot, workspaceOverlay }: MainLayoutProps) {
40+
const location = useLocation();
41+
const isMMLRoute = location.pathname.startsWith('/mml');
3842
const [selectedDiagramType, setSelectedDiagramType] = useState<string | undefined>();
3943
const flowCanvasRef = useRef<any>(null);
4044
const leftAsideRef = useRef<HTMLDivElement | null>(null);
@@ -453,7 +457,7 @@ export function MainLayout({ onDeploy, onSave, onLoad, onNew, user, onLogout, le
453457
)}
454458

455459
{/* Top-right workspace document panel (separate from ToolsPanel) */}
456-
{activeDocId && (
460+
{activeDocId && !isMMLRoute && (
457461
<div style={{ position: 'absolute', right: 16 + (rightSidebarWidth || 0), top: 56, zIndex: 25 }}>
458462
<div style={{
459463
background: '#ffffff',
@@ -546,7 +550,7 @@ export function MainLayout({ onDeploy, onSave, onLoad, onNew, user, onLogout, le
546550
)}
547551

548552
{/* Workspace info panel */}
549-
{showWorkspaceInfo && (
553+
{showWorkspaceInfo && !isMMLRoute && (
550554
<div style={{ position: 'absolute', left: 16, top: 56, zIndex: 25 }}>
551555
<div style={{
552556
background: '#ffffff',
@@ -577,19 +581,60 @@ export function MainLayout({ onDeploy, onSave, onLoad, onNew, user, onLogout, le
577581

578582
<div style={{ flexGrow: 1, position: 'relative', display: 'flex' }}>
579583
<div style={{ flexGrow: 1, position: 'relative', display: 'flex' }}>
580-
<FlowCanvas
581-
onDeploy={onDeploy}
582-
onDiagramChange={handleDiagramChange}
583-
ref={flowCanvasRef}
584-
ecoreFiles={ecoreFileBoxes}
585-
onEcoreFileSelect={handleEcoreFileSelect}
586-
onEcoreFileExpand={handleEcoreFileExpand}
587-
onEcoreFilePositionChange={handleEcoreFilePositionChange}
588-
onEcoreFileDelete={handleEcoreFileDelete}
589-
onEcoreFileRename={handleEcoreFileRename}
590-
/>
591-
{workspaceTopRightSlot && (
592-
<div style={{ position: 'absolute', right: 16, top: 60, zIndex: 15 }}>
584+
{workspaceOverlay && (
585+
<div style={{ position: 'absolute', left: 0, right: 0, top: 48, zIndex: 20, pointerEvents: 'none' }}>
586+
<div style={{ pointerEvents: 'auto' }}>
587+
{workspaceOverlay}
588+
</div>
589+
</div>
590+
)}
591+
{isMMLRoute ? (
592+
<div style={{
593+
width: '100%',
594+
height: '100%',
595+
background: '#ffffff',
596+
display: 'flex',
597+
flexDirection: 'column',
598+
alignItems: 'center',
599+
justifyContent: 'center',
600+
padding: '40px'
601+
}}>
602+
<div style={{
603+
textAlign: 'center',
604+
fontFamily: 'Georgia, serif',
605+
color: '#2c3e50',
606+
maxWidth: '600px'
607+
}}>
608+
<img
609+
src="/assets/22098030.png"
610+
alt="Vitruvius"
611+
style={{
612+
width: '200px',
613+
height: '200px',
614+
objectFit: 'contain',
615+
marginBottom: '30px'
616+
}}
617+
/>
618+
<p style={{ margin: '0 0 20px 0', fontSize: '16px', color: '#6b7280', lineHeight: '1.6' }}>
619+
Meta Model Management Platform
620+
</p>
621+
</div>
622+
</div>
623+
) : (
624+
<FlowCanvas
625+
onDeploy={onDeploy}
626+
onDiagramChange={handleDiagramChange}
627+
ref={flowCanvasRef}
628+
ecoreFiles={ecoreFileBoxes}
629+
onEcoreFileSelect={handleEcoreFileSelect}
630+
onEcoreFileExpand={handleEcoreFileExpand}
631+
onEcoreFilePositionChange={handleEcoreFilePositionChange}
632+
onEcoreFileDelete={handleEcoreFileDelete}
633+
onEcoreFileRename={handleEcoreFileRename}
634+
/>
635+
)}
636+
{workspaceTopRightSlot && !isMMLRoute && (
637+
<div style={{ position: 'absolute', right: 16, top: 60, zIndex: 30 }}>
593638
{workspaceTopRightSlot}
594639
</div>
595640
)}

src/components/ui/MetaModelsPanel.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import React, { useEffect, useState } from 'react';
22
import { apiService } from '../../services/api';
33

4+
interface MetaModelsPanelProps {
5+
activeVsumId?: number | null;
6+
selectedMetaModelIds?: number[];
7+
onAddToActiveVsum?: (model: any) => void;
8+
}
9+
410
const containerStyle: React.CSSProperties = {
511
userSelect: 'none',
612
width: '100%',
@@ -139,7 +145,7 @@ const paginationButtonDisabledStyle: React.CSSProperties = {
139145
cursor: 'not-allowed',
140146
};
141147

142-
export const MetaModelsPanel: React.FC = () => {
148+
export const MetaModelsPanel: React.FC<MetaModelsPanelProps> = ({ activeVsumId, selectedMetaModelIds, onAddToActiveVsum }) => {
143149
const [searchTerm, setSearchTerm] = useState('');
144150
const [sortBy, setSortBy] = useState<'name' | 'date' | 'domain'>('date');
145151
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
@@ -164,6 +170,7 @@ export const MetaModelsPanel: React.FC = () => {
164170
while (end < value.length && !/\s/.test(value[end])) end++;
165171
const token = value.slice(start, end);
166172
const lower = token.toLowerCase().replace(/:$/, '');
173+
if (!lower) return;
167174

168175
const candidates = ['name', 'description', 'domain', 'keywords', 'created', 'updated'];
169176
const match = candidates.find(k => k.startsWith(lower));
@@ -206,7 +213,7 @@ export const MetaModelsPanel: React.FC = () => {
206213
break;
207214
}
208215
} else {
209-
filters.push({ key: 'name', value: part });
216+
// Ignore bare tokens (no default name:)
210217
}
211218
}
212219
return filters;
@@ -500,6 +507,20 @@ export const MetaModelsPanel: React.FC = () => {
500507
<span>Domain: <strong>{model.domain}</strong></span>
501508
<span></span>
502509
<span title={new Date(model.createdAt).toLocaleString()}>{formatRelativeTime(model.createdAt)}</span>
510+
{activeVsumId ? (
511+
<>
512+
<span></span>
513+
{onAddToActiveVsum && (
514+
<button
515+
onClick={() => onAddToActiveVsum(model)}
516+
style={{ padding: '4px 8px', border: '1px solid #dee2e6', borderRadius: 6, background: '#ffffff', cursor: 'pointer', fontSize: 12, fontWeight: 600 }}
517+
disabled={(selectedMetaModelIds || []).includes(model.id)}
518+
>
519+
{(selectedMetaModelIds || []).includes(model.id) ? 'Added' : 'Add to vSUM'}
520+
</button>
521+
)}
522+
</>
523+
) : null}
503524
</div>
504525
</div>
505526
))}

src/components/ui/ToolsPanel.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export const ToolsPanel: React.FC<ToolsPanelProps> = ({ onEcoreFileUpload, onEco
334334
const token = value.slice(start, end);
335335
const lower = token.toLowerCase().replace(/:$/, '');
336336

337-
const candidates = ['name', 'description', 'domain', 'keywords', 'created', 'updated'];
337+
const candidates = ['name', 'description', 'domain', 'keywords', 'created', 'updated', 'time'];
338338
const match = candidates.find(k => k.startsWith(lower));
339339
const replacement = match ? `${match}:` : null;
340340
if (!replacement) return;
@@ -411,11 +411,11 @@ export const ToolsPanel: React.FC<ToolsPanelProps> = ({ onEcoreFileUpload, onEco
411411
}
412412
default:
413413
// Unknown key: treat as name
414-
result.push({ key: 'name', value: `${key}:${cleanValue}`, display: `name:${key}:${cleanValue}` });
414+
// result.push({ key: 'name', value: `${key}:${cleanValue}`, display: `name:${key}:${cleanValue}` });
415415
}
416416
} else if (token.trim().length > 0) {
417417
// Bare word -> name search
418-
result.push({ key: 'name', value: token, display: `name:${token}` });
418+
// result.push({ key: 'name', value: token, display: `name:${token}` });
419419
}
420420
}
421421

@@ -783,13 +783,16 @@ export const ToolsPanel: React.FC<ToolsPanelProps> = ({ onEcoreFileUpload, onEco
783783
<input
784784
type="text"
785785
placeholder="Filter by name..."
786-
value={searchTerm.includes(':') ? '' : searchTerm}
787-
onChange={(e) => {
788-
if (!e.target.value.includes(':')) {
789-
setSearchTerm(e.target.value);
786+
style={filterInputStyle}
787+
onKeyDown={(e) => {
788+
if (e.key === 'Enter') {
789+
const value = e.currentTarget.value.trim();
790+
if (value) {
791+
setSearchTerm(prev => prev ? `${prev} name:${value}` : `name:${value}`);
792+
e.currentTarget.value = '';
793+
}
790794
}
791795
}}
792-
style={filterInputStyle}
793796
/>
794797
</div>
795798

0 commit comments

Comments
 (0)