Custom pages: флажок «скрыть шапку страницы» (миграция 0089)
- custom_pages.hide_header: платформа не рендерит заголовок (название + описание) над виджетом — для полноэкранных отчётов/дашбордов, без CSS-хаков из кода страницы - UI: переключатель «Скрыть шапку страницы» в диалоге создания/редактирования - REST create/patch принимают hideHeader; MCP create_custom_page/update_custom_page — параметр hide_header (виден ИИ сразу, default false)
This commit is contained in:
@@ -173,6 +173,16 @@ export function JsPagesSection({
|
||||
onCheckedChange={(v) => setPageForm(f => ({ ...f, showInSidebar: v }))}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between rounded-md border px-3 py-2">
|
||||
<div>
|
||||
<p className="text-sm font-medium">Скрыть шапку страницы</p>
|
||||
<p className="text-xs text-muted-foreground">Не показывать платформенный заголовок с названием и описанием (для полноэкранных отчётов и дашбордов)</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={pageForm.hideHeader}
|
||||
onCheckedChange={(v) => setPageForm(f => ({ ...f, hideHeader: v }))}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium">Формы (источники данных)</label>
|
||||
<p className="text-xs text-muted-foreground mb-1">Задачи из выбранных форм будут доступны через ctx.forms[formId]</p>
|
||||
|
||||
@@ -80,7 +80,7 @@ export function useBotsController() {
|
||||
// JS Pages state
|
||||
const [pageDialogOpen, setPageDialogOpen] = useState(false);
|
||||
const [editingPage, setEditingPage] = useState<any>(null);
|
||||
const [pageForm, setPageForm] = useState({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [] as number[], icon: 'FileCode', showInSidebar: false });
|
||||
const [pageForm, setPageForm] = useState({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [] as number[], icon: 'FileCode', showInSidebar: false, hideHeader: false });
|
||||
const [pageShowTemplates, setPageShowTemplates] = useState(false);
|
||||
const [pagePreviewOpen, setPagePreviewOpen] = useState(false);
|
||||
const [pagePreviewDialogOpen, setPagePreviewDialogOpen] = useState(false);
|
||||
@@ -160,7 +160,7 @@ export function useBotsController() {
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/custom-pages'] });
|
||||
setPageDialogOpen(false);
|
||||
setEditingPage(null);
|
||||
setPageForm({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [], icon: 'FileCode', showInSidebar: false });
|
||||
setPageForm({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [], icon: 'FileCode', showInSidebar: false, hideHeader: false });
|
||||
toast({ title: 'Страница создана', description: pageForm.showInSidebar ? 'Ссылка появится в боковой панели' : 'Страница скрыта из бокового меню' });
|
||||
},
|
||||
onError: (e: any) => toast({ title: 'Ошибка', description: e?.message ?? 'Ошибка создания', variant: 'destructive' }),
|
||||
@@ -188,14 +188,14 @@ export function useBotsController() {
|
||||
|
||||
const openCreatePage = () => {
|
||||
setEditingPage(null);
|
||||
setPageForm({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [], icon: 'FileCode', showInSidebar: false });
|
||||
setPageForm({ name: '', slug: '', description: '', code: JS_PAGE_DEFAULT_CODE, formIds: [], icon: 'FileCode', showInSidebar: false, hideHeader: false });
|
||||
setSlugCheckResult('idle');
|
||||
setPageDialogOpen(true);
|
||||
};
|
||||
|
||||
const openEditPage = (page: any) => {
|
||||
setEditingPage(page);
|
||||
setPageForm({ name: page.name, slug: page.slug, description: page.description ?? '', code: page.code ?? JS_PAGE_DEFAULT_CODE, formIds: page.formIds ?? [], icon: page.icon ?? 'FileCode', showInSidebar: page.showInSidebar ?? false });
|
||||
setPageForm({ name: page.name, slug: page.slug, description: page.description ?? '', code: page.code ?? JS_PAGE_DEFAULT_CODE, formIds: page.formIds ?? [], icon: page.icon ?? 'FileCode', showInSidebar: page.showInSidebar ?? false, hideHeader: page.hideHeader ?? false });
|
||||
setSlugCheckResult('idle');
|
||||
setPageDialogOpen(true);
|
||||
};
|
||||
|
||||
@@ -113,13 +113,15 @@ export default function CustomPageView() {
|
||||
return (
|
||||
<Layout>
|
||||
<div className="flex flex-col h-full overflow-hidden">
|
||||
<div className="border-b px-4 py-2 flex items-center gap-2 shrink-0 bg-background">
|
||||
<FileCode className="w-4 h-4 text-muted-foreground" />
|
||||
<h1 className="text-sm font-medium">{page.name}</h1>
|
||||
{page.description && (
|
||||
<span className="text-xs text-muted-foreground ml-2">{page.description}</span>
|
||||
)}
|
||||
</div>
|
||||
{!page.hideHeader && (
|
||||
<div className="border-b px-4 py-2 flex items-center gap-2 shrink-0 bg-background">
|
||||
<FileCode className="w-4 h-4 text-muted-foreground" />
|
||||
<h1 className="text-sm font-medium">{page.name}</h1>
|
||||
{page.description && (
|
||||
<span className="text-xs text-muted-foreground ml-2">{page.description}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 overflow-auto p-4">
|
||||
<JsComponentRenderer
|
||||
code={page.code}
|
||||
|
||||
Reference in New Issue
Block a user