feat: 'Block DocTypes' editor button — block any doctype, incl. not on /desk

Adds an edit-mode menu action + dialog to manage a global blocked_doctypes
list (Link picker + remove), persisted in the working config and validated
server-side. Lets you block doctypes that have no link on the desk.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ali 2026-06-21 09:58:43 +00:00
parent 17893b06ae
commit b41d517249
3 changed files with 93 additions and 1 deletions

View File

@ -219,7 +219,16 @@ def _validate_config(cfg: dict) -> dict:
if order: if order:
entry["order"] = order entry["order"] = order
out_ws[ws_name] = entry out_ws[ws_name] = entry
return {"version": 1, "workspaces": out_ws}
out = {"version": 1, "workspaces": out_ws}
# Global block list: doctypes blocked anywhere (incl. ones not on /desk).
blocked_doctypes = []
for dt in cfg.get("blocked_doctypes") or []:
if isinstance(dt, str) and dt and dt not in blocked_doctypes:
blocked_doctypes.append(dt)
if blocked_doctypes:
out["blocked_doctypes"] = blocked_doctypes
return out
def _write(path: str, cfg: dict): def _write(path: str, cfg: dict):

View File

@ -204,3 +204,31 @@ body.jey-edit .links-widget-box {
outline: 1px dashed var(--border-color); outline: 1px dashed var(--border-color);
outline-offset: 2px; outline-offset: 2px;
} }
/* Block DocTypes dialog */
.jey-blocked-row {
display: flex;
align-items: center;
gap: 8px;
padding: 5px 8px;
border: 1px solid var(--border-color);
border-radius: 6px;
margin-bottom: 6px;
font-size: 13px;
}
.jey-blocked-row .dt {
flex: 1;
font-weight: 500;
}
.jey-blocked-x {
border: none;
background: transparent;
cursor: pointer;
color: var(--red-500, #e24c4c);
font-size: 12px;
padding: 2px 6px;
border-radius: 5px;
}
.jey-blocked-x:hover {
background: var(--red-100, #fce4e4);
}

View File

@ -80,6 +80,7 @@
const $fab = $(` const $fab = $(`
<div id="jey-fab"> <div id="jey-fab">
<div class="jey-fab-menu"> <div class="jey-fab-menu">
<button data-act="block">🔒 ${__("Block DocTypes")}</button>
<button data-act="export">${__("Export to jey_theme")}</button> <button data-act="export">${__("Export to jey_theme")}</button>
<button data-act="reset">${__("Reset to default")}</button> <button data-act="reset">${__("Reset to default")}</button>
</div> </div>
@ -91,10 +92,64 @@
`).appendTo("body"); `).appendTo("body");
$fab.find(".jey-fab-btn").on("click", toggle_edit); $fab.find(".jey-fab-btn").on("click", toggle_edit);
$fab.find('[data-act="block"]').on("click", open_block_doctypes_dialog);
$fab.find('[data-act="export"]').on("click", do_export); $fab.find('[data-act="export"]').on("click", do_export);
$fab.find('[data-act="reset"]').on("click", do_reset); $fab.find('[data-act="reset"]').on("click", do_reset);
} }
// Global block list — block any doctype, including ones not present on /desk.
function open_block_doctypes_dialog() {
let list = (config.blocked_doctypes || []).slice();
const d = new frappe.ui.Dialog({
title: __("Block DocTypes (anywhere, incl. not on the desk)"),
fields: [
{ fieldname: "add", label: __("Add a DocType to block"), fieldtype: "Link", options: "DocType" },
{ fieldname: "list_html", fieldtype: "HTML" },
],
primary_action_label: __("Save"),
primary_action: async () => {
if (list.length) config.blocked_doctypes = list;
else delete config.blocked_doctypes;
await save_now();
d.hide();
frappe.show_alert(
{ message: __("Saved — “✓ Done editing” to apply the block"), indicator: "green" },
5
);
},
});
const render = () => {
const $w = d.fields_dict.list_html.$wrapper;
$w.empty();
if (!list.length) {
$w.html(`<div class="text-muted" style="padding:6px 0">${__("No blocked doctypes yet.")}</div>`);
return;
}
list.forEach((dt, i) => {
const $row = $(
`<div class="jey-blocked-row">🔒 <span class="dt"></span>` +
`<button type="button" class="jey-blocked-x" title="${__("Remove")}">✕</button></div>`
);
$row.find(".dt").text(dt);
$row.find(".jey-blocked-x").on("click", () => {
list.splice(i, 1);
render();
});
$w.append($row);
});
};
d.fields_dict.add.df.onchange = () => {
const v = d.get_value("add");
if (v) {
if (!list.includes(v)) list.push(v);
d.set_value("add", "");
render();
}
};
render();
d.show();
}
function update_fab() { function update_fab() {
const $fab = $("#jey-fab"); const $fab = $("#jey-fab");
$fab.toggleClass("on", editing); $fab.toggleClass("on", editing);