Skip to content

Commit d73f8d1

Browse files
authored
Merge pull request #76 from vitruv-tools/develop
Lets deploy
2 parents d7ac8dc + d09c644 commit d73f8d1

30 files changed

+4316
-993
lines changed

public/assets/22098030.png

34.4 KB
Loading

sonar-project.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Mandatory configuration
22
sonar.projectKey=vitruv-tools_Vitruv-UI-Methodologist
33
sonar.organization=vitruv-tools
4+
sonar.host.url=https://sonarcloud.io
45

56
# Source and coverage paths
67
sonar.sources=src

src/App.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ afterEach(() => {
1414

1515
test('renders Vitruvius Modeler title', () => {
1616
render(<App />);
17-
const titleElement = screen.getByText(/vitruvius modeler/i);
18-
expect(titleElement).toBeInTheDocument();
17+
const titleHeading = screen.getByRole('heading', { name: /Metadologist Dashboard/i });
18+
expect(titleHeading).toBeInTheDocument();
1919
});

src/App.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import React from 'react';
22
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
3-
import { MainLayout, AuthPage } from './components';
3+
import { AuthPage } from './components/auth/AuthPage';
4+
import { HomePage } from './pages/HomePage';
5+
import { ProjectPage } from './pages/ProjectPage';
46
import { AuthProvider, useAuth } from './contexts/AuthContext';
57
import { apiService } from './services/api';
68
import { exportFlowData } from './utils';
79
import { Node, Edge } from 'reactflow';
810
import './App.css';
11+
import { SidebarTabs, MainLayout } from './components';
912

1013
function ProtectedRoute({ children }: { children: React.ReactNode }) {
1114
const { isAuthenticated, isLoading } = useAuth();
@@ -32,6 +35,8 @@ function ProtectedRoute({ children }: { children: React.ReactNode }) {
3235
return <>{children}</>;
3336
}
3437

38+
// Render MainLayout immediately without lazy loading for consistent UX across routes
39+
3540
function AppContent() {
3641
const { user, signOut } = useAuth();
3742

@@ -78,6 +83,8 @@ function AppContent() {
7883
onNew={handleNew}
7984
user={user}
8085
onLogout={handleLogout}
86+
leftSidebar={<SidebarTabs width={350} />}
87+
leftSidebarWidth={350}
8188
/>
8289
);
8390
}
@@ -90,7 +97,17 @@ function App() {
9097
<Route path="/auth" element={<AuthPage />} />
9198
<Route path="/" element={
9299
<ProtectedRoute>
100+
<HomePage />
101+
</ProtectedRoute>
102+
} />
103+
<Route path="/mml" element={
104+
<ProtectedRoute>
93105
<AppContent />
106+
</ProtectedRoute>
107+
} />
108+
<Route path="/project" element={
109+
<ProtectedRoute>
110+
<ProjectPage />
94111
</ProtectedRoute>
95112
} />
96113
</Routes>

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/flow/EcoreFileBox.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,8 +615,8 @@ export const EcoreFileBox: React.FC<EcoreFileBoxProps> = ({
615615

616616
<ConfirmDialog
617617
isOpen={showDeleteConfirm}
618-
title="Delete ECORE File"
619-
message={`Are you sure you want to delete "${fileName}"? This action will remove the file from the workspace but will not affect the original uploaded file.`}
618+
title="Delete ECORE File from Workspace"
619+
message={`Do you want to delete "${fileName}" from workspace?`}
620620
confirmText="Delete"
621621
cancelText="Cancel"
622622
onConfirm={confirmDelete}

src/components/flow/FlowCanvas.tsx

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { useRef, useState, forwardRef, useImperativeHandle, useEffect } from 'react';
22
import ReactFlow, {
33
MiniMap,
4-
Controls,
54
Background,
65
ReactFlowInstance,
76
Node,
@@ -54,6 +53,7 @@ export const FlowCanvas = forwardRef<{
5453
const reactFlowWrapper = useRef<HTMLDivElement>(null);
5554
const [reactFlowInstance, setReactFlowInstance] = useState<ReactFlowInstance | null>(null);
5655
const [isDragOver, setIsDragOver] = useState(false);
56+
const [isInteractive, setIsInteractive] = useState(true);
5757
const [selectedFileId, setSelectedFileId] = useState<string | null>(null);
5858
const [expandedFileId, setExpandedFileId] = useState<string | null>(null);
5959

@@ -350,9 +350,15 @@ export const FlowCanvas = forwardRef<{
350350
nodeTypes={nodeTypes}
351351
edgeTypes={edgeTypes}
352352
onInit={setReactFlowInstance}
353+
nodesDraggable={isInteractive}
354+
nodesConnectable={isInteractive}
355+
elementsSelectable={isInteractive}
356+
panOnDrag={isInteractive}
357+
panOnScroll={isInteractive}
358+
zoomOnScroll={isInteractive}
359+
zoomOnPinch={isInteractive}
353360
>
354361
<MiniMap position="bottom-right" style={{ bottom: 16, right: 16, zIndex: 30 }} />
355-
<Controls position="bottom-left" />
356362
<Background />
357363
</ReactFlow>
358364

@@ -384,6 +390,41 @@ export const FlowCanvas = forwardRef<{
384390
/>
385391
))}
386392

393+
{/* Canvas Controls anchored to wrapper so they move with sidebar resizing */}
394+
<div style={{ position: 'absolute', left: 16, bottom: 16, zIndex: 31, display: 'flex', flexDirection: 'column', gap: 6 }}>
395+
<button
396+
onClick={() => reactFlowInstance?.zoomIn?.()}
397+
style={{ width: 36, height: 36, borderRadius: 6, border: '1px solid #e5e7eb', background: '#ffffff', cursor: 'pointer' }}
398+
title="Zoom in"
399+
>
400+
+
401+
</button>
402+
<button
403+
onClick={() => reactFlowInstance?.zoomOut?.()}
404+
style={{ width: 36, height: 36, borderRadius: 6, border: '1px solid #e5e7eb', background: '#ffffff', cursor: 'pointer' }}
405+
title="Zoom out"
406+
>
407+
408+
</button>
409+
<button
410+
onClick={() => reactFlowInstance?.fitView?.({ padding: 0.2 })}
411+
style={{ width: 36, height: 36, borderRadius: 6, border: '1px solid #e5e7eb', background: '#ffffff', cursor: 'pointer' }}
412+
title="Fit view"
413+
>
414+
415+
</button>
416+
<button
417+
onClick={() => {
418+
const next = !isInteractive;
419+
setIsInteractive(next);
420+
}}
421+
style={{ width: 36, height: 36, borderRadius: 6, border: '1px solid #e5e7eb', background: '#ffffff', cursor: 'pointer' }}
422+
title={isInteractive ? 'Lock interactions' : 'Unlock interactions'}
423+
>
424+
{isInteractive ? '🔓' : '🔒'}
425+
</button>
426+
</div>
427+
387428
{isDragOver && (
388429
<div style={{
389430
position: 'absolute',

src/components/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ export { EcoreFileBox } from './flow/EcoreFileBox';
1010

1111
// UI components
1212
export { ToolsPanel } from './ui/ToolsPanel';
13+
export { SidebarTabs } from './ui/SidebarTabs';
1314
export { ConfirmDialog } from './ui/ConfirmDialog';
1415
export { CreateModelModal } from './ui/CreateModelModal';
16+
export { KeywordTagsInput } from './ui/KeywordTagsInput';
17+
export { ToastProvider, useToast } from './ui/ToastProvider';
1518

1619

1720
// Auth components

src/components/layout/Header.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface HeaderProps {
1111
onLogout?: () => void;
1212
}
1313

14-
export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderProps) {
14+
export function Header({ title = 'Metadologist Dashboard', user, onLogout }: HeaderProps) {
1515
const [isMenuOpen, setIsMenuOpen] = useState(false);
1616
const menuRef = useRef<HTMLDivElement | null>(null);
1717

@@ -62,8 +62,9 @@ export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderPr
6262
right: 0,
6363
zIndex: 20,
6464
}}>
65-
<div style={{ display: 'flex', alignItems: 'center' }}>
65+
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
6666
<h1 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>{title}</h1>
67+
6768
</div>
6869
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
6970
<div ref={menuRef} style={{ position: 'relative' }}>
@@ -72,9 +73,9 @@ export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderPr
7273
aria-haspopup="menu"
7374
aria-expanded={isMenuOpen}
7475
title={
75-
user?.name || `${user?.givenName || ''} ${user?.familyName || ''}`.trim() ||
76-
user?.email ||
77-
user?.username ||
76+
user?.name || `${user?.givenName || ''} ${user?.familyName || ''}`.trim() ||
77+
user?.email ||
78+
user?.username ||
7879
'User menu'
7980
}
8081
style={{
@@ -127,7 +128,7 @@ export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderPr
127128
}}
128129
>
129130
{/* User Info Section */}
130-
<div style={{
131+
<div style={{
131132
background: '#f8f9fa',
132133
padding: '20px',
133134
color: '#2c3e50',
@@ -168,7 +169,7 @@ export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderPr
168169
)}
169170
</div>
170171
</div>
171-
172+
172173
{/* Status Badge */}
173174
{user?.emailVerified !== undefined && (
174175
<div style={{
@@ -189,9 +190,9 @@ export function Header({ title = 'Vitruvius Modeler', user, onLogout }: HeaderPr
189190

190191
{/* Menu Actions */}
191192
<div style={{ padding: '16px' }}>
192-
<div style={{
193-
display: 'flex',
194-
flexDirection: 'column',
193+
<div style={{
194+
display: 'flex',
195+
flexDirection: 'column',
195196
gap: 8,
196197
}}>
197198
<button

0 commit comments

Comments
 (0)