Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changeset/approvals-zh-nav-action-views.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

`revenue/approvals` (zh-Hans, zh-Hant): the sidebar entry and its group are now spelled as the app's zh-CN pack renders them (待我审批 / 我的工作, Traditional script on zh-Hant), the three `sys_approval_action` views take the approvals plugin's zh-CN labels (最近 / 按执行人 / 全部) without the English gloss, and the **Completed** view is described on all three pages as including cancelled requests, matching the installed plugin's filter. Docs only; nothing ships in the package (#1976).
2 changes: 1 addition & 1 deletion content/docs/revenue/approvals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The approvals plugin also ships four built-in list views on the `sys_approval_re
| --- | --- |
| **My Pending** | Requests still pending where you are one of the approvers |
| **I Submitted** | Everything you submitted, in any state |
| **Completed** | Requests that ended — approved, rejected or recalled |
| **Completed** | Requests that ended — approved, rejected, recalled or cancelled |
| **All** | Every request, most recently updated first |

Read those as a second screen, not as the tabs above. Two names sit on both sides unchanged, and one pair differs by a single word:
Expand Down
10 changes: 5 additions & 5 deletions content/docs/revenue/approvals.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ approval 节点使用**首次响应**(`first_response`)行为——在每个

## 在哪里找到待处理的审批

HotCRM 应用里审批只有一个入口,它挂在 **My Work**(我的工作)分组下——等着你审批的事情本身就是你的工作,所以它与你的任务、商机、工单并列,而不是单独占一个分组。**My Work** 在应用加载时就是展开的,不必先点开分组才能看见它。
HotCRM 应用里审批只有一个入口,它挂在 **我的工作** 分组下——等着你审批的事情本身就是你的工作,所以它与你的任务、商机、工单并列,而不是单独占一个分组。**我的工作** 在应用加载时就是展开的,不必先点开分组才能看见它。

- **Inbox**——点开后进入平台的**审批中心**,也就是真正能把待办审批批准或拒绝的那块界面。侧边栏上的 label 就是 **Inbox**,简体中文界面下这一项显示为**待我审批**;应用里没有任何导航条目叫 *Approval Requests*(审批请求)。这个名字不是凭空捏造:它是审批插件给**对象**起的名字(*Approval Request* / *Approval Requests*,简体界面为「审批请求」)——只是本页把它摆在了侧边栏条目的位置上。
- **待我审批**——点开后进入平台的**审批中心**,也就是真正能把待办审批批准或拒绝的那块界面。侧边栏上这一项的 label 就是 **待我审批**;应用里没有任何导航条目叫 *Approval Requests*(审批请求)。这个名字不是凭空捏造:它是审批插件给**对象**起的名字(*Approval Request* / *Approval Requests*,简体界面为「审批请求」)——只是本页把它摆在了侧边栏条目的位置上。下面会看到,审批中心的第一个页签和对象内置的第一个视图也都叫 **待我审批**——三处同名,却是三样东西。

该条目没有绑定自己的视图。它过去落在 `sys_approval_request` 对象的列表页上,而那个列表是只读的——能看到请求,却动不了它——所以现在改为直接打开审批中心,也就是带**批准** / **拒绝**按钮的那块界面。对象名仍然留在条目上,作用是在没装审批插件的环境里把整个条目隐藏掉,但它已经不是这一项的落点了。

Expand All @@ -99,13 +99,13 @@ HotCRM 应用里审批只有一个入口,它挂在 **My Work**(我的工作

### 对象自带的列表视图是另一块界面

审批插件同时还在 `sys_approval_request` **对象**上内置了四个列表视图。它们是真实存在、也仍在发货的——只是点 **Inbox** 打不开它们,本应用侧边栏里也没有任何条目能打开:
审批插件同时还在 `sys_approval_request` **对象**上内置了四个列表视图。它们是真实存在、也仍在发货的——只是点侧边栏的 **待我审批** 条目打不开它们,本应用侧边栏里也没有任何条目能打开:

| 对象内置视图 | 内容 |
| --- | --- |
| **待我审批** | 仍在待批、且你是审批人之一的请求 |
| **我提交的** | 你提交过的全部请求,不分状态 |
| **已完成** | 已结束的请求——已批准、已拒绝或已撤回 |
| **已完成** | 已结束的请求——已批准、已拒绝、已撤回或已作废 |
| **全部** | 全部请求,按最近更新排序 |

请把这四个当成第二块界面,不要和上面的页签混着读。有两个名字在两边一模一样,还有一对只差一个词:
Expand All @@ -119,7 +119,7 @@ HotCRM 应用里审批只有一个入口,它挂在 **My Work**(我的工作

本页过去列出的三个名字——*Pending My Approval*、*Submitted by Me*、*Recently Approved*——**哪里都不存在**:`src/` 与已安装的审批插件双面零命中,换任何拼写都一样。它们想描述的其实就是 **待我审批**、**我提交的** 和 **已完成**。有一点是随这次改指向新出现的:审批中心的 **我发起的** 页签在英文界面上叫 *Submitted by me*,与幻影名字 *Submitted by Me* 只差一个字母的大小写。那个页签是审批中心里真实存在的一块界面,但它从来不是对象上的视图。

**Action History**(操作历史)同样不在这个分组里,本应用侧边栏上也没有任何条目叫这个名字。审批的操作留痕本身是真实数据——审批插件把每一次操作存为 `sys_approval_action`,还为它内置了 **Recent**(最近)/ **By Actor**(按执行人)/ **All**(全部)三个视图,每条操作都通过 `request_id` 指回它所属的请求。缺的只是入口:本应用里没有任何导航条目能打开这个对象。
**Action History**(操作历史)同样不在这个分组里,本应用侧边栏上也没有任何条目叫这个名字。审批的操作留痕本身是真实数据——审批插件把每一次操作存为 `sys_approval_action`,还为它内置了 **最近** / **按执行人** / **全部** 三个视图,每条操作都通过 `request_id` 指回它所属的请求。缺的只是入口:本应用里没有任何导航条目能打开这个对象。

## 给销售代表的提示

Expand Down
10 changes: 5 additions & 5 deletions content/docs/revenue/approvals.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ approval 節點使用**首次回應**(`first_response`)行為——在每個

## 在哪裡找到待處理的審批

HotCRM 應用裡審批只有一個入口,它掛在 **My Work**(我的工作)群組下——等著你審批的事情本身就是你的工作,所以它與你的任務、商機、工單並列,而不是單獨佔一個群組。**My Work** 在應用載入時就是展開的,不必先點開群組才能看見它。
HotCRM 應用裡審批只有一個入口,它掛在 **我的工作** 群組下——等著你審批的事情本身就是你的工作,所以它與你的任務、商機、工單並列,而不是單獨佔一個群組。**我的工作** 在應用載入時就是展開的,不必先點開群組才能看見它。

- **Inbox**——點開後進入平台的**審批中心**,也就是真正能把待辦審批批准或拒絕的那塊介面。側邊欄上的 label 就是 **Inbox**(本應用提供 en / zh-CN / ja-JP / es-ES 四種介面語言,簡體中文介面下這一項顯示為「待我审批」);應用裡沒有任何導覽條目叫 *Approval Requests*(審批請求)。這個名字不是憑空捏造:它是審批外掛給**物件**取的名字(*Approval Request* / *Approval Requests*)——只是本頁把它擺在了側邊欄條目的位置上。
- **待我審批**——點開後進入平台的**審批中心**,也就是真正能把待辦審批批准或拒絕的那塊介面。側邊欄上這一項的 label 就是 **待我審批**(本應用提供 en / zh-CN / ja-JP / es-ES 四種介面語言,簡體中文介面下這一項顯示為「待我审批」);應用裡沒有任何導覽條目叫 *Approval Requests*(審批請求)。這個名字不是憑空捏造:它是審批外掛給**物件**取的名字(*Approval Request* / *Approval Requests*)——只是本頁把它擺在了側邊欄條目的位置上。下面會看到,審批中心的第一個頁籤和物件內建的第一個檢視也都叫 **待我審批**——三處同名,卻是三樣東西。

該條目沒有綁定自己的檢視。它過去落在 `sys_approval_request` 物件的列表頁上,而那個列表是唯讀的——看得到請求,卻動不了它——所以現在改成直接打開審批中心,也就是帶**批准** / **拒絕**按鈕的那塊介面。物件名仍然留在條目上,作用是在沒裝審批外掛的環境裡把整個條目隱藏掉,但它已經不是這一項的落點了。

Expand All @@ -101,13 +101,13 @@ HotCRM 應用裡審批只有一個入口,它掛在 **My Work**(我的工作

### 物件自帶的列表檢視是另一塊介面

審批外掛同時還在 `sys_approval_request` **物件**上內建了四個列表檢視。它們是真實存在、也仍在出貨的——只是點 **Inbox** 打不開它們,本應用側邊欄裡也沒有任何條目能打開:
審批外掛同時還在 `sys_approval_request` **物件**上內建了四個列表檢視。它們是真實存在、也仍在出貨的——只是點側邊欄的 **待我審批** 條目打不開它們,本應用側邊欄裡也沒有任何條目能打開:

| 物件內建檢視 | 內容 |
| --- | --- |
| **待我審批** | 仍在待批、且你是審批人之一的請求 |
| **我提交的** | 你提交過的全部請求,不分狀態 |
| **已完成** | 已結束的請求——已批准、已拒絕或已撤回 |
| **已完成** | 已結束的請求——已批准、已拒絕、已撤回或已作廢 |
| **全部** | 全部請求,按最近更新排序 |

請把這四個當成第二塊介面,不要和上面的頁籤混著讀。有兩個名字在兩邊一模一樣,還有一對只差一個詞:
Expand All @@ -121,7 +121,7 @@ HotCRM 應用裡審批只有一個入口,它掛在 **My Work**(我的工作

本頁過去列出的三個名字——*Pending My Approval*、*Submitted by Me*、*Recently Approved*——**哪裡都不存在**:`src/` 與已安裝的審批外掛雙面零命中,換任何拼寫都一樣。它們想描述的其實就是 **待我審批**、**我提交的** 和 **已完成**。有一點是隨這次改指向新出現的:審批中心的 **我發起的** 頁籤在英文介面上叫 *Submitted by me*,與幻影名字 *Submitted by Me* 只差一個字母的大小寫。那個頁籤是審批中心裡真實存在的一塊介面,但它從來不是物件上的檢視。

**Action History**(操作歷史)同樣不在這個群組裡,本應用側邊欄上也沒有任何條目叫這個名字。審批的操作留痕本身是真實資料——審批外掛把每一次操作存為 `sys_approval_action`,還為它內建了 **Recent**(最近)/ **By Actor**(按執行人)/ **All**(全部)三個檢視,每條操作都透過 `request_id` 指回它所屬的請求。缺的只是入口:本應用裡沒有任何導覽條目能打開這個物件。
**Action History**(操作歷史)同樣不在這個群組裡,本應用側邊欄上也沒有任何條目叫這個名字。審批的操作留痕本身是真實資料——審批外掛把每一次操作存為 `sys_approval_action`,還為它內建了 **最近** / **按執行人** / **全部** 三個檢視,每條操作都透過 `request_id` 指回它所屬的請求。缺的只是入口:本應用裡沒有任何導覽條目能打開這個物件。

## 給銷售代表的提示

Expand Down
45 changes: 32 additions & 13 deletions test/docs-revenue-approvals-navigation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const REQUEST_VIEWS = viewLabels(SysApprovalRequest as unknown as AnyRec);
const ACTION_VIEWS = viewLabels(SysApprovalAction as unknown as AnyRec);

/**
* The zh-CN labels of the request views, from the plugin's own pack — a Chinese
* The zh-CN labels of the plugin's views, from the plugin's own pack — a Chinese
* page spells a view name as the zh-CN value of the pack that owns the object
* (#1552). The package exports its schemas but not its locale packs, so the
* labels are read off the built bundle with its `\uXXXX` escapes decoded, the
Expand All @@ -142,22 +142,31 @@ const ZH_CN_PLUGIN_OBJECTS: string = (() => {
return end < 0 ? raw.slice(start) : raw.slice(start, start + 1 + end);
})();

const ZH_HANS_REQUEST_VIEWS: string[] = Object.keys(
((SysApprovalRequest as unknown as AnyRec).listViews ?? {}) as Record<string, AnyRec>,
).map((key) => {
const m = ZH_CN_PLUGIN_OBJECTS.match(new RegExp(`\\b${key}:\\s*\\{\\s*label:\\s*"([^"]+)"`));
if (!m) throw new Error(`the approvals plugin ships no zh-CN label for view '${key}'`);
return m[1];
});
/** The zh-CN labels of one plugin object's views, read from the plugin's pack. */
const zhHansViews = (schema: AnyRec): string[] =>
Object.keys((schema.listViews ?? {}) as Record<string, AnyRec>).map((key) => {
const m = ZH_CN_PLUGIN_OBJECTS.match(new RegExp(`\\b${key}:\\s*\\{\\s*label:\\s*"([^"]+)"`));
if (!m) throw new Error(`the approvals plugin ships no zh-CN label for view '${key}'`);
return m[1];
});

