ui: migrate ControllerPage.js off Semantic UI onto the token component library

Replaces semantic-ui-react and Theme.tsx imports with components from
components/ui (Panel, Table, Modal, Confirm, Status, Select, TextInput,
Checkbox, IconButton, Message). Preserves every confirmation, disabled
state, and polling interval; service status now maps onto Status'
complete/active/pending/failed kinds instead of a raw color. Repairs
ControllerPage.test.js to render inside MantineProvider and to find the
unmount Confirm button by dialog role instead of DOM-order position,
since Mantine portals the modal ahead of the page content. Drops
ControllerPage.js from semantic-baseline.json now that it's migrated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Roland 2026-07-30 13:23:59 -06:00
parent ebd32f0864
commit 9529d78885
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
3 changed files with 343 additions and 334 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,9 @@
import React from 'react';
import {fireEvent, render, screen, waitFor} from '@testing-library/react';
import {fireEvent, render, screen, waitFor, within} from '@testing-library/react';
import {BrowserRouter} from 'react-router';
import {MantineProvider} from '@mantine/core';
import {ThemeContext, SettingsContext} from '../../contexts/contexts';
import {cssVariablesResolver, mantineTheme} from '../../themes/mantine';
import {ControllerPage} from './ControllerPage';
// Mock the controller API
@ -134,11 +136,13 @@ const defaultSettings = {
const renderControllerPage = () => {
return render(
<BrowserRouter>
<ThemeContext.Provider value={defaultTheme}>
<SettingsContext.Provider value={defaultSettings}>
<ControllerPage/>
</SettingsContext.Provider>
</ThemeContext.Provider>
<MantineProvider theme={mantineTheme} cssVariablesResolver={cssVariablesResolver}>
<ThemeContext.Provider value={defaultTheme}>
<SettingsContext.Provider value={defaultSettings}>
<ControllerPage/>
</SettingsContext.Provider>
</ThemeContext.Provider>
</MantineProvider>
</BrowserRouter>
);
};
@ -279,9 +283,11 @@ describe('DiskSection primary unmount', () => {
expect(screen.getByText(/API service will/)).toBeInTheDocument();
});
// Semantic's Confirm renders confirmButton='Unmount' as the last match.
const buttons = screen.getAllByText('Unmount');
fireEvent.click(buttons[buttons.length - 1]);
// The Confirm modal is portaled to the end of <body>, so it renders
// *before* the page content in DOM order -- scope the query to the
// dialog rather than assuming which match comes last.
const dialog = screen.getByRole('dialog');
fireEvent.click(within(dialog).getByText('Unmount'));
await waitFor(() => {
expect(controllerApi.unmountDisk).toHaveBeenCalledWith('/media/wrolpi');

View file

@ -12,6 +12,5 @@
"src/components/Upload.js",
"src/components/VideoPlayer.js",
"src/components/Zim.js",
"src/components/admin/ControllerPage.js",
"src/components/admin/Downloads.js"
]