feat(client-portal): show shots and task titles in the client's own naming
Deploy / deploy (push) Successful in 6m8s
Deploy / deploy (push) Successful in 6m8s
Shot.clientCode already drove slates, overlay burn-ins and delivered file names, but the client portal — the one place the client actually reads — was still showing our internal codes. Task titles were the larger leak. They follow the house convention "UNG_106_010_020_cmp_TT_v004", so the internal code sat embedded in the string the client reads and copies, in three places on the shot list and again in the player header. Swapping only the heading would have left it on display directly underneath. lib/shot-code.ts resolves both: clientShotCode picks the alias when set, and clientTaskTitle swaps the code out of a title by substring, leaving a hand-edited title that does not carry the code untouched rather than guessing at it. Applied at the API boundary rather than at each render site, so the shot list, search, playlist labels, alt text, player header and every copy-to-clipboard button inherit it and nothing downstream has to remember which code it is holding. The internal code is no longer sent to the browser on these routes at all. Slack notifications deliberately keep the internal code: those go to our artists, who need the code that matches the comp and the SAN path. The two existing "clientCode || shotCode" expressions in preview.ts and deliveries.ts now use the same helper so slates, deliveries and the portal cannot drift apart. Shots with no clientCode are unchanged throughout. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* What a client is shown for a shot.
|
||||
*
|
||||
* `Shot.clientCode` is the naming alias some productions supply — their own
|
||||
* code for the same shot. It already drives slates, overlay burn-ins and
|
||||
* delivered file names (RenderPipeline2 §11.2); internal paths, comp names and
|
||||
* every DB lookup stay on `shotCode`.
|
||||
*
|
||||
* The client portal is the other place the client's own naming belongs, and
|
||||
* that includes task titles: they follow the house convention
|
||||
* `UNG_102_019_010_cmp_TT_v004`, so the internal code is embedded in the
|
||||
* string the client reads and copies.
|
||||
*
|
||||
* Apply these at the API boundary rather than at each render site, so nothing
|
||||
* downstream has to remember which code it is holding.
|
||||
*/
|
||||
|
||||
export interface ShotCodeFields {
|
||||
shotCode: string;
|
||||
clientCode?: string | null;
|
||||
}
|
||||
|
||||
/** The shot's code as the client knows it; their alias if set, ours otherwise. */
|
||||
export function clientShotCode(shot: ShotCodeFields): string {
|
||||
return shot.clientCode?.trim() || shot.shotCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* A task title with the internal shot code swapped for the client's alias.
|
||||
*
|
||||
* Titles are built from the shot code by convention, so this is a substring
|
||||
* swap rather than a rename — a title that does not contain the code (a
|
||||
* hand-edited one, say) is returned untouched rather than guessed at.
|
||||
*/
|
||||
export function clientTaskTitle(title: string, shot: ShotCodeFields): string {
|
||||
const alias = shot.clientCode?.trim();
|
||||
if (!alias || !title || alias === shot.shotCode) return title;
|
||||
// split/join rather than a regex: shot codes are user-supplied and would
|
||||
// otherwise need escaping.
|
||||
return title.split(shot.shotCode).join(alias);
|
||||
}
|
||||
Reference in New Issue
Block a user