const ZH_HANS_REQUEST_VIEWS = zhHansViews(SysApprovalRequest as unknown as AnyRec);
const ZH_HANS_ACTION_VIEWS = zhHansViews(SysApprovalAction as unknown as AnyRec);

/**
* No pack ships Traditional script, so the zh-Hant page spells the same labels
* by character conversion only (no word swap) — the convention AGENTS.md sets
* for zh-Hant view names. Only the characters these labels use are mapped.
*/
const ZH_HANT_REQUEST_VIEWS = ZH_HANS_REQUEST_VIEWS.map((l) =>
l.replace(/审/g, '審').replace(/发/g, '發'),
);
const toHant = (l: string): string =>
l.replace(/审/g, '審').replace(/发/g, '發').replace(/执/g, '執');

const ZH_HANT_REQUEST_VIEWS = ZH_HANS_REQUEST_VIEWS.map(toHant);
const ZH_HANT_ACTION_VIEWS = ZH_HANS_ACTION_VIEWS.map(toHant);

/** The Inbox entry's label as this app's own zh-CN pack renders it (#1976). */
const ZH_HANS_INBOX: string =
(packFor('zh-CN') as AnyRec)?.apps?.[CrmApp.name]?.navigation?.nav_approval_requests?.label;

/**
* Which destination the Inbox entry actually carries, reduced to the
Expand Down Expand Up @@ -233,8 +242,12 @@ const PAGES = [
file: 'content/docs/revenue/approvals.mdx',
lang: 'en',
heading: '## Where to find pending approvals',
/** The Inbox entry's label, in this page's language. */
inboxLabel: 'Inbox',
/** The request views' labels, in this page's language. */
requestViews: REQUEST_VIEWS,
/** The action views' labels, in this page's language. */
actionViews: ACTION_VIEWS,
/** The denials the section must actually make, not merely imply. */
denials: [
/\*Approval Requests\* is not a navigation entry anywhere in this app/,
Expand Down Expand Up @@ -267,7 +280,9 @@ const PAGES = [
file: 'content/docs/revenue/approvals.zh-Hans.mdx',
lang: 'zh-Hans',
heading: '## 在哪里找到待处理的审批',
inboxLabel: ZH_HANS_INBOX,
requestViews: ZH_HANS_REQUEST_VIEWS,
actionViews: ZH_HANS_ACTION_VIEWS,
denials: [
/应用里没有任何导航条目叫 \*Approval Requests\*/,
/哪里都不存在/,
Expand Down Expand Up @@ -303,7 +318,9 @@ const PAGES = [
file: 'content/docs/revenue/approvals.zh-Hant.mdx',
lang: 'zh-Hant',
heading: '## 在哪裡找到待處理的審批',
inboxLabel: toHant(ZH_HANS_INBOX),
requestViews: ZH_HANT_REQUEST_VIEWS,
actionViews: ZH_HANT_ACTION_VIEWS,
denials: [
/應用裡沒有任何導覽條目叫 \*Approval Requests\*/,
/哪裡都不存在/,
Expand Down Expand Up @@ -527,7 +544,9 @@ describe('revenue/approvals names the navigation that exists (#963, #1162)', ()
({
file,
heading,
inboxLabel,
requestViews,
actionViews,
denials,
attribution,
destinationClaims,
Expand All @@ -538,7 +557,7 @@ describe('revenue/approvals names the navigation that exists (#963, #1162)', ()
const section = () => sectionOf(file, heading);

it('names the real sidebar item', () => {
expect(section()).toContain('Inbox');
expect(section()).toContain(inboxLabel);
});

/**
Expand Down Expand Up @@ -613,7 +632,7 @@ describe('revenue/approvals names the navigation that exists (#963, #1162)', ()

it('lists the audit-trail views too, so "real data, no entry point" is concrete', () => {
const text = section();
expect(ACTION_VIEWS.filter((l) => !text.includes(l))).toEqual([]);
expect(actionViews.filter((l) => !text.includes(l))).toEqual([]);
expect(text).toContain(SysApprovalAction.name);
});

Expand Down
Loading