mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
feat(archives): Not Printed / Printed collections (#1153)
VP-uploaded archives land with status='archived' (uploaded but never sent to a printer), but the Archives page sidebar only offered All/Recent/This Week/This Month/Favorites/Failed/Duplicates -- no way to filter "what's still queued in my library" vs "what's been printed." Two new collections fill the gap: Not Printed filters to status==='archived'; Printed filters to any final-status archive (completed/failed/aborted/cancelled/stopped) so users see every archive that had a print attempt regardless of outcome (the existing Failed collection covers just the failure subset). Frontend-only -- the status field was already populated correctly by the VP archive paths, this was purely a UI gap. 2 new tests pin the filter behaviour against a 4-status fixture.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { screen, waitFor, fireEvent } from '@testing-library/react';
|
||||
import { render } from '../utils';
|
||||
import { ArchivesPage } from '../../pages/ArchivesPage';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
@@ -372,4 +372,59 @@ describe('ArchivesPage', () => {
|
||||
// Upload Timelapse should also be disabled
|
||||
});
|
||||
});
|
||||
|
||||
// #1153 — Sylvain wanted to differentiate VP-uploaded archives (status='archived',
|
||||
// never sent to a printer) from those that have been printed at least once.
|
||||
describe('Not Printed / Printed collections', () => {
|
||||
const mixedStatusArchives = [
|
||||
{ ...mockArchives[0], id: 100, print_name: 'NeverPrinted', status: 'archived', started_at: null, completed_at: null },
|
||||
{ ...mockArchives[0], id: 101, print_name: 'WasPrinted', status: 'completed' },
|
||||
{ ...mockArchives[0], id: 102, print_name: 'WasFailed', status: 'failed' },
|
||||
{ ...mockArchives[0], id: 103, print_name: 'WasCancelled', status: 'cancelled' },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset persisted collection so each test starts on "All Archives".
|
||||
window.localStorage.removeItem('archiveCollection');
|
||||
server.use(
|
||||
http.get('/api/v1/archives/', () => HttpResponse.json(mixedStatusArchives))
|
||||
);
|
||||
});
|
||||
|
||||
it('shows only archived (never-printed) entries when "Not Printed" is selected', async () => {
|
||||
render(<ArchivesPage />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('NeverPrinted')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const collectionSelect = screen.getByDisplayValue('All Archives');
|
||||
fireEvent.change(collectionSelect, { target: { value: 'not-printed' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('NeverPrinted')).toBeInTheDocument();
|
||||
expect(screen.queryByText('WasPrinted')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('WasFailed')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('WasCancelled')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows only print-attempted entries (any final status) when "Printed" is selected', async () => {
|
||||
render(<ArchivesPage />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('NeverPrinted')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const collectionSelect = screen.getByDisplayValue('All Archives');
|
||||
fireEvent.change(collectionSelect, { target: { value: 'printed' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('NeverPrinted')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('WasPrinted')).toBeInTheDocument();
|
||||
expect(screen.getByText('WasFailed')).toBeInTheDocument();
|
||||
expect(screen.getByText('WasCancelled')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2405,7 +2405,11 @@ function ArchiveListRow({
|
||||
|
||||
type SortOption = 'date-desc' | 'date-asc' | 'name-asc' | 'name-desc' | 'size-desc' | 'size-asc';
|
||||
type ViewMode = 'grid' | 'list' | 'calendar' | 'log';
|
||||
type Collection = 'all' | 'recent' | 'this-week' | 'this-month' | 'favorites' | 'failed' | 'duplicates';
|
||||
type Collection = 'all' | 'recent' | 'this-week' | 'this-month' | 'favorites' | 'not-printed' | 'printed' | 'failed' | 'duplicates';
|
||||
|
||||
// status values that indicate a print attempt has finished (regardless of outcome).
|
||||
// `archived` is the only status that means "uploaded but never sent to a printer."
|
||||
const PRINTED_STATUSES = ['completed', 'failed', 'aborted', 'cancelled', 'stopped'] as const;
|
||||
|
||||
const collections: { id: Collection; label: string; icon: React.ReactNode }[] = [
|
||||
{ id: 'all', label: 'All Archives', icon: <FolderOpen className="w-4 h-4" /> },
|
||||
@@ -2413,6 +2417,8 @@ const collections: { id: Collection; label: string; icon: React.ReactNode }[] =
|
||||
{ id: 'this-week', label: 'This Week', icon: <Calendar className="w-4 h-4" /> },
|
||||
{ id: 'this-month', label: 'This Month', icon: <Calendar className="w-4 h-4" /> },
|
||||
{ id: 'favorites', label: 'Favorites', icon: <Star className="w-4 h-4" /> },
|
||||
{ id: 'not-printed', label: 'Not Printed', icon: <Upload className="w-4 h-4" /> },
|
||||
{ id: 'printed', label: 'Printed', icon: <Printer className="w-4 h-4" /> },
|
||||
{ id: 'failed', label: 'Failed Prints', icon: <AlertCircle className="w-4 h-4" /> },
|
||||
{ id: 'duplicates', label: 'Duplicates', icon: <Copy className="w-4 h-4" /> },
|
||||
];
|
||||
@@ -2759,6 +2765,12 @@ export function ArchivesPage() {
|
||||
case 'favorites':
|
||||
matchesCollection = a.is_favorite === true;
|
||||
break;
|
||||
case 'not-printed':
|
||||
matchesCollection = a.status === 'archived';
|
||||
break;
|
||||
case 'printed':
|
||||
matchesCollection = (PRINTED_STATUSES as readonly string[]).includes(a.status);
|
||||
break;
|
||||
case 'failed':
|
||||
matchesCollection = a.status === 'failed' || a.status === 'aborted';
|
||||
break;
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -26,7 +26,7 @@
|
||||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-5P0GaR3D.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CeqwraNQ.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-7GmlJb0k.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user