@aglyn/plugins-ai 1.0.0-beta.292 → 1.0.0-beta.296
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -17
- package/src/lib/components/ai-job-links.d.ts +15 -2
- package/src/lib/components/ai-job-links.js +24 -3
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +9 -0
- package/src/lib/components/ai-job-requests.js +34 -0
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +28 -2
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-import-job.component.js +5 -4
- package/src/lib/components/ai-site-import-job.component.js.map +1 -1
- package/src/lib/components/ai-site-import-start.component.js +3 -3
- package/src/lib/components/ai-site-import-start.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
- package/src/lib/components/ai-site-start-card.component.js +129 -29
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +15 -3
- package/src/lib/components/ai-site-start-steps.component.js +42 -25
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
- package/src/lib/components/ai-site-style-previews.d.ts +17 -0
- package/src/lib/components/ai-site-style-previews.js +26 -95
- package/src/lib/components/ai-site-style-previews.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.d.ts +7 -1
- package/src/lib/components/assist-jobs-drawer.component.js +20 -6
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-page-change-card.component.d.ts +44 -0
- package/src/lib/components/assist-page-change-card.component.js +166 -0
- package/src/lib/components/assist-page-change-card.component.js.map +1 -0
- package/src/lib/components/assist-panel.component.d.ts +105 -1
- package/src/lib/components/assist-panel.component.js +224 -29
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/declarations.server.js +22 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/jobs/ai-job-edit-step.d.ts +62 -16
- package/src/lib/jobs/ai-job-edit-step.js +172 -61
- package/src/lib/jobs/ai-job-edit-step.js.map +1 -1
- package/src/lib/jobs/ai-job-import-step.d.ts +21 -2
- package/src/lib/jobs/ai-job-import-step.js +179 -49
- package/src/lib/jobs/ai-job-import-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +27 -3
- package/src/lib/jobs/ai-job-layout-language.js +156 -113
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +56 -17
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-navigation-step.js +4 -2
- package/src/lib/jobs/ai-job-navigation-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +25 -15
- package/src/lib/jobs/ai-job-page-language.js +120 -66
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.js +27 -7
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +12 -4
- package/src/lib/jobs/ai-job-site-datasets.js +36 -16
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-jobs.js +6 -2
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +50 -1
- package/src/lib/jobs/ai-layout-stock-photos.js +586 -35
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-import-compile.d.ts +147 -0
- package/src/lib/jobs/ai-site-import-compile.js +1143 -0
- package/src/lib/jobs/ai-site-import-compile.js.map +1 -0
- package/src/lib/jobs/ai-site-import-document.d.ts +9 -36
- package/src/lib/jobs/ai-site-import-document.js +23 -489
- package/src/lib/jobs/ai-site-import-document.js.map +1 -1
- package/src/lib/jobs/ai-site-import-look.d.ts +54 -7
- package/src/lib/jobs/ai-site-import-look.js +163 -52
- package/src/lib/jobs/ai-site-import-look.js.map +1 -1
- package/src/lib/jobs/ai-site-import-publish.d.ts +7 -1
- package/src/lib/jobs/ai-site-import-publish.js +19 -5
- package/src/lib/jobs/ai-site-import-publish.js.map +1 -1
- package/src/lib/jobs/ai-site-late-photos.js +4 -2
- package/src/lib/jobs/ai-site-late-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-publish.d.ts +10 -1
- package/src/lib/jobs/ai-site-publish.js +8 -3
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js +677 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl4092-1029-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +26 -0
- package/src/lib/layout-language/ai-layout-compiler.js +677 -33
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame-hollows.js +5 -1
- package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame-source.d.ts +196 -0
- package/src/lib/layout-language/ai-layout-frame-source.js +726 -0
- package/src/lib/layout-language/ai-layout-frame-source.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +22 -0
- package/src/lib/layout-language/ai-layout-frame.js +121 -29
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +103 -37
- package/src/lib/layout-language/ai-layout-language.js +85 -120
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +11 -7
- package/src/lib/model/ai-credit-estimate.js +11 -7
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-edit-job.d.ts +33 -16
- package/src/lib/model/ai-edit-job.js +50 -34
- package/src/lib/model/ai-edit-job.js.map +1 -1
- package/src/lib/model/ai-job-activity.d.ts +6 -11
- package/src/lib/model/ai-job-activity.js +8 -15
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +6 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-import.d.ts +307 -13
- package/src/lib/model/ai-site-import.js +227 -19
- package/src/lib/model/ai-site-import.js.map +1 -1
- package/src/lib/model/ai-site-inventory.d.ts +6 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -1
- package/src/lib/model/ai-site-look.d.ts +65 -1
- package/src/lib/model/ai-site-look.js +141 -23
- package/src/lib/model/ai-site-look.js.map +1 -1
- package/src/lib/model/ai-site-photos.d.ts +2 -0
- package/src/lib/model/ai-site-photos.js.map +1 -1
- package/src/lib/model/ai-site-start-steps.d.ts +4 -3
- package/src/lib/model/ai-site-start-steps.js +11 -3
- package/src/lib/model/ai-site-start-steps.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +23 -2
- package/src/lib/model/ai-site-start.js +25 -3
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/assist-edit.d.ts +18 -1
- package/src/lib/model/assist-edit.js +7 -0
- package/src/lib/model/assist-edit.js.map +1 -1
- package/src/lib/model/assist-page-change.d.ts +86 -0
- package/src/lib/model/assist-page-change.js +86 -0
- package/src/lib/model/assist-page-change.js.map +1 -0
- package/src/lib/providers/routing.d.ts +11 -0
- package/src/lib/providers/routing.js +23 -0
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +4 -2
- package/src/lib/runtime/ai-doctrine-validators.js +7 -2
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-eval.js +3 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/ai-icon-library.d.ts +4 -0
- package/src/lib/runtime/ai-icon-library.js +4 -0
- package/src/lib/runtime/ai-icon-library.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +5 -0
- package/src/lib/runtime/ai-node-tree.js +23 -4
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/runtime/ai-palette.d.ts +2 -0
- package/src/lib/runtime/ai-palette.generated.js +19 -3
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-palette.js +2 -1
- package/src/lib/runtime/ai-palette.js.map +1 -1
- package/src/lib/runtime/site-inventory.d.ts +8 -1
- package/src/lib/runtime/site-inventory.js +18 -0
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server/assist-build.js +2 -0
- package/src/lib/server/assist-build.js.map +1 -1
- package/src/lib/server/assist-chat.js +51 -2
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.d.ts +54 -2
- package/src/lib/server/assist-edit.js +219 -30
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-page-change.d.ts +62 -0
- package/src/lib/server/assist-page-change.js +140 -0
- package/src/lib/server/assist-page-change.js.map +1 -0
- package/src/lib/site-import/fixtures/site-layout-recordings.d.ts +50 -0
- package/src/lib/site-import/fixtures/site-layout-recordings.js +86 -0
- package/src/lib/site-import/fixtures/site-layout-recordings.js.map +1 -0
- package/src/lib/site-import/site-import-crawl.d.ts +18 -1
- package/src/lib/site-import/site-import-crawl.js +70 -10
- package/src/lib/site-import/site-import-crawl.js.map +1 -1
- package/src/lib/site-import/site-import-css.d.ts +110 -0
- package/src/lib/site-import/site-import-css.js +826 -0
- package/src/lib/site-import/site-import-css.js.map +1 -0
- package/src/lib/site-import/site-import-html.d.ts +116 -1
- package/src/lib/site-import/site-import-html.js +538 -46
- package/src/lib/site-import/site-import-html.js.map +1 -1
- package/src/lib/site-import/site-import-layout.d.ts +79 -0
- package/src/lib/site-import/site-import-layout.js +1608 -0
- package/src/lib/site-import/site-import-layout.js.map +1 -0
- package/src/lib/site-import/site-import-nav.d.ts +40 -0
- package/src/lib/site-import/site-import-nav.js +437 -0
- package/src/lib/site-import/site-import-nav.js.map +1 -0
- package/src/lib/site-import/site-import-page.d.ts +8 -1
- package/src/lib/site-import/site-import-page.js +24 -2
- package/src/lib/site-import/site-import-page.js.map +1 -1
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/site-import/site-import-review.d.ts +0 -40
- package/src/lib/site-import/site-import-review.js +0 -149
- package/src/lib/site-import/site-import-review.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-import-start.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal, PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport type { ConsolePendingSite } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiWebSync } from '@aglyn/shared-data-mdi'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { Alert, Box, Button, Stack, TextField, Typography } from '@mui/material'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useRef, useState } from 'react'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_SITE_IMPORT_DOMAIN_INPUT, AI_SITE_IMPORT_KIND, AI_SITE_IMPORT_WAVE_PAGES } from '../model/ai-site-import'\nimport type { AiSiteImportClaim } from '../model/ai-site-import-view'\nimport { aiSiteBuildHref } from './ai-job-links'\nimport { publishAiJob } from './ai-jobs-store'\nimport { AiSiteOwnershipProof, postAiSiteOwnership } from './ai-site-ownership-proof.component'\n\n/** Each part of the flow links its own section of the Bring my site guide. */\nexport const AI_SITE_IMPORT_HELP = {\n address: pluginDocsHelp('aiImport', {\n anchor: '#your-current-website',\n excerpt: 'The address people type to reach your site today. You prove it is yours next, so only a site you own can be brought in.',\n }),\n prove: pluginDocsHelp('aiImport', {\n anchor: '#prove-it-is-yours',\n excerpt: 'Add a DNS record, add a tag to your home page, or get a code at an address at your domain. Any one is enough.',\n }),\n waves: pluginDocsHelp('aiImport', {\n anchor: '#waves',\n excerpt: 'Your main pages come in first, then each collection, such as blog posts, ten pages at a time. You review each wave and start the next yourself.',\n }),\n turnedAway: pluginDocsHelp('aiImport', {\n anchor: '#turned-away',\n excerpt: 'Allow AglynBot in your site’s bot protection or firewall settings, then choose Check again. Reading your site again uses no AI credits.',\n }),\n}\n\ntype Step = 'address' | 'prove' | 'read'\n\nexport interface AiSiteImportStartProps {\n orgId: string\n orgSlug: string | null\n hostId: string | null\n host: string | null\n user: MaybeTokenSource\n /** The site being created by \"Create site\", when it does not exist yet (AGL-3761). */\n pendingSite?: ConsolePendingSite\n /** Back to how the site starts. */\n onBack: () => void\n /** The dialog closes before the job's page opens. */\n leave?: () => void\n}\n\n/**\n * \"Bring my site\" (AGL-3976): the address of the site the person has now,\n * the proof that it is theirs, and what happens next — then the site is read\n * and its waves planned, nothing built, on the import job's own page.\n *\n * Nothing is created until \"Read my site\": the site in Create site is made\n * then, empty, and the import job is started on it. The job reads the site\n * and waits for the person to start its first wave, so even this costs no\n * AI credits.\n */\nexport function AiSiteImportStart({ orgId, orgSlug, hostId, host, user, pendingSite, onBack, leave }: AiSiteImportStartProps) {\n const router = useRouter()\n const userRef = useRef(user)\n userRef.current = user\n const [step, setStep] = useState<Step>('address')\n const [address, setAddress] = useState('')\n const [claim, setClaim] = useState<AiSiteImportClaim | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n // A site already verified skips the proof step, and Back skips it too.\n const [proved, setProved] = useState(false)\n\n const claimIt = useCallback(async () => {\n setBusy(true)\n setNotice(null)\n const answer = await postAiSiteOwnership(userRef.current, { orgId, action: 'claim', domain: address })\n setBusy(false)\n if (!answer.claim) {\n setNotice(answer.message ?? 'That address could not be used.')\n return\n }\n setClaim(answer.claim)\n setProved(!answer.claim.current)\n setStep(answer.claim.current ? 'read' : 'prove')\n }, [orgId, address])\n\n const read = useCallback(async () => {\n if (!claim?.current) return\n setBusy(true)\n setNotice(null)\n try {\n const requestJob = (siteId: string | null, check: boolean) =>\n authorizedFetch(userRef.current, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId: siteId,\n kind: AI_SITE_IMPORT_KIND,\n brief: `Bring in ${claim.domain}`,\n inputs: { [AI_SITE_IMPORT_DOMAIN_INPUT]: claim.domain },\n ...(check ? { check: true } : {}),\n }),\n })\n const refused = async (response: Response): Promise<Record<string, unknown> | null> => {\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (response.ok) return payload ?? {}\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(locked ? lockdownRefusalText(locked) : String(payload?.['error'] ?? 'Your site could not be read. Try again.'))\n return null\n }\n let site = { hostId, host, orgSlug }\n if (!hostId && pendingSite) {\n // Asked before the site exists, so a refusal creates nothing (AGL-3859).\n if (!pendingSite.created && !(await refused(await requestJob(null, true)))) return\n // A site brought in starts in preview unless the person switched it\n // off (AGL-4086): its pages arrive here before anyone has looked.\n const made = await pendingSite.create({ start: 'import' })\n if ('error' in made) {\n setNotice(made.error)\n if (made.address) onBack()\n return\n }\n site = { hostId: made.hostId, host: made.host, orgSlug: made.orgSlug || orgSlug }\n }\n if (!site.hostId) return\n const payload = await refused(await requestJob(site.hostId, false))\n const job = (payload?.['job'] as AiJobSummary | undefined) ?? null\n if (!job) {\n if (payload) setNotice('Your site could not be read. Try again.')\n return\n }\n publishAiJob(job)\n const href = aiSiteBuildHref(site.orgSlug, site.host, job.id)\n if (href) {\n leave?.()\n router.push(href)\n }\n } catch {\n setNotice('Your site could not be read. Try again.')\n } finally {\n setBusy(false)\n }\n }, [claim, orgId, hostId, host, orgSlug, pendingSite, onBack, leave, router])\n\n const back = () => {\n setNotice(null)\n if (step === 'address') onBack()\n else if (step === 'prove') setStep('address')\n else setStep(proved ? 'prove' : 'address')\n }\n\n return (\n <Stack spacing={3} component=\"section\" aria-label=\"Bring my site\" data-start-area=\"import\">\n {notice && <Alert severity=\"info\">{notice}</Alert>}\n {step === 'address' && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {'Your current website'}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.address} />\n </Stack>\n <TextField\n label=\"Website address\"\n placeholder=\"example.com\"\n value={address}\n autoFocus\n onChange={(event) => setAddress(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && address.trim() && !busy) {\n event.preventDefault()\n void claimIt()\n }\n }}\n helperText=\"The address people type to reach your site today. You prove it is yours next.\"\n />\n </Stack>\n )}\n {step === 'prove' && claim && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {'Prove it is yours'}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.prove} />\n </Stack>\n <AiSiteOwnershipProof orgId={orgId} user={user} claim={claim} onClaim={setClaim} />\n </Stack>\n )}\n {step === 'read' && claim && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {`Bring in ${claim.domain}`}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.waves} />\n </Stack>\n <Box component=\"ul\" sx={{ m: 0, pl: 3, '& li': { mb: 1 } }}>\n <Typography component=\"li\" variant=\"body2\">\n {`AglynBot reads your whole site, home page first, as many pages as your plan includes: your main pages first, then collections such as blog posts.`}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {`You see what was found, what could not be read and why, and what each wave of up to ${AI_SITE_IMPORT_WAVE_PAGES} pages costs before anything is built. Reading your site uses no AI credits.`}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {'If your home page cannot be read, nothing is planned and no AI credits are used. You are told why, and you check again once it can be.'}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {`${PLATFORM_BRAND_NAME} AI rewrites each page into your new site’s design, with its words, facts and photos. You review each wave and start the next yourself.`}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {'Every page is a draft. Nothing is published until you publish it, and your current site is not changed.'}\n </Typography>\n </Box>\n {/* Start in preview (AGL-4086), for a site this creates: on unless\n the person switches it off. */}\n {!hostId && pendingSite && !pendingSite.created\n ? pendingSite.previewControl?.('import')\n : null}\n </Stack>\n )}\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'space-between' }}>\n <Button onClick={back} disabled={busy}>\n {'Back'}\n </Button>\n {step === 'address' && (\n <Button variant=\"contained\" disabled={busy || !address.trim()} onClick={() => void claimIt()}>\n {busy ? 'Checking…' : 'Next'}\n </Button>\n )}\n {step === 'prove' && (\n <Button variant=\"contained\" disabled={!claim?.current} onClick={() => setStep('read')}>\n {'Next'}\n </Button>\n )}\n {step === 'read' && (\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={busy || !claim?.current}\n onClick={() => void read()}\n startIcon={<MdiIcon path={mdiWebSync.path} />}\n >\n {busy ? 'Starting…' : 'Read my site'}\n </Button>\n )}\n </Stack>\n </Stack>\n )\n}\n\nexport default AiSiteImportStart\n"],"names":["lockdownRefusalText","parseLockdownRefusal","PLATFORM_BRAND_NAME","pluginDocsHelp","mdiWebSync","HelpTip","MdiIcon","authorizedFetch","Alert","Box","Button","Stack","TextField","Typography","useRouter","useCallback","useRef","useState","AI_SITE_IMPORT_DOMAIN_INPUT","AI_SITE_IMPORT_KIND","AI_SITE_IMPORT_WAVE_PAGES","aiSiteBuildHref","publishAiJob","AiSiteOwnershipProof","postAiSiteOwnership","AI_SITE_IMPORT_HELP","address","anchor","excerpt","prove","waves","turnedAway","AiSiteImportStart","orgId","orgSlug","hostId","host","user","pendingSite","onBack","leave","router","userRef","current","step","setStep","setAddress","claim","setClaim","notice","setNotice","busy","setBusy","proved","setProved","claimIt","answer","action","domain","message","read","requestJob","siteId","check","method","headers","body","JSON","stringify","kind","brief","inputs","refused","response","payload","json","catch","ok","locked","status","String","site","created","made","create","start","error","job","href","id","push","back","spacing","component","aria-label","data-start-area","severity","direction","sx","alignItems","variant","label","placeholder","value","autoFocus","onChange","event","target","onKeyDown","key","trim","preventDefault","helperText","onClaim","m","pl","mb","previewControl","justifyContent","onClick","disabled","size","startIcon","path"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-import-start.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal, PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport type { ConsolePendingSite } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiWebSync } from '@aglyn/shared-data-mdi'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { authorizedFetch, type MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { Alert, Box, Button, Stack, TextField, Typography } from '@mui/material'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useRef, useState } from 'react'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_SITE_IMPORT_DOMAIN_INPUT, AI_SITE_IMPORT_KIND, AI_SITE_IMPORT_WAVE_PAGES } from '../model/ai-site-import'\nimport type { AiSiteImportClaim } from '../model/ai-site-import-view'\nimport { aiSiteBuildHref } from './ai-job-links'\nimport { publishAiJob } from './ai-jobs-store'\nimport { AiSiteOwnershipProof, postAiSiteOwnership } from './ai-site-ownership-proof.component'\n\n/** Each part of the flow links its own section of the Bring my site guide. */\nexport const AI_SITE_IMPORT_HELP = {\n address: pluginDocsHelp('aiImport', {\n anchor: '#your-current-website',\n excerpt: 'The address people type to reach your site today. You prove it is yours next, so only a site you own can be brought in.',\n }),\n prove: pluginDocsHelp('aiImport', {\n anchor: '#prove-it-is-yours',\n excerpt: 'Add a DNS record, add a tag to your home page, or get a code at an address at your domain. Any one is enough.',\n }),\n waves: pluginDocsHelp('aiImport', {\n anchor: '#waves',\n excerpt: 'Your main pages come in first, then each collection, such as blog posts, ten pages at a time. You review each wave and start the next yourself.',\n }),\n turnedAway: pluginDocsHelp('aiImport', {\n anchor: '#turned-away',\n excerpt: 'Allow AglynBot in your site’s bot protection or firewall settings, then choose Check again. Reading your site again uses no AI credits.',\n }),\n}\n\ntype Step = 'address' | 'prove' | 'read'\n\nexport interface AiSiteImportStartProps {\n orgId: string\n orgSlug: string | null\n hostId: string | null\n host: string | null\n user: MaybeTokenSource\n /** The site being created by \"Create site\", when it does not exist yet (AGL-3761). */\n pendingSite?: ConsolePendingSite\n /** Back to how the site starts. */\n onBack: () => void\n /** The dialog closes before the job's page opens. */\n leave?: () => void\n}\n\n/**\n * \"Bring my site\" (AGL-3976): the address of the site the person has now,\n * the proof that it is theirs, and what happens next — then the site is read\n * and its waves planned, nothing built, on the import job's own page.\n *\n * Nothing is created until \"Read my site\": the site in Create site is made\n * then, empty, and the import job is started on it. The job reads the site\n * and waits for the person to start its first wave, so even this costs no\n * AI credits.\n */\nexport function AiSiteImportStart({ orgId, orgSlug, hostId, host, user, pendingSite, onBack, leave }: AiSiteImportStartProps) {\n const router = useRouter()\n const userRef = useRef(user)\n userRef.current = user\n const [step, setStep] = useState<Step>('address')\n const [address, setAddress] = useState('')\n const [claim, setClaim] = useState<AiSiteImportClaim | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n // A site already verified skips the proof step, and Back skips it too.\n const [proved, setProved] = useState(false)\n\n const claimIt = useCallback(async () => {\n setBusy(true)\n setNotice(null)\n const answer = await postAiSiteOwnership(userRef.current, { orgId, action: 'claim', domain: address })\n setBusy(false)\n if (!answer.claim) {\n setNotice(answer.message ?? 'That address could not be used.')\n return\n }\n setClaim(answer.claim)\n setProved(!answer.claim.current)\n setStep(answer.claim.current ? 'read' : 'prove')\n }, [orgId, address])\n\n const read = useCallback(async () => {\n if (!claim?.current) return\n setBusy(true)\n setNotice(null)\n try {\n const requestJob = (siteId: string | null, check: boolean) =>\n authorizedFetch(userRef.current, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId: siteId,\n kind: AI_SITE_IMPORT_KIND,\n brief: `Bring in ${claim.domain}`,\n inputs: { [AI_SITE_IMPORT_DOMAIN_INPUT]: claim.domain },\n ...(check ? { check: true } : {}),\n }),\n })\n const refused = async (response: Response): Promise<Record<string, unknown> | null> => {\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (response.ok) return payload ?? {}\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(locked ? lockdownRefusalText(locked) : String(payload?.['error'] ?? 'Your site could not be read. Try again.'))\n return null\n }\n let site = { hostId, host, orgSlug }\n if (!hostId && pendingSite) {\n // Asked before the site exists, so a refusal creates nothing (AGL-3859).\n if (!pendingSite.created && !(await refused(await requestJob(null, true)))) return\n // A site brought in starts in preview unless the person switched it\n // off (AGL-4086): its pages arrive here before anyone has looked.\n const made = await pendingSite.create({ start: 'import' })\n if ('error' in made) {\n setNotice(made.error)\n if (made.address) onBack()\n return\n }\n site = { hostId: made.hostId, host: made.host, orgSlug: made.orgSlug || orgSlug }\n }\n if (!site.hostId) return\n const payload = await refused(await requestJob(site.hostId, false))\n const job = (payload?.['job'] as AiJobSummary | undefined) ?? null\n if (!job) {\n if (payload) setNotice('Your site could not be read. Try again.')\n return\n }\n publishAiJob(job)\n const href = aiSiteBuildHref(site.orgSlug, site.host, job.id)\n if (href) {\n leave?.()\n router.push(href)\n }\n } catch {\n setNotice('Your site could not be read. Try again.')\n } finally {\n setBusy(false)\n }\n }, [claim, orgId, hostId, host, orgSlug, pendingSite, onBack, leave, router])\n\n const back = () => {\n setNotice(null)\n if (step === 'address') onBack()\n else if (step === 'prove') setStep('address')\n else setStep(proved ? 'prove' : 'address')\n }\n\n return (\n <Stack spacing={3} component=\"section\" aria-label=\"Bring my site\" data-start-area=\"import\">\n {notice && <Alert severity=\"info\">{notice}</Alert>}\n {step === 'address' && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {'Your current website'}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.address} />\n </Stack>\n <TextField\n label=\"Website address\"\n placeholder=\"example.com\"\n value={address}\n autoFocus\n onChange={(event) => setAddress(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && address.trim() && !busy) {\n event.preventDefault()\n void claimIt()\n }\n }}\n helperText=\"The address people type to reach your site today. You prove it is yours next.\"\n />\n </Stack>\n )}\n {step === 'prove' && claim && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {'Prove it is yours'}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.prove} />\n </Stack>\n <AiSiteOwnershipProof orgId={orgId} user={user} claim={claim} onClaim={setClaim} />\n </Stack>\n )}\n {step === 'read' && claim && (\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h2\">\n {`Bring in ${claim.domain}`}\n </Typography>\n <HelpTip {...AI_SITE_IMPORT_HELP.waves} />\n </Stack>\n <Box component=\"ul\" sx={{ m: 0, pl: 3, '& li': { mb: 1 } }}>\n <Typography component=\"li\" variant=\"body2\">\n {`AglynBot reads your whole site, home page first, as many pages as your plan includes: your main pages first, then collections such as blog posts.`}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {`You see what was found, what could not be read and why, and what each wave of up to ${AI_SITE_IMPORT_WAVE_PAGES} pages costs before anything is built. Reading your site uses no AI credits.`}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {'If your home page cannot be read, nothing is planned and no AI credits are used. You are told why, and you check again once it can be.'}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {'Each page keeps every word as you wrote it and is laid out as your page is: its sections, columns, cards, icons, pictures, tables and tabs, in your site’s own look. You review each wave and start the next yourself.'}\n </Typography>\n <Typography component=\"li\" variant=\"body2\">\n {'Each wave lands in your new site’s preview, where only you and your team can see it, until you make the site public. A site not in preview keeps its pages as drafts. Your current site is not changed.'}\n </Typography>\n </Box>\n {/* Start in preview (AGL-4086), for a site this creates: on unless\n the person switches it off. */}\n {!hostId && pendingSite && !pendingSite.created\n ? pendingSite.previewControl?.('import')\n : null}\n </Stack>\n )}\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'space-between' }}>\n <Button onClick={back} disabled={busy}>\n {'Back'}\n </Button>\n {step === 'address' && (\n <Button variant=\"contained\" disabled={busy || !address.trim()} onClick={() => void claimIt()}>\n {busy ? 'Checking…' : 'Next'}\n </Button>\n )}\n {step === 'prove' && (\n <Button variant=\"contained\" disabled={!claim?.current} onClick={() => setStep('read')}>\n {'Next'}\n </Button>\n )}\n {step === 'read' && (\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={busy || !claim?.current}\n onClick={() => void read()}\n startIcon={<MdiIcon path={mdiWebSync.path} />}\n >\n {busy ? 'Starting…' : 'Read my site'}\n </Button>\n )}\n </Stack>\n </Stack>\n )\n}\n\nexport default AiSiteImportStart\n"],"names":["lockdownRefusalText","parseLockdownRefusal","pluginDocsHelp","mdiWebSync","HelpTip","MdiIcon","authorizedFetch","Alert","Box","Button","Stack","TextField","Typography","useRouter","useCallback","useRef","useState","AI_SITE_IMPORT_DOMAIN_INPUT","AI_SITE_IMPORT_KIND","AI_SITE_IMPORT_WAVE_PAGES","aiSiteBuildHref","publishAiJob","AiSiteOwnershipProof","postAiSiteOwnership","AI_SITE_IMPORT_HELP","address","anchor","excerpt","prove","waves","turnedAway","AiSiteImportStart","orgId","orgSlug","hostId","host","user","pendingSite","onBack","leave","router","userRef","current","step","setStep","setAddress","claim","setClaim","notice","setNotice","busy","setBusy","proved","setProved","claimIt","answer","action","domain","message","read","requestJob","siteId","check","method","headers","body","JSON","stringify","kind","brief","inputs","refused","response","payload","json","catch","ok","locked","status","String","site","created","made","create","start","error","job","href","id","push","back","spacing","component","aria-label","data-start-area","severity","direction","sx","alignItems","variant","label","placeholder","value","autoFocus","onChange","event","target","onKeyDown","key","trim","preventDefault","helperText","onClaim","m","pl","mb","previewControl","justifyContent","onClick","disabled","size","startIcon","path"],"mappings":"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"}
|
|
@@ -44,5 +44,5 @@ export type AiSiteStartCardProps = ConsoleHostFirstRunZoneProps & {
|
|
|
44
44
|
* `aiSiteStartBrief` and `aiSiteStartInputs`. Each step is reported as a
|
|
45
45
|
* funnel, with where people struggle (`ai-site-start-tracking.ts`).
|
|
46
46
|
*/
|
|
47
|
-
export declare function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, pendingSite, clientBuild, initialAnswers, }: AiSiteStartCardProps): import("react").JSX.Element;
|
|
47
|
+
export declare function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, pendingSite, chooseStarter: chooseStarterInShell, clientBuild, initialAnswers, }: AiSiteStartCardProps): import("react").JSX.Element;
|
|
48
48
|
export default AiSiteStartCard;
|
|
@@ -23,6 +23,7 @@ import { mdiCreation, mdiPageLayoutHeaderFooter, mdiWebSync } from "@aglyn/share
|
|
|
23
23
|
import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
|
|
24
24
|
import { HelpTip, MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
25
25
|
import BlockedControl from "@aglyn/shared-ui-jsx/components/blocked-control.component";
|
|
26
|
+
import { OptionCardGrid } from "@aglyn/shared-ui-jsx/components/option-card-grid.component";
|
|
26
27
|
import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
|
|
27
28
|
import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
28
29
|
import { useUser } from "@aglyn/tenant-feature-instance";
|
|
@@ -34,12 +35,12 @@ import { AI_JOB_AUTO_CONFIRM_INPUT, AI_SITE_FREE_PAGES, aiFreeCreditsNoneLeftTex
|
|
|
34
35
|
import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
|
|
35
36
|
import { AI_CREDITS_CONFIRM_CODE, aiCreditRangeText } from "../model/ai-credit-estimate.js";
|
|
36
37
|
import { AiCreditsPromptNotice } from "./ai-credits-prompt.component.js";
|
|
37
|
-
import { AI_SITE_START_ANSWERS, aiSiteStartAnswersFromClientBuild, aiSiteStartBrief, aiSiteStartClientBrief, aiSiteStartClientInputs, aiSiteStartClientNote, aiSiteStartExtrasGiven, aiSiteStartInputs, aiSiteStartRefusal } from "../model/ai-site-start.js";
|
|
38
|
+
import { AI_SITE_START_ANSWERS, AI_SITE_START_STYLE_REQUIRED, aiSiteStartAnswersFromClientBuild, aiSiteStartBrief, aiSiteStartClientBrief, aiSiteStartClientInputs, aiSiteStartClientNote, aiSiteStartExtrasGiven, aiSiteStartInputs, aiSiteStartKind, aiSiteStartRefusal } from "../model/ai-site-start.js";
|
|
38
39
|
import { aiSiteInspirationLimit } from "../model/ai-site-inspiration.js";
|
|
39
40
|
import { aiSiteStartFieldErrors, aiSiteStartFirstInvalidStep, aiSiteStartNextStep, aiSiteStartPreviousStep, aiSiteStartStepErrors, aiSiteStartStepIndex, AI_SITE_START_STEPS, AI_SITE_START_STEP_FIELDS } from "../model/ai-site-start-steps.js";
|
|
40
41
|
import { aiSiteKindOfInputs } from "../model/ai-site-kinds.js";
|
|
41
42
|
import { aiSiteStartClickOf, useAiSiteStartTracking } from "./ai-site-start-tracking.js";
|
|
42
|
-
import { AudienceStep, DetailsStep, KindStep, MoreDetails, ReviewStep, StartProgress, StepHelp, StyleStep } from "./ai-site-start-steps.component.js";
|
|
43
|
+
import { aiSiteStyleCards, AudienceStep, DetailsStep, KindStep, MoreDetails, ReviewStep, StartProgress, StepHelp, StyleStep } from "./ai-site-start-steps.component.js";
|
|
43
44
|
import { AiJobFollow } from "./ai-job-follow.component.js";
|
|
44
45
|
import { AiModelSelector } from "./ai-model-selector.component.js";
|
|
45
46
|
import { useAiModelChoice } from "./use-ai-model-choice.js";
|
|
@@ -163,7 +164,7 @@ import { aiSiteImportOfferOf } from "../model/ai-site-import-view.js";
|
|
|
163
164
|
*/ const START_HELP = {
|
|
164
165
|
choose: pluginDocsHelp('aiStart', {
|
|
165
166
|
anchor: '#how-do-you-want-to-start',
|
|
166
|
-
excerpt: 'The starter site gives you a ready-made home page to edit. Start with AI asks a few questions, then plans, writes and publishes your pages.'
|
|
167
|
+
excerpt: 'The starter site gives you a ready-made home page to edit, in a style you choose. Start with AI asks a few questions, then plans, writes and publishes your pages.'
|
|
167
168
|
}),
|
|
168
169
|
estimate: pluginDocsHelp('aiCredits', {
|
|
169
170
|
anchor: '#before-a-job-starts',
|
|
@@ -202,9 +203,9 @@ function SectionLabel({ children, help }) {
|
|
|
202
203
|
* held, and only the review turns them into the job, through the same
|
|
203
204
|
* `aiSiteStartBrief` and `aiSiteStartInputs`. Each step is reported as a
|
|
204
205
|
* funnel, with where people struggle (`ai-site-start-tracking.ts`).
|
|
205
|
-
*/ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, pendingSite, clientBuild, initialAnswers = null }) {
|
|
206
|
-
var _ref, _ref1, _ref2, _ref3, _aiFreeSitePrompt;
|
|
207
|
-
var _aiSiteKindOfInputs, _modelChoice_options_options_find, _modelChoice_options;
|
|
206
|
+
*/ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, pendingSite, chooseStarter: chooseStarterInShell, clientBuild, initialAnswers = null }) {
|
|
207
|
+
var _ref, _ref1, _ref2, _ref3, _aiFreeSitePrompt, _aiSiteStartRefusal;
|
|
208
|
+
var _aiSiteKindOfInputs, _modelChoice_options_options_find, _modelChoice_options, _pendingSite_previewControl;
|
|
208
209
|
const { data: user } = useUser();
|
|
209
210
|
const router = useRouter();
|
|
210
211
|
// Held in a ref so a request reads WHO is signed in, never the identity of
|
|
@@ -248,6 +249,10 @@ function SectionLabel({ children, help }) {
|
|
|
248
249
|
const [busy, setBusy] = useState(false);
|
|
249
250
|
// The starter card's own busy state while `startBlank` runs (AGL-3594).
|
|
250
251
|
const [startingStarter, setStartingStarter] = useState(false);
|
|
252
|
+
// The starter card's style choice (AGL-4049): drawn after the starter card
|
|
253
|
+
// is clicked, with nothing chosen until a card is.
|
|
254
|
+
const [pickingStyle, setPickingStyle] = useState(false);
|
|
255
|
+
const [starterStyle, setStarterStyle] = useState(null);
|
|
251
256
|
const [notice, setNotice] = useState(null);
|
|
252
257
|
/** The site job "Plan my site" started, as the create door answered with it. */ const [started, setStarted] = useState(null);
|
|
253
258
|
// The Free taste's page band (AGL-3594), read off the verdict request.
|
|
@@ -340,9 +345,10 @@ function SectionLabel({ children, help }) {
|
|
|
340
345
|
siteKind
|
|
341
346
|
})) != null ? _aiFreeSitePrompt : serverPrompt : null;
|
|
342
347
|
const noneLeft = freeTaste && freeCredits !== null && freeCredits.left <= 0;
|
|
343
|
-
|
|
348
|
+
// The door's refusal, else the questions' own: a style not yet chosen (AGL-4049).
|
|
349
|
+
const refusal = (_aiSiteStartRefusal = aiSiteStartRefusal(answers, {
|
|
344
350
|
freeTaste
|
|
345
|
-
});
|
|
351
|
+
})) != null ? _aiSiteStartRefusal : answers.style === null ? AI_SITE_START_STYLE_REQUIRED : null;
|
|
346
352
|
const band = aiSitePagesBand(freeTaste);
|
|
347
353
|
// On a paid plan the person picks the model that builds the site (AGL-3660),
|
|
348
354
|
// Auto by default, from the models their plan allows; every step of the job
|
|
@@ -371,7 +377,7 @@ function SectionLabel({ children, help }) {
|
|
|
371
377
|
}) : answers;
|
|
372
378
|
if (!orgId || aiSiteStartRefusal(asked, {
|
|
373
379
|
freeTaste
|
|
374
|
-
}) || noneLeft) return;
|
|
380
|
+
}) || asked.style === null || noneLeft) return;
|
|
375
381
|
// Past what is left, only an explicit go-ahead starts it.
|
|
376
382
|
if (freeTaste && !options.creditsConfirmed && aiFreeSitePrompt(freeCredits, asked.pages, {
|
|
377
383
|
siteKind
|
|
@@ -442,7 +448,10 @@ function SectionLabel({ children, help }) {
|
|
|
442
448
|
};
|
|
443
449
|
if (!hostId && pendingSite) {
|
|
444
450
|
if (!pendingSite.created && !await refused(await requestJob(null, true))) return;
|
|
445
|
-
|
|
451
|
+
// The style the questions took (AGL-4049), recorded on the site.
|
|
452
|
+
const made = await pendingSite.create(asked.style ? {
|
|
453
|
+
style: asked.style
|
|
454
|
+
} : undefined);
|
|
446
455
|
if ('error' in made) {
|
|
447
456
|
setNotice(made.error);
|
|
448
457
|
if (made.address) setStep('choose');
|
|
@@ -522,33 +531,54 @@ function SectionLabel({ children, help }) {
|
|
|
522
531
|
clientIntake,
|
|
523
532
|
siteInspiration
|
|
524
533
|
]);
|
|
525
|
-
// The zone's `startBlank
|
|
526
|
-
//
|
|
527
|
-
// address to fix, which
|
|
528
|
-
|
|
529
|
-
|
|
534
|
+
// The zone's `startBlank`, with the style chosen for the starter (AGL-4049).
|
|
535
|
+
// Before the site exists it creates it with the starter, and answers
|
|
536
|
+
// `false` when it could not — most often a name or address to fix, which
|
|
537
|
+
// step 1 shows.
|
|
538
|
+
const runStartBlank = useCallback((options)=>{
|
|
539
|
+
const result = startBlank((options == null ? void 0 : options.style) ? {
|
|
540
|
+
style: options.style
|
|
541
|
+
} : undefined);
|
|
530
542
|
if (result && typeof result.then === 'function') {
|
|
531
543
|
void result.then((done)=>{
|
|
532
544
|
if (done) return;
|
|
533
545
|
setStartingStarter(false);
|
|
546
|
+
setPickingStyle(false);
|
|
534
547
|
setStep('choose');
|
|
535
548
|
});
|
|
536
549
|
}
|
|
537
550
|
}, [
|
|
538
551
|
startBlank
|
|
539
552
|
]);
|
|
553
|
+
// The starter card asks a style first (AGL-4049): nothing is created, and
|
|
554
|
+
// nothing chosen, until a style card is clicked and Create site with it.
|
|
555
|
+
// Where the shell offers "Choose your starter" — the platform's styles and
|
|
556
|
+
// the marketplace's starters together — the card hands the choice to it
|
|
557
|
+
// instead, and asks no style itself.
|
|
540
558
|
const chooseStarter = useCallback(()=>{
|
|
541
559
|
if (pendingSite && !pendingSite.created && !pendingSite.check()) return;
|
|
542
|
-
setStartingStarter(true);
|
|
543
560
|
trackEvent('site_start_choice', {
|
|
544
561
|
choice: 'starter'
|
|
545
562
|
});
|
|
563
|
+
if (chooseStarterInShell && pendingSite && !pendingSite.created) return chooseStarterInShell();
|
|
564
|
+
setPickingStyle(true);
|
|
565
|
+
}, [
|
|
566
|
+
chooseStarterInShell,
|
|
567
|
+
pendingSite
|
|
568
|
+
]);
|
|
569
|
+
const starterInShell = Boolean(chooseStarterInShell && pendingSite && !pendingSite.created);
|
|
570
|
+
const createStarter = useCallback(()=>{
|
|
571
|
+
if (!starterStyle || startingStarter) return;
|
|
572
|
+
setStartingStarter(true);
|
|
546
573
|
// The starter is a way to start, not a way to leave: no abandonment after it.
|
|
547
574
|
tracker.finish();
|
|
548
|
-
runStartBlank(
|
|
575
|
+
runStartBlank({
|
|
576
|
+
style: starterStyle
|
|
577
|
+
});
|
|
549
578
|
}, [
|
|
550
|
-
pendingSite,
|
|
551
579
|
runStartBlank,
|
|
580
|
+
starterStyle,
|
|
581
|
+
startingStarter,
|
|
552
582
|
tracker
|
|
553
583
|
]);
|
|
554
584
|
const chooseImport = useCallback(()=>{
|
|
@@ -648,9 +678,15 @@ function SectionLabel({ children, help }) {
|
|
|
648
678
|
setStep(target);
|
|
649
679
|
};
|
|
650
680
|
if (verdict !== 'ready') return null;
|
|
681
|
+
// The style a way out gives the starter on a site that exists (AGL-4049):
|
|
682
|
+
// the one the starter's style view or the questions took, if any.
|
|
683
|
+
const exitStyle = starterStyle != null ? starterStyle : answers.style !== null ? aiSiteStartKind(answers).id : null;
|
|
684
|
+
const giveStarter = ()=>runStartBlank(exitStyle ? {
|
|
685
|
+
style: exitStyle
|
|
686
|
+
} : undefined);
|
|
651
687
|
// Before a job is started Skip is the blank site, which writes the starter
|
|
652
688
|
// (AGL-3594); after, it only closes — the job builds the site.
|
|
653
|
-
const exit = started ? leave != null ? leave :
|
|
689
|
+
const exit = started ? leave != null ? leave : giveStarter : giveStarter;
|
|
654
690
|
// Skip, as the header draws it: before a site is started it is leaving the questions.
|
|
655
691
|
const skip = ()=>{
|
|
656
692
|
if (!started) tracker.abandon('skip');
|
|
@@ -659,10 +695,10 @@ function SectionLabel({ children, help }) {
|
|
|
659
695
|
// Escape and the close control. Before "Create site" has made the site
|
|
660
696
|
// (AGL-3761) there is nothing to give a starter to, so they only close,
|
|
661
697
|
// and nothing is created; otherwise they are the same way out as Skip.
|
|
662
|
-
const dismissTo = creating && !started ? leave != null ? leave :
|
|
698
|
+
const dismissTo = creating && !started ? leave != null ? leave : giveStarter : exit;
|
|
663
699
|
// Anything the person typed or picked, which a dismissal must not discard
|
|
664
700
|
// silently (AGL-3660). After a job starts there is nothing left to lose.
|
|
665
|
-
const drafted = !started && Boolean(answers.siteType.trim() || answers.audience.trim() || answers.
|
|
701
|
+
const drafted = !started && Boolean(answers.siteType.trim() || answers.audience.trim() || answers.style !== null || starterStyle !== null || aiSiteStartExtrasGiven(answers).length > 0 || creating && (pendingSite == null ? void 0 : pendingSite.dirty));
|
|
666
702
|
// Escape and the close control: a dismissal, never a choice. Escape that
|
|
667
703
|
// bubbled here through React from a portal outside this dialog's own DOM is
|
|
668
704
|
// a nested menu's, already handled there, and is not this dialog's to act on.
|
|
@@ -704,7 +740,9 @@ function SectionLabel({ children, help }) {
|
|
|
704
740
|
const estimateText = freeTaste ? freeCredits ? `${aiCreditRangeText(estimate)}. You have ${freeCredits.left.toLocaleString('en-US')} of your ${freeCredits.total.toLocaleString('en-US')} free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}` : `${aiCreditRangeText(estimate)}, of the ${FREE_AI_TASTE_CREDITS_PER_MONTH} AI credits you get free each month` : `${aiCreditRangeText(estimate)}, estimated`;
|
|
705
741
|
// The card is drawn wherever the workspace could use it, disabled where it cannot yet.
|
|
706
742
|
const showsImport = importAvailability.state === 'ready' || importAvailability.state === 'blocked';
|
|
707
|
-
|
|
743
|
+
// The starter's style view (AGL-4049), on step 1.
|
|
744
|
+
const stylingStarter = step === 'choose' && pickingStyle && !started && !importing;
|
|
745
|
+
const choosing = step === 'choose' && !pickingStyle && !started && !importing;
|
|
708
746
|
const reviewing = step === 'review' && !started && !importing;
|
|
709
747
|
const asking = step !== 'choose' && !started && !importing;
|
|
710
748
|
// Each answer's reason not to go forward, shown on a step once Next was refused there.
|
|
@@ -753,6 +791,9 @@ function SectionLabel({ children, help }) {
|
|
|
753
791
|
const heading = importing ? {
|
|
754
792
|
title: 'Bring my site',
|
|
755
793
|
lede: `Bring the website you have now into ${PLATFORM_BRAND_NAME}: its pages, words and photos. First, prove it is yours.`
|
|
794
|
+
} : stylingStarter ? {
|
|
795
|
+
title: 'Choose a style',
|
|
796
|
+
lede: 'Your site starts with a home page, a header and a footer in the style you choose. You can change everything later.'
|
|
756
797
|
} : HEADINGS[step];
|
|
757
798
|
// Enter in a text answer is Next. A select, a card or a button keeps its own Enter.
|
|
758
799
|
const onStepKeyDown = (event)=>{
|
|
@@ -821,7 +862,7 @@ function SectionLabel({ children, help }) {
|
|
|
821
862
|
},
|
|
822
863
|
children: 'Start your site'
|
|
823
864
|
}),
|
|
824
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
865
|
+
creating && !started ? null : /*#__PURE__*/ _jsx(Button, {
|
|
825
866
|
color: "inherit",
|
|
826
867
|
onClick: skip,
|
|
827
868
|
"aria-label": started ? 'Close' : 'Skip and start blank',
|
|
@@ -839,7 +880,7 @@ function SectionLabel({ children, help }) {
|
|
|
839
880
|
},
|
|
840
881
|
onKeyDown: onStepKeyDown,
|
|
841
882
|
children: [
|
|
842
|
-
importing ? null : /*#__PURE__*/ _jsx(Box, {
|
|
883
|
+
importing || stylingStarter ? null : /*#__PURE__*/ _jsx(Box, {
|
|
843
884
|
sx: {
|
|
844
885
|
pt: {
|
|
845
886
|
xs: 3,
|
|
@@ -853,7 +894,7 @@ function SectionLabel({ children, help }) {
|
|
|
853
894
|
})
|
|
854
895
|
}),
|
|
855
896
|
/*#__PURE__*/ _jsx(Container, {
|
|
856
|
-
maxWidth: choosing || step === 'kind' || step === 'style' ? 'md' : 'sm',
|
|
897
|
+
maxWidth: choosing || stylingStarter || step === 'kind' || step === 'style' ? 'md' : 'sm',
|
|
857
898
|
disableGutters: true,
|
|
858
899
|
sx: {
|
|
859
900
|
py: {
|
|
@@ -890,7 +931,7 @@ function SectionLabel({ children, help }) {
|
|
|
890
931
|
variant: "body1",
|
|
891
932
|
color: "text.secondary",
|
|
892
933
|
children: [
|
|
893
|
-
choosing ? /*#__PURE__*/ _jsx(HelpTip, _extends({
|
|
934
|
+
choosing || stylingStarter ? /*#__PURE__*/ _jsx(HelpTip, _extends({
|
|
894
935
|
sx: {
|
|
895
936
|
float: 'right'
|
|
896
937
|
}
|
|
@@ -939,6 +980,28 @@ function SectionLabel({ children, help }) {
|
|
|
939
980
|
pendingSite: pendingSite,
|
|
940
981
|
onBack: ()=>setImporting(false),
|
|
941
982
|
leave: leave
|
|
983
|
+
}) : stylingStarter ? /*#__PURE__*/ _jsxs(Stack, {
|
|
984
|
+
spacing: 3,
|
|
985
|
+
component: "section",
|
|
986
|
+
"aria-label": "Style of your starter site",
|
|
987
|
+
children: [
|
|
988
|
+
/*#__PURE__*/ _jsx(OptionCardGrid, {
|
|
989
|
+
label: "Style of site",
|
|
990
|
+
"data-start-area": "starter-style-cards",
|
|
991
|
+
columns: {
|
|
992
|
+
xs: 2,
|
|
993
|
+
sm: 2,
|
|
994
|
+
md: 3
|
|
995
|
+
},
|
|
996
|
+
options: aiSiteStyleCards(),
|
|
997
|
+
value: starterStyle,
|
|
998
|
+
onChange: (id)=>{
|
|
999
|
+
setStarterStyle(id);
|
|
1000
|
+
tracker.fieldPicked('style');
|
|
1001
|
+
}
|
|
1002
|
+
}),
|
|
1003
|
+
creating ? pendingSite == null ? void 0 : (_pendingSite_previewControl = pendingSite.previewControl) == null ? void 0 : _pendingSite_previewControl.call(pendingSite, 'starter') : null
|
|
1004
|
+
]
|
|
942
1005
|
}) : choosing ? /*#__PURE__*/ _jsxs(Stack, {
|
|
943
1006
|
spacing: 2,
|
|
944
1007
|
children: [
|
|
@@ -961,8 +1024,8 @@ function SectionLabel({ children, help }) {
|
|
|
961
1024
|
accent: "secondary",
|
|
962
1025
|
icon: mdiPageLayoutHeaderFooter.path,
|
|
963
1026
|
iconId: "page-layout-header-footer",
|
|
964
|
-
title:
|
|
965
|
-
description:
|
|
1027
|
+
title: starterInShell ? 'Start from a starter site' : 'Start from the starter site',
|
|
1028
|
+
description: starterInShell ? 'A ready-made website from the marketplace, in a style you choose.' : 'A ready-made home page with a header, footer and contact form, in a style you choose.',
|
|
966
1029
|
busy: startingStarter,
|
|
967
1030
|
onChoose: chooseStarter
|
|
968
1031
|
}),
|
|
@@ -991,7 +1054,7 @@ function SectionLabel({ children, help }) {
|
|
|
991
1054
|
icon: mdiWebSync.path,
|
|
992
1055
|
iconId: "web-sync",
|
|
993
1056
|
title: "Bring my site",
|
|
994
|
-
description: `Bring the website you have now into ${PLATFORM_BRAND_NAME}:
|
|
1057
|
+
description: `Bring the website you have now into ${PLATFORM_BRAND_NAME}: every word as you wrote it, laid out as your pages are, in your new site’s preview.`,
|
|
995
1058
|
blocked: importAvailability.state === 'blocked' ? importAvailability.message : null,
|
|
996
1059
|
onChoose: chooseImport,
|
|
997
1060
|
children: importAvailability.state === 'blocked' && importAvailability.reason === 'plan' ? /*#__PURE__*/ _jsx(Chip, {
|
|
@@ -1084,6 +1147,43 @@ function SectionLabel({ children, help }) {
|
|
|
1084
1147
|
})
|
|
1085
1148
|
]
|
|
1086
1149
|
}),
|
|
1150
|
+
stylingStarter && /* The starter's style view (AGL-4049): Create site waits for a style. */ /*#__PURE__*/ _jsxs(DialogActions, {
|
|
1151
|
+
"data-start-area": "footer",
|
|
1152
|
+
sx: _extends({
|
|
1153
|
+
px: {
|
|
1154
|
+
xs: 2,
|
|
1155
|
+
sm: 3
|
|
1156
|
+
},
|
|
1157
|
+
py: 2,
|
|
1158
|
+
flexWrap: 'wrap',
|
|
1159
|
+
rowGap: 1,
|
|
1160
|
+
columnGap: 2,
|
|
1161
|
+
borderTop: 1,
|
|
1162
|
+
borderColor: 'divider'
|
|
1163
|
+
}, AI_SITE_START_SURFACE_SX),
|
|
1164
|
+
children: [
|
|
1165
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
1166
|
+
onClick: ()=>setPickingStyle(false),
|
|
1167
|
+
disabled: startingStarter,
|
|
1168
|
+
sx: {
|
|
1169
|
+
mr: 'auto'
|
|
1170
|
+
},
|
|
1171
|
+
children: 'Back'
|
|
1172
|
+
}),
|
|
1173
|
+
starterStyle ? null : /*#__PURE__*/ _jsx(Typography, {
|
|
1174
|
+
variant: "body2",
|
|
1175
|
+
color: "text.secondary",
|
|
1176
|
+
children: 'Choose a style to continue.'
|
|
1177
|
+
}),
|
|
1178
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
1179
|
+
variant: "contained",
|
|
1180
|
+
size: "large",
|
|
1181
|
+
disabled: !starterStyle || startingStarter,
|
|
1182
|
+
onClick: createStarter,
|
|
1183
|
+
children: startingStarter ? creating ? 'Creating…' : 'Starting…' : creating ? 'Create site' : 'Use this style'
|
|
1184
|
+
})
|
|
1185
|
+
]
|
|
1186
|
+
}),
|
|
1087
1187
|
asking && /* The footer stays put while the questions scroll. It wraps, because
|
|
1088
1188
|
the estimate, the reason and the buttons are wider than a phone. */ /*#__PURE__*/ _jsxs(DialogActions, {
|
|
1089
1189
|
"data-start-area": "footer",
|