mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-09-14 18:56:52 +00:00
docs(monitor): new App + Updates sub-pages for VMs & LXCs with i18n
This commit is contained in:
@@ -0,0 +1,393 @@
|
||||
import type { Metadata } from "next"
|
||||
import type React from "react"
|
||||
import { getTranslations, getMessages, setRequestLocale } from "next-intl/server"
|
||||
import { Link } from "@/i18n/navigation"
|
||||
import { DocHeader } from "@/components/ui/doc-header"
|
||||
import { Callout } from "@/components/ui/callout"
|
||||
import CopyableCode from "@/components/CopyableCode"
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params
|
||||
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsApp.meta" })
|
||||
return { title: t("title"), description: t("description") }
|
||||
}
|
||||
|
||||
type TableRow = { method: string; when: string }
|
||||
type BreakdownRow = { part: string; meaning: string }
|
||||
type ExampleRow = { text: string; regex: string; result: string }
|
||||
|
||||
function Figure({ src, alt, caption }: { src: string; alt: string; caption: string }) {
|
||||
return (
|
||||
<figure className="my-6">
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
className="rounded-lg border border-gray-200 shadow-sm w-full"
|
||||
/>
|
||||
<figcaption className="text-sm text-gray-500 mt-2 text-center italic">
|
||||
{caption}
|
||||
</figcaption>
|
||||
</figure>
|
||||
)
|
||||
}
|
||||
|
||||
export default async function AppTabPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>
|
||||
}) {
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsApp" })
|
||||
|
||||
const messages = (await getMessages({ locale })) as unknown as {
|
||||
docs: { monitor: { dashboard: { vmsLxcsApp: {
|
||||
whatYouGet: { items: string[] }
|
||||
registerSuggested: { steps: string[] }
|
||||
manual: { linksItems: string[] }
|
||||
multiple: { usefulItems: string[] }
|
||||
tracking: {
|
||||
ingredients: string[]
|
||||
methodsTable: { rows: TableRow[] }
|
||||
sourceItems: string[]
|
||||
regexTwoItems: string[]
|
||||
step2Items: string[]
|
||||
step2Breakdown: { rows: BreakdownRow[] }
|
||||
step3Examples: { rows: ExampleRow[] }
|
||||
step4Items: string[]
|
||||
step6CorrectItems: string[]
|
||||
}
|
||||
state: { items: string[] }
|
||||
manage: { items: string[] }
|
||||
notDetected: { steps: string[] }
|
||||
} } } }
|
||||
}
|
||||
const v = messages.docs.monitor.dashboard.vmsLxcsApp
|
||||
const whatYouGetItems = v.whatYouGet.items
|
||||
const registerSteps = v.registerSuggested.steps
|
||||
const manualLinks = v.manual.linksItems
|
||||
const multipleUseful = v.multiple.usefulItems
|
||||
const ingredients = v.tracking.ingredients
|
||||
const methodsRows = v.tracking.methodsTable.rows
|
||||
const sourceItems = v.tracking.sourceItems
|
||||
const regexTwoItems = v.tracking.regexTwoItems
|
||||
const step2Items = v.tracking.step2Items
|
||||
const breakdownRows = v.tracking.step2Breakdown.rows
|
||||
const exampleRows = v.tracking.step3Examples.rows
|
||||
const step4Items = v.tracking.step4Items
|
||||
const step6CorrectItems = v.tracking.step6CorrectItems
|
||||
const stateItems = v.state.items
|
||||
const manageItems = v.manage.items
|
||||
const notDetectedSteps = v.notDetected.steps
|
||||
|
||||
// Rich-text tag handlers
|
||||
const strong = (chunks: React.ReactNode) => <strong>{chunks}</strong>
|
||||
const em = (chunks: React.ReactNode) => <em>{chunks}</em>
|
||||
const code = (chunks: React.ReactNode) => (
|
||||
<code className="text-sm bg-gray-100 px-1 rounded">{chunks}</code>
|
||||
)
|
||||
const linkUpdates = (chunks: React.ReactNode) => (
|
||||
<Link href="/docs/monitor/dashboard/vms-lxcs/updates" className="text-blue-600 hover:underline">
|
||||
{chunks}
|
||||
</Link>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto px-4 py-8">
|
||||
<DocHeader
|
||||
title={t("header.title")}
|
||||
description={t("header.description")}
|
||||
estimatedMinutes={12}
|
||||
/>
|
||||
|
||||
<p className="text-gray-800 mt-6">{t.rich("intro.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("intro.p2", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("intro.p3", { strong, em, code, link: linkUpdates })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("whatYouGet.heading")}</h2>
|
||||
<p className="text-gray-800">{t("whatYouGet.lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{whatYouGetItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`whatYouGet.items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("whatYouGet.trailing", { strong, em, code })}</p>
|
||||
<Callout variant="warning">{t.rich("whatYouGet.callout", { strong, em, code })}</Callout>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("firstOpening.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("firstOpening.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("firstOpening.p2", { strong, em, code })}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-01.png"
|
||||
alt={t("figures.f01.alt")}
|
||||
caption={t("figures.f01.caption")}
|
||||
/>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("registerSuggested.heading")}</h3>
|
||||
<ol className="list-decimal pl-6 space-y-1 text-gray-800">
|
||||
{registerSteps.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`registerSuggested.steps.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ol>
|
||||
<p className="text-gray-800 mt-4">{t.rich("registerSuggested.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("catalog.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("catalog.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("catalog.p2", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("catalog.p3", { strong, em, code })}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-02.png"
|
||||
alt={t("figures.f02.alt")}
|
||||
caption={t("figures.f02.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("manual.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("manual.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("manual.p2", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("manual.nameHeading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("manual.nameBody", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("manual.linksHeading")}</h3>
|
||||
<p className="text-gray-800">{t("manual.linksLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{manualLinks.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`manual.linksItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("manual.linksTrailing", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("manual.linksConfirm", { strong, em, code })}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-03.png"
|
||||
alt={t("figures.f03.alt")}
|
||||
caption={t("figures.f03.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("multiple.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("multiple.intro", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("multiple.usefulLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{multipleUseful.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`multiple.usefulItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("multiple.dontGroup", { strong, em, code })}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-04.png"
|
||||
alt={t("figures.f04.alt")}
|
||||
caption={t("figures.f04.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("tracking.heading")}</h2>
|
||||
<p className="text-gray-800">{t("tracking.intro")}</p>
|
||||
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{ingredients.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.ingredients.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ol>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.methodsHeading")}</h3>
|
||||
<p className="text-gray-800">{t("tracking.methodsLead")}</p>
|
||||
<div className="overflow-x-auto my-4">
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.methodsTable.colMethod")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.methodsTable.colWhen")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{methodsRows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.method}</td>
|
||||
<td className="border border-gray-300 px-3 py-2">{row.when}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.methodsTrailing", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.commandHeading")}</h4>
|
||||
<p className="text-gray-800">{t.rich("tracking.commandP1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.commandP2")}</p>
|
||||
<CopyableCode code={t("tracking.commandExample1")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t("tracking.commandP3")}</p>
|
||||
<CopyableCode code={t("tracking.commandExample2")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.commandP4", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.sourceHeading")}</h3>
|
||||
<p className="text-gray-800">{t("tracking.sourceLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{sourceItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.sourceItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.sourceTrailing", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.regexHeading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("tracking.regexIntro", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.regexOptional", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.regexTwoHeading")}</h4>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{regexTwoItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.regexTwoItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.regexTwoTrailing", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step1Heading")}</h4>
|
||||
<p className="text-gray-800">{t("tracking.step1P1")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step1P2")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step1P3")}</p>
|
||||
<CopyableCode code={t("tracking.step1Cmd")} language="sh" />
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step1P4")}</p>
|
||||
<CopyableCode code={t("tracking.step1Output")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step1P5")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step1P6")}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step2Heading")}</h4>
|
||||
<p className="text-gray-800">{t.rich("tracking.step2Lead", { strong, em, code })}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{step2Items.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.step2Items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step2Recommended")}</p>
|
||||
<CopyableCode code={t("tracking.step2Regex")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step2ReadLead")}</p>
|
||||
<div className="overflow-x-auto my-4">
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step2Breakdown.colPart")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step2Breakdown.colMeaning")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{breakdownRows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.part}</td>
|
||||
<td className="border border-gray-300 px-3 py-2">{row.meaning}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step2DotNote", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step3Heading")}</h4>
|
||||
<p className="text-gray-800">{t("tracking.step3Lead")}</p>
|
||||
<div className="overflow-x-auto my-4">
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colText")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colRegex")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colResult")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{exampleRows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.text}</td>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.regex}</td>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.result}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step3Note1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step3Note2", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step4Heading")}</h4>
|
||||
<p className="text-gray-800">{t("tracking.step4Intro")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{step4Items.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.step4Items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step4Trailing", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4"><strong>{t("tracking.step4RecLabel")}</strong></p>
|
||||
<CopyableCode code={t.raw("tracking.step4RecRegex") as string} language="text" />
|
||||
<p className="text-gray-800 mt-4"><strong>{t("tracking.step4LessLabel")}</strong></p>
|
||||
<CopyableCode code={t("tracking.step4LessRegex")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step4Note", { strong, em, code })}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step5Heading")}</h4>
|
||||
<p className="text-gray-800">{t("tracking.step5Lead")}</p>
|
||||
<CopyableCode code={t("tracking.step5Regex")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step5P1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step5P2")}</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step6Heading")}</h4>
|
||||
<p className="text-gray-800">{t.rich("tracking.step6Lead", { strong, em, code })}</p>
|
||||
<CopyableCode code={t("tracking.step6Output")} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t("tracking.step6CorrectLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{step6CorrectItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`tracking.step6CorrectItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("tracking.step6ErrorNote", { strong, em, code })}</p>
|
||||
<Callout variant="tip">{t.rich("tracking.step6Callout", { strong, em, code })}</Callout>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-05.png"
|
||||
alt={t("figures.f05.alt")}
|
||||
caption={t("figures.f05.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("state.heading")}</h2>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-06.png"
|
||||
alt={t("figures.f06.alt")}
|
||||
caption={t("figures.f06.caption")}
|
||||
/>
|
||||
|
||||
<p className="text-gray-800">{t("state.lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{stateItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`state.items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("state.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("manage.heading")}</h2>
|
||||
<p className="text-gray-800">{t("manage.lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{manageItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`manage.items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("manage.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("notDetected.heading")}</h2>
|
||||
<p className="text-gray-800">{t("notDetected.intro")}</p>
|
||||
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{notDetectedSteps.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`notDetected.steps.${idx}`, { strong, em, code, link: linkUpdates })}</li>
|
||||
))}
|
||||
</ol>
|
||||
<p className="text-gray-800 mt-4">{t.rich("notDetected.trailing", { strong, em, code })}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-app-07.png"
|
||||
alt={t("figures.f07.alt")}
|
||||
caption={t("figures.f07.caption")}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -39,7 +39,6 @@ export default async function VmsLxcsTabPage({
|
||||
mountTypesItems: string[]
|
||||
mountStateItems: string[]
|
||||
backupsItems: string[]
|
||||
updatesPanelItems: string[]
|
||||
firewallItems: string[]
|
||||
lifecycleRows: LifecycleRow[]
|
||||
}
|
||||
@@ -56,7 +55,6 @@ export default async function VmsLxcsTabPage({
|
||||
const mountTypesItems = v.drillIn.mountTypesItems
|
||||
const mountStateItems = v.drillIn.mountStateItems
|
||||
const backupsItems = v.drillIn.backupsItems
|
||||
const updatesPanelItems = v.drillIn.updatesPanelItems
|
||||
const firewallItems = v.drillIn.firewallItems
|
||||
const lifecycleRows = v.drillIn.lifecycleRows
|
||||
const dataRows = v.dataCollected.rows
|
||||
@@ -227,6 +225,40 @@ export default async function VmsLxcsTabPage({
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.ipsTitle")}</h4>
|
||||
<p className="mb-6 text-gray-800 leading-relaxed">{t("drillIn.ipsBody")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">App</h3>
|
||||
<p className="mb-4 text-gray-800 leading-relaxed">
|
||||
The <strong>App</strong> section lets you register the applications running inside an LXC, wire quick web
|
||||
links, and optionally track installed vs. upstream versions. Registrations feed the App-level notifications
|
||||
and the update flows on the next section.
|
||||
</p>
|
||||
<p className="mb-6 text-gray-800 leading-relaxed">
|
||||
See the{" "}
|
||||
<Link
|
||||
href="/docs/monitor/dashboard/vms-lxcs/app"
|
||||
className="text-blue-600 hover:underline"
|
||||
>
|
||||
dedicated App page
|
||||
</Link>{" "}
|
||||
for the catalog, manual registration, version-tracking methods and regex patterns.
|
||||
</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">Updates</h3>
|
||||
<p className="mb-4 text-gray-800 leading-relaxed">
|
||||
The <strong>Updates</strong> section covers OS package updates (APT / APK) and application updates via
|
||||
Community Scripts helpers or custom commands. Detection runs unconditionally on running LXCs; whether pending
|
||||
updates also trigger a notification is controlled from <strong>Settings → Notifications</strong>.
|
||||
</p>
|
||||
<p className="mb-6 text-gray-800 leading-relaxed">
|
||||
See the{" "}
|
||||
<Link
|
||||
href="/docs/monitor/dashboard/vms-lxcs/updates"
|
||||
className="text-blue-600 hover:underline"
|
||||
>
|
||||
dedicated Updates page
|
||||
</Link>{" "}
|
||||
for the decision matrix, custom-command guidance, backup / restart preferences and scheduled updates.
|
||||
</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.mountsTitle")}</h3>
|
||||
|
||||
<figure className="my-4">
|
||||
@@ -287,45 +319,6 @@ export default async function VmsLxcsTabPage({
|
||||
{t.rich("drillIn.backupsOutro", { strong })}
|
||||
</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.updatesTitle")}</h3>
|
||||
|
||||
<figure className="my-4">
|
||||
<img
|
||||
src="/monitor/vms-modal-lxc-updates.png"
|
||||
alt={t("drillIn.updatesImageAlt")}
|
||||
className="rounded-lg border border-gray-200 shadow-sm w-full"
|
||||
/>
|
||||
<figcaption className="text-sm text-gray-500 mt-2 text-center italic">
|
||||
{t("drillIn.updatesImageCaption")}
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<p className="mb-4 text-gray-800 leading-relaxed">
|
||||
{t.rich("drillIn.updatesIntro", { strong, code })}
|
||||
</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.updatesPanelTitle")}</h4>
|
||||
<ul className="list-disc pl-6 mb-4 text-gray-800 leading-relaxed space-y-1">
|
||||
{updatesPanelItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`drillIn.updatesPanelItems.${idx}`, { strong })}</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.updatesScopeTitle")}</h4>
|
||||
<p className="mb-4 text-gray-800 leading-relaxed">
|
||||
{t.rich("drillIn.updatesScopeBody", { strong, em, code })}
|
||||
</p>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.updatesToggleTitle")}</h4>
|
||||
<Callout variant="info" title={t("drillIn.updatesToggleCalloutTitle")}>
|
||||
{t.rich("drillIn.updatesToggleCalloutBody", { strong, code })}
|
||||
</Callout>
|
||||
|
||||
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.updatesApplyTitle")}</h4>
|
||||
<p className="mb-6 text-gray-800 leading-relaxed">
|
||||
{t.rich("drillIn.updatesApplyBody", { code })}
|
||||
</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.firewallTitle")}</h3>
|
||||
|
||||
<p className="mb-4 text-gray-800 leading-relaxed">{t("drillIn.firewallIntro")}</p>
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
import type { Metadata } from "next"
|
||||
import type React from "react"
|
||||
import { getTranslations, getMessages, setRequestLocale } from "next-intl/server"
|
||||
import { Link } from "@/i18n/navigation"
|
||||
import { ExternalLink } from "lucide-react"
|
||||
import { DocHeader } from "@/components/ui/doc-header"
|
||||
import { Callout } from "@/components/ui/callout"
|
||||
import CopyableCode from "@/components/CopyableCode"
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params
|
||||
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsUpdates.meta" })
|
||||
return { title: t("title"), description: t("description") }
|
||||
}
|
||||
|
||||
type DecisionRow = { situation: string; action: string }
|
||||
type DifferenceRow = { field: string; location: string; role: string }
|
||||
|
||||
function Figure({ src, alt, caption }: { src: string; alt: string; caption: string }) {
|
||||
return (
|
||||
<figure className="my-6">
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
className="rounded-lg border border-gray-200 shadow-sm w-full"
|
||||
/>
|
||||
<figcaption className="text-sm text-gray-500 mt-2 text-center italic">
|
||||
{caption}
|
||||
</figcaption>
|
||||
</figure>
|
||||
)
|
||||
}
|
||||
|
||||
export default async function UpdatesTabPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>
|
||||
}) {
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsUpdates" })
|
||||
|
||||
const messages = (await getMessages({ locale })) as unknown as {
|
||||
docs: { monitor: { dashboard: { vmsLxcsUpdates: {
|
||||
decision: { table: { rows: DecisionRow[] } }
|
||||
figureOut: {
|
||||
step3Items: string[]
|
||||
step4Items: string[]
|
||||
}
|
||||
requirements: { items: string[] }
|
||||
difference: { table: { rows: DifferenceRow[] } }
|
||||
apply: {
|
||||
steps: string[]
|
||||
systemItems: string[]
|
||||
appItems: string[]
|
||||
}
|
||||
scheduled: { createSteps: string[] }
|
||||
} } } }
|
||||
}
|
||||
const v = messages.docs.monitor.dashboard.vmsLxcsUpdates
|
||||
const decisionRows = v.decision.table.rows
|
||||
const step3Items = v.figureOut.step3Items
|
||||
const step4Items = v.figureOut.step4Items
|
||||
const reqItems = v.requirements.items
|
||||
const diffRows = v.difference.table.rows
|
||||
const applySteps = v.apply.steps
|
||||
const applySystem = v.apply.systemItems
|
||||
const applyApp = v.apply.appItems
|
||||
const schedSteps = v.scheduled.createSteps
|
||||
|
||||
// Rich-text tag handlers
|
||||
const strong = (chunks: React.ReactNode) => <strong>{chunks}</strong>
|
||||
const em = (chunks: React.ReactNode) => <em>{chunks}</em>
|
||||
const code = (chunks: React.ReactNode) => (
|
||||
<code className="text-sm bg-gray-100 px-1 rounded">{chunks}</code>
|
||||
)
|
||||
const linkApp = (chunks: React.ReactNode) => (
|
||||
<Link href="/docs/monitor/dashboard/vms-lxcs/app" className="text-blue-600 hover:underline">
|
||||
{chunks}
|
||||
</Link>
|
||||
)
|
||||
const linkHelperHome = (chunks: React.ReactNode) => (
|
||||
<a
|
||||
href="https://community-scripts.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-blue-600 hover:underline"
|
||||
>
|
||||
{chunks}
|
||||
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</a>
|
||||
)
|
||||
const linkHelperDocs = (chunks: React.ReactNode) => (
|
||||
<a
|
||||
href="https://community-scripts.org/docs/tools/pve/update-apps"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 text-blue-600 hover:underline"
|
||||
>
|
||||
{chunks}
|
||||
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</a>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto px-4 py-8">
|
||||
<DocHeader
|
||||
title={t("header.title")}
|
||||
description={t("header.description")}
|
||||
estimatedMinutes={12}
|
||||
/>
|
||||
|
||||
<p className="text-gray-800 mt-6">{t.rich("intro.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("intro.p2", { strong, em, code, link: linkApp })}</p>
|
||||
<Callout variant="info">{t.rich("intro.callout", { strong, em, code })}</Callout>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("mechanisms.heading")}</h2>
|
||||
<p className="text-gray-800">{t("mechanisms.intro")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.osHeading")}</h3>
|
||||
<p className="text-gray-800">{t("mechanisms.osP1")}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("mechanisms.osP2", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("mechanisms.osP3")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.helperHeading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("mechanisms.helperP1", { strong, em, code, linkHelperHome })}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("mechanisms.helperP2", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">
|
||||
{t.rich("mechanisms.helperP3", { strong, em, code, linkHelperHome, linkHelperDocs })}
|
||||
</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("mechanisms.helperP4", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.customHeading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("mechanisms.customP1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("mechanisms.customP2")}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("decision.heading")}</h2>
|
||||
<div className="overflow-x-auto my-4">
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("decision.table.colSituation")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("decision.table.colAction")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{decisionRows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="border border-gray-300 px-3 py-2">{row.situation}</td>
|
||||
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.action}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-gray-800 mt-4">{t("decision.trailing")}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-01.png"
|
||||
alt={t("figures.f01.alt")}
|
||||
caption={t("figures.f01.caption")}
|
||||
/>
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-02.png"
|
||||
alt={t("figures.f02.alt")}
|
||||
caption={t("figures.f02.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("custom.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("custom.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("custom.p2")}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-03.png"
|
||||
alt={t("figures.f03.alt")}
|
||||
caption={t("figures.f03.caption")}
|
||||
/>
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-04.png"
|
||||
alt={t("figures.f04.alt")}
|
||||
caption={t("figures.f04.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("figureOut.heading")}</h2>
|
||||
<p className="text-gray-800">{t("figureOut.intro")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step1Heading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("figureOut.step1P1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step1P2")}</p>
|
||||
<CopyableCode code={t("figureOut.step1Cmd1")} language="sh" />
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step1P3")}</p>
|
||||
<CopyableCode code={t("figureOut.step1Cmd2")} language="sh" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("figureOut.step1P4", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step2Heading")}</h3>
|
||||
<p className="text-gray-800">{t.rich("figureOut.step2P1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step2P2")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step3Heading")}</h3>
|
||||
<p className="text-gray-800">{t("figureOut.step3Lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{step3Items.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`figureOut.step3Items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step3P1")}</p>
|
||||
<CopyableCode code={t("figureOut.step3Cmd")} language="sh" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("figureOut.step3P2", { strong, em, code })}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step4Heading")}</h3>
|
||||
<p className="text-gray-800">{t("figureOut.step4Lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{step4Items.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`figureOut.step4Items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step4Note")}</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step5Heading")}</h3>
|
||||
<p className="text-gray-800">{t("figureOut.step5P1")}</p>
|
||||
<CopyableCode code={t.raw("figureOut.step5Cmd1") as string} language="text" />
|
||||
<p className="text-gray-800 mt-4">{t.rich("figureOut.step5P2", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step5P3")}</p>
|
||||
<CopyableCode code={t("figureOut.step5Cmd2")} language="sh" />
|
||||
<p className="text-gray-800 mt-4">{t("figureOut.step5P4")}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("requirements.heading")}</h2>
|
||||
<p className="text-gray-800">{t("requirements.lead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{reqItems.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`requirements.items.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t.rich("requirements.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("difference.heading")}</h2>
|
||||
<p className="text-gray-800">{t("difference.lead")}</p>
|
||||
<div className="overflow-x-auto my-4">
|
||||
<table className="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colField")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colLocation")}</th>
|
||||
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colRole")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{diffRows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
<td className="border border-gray-300 px-3 py-2 font-medium">{row.field}</td>
|
||||
<td className="border border-gray-300 px-3 py-2 text-xs">{row.location}</td>
|
||||
<td className="border border-gray-300 px-3 py-2 text-xs">{row.role}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="text-gray-800 mt-4">{t.rich("difference.trailing", { strong, em, code })}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("apply.heading")}</h2>
|
||||
<p className="text-gray-800">{t("apply.lead")}</p>
|
||||
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{applySteps.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`apply.steps.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ol>
|
||||
<p className="text-gray-800 mt-4">{t("apply.trailing1")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("apply.systemLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{applySystem.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`apply.systemItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t("apply.appLead")}</p>
|
||||
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{applyApp.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`apply.appItems.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-gray-800 mt-4">{t("apply.trailing2")}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-05.png"
|
||||
alt={t("figures.f05.alt")}
|
||||
caption={t("figures.f05.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("backup.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("backup.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("backup.p2")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("backup.p3")}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("restart.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("restart.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("restart.p2")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("restart.p3")}</p>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-06.png"
|
||||
alt={t("figures.f06.alt")}
|
||||
caption={t("figures.f06.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("scheduled.heading")}</h2>
|
||||
<p className="text-gray-800">{t.rich("scheduled.p1", { strong, em, code })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("scheduled.createLead")}</p>
|
||||
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
|
||||
{schedSteps.map((_, idx) => (
|
||||
<li key={idx}>{t.rich(`scheduled.createSteps.${idx}`, { strong, em, code })}</li>
|
||||
))}
|
||||
</ol>
|
||||
<p className="text-gray-800 mt-4">{t("scheduled.p2")}</p>
|
||||
<p className="text-gray-800 mt-4">{t("scheduled.p3")}</p>
|
||||
<Callout variant="tip">{t("scheduled.callout")}</Callout>
|
||||
|
||||
<Figure
|
||||
src="/monitor/vms-modal-updates-07.png"
|
||||
alt={t("figures.f07.alt")}
|
||||
caption={t("figures.f07.caption")}
|
||||
/>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("verify.heading")}</h2>
|
||||
<p className="text-gray-800">{t("verify.p1")}</p>
|
||||
<p className="text-gray-800 mt-4">{t.rich("verify.p2", { strong, em, code, link: linkApp })}</p>
|
||||
<p className="text-gray-800 mt-4">{t("verify.p3")}</p>
|
||||
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("troubleshoot.heading")}</h2>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.noButtonHeading")}</h3>
|
||||
<Callout variant="troubleshoot">{t.rich("troubleshoot.noButtonBody", { strong, em, code })}</Callout>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.aptHeading")}</h3>
|
||||
<Callout variant="troubleshoot">{t.rich("troubleshoot.aptBody", { strong, em, code })}</Callout>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.noUpdaterHeading")}</h3>
|
||||
<Callout variant="troubleshoot">{t.rich("troubleshoot.noUpdaterBody", { strong, em, code })}</Callout>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.helperDetectedHeading")}</h3>
|
||||
<Callout variant="troubleshoot">{t.rich("troubleshoot.helperDetectedBody", { strong, em, code })}</Callout>
|
||||
|
||||
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.customFailsHeading")}</h3>
|
||||
<Callout variant="troubleshoot">{t.rich("troubleshoot.customFailsBody", { strong, em, code })}</Callout>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user