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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "essentials-web-config-app",
"version": "0.1.0",
"version": "1.0.0-local",
"type": "module",
"private": true,
"dependencies": {
Expand Down
6 changes: 2 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,10 @@ function App() {
<Suspense fallback={null}>
<Routes>
<Route path="/" element={<Navigate to="/login" replace />} />
<Route path="/login" element={<MainLayout isConnected={isConnected} />}>
<Route index element={<LoginForm />} />
</Route>
<Route path="/login" element={<LoginForm />} />

<Route path=":appId/login" element={<LoginForm />} />
<Route path=":appId" element={<MainLayout isConnected={isConnected} />}>
<Route path="login" element={<LoginForm />} />
<Route element={<RequireAuth />}>
<Route path="versions" element={<Versions />} />
<Route path="apiPaths" element={<ApiPaths />} />
Expand Down
2 changes: 1 addition & 1 deletion src/features/DebugConsole/DebugFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const DebugFilters = () => {
<div className="col-12 d-none d-lg-block">
<DeviceFilterDropdown items={items} />
<Button
variant="outline"
variant="outline-secondary"
className="py-1 ms-1"
onClick={() => dispatch(debugConsoleActions.clearAllFilters())}
>
Expand Down
12 changes: 5 additions & 7 deletions src/features/InitializationExceptions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { skipToken } from "@reduxjs/toolkit/query";
import { useState } from "react";
import { Fragment, useState } from "react";
import useAppParams from "../shared/hooks/useAppParams";
import {
EssentialsException,
Expand All @@ -12,8 +12,6 @@ const InitializationExceptions = () => {
appId ? { appId } : skipToken,
);

console.log("Initialization exceptions:", data?.Exceptions);

const [expandedIndex, setExpandedIndex] = useState<number | null>(null);

if (isLoading) return <div className="p-3">Loading…</div>;
Expand Down Expand Up @@ -48,8 +46,8 @@ const InitializationExceptions = () => {
{data.Exceptions.map((ex: EssentialsException, idx: number) => {
const isExpanded = expandedIndex === idx;
return (
<>
<tr key={`ex-${idx}`}>
<Fragment key={`ex-${idx}`}>
<tr>
<td className="text-muted">{idx + 1}</td>
<td>
<span className="text-danger fw-semibold">
Expand All @@ -70,7 +68,7 @@ const InitializationExceptions = () => {
</td>
</tr>
{isExpanded && ex.StackTrace && (
<tr key={`ex-${idx}-trace`}>
<tr>
<td colSpan={3} className="p-0">
<pre
className="m-0 p-3 bg-light text-muted"
Expand All @@ -81,7 +79,7 @@ const InitializationExceptions = () => {
</td>
</tr>
)}
</>
</Fragment>
);
})}
</tbody>
Expand Down
9 changes: 6 additions & 3 deletions src/features/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Alert, Button, Form, Spinner } from 'react-bootstrap';
import { Navigate, useLocation, useNavigate } from 'react-router-dom';
import useAppParams from '../shared/hooks/useAppParams';
import { useSetLoginCredentialsMutation } from '../store/apiSlice';
import { selectIsAuthenticated } from '../store/auth/authSelectors';
import { selectAvailableApps, selectIsAuthenticated } from '../store/auth/authSelectors';
import { authActions } from '../store/auth/authSlice';
import { useAppDispatch, useAppSelector } from '../store/hooks';

Expand All @@ -15,6 +15,7 @@ const ALL_APP_IDS = [
const LoginForm = () => {
const { appId } = useAppParams();
const isAuthenticated = useAppSelector(selectIsAuthenticated);
const discoveredApps = useAppSelector(selectAvailableApps);
const dispatch = useAppDispatch();
Comment thread
ndorin marked this conversation as resolved.
const navigate = useNavigate();
const location = useLocation();
Expand All @@ -30,9 +31,10 @@ const LoginForm = () => {

const isValidAppId = appId && ALL_APP_IDS.includes(appId);
const probeAppId = isValidAppId ? appId : ALL_APP_IDS[0];
const safeAppId = isValidAppId ? appId : (discoveredApps[0] ?? probeAppId);

if (isAuthenticated) {
return <Navigate to={from ?? `/${appId}/versions`} replace />;
return <Navigate to={from ?? `/${safeAppId}/versions`} replace />;
}

async function handleSubmit(e: FormEvent) {
Expand Down Expand Up @@ -68,7 +70,8 @@ const LoginForm = () => {
}

return (
<div className="d-flex justify-content-center align-items-center h-100">
<div className="d-flex flex-column justify-content-center align-items-center h-100">
<h1 className="mb-5 text-center">PepperDash Essentials Developer Tools</h1>
<div className="w-100" style={{ maxWidth: '360px' }}>
<h2 className="mb-4">Sign In</h2>
{error && <Alert variant="danger">{error}</Alert>}
Expand Down
1 change: 0 additions & 1 deletion src/features/MobileControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {

const MobileControl = () => {
const { appId } = useAppParams();
console.log("AppId in MobileControl", appId);

const { data: info } = useGetMobileControlInfoQuery(
appId ? { appId, deviceKey: "appServer" } : skipToken,
Expand Down
60 changes: 39 additions & 21 deletions src/features/Routing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import dagre from "dagre";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Dropdown } from "react-bootstrap";

import { meetsMinVersion } from '../shared/functions/meetsMinimumVersion';
import { meetsMinVersion } from "../shared/functions/meetsMinimumVersion";
import useAppParams from "../shared/hooks/useAppParams";
import {
RoutingDevice,
Expand Down Expand Up @@ -125,13 +125,20 @@ function buildGraph(
: d,
);

const effectiveDeviceKeys = new Set(effectiveDevices.map((d) => d.key));
// Collect one unique device-pair edge per source→destination (dagre only
// needs connectivity, not multiplicity, for rank assignment).
// needs connectivity, not multiplicity, for rank assignment). Only use
// visible tie lines whose endpoints are present in the visible device set
// so hidden devices cannot be implicitly added to the layout graph.
const uniquePairs = [
...new Set(
data.tieLines.map(
(tl) => `${tl.sourceDeviceKey}|${tl.destinationDeviceKey}`,
),
visibleTieLines
.filter(
(tl) =>
effectiveDeviceKeys.has(tl.sourceDeviceKey) &&
effectiveDeviceKeys.has(tl.destinationDeviceKey),
)
.map((tl) => `${tl.sourceDeviceKey}|${tl.destinationDeviceKey}`),
),
];

Expand Down Expand Up @@ -172,18 +179,20 @@ function buildGraph(
dagre.layout(g);

// Map dagre positions → React Flow nodes
const nodes: Node<RoutingDeviceNodeData>[] = effectiveDevices.map((device) => {
const pos = g.node(device.key);
return {
id: device.key,
type: "routingDevice",
position: {
x: pos.x - NODE_WIDTH / 2,
y: pos.y - nodeHeight(device) / 2,
},
data: { device },
};
});
const nodes: Node<RoutingDeviceNodeData>[] = effectiveDevices.map(
(device) => {
const pos = g.node(device.key);
return {
id: device.key,
type: "routingDevice",
position: {
x: pos.x - NODE_WIDTH / 2,
y: pos.y - nodeHeight(device) / 2,
},
data: { device },
};
},
);

// Map tieLines → React Flow edges, filtering by hidden signal types and hidden devices.
// All tie lines are rendered regardless of whether they were excluded from
Expand Down Expand Up @@ -223,7 +232,6 @@ function uniqueSignalTypes(tieLines: TieLine[]): string[] {
return [...new Set(tieLines.map((tl) => tl.signalType))].sort();
}


// ─── Node types registry (stable reference outside component) ────────────────

const nodeTypes: NodeTypes = {
Expand Down Expand Up @@ -305,7 +313,16 @@ const Routing = () => {
);
setEdges(layoutEdges);
setSelectedEdgeId(null);
}, [data, hiddenTypes, hideUnconnected, hiddenDevices, hideUnconnectedPorts, darkMode, setNodes, setEdges]);
}, [
data,
hiddenTypes,
hideUnconnected,
hiddenDevices,
hideUnconnectedPorts,
darkMode,
setNodes,
setEdges,
]);

// Re-style edges when selection changes without triggering a layout rebuild.
useEffect(() => {
Expand Down Expand Up @@ -402,7 +419,6 @@ const Routing = () => {
if (isError || !data)
return <div className="p-3 text-danger">Failed to load routing data.</div>;


if (
versions &&
!versions.some(
Expand Down Expand Up @@ -572,7 +588,9 @@ const Routing = () => {
</div>

{/* React Flow canvas */}
<div className={`flex-grow-1 position-relative${darkMode ? " bg-dark" : ""}`}>
<div
className={`flex-grow-1 position-relative${darkMode ? " bg-dark" : ""}`}
>
<ReactFlow
nodes={nodes}
edges={edges}
Expand Down
Loading