feat(uat-batch-12): password-reveal env messaging + berth Latest-stage sortable
- registry-driven-form password-reveal eye toggle: when the value is resolved from env / default fallback (not port / global override), the toggle is now disabled with a tooltip explaining "Value comes from the environment. Configure in admin to enable reveal." Stops the silent-no-op confusion that read as a broken toggle. - Berth list: 'Latest deal stage' column dropped enableSorting:false. Service-side adds a stageSort correlated subquery that ranks each berth by the highest active interest's pipelineStage (enquiry=1 → contract=7); NULLS LAST regardless of direction so empty rows always land at the bottom. tsc clean. 1419/1419 vitest pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -436,7 +436,27 @@ function SettingField({
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
disabled={reveal.isPending}
|
||||
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
|
||||
// path for those, and silently no-op'ing was indistinguishable
|
||||
// from a broken toggle.
|
||||
(!showSecret &&
|
||||
resolved?.isSet === true &&
|
||||
(resolved?.source === 'env' || resolved?.source === 'default') &&
|
||||
!(typeof draft === 'string' && draft.length > 0))
|
||||
}
|
||||
title={
|
||||
!showSecret &&
|
||||
resolved?.isSet === true &&
|
||||
(resolved?.source === 'env' || resolved?.source === 'default') &&
|
||||
!(typeof draft === 'string' && draft.length > 0)
|
||||
? 'Value comes from the environment. Configure in admin to enable reveal.'
|
||||
: showSecret
|
||||
? 'Hide value'
|
||||
: 'Reveal value'
|
||||
}
|
||||
onClick={() => {
|
||||
if (showSecret) {
|
||||
// Hide. If this draft came from the server reveal, drop it so
|
||||
|
||||
@@ -273,7 +273,7 @@ export const berthColumns: ColumnDef<BerthRow, unknown>[] = [
|
||||
{
|
||||
id: 'latestInterestStage',
|
||||
header: 'Latest deal stage',
|
||||
enableSorting: false,
|
||||
enableSorting: true,
|
||||
cell: ({ row }) => {
|
||||
const s = row.original.latestInterestStage;
|
||||
if (!s) return <span className="text-muted-foreground">-</span>;
|
||||
|
||||
Reference in New Issue
Block a user