Mirrored from GitHub github.com/roostorg/coop

Wire MEDIA scalar through server + client UI (#632) master

* Wire MEDIA scalar through server + client UI Builds on #605 (which added MEDIA to @roostorg/coop-types v2.3.0) to make MEDIA actually usable end-to-end: Server: - Adds MEDIA to ScalarType / FieldType / SignalInputType GraphQL enums. - Adds a coerceMediaInput handler that validates the URL and resolves the media kind from the pathname extension. Conservative table — only unambiguous extensions are mapped, so e.g. .ogg stays unresolved. - Exports detectMediaKindFromUrl so other consumers can run the same detection without going through coerce. - Test arbitrary + 33 unit tests covering happy paths (image / video / audio extensions), unresolved cases (unknown ext, no ext, ambiguous containers), and rejection paths (non-string input, blocked / unsupported schemes, query-string extension confusion). Client: - MEDIA appears in the ItemType form field-type dropdown automatically (the dropdown iterates Object.values(GQLScalarType)). - ManualReviewJobFieldsComponent renders a MEDIA value as image / video / audio per the stored mediaType, falling back to a link when detection didn't resolve. AUDIO/IMAGE/VIDEO branches unchanged. - Updates the exhaustive switches in RuleTestModal, RuleInsightsSamplesTable, generateFakeScalarFieldValue, signal comparators, and the rules-side isMediaType helper so MEDIA is handled everywhere AUDIO/IMAGE/VIDEO were. Closes #418 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(client): return MEDIA fake value as raw URL string generateFakeScalarFieldValue produces *input* (pre-coercion) values for code samples — AUDIO/IMAGE/VIDEO all return raw URL strings, not the post-coerce `{ url }` shape. MEDIA followed the same input contract: a raw URL. This also fixes the CI lint failure on PR #632. Returning an object for MEDIA polluted the function's union return type: TS narrowed RELATED_ITEM's branch to `{ id, typeId, name, url?: undefined, mediaType?: undefined }` and the optional-undefined props tripped the strict JsonValue index signature in itemTypeCodeSampleUtils.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Address CodeRabbit feedback on MEDIA wiring - ManualReviewJobFieldsComponent: include MEDIA in the container layout condition that picks horizontal flex for media value types, so an Array<MEDIA> gets the same horizontal scroll layout as Array<IMAGE> / VIDEO / AUDIO. - itemTypeUtils.generateFakeScalarFieldValue: emit a MEDIA fake URL with a real .jpg / .mp4 / .mp3 extension, cycling between kinds. The previous picsum URL had no extension, so the server's coercion would set mediaType to null and the IMAGE / VIDEO / AUDIO render paths never got fake-data coverage. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>