@hed-hog/studio 0.0.285
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/studio.controller.d.ts +79 -0
- package/dist/studio.controller.d.ts.map +1 -0
- package/dist/studio.controller.js +186 -0
- package/dist/studio.controller.js.map +1 -0
- package/dist/studio.module.d.ts +3 -0
- package/dist/studio.module.d.ts.map +1 -0
- package/dist/studio.module.js +33 -0
- package/dist/studio.module.js.map +1 -0
- package/dist/studio.service.d.ts +76 -0
- package/dist/studio.service.d.ts.map +1 -0
- package/dist/studio.service.js +98 -0
- package/dist/studio.service.js.map +1 -0
- package/hedhog/data/menu.yaml +114 -0
- package/hedhog/data/role.yaml +7 -0
- package/hedhog/data/route.yaml +152 -0
- package/hedhog/data/setting_group.yaml +8 -0
- package/hedhog/frontend/app/_components/studio-status-badge.tsx.ejs +14 -0
- package/hedhog/frontend/app/_lib/mocks.ts.ejs +209 -0
- package/hedhog/frontend/app/_lib/status.ts.ejs +38 -0
- package/hedhog/frontend/app/_lib/types.ts.ejs +148 -0
- package/hedhog/frontend/app/assets/page.tsx.ejs +117 -0
- package/hedhog/frontend/app/editing/page.tsx.ejs +55 -0
- package/hedhog/frontend/app/incidents/page.tsx.ejs +59 -0
- package/hedhog/frontend/app/page.tsx.ejs +207 -0
- package/hedhog/frontend/app/projects/[id]/page.tsx.ejs +323 -0
- package/hedhog/frontend/app/projects/form/page.tsx.ejs +129 -0
- package/hedhog/frontend/app/projects/page.tsx.ejs +169 -0
- package/hedhog/frontend/app/publication/page.tsx.ejs +62 -0
- package/hedhog/frontend/app/scenes/form/page.tsx.ejs +110 -0
- package/hedhog/frontend/app/sessions/[id]/page.tsx.ejs +118 -0
- package/hedhog/frontend/app/sessions/form/page.tsx.ejs +103 -0
- package/hedhog/frontend/app/sessions/page.tsx.ejs +80 -0
- package/hedhog/frontend/app/storage-profiles/form/page.tsx.ejs +100 -0
- package/hedhog/frontend/app/storage-profiles/page.tsx.ejs +80 -0
- package/hedhog/frontend/app/takes/[id]/page.tsx.ejs +143 -0
- package/hedhog/frontend/app/takes/page.tsx.ejs +74 -0
- package/hedhog/table/capture_agent.yaml +48 -0
- package/hedhog/table/edit_composition.yaml +67 -0
- package/hedhog/table/edit_pipeline.yaml +46 -0
- package/hedhog/table/edit_stage_execution.yaml +46 -0
- package/hedhog/table/editor_delivery_package.yaml +63 -0
- package/hedhog/table/ingestion_job.yaml +74 -0
- package/hedhog/table/media_asset.yaml +130 -0
- package/hedhog/table/participant_command_ack.yaml +32 -0
- package/hedhog/table/participant_recording.yaml +67 -0
- package/hedhog/table/production_binding.yaml +34 -0
- package/hedhog/table/production_project.yaml +104 -0
- package/hedhog/table/publication_target.yaml +44 -0
- package/hedhog/table/recorded_file.yaml +74 -0
- package/hedhog/table/recording_command.yaml +72 -0
- package/hedhog/table/recording_incident.yaml +65 -0
- package/hedhog/table/recording_session.yaml +86 -0
- package/hedhog/table/scene.yaml +64 -0
- package/hedhog/table/scene_take.yaml +83 -0
- package/hedhog/table/session_participant.yaml +55 -0
- package/hedhog/table/storage_profile.yaml +75 -0
- package/hedhog/table/sync_marker.yaml +44 -0
- package/package.json +38 -0
- package/src/index.ts +4 -0
- package/src/language/en.json +8 -0
- package/src/language/pt.json +8 -0
- package/src/studio.controller.ts +94 -0
- package/src/studio.module.ts +20 -0
- package/src/studio.service.ts +102 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Page, PageHeader } from '@/components/entity-list';
|
|
4
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
5
|
+
|
|
6
|
+
export default function StudioEditingPage() {
|
|
7
|
+
return (
|
|
8
|
+
<Page>
|
|
9
|
+
<PageHeader
|
|
10
|
+
title="Edicao"
|
|
11
|
+
description="Pipeline e execucao de etapas de edicao"
|
|
12
|
+
breadcrumbs={[
|
|
13
|
+
{ label: 'Home', href: '/' },
|
|
14
|
+
{ label: 'Studio', href: '/studio' },
|
|
15
|
+
{ label: 'Edicao' },
|
|
16
|
+
]}
|
|
17
|
+
/>
|
|
18
|
+
<div className="grid gap-4 lg:grid-cols-3">
|
|
19
|
+
<Card>
|
|
20
|
+
<CardHeader>
|
|
21
|
+
<CardTitle className="text-base">Pipeline atual</CardTitle>
|
|
22
|
+
</CardHeader>
|
|
23
|
+
<CardContent className="space-y-2 text-sm">
|
|
24
|
+
<div>Preparation • completed</div>
|
|
25
|
+
<div>Recording • completed</div>
|
|
26
|
+
<div>Rough cut • in_progress</div>
|
|
27
|
+
<div>Cleanup • pending</div>
|
|
28
|
+
<div>Finalization • pending</div>
|
|
29
|
+
<div>Publication • pending</div>
|
|
30
|
+
</CardContent>
|
|
31
|
+
</Card>
|
|
32
|
+
<Card>
|
|
33
|
+
<CardHeader>
|
|
34
|
+
<CardTitle className="text-base">Composicao base</CardTitle>
|
|
35
|
+
</CardHeader>
|
|
36
|
+
<CardContent className="space-y-2 text-sm">
|
|
37
|
+
<div>Tipo: multi_participant</div>
|
|
38
|
+
<div>Fonte primaria: microphone_audio</div>
|
|
39
|
+
<div>Status: in_editing</div>
|
|
40
|
+
</CardContent>
|
|
41
|
+
</Card>
|
|
42
|
+
<Card>
|
|
43
|
+
<CardHeader>
|
|
44
|
+
<CardTitle className="text-base">Pacotes</CardTitle>
|
|
45
|
+
</CardHeader>
|
|
46
|
+
<CardContent className="space-y-2 text-sm">
|
|
47
|
+
<div>raw_take_bundle • available</div>
|
|
48
|
+
<div>editing_bundle • generating</div>
|
|
49
|
+
<div>proxy_bundle • pending</div>
|
|
50
|
+
</CardContent>
|
|
51
|
+
</Card>
|
|
52
|
+
</div>
|
|
53
|
+
</Page>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Page, PageHeader } from '@/components/entity-list';
|
|
4
|
+
import {
|
|
5
|
+
Table,
|
|
6
|
+
TableBody,
|
|
7
|
+
TableCell,
|
|
8
|
+
TableHead,
|
|
9
|
+
TableHeader,
|
|
10
|
+
TableRow,
|
|
11
|
+
} from '@/components/ui/table';
|
|
12
|
+
import { STUDIO_INCIDENTS } from '../_lib/mocks';
|
|
13
|
+
import { StudioStatusBadge } from '../_components/studio-status-badge';
|
|
14
|
+
|
|
15
|
+
export default function StudioIncidentsPage() {
|
|
16
|
+
return (
|
|
17
|
+
<Page>
|
|
18
|
+
<PageHeader
|
|
19
|
+
title="Incidentes"
|
|
20
|
+
description="Falhas tecnicas e acompanhamento de resolucao"
|
|
21
|
+
breadcrumbs={[
|
|
22
|
+
{ label: 'Home', href: '/' },
|
|
23
|
+
{ label: 'Studio', href: '/studio' },
|
|
24
|
+
{ label: 'Incidentes' },
|
|
25
|
+
]}
|
|
26
|
+
/>
|
|
27
|
+
<div className="rounded-md border">
|
|
28
|
+
<Table>
|
|
29
|
+
<TableHeader>
|
|
30
|
+
<TableRow>
|
|
31
|
+
<TableHead>Tipo</TableHead>
|
|
32
|
+
<TableHead>Severidade</TableHead>
|
|
33
|
+
<TableHead>Alvo</TableHead>
|
|
34
|
+
<TableHead>Status</TableHead>
|
|
35
|
+
<TableHead>Detectado em</TableHead>
|
|
36
|
+
</TableRow>
|
|
37
|
+
</TableHeader>
|
|
38
|
+
<TableBody>
|
|
39
|
+
{STUDIO_INCIDENTS.map((incident) => (
|
|
40
|
+
<TableRow key={incident.id}>
|
|
41
|
+
<TableCell>{incident.type}</TableCell>
|
|
42
|
+
<TableCell>
|
|
43
|
+
<StudioStatusBadge value={incident.severity} />
|
|
44
|
+
</TableCell>
|
|
45
|
+
<TableCell>{incident.target}</TableCell>
|
|
46
|
+
<TableCell>
|
|
47
|
+
<StudioStatusBadge value={incident.status} />
|
|
48
|
+
</TableCell>
|
|
49
|
+
<TableCell>
|
|
50
|
+
{new Date(incident.detectedAt).toLocaleString('pt-BR')}
|
|
51
|
+
</TableCell>
|
|
52
|
+
</TableRow>
|
|
53
|
+
))}
|
|
54
|
+
</TableBody>
|
|
55
|
+
</Table>
|
|
56
|
+
</div>
|
|
57
|
+
</Page>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Page,
|
|
5
|
+
PageHeader,
|
|
6
|
+
StatsCards,
|
|
7
|
+
type StatCardConfig,
|
|
8
|
+
} from '@/components/entity-list';
|
|
9
|
+
import type { PageHeaderProps } from '@/components/entity-list/page-header';
|
|
10
|
+
import { Button } from '@/components/ui/button';
|
|
11
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
12
|
+
import {
|
|
13
|
+
Table,
|
|
14
|
+
TableBody,
|
|
15
|
+
TableCell,
|
|
16
|
+
TableHead,
|
|
17
|
+
TableHeader,
|
|
18
|
+
TableRow,
|
|
19
|
+
} from '@/components/ui/table';
|
|
20
|
+
import {
|
|
21
|
+
AlertTriangle,
|
|
22
|
+
Clapperboard,
|
|
23
|
+
Clock3,
|
|
24
|
+
Film,
|
|
25
|
+
UploadCloud,
|
|
26
|
+
Video,
|
|
27
|
+
} from 'lucide-react';
|
|
28
|
+
import Link from 'next/link';
|
|
29
|
+
import { StudioStatusBadge } from './_components/studio-status-badge';
|
|
30
|
+
import {
|
|
31
|
+
STUDIO_INCIDENTS,
|
|
32
|
+
STUDIO_PROJECTS,
|
|
33
|
+
STUDIO_SESSIONS,
|
|
34
|
+
STUDIO_TAKES,
|
|
35
|
+
} from './_lib/mocks';
|
|
36
|
+
|
|
37
|
+
export default function StudioDashboardPage() {
|
|
38
|
+
const breadcrumbs: PageHeaderProps['breadcrumbs'] = [
|
|
39
|
+
{ label: 'Home', href: '/' },
|
|
40
|
+
{ label: 'Studio' },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const stats: StatCardConfig[] = [
|
|
44
|
+
{
|
|
45
|
+
title: 'Projetos totais',
|
|
46
|
+
value: STUDIO_PROJECTS.length,
|
|
47
|
+
icon: <Clapperboard className="size-5" />,
|
|
48
|
+
iconBgColor: 'bg-cyan-50',
|
|
49
|
+
iconColor: 'text-cyan-700',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
title: 'Em gravacao',
|
|
53
|
+
value: STUDIO_PROJECTS.filter((item) => item.status === 'in_recording')
|
|
54
|
+
.length,
|
|
55
|
+
icon: <Video className="size-5" />,
|
|
56
|
+
iconBgColor: 'bg-orange-50',
|
|
57
|
+
iconColor: 'text-orange-700',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: 'Em edicao',
|
|
61
|
+
value: STUDIO_PROJECTS.filter((item) => item.status === 'in_editing')
|
|
62
|
+
.length,
|
|
63
|
+
icon: <Film className="size-5" />,
|
|
64
|
+
iconBgColor: 'bg-violet-50',
|
|
65
|
+
iconColor: 'text-violet-700',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: 'Takes pendentes',
|
|
69
|
+
value: STUDIO_TAKES.filter((item) => item.status === 'partial').length,
|
|
70
|
+
icon: <UploadCloud className="size-5" />,
|
|
71
|
+
iconBgColor: 'bg-amber-50',
|
|
72
|
+
iconColor: 'text-amber-700',
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Page>
|
|
78
|
+
<PageHeader
|
|
79
|
+
title="Studio"
|
|
80
|
+
description="Visao operacional de producao audiovisual"
|
|
81
|
+
breadcrumbs={breadcrumbs as { label: string; href?: string }[]}
|
|
82
|
+
actions={
|
|
83
|
+
<Button asChild size="sm">
|
|
84
|
+
<Link href="/studio/projects/form">Novo Projeto</Link>
|
|
85
|
+
</Button>
|
|
86
|
+
}
|
|
87
|
+
/>
|
|
88
|
+
|
|
89
|
+
<StatsCards stats={stats} />
|
|
90
|
+
|
|
91
|
+
<div className="grid gap-4 lg:grid-cols-2">
|
|
92
|
+
<Card>
|
|
93
|
+
<CardHeader>
|
|
94
|
+
<CardTitle className="text-base">Projetos recentes</CardTitle>
|
|
95
|
+
</CardHeader>
|
|
96
|
+
<CardContent>
|
|
97
|
+
<Table>
|
|
98
|
+
<TableHeader>
|
|
99
|
+
<TableRow>
|
|
100
|
+
<TableHead>Titulo</TableHead>
|
|
101
|
+
<TableHead>Status</TableHead>
|
|
102
|
+
<TableHead>Responsavel</TableHead>
|
|
103
|
+
</TableRow>
|
|
104
|
+
</TableHeader>
|
|
105
|
+
<TableBody>
|
|
106
|
+
{STUDIO_PROJECTS.map((project) => (
|
|
107
|
+
<TableRow key={project.id}>
|
|
108
|
+
<TableCell>
|
|
109
|
+
<Link
|
|
110
|
+
href={`/studio/projects/${project.id}`}
|
|
111
|
+
className="hover:underline"
|
|
112
|
+
>
|
|
113
|
+
{project.title}
|
|
114
|
+
</Link>
|
|
115
|
+
</TableCell>
|
|
116
|
+
<TableCell>
|
|
117
|
+
<StudioStatusBadge value={project.status} />
|
|
118
|
+
</TableCell>
|
|
119
|
+
<TableCell>{project.owner}</TableCell>
|
|
120
|
+
</TableRow>
|
|
121
|
+
))}
|
|
122
|
+
</TableBody>
|
|
123
|
+
</Table>
|
|
124
|
+
</CardContent>
|
|
125
|
+
</Card>
|
|
126
|
+
|
|
127
|
+
<Card>
|
|
128
|
+
<CardHeader>
|
|
129
|
+
<CardTitle className="text-base">Sessoes em andamento</CardTitle>
|
|
130
|
+
</CardHeader>
|
|
131
|
+
<CardContent className="space-y-3">
|
|
132
|
+
{STUDIO_SESSIONS.map((session) => (
|
|
133
|
+
<div
|
|
134
|
+
key={session.id}
|
|
135
|
+
className="flex items-center justify-between rounded-md border p-3"
|
|
136
|
+
>
|
|
137
|
+
<div>
|
|
138
|
+
<div className="font-medium">{session.title}</div>
|
|
139
|
+
<div className="text-muted-foreground text-xs">
|
|
140
|
+
Room {session.roomKey}
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
<StudioStatusBadge value={session.status} />
|
|
144
|
+
</div>
|
|
145
|
+
))}
|
|
146
|
+
</CardContent>
|
|
147
|
+
</Card>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div className="grid gap-4 lg:grid-cols-3">
|
|
151
|
+
<Card className="lg:col-span-2">
|
|
152
|
+
<CardHeader>
|
|
153
|
+
<CardTitle className="text-base">Incidentes recentes</CardTitle>
|
|
154
|
+
</CardHeader>
|
|
155
|
+
<CardContent className="space-y-3">
|
|
156
|
+
{STUDIO_INCIDENTS.map((incident) => (
|
|
157
|
+
<div
|
|
158
|
+
key={incident.id}
|
|
159
|
+
className="flex items-center justify-between rounded-md border p-3"
|
|
160
|
+
>
|
|
161
|
+
<div className="flex items-start gap-3">
|
|
162
|
+
<AlertTriangle className="mt-0.5 size-4 text-red-600" />
|
|
163
|
+
<div>
|
|
164
|
+
<div className="font-medium">{incident.type}</div>
|
|
165
|
+
<div className="text-muted-foreground text-xs">
|
|
166
|
+
{incident.target}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
<StudioStatusBadge value={incident.severity} />
|
|
171
|
+
</div>
|
|
172
|
+
))}
|
|
173
|
+
</CardContent>
|
|
174
|
+
</Card>
|
|
175
|
+
|
|
176
|
+
<Card>
|
|
177
|
+
<CardHeader>
|
|
178
|
+
<CardTitle className="text-base">Atalhos</CardTitle>
|
|
179
|
+
</CardHeader>
|
|
180
|
+
<CardContent className="grid gap-2 text-sm">
|
|
181
|
+
<Link
|
|
182
|
+
href="/studio/projects"
|
|
183
|
+
className="rounded-md border px-3 py-2 hover:bg-muted"
|
|
184
|
+
>
|
|
185
|
+
Ir para projetos
|
|
186
|
+
</Link>
|
|
187
|
+
<Link
|
|
188
|
+
href="/studio/sessions"
|
|
189
|
+
className="rounded-md border px-3 py-2 hover:bg-muted"
|
|
190
|
+
>
|
|
191
|
+
Monitorar sessoes
|
|
192
|
+
</Link>
|
|
193
|
+
<Link
|
|
194
|
+
href="/studio/storage-profiles"
|
|
195
|
+
className="rounded-md border px-3 py-2 hover:bg-muted"
|
|
196
|
+
>
|
|
197
|
+
Gerenciar storage
|
|
198
|
+
</Link>
|
|
199
|
+
<div className="text-muted-foreground flex items-center gap-2 pt-2 text-xs">
|
|
200
|
+
<Clock3 className="size-3" /> Ultima sincronizacao agora
|
|
201
|
+
</div>
|
|
202
|
+
</CardContent>
|
|
203
|
+
</Card>
|
|
204
|
+
</div>
|
|
205
|
+
</Page>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Page, PageHeader } from '@/components/entity-list';
|
|
4
|
+
import type { PageHeaderProps } from '@/components/entity-list/page-header';
|
|
5
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
6
|
+
import {
|
|
7
|
+
Table,
|
|
8
|
+
TableBody,
|
|
9
|
+
TableCell,
|
|
10
|
+
TableHead,
|
|
11
|
+
TableHeader,
|
|
12
|
+
TableRow,
|
|
13
|
+
} from '@/components/ui/table';
|
|
14
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
15
|
+
import { useParams } from 'next/navigation';
|
|
16
|
+
import { StudioStatusBadge } from '../../_components/studio-status-badge';
|
|
17
|
+
import {
|
|
18
|
+
STUDIO_ASSETS,
|
|
19
|
+
STUDIO_INCIDENTS,
|
|
20
|
+
STUDIO_PROJECTS,
|
|
21
|
+
STUDIO_PUBLICATION_TARGETS,
|
|
22
|
+
STUDIO_SCENES,
|
|
23
|
+
STUDIO_SESSIONS,
|
|
24
|
+
STUDIO_TAKES,
|
|
25
|
+
} from '../../_lib/mocks';
|
|
26
|
+
|
|
27
|
+
export default function StudioProjectDetailPage() {
|
|
28
|
+
const params = useParams<{ id: string }>();
|
|
29
|
+
const projectId = Number(params.id);
|
|
30
|
+
const project = STUDIO_PROJECTS.find((item) => item.id === projectId);
|
|
31
|
+
|
|
32
|
+
if (!project) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const currentProject = project!;
|
|
37
|
+
|
|
38
|
+
const breadcrumbs: PageHeaderProps['breadcrumbs'] = [
|
|
39
|
+
{ label: 'Home', href: '/' },
|
|
40
|
+
{ label: 'Studio', href: '/studio' },
|
|
41
|
+
{ label: 'Projetos', href: '/studio/projects' },
|
|
42
|
+
{ label: `Projeto #${currentProject.id}` },
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const scenes = STUDIO_SCENES.filter(
|
|
46
|
+
(item) => item.projectId === currentProject.id
|
|
47
|
+
);
|
|
48
|
+
const sessions = STUDIO_SESSIONS.filter(
|
|
49
|
+
(item) => item.projectId === currentProject.id
|
|
50
|
+
);
|
|
51
|
+
const takes = STUDIO_TAKES.filter(
|
|
52
|
+
(item) => item.projectId === currentProject.id
|
|
53
|
+
);
|
|
54
|
+
const incidents = STUDIO_INCIDENTS.filter(
|
|
55
|
+
(item) => item.projectId === currentProject.id
|
|
56
|
+
);
|
|
57
|
+
const publicationTargets = STUDIO_PUBLICATION_TARGETS.filter(
|
|
58
|
+
(item) => item.projectId === currentProject.id
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Page>
|
|
63
|
+
<PageHeader
|
|
64
|
+
title={currentProject.title}
|
|
65
|
+
description="Painel central do projeto de producao"
|
|
66
|
+
breadcrumbs={breadcrumbs as { label: string; href?: string }[]}
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<Tabs defaultValue="overview" className="space-y-4">
|
|
70
|
+
<TabsList className="grid w-full grid-cols-4 lg:grid-cols-8">
|
|
71
|
+
<TabsTrigger value="overview">Visao geral</TabsTrigger>
|
|
72
|
+
<TabsTrigger value="scenes">Cenas</TabsTrigger>
|
|
73
|
+
<TabsTrigger value="sessions">Sessoes</TabsTrigger>
|
|
74
|
+
<TabsTrigger value="takes">Takes</TabsTrigger>
|
|
75
|
+
<TabsTrigger value="assets">Arquivos</TabsTrigger>
|
|
76
|
+
<TabsTrigger value="editing">Edicao</TabsTrigger>
|
|
77
|
+
<TabsTrigger value="publication">Publicacao</TabsTrigger>
|
|
78
|
+
<TabsTrigger value="incidents">Incidentes</TabsTrigger>
|
|
79
|
+
</TabsList>
|
|
80
|
+
|
|
81
|
+
<TabsContent value="overview" className="grid gap-4 md:grid-cols-2">
|
|
82
|
+
<Card>
|
|
83
|
+
<CardHeader>
|
|
84
|
+
<CardTitle className="text-base">Resumo</CardTitle>
|
|
85
|
+
</CardHeader>
|
|
86
|
+
<CardContent className="space-y-2 text-sm">
|
|
87
|
+
<div>Tipo: {currentProject.projectType}</div>
|
|
88
|
+
<div>
|
|
89
|
+
Status: <StudioStatusBadge value={currentProject.status} />
|
|
90
|
+
</div>
|
|
91
|
+
<div>
|
|
92
|
+
Etapa: <StudioStatusBadge value={currentProject.currentStage} />
|
|
93
|
+
</div>
|
|
94
|
+
<div>Binding: {currentProject.binding}</div>
|
|
95
|
+
<div>Responsavel: {currentProject.owner}</div>
|
|
96
|
+
</CardContent>
|
|
97
|
+
</Card>
|
|
98
|
+
<Card>
|
|
99
|
+
<CardHeader>
|
|
100
|
+
<CardTitle className="text-base">Metricas</CardTitle>
|
|
101
|
+
</CardHeader>
|
|
102
|
+
<CardContent className="space-y-2 text-sm">
|
|
103
|
+
<div>Cenas: {scenes.length}</div>
|
|
104
|
+
<div>Sessoes: {sessions.length}</div>
|
|
105
|
+
<div>Takes: {takes.length}</div>
|
|
106
|
+
<div>
|
|
107
|
+
Assets:{' '}
|
|
108
|
+
{
|
|
109
|
+
STUDIO_ASSETS.filter((item) =>
|
|
110
|
+
takes.some((take) => take.id === item.takeId)
|
|
111
|
+
).length
|
|
112
|
+
}
|
|
113
|
+
</div>
|
|
114
|
+
</CardContent>
|
|
115
|
+
</Card>
|
|
116
|
+
</TabsContent>
|
|
117
|
+
|
|
118
|
+
<TabsContent value="scenes">
|
|
119
|
+
<div className="rounded-md border">
|
|
120
|
+
<Table>
|
|
121
|
+
<TableHeader>
|
|
122
|
+
<TableRow>
|
|
123
|
+
<TableHead>Cena</TableHead>
|
|
124
|
+
<TableHead>Status</TableHead>
|
|
125
|
+
<TableHead>Duracao Est.</TableHead>
|
|
126
|
+
<TableHead>Takes</TableHead>
|
|
127
|
+
</TableRow>
|
|
128
|
+
</TableHeader>
|
|
129
|
+
<TableBody>
|
|
130
|
+
{scenes.map((scene) => (
|
|
131
|
+
<TableRow key={scene.id}>
|
|
132
|
+
<TableCell>{scene.name}</TableCell>
|
|
133
|
+
<TableCell>
|
|
134
|
+
<StudioStatusBadge value={scene.status} />
|
|
135
|
+
</TableCell>
|
|
136
|
+
<TableCell>{scene.estimatedSeconds}s</TableCell>
|
|
137
|
+
<TableCell>{scene.takes}</TableCell>
|
|
138
|
+
</TableRow>
|
|
139
|
+
))}
|
|
140
|
+
</TableBody>
|
|
141
|
+
</Table>
|
|
142
|
+
</div>
|
|
143
|
+
</TabsContent>
|
|
144
|
+
|
|
145
|
+
<TabsContent value="sessions">
|
|
146
|
+
<div className="rounded-md border">
|
|
147
|
+
<Table>
|
|
148
|
+
<TableHeader>
|
|
149
|
+
<TableRow>
|
|
150
|
+
<TableHead>Titulo</TableHead>
|
|
151
|
+
<TableHead>Status</TableHead>
|
|
152
|
+
<TableHead>Tipo</TableHead>
|
|
153
|
+
<TableHead>Host</TableHead>
|
|
154
|
+
<TableHead>Participantes</TableHead>
|
|
155
|
+
<TableHead>Room</TableHead>
|
|
156
|
+
</TableRow>
|
|
157
|
+
</TableHeader>
|
|
158
|
+
<TableBody>
|
|
159
|
+
{sessions.map((session) => (
|
|
160
|
+
<TableRow key={session.id}>
|
|
161
|
+
<TableCell>{session.title}</TableCell>
|
|
162
|
+
<TableCell>
|
|
163
|
+
<StudioStatusBadge value={session.status} />
|
|
164
|
+
</TableCell>
|
|
165
|
+
<TableCell>{session.sessionType}</TableCell>
|
|
166
|
+
<TableCell>{session.host}</TableCell>
|
|
167
|
+
<TableCell>{session.participants}</TableCell>
|
|
168
|
+
<TableCell>{session.roomKey}</TableCell>
|
|
169
|
+
</TableRow>
|
|
170
|
+
))}
|
|
171
|
+
</TableBody>
|
|
172
|
+
</Table>
|
|
173
|
+
</div>
|
|
174
|
+
</TabsContent>
|
|
175
|
+
|
|
176
|
+
<TabsContent value="takes">
|
|
177
|
+
<div className="rounded-md border">
|
|
178
|
+
<Table>
|
|
179
|
+
<TableHeader>
|
|
180
|
+
<TableRow>
|
|
181
|
+
<TableHead>Take</TableHead>
|
|
182
|
+
<TableHead>Status</TableHead>
|
|
183
|
+
<TableHead>Participantes</TableHead>
|
|
184
|
+
<TableHead>Upload</TableHead>
|
|
185
|
+
<TableHead>Integridade</TableHead>
|
|
186
|
+
</TableRow>
|
|
187
|
+
</TableHeader>
|
|
188
|
+
<TableBody>
|
|
189
|
+
{takes.map((take) => (
|
|
190
|
+
<TableRow key={take.id}>
|
|
191
|
+
<TableCell>#{take.id}</TableCell>
|
|
192
|
+
<TableCell>
|
|
193
|
+
<StudioStatusBadge value={take.status} />
|
|
194
|
+
</TableCell>
|
|
195
|
+
<TableCell>{take.participants}</TableCell>
|
|
196
|
+
<TableCell>
|
|
197
|
+
{take.uploadedFiles}/{take.expectedFiles}
|
|
198
|
+
</TableCell>
|
|
199
|
+
<TableCell>
|
|
200
|
+
<StudioStatusBadge value={take.integrity} />
|
|
201
|
+
</TableCell>
|
|
202
|
+
</TableRow>
|
|
203
|
+
))}
|
|
204
|
+
</TableBody>
|
|
205
|
+
</Table>
|
|
206
|
+
</div>
|
|
207
|
+
</TabsContent>
|
|
208
|
+
|
|
209
|
+
<TabsContent value="assets">
|
|
210
|
+
<div className="rounded-md border">
|
|
211
|
+
<Table>
|
|
212
|
+
<TableHeader>
|
|
213
|
+
<TableRow>
|
|
214
|
+
<TableHead>Participante</TableHead>
|
|
215
|
+
<TableHead>Take</TableHead>
|
|
216
|
+
<TableHead>Tipo</TableHead>
|
|
217
|
+
<TableHead>Disponibilidade</TableHead>
|
|
218
|
+
</TableRow>
|
|
219
|
+
</TableHeader>
|
|
220
|
+
<TableBody>
|
|
221
|
+
{STUDIO_ASSETS.filter((item) =>
|
|
222
|
+
takes.some((take) => take.id === item.takeId)
|
|
223
|
+
).map((asset) => (
|
|
224
|
+
<TableRow key={asset.id}>
|
|
225
|
+
<TableCell>{asset.participant}</TableCell>
|
|
226
|
+
<TableCell>#{asset.takeId}</TableCell>
|
|
227
|
+
<TableCell>{asset.sourceType}</TableCell>
|
|
228
|
+
<TableCell>
|
|
229
|
+
<StudioStatusBadge value={asset.availability} />
|
|
230
|
+
</TableCell>
|
|
231
|
+
</TableRow>
|
|
232
|
+
))}
|
|
233
|
+
</TableBody>
|
|
234
|
+
</Table>
|
|
235
|
+
</div>
|
|
236
|
+
</TabsContent>
|
|
237
|
+
|
|
238
|
+
<TabsContent value="editing" className="grid gap-4 md:grid-cols-2">
|
|
239
|
+
<Card>
|
|
240
|
+
<CardHeader>
|
|
241
|
+
<CardTitle className="text-base">Pipeline</CardTitle>
|
|
242
|
+
</CardHeader>
|
|
243
|
+
<CardContent className="space-y-2 text-sm">
|
|
244
|
+
<div>Preparation: completed</div>
|
|
245
|
+
<div>Recording: in_progress</div>
|
|
246
|
+
<div>Rough cut: pending</div>
|
|
247
|
+
<div>Finalization: pending</div>
|
|
248
|
+
</CardContent>
|
|
249
|
+
</Card>
|
|
250
|
+
<Card>
|
|
251
|
+
<CardHeader>
|
|
252
|
+
<CardTitle className="text-base">Pacotes para editor</CardTitle>
|
|
253
|
+
</CardHeader>
|
|
254
|
+
<CardContent className="space-y-2 text-sm">
|
|
255
|
+
<div>Raw take bundle: available</div>
|
|
256
|
+
<div>Proxy bundle: generating</div>
|
|
257
|
+
</CardContent>
|
|
258
|
+
</Card>
|
|
259
|
+
</TabsContent>
|
|
260
|
+
|
|
261
|
+
<TabsContent value="publication">
|
|
262
|
+
<div className="rounded-md border">
|
|
263
|
+
<Table>
|
|
264
|
+
<TableHeader>
|
|
265
|
+
<TableRow>
|
|
266
|
+
<TableHead>Destino</TableHead>
|
|
267
|
+
<TableHead>Status</TableHead>
|
|
268
|
+
<TableHead>Agendamento</TableHead>
|
|
269
|
+
<TableHead>URL</TableHead>
|
|
270
|
+
</TableRow>
|
|
271
|
+
</TableHeader>
|
|
272
|
+
<TableBody>
|
|
273
|
+
{publicationTargets.map((target) => (
|
|
274
|
+
<TableRow key={target.id}>
|
|
275
|
+
<TableCell>{target.targetType}</TableCell>
|
|
276
|
+
<TableCell>
|
|
277
|
+
<StudioStatusBadge value={target.status} />
|
|
278
|
+
</TableCell>
|
|
279
|
+
<TableCell>
|
|
280
|
+
{target.scheduledAt
|
|
281
|
+
? new Date(target.scheduledAt).toLocaleString('pt-BR')
|
|
282
|
+
: '-'}
|
|
283
|
+
</TableCell>
|
|
284
|
+
<TableCell>{target.publishedUrl || '-'}</TableCell>
|
|
285
|
+
</TableRow>
|
|
286
|
+
))}
|
|
287
|
+
</TableBody>
|
|
288
|
+
</Table>
|
|
289
|
+
</div>
|
|
290
|
+
</TabsContent>
|
|
291
|
+
|
|
292
|
+
<TabsContent value="incidents">
|
|
293
|
+
<div className="rounded-md border">
|
|
294
|
+
<Table>
|
|
295
|
+
<TableHeader>
|
|
296
|
+
<TableRow>
|
|
297
|
+
<TableHead>Tipo</TableHead>
|
|
298
|
+
<TableHead>Severidade</TableHead>
|
|
299
|
+
<TableHead>Alvo</TableHead>
|
|
300
|
+
<TableHead>Status</TableHead>
|
|
301
|
+
</TableRow>
|
|
302
|
+
</TableHeader>
|
|
303
|
+
<TableBody>
|
|
304
|
+
{incidents.map((incident) => (
|
|
305
|
+
<TableRow key={incident.id}>
|
|
306
|
+
<TableCell>{incident.type}</TableCell>
|
|
307
|
+
<TableCell>
|
|
308
|
+
<StudioStatusBadge value={incident.severity} />
|
|
309
|
+
</TableCell>
|
|
310
|
+
<TableCell>{incident.target}</TableCell>
|
|
311
|
+
<TableCell>
|
|
312
|
+
<StudioStatusBadge value={incident.status} />
|
|
313
|
+
</TableCell>
|
|
314
|
+
</TableRow>
|
|
315
|
+
))}
|
|
316
|
+
</TableBody>
|
|
317
|
+
</Table>
|
|
318
|
+
</div>
|
|
319
|
+
</TabsContent>
|
|
320
|
+
</Tabs>
|
|
321
|
+
</Page>
|
|
322
|
+
);
|
|
323
|
+
}
|