feat(desk): expand layout config with block/hide rules + silk bg asset

- desk_layout.json: add blocked_doctypes and per-workspace hide/block
  rules across Assets, Buying, Invoicing, Manufacturing, Payroll,
  Recruitment, Selling, Stock (+ Landed Cost Voucher inject/order)
- add silk-bg.jpg (referenced by jey_theme.bundle.css)
- CLAUDE.md: doc updates

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali 2026-07-20 14:17:52 +00:00
parent 8fcd2a5999
commit 4d628576c7
3 changed files with 360 additions and 10 deletions

View File

@ -15,8 +15,7 @@ Installed into `frappe-bench` as a normal app. Python code is at `jey_theme/` (F
Run from `frappe-bench/` (the bench root), not this app dir. Run from `frappe-bench/` (the bench root), not this app dir.
- `bench build --app jey_theme` — rebuild JS bundle after editing `jey_theme/public/js/jey_theme.js`. - `bench build --app jey_theme` — required after **CSS** edits (`jey_theme.bundle.css` → hashed file in `public/dist/css/`). JS is served raw and needs only a hard reload.
- CSS-only changes: no build needed, just hard-reload the browser.
- `bench migrate` — runs the `after_migrate` hook that rebuilds the Taxes Az workspace from `setup/taxes_workspace.py`. - `bench migrate` — runs the `after_migrate` hook that rebuilds the Taxes Az workspace from `setup/taxes_workspace.py`.
- `bench execute jey_theme.setup.taxes_workspace.setup` — re-run the workspace setup without a full migrate. - `bench execute jey_theme.setup.taxes_workspace.setup` — re-run the workspace setup without a full migrate.
- `bench restart` — reload Python workers after editing `access_control.py` or `hooks.py`. - `bench restart` — reload Python workers after editing `access_control.py` or `hooks.py`.
@ -128,12 +127,44 @@ Idempotent setup run via `after_migrate`.
### Frontend: multi-theme system ### Frontend: multi-theme system
Bundle entry: `jey_theme/public/js/jey_theme.js`. CSS: `jey_theme/public/css/{shared,theme_chrome,theme_modern}.css`. All four are loaded via `app_include_css` / `app_include_js` in `hooks.py` for both desk and web contexts. JS entry: `jey_theme/public/js/jey_theme.js` (served raw via `app_include_js`, not bundled).
CSS: **one file**, `jey_theme/public/css/jey_theme.bundle.css` — the former
`shared.css` / `theme_chrome.css` / `theme_modern.css` were concatenated into it
(in that order, still marked by `/* ===== <name>.css ===== */` banners) so the
desk's preload header stays under the edge proxy's 4 KB buffer. Edit the bundle
directly; there are no separate source files to regenerate it from.
- **CSS changes need `bench build --app jey_theme`.** `app_include_css` names the
bundle, and esbuild emits the hashed `public/dist/css/jey_theme.bundle.<HASH>.css`
that `sites/assets/assets.json` actually points the browser at. Editing the bundle
alone changes nothing in the browser.
- JS changes need only a hard reload — but `/assets/jey_theme/js/jey_theme.js` is a
hashless path under a 1-year nginx cache, so it really does have to be a *hard*
reload (or a cache-disabled session).
- Theme selector lives in `data-jey-theme` on `<html>`, stored in `localStorage("jey-theme")`. Default: `chrome`. Set before first paint by an IIFE at the top of `jey_theme.js`. - Theme selector lives in `data-jey-theme` on `<html>`, stored in `localStorage("jey-theme")`. Default: `chrome`. Set before first paint by an IIFE at the top of `jey_theme.js`.
- Themes supported: **chrome** (metallic rings), **silk** (warm ivory & champagne-gold, frosted cards). No dark/light variants — each theme is self-contained. - Themes supported: **chrome** (metallic rings), **silk** (warm ivory & champagne-gold
glass-neumorphism, ported from `public/silk_dashboard_crisp.html` — that mockup is
silk's design reference; keep the two in sync).
No dark/light variants — each theme is self-contained.
- Theme-specific CSS MUST be wrapped in `[data-jey-theme="themename"]`. Keyframes MUST be prefixed `jey-<theme>-*` to avoid cross-theme name collisions. - Theme-specific CSS MUST be wrapped in `[data-jey-theme="themename"]`. Keyframes MUST be prefixed `jey-<theme>-*` to avoid cross-theme name collisions.
- Shared CSS (checkboxes, icon base sizing, switcher UI, column-resize rules) lives in `shared.css` without theme selectors. - Shared CSS (checkboxes, icon base sizing, switcher UI, column-resize rules, the
card icon-tile defaults) lives in the `shared.css` section without theme selectors.
**Frosted glass (silk, and any future glass theme) — two rules that cost real
debugging time:**
- **One `backdrop-filter` per stack.** A frosted element inside another frosted
element paints as an opaque white block on real GPUs; headless Chrome
(SwiftShader) renders it correctly, so it passes every test render. Only the
outermost surface gets the filter — currently `.widget`, `.form-page`,
`.frappe-list .result-container`, `.navbar-search-bar`, `.dropdown-navbar-user`,
`.desktop-navbar-modal-search`, `.jey-chrome`. Everything nested (icon tiles,
chips, count pills, buttons) gets a translucent fill and no filter. There's a
backstop rule near the Modals section, but don't rely on it — check with the
live-DOM audit (walk every element, flag any whose ancestor also has a
non-`none` computed `backdropFilter`).
- **On silk it's the translucency, not the blur, that reads as glass.** The fabric
is near-uniform, so a strong blur averages it into a flat opaque panel. Light
blur (6px) over a very translucent warm fill is what lets it show through.
### Frontend: per-theme icons ### Frontend: per-theme icons
@ -153,11 +184,10 @@ Keep this IIFE minimal and synchronous — anything slow here delays first paint
## Adding a new theme ## Adding a new theme
1. Create `jey_theme/public/css/theme_mytheme.css` with `[data-jey-theme="mytheme"]` selectors. Prefix keyframes `jey-mytheme-*`. 1. Append a `/* ===== theme_mytheme.css ===== */` section to `jey_theme/public/css/jey_theme.bundle.css`, with every rule wrapped in `[data-jey-theme="mytheme"]`. Prefix keyframes `jey-mytheme-*`. Do NOT add a new file/`app_include_css` entry — extra preload-header lines are what the single bundle exists to avoid.
2. Add `THEME_ICONS.mytheme = { ... }` in `jey_theme.js` (only override keys you care about). 2. Add `THEME_ICONS.mytheme = { ... }` in `jey_theme.js` (only override keys you care about).
3. Add an entry to `JEY_THEMES` array in the switcher section of `jey_theme.js`. 3. Add an entry to the `JEY_THEMES` array in the switcher section of `jey_theme.js`, and a `.jey-theme-preview--mytheme` swatch in the bundle's shared section.
4. Add the CSS file to both `app_include_css` and `web_include_css` in `hooks.py`. 4. `bench build --app jey_theme`.
5. `bench build --app jey_theme`.
## Rules ## Rules

View File

@ -1,4 +1,324 @@
{ {
"blocked_doctypes": [
"Server Script",
"Client Script",
"Website Script",
"Subcontracting Inward Order Secondary Item",
"Subcontracting Inward Order Service Item",
"Subcontracting Inward Order Received Item",
"Subcontracting Inward Order Item",
"Subcontracting Inward Order",
"Subcontracting BOM",
"Subcontracting Receipt",
"Subcontracting Receipt Supplied Item",
"Subcontracting Receipt Item",
"Subcontracting Order",
"Subcontracting Order Supplied Item",
"Subcontracting Order Item",
"Subcontracting Order Service Item",
"Job Opening"
],
"version": 1, "version": 1,
"workspaces": {} "workspaces": {
"Assets": {
"cards": {
"Maintenance": {
"state": "hidden"
}
},
"links": {
"DocType::Asset Capitalization": {
"state": "blocked"
},
"DocType::Asset Maintenance": {
"state": "blocked"
},
"DocType::Asset Maintenance Log": {
"state": "blocked"
},
"DocType::Asset Maintenance Team": {
"state": "blocked"
},
"DocType::Asset Repair": {
"state": "blocked"
},
"DocType::Asset Value Adjustment": {
"state": "blocked"
}
},
"state": "visible"
},
"Buying": {
"cards": {
"Supplier Scorecard": {
"state": "hidden"
}
},
"links": {
"DocType::Promotional Scheme": {
"state": "blocked"
},
"DocType::Request for Quotation": {
"state": "blocked"
},
"DocType::Supplier Quotation": {
"state": "blocked"
},
"DocType::Supplier Scorecard": {
"state": "blocked"
},
"DocType::Supplier Scorecard Criteria": {
"state": "blocked"
},
"DocType::Supplier Scorecard Standing": {
"state": "blocked"
},
"DocType::Supplier Scorecard Variable": {
"state": "blocked"
},
"Report::Subcontracted Item To Be Received": {
"state": "blocked"
},
"Report::Subcontracted Raw Materials To Be Transferred": {
"state": "blocked"
},
"Report::Supplier Quotation Comparison": {
"state": "blocked"
}
},
"state": "visible"
},
"Expenses": {
"cards": {
"Fleet Management": {
"state": "hidden"
},
"Travel": {
"state": "hidden"
}
},
"state": "visible"
},
"Invoicing": {
"cards": {
"Share Management": {
"state": "hidden"
}
},
"links": {
"DocType::Share Transfer": {
"state": "blocked"
},
"DocType::Shareholder": {
"state": "blocked"
},
"DocType::Tax Rule": {
"state": "blocked"
},
"DocType::Tax Withholding Category": {
"state": "blocked"
},
"Report::Share Balance": {
"state": "blocked"
},
"Report::Share Ledger": {
"state": "blocked"
}
},
"state": "visible"
},
"Manufacturing": {
"cards": {
"Subcontracting": {
"state": "hidden"
}
},
"links": {
"DocType::Downtime Entry": {
"state": "blocked"
},
"DocType::Item Lead Time": {
"state": "blocked"
},
"DocType::Production Plan": {
"state": "blocked"
},
"DocType::Sales Forecast": {
"state": "blocked"
},
"DocType::Subcontracting BOM": {
"state": "blocked"
},
"DocType::Subcontracting Order": {
"state": "blocked"
},
"DocType::Subcontracting Receipt": {
"state": "blocked"
},
"Report::Downtime Analysis": {
"state": "blocked"
},
"Report::Production Planning Report": {
"state": "blocked"
},
"Report::Quality Inspection Summary": {
"state": "blocked"
},
"Report::Subcontract Order Summary": {
"state": "blocked"
},
"Report::Subcontracted Item To Be Received": {
"state": "blocked"
},
"Report::Subcontracted Raw Materials To Be Transferred": {
"state": "blocked"
}
},
"state": "visible"
},
"Payroll": {
"links": {
"DocType::Income Tax Slab": {
"state": "blocked"
},
"Report::Income Tax Computation": {
"state": "blocked"
},
"Report::Salary Payments via ECS": {
"state": "blocked"
}
},
"state": "visible"
},
"Recruitment": {
"cards": {
"Appointment": {
"state": "hidden"
},
"Interviews": {
"state": "hidden"
},
"Reports": {
"state": "hidden"
}
},
"links": {
"DocType::Appointment Letter": {
"state": "blocked"
},
"DocType::Appointment Letter Template": {
"state": "blocked"
},
"DocType::Employee Referral": {
"state": "blocked"
},
"DocType::Interview": {
"state": "blocked"
},
"DocType::Interview Feedback": {
"state": "blocked"
},
"DocType::Interview Type": {
"state": "blocked"
},
"DocType::Job Requisition": {
"state": "blocked"
},
"DocType::Staffing Plan": {
"state": "blocked"
},
"Report::Recruitment Analytics": {
"state": "blocked"
}
},
"state": "visible"
},
"Selling": {
"links": {
"DocType::Coupon Code": {
"state": "blocked"
}
},
"state": "visible"
},
"Stock": {
"added": {
"DocType::Landed Cost Voucher": {
"card": "Stock Transactions",
"label": "Landed Cost Voucher",
"link_to": "Landed Cost Voucher",
"link_type": "DocType"
}
},
"cards": {
"Serial No and Batch": {
"state": "hidden"
},
"Tools": {
"state": "hidden"
}
},
"links": {
"DocType::Batch": {
"state": "blocked"
},
"DocType::Installation Note": {
"state": "blocked"
},
"DocType::Material Request": {
"state": "blocked"
},
"DocType::Packing Slip": {
"state": "blocked"
},
"DocType::Quality Inspection": {
"state": "blocked"
},
"DocType::Quality Inspection Template": {
"state": "blocked"
},
"DocType::Quick Stock Balance": {
"state": "blocked"
},
"DocType::Serial No": {
"state": "blocked"
},
"DocType::Stock Reconciliation": {
"state": "blocked"
},
"Report::Serial No Ledger": {
"state": "blocked"
},
"Report::Serial No Service Contract Expiry": {
"state": "blocked"
},
"Report::Serial No Status": {
"state": "blocked"
},
"Report::Serial No Warranty Expiry": {
"state": "blocked"
},
"Report::Serial No and Batch Traceability": {
"state": "blocked"
},
"Report::Subcontracted Item To Be Received": {
"state": "blocked"
},
"Report::Subcontracted Raw Materials To Be Transferred": {
"state": "blocked"
}
},
"order": {
"Tools": [
"DocType::Landed Cost Voucher",
"DocType::Stock Reconciliation",
"DocType::Packing Slip",
"DocType::Quality Inspection",
"DocType::Quality Inspection Template",
"DocType::Quick Stock Balance"
]
},
"state": "visible"
}
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB