Fix data exports UI and scope format
This commit is contained in:
@@ -23,6 +23,7 @@ import { formatRelativeTime } from './lib/relativeTime';
|
||||
import { useAdminTheme } from './theme';
|
||||
import i18n from '../i18n';
|
||||
import { triggerDownloadFromBlob } from './invite-layout/export-utils';
|
||||
import { hasInProgressExports } from './lib/dataExports';
|
||||
|
||||
const statusTone: Record<DataExportSummary['status'], 'success' | 'warning' | 'muted'> = {
|
||||
pending: 'warning',
|
||||
@@ -89,6 +90,22 @@ export default function MobileDataExportsPage() {
|
||||
void load();
|
||||
}, [load]);
|
||||
|
||||
const hasInProgress = hasInProgressExports(exports);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!hasInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const interval = window.setInterval(() => {
|
||||
void load();
|
||||
}, 5000);
|
||||
|
||||
return () => {
|
||||
window.clearInterval(interval);
|
||||
};
|
||||
}, [hasInProgress, load]);
|
||||
|
||||
const handleRequest = async () => {
|
||||
if (requesting) {
|
||||
return;
|
||||
@@ -152,7 +169,7 @@ export default function MobileDataExportsPage() {
|
||||
value={scope}
|
||||
onChange={(event) => setScope(event.target.value as 'tenant' | 'event')}
|
||||
compact
|
||||
style={{ minWidth: 160 }}
|
||||
style={{ minWidth: 140, maxWidth: 180 }}
|
||||
>
|
||||
<option value="tenant">{t('dataExports.scopes.tenant', 'Tenant')}</option>
|
||||
<option value="event">{t('dataExports.scopes.event', 'Event')}</option>
|
||||
@@ -167,7 +184,7 @@ export default function MobileDataExportsPage() {
|
||||
value={eventId ? String(eventId) : ''}
|
||||
onChange={(event) => setEventId(event.target.value ? Number(event.target.value) : null)}
|
||||
compact
|
||||
style={{ minWidth: 200 }}
|
||||
style={{ minWidth: 180, maxWidth: 220 }}
|
||||
>
|
||||
<option value="">{t('dataExports.fields.eventPlaceholder', 'Choose event')}</option>
|
||||
{events.map((event) => (
|
||||
@@ -187,7 +204,14 @@ export default function MobileDataExportsPage() {
|
||||
{t('dataExports.fields.includeMediaHint', 'Bigger ZIP; choose when needed.')}
|
||||
</Text>
|
||||
</YStack>
|
||||
<Switch checked={includeMedia} onCheckedChange={setIncludeMedia} />
|
||||
<Switch
|
||||
size="$3"
|
||||
checked={includeMedia}
|
||||
onCheckedChange={setIncludeMedia}
|
||||
aria-label={t('dataExports.fields.includeMedia', 'Include raw media')}
|
||||
>
|
||||
<Switch.Thumb />
|
||||
</Switch>
|
||||
</XStack>
|
||||
</YStack>
|
||||
<CTAButton
|
||||
|
||||
22
resources/js/admin/mobile/lib/dataExports.test.ts
Normal file
22
resources/js/admin/mobile/lib/dataExports.test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { hasInProgressExports } from './dataExports';
|
||||
|
||||
describe('dataExports helpers', () => {
|
||||
it('detects in-progress exports', () => {
|
||||
const result = hasInProgressExports([
|
||||
{ id: 1, status: 'pending' } as any,
|
||||
{ id: 2, status: 'ready' } as any,
|
||||
]);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when exports are terminal', () => {
|
||||
const result = hasInProgressExports([
|
||||
{ id: 1, status: 'ready' } as any,
|
||||
{ id: 2, status: 'failed' } as any,
|
||||
]);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
5
resources/js/admin/mobile/lib/dataExports.ts
Normal file
5
resources/js/admin/mobile/lib/dataExports.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { DataExportSummary } from '../../api';
|
||||
|
||||
export function hasInProgressExports(exports: DataExportSummary[]): boolean {
|
||||
return exports.some((entry) => entry.status === 'pending' || entry.status === 'processing');
|
||||
}
|
||||
Reference in New Issue
Block a user