fix(team): show launch dialog loading fallback
This commit is contained in:
parent
e88d3a1e98
commit
bafd4d7194
5 changed files with 138 additions and 5 deletions
|
|
@ -25,6 +25,7 @@ import {
|
|||
} from 'lucide-react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { LaunchTeamDialogLoadingFallback } from '../team/dialogs/LaunchTeamDialogLoadingFallback';
|
||||
import { ScheduleRunLogDialog } from '../team/schedule/ScheduleRunLogDialog';
|
||||
import { ScheduleRunRow } from '../team/schedule/ScheduleRunRow';
|
||||
import { ScheduleStatusBadge } from '../team/schedule/ScheduleStatusBadge';
|
||||
|
|
@ -588,7 +589,16 @@ export const SchedulesView = (): React.JSX.Element => {
|
|||
|
||||
{/* Create/Edit Dialog */}
|
||||
{dialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LaunchTeamDialogLoadingFallback
|
||||
mode="schedule"
|
||||
teamName={editingSchedule?.teamName}
|
||||
isEditingSchedule={Boolean(editingSchedule)}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LaunchTeamDialog
|
||||
mode="schedule"
|
||||
open={dialogOpen}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import { useShallow } from 'zustand/react/shallow';
|
|||
|
||||
import { AddMemberDialog } from './dialogs/AddMemberDialog';
|
||||
import { EditTeamDialog } from './dialogs/EditTeamDialog';
|
||||
import { LaunchTeamDialogLoadingFallback } from './dialogs/LaunchTeamDialogLoadingFallback';
|
||||
import { ReviewDialog } from './dialogs/ReviewDialog';
|
||||
import { executeTeamRelaunch } from './dialogs/teamRelaunchFlow';
|
||||
import { KanbanBoard } from './kanban/KanbanBoard';
|
||||
|
|
@ -2580,7 +2581,15 @@ export const TeamDetailView = memo(function TeamDetailView({
|
|||
</div>
|
||||
</div>
|
||||
{launchDialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LaunchTeamDialogLoadingFallback
|
||||
mode={launchDialogState.mode}
|
||||
teamName={teamName}
|
||||
onClose={closeLaunchDialog}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LaunchTeamDialog
|
||||
mode={launchDialogState.mode}
|
||||
open={launchDialogOpen}
|
||||
|
|
@ -3418,7 +3427,15 @@ export const TeamDetailView = memo(function TeamDetailView({
|
|||
</Dialog>
|
||||
|
||||
{launchDialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LaunchTeamDialogLoadingFallback
|
||||
mode={launchDialogState.mode}
|
||||
teamName={teamName}
|
||||
onClose={closeLaunchDialog}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LaunchTeamDialog
|
||||
mode={launchDialogState.mode}
|
||||
open={launchDialogOpen}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import {
|
|||
} from 'lucide-react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { LaunchTeamDialogLoadingFallback } from './dialogs/LaunchTeamDialogLoadingFallback';
|
||||
import { executeTeamRelaunch } from './dialogs/teamRelaunchFlow';
|
||||
import { TeamEmptyState } from './TeamEmptyState';
|
||||
import { EMPTY_TEAM_FILTER, TeamListFilterPopover } from './TeamListFilterPopover';
|
||||
|
|
@ -1094,7 +1095,15 @@ export const TeamListView = memo(function TeamListView(): React.JSX.Element {
|
|||
);
|
||||
|
||||
const launchDialogElement = launchDialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LaunchTeamDialogLoadingFallback
|
||||
mode={launchDialogMode}
|
||||
teamName={launchDialogTeamName}
|
||||
onClose={() => setLaunchDialogOpen(false)}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{launchDialogMode === 'relaunch' ? (
|
||||
<LaunchTeamDialog
|
||||
mode="relaunch"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
import React from 'react';
|
||||
|
||||
import { useAppTranslation } from '@features/localization/renderer';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@renderer/components/ui/dialog';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
type LaunchTeamDialogLoadingMode = 'launch' | 'relaunch' | 'schedule';
|
||||
|
||||
interface LaunchTeamDialogLoadingFallbackProps {
|
||||
readonly mode: LaunchTeamDialogLoadingMode;
|
||||
readonly teamName?: string;
|
||||
readonly isEditingSchedule?: boolean;
|
||||
readonly onClose: () => void;
|
||||
}
|
||||
|
||||
export const LaunchTeamDialogLoadingFallback = ({
|
||||
mode,
|
||||
teamName,
|
||||
isEditingSchedule = false,
|
||||
onClose,
|
||||
}: LaunchTeamDialogLoadingFallbackProps): React.JSX.Element => {
|
||||
const { t } = useAppTranslation('team');
|
||||
const { t: tCommon } = useAppTranslation('common');
|
||||
|
||||
const title =
|
||||
mode === 'schedule'
|
||||
? isEditingSchedule
|
||||
? t('launch.title.editSchedule')
|
||||
: t('launch.title.createSchedule')
|
||||
: mode === 'relaunch'
|
||||
? t('launch.title.relaunch')
|
||||
: t('launch.title.launch');
|
||||
|
||||
const description =
|
||||
mode === 'schedule'
|
||||
? isEditingSchedule && teamName
|
||||
? t('launch.description.editSchedule', { team: teamName })
|
||||
: teamName
|
||||
? t('launch.description.createScheduleForTeam', { team: teamName })
|
||||
: t('launch.description.createSchedule')
|
||||
: mode === 'relaunch'
|
||||
? t('launch.description.relaunchPrefix')
|
||||
: t('launch.description.launchPrefix');
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open
|
||||
onOpenChange={(nextOpen) => {
|
||||
if (!nextOpen) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogContent className="max-w-[52rem]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-sm">{title}</DialogTitle>
|
||||
<DialogDescription className="text-xs">
|
||||
{mode === 'schedule' ? (
|
||||
description
|
||||
) : (
|
||||
<>
|
||||
{description} <span className="font-mono font-medium">{teamName}</span>{' '}
|
||||
{mode === 'relaunch'
|
||||
? t('launch.description.relaunchSuffix')
|
||||
: t('launch.description.launchSuffix')}
|
||||
</>
|
||||
)}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div
|
||||
className="flex items-center gap-2 rounded-md border border-[var(--color-border)] bg-[var(--color-surface-overlay)] px-3 py-2 text-xs text-[var(--color-text-muted)]"
|
||||
aria-live="polite"
|
||||
>
|
||||
<Loader2 className="size-3.5 shrink-0 animate-spin" />
|
||||
<span>{tCommon('states.loading')}</span>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
|
@ -19,6 +19,8 @@ import {
|
|||
} from 'lucide-react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { LaunchTeamDialogLoadingFallback } from '../dialogs/LaunchTeamDialogLoadingFallback';
|
||||
|
||||
import { ScheduleEmptyState } from './ScheduleEmptyState';
|
||||
import { ScheduleRunLogDialog } from './ScheduleRunLogDialog';
|
||||
import { ScheduleRunRow } from './ScheduleRunRow';
|
||||
|
|
@ -311,7 +313,16 @@ export const ScheduleSection = ({ teamName }: ScheduleSectionProps): React.JSX.E
|
|||
|
||||
{/* Create/Edit Dialog */}
|
||||
{dialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<LaunchTeamDialogLoadingFallback
|
||||
mode="schedule"
|
||||
teamName={teamName}
|
||||
isEditingSchedule={Boolean(editingSchedule)}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LaunchTeamDialog
|
||||
mode="schedule"
|
||||
open={dialogOpen}
|
||||
|
|
|
|||
Loading…
Reference in a new issue