feat: integration screen
This commit is contained in:
1 parent
a9a208b80a
commit
ad55137883
13 files changed
+786
-6
No files matched your search
@@ -1,9 +1,121 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import DashboardShell from '@/components/DashboardShell.vue'
|
||||
import EndpointCard from '@/components/EndpointCard.vue'
|
||||
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
||||
|
||||
const origin = computed(() => window.location.origin)
|
||||
|
||||
const { copied, copy } = useCopyToClipboard()
|
||||
|
||||
const copyButtonLabel = computed(() => (copied.value ? 'Copied' : 'Copy'))
|
||||
const copyButtonIcon = computed(() => (copied.value ? 'i-lucide-check' : 'i-lucide-copy'))
|
||||
|
||||
function copyBaseUrl() {
|
||||
copy(origin.value)
|
||||
}
|
||||
|
||||
const sampleArticle = {
|
||||
id: 12,
|
||||
title: 'How we price a bathroom renovation',
|
||||
body: '<p>Every bathroom is different, but the way we price them isn’t.</p>',
|
||||
images: [
|
||||
{
|
||||
id: 1,
|
||||
path: '/static/uploadedImages/2f6a1c0e-2b8b-4c3d-9c1e-1a2b3c4d5e6f.png',
|
||||
article_id: 12,
|
||||
created_at: '2026-03-12T09:14:00Z',
|
||||
updated_at: '2026-03-12T09:14:00Z',
|
||||
},
|
||||
],
|
||||
is_online: true,
|
||||
created_at: '2026-03-12T09:14:00Z',
|
||||
updated_at: '2026-09-10T07:00:00Z',
|
||||
}
|
||||
|
||||
const sampleArticleList = [sampleArticle]
|
||||
|
||||
const endpoints = computed(() => [
|
||||
{
|
||||
method: 'GET' as const,
|
||||
path: '/v1/article/',
|
||||
description: 'Lists every online article.',
|
||||
examples: {
|
||||
fetch: `const res = await fetch('${origin.value}/v1/article/')\nconst articles = await res.json()`,
|
||||
curl: `curl ${origin.value}/v1/article/`,
|
||||
response: JSON.stringify(sampleArticleList, null, 2),
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'GET' as const,
|
||||
path: '/v1/article/{id}',
|
||||
description: 'Returns one online article. Drafts and unknown ids both return 404.',
|
||||
examples: {
|
||||
fetch: `const res = await fetch('${origin.value}/v1/article/12')\nif (res.status === 404) return notFound()\nconst article = await res.json()`,
|
||||
curl: `curl ${origin.value}/v1/article/12`,
|
||||
response: JSON.stringify(sampleArticle, null, 2),
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const notes = [
|
||||
'Anonymous callers only ever get online articles. Drafts stay private until you publish them.',
|
||||
'Images in body use paths like /static/uploadedImages/<uuid>.png. Prefix them with the base URL before rendering.',
|
||||
"Browsers can only call the API from origins listed in the server's CORS setting. Ask whoever runs the server to add your site's address.",
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardShell>
|
||||
<p>Integration placeholder.</p>
|
||||
<DashboardShell mobile-title="Integration">
|
||||
<div class="flex max-w-199 flex-col gap-6">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h1 class="text-xl font-semibold text-highlighted">Connect your website</h1>
|
||||
<p class="text-muted">A guide for the developer who builds your public site.</p>
|
||||
</div>
|
||||
|
||||
<p class="text-base text-pretty text-toned">
|
||||
RenewCMS is headless: it stores and publishes your articles but doesn't show them to
|
||||
visitors. Your website fetches published articles from the two addresses below and
|
||||
displays them in its own design.
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<span class="font-medium text-highlighted">Base URL</span>
|
||||
<div class="flex border border-accented bg-default">
|
||||
<span
|
||||
class="h-10 min-w-0 flex-1 truncate px-3 font-mono text-sm leading-10 text-default"
|
||||
>{{ origin }}</span
|
||||
>
|
||||
<UButton
|
||||
:icon="copyButtonIcon"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
aria-live="polite"
|
||||
class="h-10 gap-1.5 rounded-none border-l border-accented px-3 font-medium"
|
||||
:class="copied ? 'text-success' : 'text-highlighted'"
|
||||
:ui="{ leadingIcon: 'size-3.5' }"
|
||||
@click="copyBaseUrl"
|
||||
>
|
||||
{{ copyButtonLabel }}
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<EndpointCard
|
||||
v-for="endpoint in endpoints"
|
||||
:key="endpoint.path"
|
||||
:method="endpoint.method"
|
||||
:path="endpoint.path"
|
||||
:description="endpoint.description"
|
||||
:examples="endpoint.examples"
|
||||
/>
|
||||
|
||||
<div class="flex flex-col gap-2.5">
|
||||
<div v-for="note in notes" :key="note" class="flex gap-2.5">
|
||||
<UIcon name="i-lucide-info" class="mt-0.75 size-4 shrink-0 text-info" />
|
||||
<span class="text-base text-pretty text-toned">{{ note }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DashboardShell>
|
||||
</template>
|
||||
Reference in new issue
Block a user