mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
fix(S29): achados da review — snapshot pós-rebase, manifest e2e e a11y do anúncio
- snapshot drizzle da migration regenerado pós-rebase (inclui as tabelas do S27; sem ele o próximo migrate:create recriaria content_piece) - manifest e2e: CampaignFooter/jingleReads/campaignTime acordam o frontendShareLink; dynamicParams inerte removido da rota .ics - anúncio: dl válido (Local sem dd), aria-live só no status/chip, sem hasImage/cast; hook direct deixa o erro de URL falar antes (+ teste int) - débitos triados no impl plan (folding .ics -> #1281; deferidos com gatilho) Related #1268
This commit is contained in:
parent
b0bac78090
commit
2a0dca6243
8 changed files with 907 additions and 30 deletions
|
|
@ -100,7 +100,7 @@ Não se aplica — a intenção não apresenta dado agregado (sem contagem/analy
|
|||
|
||||
- [ ] Aceite de produto da intenção ainda coberto (modo por link; pool com rótulo; direct sem no-ar recusado; anúncio com data/local; Entrar desativado→ativo ~1 min; agenda Google+.ics com data e sem data esconde o botão; compartilha o link curto; despublicado 404; nada hardcoded para 03/10)
|
||||
- [ ] Invariantes AGENTS/engineering-standards (URL pública intacta; S19 sem mudança de comportamento; fail-closed/noindex; sem Consent/PII; schema só por migration `push:false`; `overrideAccess` documentado; lib→utilities→components→app; pt-BR em copy, inglês em identificador)
|
||||
- [ ] Testes de domínio previstos (unit/int) onde access/write paths mudam — obrigatórios: unit `shareLink` (modo/live/`shareLinkIcsPath`), unit `calendarEvent` (Google/ICS/2h), unit `shareLinkAnnouncement` (view + ilha de ativação jsdom), unit `contentShare` (`event`); int `shareLink` (hook cross-field com mensagens, loader publicado, live target fail-closed). Discricionários: admin e2e do checkbox; ETag do `.ics`. E2E obrigatório estendendo `frontendShareLink`: página de anúncio 200/noindex/sem refresh, `.ics` 200/404, redirect pós-live, e a regressão S19 (redirect/meta/no-JS/404/republicação) — o spec já é do conjunto curado.
|
||||
- [ ] Testes de domínio previstos (unit/int) onde access/write paths mudam — obrigatórios: unit `shareLink` (modo/live/`shareLinkIcsPath`), unit `calendarEvent` (Google/ICS/2h), unit `shareLinkAnnouncement` (view model), unit `contentShare` (`event`); int `shareLink` (hook cross-field com mensagens, loader publicado, live target fail-closed). Discricionários: admin e2e do checkbox; ETag do `.ics`. E2E obrigatório estendendo `frontendShareLink`: página de anúncio 200/noindex/sem refresh, `.ics` 200/404, redirect pós-live, e a regressão S19 (redirect/meta/no-JS/404/republicação) — o spec já é do conjunto curado. A **ilha de ativação** é coberta por e2e (client real, prod e dev) em vez de unit jsdom.
|
||||
|
||||
## Self-score (decision-quality)
|
||||
|
||||
|
|
@ -111,3 +111,10 @@ Não se aplica — a intenção não apresenta dado agregado (sem contagem/analy
|
|||
5. **Intenção satisfeita:** 5 — todos os bullets do aceite mapeados em componentes/fases/testes, incluindo a questão em aberto aprovada (B: link volta a levar direto).
|
||||
|
||||
Média 4.8/5 — plano aprovado no modo `--auto`.
|
||||
|
||||
## Débitos triados (review do PR #1280)
|
||||
|
||||
- **Folding RFC 5545 (75 octets) no `.ics`** — registrado como **#1281** (`S29-FOLLOWUP`, kind chore, P3): owner `src/lib/ical.ts`, 2 call sites (`lib/calendarEvent.ts`, `utilities/calendarFeed.ts`).
|
||||
- **`importMap.js` tracked apesar do OPS99** — descartado: dívida pré-existente do `main`, classe já rastreada em #772/#791 + postmortem 2026-09-12; reavaliar `git rm --cached` quando o guard do #772 fechar.
|
||||
- **Rate limiting da rota `live`** — deferido: gatilho = pico anômalo de requisições na rota (mitigação barata: cache in-memory de 5–10s no loader).
|
||||
- **Settle dev-only de 6s no e2e `frontendShareLink`** — deferido: gatilho = primeira flake local do spec (trocar por condição observável); o SQL cru é deliberado e documentado (isola a race de revalidação/HMR).
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@ export const E2E_AFFECTED_MANIFEST = [
|
|||
prefixes: ['src/lib/contentShare.ts'],
|
||||
specs: ['frontend', 'frontendShareLink'],
|
||||
},
|
||||
{
|
||||
// S29 — the announcement page and its spec derive the Bahia event label
|
||||
// here (the spec imports the formatter), so a diff must wake it.
|
||||
prefixes: ['src/lib/campaignTime.ts'],
|
||||
specs: ['frontendShareLink'],
|
||||
},
|
||||
{
|
||||
// S21 — the public jingles page: ordered published cards, the lazy
|
||||
// in-page player (one at a time), the slug-based download name and the
|
||||
|
|
@ -134,7 +140,9 @@ export const E2E_AFFECTED_MANIFEST = [
|
|||
'src/collections/Jingle.ts',
|
||||
'src/components/jingles',
|
||||
],
|
||||
specs: ['frontendJingles'],
|
||||
// S29 — `hasPublishedJingles` also decides the footer of the announcement
|
||||
// page, so the share-link spec wakes on the same owners.
|
||||
specs: ['frontendJingles', 'frontendShareLink'],
|
||||
},
|
||||
{
|
||||
// S27 — the public Central de Conteúdos: the facet/term catalogue, the
|
||||
|
|
@ -157,10 +165,11 @@ export const E2E_AFFECTED_MANIFEST = [
|
|||
},
|
||||
{
|
||||
// S21 — the campaign footer owns the conditional "Jingles" discovery link
|
||||
// (it renders on the home, the cards page and `/jingles`).
|
||||
// (it renders on the home, the cards page, `/jingles` and the S29
|
||||
// announcement page).
|
||||
// S27 — and the conditional "Conteúdos" link.
|
||||
prefixes: ['src/components/CampaignFooter.tsx'],
|
||||
specs: ['frontend', 'frontendJingles', 'frontendConteudos'],
|
||||
specs: ['frontend', 'frontendJingles', 'frontendConteudos', 'frontendShareLink'],
|
||||
},
|
||||
{
|
||||
// S13/S30 — the personalized-cards studio lives in shared cards components
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { buildCalendarEventIcs } from '@/lib/calendarEvent'
|
|||
import { shareLinkIcsUid } from '@/lib/shareLink'
|
||||
import { getCachedPublishedShareLinkBySlug } from '@/utilities/shareLinkReads'
|
||||
|
||||
export const dynamicParams = true
|
||||
|
||||
type RouteParams = { type: string }
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
isReservedShareLinkSlug,
|
||||
isValidShareLinkDestination,
|
||||
isValidShareLinkSlug,
|
||||
resolveLiveShareLinkDestination,
|
||||
resolveShareLinkMode,
|
||||
type ShareLinkDestinationLike,
|
||||
} from '@/lib/shareLink'
|
||||
|
|
@ -79,14 +78,15 @@ const validateShareLinkConfiguration: CollectionBeforeValidateHook = ({
|
|||
? (nextData.destinations as ShareLinkDestinationLike[])
|
||||
: []
|
||||
|
||||
if (destinations.filter((destination) => destination?.live).length > 1) {
|
||||
const liveCount = destinations.filter((destination) => destination?.live).length
|
||||
if (liveCount > 1) {
|
||||
throw new APIError(SHARE_LINK_LIVE_DUPLICATE_MESSAGE, 400)
|
||||
}
|
||||
|
||||
if (
|
||||
resolveShareLinkMode(nextData.mode) === 'direct' &&
|
||||
!resolveLiveShareLinkDestination(destinations)
|
||||
) {
|
||||
// Only the absence of a flagged row is the `direct` rule's business: a live
|
||||
// row with a malformed URL must surface the field's own URL message (the
|
||||
// runtime read still fails closed on it).
|
||||
if (resolveShareLinkMode(nextData.mode) === 'direct' && liveCount === 0) {
|
||||
throw new APIError(SHARE_LINK_DIRECT_WITHOUT_LIVE_MESSAGE, 400)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ export const ShareLinkAnnouncement = ({
|
|||
}) => {
|
||||
const [live, setLive] = useState<ShareLinkLiveTarget | null>(null)
|
||||
const isLive = live !== null
|
||||
const hasImage = Boolean(view.imageUrl)
|
||||
const hasEventDetails = Boolean(view.eventLabel || view.location)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -100,13 +99,13 @@ export const ShareLinkAnnouncement = ({
|
|||
className={cn(
|
||||
'relative z-1 mx-auto grid max-w-6xl overflow-hidden rounded-[18px] border border-(--campaign-line) bg-white',
|
||||
'shadow-[0_18px_50px_rgb(71_19_14/10%)]',
|
||||
hasImage && 'lg:grid-cols-[0.95fr_1.05fr]',
|
||||
view.imageUrl && 'lg:grid-cols-[0.95fr_1.05fr]',
|
||||
)}
|
||||
>
|
||||
{hasImage ? (
|
||||
{view.imageUrl ? (
|
||||
<div className="relative aspect-[1.91/1] w-full overflow-hidden bg-[#184e92] lg:aspect-auto lg:min-h-[535px]">
|
||||
<Image
|
||||
src={view.imageUrl as string}
|
||||
src={view.imageUrl}
|
||||
alt={view.imageAlt}
|
||||
fill
|
||||
priority
|
||||
|
|
@ -142,9 +141,9 @@ export const ShareLinkAnnouncement = ({
|
|||
)}
|
||||
|
||||
{!isLive && hasEventDetails ? (
|
||||
<dl className="mt-4 grid gap-3 border-y border-black/10 py-4 text-sm sm:mt-7 sm:gap-4 sm:py-5">
|
||||
<div className="mt-4 grid gap-3 border-y border-black/10 py-4 text-sm sm:mt-7 sm:gap-4 sm:py-5">
|
||||
{view.eventLabel ? (
|
||||
<div className="flex items-start gap-3">
|
||||
<dl className="m-0 flex items-start gap-3">
|
||||
<CalendarIcon
|
||||
className="mt-0.5 size-5 flex-none text-(--pt-red)"
|
||||
strokeWidth={2}
|
||||
|
|
@ -156,7 +155,7 @@ export const ShareLinkAnnouncement = ({
|
|||
Horário da Bahia
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</dl>
|
||||
) : null}
|
||||
{view.location ? (
|
||||
<div className="flex items-center gap-3">
|
||||
|
|
@ -165,15 +164,18 @@ export const ShareLinkAnnouncement = ({
|
|||
strokeWidth={2}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<dt className="font-bold text-black">{view.location}</dt>
|
||||
<span className="font-bold text-black">{view.location}</span>
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="mt-auto pt-5 sm:pt-7" aria-live="polite">
|
||||
<div className="mt-auto pt-5 sm:pt-7">
|
||||
{isLive && live ? (
|
||||
<div className="mb-3 flex flex-wrap items-center justify-center gap-2 text-xs font-bold text-black/55">
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="mb-3 flex flex-wrap items-center justify-center gap-2 text-xs font-bold text-black/55"
|
||||
>
|
||||
<span>Destino no ar</span>
|
||||
<span className="rounded-full bg-(--campaign-band) px-2.5 py-1 text-black">
|
||||
{live.label || 'Destino'}
|
||||
|
|
@ -204,7 +206,10 @@ export const ShareLinkAnnouncement = ({
|
|||
)}
|
||||
|
||||
{!isLive ? (
|
||||
<p className="mt-3 text-center text-xs font-medium text-black/55 sm:text-sm">
|
||||
<p
|
||||
aria-live="polite"
|
||||
className="mt-3 text-center text-xs font-medium text-black/55 sm:text-sm"
|
||||
>
|
||||
A transmissão ainda não começou.
|
||||
</p>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export type CalendarEventInput = {
|
|||
endsAt?: string | null
|
||||
}
|
||||
|
||||
const formatICSInstant = (date: Date): string => formatICalDate(date.toISOString())
|
||||
const formatInstant = (date: Date): string => formatICalDate(date.toISOString())
|
||||
|
||||
/**
|
||||
* The event window: no `startsAt` (or an invalid one) means "no event" — the
|
||||
|
|
@ -49,7 +49,7 @@ export const buildGoogleCalendarEventUrl = (event: CalendarEventInput): string |
|
|||
const params = new URLSearchParams({
|
||||
action: 'TEMPLATE',
|
||||
text: event.title,
|
||||
dates: `${formatICSInstant(window.start)}/${formatICSInstant(window.end)}`,
|
||||
dates: `${formatInstant(window.start)}/${formatInstant(window.end)}`,
|
||||
})
|
||||
if (event.description) params.set('details', event.description)
|
||||
if (event.location) params.set('location', event.location)
|
||||
|
|
@ -80,9 +80,9 @@ export const buildCalendarEventIcs = ({
|
|||
'METHOD:PUBLISH',
|
||||
'BEGIN:VEVENT',
|
||||
`UID:${escapeICalText(uid)}`,
|
||||
`DTSTAMP:${formatICSInstant(dtstamp)}`,
|
||||
`DTSTART:${formatICSInstant(window.start)}`,
|
||||
`DTEND:${formatICSInstant(window.end)}`,
|
||||
`DTSTAMP:${formatInstant(dtstamp)}`,
|
||||
`DTSTART:${formatInstant(window.start)}`,
|
||||
`DTEND:${formatInstant(window.end)}`,
|
||||
`SUMMARY:${escapeICalText(event.title)}`,
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -8362,6 +8362,699 @@
|
|||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.content_piece_topics": {
|
||||
"name": "content_piece_topics",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"parent_id": {
|
||||
"name": "parent_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "enum_content_piece_topics",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"content_piece_topics_order_idx": {
|
||||
"name": "content_piece_topics_order_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "order",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_topics_parent_idx": {
|
||||
"name": "content_piece_topics_parent_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "parent_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_topics_value_idx": {
|
||||
"name": "content_piece_topics_value_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "value",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"content_piece_topics_parent_fk": {
|
||||
"name": "content_piece_topics_parent_fk",
|
||||
"tableFrom": "content_piece_topics",
|
||||
"tableTo": "content_piece",
|
||||
"columnsFrom": [
|
||||
"parent_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.content_piece_curated_fields": {
|
||||
"name": "content_piece_curated_fields",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"parent_id": {
|
||||
"name": "parent_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "enum_content_piece_curated_fields",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"content_piece_curated_fields_order_idx": {
|
||||
"name": "content_piece_curated_fields_order_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "order",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_curated_fields_parent_idx": {
|
||||
"name": "content_piece_curated_fields_parent_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "parent_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"content_piece_curated_fields_parent_fk": {
|
||||
"name": "content_piece_curated_fields_parent_fk",
|
||||
"tableFrom": "content_piece_curated_fields",
|
||||
"tableTo": "content_piece",
|
||||
"columnsFrom": [
|
||||
"parent_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.content_piece": {
|
||||
"name": "content_piece",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "enum_content_piece_type",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"municipality_id": {
|
||||
"name": "municipality_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"city_label": {
|
||||
"name": "city_label",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"region": {
|
||||
"name": "region",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"institution": {
|
||||
"name": "institution",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"piece_date": {
|
||||
"name": "piece_date",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"duration_seconds": {
|
||||
"name": "duration_seconds",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"transcript": {
|
||||
"name": "transcript",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"media_id": {
|
||||
"name": "media_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"source_url": {
|
||||
"name": "source_url",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"origin": {
|
||||
"name": "origin",
|
||||
"type": "enum_content_piece_origin",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'arquivo'"
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "enum_content_piece_status",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'rascunho'"
|
||||
},
|
||||
"published_at": {
|
||||
"name": "published_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"processing_status": {
|
||||
"name": "processing_status",
|
||||
"type": "enum_content_piece_processing_status",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'pronto'"
|
||||
},
|
||||
"step": {
|
||||
"name": "step",
|
||||
"type": "enum_content_piece_step",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"error": {
|
||||
"name": "error",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"search_text": {
|
||||
"name": "search_text",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_by_id": {
|
||||
"name": "created_by_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"content_piece_slug_idx": {
|
||||
"name": "content_piece_slug_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "slug",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_type_idx": {
|
||||
"name": "content_piece_type_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "type",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_municipality_idx": {
|
||||
"name": "content_piece_municipality_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "municipality_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_piece_date_idx": {
|
||||
"name": "content_piece_piece_date_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "piece_date",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_media_idx": {
|
||||
"name": "content_piece_media_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "media_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_source_url_idx": {
|
||||
"name": "content_piece_source_url_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "source_url",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_status_idx": {
|
||||
"name": "content_piece_status_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "status",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_processing_status_idx": {
|
||||
"name": "content_piece_processing_status_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "processing_status",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_created_by_idx": {
|
||||
"name": "content_piece_created_by_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "created_by_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_updated_at_idx": {
|
||||
"name": "content_piece_updated_at_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "updated_at",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_piece_created_at_idx": {
|
||||
"name": "content_piece_created_at_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "created_at",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"content_piece_municipality_id_municipality_id_fk": {
|
||||
"name": "content_piece_municipality_id_municipality_id_fk",
|
||||
"tableFrom": "content_piece",
|
||||
"tableTo": "municipality",
|
||||
"columnsFrom": [
|
||||
"municipality_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"content_piece_media_id_content_media_id_fk": {
|
||||
"name": "content_piece_media_id_content_media_id_fk",
|
||||
"tableFrom": "content_piece",
|
||||
"tableTo": "content_media",
|
||||
"columnsFrom": [
|
||||
"media_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"content_piece_created_by_id_campaign_user_id_fk": {
|
||||
"name": "content_piece_created_by_id_campaign_user_id_fk",
|
||||
"tableFrom": "content_piece",
|
||||
"tableTo": "campaign_user",
|
||||
"columnsFrom": [
|
||||
"created_by_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.content_media": {
|
||||
"name": "content_media",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"alt": {
|
||||
"name": "alt",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail_u_r_l": {
|
||||
"name": "thumbnail_u_r_l",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"filename": {
|
||||
"name": "filename",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"mime_type": {
|
||||
"name": "mime_type",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"filesize": {
|
||||
"name": "filesize",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"width": {
|
||||
"name": "width",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"height": {
|
||||
"name": "height",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"focal_x": {
|
||||
"name": "focal_x",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"focal_y": {
|
||||
"name": "focal_y",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"content_media_updated_at_idx": {
|
||||
"name": "content_media_updated_at_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "updated_at",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_media_created_at_idx": {
|
||||
"name": "content_media_created_at_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "created_at",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"content_media_filename_idx": {
|
||||
"name": "content_media_filename_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "filename",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": true,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.recording_speaker_labels": {
|
||||
"name": "recording_speaker_labels",
|
||||
"schema": "",
|
||||
|
|
@ -13993,6 +14686,18 @@
|
|||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"content_piece_id": {
|
||||
"name": "content_piece_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"content_media_id": {
|
||||
"name": "content_media_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"recording_id": {
|
||||
"name": "recording_id",
|
||||
"type": "integer",
|
||||
|
|
@ -14493,6 +15198,36 @@
|
|||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"payload_locked_documents_rels_content_piece_id_idx": {
|
||||
"name": "payload_locked_documents_rels_content_piece_id_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "content_piece_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"payload_locked_documents_rels_content_media_id_idx": {
|
||||
"name": "payload_locked_documents_rels_content_media_id_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "content_media_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
},
|
||||
"payload_locked_documents_rels_recording_id_idx": {
|
||||
"name": "payload_locked_documents_rels_recording_id_idx",
|
||||
"columns": [
|
||||
|
|
@ -15077,6 +15812,32 @@
|
|||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"payload_locked_documents_rels_content_piece_fk": {
|
||||
"name": "payload_locked_documents_rels_content_piece_fk",
|
||||
"tableFrom": "payload_locked_documents_rels",
|
||||
"tableTo": "content_piece",
|
||||
"columnsFrom": [
|
||||
"content_piece_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"payload_locked_documents_rels_content_media_fk": {
|
||||
"name": "payload_locked_documents_rels_content_media_fk",
|
||||
"tableFrom": "payload_locked_documents_rels",
|
||||
"tableTo": "content_media",
|
||||
"columnsFrom": [
|
||||
"content_media_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"payload_locked_documents_rels_recording_fk": {
|
||||
"name": "payload_locked_documents_rels_recording_fk",
|
||||
"tableFrom": "payload_locked_documents_rels",
|
||||
|
|
@ -16928,6 +17689,91 @@
|
|||
"unpublished"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_topics": {
|
||||
"name": "enum_content_piece_topics",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"saude",
|
||||
"educacao",
|
||||
"cultura",
|
||||
"esporte",
|
||||
"seguranca-publica",
|
||||
"meio-ambiente",
|
||||
"economia-trabalho",
|
||||
"direitos-humanos",
|
||||
"infraestrutura",
|
||||
"ciencia-tecnologia",
|
||||
"politica-instituicoes",
|
||||
"agricultura",
|
||||
"habitacao-cidades",
|
||||
"comunicacao-midia",
|
||||
"igualdade-racial",
|
||||
"mulheres-genero",
|
||||
"juventude",
|
||||
"pessoa-deficiencia"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_curated_fields": {
|
||||
"name": "enum_content_piece_curated_fields",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"title",
|
||||
"description",
|
||||
"topics",
|
||||
"municipality",
|
||||
"institution",
|
||||
"pieceDate",
|
||||
"transcript",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_type": {
|
||||
"name": "enum_content_piece_type",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"video",
|
||||
"foto",
|
||||
"texto",
|
||||
"audio",
|
||||
"card"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_origin": {
|
||||
"name": "enum_content_piece_origin",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"arquivo",
|
||||
"instagram",
|
||||
"youtube"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_status": {
|
||||
"name": "enum_content_piece_status",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"rascunho",
|
||||
"publicado"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_processing_status": {
|
||||
"name": "enum_content_piece_processing_status",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"processando",
|
||||
"pronto",
|
||||
"falhou"
|
||||
]
|
||||
},
|
||||
"public.enum_content_piece_step": {
|
||||
"name": "enum_content_piece_step",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"extraindo",
|
||||
"transcrevendo",
|
||||
"catalogando",
|
||||
"salvando"
|
||||
]
|
||||
},
|
||||
"public.enum_recording_status": {
|
||||
"name": "enum_recording_status",
|
||||
"schema": "public",
|
||||
|
|
@ -17264,6 +18110,6 @@
|
|||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "267190ce-de8f-4bbf-8b43-de400507dc4d",
|
||||
"id": "a043d1e9-f128-4742-90d5-2deb25a9b7d4",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
|
|
@ -251,6 +251,18 @@ describe('shareLink', () => {
|
|||
},
|
||||
)
|
||||
|
||||
it('lets the URL field speak when a live row has a malformed URL', async () => {
|
||||
const messages = await createErrorMessages({
|
||||
title: 'URL malformada no ar',
|
||||
slug: 'url-malformada-no-ar-s29',
|
||||
description: 'x',
|
||||
mode: 'direct',
|
||||
destinations: [{ label: 'Meet', url: 'meet.google.com/abc', live: true }],
|
||||
})
|
||||
|
||||
expect(messages).toContain(SHARE_LINK_DESTINATION_INVALID_MESSAGE)
|
||||
})
|
||||
|
||||
it('rejects more than one destination on air', async () => {
|
||||
await expect(
|
||||
createShareLink({
|
||||
|
|
|
|||
Loading…
Reference in a new issue