import { relayServerFailure } from '../fetchFailureMessage'; export interface WorkspaceSaveOutcome { /** Did EVERY role land? Anything less is not a save, and the seat is the reason it matters. */ saved: boolean; /** Undefined only when `saved` - there is always something to say about a failure. */ error?: string; } /** * What the workspaces tab says after a save, and whether that save counts as one. * * IT EXISTS BECAUSE "SAVED FOR SOME OF THIS PERSON'S ROLES BUT NOT ALL - 2 OF 2 COULD NOT BE WRITTEN" * IS A SENTENCE THIS SCREEN COULD PRINT. The partial-save copy was written for the case it names, and * nothing checked that some of them HAD landed before printing it. That is unreachable while the server * answers 200 to a seat change it will not make, and it becomes reachable the moment the server starts * refusing - which is the point of the fix on the other side of the wire. A contradiction is not a * denial: the reader cannot tell whether to save again, and the seat they were removing is still billing. * * AND THE SERVER'S OWN SENTENCE IS THE MOST USEFUL THING ON THE SCREEN. Our routes refuse with copy * written to be read - "changing a clinician seat needs the clinicians permission for this practice" - * and it names the thing the administrator has to go and get. `relayServerFailure` is what keeps an * IAM policy string from arriving in its place when the refusal came from the gateway rather than us. * * THE SEAT WARNING BELONGS ONLY TO A PARTIAL. A total failure changed nothing, so telling somebody their * roles may now disagree would be a second false statement in the same message. */ export const describeWorkspaceSaveOutcome = (params: { totalRoles: number; failedRoles: number; /** Was the seat being moved by this save? Only then is the partial dangerous rather than untidy. */ seatWasChanging: boolean; /** The rejection the writes came back with, if any - the server's words are preferred to ours. */ failure?: unknown; }): WorkspaceSaveOutcome => { const { totalRoles, failedRoles, seatWasChanging, failure } = params; if (failedRoles === 0) { return { saved: true }; } // A refusal we wrote, or nothing usable. `relayServerFailure` returns the fallback for a gateway // denial, so an empty fallback here means "the server said nothing worth showing". const relayed = failure === undefined ? '' : relayServerFailure(failure, ''); if (failedRoles >= totalRoles) { return { saved: false, error: relayed ? `Nothing was saved. ${relayed}` : 'Nothing was saved — none of this person\'s roles could be written. ' + 'Their workspaces and clinician seat are unchanged.', }; } return { saved: false, error: `Saved for some of this person's roles but not all — ${failedRoles} of ${totalRoles} ` + 'could not be written.' + (seatWasChanging ? ' The clinician seat may now be set on some of their roles and not others, so the' + ' subscription count and whether they can be booked may disagree. Check the seat' + ' before saving again.' : ' Their workspace assignments are inconsistent until this is saved again.') + (relayed ? ` ${relayed}` : ''), }; };