perf(ui): stabilize install warning bundle

This commit is contained in:
Jesse Merhi
2026-08-10 15:40:35 +10:00
committed by jesse-merhi
parent 10256a172c
commit 4478fb22ba
3 changed files with 71 additions and 120 deletions
-5
View File
@@ -2798,14 +2798,9 @@ export const en: TranslationMap = {
acknowledgeRisk: "Acknowledge risk and install",
defaultRiskWarning: "Review the ClawHub warning before installing this plugin.",
policyReviewTitle: "Security review needed",
policyReviewBodyUnknown: "Policy flagged this plugin. Not installed.",
policyReviewBodyKnown: "Policy warnings: {count}. Not installed.",
policyReviewFindings: "Findings",
policyReviewTechnicalDetails: "Details",
policyReviewPolicyResponse: "Reason",
policyReviewRule: "Rule {count}",
policyReviewLocation: "Location",
policyReviewEvidence: "Evidence",
installAnyway: "Install anyway",
connectToChange: "Connect to the gateway to change plugins.",
adminRequired: "Browsing only. Plugin changes require operator.admin access.",
+46 -75
View File
@@ -389,7 +389,7 @@ function renderRowMessage(
const findings = details.findings ?? [];
const reviewBody =
findings.length === 0
? t("pluginsPage.policyReviewBodyUnknown")
? details.reason
: t("pluginsPage.policyReviewBodyKnown", { count: String(findings.length) });
return html`
<div class="plugins-row-message plugins-row-message--warning" role="alert">
@@ -405,26 +405,15 @@ function renderRowMessage(
${findings.length > 0
? html`
<section class="plugins-policy-review__findings-panel">
<div class="plugins-policy-review__findings-heading">
<span>${t("pluginsPage.policyReviewFindings")}</span>
</div>
<strong class="plugins-policy-review__findings-heading"
>${t("pluginsPage.policyReviewFindings")}</strong
>
<ul class="plugins-policy-review__findings">
${findings.map(
(finding) => html`
<li>
<span class="plugins-policy-review__finding-mark" aria-hidden="true"></span>
<span>${finding.message}</span>
</li>
`,
)}
${findings.map((finding) => html` <li>${finding.message}</li> `)}
</ul>
</section>
`
: html`
<section class="plugins-policy-review__findings-panel">
<p class="plugins-policy-review__reason">${details.reason}</p>
</section>
`}
: nothing}
${findings.length > 0
? html`
<details class="plugins-policy-review__details">
@@ -434,67 +423,49 @@ function renderRowMessage(
>
<span>${t("pluginsPage.policyReviewTechnicalDetails")}</span>
</summary>
<dl>
<div>
<dt>${t("pluginsPage.policyReviewPolicyResponse")}</dt>
<dd>${details.reason}</dd>
</div>
${findings.map(
(finding, index) => html`
<div>
<dt>${t("pluginsPage.policyReviewRule", { count: String(index + 1) })}</dt>
<dd><code>${finding.ruleId}</code></dd>
</div>
${finding.file
? html`
<div>
<dt>${t("pluginsPage.policyReviewLocation")}</dt>
<dd>
<code
>${finding.file}${finding.line ? `:${finding.line}` : ""}</code
>
</dd>
</div>
`
: nothing}
${finding.evidence
? html`
<div>
<dt>${t("pluginsPage.policyReviewEvidence")}</dt>
<dd>${finding.evidence}</dd>
</div>
`
: nothing}
`,
)}
</dl>
<div class="plugins-policy-review__details-body">
<p>${details.reason}</p>
<ul>
${findings.map(
(finding) => html`
<li>
<code>${finding.ruleId}</code>
${finding.file
? html`<code
>${finding.file}${finding.line ? `:${finding.line}` : ""}</code
>`
: nothing}
${finding.evidence ? html`<span>${finding.evidence}</span>` : nothing}
</li>
`,
)}
</ul>
</div>
</details>
`
: nothing}
<div class="plugins-policy-review__footer">
<div class="plugins-policy-review__actions">
<button
type="button"
class="btn btn--sm"
?disabled=${busy}
@click=${() => props.onDismissMessage(key)}
>
${t("pluginsPage.cancel")}
</button>
<button
type="button"
class="btn btn--sm danger"
title=${props.mutationBlockedReason ?? ""}
?disabled=${busy || !props.canMutate}
@click=${() =>
props.onInstall(key, {
...request,
acknowledgeInstallPolicyWarning: true,
})}
>
${busy ? t("pluginsPage.installing") : t("pluginsPage.installAnyway")}
</button>
</div>
<div class="plugins-policy-review__actions">
<button
type="button"
class="btn btn--sm"
?disabled=${busy}
@click=${() => props.onDismissMessage(key)}
>
${t("pluginsPage.cancel")}
</button>
<button
type="button"
class="btn btn--sm danger"
title=${props.mutationBlockedReason ?? ""}
?disabled=${busy || !props.canMutate}
@click=${() =>
props.onInstall(key, {
...request,
acknowledgeInstallPolicyWarning: true,
})}
>
${busy ? t("pluginsPage.installing") : t("pluginsPage.installAnyway")}
</button>
</div>
</div>
`;
+25 -40
View File
@@ -520,10 +520,6 @@ h3.plugins-subheader {
}
.plugins-policy-review__findings-heading {
display: flex;
align-items: center;
justify-content: flex-start;
gap: var(--space-2);
color: var(--text-strong);
font-weight: 600;
}
@@ -544,21 +540,18 @@ h3.plugins-subheader {
color: var(--text);
}
.plugins-policy-review__findings li + li {
margin-top: var(--space-2);
}
.plugins-policy-review__finding-mark {
.plugins-policy-review__findings li::before {
width: 7px;
height: 7px;
margin-top: 6px;
border-radius: var(--radius-full);
background: var(--warn);
content: "";
justify-self: center;
}
.plugins-policy-review__reason {
margin: 0;
.plugins-policy-review__findings li + li {
margin-top: var(--space-2);
}
.plugins-policy-review__details {
@@ -612,24 +605,30 @@ h3.plugins-subheader {
box-shadow: var(--focus-ring);
}
.plugins-policy-review__details dl {
.plugins-policy-review__details-body {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-2);
margin: var(--space-2) 0 0;
}
.plugins-policy-review__details dl > div {
min-width: 0;
}
.plugins-policy-review__details dt {
margin-bottom: 2px;
}
.plugins-policy-review__details dd {
overflow-wrap: anywhere;
.plugins-policy-review__details-body p,
.plugins-policy-review__details-body ul {
margin: 0;
}
.plugins-policy-review__details-body ul {
display: grid;
gap: var(--space-2);
padding: 0;
list-style: none;
}
.plugins-policy-review__details-body li {
display: flex;
min-width: 0;
flex-wrap: wrap;
gap: var(--space-2);
overflow-wrap: anywhere;
color: var(--text);
}
@@ -637,22 +636,17 @@ h3.plugins-subheader {
font-size: inherit;
}
.plugins-policy-review__footer {
.plugins-policy-review__actions {
display: flex;
align-items: center;
justify-content: space-between;
justify-content: flex-end;
gap: var(--space-3);
padding: var(--space-2) 0 0 var(--plugins-policy-review-indent);
border-top: 1px solid color-mix(in srgb, var(--warn) 20%, var(--border));
}
.plugins-policy-review__actions {
display: flex;
flex: 0 0 auto;
gap: var(--space-2);
}
.plugins-policy-review__actions .btn {
flex: 0 0 auto;
min-height: 44px;
}
@@ -915,15 +909,6 @@ h3.plugins-subheader {
padding: var(--space-2) 0 0;
}
.plugins-policy-review__details dl {
grid-template-columns: minmax(0, 1fr);
}
.plugins-policy-review__footer {
align-items: stretch;
flex-direction: column;
}
.plugins-policy-review__actions,
.plugins-policy-review__actions .btn {
flex: 1 1 0;