Unify page workspace error panels
This commit is contained in:
parent
7be6104b6b
commit
942373563d
|
|
@ -1039,6 +1039,10 @@ function getWorkspaceKey(projectId: string, scopeId: string) {
|
||||||
return `${projectId}:${scopeId}`;
|
return `${projectId}:${scopeId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWorkspaceUiKeyFromWorkspaceKey(workspaceKey: string) {
|
||||||
|
return workspaceKey.split(":")[0] ?? workspaceKey;
|
||||||
|
}
|
||||||
|
|
||||||
type WorkspaceSection = PageWorkspace["sections"][number];
|
type WorkspaceSection = PageWorkspace["sections"][number];
|
||||||
type WorkspaceSectionTextMap = Record<string, string>;
|
type WorkspaceSectionTextMap = Record<string, string>;
|
||||||
|
|
||||||
|
|
@ -1059,7 +1063,9 @@ type WorkspaceTarget = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type WorkspacePreviewMode = "desktop" | "mobile";
|
type WorkspacePreviewMode = "desktop" | "mobile";
|
||||||
type WorkspaceDrawerPanel = "fields" | "issues";
|
type WorkspaceDrawerPanel = "pages" | "issues";
|
||||||
|
|
||||||
|
const WORKSPACE_DRAWER_ORDER: WorkspaceDrawerPanel[] = ["pages", "issues"];
|
||||||
|
|
||||||
const WORKSPACE_PREVIEW_MODES: Array<{ id: WorkspacePreviewMode; label: string }> = [
|
const WORKSPACE_PREVIEW_MODES: Array<{ id: WorkspacePreviewMode; label: string }> = [
|
||||||
{ id: "desktop", label: "Desktop" },
|
{ id: "desktop", label: "Desktop" },
|
||||||
|
|
@ -1500,7 +1506,6 @@ export function App() {
|
||||||
const [activeWorkspaceTargetIds, setActiveWorkspaceTargetIds] = useState<Record<string, string>>({});
|
const [activeWorkspaceTargetIds, setActiveWorkspaceTargetIds] = useState<Record<string, string>>({});
|
||||||
const [workspacePreviewMarkers, setWorkspacePreviewMarkers] = useState<Record<string, PreviewMarker[]>>({});
|
const [workspacePreviewMarkers, setWorkspacePreviewMarkers] = useState<Record<string, PreviewMarker[]>>({});
|
||||||
const [workspaceDrawers, setWorkspaceDrawers] = useState<Record<string, WorkspaceDrawerPanel[]>>({});
|
const [workspaceDrawers, setWorkspaceDrawers] = useState<Record<string, WorkspaceDrawerPanel[]>>({});
|
||||||
const [workspacePageMenus, setWorkspacePageMenus] = useState<Record<string, boolean>>({});
|
|
||||||
const [workspacePreviewScopeIds, setWorkspacePreviewScopeIds] = useState<Record<string, string>>({});
|
const [workspacePreviewScopeIds, setWorkspacePreviewScopeIds] = useState<Record<string, string>>({});
|
||||||
const [pageWorkspaces, setPageWorkspaces] = useState<Record<string, PageWorkspace>>({});
|
const [pageWorkspaces, setPageWorkspaces] = useState<Record<string, PageWorkspace>>({});
|
||||||
const [workspaceDraftTexts, setWorkspaceDraftTexts] = useState<Record<string, string>>({});
|
const [workspaceDraftTexts, setWorkspaceDraftTexts] = useState<Record<string, string>>({});
|
||||||
|
|
@ -1760,11 +1765,6 @@ export function App() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === "seo-mode:preview-pointerdown") {
|
|
||||||
closeWorkspacePageMenus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.type !== "seo-mode:preview-markers") {
|
if (data.type !== "seo-mode:preview-markers") {
|
||||||
if (data?.type === "seo-mode:active-scope-page") {
|
if (data?.type === "seo-mode:active-scope-page") {
|
||||||
const sourceWorkspaceKey = typeof data.workspaceKey === "string" ? data.workspaceKey : "";
|
const sourceWorkspaceKey = typeof data.workspaceKey === "string" ? data.workspaceKey : "";
|
||||||
|
|
@ -1832,7 +1832,7 @@ export function App() {
|
||||||
...currentSectionIds,
|
...currentSectionIds,
|
||||||
[workspaceKey]: sectionId || targetId
|
[workspaceKey]: sectionId || targetId
|
||||||
}));
|
}));
|
||||||
openWorkspaceDrawer(workspaceKey, "fields");
|
openWorkspaceDrawer(getWorkspaceUiKeyFromWorkspaceKey(workspaceKey), "issues");
|
||||||
|
|
||||||
scrollWorkspaceFieldIntoView(workspaceKey, targetId);
|
scrollWorkspaceFieldIntoView(workspaceKey, targetId);
|
||||||
return;
|
return;
|
||||||
|
|
@ -2550,7 +2550,7 @@ export function App() {
|
||||||
...currentSectionIds,
|
...currentSectionIds,
|
||||||
[workspaceKey]: target.sectionId
|
[workspaceKey]: target.sectionId
|
||||||
}));
|
}));
|
||||||
openWorkspaceDrawer(workspaceKey, "fields");
|
openWorkspaceDrawer(getWorkspaceUiKeyFromWorkspaceKey(workspaceKey), "issues");
|
||||||
|
|
||||||
scrollWorkspaceFieldIntoView(workspaceKey, target.id);
|
scrollWorkspaceFieldIntoView(workspaceKey, target.id);
|
||||||
}
|
}
|
||||||
|
|
@ -2599,49 +2599,6 @@ export function App() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleWorkspacePageMenu(workspaceKey: string) {
|
|
||||||
setWorkspacePageMenus((currentMenus) => ({
|
|
||||||
...currentMenus,
|
|
||||||
[workspaceKey]: !currentMenus[workspaceKey]
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeWorkspacePageMenus() {
|
|
||||||
setWorkspacePageMenus((currentMenus) => {
|
|
||||||
let hasOpenMenu = false;
|
|
||||||
const nextMenus = { ...currentMenus };
|
|
||||||
|
|
||||||
Object.keys(nextMenus).forEach((workspaceKey) => {
|
|
||||||
if (nextMenus[workspaceKey]) {
|
|
||||||
nextMenus[workspaceKey] = false;
|
|
||||||
hasOpenMenu = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return hasOpenMenu ? nextMenus : currentMenus;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!Object.values(workspacePageMenus).some(Boolean)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDocumentPointerDown(event: PointerEvent) {
|
|
||||||
if (event.target instanceof Element && event.target.closest(".workspace-page-control")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
closeWorkspacePageMenus();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("pointerdown", handleDocumentPointerDown, true);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("pointerdown", handleDocumentPointerDown, true);
|
|
||||||
};
|
|
||||||
}, [workspacePageMenus]);
|
|
||||||
|
|
||||||
function updateWorkspacePreviewMarkers(
|
function updateWorkspacePreviewMarkers(
|
||||||
workspaceKey: string,
|
workspaceKey: string,
|
||||||
targets: WorkspaceTarget[],
|
targets: WorkspaceTarget[],
|
||||||
|
|
@ -2803,11 +2760,10 @@ export function App() {
|
||||||
);
|
);
|
||||||
setWorkspaceDrawers((currentDrawers) =>
|
setWorkspaceDrawers((currentDrawers) =>
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(currentDrawers).filter(([workspaceKey]) => !workspaceKey.startsWith(`${project.id}:`))
|
Object.entries(currentDrawers).filter(
|
||||||
|
([workspaceKey]) => workspaceKey !== project.id && !workspaceKey.startsWith(`${project.id}:`)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
|
||||||
setWorkspacePageMenus((currentMenus) =>
|
|
||||||
Object.fromEntries(Object.entries(currentMenus).filter(([workspaceKey]) => !workspaceKey.startsWith(`${project.id}:`)))
|
|
||||||
);
|
);
|
||||||
setActiveWorkspaceSectionIds((currentSectionIds) =>
|
setActiveWorkspaceSectionIds((currentSectionIds) =>
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
|
|
@ -3522,12 +3478,10 @@ export function App() {
|
||||||
null;
|
null;
|
||||||
const activeWorkspaceMarkers = activeWorkspaceKey ? (workspacePreviewMarkers[activeWorkspaceKey] ?? []) : [];
|
const activeWorkspaceMarkers = activeWorkspaceKey ? (workspacePreviewMarkers[activeWorkspaceKey] ?? []) : [];
|
||||||
const activeWorkspacePreviewMode = activeWorkspaceKey ? (workspacePreviewModes[activeWorkspaceKey] ?? "desktop") : "desktop";
|
const activeWorkspacePreviewMode = activeWorkspaceKey ? (workspacePreviewModes[activeWorkspaceKey] ?? "desktop") : "desktop";
|
||||||
const activeWorkspaceDrawers = activeWorkspaceKey
|
const activeWorkspaceUiKey = project.id;
|
||||||
? (workspaceDrawers[activeWorkspaceKey] ?? []).filter(
|
const activeWorkspaceDrawers = WORKSPACE_DRAWER_ORDER.filter((drawer) =>
|
||||||
(drawer): drawer is WorkspaceDrawerPanel => drawer === "fields" || drawer === "issues"
|
(workspaceDrawers[activeWorkspaceUiKey] ?? []).includes(drawer)
|
||||||
)
|
);
|
||||||
: [];
|
|
||||||
const isWorkspacePageMenuOpen = activeWorkspaceKey ? Boolean(workspacePageMenus[activeWorkspaceKey]) : false;
|
|
||||||
const previewWorkspaceScopeId = workspacePreviewScopeIds[project.id] ?? activeWorkspaceScopeItem?.scopeId ?? null;
|
const previewWorkspaceScopeId = workspacePreviewScopeIds[project.id] ?? activeWorkspaceScopeItem?.scopeId ?? null;
|
||||||
const previewWorkspaceScopeItem =
|
const previewWorkspaceScopeItem =
|
||||||
selectedWorkspaceScopeItems.find((item) => item.scopeId === previewWorkspaceScopeId) ??
|
selectedWorkspaceScopeItems.find((item) => item.scopeId === previewWorkspaceScopeId) ??
|
||||||
|
|
@ -4793,12 +4747,9 @@ export function App() {
|
||||||
<span>Warning: {activeWorkspaceIssueCounts.warnings} · Info: {activeWorkspaceIssueCounts.info}</span>
|
<span>Warning: {activeWorkspaceIssueCounts.warnings} · Info: {activeWorkspaceIssueCounts.info}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="workspace-current-page-actions">
|
<div className="workspace-current-page-actions">
|
||||||
<div className={`workspace-page-control ${isWorkspacePageMenuOpen ? "open" : ""}`}>
|
|
||||||
<button
|
<button
|
||||||
aria-expanded={isWorkspacePageMenuOpen}
|
className={activeWorkspaceDrawers.includes("pages") ? "active" : undefined}
|
||||||
aria-haspopup="menu"
|
onClick={() => toggleWorkspaceDrawer(activeWorkspaceUiKey, "pages")}
|
||||||
className="workspace-page-control-trigger"
|
|
||||||
onClick={() => toggleWorkspacePageMenu(activeWorkspaceKey)}
|
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<FileText size={14} />
|
<FileText size={14} />
|
||||||
|
|
@ -4808,68 +4759,13 @@ export function App() {
|
||||||
</em>
|
</em>
|
||||||
<ChevronDown size={14} />
|
<ChevronDown size={14} />
|
||||||
</button>
|
</button>
|
||||||
{isWorkspacePageMenuOpen ? (
|
|
||||||
<div className="workspace-page-menu" role="menu">
|
|
||||||
<div className="workspace-page-menu-head">
|
|
||||||
<strong>Страницы и секции</strong>
|
|
||||||
<small>Переключает preview, ошибки и поля рабочей зоны.</small>
|
|
||||||
</div>
|
|
||||||
{selectedWorkspaceScopeItems.length > 0 ? (
|
|
||||||
<div className="workspace-page-menu-list">
|
|
||||||
{selectedWorkspaceScopeItems.map((scopeItem, pageIndex) => {
|
|
||||||
const pageWorkspaceKey = getWorkspaceKey(project.id, scopeItem.scopeId);
|
|
||||||
const isActivePage = activeWorkspaceScopeItem?.scopeId === scopeItem.scopeId;
|
|
||||||
const isOpening = busyWorkspaceKey === pageWorkspaceKey;
|
|
||||||
const pageIssues = getPageIssues(scanSummary, scopeItem.pageId);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={isActivePage ? "active" : undefined}
|
|
||||||
disabled={isOpening}
|
|
||||||
key={`workspace-page-menu-${scopeItem.scopeId}`}
|
|
||||||
onClick={() => {
|
|
||||||
setWorkspacePageMenus((currentMenus) => ({
|
|
||||||
...currentMenus,
|
|
||||||
[activeWorkspaceKey]: false,
|
|
||||||
[pageWorkspaceKey]: true
|
|
||||||
}));
|
|
||||||
void handleOpenPageWorkspace(project, scopeItem, { silent: true });
|
|
||||||
}}
|
|
||||||
role="menuitem"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>{pageIndex + 1}</span>
|
|
||||||
<strong>{scopeItem.title}</strong>
|
|
||||||
<small>{scopeItem.pathLabel}</small>
|
|
||||||
<em>{pageIssues.length} замечаний</em>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<small className="workspace-page-menu-empty">
|
|
||||||
В выбранном наборе пока нет рабочих страниц или секций.
|
|
||||||
</small>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
className={activeWorkspaceDrawers.includes("issues") ? "active" : undefined}
|
className={activeWorkspaceDrawers.includes("issues") ? "active" : undefined}
|
||||||
onClick={() => toggleWorkspaceDrawer(activeWorkspaceKey, "issues")}
|
onClick={() => toggleWorkspaceDrawer(activeWorkspaceUiKey, "issues")}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<CircleAlert size={14} />
|
<CircleAlert size={14} />
|
||||||
Ошибки
|
Ошибки
|
||||||
<em>{activeWorkspaceIssues.length}</em>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={activeWorkspaceDrawers.includes("fields") ? "active" : undefined}
|
|
||||||
onClick={() => toggleWorkspaceDrawer(activeWorkspaceKey, "fields")}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<FileText size={14} />
|
|
||||||
Поля
|
|
||||||
<em>{activeWorkspaceTargets.length}</em>
|
<em>{activeWorkspaceTargets.length}</em>
|
||||||
</button>
|
</button>
|
||||||
<div className="workspace-preview-mode-switch" aria-label="Режим зеркала">
|
<div className="workspace-preview-mode-switch" aria-label="Режим зеркала">
|
||||||
|
|
@ -4949,34 +4845,67 @@ export function App() {
|
||||||
</div>
|
</div>
|
||||||
{activeWorkspaceDrawers.length > 0 ? (
|
{activeWorkspaceDrawers.length > 0 ? (
|
||||||
<div className="workspace-drawer-stack">
|
<div className="workspace-drawer-stack">
|
||||||
{activeWorkspaceDrawers.map((activeWorkspaceDrawer) => (
|
{activeWorkspaceDrawers.map((activeWorkspaceDrawer) => {
|
||||||
|
const isPagesDrawer = activeWorkspaceDrawer === "pages";
|
||||||
|
|
||||||
|
return (
|
||||||
<aside className="workspace-drawer open" key={`workspace-drawer-${activeWorkspaceDrawer}`}>
|
<aside className="workspace-drawer open" key={`workspace-drawer-${activeWorkspaceDrawer}`}>
|
||||||
<div className="workspace-drawer-header">
|
<div className="workspace-drawer-header">
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>{isPagesDrawer ? "Страницы и секции" : "Ошибки страницы"}</span>
|
||||||
{activeWorkspaceDrawer === "fields" ? "Поля для правки" : "Аудит страницы"}
|
|
||||||
</span>
|
|
||||||
<strong>
|
<strong>
|
||||||
{activeWorkspaceDrawer === "fields"
|
{isPagesDrawer
|
||||||
? `${activeWorkspaceTargets.length} полей`
|
? `${activeWorkspacePageIndex + 1}/${selectedWorkspaceScopeItems.length}`
|
||||||
: `${activeWorkspaceIssues.length} замечаний`}
|
: `${activeWorkspaceTargets.length} замечаний`}
|
||||||
</strong>
|
</strong>
|
||||||
<small>
|
<small>
|
||||||
{activeWorkspaceDrawer === "fields"
|
{isPagesDrawer
|
||||||
? "Клик по точке или карточке открывает связанное поле."
|
? "Переключает preview и ошибки рабочей зоны."
|
||||||
: "Список относится к активной странице, не ко всему сайту."}
|
: "Карточки относятся к активной странице."}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
aria-label="Закрыть панель"
|
aria-label="Закрыть панель"
|
||||||
className="workspace-drawer-close"
|
className="workspace-drawer-close"
|
||||||
onClick={() => closeWorkspaceDrawer(activeWorkspaceKey, activeWorkspaceDrawer)}
|
onClick={() => closeWorkspaceDrawer(activeWorkspaceUiKey, activeWorkspaceDrawer)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<X size={16} />
|
<X size={16} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{activeWorkspaceDrawer === "fields" ? (
|
{isPagesDrawer ? (
|
||||||
|
selectedWorkspaceScopeItems.length > 0 ? (
|
||||||
|
<div className="workspace-page-menu-list workspace-drawer-page-list">
|
||||||
|
{selectedWorkspaceScopeItems.map((scopeItem, pageIndex) => {
|
||||||
|
const pageWorkspaceKey = getWorkspaceKey(project.id, scopeItem.scopeId);
|
||||||
|
const isActivePage = activeWorkspaceScopeItem?.scopeId === scopeItem.scopeId;
|
||||||
|
const isOpening = busyWorkspaceKey === pageWorkspaceKey;
|
||||||
|
const pageIssues = getPageIssues(scanSummary, scopeItem.pageId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={isActivePage ? "active" : undefined}
|
||||||
|
disabled={isOpening}
|
||||||
|
key={`workspace-page-drawer-${scopeItem.scopeId}`}
|
||||||
|
onClick={() => {
|
||||||
|
void handleOpenPageWorkspace(project, scopeItem, { silent: true });
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>{pageIndex + 1}</span>
|
||||||
|
<strong>{scopeItem.title}</strong>
|
||||||
|
<small>{scopeItem.pathLabel}</small>
|
||||||
|
<em>{pageIssues.length} замечаний</em>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<small className="workspace-page-menu-empty">
|
||||||
|
В выбранном наборе пока нет рабочих страниц или секций.
|
||||||
|
</small>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
<div className="workspace-fields-drawer">
|
<div className="workspace-fields-drawer">
|
||||||
{activeWorkspaceTargets.length > 0 ? (
|
{activeWorkspaceTargets.length > 0 ? (
|
||||||
activeWorkspaceTargets.map((target) => {
|
activeWorkspaceTargets.map((target) => {
|
||||||
|
|
@ -4999,19 +4928,29 @@ export function App() {
|
||||||
</strong>
|
</strong>
|
||||||
<small>{target.selector ?? "selector пока не задан"}</small>
|
<small>{target.selector ?? "selector пока не задан"}</small>
|
||||||
</div>
|
</div>
|
||||||
|
{target.issues.length > 0 ? (
|
||||||
|
<div className="workspace-target-issues">
|
||||||
|
{target.issues.map((issue) => {
|
||||||
|
const explanation = getAuditIssueExplanation(issue.code);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<article
|
||||||
|
className="workspace-target-issue"
|
||||||
|
key={`target-issue-${target.id}-${issue.id}`}
|
||||||
|
>
|
||||||
|
<span>{getAuditSeverityLabel(issue.severity)}</span>
|
||||||
|
<strong>{issue.message}</strong>
|
||||||
|
<small>{issue.field ? `Поле: ${issue.field}` : "Медиа/страница"}</small>
|
||||||
|
<p>{explanation.action}</p>
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div className="workspace-field-meta">
|
<div className="workspace-field-meta">
|
||||||
<span>{getSectionKindLabel(target.kind)}</span>
|
<span>{getSectionKindLabel(target.kind)}</span>
|
||||||
<em>{target.workingText.length} симв.</em>
|
<em>{target.workingText.length} симв.</em>
|
||||||
</div>
|
</div>
|
||||||
{target.issues.length > 0 ? (
|
|
||||||
<div className="workspace-target-issues">
|
|
||||||
{target.issues.map((issue) => (
|
|
||||||
<small key={`target-issue-${target.id}-${issue.id}`}>
|
|
||||||
{getAuditSeverityLabel(issue.severity)} · {issue.message}
|
|
||||||
</small>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<label>
|
<label>
|
||||||
<span>Original · только чтение</span>
|
<span>Original · только чтение</span>
|
||||||
<pre>{target.originalText || "Пусто"}</pre>
|
<pre>{target.originalText || "Пусто"}</pre>
|
||||||
|
|
@ -5069,42 +5008,13 @@ export function App() {
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
<small className="workspace-empty">Для этой страницы пока нет полей, связанных с замечаниями.</small>
|
<small className="workspace-empty">Для этой страницы пока нет ошибок, связанных с полями.</small>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{activeWorkspaceIssues.length > 0 ? (
|
|
||||||
<div className="workspace-issue-list">
|
|
||||||
{activeWorkspaceIssues.map((issue) => {
|
|
||||||
const target = activeWorkspaceTargets.find((item) => item.issues.some((targetIssue) => targetIssue.id === issue.id));
|
|
||||||
const explanation = getAuditIssueExplanation(issue.code);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
disabled={!target}
|
|
||||||
key={`workspace-issue-${issue.id}`}
|
|
||||||
onClick={() => {
|
|
||||||
if (!target) return;
|
|
||||||
activateWorkspaceTarget(activeWorkspaceKey, target);
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>{getAuditSeverityLabel(issue.severity)}</span>
|
|
||||||
<strong>{issue.message}</strong>
|
|
||||||
<small>{issue.field ? `Поле: ${issue.field}` : "Медиа/страница"}</small>
|
|
||||||
<p>{explanation.action}</p>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<small className="workspace-empty">По активной странице ошибок базового аудита нет.</small>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</aside>
|
</aside>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7926,3 +7926,137 @@ textarea:focus {
|
||||||
background: var(--nodedc-glass-control-bg) !important;
|
background: var(--nodedc-glass-control-bg) !important;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-drawer-page-list {
|
||||||
|
min-height: 0;
|
||||||
|
max-height: none;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button,
|
||||||
|
.stage-3 .workspace-drawer-page-list button {
|
||||||
|
grid-template-columns: 28px minmax(0, 1fr);
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px 10px;
|
||||||
|
min-height: 68px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button span,
|
||||||
|
.stage-3 .workspace-drawer-page-list button span {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1 / span 3;
|
||||||
|
align-self: center;
|
||||||
|
width: 26px;
|
||||||
|
min-width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button strong,
|
||||||
|
.stage-3 .workspace-page-menu-list button small,
|
||||||
|
.stage-3 .workspace-page-menu-list button em,
|
||||||
|
.stage-3 .workspace-drawer-page-list button strong,
|
||||||
|
.stage-3 .workspace-drawer-page-list button small,
|
||||||
|
.stage-3 .workspace-drawer-page-list button em {
|
||||||
|
grid-column: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button em,
|
||||||
|
.stage-3 .workspace-drawer-page-list button em {
|
||||||
|
grid-row: auto;
|
||||||
|
justify-self: start;
|
||||||
|
align-self: start;
|
||||||
|
min-width: max-content;
|
||||||
|
min-height: 22px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 9px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button.active,
|
||||||
|
.stage-3 .workspace-drawer-page-list button.active,
|
||||||
|
.workspace-fields-drawer .workspace-field-card.active {
|
||||||
|
background: var(--nodedc-header-dropdown-item-active-bg) !important;
|
||||||
|
box-shadow: var(--nodedc-glass-control-shadow), 0 0 0 1px rgba(24, 32, 29, 0.12) inset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button.active span,
|
||||||
|
.stage-3 .workspace-drawer-page-list button.active span {
|
||||||
|
color: #fff !important;
|
||||||
|
background: var(--ink) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-page-menu-list button.active strong,
|
||||||
|
.stage-3 .workspace-page-menu-list button.active small,
|
||||||
|
.stage-3 .workspace-page-menu-list button.active em,
|
||||||
|
.stage-3 .workspace-drawer-page-list button.active strong,
|
||||||
|
.stage-3 .workspace-drawer-page-list button.active small,
|
||||||
|
.stage-3 .workspace-drawer-page-list button.active em {
|
||||||
|
color: var(--ink) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-3 .workspace-target-issues {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
backdrop-filter: none !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-target-issue {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
gap: 4px 8px;
|
||||||
|
padding: 10px;
|
||||||
|
color: var(--ink);
|
||||||
|
background: var(--nodedc-glass-control-bg);
|
||||||
|
border: 0;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: var(--nodedc-glass-control-shadow);
|
||||||
|
backdrop-filter: var(--nodedc-glass-blur);
|
||||||
|
-webkit-backdrop-filter: var(--nodedc-glass-blur);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-target-issue span {
|
||||||
|
grid-row: 1 / span 3;
|
||||||
|
align-self: start;
|
||||||
|
min-height: 22px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
color: var(--muted) !important;
|
||||||
|
background: rgba(24, 32, 29, 0.06) !important;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-target-issue strong,
|
||||||
|
.workspace-target-issue small,
|
||||||
|
.workspace-target-issue p {
|
||||||
|
grid-column: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-target-issue strong {
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 1.22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-target-issue small,
|
||||||
|
.workspace-target-issue p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 520;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue