UX Spec

Manage Device Access by Site

Amy TangJul 9 2026
Open Spec Changes
manage-device-access-role-improvement
formalize-rebac-permission-model
Prototype
manage-device-access-role-improvement-demo.html(edit a user's device access across the Site tree)

Visual basis: vortex-1.0 — verify behavior / copy / structure, not pixel style.

Context

Why we're building this

VORTEX grants device access per user, per device — an Admin/Owner decides which roles a single user may hold on the organization's devices. At scale (up to ~1,000 sites and ~300,000 devices) doing that device-by-device is impractical, so access is managed against the Site tree: check the sites or areas that should retain access, set a role per node or per device, then review before submitting.

Manage Device Access by Site is the single edit surface for that. It opens from a user's detail page, preloads the user's current access, and submits only the diff. The dialog assembles the Site Tree View (node-inclusive tri-state) and the Filter Combo search/filter conventions, adding batch application, single-device drill-in, linked-device (NVR / Bridge) reconciliation, and a reviewable change set.

What value it brings

One surface to assign a user's device access across the whole organization, at any granularity:

  • Batch — one role to the entire org, or to a selection of sites/areas
  • Precise — drill into a site to set a single device
  • Safe — every change (including removals) is tracked, reviewable, and reversible before submit; destructive edits are recorded, not hidden
Section 01

對話框結構與進入點

Manage Device Access by Site 是一個模態對話框,讓管理者(Admin / Owner)設定單一使用者對整個組織裝置的存取角色。固定尺寸 1116 × 747,分三塊。

進入點與編輯模型 Entry & edit model

  • 從哪進:Portal › Site management › 某使用者的 detail page → 開啟此對話框。
  • 誰是唯讀、誰是編輯:外層 user detail page 是唯讀瀏覽該使用者目前的存取;這個對話框是唯一的編輯介面
  • 開啟時:預載該使用者目前的有效存取(pre-check 保有存取的節點,部分保有用半選)。對話框顯示的值與外層頁面一致。
  • 送出時:只送出這次 session 的 diff(變更集),不是整份重寫。
mda-has-value
主 mode(Has value)— 左 sidemenu 站點樹 + 右角色面板,開啟時預載現況(Figma key screen)

三個區塊 Regions

區塊 內容
Header 70px 標題「Manage Device Access by Site」+ 右上關閉
Body 607px 四種 mode 之一(見下);padding 8px 40px、雙欄間距 40px
Footer 70px 右下「Save changes」+「Cancel」(各 150px);drill-in mode 隱藏 footer

Body 的四種 mode Four modes

Mode 觸發 版面
主 mode 開啟預設 左 280px sidemenu + 右 716px 面板
All sites 批次 點 sidemenu 上「All sites」的 checkbox 未勾 → 勾選(半選點下去走 Reset,不進批次,見 Section 04) 左 sidemenu 不變 + 右單一 batch row(見 Section 04)
Drill-in 點右面板某列的 chevron > 整個 body 換成單欄裝置清單(見 Section 05)
Review Changes 點右面板上的「N changes」 整個 body 換成單欄 diff 清單(見 Section 07)

兩種起始狀態 Initial states

  • Empty(從未設定過):右面板顯示空狀態「No Device Access」+「Select sites from the side menu to manage device access.」。明確設為 No Access 的節點算「已設定」,不算 Empty。
  • Has value(已有設定):sidemenu 依「保有存取」pre-check(三態),每列顯示目前角色,與外層頁面一致。
mda-empty
起始 Empty — 從未設定過的使用者,右面板顯示 No Device Access(Figma key screen)

貫穿全對話框的原則 Key principles

  • checkbox = 該 site/area subtree 是否「保有任何存取」(見 Section 02),不是「我正在編輯誰」。
  • 站點層 dropdown 沒有 No Access;移除存取靠 sidemenu uncheck(見 Section 03)。No Access 只在裝置層(drill-in)才可選。
  • 破壞性編輯不用 confirm 擋(uncheck 保有存取的 site、drill-in 把直屬裝置全設 No Access、Multiple roles 壓平)——但一律記進 diff、送出前可檢視(見 Section 07)。唯一會即時跳 modal 的是「撤銷會牽動 linked 裝置」的情況(見 Section 06)。
  • 組裝了既有 pattern:sidemenu 站點樹沿用 Design Pattern: Tree View;search / filter 慣例沿用 Design Pattern: Filter Combo

驗收條件 QA · Given-When-Then

  • Given 從 user detail page 開啟,Then 對話框以編輯模式開啟並預載該使用者目前存取;外層頁面維持唯讀。
  • Given 使用者已有設定,Then 保有存取的節點 pre-check(部分保有為半選),各列角色與外層一致。
  • Given 使用者從未設定,Then 顯示 Empty 空狀態「No Device Access」。
  • Given 某節點先前被明確設為 No Access,Then 視為已設定、開啟時仍顯示(不當成 Empty 隱藏)。
Section 02

側邊站點樹

左側 280px 的 sidemenu,是選取「要管理哪些 site/area」的地方。由上到下:搜尋、All sites 列、站點樹(含 checkbox)。

本節聚焦 sidemenu 的規則;整體畫面見 Section 01 的主 mode 截圖。站點樹本身沿用 Design Pattern: Tree View

搜尋 Search

沿用 Filter Combo 的搜尋規則:

  • 輸入 2 個字以上、300ms debounce 觸發過濾。
  • 命中節點與其所有祖先顯示且可選;無關分支隱藏。
  • 命中文字 highlight(primary 底 + 白字)。
  • 無結果:顯示「No Matches Found / Adjust filters or try different keywords.」。
  • 清除搜尋 → 還原搜尋前的展開狀態。

All sites 列 All sites row

  • checkbox(未勾 / 勾選 / 半選 三態):進入 All sites 批次 mode 的唯一入口(見 Section 04)。
  • 列名稱不可點——避免與 checkbox 語意衝突(checkbox 同時管 mode 與 selection,label 不參與)。
  • 右側雙箭頭按鈕 = Collapse all(收合到 level 1);再點一次還原全展開。

站點樹 checkbox 變體 Tree with checkbox

在 Tree View 既有規格上,每個節點於 chevron 後加一個 20×20 checkbox:

  • checkbox:只動 selection,不影響展開。
  • chevron:只 toggle 展開,不動 selection。
  • 列名稱:在此對話框為 no-op(selection 已由 checkbox 表達)。
  • 預設全部展開到最深層(含 Empty 與 Has value 起始態)。

checkbox 三態的意義 Node-inclusive tri-state

checkbox 採「節點含入式」三態(與 Filter Combo 一致),語意對應「是否保有存取」:

狀態 意義
勾選 該節點直屬裝置 + 整個 subtree 所有裝置都保有存取(任一非 No Access 角色)
半選 該節點自己的直屬裝置保有存取,但 subtree 中至少一個子節點/裝置是 No Access
未勾 該節點 + 整個 subtree 全部 No Access

操作行為:

操作 結果
未勾 → 點 → 勾選 該節點 + 整 subtree 全部納入(勾選)
勾選 → 點 → 未勾 該節點 + 整 subtree 全部設為 No Access(進 diff)
子層獨立勾/取消 自動重算 ancestors(全勾→勾選、部分→ 半選 、全不勾→未勾)

diff 何時產生 When a diff is recorded

  • 未勾 → 勾選:不直接算 diff。因為還沒選具體角色——右面板該列 dropdown 顯示「Select role」placeholder;等使用者在右面板/drill-in 選了角色才算 1 筆 diff。
  • 勾選 / 半選 → 未勾:算 1 筆 diff(該節點 → No Access,subtree cascade 不獨立列)。若 subtree 內裝置連動到其他 site/area 的裝置且會一併失去存取 → 額外跳 link-confirm modal(見 Section 06)。
  • 子層 uncheck 連動 ancestor 變半選:不額外算 diff(只算子層那筆)。

驗收條件 QA · Given-When-Then

  • Given 勾選一個原本未勾的節點,Then 該節點與 subtree 加入 selection,但不改任何角色、不記 diff;右面板該列顯示「Select role」。
  • Given uncheck 一個保有存取的 site,Then 整 subtree 設為 No Access 並記進 diff(不跳 blocking confirm;若牽動 linked 裝置才跳 link-confirm)。
  • Given 子層部分勾選,Then 祖先自動呈現半選。
  • Given 搜尋輸入 2 字以上,Then 命中節點與祖先顯示、highlight,無關分支隱藏。
Section 03

右側面板(主 mode)

右側 716px 是設定角色的地方。由上到下:標題列、批次列、以及每個被選節點各一列。

標題列 Header row(40px)

  • N sites, M areas — 計數 = sidemenu 上 勾選 與半選的所有節點(level 1 = sites、level 2–5 = areas);單複數依數量、其中一邊為 0 則略去(沿用 Filter Combo 的 siteHeaderText 規則)。
  • N changes — 只在有變更(N > 0)時顯示,點下去進 Review Changes(見 Section 07)。
  • :filter chip,在 Camera(預設)與 NVR / Bridge / Speaker / PoE / VSS 之間切換。

filter chip Camera ↔ Other devices

  • 兩個固定選項;chip 上實際顯示的字是 Camera(預設)/ NVR / Bridge / Speaker / PoE / VSS
  • 後者這一組概念上稱 Other devices(= NVR / Bridge / Network Speaker / PoE Switch / VSS 共 5 種);OpenSpec 提案想把 chip 標籤改為「Other devices」,目前 prototype 仍顯示列舉字串——以實作為準。
  • 切換時,每列 dropdown 重新計算「該節點直屬該類型裝置的聚合角色」;列本身不變。
  • 標題 N sites, M areas 與 filter chip 無關(計數不依類型過濾)。
mda-camera-batch
主 mode,filter = Camera — 站點層角色 dropdown 與批次列(Figma key screen)
mda-other-batch
主 mode,filter = Other devices — 只有 Viewer / Supervisor 兩個角色(Figma key screen)

批次列 Batch row(60px)

  • 「Apply to all selected」+ 一個 200×32 dropdown。
  • 選一個角色 → 套用到目前面板顯示的所有 site/area 列直屬的該類型裝置(每列各記 1 筆 diff)。
  • 範圍有限(只限顯示中的 sites),所以不需要 confirm modal——這點與 All sites 全 org 批次不同(見 Section 04)。

每個 site/area 列 Site/Area row(60px)

元件 規格
名稱 只顯示該層名稱(不放 breadcrumb,因為 sidemenu 已給階層)
Dropdown 200×32,顯示該節點直屬該類型裝置的聚合角色
Chevron > 進入 drill-in(見 Section 05)

顯示哪些列 = sidemenu 上 勾選 或半選的所有節點,展平、按 sidemenu 順序排列(site 與 area 穿插,不分組)。

dropdown 的角色選項 Role options

filter 選項
Camera Viewer / Supervisor / Custom role 01 / 02 / 03(5 個)
Other devices Viewer / Supervisor(2 個)

站點層沒有 No Access——移除存取靠 sidemenu uncheck(見 Section 02);No Access 只在裝置層(drill-in)才可選。只有 Camera 有 Custom role。

mda-row-dropdown
站點層角色 dropdown 展開 — Viewer / Supervisor / Custom role(Camera),沒有 No Access

三種特殊顯示 Aggregate display

  • Select role(placeholder,灰字):未勾 → 勾選 後、使用者還沒選角色。
  • Multiple roles:該節點直屬該類型裝置的角色不一致(顯示用保留字,不能當自訂角色名)。選一個具體值會把該節點直屬裝置壓平成新角色,不遞迴子層 area,記 1 筆 diff。
  • (em-dash,disabled):該節點直屬沒有該類型裝置(null 聚合,別於 No Access 與 Multiple roles)——dropdown 停用、不可開;但 chevron 仍可 drill-in。
mda-n-changes
有變更時 — 標題列中間出現可點的「N changes」,進入 Review Changes(Figma key screen)

Empty 狀態 Empty

sidemenu 全 未勾 時,右面板換成空狀態:「No Device Access」+「Select sites from the side menu to manage device access.」。

驗收條件 QA · Given-When-Then

  • Given 開啟站點層 dropdown,Then 選項為 Viewer / Supervisor(+ Camera 才有 Custom role),沒有 No Access
  • Given 某節點直屬裝置角色不一致,Then 顯示 Multiple roles;選具體值只壓平該節點直屬裝置,不動子層 area。
  • Given 某節點沒有該類型裝置,Then dropdown 為 disabled,但仍可 drill-in。
  • Given 切換 filter chip,Then 每列 dropdown 依新類型重算 enabled/disabled 與聚合角色。
  • Given 用批次列選角色,Then 套用到顯示中所有列的直屬該類型裝置(各記 1 筆),不跳 confirm。
Section 04

All sites 批次

點 sidemenu「All sites」的 checkbox(未勾 → 勾選)→ 右面板換成單一批次列,一次套用一個角色到全組織該類型裝置。(從半選點下去不會進批次,而是走 Reset 路徑,見下方「為什麼半選不進入」。)

mda-all-sites
All sites 批次 mode — 右面板單一批次列,一次套用一個角色到全組織(Figma key screen)

進入與快照 Enter & snapshot

  • 進入 = 點 All sites checkbox 從未勾→ 勾選(只有未勾能進;半選點下去走 Reset,見下方「為什麼半選不進入」):sidemenu 全部變 勾選、右面板換成單一「All sites batch settings」列,且系統快照當前狀態(各裝置角色/來源、sidemenu 勾選、進入前的 mode)。此步驟不改任何角色
  • 標題改為 All sites(整 org 語意,不再顯示 N sites, M areas 計數)。
  • 單一列的 dropdown 顯示全 org 該類型裝置的聚合角色(全同→該角色、不一致→Multiple roles、沒裝置→ disabled)。

套用角色必須 confirm Apply needs confirmation

因為會覆蓋整個組織的該類型裝置,選角色時先跳 confirm modal(bounded 的主 mode 批次列則不需要):

元素 內容
標題 Apply role to all Cameras?(Camera)/ 對應 Other 類型的標題
內容 說明此舉會覆蓋全 org 該類型裝置、取代先前 per-site / per-device 設定;並提示送出前可逐筆檢視調整
主鈕 Apply to all
次鈕 Cancel
  • 確認 → 套用到全 org 該類型裝置,記 1 筆 diff(All sites → 角色);快照失效
  • 取消 → 回 All sites mode、不套用、快照保留。
  • Empty(該類型全是 No Access)或該類型無裝置 → 不跳 confirm(沒東西可覆蓋);後者不記 diff。
mda-all-sites-confirm
「Apply role to all Cameras?」— All sites 套用角色前的覆蓋全 org 確認(prototype)

退出 All sites mode Exit

點 All sites checkbox 勾選 → 未勾:

情境 行為
快照仍在(還沒套過角色) 完整還原到進入前狀態,無 diff
快照已失效(已套過角色) Reset access for all sites? confirm;確認後全 org 設 No Access、清空 selection、change log 歸零、回主 mode 的 Empty 狀態
  • 點 sidemenu 任一非 All sites 的列名稱 → 直接退出 All sites mode 回主 mode。
  • 從 All sites mode 進 Review Changes 再按 back → 回到 All sites mode(不是主 mode)。
mda-reset-modal
「Reset access for all sites?」— has-value 下取消 All sites,確認會將全 org 設為 No Access(prototype)

為什麼「半選」不進入 All sites mode Design rationale

Has-value 起始時 All sites checkbox 是 半選,點它不會進批次 mode,而是走退出路徑(快照失效 → 跳 Reset access confirm)。這是刻意的取捨:保留樹狀 checkbox 的標準三態語意(勾選/半選 → 點 → 未勾)一致,不為 All sites 開特例分支;想用批次套角色的 has-value 使用者,會先經過 Reset access modal 明確意識到「全 org 覆蓋會清掉 per-site 設定」。

驗收條件 QA · Given-When-Then

  • Given 點 All sites checkbox 未勾 → 勾選,Then 全 site 變 勾選、右面板換單一批次列、系統快照現況,且不改任何角色。
  • Given All sites 為半選時點它,Then 不進批次 mode,改跳 Reset access 確認(見下方「為什麼半選不進入」)。
  • Given 在 All sites 選角色且該類型有非 No Access 裝置,Then 跳「Apply role to all …?」confirm;確認後全 org 套用並記 1 筆「All sites → 角色」。
  • Given 進入批次 mode 後、套角色前 uncheck All sites,Then 由快照完整還原,無 diff。
  • Given has-value 下已套過角色再 uncheck All sites,Then 跳「Reset access for all sites?」;確認後全 org No Access、change log 歸零、回 Empty。
  • Given 從 All sites mode 進 Review Changes 再 back,Then 回到 All sites mode。
Section 05

Drill-in 單一裝置

點右面板某列的 chevron > → 整個 body 換成該節點的單一裝置清單,可逐台設定角色。drill-in 期間 footer(Save / Cancel)隱藏,變更累計回主 mode 統一送出。

Header(40px) Header

  • 左:back <(回主 mode 或 All sites mode,看進來時的狀態)。
  • 中:只顯示該層名稱(不套 breadcrumb)。
  • 右:240×32「Search devices」搜尋框(沿用 Filter Combo 規則,搜尋裝置名稱)。

Area header 列(60px) Area header

  • 左:該層名稱;右:200×32 dropdown,顯示該節點直屬該類型裝置的聚合角色。
  • 改 dropdown = 套用到「目前列出的所有裝置」(該節點直屬該類型,不遞迴子層)。
  • 節點無該類型裝置時 dropdown 為 disabled。

裝置列(60px) Device row

元件 顯示條件 說明
裝置 icon 永遠 依裝置類型(見下)
裝置名稱 永遠
N tag Camera 連動到同節點任一 NVR 直角小標;hover 顯示連動的 NVR 名
PREM tag Camera 且實體屬性為 premium outline pill + info icon;點 info icon 出說明(支援 Attribute search / Re-search)
B tag Speaker / PoE Switch 連動到 Bridge 直角小標;hover 顯示連動的 Bridge 名
Auto-granted tag NVR / Bridge 因連動被自動賦權(來源 = auto) 藍底 pill;hover 顯示觸發它的來源裝置(見 Section 06)
Dropdown 永遠 200×32,選項見下

裝置類型 icon(9 類 + 容錯):Camera(default / fisheye / PTZ / MA 多sensor)、NVR、Bridge、Network Speaker、PoE Switch、VSS,以及 Unknown 容錯。

dropdown 選項(裝置層才有 No Access) Options

裝置類別 選項
Camera 系 No Access / Viewer / Supervisor / Custom role 01 / 02 / 03(6 個)
Other 系 No Access / Viewer / Supervisor(3 個)

Custom role 只能套到 Camera 系。No Access 只在此裝置層出現(站點層沒有)。

mda-drill-camera
Drill-in — Camera 裝置清單,逐台角色 dropdown(含 No Access)、N / PREM tag(Figma key screen)
mda-drill-other
Drill-in — Other devices 清單,NVR 的 Auto-granted tag(Figma key screen)

空狀態 Empty states

drill-in 可進入任何節點(即使沒裝置);依情況顯示對應空狀態(共用 64×64 插圖):

情境 標題 說明
該節點任何類型都沒裝置 No Devices in This Site or Area Go back to pick another site, or add devices to this one first.
有 Other 但沒 Camera(filter = Camera) No Cameras Here Switch the device type filter to see what's on this site.
有 Camera 但沒 Other(filter = Other devices) No Devices Here Switch the device type filter to see what's on this site.
搜尋無結果 No Matches Found Adjust filters or try different keywords.

drill-in 空節點不算 diff;filter chip 在空狀態下仍可互動,可直接切到另一類型。

大量裝置的載入 Infinite scroll

裝置多(60+)的節點採分批載入:第一批 50 筆,捲到接近底部自動載下一批 50 筆;切 filter / 改搜尋 / 進不同節點都重置回第一批。載入時清單末端顯示置中的 48×48 loading(無文字)。

驗收條件 QA · Given-When-Then

  • Given 點某列 chevron >,Then 進入該節點的裝置清單,footer 隱藏。
  • Given 改一台裝置的角色,Then 只有該台變更並記 1 筆 diff。
  • Given 裝置層 dropdown,Then 有 No Access 選項(站點層沒有);Custom role 只出現在 Camera 系。
  • Given 進入沒有該類型裝置的節點,Then 顯示對應空狀態、filter chip 仍可切換,且不記 diff。
  • Given 節點裝置超過一批,Then 捲動載入下一批 50 筆,末端顯示 loading。
Section 06

連動與確認

有些裝置彼此連動:Camera ↔ NVRSpeaker / PoE Switch ↔ Bridge。改一邊的存取會牽動另一邊。原則是正向自動、反向確認;實際會遇到三種連動確認狀況

正向自動賦權(不打斷) Forward auto-grant

  • 把 Camera(或 Speaker / PoE)從 No Access 改成其他角色時,若連動的 parent(NVR / Bridge)當下是 No Access 且來源非手動 → parent 自動變 Viewer、來源標 auto、顯示 Auto-granted tag(見 Section 05)。
  • 全部連動的 child 都回 No Access → auto 的 parent 也跟著回 No Access。
  • 使用者手動改 parent → 來源變 manual,脫離 auto。
  • 正向不當下打斷;自動賦權在背景累積,送出前才統一確認(狀況三)。

狀況一:操作當下的撤銷確認 Link-confirm · device trigger

drill-in 把某裝置改成 No Access、且會連帶讓 linked 裝置失去存取時,當下立刻跳確認。

觸發 連動對象
NVR → No Access 連動的 Cameras
Bridge → No Access 連動的 Speaker / PoE Switch
Camera → No Access(且它是某 NVR 最後一個保有存取的來源) 該 NVR(來源非 manual)
Speaker / PoE → No Access(同上邏輯) 該 Bridge(來源非 manual)
  • 標題:Remove access from "<裝置名>"?;內文:Setting "<裝置>" to No Access also removes access from its linked <類型>:,逐列列出 裝置名(類型)舊角色 → No Access;hover 出完整路徑。
  • CTA:Remove access(主)/ Cancel(次)。
  • 確認 → 觸發裝置與所列 linked 裝置都設 No Access,各記 1 筆 diff;取消 → 全 revert、無 diff。
mda-link-confirm
狀況一 — 操作當下的撤銷確認「Remove access from …?」,列出連動失去存取的裝置(prototype)

狀況二:移除整個 site 的連動確認 Link-confirm · site trigger

從 sidemenu uncheck 一個 site/area,若其 subtree 連動到其他站點的裝置且會一併失去存取 → 跳同一個 link-confirm,但為 site 觸發版本。

  • 標題:Remove access from "<site 名>"?;內文:Removing access from "<site>" also removes access from these linked devices in other sites:,逐列列出跨站受影響裝置 + 路徑。
  • CTA:Remove access / Cancel。行為同狀況一(確認一併撤銷並記 diff;取消不動)。
mda-link-confirm-site
狀況二 — uncheck 一個 site 時的跨站連動確認「… removes access from these linked devices in other sites」(prototype)

狀況三:送出前的正向連動彙總 Confirm Summary at save

按「Save changes」時,若這次 session 有因正向連動而自動賦權(來源從初始變成 auto)的 NVR / Bridge,先跳彙總 modal 統一確認。

元素 內容
標題 Confirm Device Access Changes
區塊 These device(s) will update automatically based on linked devices:
每列 裝置名(NVR / Bridge)No Access → 角色Triggered by: 觸發來源裝置;hover 出路徑
CTA Confirm changes(主)/ Cancel(次)

反向撤銷已在狀況一/二當下確認過,不在此重複列出

mda-confirm-summary
狀況三 — 送出前彙總「Confirm Device Access Changes」,列出正向連動自動更新的 NVR / Bridge(prototype)

邊界:VSS Out of scope

VSS 的連動在此版不實作警示——現有情境尚未出現需要 VSS 警示的商業條件;VSS 在 drill-in 只當一般裝置顯示,不觸發 link tag 或 link-confirm。未來商業條件符合時再規劃。

驗收條件 QA · Given-When-Then

  • Given 把某 Camera 從 No Access 改為有角色、連動 NVR 當下 No Access 且非手動,Then NVR 自動變 Viewer、標 Auto-granted,不當下跳 modal
  • (狀況一)Given drill-in 把裝置改為 No Access 且牽動 linked 裝置,Then 跳「Remove access from "<裝置>"?」列出受影響裝置;確認一併 No Access 並各記 diff,取消全 revert。
  • (狀況二)Given uncheck 的 site subtree 連動到外部站點裝置,Then 跳「Remove access from ""?」列出跨站受影響裝置。
  • (狀況三)Given 正向賦權產生 auto NVR / Bridge,Then 按 Save 跳「Confirm Device Access Changes」列出這些自動更新,CTA 為 Confirm changes;反向撤銷不重列。
  • Given VSS 參與連動,Then 此版不顯示警示(一般裝置處理)。
Section 07

Review Changes

點右面板標題列的「N changes」→ 整個 body 換成本次 session 的變更清單。每一筆變更(含移除)都列出來,送出前一覽無遺。

mda-review
Review Changes — 兩段式 diff 清單(Site/Area 4 欄表 + Device 群組),Old → New,可重選(Figma key screen)

版面 Layout

  • Header(40px):back <(回進入前的 mode)+ 標題「N changes」(單數「1 change」)。
  • Footer 顯示(Save changes / Cancel)——與 drill-in 不同,Review 沿用主 mode 的 footer。

兩段排序 Two sections

清單分兩段,各段內依變更加入順序:

  1. Site / Area 等級變更——4 欄表格:Site / AreaDevice typeOld roleNew role
  2. Device 等級變更——依「裝置所屬節點」群組,每群一個 sub-header(40px)+ 該節點下的裝置列。

同節點的裝置變更會聚在同一個 sub-header 下,即使操作時在不同節點間穿插。

欄位與呈現 Columns

  • Site / Area:只顯示該節點最末層名稱;有路徑時 hover 出完整 Root > … > Self tooltip(游標變 help)。不採漸進式截斷——只顯示 leaf + tooltip。
  • Old role:舊角色(灰字 + 刪除線)+ 箭頭 icon。
  • New role:200×32 dropdown,可直接重選,立即套回對應範圍。

diff 顆粒度 Diff granularity

每筆只在「使用者真正動到的最高層級」記一次:

操作 diff
sidemenu uncheck 一個 site(勾選/ 半選 → 未勾) 2 筆(Camera 一筆、Other 一筆,讓 Device type 欄正確);整 subtree cascade 不列
右面板改一列 dropdown 1 筆(該節點 → 新角色,對應該 filter)
drill-in 改一台裝置 1 筆(裝置層)
All sites 批次改角色 1 筆(All sites)
自動賦權的 NVR / Bridge(來源 auto) 各別獨立列(送出前 Confirm Summary 也會列)

在 Review 內重選 Re-select in review

  • 每筆 New role dropdown 可直接改,立即套回原本 scope(node / device / all-sites / uncheck 各自對應)。
  • 改回最初的舊角色 → 該筆自動從清單移除(revert);Old role 永遠保留「最初值」不被覆蓋。

Back 行為 Back

進入 Review 時記住前一個 mode(主 / All sites),按 back 還原到該 mode——特別是從 All sites mode 進來,back 要回到 All sites mode,不會跳成「主 mode 但 sidemenu 全 勾選」的混合狀態。

驗收條件 QA · Given-When-Then

  • Given uncheck 一個含 Camera 與 Other 的 site,Then Review 列 2 筆(Device type 各為 Camera 與 Other),皆 舊角色 → No Access
  • Given 移除某站點存取使它從可見清單消失,Then 該變更仍出現在 Review(舊角色 → No Access)。
  • Given 在 Review 把某筆 New role 改回最初值,Then 該筆自動從清單移除、N changes 遞減。
  • Given 從 All sites mode 進 Review 再 back,Then 回到 All sites mode。
  • Given N changes = 0,Then 不顯示 N changes 入口(不會進到空的 Review)。
Section 08

送出與取消

Footer 有「Save changes」與「Cancel」。送出只送 diff;有未存變更時關閉會先確認。

Save changes Submit

條件 行為
啟用 有變更(N changes > 0)
停用 沒有變更(N changes = 0),灰色
點下去(無自動賦權) 直接送出 diff
點下去(有自動賦權的 NVR / Bridge) 先跳 Confirm Summary(見 Section 06),確認後才送
  • 成功 → 關閉對話框、外層 user detail 頁刷新為新值,並顯示成功 toast(說明變更何時生效)。
  • 失敗 → 顯示紅色 toast,對話框保持開啟、變更保留。

Cancel / 關閉 / ESC Dismiss

情境 行為
N changes = 0 直接關閉
N changes > 0 跳 Discard 確認

Discard modal:

元素 內容
標題 Discard changes?
內容 提示未存的存取變更將遺失
主鈕 Discard(捨棄並關閉)
次鈕 Keep editing(留在對話框)
mda-discard
「Discard changes?」— 有未存變更時 Cancel / 關閉 / ESC 會先確認(prototype)

驗收條件 QA · Given-When-Then

  • Given 沒有任何變更,Then Save changes 停用。
  • Given 有變更並送出成功,Then 外層頁面刷新為新值,顯示成功 toast(含生效時間)。
  • Given 送出失敗,Then 顯示失敗 toast、對話框保留、變更不遺失。
  • Given 有未存變更時按 Cancel / 關閉 / ESC,Then 跳「Discard changes?」;Discard 捨棄關閉、Keep editing 留下。
  • Given 送出時 diff 含自動賦權 NVR / Bridge,Then 先跳 Confirm Summary(見 Section 06)。
Section 09

使用場景與需求對應

用在哪 Where it's used

VORTEX 的裝置存取是逐使用者、逐裝置授予的。管理者在某使用者的 detail page 開啟這個對話框,設定該使用者能對哪些裝置持有哪些角色。它是這件事的唯一編輯介面,支援從「全 org 一次套用」到「單一裝置逐台調整」的各種顆粒度。

組裝了哪些 pattern Composition

借用 來源
站點樹(節點含入式三態、search) Design Pattern: Tree View
search / filter 慣例、cross-filter 概念 Design Pattern: Filter Combo
部分載入(樹逐層、清單分批) 平台共通原則

七項需求對應 Requirement coverage

# 原始需求 由什麼滿足
1 一次設定全 org 所有相機 All sites 批次(見 Section 04)
2 批次設定一個或多個 site/area 主 mode 批次列(見 Section 03)
3 設定單一裝置(難找也可接受) drill-in > + Search devices(見 Section 05)
4 重開顯示目前設定 外層頁瀏覽 + 對話框預載(Has value / Empty,見 Section 01)
5 辨識這次 session 會套用什麼 變更列 highlight + N changes + Review Changes(見 Section 07)
6 非相機類型沒有自訂角色 依裝置類型的角色選項(見 Section 03、05)
7 一個站點含多種存取值時顯示 Multiple roles Multiple roles 聚合(保留字,見 Section 03)

規模 Scale

  • 支援 org 級規模:最多約 1,000 sites、~300,000 裝置
  • 樹狀節點逐層 lazy-load;有效角色與 Multiple roles 由後端計算(外層頁與對話框共用同一計算);廣泛指派存成節點層規則,不展開成每台裝置的資料列。

邊界 Boundaries

面向 說明
No Access 位置 站點層 dropdown 沒有;只在裝置層(drill-in)可選,站點層靠 uncheck 移除
破壞性編輯 不用 blocking confirm 擋(除了會牽動 linked 裝置的撤銷);一律記進 diff、送出前可檢視
VSS 連動 此版不顯示警示(見 Section 06)
權限模型 formalize-rebac-permission-model;逐裝置授予,無 site 級單一權限物件

這份是 feature dialog 規格;其依賴的權限模型細節屬 formalize-rebac-permission-model,不在本 deck 重述。