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:
parent
8fcd2a5999
commit
4d628576c7
48
CLAUDE.md
48
CLAUDE.md
|
|
@ -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.
|
||||
|
||||
- `bench build --app jey_theme` — rebuild JS bundle after editing `jey_theme/public/js/jey_theme.js`.
|
||||
- CSS-only changes: no build needed, just hard-reload the browser.
|
||||
- `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.
|
||||
- `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 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
|
||||
|
||||
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`.
|
||||
- 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.
|
||||
- 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
|
||||
|
||||
|
|
@ -153,11 +184,10 @@ Keep this IIFE minimal and synchronous — anything slow here delays first paint
|
|||
|
||||
## 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).
|
||||
3. Add an entry to `JEY_THEMES` array in the switcher section of `jey_theme.js`.
|
||||
4. Add the CSS file to both `app_include_css` and `web_include_css` in `hooks.py`.
|
||||
5. `bench build --app jey_theme`.
|
||||
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. `bench build --app jey_theme`.
|
||||
|
||||
## Rules
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
"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 |
Loading…
Reference in New Issue