Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions AUTHENTICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The authentication system provides:
## API Endpoints

### Sign Up
- **URL**: `POST http://localhost:9811/api/v1/users/sign-up`
- **URL**: `POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/sign-up`
- **Request Body**:
```json
{
Expand All @@ -34,7 +34,7 @@ The authentication system provides:
```

### Sign In
- **URL**: `POST http://localhost:9811/api/v1/users/login`
- **URL**: `POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/login`
- **Request Body**:
```json
{
Expand All @@ -57,7 +57,7 @@ The authentication system provides:
```

### Token Refresh
- **URL**: `POST http://localhost:9811/api/v1/users/access-token/by-refresh-token`
- **URL**: `POST http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080/api/v1/users/access-token/by-refresh-token`
- **Request Body**:
```json
{
Expand Down Expand Up @@ -235,7 +235,7 @@ function TokenManagement() {
### Backend URL
The backend URL is configured in `src/services/auth.ts`:
```typescript
private static readonly LOCAL_API_BASE_URL = 'http://localhost:9811';
private static readonly LOCAL_API_BASE_URL = 'http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080';
```

### Token Storage
Expand Down Expand Up @@ -269,7 +269,7 @@ The system provides comprehensive error handling:

To test the authentication system:

1. Ensure your backend server is running on `localhost:9811`
1. Ensure your backend server is running on `http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080`
2. Use the sign-up form to create a new account
3. Use the sign-in form to authenticate
4. Check the browser's developer tools to see stored tokens
Expand Down
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ---------- build stage ----------
FROM node:20-alpine AS build
WORKDIR /app

COPY package*.json ./
RUN npm ci --no-audit

COPY . .
# build the app
RUN npm run build

# normalize output dir to /app/out (supports Vite 'dist' or CRA 'build')
RUN set -eux; \
if [ -d dist ]; then \
cp -r dist out; \
elif [ -d build ]; then \
cp -r build out; \
else \
echo "ERROR: No build output dir found (looked for 'dist' and 'build')."; \
echo "Listing /app after build:"; ls -la; \
exit 1; \
fi; \
ls -la out

# ---------- runtime stage ----------
FROM nginx:1.27-alpine
# nginx config (we already created frontend/docker/nginx.conf earlier)
COPY docker/nginx.conf /etc/nginx/nginx.conf
# built static assets
COPY --from=build /app/out /usr/share/nginx/html
32 changes: 3 additions & 29 deletions src/components/ui/VsumTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ export const VsumTabs: React.FC<VsumTabsProps> = ({ openVsums, activeVsumId, onA
const edit = edits[id];
const details = detailsById[id];
if (!edit || !details) { map[id] = false; return; }
const detailsSourceIds = (details.metaModels || [])
.map(m => (typeof m.sourceId === 'number' ? m.sourceId : undefined))
.filter((v): v is number => typeof v === 'number');
map[id] = !areIdArraysEqual(edit.metaModelSourceIds, detailsSourceIds);
map[id] = !areIdArraysEqual(edit.metaModelSourceIds);
});
return map;
}, [openVsums, edits, detailsById]);
Expand All @@ -48,13 +45,6 @@ export const VsumTabs: React.FC<VsumTabsProps> = ({ openVsums, activeVsumId, onA
try {
const res = await apiService.getVsumDetails(id);
setDetailsById(prev => ({ ...prev, [id]: res.data }));
const seededSourceIds = (res.data.metaModels || [])
.map(m => (typeof m.sourceId === 'number' ? m.sourceId : undefined))
.filter((v): v is number => typeof v === 'number');
setEdits(prev => ({
...prev,
[id]: { metaModelSourceIds: seededSourceIds }
}));
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to load VSUM details');
}
Expand All @@ -72,9 +62,7 @@ export const VsumTabs: React.FC<VsumTabsProps> = ({ openVsums, activeVsumId, onA
const edit = edits[id];

// fallback from details using sourceId
const fallbackSourceIds = (detailsById[id]?.metaModels || [])
.map(m => (typeof m.sourceId === 'number' ? m.sourceId : undefined))
.filter((v): v is number => typeof v === 'number');
const fallbackSourceIds = (detailsById[id]?.metaModels);

const metaModelSourceIds =
override?.metaModelSourceIds ?? edit?.metaModelSourceIds ?? fallbackSourceIds;
Expand All @@ -96,16 +84,6 @@ export const VsumTabs: React.FC<VsumTabsProps> = ({ openVsums, activeVsumId, onA
const res = await apiService.getVsumDetails(id);
setDetailsById(prev => ({ ...prev, [id]: res.data }));

// sync local edits with server (by sourceId again)
const serverSourceIds = (res.data.metaModels || [])
.map(m => (typeof m.sourceId === 'number' ? m.sourceId : undefined))
.filter((v): v is number => typeof v === 'number');

setEdits(prev => ({
...prev,
[id]: { metaModelSourceIds: serverSourceIds },
}));

window.dispatchEvent(new CustomEvent('vitruv.refreshVsums'));
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to save VSUM');
Expand Down Expand Up @@ -133,11 +111,7 @@ export const VsumTabs: React.FC<VsumTabsProps> = ({ openVsums, activeVsumId, onA

if (typeof sourceId !== 'number') return;

const current = edits[activeVsumId] || {
metaModelSourceIds: (detailsById[activeVsumId!]?.metaModels || [])
.map(m => (typeof m.sourceId === 'number' ? m.sourceId : undefined))
.filter((v): v is number => typeof v === 'number')
};
const current = edits[activeVsumId];

if (current.metaModelSourceIds.includes(sourceId)) return;

Expand Down
78 changes: 50 additions & 28 deletions src/components/ui/VsumsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,37 +223,59 @@ export const VsumsPanel: React.FC = () => {

<div style={sectionStyle}>All</div>

{items.map((item) => (
<div
key={item.id}
style={cardStyle}
onDoubleClick={() =>
window.dispatchEvent(new CustomEvent('vitruv.openVsum', { detail: { id: item.id } }))
}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ fontWeight: 700, color: '#2c3e50' }}>{item.name}</div>
<div style={{ fontSize: 12, color: '#5a6c7d' }}>
Created: {formatDateTime(item.createdAt)}
{items.map((item) => {
const role = (item as any).role as string | undefined;
const canManage = role === 'OWNER';
return (
<div
key={item.id}
style={cardStyle}
onDoubleClick={() =>
window.dispatchEvent(new CustomEvent('vitruv.openVsum', { detail: { id: item.id } }))
}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ fontWeight: 700, color: '#2c3e50', display: 'flex', alignItems: 'center', gap: 8 }}>
{item.name}
{role && (
<span
style={{
padding: '2px 6px',
borderRadius: 6,
fontSize: 11,
fontWeight: 700,
border: '1px solid #e5e7eb',
background: role === 'OWNER' ? '#ecfdf5' : '#f3f4f6',
color: role === 'OWNER' ? '#065f46' : '#374151',
}}
>
{role}
</span>
)}
</div>
<div style={{ fontSize: 12, color: '#5a6c7d' }}>Created: {formatDateTime(item.createdAt)}</div>
</div>

{canManage && (
<button
onClick={() => setDetailsId(item.id)}
style={{
padding: '6px 10px',
border: '1px solid #dee2e6',
borderRadius: 6,
background: '#ffffff',
cursor: 'pointer',
fontWeight: 600,
}}
>
Details
</button>
)}
</div>
<button
onClick={() => setDetailsId(item.id)}
style={{
padding: '6px 10px',
border: '1px solid #dee2e6',
borderRadius: 6,
background: '#ffffff',
cursor: 'pointer',
fontWeight: 600,
}}
>
Details
</button>
</div>
</div>
))}
);
})}

{!loading && items.length === 0 && (
<div style={{ textAlign: 'center', color: '#6b7280', marginTop: 40, fontStyle: 'italic' }}>
Expand Down
2 changes: 1 addition & 1 deletion src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ApiService {
private baseURL: string;

constructor() {
this.baseURL = 'http://localhost:9811';
this.baseURL = 'http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/services/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface User {

export class AuthService {
private static readonly API_BASE_URL = 'https://api-stage.cyruswallet.io';
private static readonly LOCAL_API_BASE_URL = 'http://localhost:9811';
private static readonly LOCAL_API_BASE_URL = 'http://fe3ab829-d558-4834-afcf-6ed7ca440ca4.ka.bw-cloud-instance.org:8080';
private static readonly CLIENT_ID = 'exit-normal-customer-mobile-app';
private static readonly GRANT_TYPE = 'password';

Expand Down
7 changes: 1 addition & 6 deletions src/types/vsum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,11 @@ export interface Vsum {

export interface VsumMetaModelRef {
id: number;
sourceId: number;
name: string;
description: string;
domain: string;
keyword: string[];
role: string;
createdAt: string;
updatedAt: string;
removedAt?: string | null;
ecoreFileId: number;
genModelFileId: number;
}

export interface VsumDetails extends Vsum {
Expand Down
Loading