Skip to content

Commit acddb37

Browse files
committed
feat(actions): say why a greyed lifecycle button is unavailable
Send for Approval, Start Signing and Activate declare a disabledReason (ActionSchema since @objectstack/spec 18.3.0), so the greyed button names the missing precondition instead of the console's generic default. Each reason mirrors the hook's refusal for the same guard, in en and zh-CN. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
1 parent fc68eb6 commit acddb37

3 files changed

Lines changed: 30 additions & 5 deletions

File tree

‎src/actions/contract-lifecycle.actions.ts‎

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ const transition = (
7070
confirmText?: string;
7171
/** Grey the button out while a precondition the hook will refuse is unmet (see below). */
7272
disabled?: ReturnType<typeof P>;
73+
/** What the greyed button says on hover: the precondition `disabled` mirrors. Only beside `disabled`. */
74+
disabledReason?: string;
7375
},
7476
): Action => ({
7577
name,
@@ -155,9 +157,17 @@ const transition = (
155157
// guard it mirrors. Like `visible` it is a convenience, not a control: the
156158
// guards in contract.hook.ts read the children directly and keep refusing.
157159
//
158-
// The console shows its generic reason on hover (「对此记录不可用」 / "Not
159-
// available for this record"): ActionSchema has no key for an authored one.
160+
// `disabledReason` is what the greyed button says on hover and to a screen
161+
// reader (issue #195; ActionSchema key since 18.3.0, objectstack#26619).
162+
// Without it the console says only 「对此记录不可用」 / "Not available for
163+
// this record". It is fixed copy, not an expression: it cannot tell WHICH
164+
// half of an `||` predicate is true, so a reason names every condition its
165+
// predicate tests. It mirrors the hook's refusal sentence for the same
166+
// guard, in the reader's words. Translated at
167+
// `objects.clm_contract._actions.ACTION.disabledReason`. Display only — the
168+
// hook still decides.
160169
...(options?.disabled ? { disabled: options.disabled } : {}),
170+
...(options?.disabledReason ? { disabledReason: options.disabledReason } : {}),
161171
// The status this button writes is the status the header shows, and the
162172
// status every one of these `visible` predicates reads. The spec defaults
163173
// `refreshAfter` to `false` (materialized at parse), and the record page
@@ -238,7 +248,10 @@ export const SendForApprovalAction: Action = transition(
238248
'Close legal review and start approval. Possible once a legal review is approved and no deviation is still open.',
239249
'Sent for approval.',
240250
['clm_legal.access'],
241-
{ disabled: P`record.open_deviation_count > 0 || record.approved_legal_review_count == 0` },
251+
{
252+
disabled: P`record.open_deviation_count > 0 || record.approved_legal_review_count == 0`,
253+
disabledReason: 'An approved legal review is required, and no deviation may still be open, before the contract enters approval.',
254+
},
242255
);
243256

244257
/** 发起签署 — approved, now get it signed. The hook refuses it unless the
@@ -249,7 +262,10 @@ export const StartSigningAction: Action = transition(
249262
'Move an approved contract into signing. Possible once the current version is a clean copy.',
250263
'Signing started.',
251264
['execute_contract'],
252-
{ disabled: P`record.current_clean_version_count == 0` },
265+
{
266+
disabled: P`record.current_clean_version_count == 0`,
267+
disabledReason: 'A current Clean version is required before signing.',
268+
},
253269
);
254270

255271
/** 生效 — the execution formalities are complete. F9 (`contract_activate`)
@@ -274,7 +290,10 @@ export const ActivateContractAction: Action = transition(
274290
'Bring a signed contract into force. Its activation date is recorded and, if it has an end date, a renewal reminder is set up.',
275291
'Contract activated.',
276292
['execute_contract'],
277-
{ disabled: P`record.final_signed_version_count == 0` },
293+
{
294+
disabled: P`record.final_signed_version_count == 0`,
295+
disabledReason: 'A Final Signed version is required before activation.',
296+
},
278297
);
279298

280299
/**

‎src/translations/en/objects.contract.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ export const contract: Record<string, ObjectTranslationData> = {
328328
label: 'Activate',
329329
description: 'Bring a signed contract into force. Its activation date is recorded and, if it has an end date, a renewal reminder is set up.',
330330
successMessage: 'Contract activated.',
331+
disabledReason: 'A Final Signed version is required before activation.',
331332
},
332333
executed_upload: {
333334
label: 'Backfill Executed Contract',
@@ -455,11 +456,13 @@ export const contract: Record<string, ObjectTranslationData> = {
455456
label: 'Send for Approval',
456457
description: 'Close legal review and start approval. Possible once a legal review is approved and no deviation is still open.',
457458
successMessage: 'Sent for approval.',
459+
disabledReason: 'An approved legal review is required, and no deviation may still be open, before the contract enters approval.',
458460
},
459461
start_signing: {
460462
label: 'Start Signing',
461463
description: 'Move an approved contract into signing. Possible once the current version is a clean copy.',
462464
successMessage: 'Signing started.',
465+
disabledReason: 'A current Clean version is required before signing.',
463466
},
464467
submit_contract: {
465468
label: 'Submit',

‎src/translations/zh-CN/objects.contract.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ export const contract: Record<string, ObjectTranslationData> = {
328328
label: '生效',
329329
description: '让已签署的合同正式生效。系统会写入生效时间,并在有到期日时设好续约提醒。',
330330
successMessage: '合同已生效。',
331+
disabledReason: '须先上传一份「最终签署版」版本,才能生效。',
331332
},
332333
executed_upload: {
333334
label: '补录已签合同',
@@ -455,11 +456,13 @@ export const contract: Record<string, ObjectTranslationData> = {
455456
label: '送审',
456457
description: '结束法务审查并开启审批。须有一条通过的法务审查,且没有未决偏离,才能送审。',
457458
successMessage: '已送审,进入审批。',
459+
disabledReason: '须有一条结论为「通过」的法务审查,且没有未决偏离,才能送审。',
458460
},
459461
start_signing: {
460462
label: '发起签署',
461463
description: '把已批准的合同推进到签署中。当前版本须为清稿,才能发起签署。',
462464
successMessage: '已进入签署。',
465+
disabledReason: '当前版本须为「清稿」,才能发起签署。',
463466
},
464467
submit_contract: {
465468
label: '提交',

0 commit comments

Comments
 (0)