mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 15:36:33 +00:00
fix(docsync): give the sync flow its own TREK icon and restore the wordmark
The document-sync flow needed TREK's square app icon next to the provider glyphs, and the PR got it by rewriting the shared TrekMark component. TrekMark is the wordmark with the API pill that the admin Places API card, the mobile admin block and the release notes popup draw, so all three showed the app icon instead, and AdminSettingsTab FE-ADMSET-031 failed on the missing "TREK Places API" image. TrekMark is back to its dev version. The app icon now lives in TrekIcon, which DocSyncFlow and MDocSyncSheet use. AddonManager had also switched Synology Photos to the Synology Drive glyph, which renders as a block and sat off-line from the Immich row under Journey. Photos keeps its own icon again. The new Documents shelf gets tests: its rows and glyphs, staying out of the addon count, hiding while Documents is off, the re-read after Documents is switched off, and a provider toggle that saves without re-reading.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// FE-ADMIN-ADDON-001 to FE-ADMIN-ADDON-025
|
||||
// FE-ADMIN-ADDON-001 to FE-ADMIN-ADDON-036
|
||||
import { render, screen, waitFor } from '../../../tests/helpers/render';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { delay, http, HttpResponse } from 'msw';
|
||||
@@ -418,7 +418,102 @@ describe('AddonManager', () => {
|
||||
expect(isOn(addonToggle('Todo List'))).toBe(true);
|
||||
});
|
||||
|
||||
it('FE-ADMIN-ADDON-018: the collab sub-features render their state and report the toggled key', async () => {
|
||||
it('FE-ADMIN-ADDON-033: document providers hang off Documents with their glyphs and stay out of the count', async () => {
|
||||
server.use(addonsRoute([
|
||||
buildAddon({ id: 'documents', name: 'Documents', icon: 'FileText', enabled: true }),
|
||||
buildAddon({ id: 'journey', name: 'Journey', type: 'global', icon: 'Compass', enabled: false }),
|
||||
buildAddon({ id: 'paperless', name: 'Paperless-ngx', description: 'Document archive', type: 'document_provider', enabled: true }),
|
||||
buildAddon({ id: 'nextcloud', name: 'Nextcloud', description: 'WebDAV files', type: 'document_provider', enabled: false }),
|
||||
]));
|
||||
render(<AddonManager />);
|
||||
|
||||
await screen.findByText('Paperless-ngx');
|
||||
const paperlessRow = screen.getByText('Paperless-ngx').closest('li') as HTMLElement;
|
||||
expect(paperlessRow.querySelector('svg')).toBeInTheDocument();
|
||||
expect(isOn(subToggle('Paperless-ngx'))).toBe(true);
|
||||
expect(isOn(subToggle('Nextcloud'))).toBe(false);
|
||||
// Documents and Journey are the addons; an enabled provider is a shelf row
|
||||
// and must not turn 1/2 into 2/2.
|
||||
expect(screen.getByText('1/2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('FE-ADMIN-ADDON-034: document providers stay hidden while Documents itself is off', async () => {
|
||||
server.use(addonsRoute([
|
||||
buildAddon({ id: 'documents', name: 'Documents', icon: 'FileText', enabled: false }),
|
||||
buildAddon({ id: 'paperless', name: 'Paperless-ngx', type: 'document_provider', enabled: true }),
|
||||
]));
|
||||
render(<AddonManager />);
|
||||
|
||||
await screen.findByText('Documents');
|
||||
expect(screen.queryByText('Paperless-ngx')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('FE-ADMIN-ADDON-035: switching Documents off and on again shows the cascaded providers as off', async () => {
|
||||
const user = userEvent.setup();
|
||||
let loads = 0;
|
||||
let documentsOn = true;
|
||||
let paperlessOn = true;
|
||||
server.use(
|
||||
http.get('/api/admin/addons', () => {
|
||||
loads += 1;
|
||||
return HttpResponse.json({
|
||||
addons: [
|
||||
buildAddon({ id: 'documents', name: 'Documents', icon: 'FileText', enabled: documentsOn }),
|
||||
buildAddon({ id: 'paperless', name: 'Paperless-ngx', type: 'document_provider', enabled: paperlessOn }),
|
||||
],
|
||||
});
|
||||
}),
|
||||
http.put('/api/admin/addons/documents', async ({ request }) => {
|
||||
documentsOn = (await request.json() as { enabled: boolean }).enabled;
|
||||
if (!documentsOn) paperlessOn = false;
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
);
|
||||
render(<><ToastContainer /><AddonManager /></>);
|
||||
await screen.findByText('Paperless-ngx');
|
||||
|
||||
await user.click(addonToggle('Documents'));
|
||||
await screen.findByText('Addon updated');
|
||||
expect(loads).toBe(2);
|
||||
expect(screen.queryByText('Paperless-ngx')).not.toBeInTheDocument();
|
||||
|
||||
await user.click(addonToggle('Documents'));
|
||||
|
||||
await screen.findByText('Paperless-ngx');
|
||||
expect(isOn(subToggle('Paperless-ngx'))).toBe(false);
|
||||
});
|
||||
|
||||
it('FE-ADMIN-ADDON-036: toggling a document provider persists it without re-reading the list', async () => {
|
||||
const user = userEvent.setup();
|
||||
let loads = 0;
|
||||
let body: unknown = null;
|
||||
server.use(
|
||||
http.get('/api/admin/addons', () => {
|
||||
loads += 1;
|
||||
return HttpResponse.json({
|
||||
addons: [
|
||||
buildAddon({ id: 'documents', name: 'Documents', icon: 'FileText', enabled: true }),
|
||||
buildAddon({ id: 'papra', name: 'Papra', type: 'document_provider', enabled: false }),
|
||||
],
|
||||
});
|
||||
}),
|
||||
http.put('/api/admin/addons/papra', async ({ request }) => {
|
||||
body = await request.json();
|
||||
return HttpResponse.json({ success: true });
|
||||
}),
|
||||
);
|
||||
render(<><ToastContainer /><AddonManager /></>);
|
||||
await screen.findByText('Papra');
|
||||
|
||||
await user.click(subToggle('Papra'));
|
||||
|
||||
await screen.findByText('Addon updated');
|
||||
expect(body).toEqual({ enabled: true });
|
||||
expect(loads).toBe(1);
|
||||
expect(isOn(subToggle('Papra'))).toBe(true);
|
||||
});
|
||||
|
||||
it('FE-ADMIN-ADDON-018:the collab sub-features render their state and report the toggled key', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onToggleCollabFeature = vi.fn();
|
||||
server.use(addonsRoute([buildAddon({ id: 'collab', name: 'Collab', enabled: true })]));
|
||||
|
||||
@@ -9,7 +9,7 @@ import CustomSelect from '../shared/CustomSelect'
|
||||
import EmptyState from '../shared/EmptyState'
|
||||
import DawarichIcon from '../shared/DawarichIcon'
|
||||
import AirTrailIcon from '../shared/AirTrailIcon'
|
||||
import { DOCUMENT_PROVIDER_ICONS, SynologyDriveIcon } from '../shared/DocumentProviderIcons'
|
||||
import { DOCUMENT_PROVIDER_ICONS } from '../shared/DocumentProviderIcons'
|
||||
import AddonTile from './AddonTile'
|
||||
import AddonSubRow from './AddonSubRow'
|
||||
|
||||
@@ -31,10 +31,17 @@ function ImmichIcon({ size = 14 }: { size?: number }) {
|
||||
)
|
||||
}
|
||||
|
||||
function SynologyIcon({ size = 14 }: { size?: number }) {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" width={size} height={size} style={{ flexShrink: 0 }}>
|
||||
<path d="M17.895 11.927a3.196 3.196 0 0 1 .394-1.53l-.008.017a2.677 2.677 0 0 1 1.075-1.108l.014-.007a3.181 3.181 0 0 1 1.523-.382h.05-.003q1.346 0 2.2.871.854.871.86 2.203c0 .895-.29 1.635-.867 2.226s-1.306.886-2.183.886c-.566 0-1.1-.137-1.571-.379l.019.009a2.535 2.535 0 0 1-1.115-1.067l-.007-.013q-.38-.708-.381-1.726zm1.593.083c0 .591.138 1.043.42 1.349a1.365 1.365 0 0 0 2.066.002l.001-.002c.275-.307.413-.764.413-1.357s-.138-1.033-.413-1.342a1.371 1.371 0 0 0-2.066-.001l-.001.002c-.281.306-.42.758-.42 1.345zm-1.602 2.941H16.33v-3.015c0-.635-.032-1.044-.101-1.234a.876.876 0 0 0-.328-.435l-.003-.002a.938.938 0 0 0-.521-.156h-.027.001-.012c-.27 0-.521.084-.727.228l.004-.003a1.115 1.115 0 0 0-.444.576l-.002.008c-.083.248-.121.696-.121 1.359v2.673H12.5V9.027h1.439v.867c.518-.656 1.167-.98 1.952-.98h.021c.335 0 .655.067.946.189l-.016-.006c.261.105.48.268.648.475l.002.003c.141.185.247.404.304.643l.002.012c.057.278.089.597.089.924l-.002.135v-.007zM6.413 9.028h1.654l1.412 4.204 1.376-4.204h1.611l-2.067 5.693-.38 1.038a4.158 4.158 0 0 1-.4.807l.01-.017a1.637 1.637 0 0 1-.422.443l-.005.003c-.17.113-.367.203-.578.26l-.014.003c-.232.064-.499.1-.774.1h-.025.001a4.13 4.13 0 0 1-.911-.105l.028.005-.129-1.229c.198.046.426.074.659.077h.002c.36 0 .628-.106.8-.318a2.27 2.27 0 0 0 .395-.807l.004-.016zM0 12.29l1.592-.149q.147.802.586 1.181.439.379 1.192.375c.528 0 .927-.113 1.197-.335.27-.222.4-.486.4-.782v-.024a.751.751 0 0 0-.167-.474l.001.001c-.113-.132-.309-.252-.59-.347-.193-.074-.631-.191-1.312-.365-.882-.216-1.496-.486-1.85-.804A2.147 2.147 0 0 1 .3 8.936v-.019V8.908c0-.431.132-.831.358-1.163l-.005.007a2.226 2.226 0 0 1 1.003-.826l.015-.005c.442-.184.973-.281 1.602-.281q1.529 0 2.304.676c.516.457.785 1.057.811 1.809l-1.649.055c-.073-.413-.219-.714-.452-.899-.233-.185-.579-.276-1.034-.276-.476 0-.85.098-1.118.298a.59.59 0 0 0-.261.49v.011-.001.002c0 .201.095.379.242.493l.001.001c.205.179.709.36 1.507.546.798.186 1.388.387 1.769.59.374.196.678.48.893.825l.006.01c.214.345.326.786.326 1.305 0 .489-.146.944-.396 1.325l.006-.009c-.264.408-.64.724-1.084.908l-.016.006c-.475.194-1.065.298-1.772.298-1.029 0-1.819-.241-2.373-.722-.554-.481-.879-1.177-.986-2.091z" fill="currentColor" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const PROVIDER_ICONS: Record<string, ComponentType<{ size?: number }>> = {
|
||||
immich: ImmichIcon,
|
||||
// Photos and Drive are the same brand, so they carry the same mark.
|
||||
synologyphotos: SynologyDriveIcon,
|
||||
synologyphotos: SynologyIcon,
|
||||
// The document providers' own marks, single-colour so they read as glyphs in
|
||||
// a row of lucide icons and invert with the theme.
|
||||
...DOCUMENT_PROVIDER_ICONS,
|
||||
|
||||
Reference in New Issue
Block a user