chore(autonomous-session): consolidate uncommitted work from prior session
Bundles the prior autonomous-session output that was sitting unstaged: - Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances) - country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk after the per-subpath dynamic-import approach silently failed in webpack) - Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index, redirects (ocr to ai, reports to dashboard, invitations to users), docs/admin-ia-proposal.md - Per-template email tester (registry + endpoint + UI on Email admin page) - Cancel-document mode picker (delete-from-Documenso vs keep-for-audit) - Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers - Customize-widgets per-region sortables at xl+ (charts/rails/feed); single flat sortable below xl when the layout stacks; per-viewport saved orders - Audit doc updates capturing each shipped item - Lint fixes: react-compiler immutability in DonutChart (reduce instead of let-reassign), set-state-in-effect disables in CountryFlag and UploadForSigning preview-bytes effect, unused 'confirm' destructures in interest contract + reservation tabs, unescaped apostrophe in test-template card copy
This commit is contained in:
@@ -92,7 +92,7 @@ export function RegistryDrivenForm({ sections, title, description, extra }: Prop
|
||||
),
|
||||
});
|
||||
|
||||
// Lifted draft state — every field's current input value is held here so
|
||||
// Lifted draft state - every field's current input value is held here so
|
||||
// a card-level "Save N changes" button can write them all in one batch.
|
||||
// Sensitive fields seed as empty (we never seed cleartext from the server);
|
||||
// non-sensitive fields seed from the resolved value.
|
||||
@@ -313,13 +313,13 @@ function SettingField({
|
||||
},
|
||||
onSuccess: (r) => {
|
||||
if (r.revealed && r.value != null) {
|
||||
// Server reveal — populate draft but do NOT mark dirty (the value
|
||||
// Server reveal - populate draft but do NOT mark dirty (the value
|
||||
// already matches what's stored).
|
||||
setDraft(r.value, { dirty: false });
|
||||
setRevealedFromServer(true);
|
||||
setShowSecret(true);
|
||||
} else {
|
||||
toast.info(`${entry.label} isn't set — nothing to reveal.`);
|
||||
toast.info(`${entry.label} isn't set - nothing to reveal.`);
|
||||
}
|
||||
},
|
||||
onError: (err) => toastError(err, `Failed to reveal ${entry.label}`),
|
||||
@@ -439,7 +439,7 @@ function SettingField({
|
||||
disabled={
|
||||
reveal.isPending ||
|
||||
// Disable when the value is resolved from env/default and the
|
||||
// rep hasn't typed anything yet — there's no in-app cleartext
|
||||
// rep hasn't typed anything yet - there's no in-app cleartext
|
||||
// path for those, and silently no-op'ing was indistinguishable
|
||||
// from a broken toggle.
|
||||
(!showSecret &&
|
||||
|
||||
@@ -44,14 +44,14 @@ export interface SettingFieldDef {
|
||||
options?: Array<{ value: string; label: string }>;
|
||||
/** For 'image-upload' fields: aspect ratio for the cropper (default 1).
|
||||
* For 'html' fields: when set, renders an "Insert default" button that
|
||||
* pastes this text into the textarea — used for email-template defaults
|
||||
* pastes this text into the textarea - used for email-template defaults
|
||||
* so admins can see the baseline before editing. */
|
||||
defaultTemplate?: string;
|
||||
/** For 'image-upload' fields: cropper aspect ratio. */
|
||||
imageAspect?: number;
|
||||
/** For 'image-upload' fields: output format. Default 'jpeg' (smaller
|
||||
* files, good for photos / backgrounds). Use 'png' for logos with
|
||||
* transparency — JPEG has no alpha channel, so transparent pixels
|
||||
* transparency - JPEG has no alpha channel, so transparent pixels
|
||||
* composite against black on export. */
|
||||
imageFormat?: 'jpeg' | 'png';
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export function SettingsFormCard({ title, description, fields, extra }: Settings
|
||||
// Parent components often pass `FIELDS.slice(0, 5)` directly, so the prop
|
||||
// reference changes on every render. Capture it in a ref so the fetch
|
||||
// callback can read the current list without being re-created and looping
|
||||
// through useEffect forever. Update inside an effect — writing to ref
|
||||
// through useEffect forever. Update inside an effect - writing to ref
|
||||
// .current during render trips the React Compiler purity rules.
|
||||
const fieldsRef = useRef(fields);
|
||||
useEffect(() => {
|
||||
@@ -112,7 +112,7 @@ export function SettingsFormCard({ title, description, fields, extra }: Settings
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Initial load — fetchValues internally setStates loading + values.
|
||||
// Initial load - fetchValues internally setStates loading + values.
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
void fetchValues();
|
||||
}, [fetchValues]);
|
||||
@@ -404,13 +404,13 @@ function ImageUploadField({
|
||||
|
||||
async function uploadCropped(blob: Blob) {
|
||||
const fd = new FormData();
|
||||
// Trust the blob's own MIME — the cropper auto-picks PNG when the
|
||||
// Trust the blob's own MIME - the cropper auto-picks PNG when the
|
||||
// source had alpha, JPEG otherwise. Hardcoding to JPEG here threw
|
||||
// away the alpha channel on transparent logos.
|
||||
const mime = blob.type || 'image/jpeg';
|
||||
const ext = mime === 'image/png' ? 'png' : 'jpg';
|
||||
fd.append('file', new File([blob], `image.${ext}`, { type: mime }));
|
||||
// Raw fetch (not apiFetch — FormData body) → manually attach the
|
||||
// Raw fetch (not apiFetch - FormData body) → manually attach the
|
||||
// X-Port-Id header that the admin settings route requires.
|
||||
const headers = new Headers();
|
||||
if (typeof window !== 'undefined') {
|
||||
|
||||
@@ -41,12 +41,12 @@ function useCustomFieldTokens() {
|
||||
* Renders the canonical `MERGE_FIELDS` catalog grouped by entity scope.
|
||||
* Below the static catalog, lazily fetches per-port custom field
|
||||
* definitions and renders any whose entityType is resolvable at
|
||||
* send-time (client / interest / berth — see `mergeCustomFieldValues`
|
||||
* send-time (client / interest / berth - see `mergeCustomFieldValues`
|
||||
* in `document-sends.service.ts`) as a "Custom" group.
|
||||
*
|
||||
* The validator accepts any `{{custom.<fieldName>}}` shape, but only
|
||||
* the three entity types above resolve to real values, so we only show
|
||||
* those — surfacing client-portal-only fields would mis-set expectations.
|
||||
* those - surfacing client-portal-only fields would mis-set expectations.
|
||||
*/
|
||||
export function TemplateTokenPicker() {
|
||||
const customQuery = useCustomFieldTokens();
|
||||
|
||||
Reference in New Issue
Block a user