Skip to content

Commit

Permalink
Add bot api doc (#525)
Browse files Browse the repository at this point in the history
* Refactor bot view and add API helper generation

* Remove bot service and refactor snapshot views to use centralized snapshot service functions.
  • Loading branch information
swuecho authored Sep 8, 2024
1 parent 85a74e8 commit b4baae3
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 90 deletions.
4 changes: 3 additions & 1 deletion web/src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"common": {
"ask_user_register": "请注册, 只有注册账号才能继续对话",
"help": "第一条是主题(prompt, 角色定义), 上下文默认包括10条信息, 参数可以点击按钮进行调节, 请务必注意隐私, 不输入涉密, 敏感信息.",
"copy": "复制",
"edit": "编辑",
"delete": "删除",
"save": "保存",
Expand Down Expand Up @@ -40,7 +41,8 @@
"list": "机器人列表",
"all": {
"title": "机器人列表"
}
},
"showCode": "生成API调用代码"
},
"chat": {
"new": "新对话",
Expand Down
56 changes: 56 additions & 0 deletions web/src/service/snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { displayLocaleDate, formatYearMonth } from '@/utils/date'





export function generateAPIHelper(uuid: string, apiToken: string, origin: string) {
const data = {
"message": "Your message here",
"snapshot_uuid": uuid,
"stream": false,
}
return `curl -X POST ${origin}/api/chatbot -H "Content-Type: application/json" -H "Authorization: Bearer ${apiToken}" -d '${JSON.stringify(data)}'`
}

export function getChatbotPosts(posts: Snapshot.Snapshot[]) {
return posts
.filter((post: Snapshot.Snapshot) => post.typ === 'chatbot')
.map((post: Snapshot.Snapshot): Snapshot.PostLink => ({
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}))
}

export function getSnapshotPosts(posts: Snapshot.Snapshot[]) {
return posts
.filter((post: Snapshot.Snapshot) => post.typ === 'snapshot')
.map((post: Snapshot.Snapshot): Snapshot.PostLink => ({
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}))
}

export function postsByYearMonthTransform(posts: Snapshot.PostLink[]) {
const init: Record<string, Snapshot.PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []

acc[yearMonth].push(post)
return acc
}, init)
}

export function getSnapshotPostLinks(snapshots: Snapshot.Snapshot[]): Record<string, Snapshot.PostLink[]> {
const snapshotPosts = getSnapshotPosts(snapshots)
return postsByYearMonthTransform(snapshotPosts)
}

export function getBotPostLinks(bots: Snapshot.Snapshot[]): Record<string, Snapshot.PostLink[]> {
const chatbotPosts = getChatbotPosts(bots)
return postsByYearMonthTransform(chatbotPosts)
}
20 changes: 20 additions & 0 deletions web/src/typings/chat.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,24 @@ declare namespace Chat {
userEmail: string
rateLimit: string
}


}

declare namespace Snapshot {

interface Snapshot {
uuid: string;
title: string;
summary: string;
tags: Record<string, unknown>;
createdAt: string;
typ: 'chatbot' | 'snapshot';
}

interface PostLink {
uuid: string;
date: string;
title: string;
}
}
119 changes: 65 additions & 54 deletions web/src/views/bot/all.vue
Original file line number Diff line number Diff line change
@@ -1,56 +1,42 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { onMounted, ref, h } from 'vue'
import { NModal, useDialog, useMessage } from 'naive-ui'
import Search from '../snapshot/components/Search.vue'
import { fetchSnapshotAll, fetchSnapshotDelete } from '@/api'
import { displayLocaleDate, formatYearMonth } from '@/utils/date'
import { HoverButton, SvgIcon } from '@/components/common'
import { generateAPIHelper, getBotPostLinks } from '@/service/snapshot'
import request from '@/utils/request/axios'
import { t } from '@/locales'
const dialog = useDialog()
const nui_msg = useMessage()
const search_visible = ref(false)
interface PostLink {
uuid: string
date: string
title: string
}
function post_url(uuid: string): string {
return `#/bot/${uuid}`
}
const search_visible = ref(false)
const apiToken = ref('')
const postsByYearMonth = ref<Record<string, PostLink[]>>({})
const postsByYearMonth = ref<Record<string, Snapshot.PostLink[]>>({})
function postsByYearMonthTransform(posts: PostLink[]) {
const init: Record<string, PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []
onMounted(async () => {
await refreshSnapshot()
try {
const response = await request.get('/token_10years')
if (response.status === 200) {
apiToken.value = response.data.accessToken
}
else {
nui_msg.error('Failed to fetch API token')
}
} catch (error) {
nui_msg.error('Error fetching API token')
}
})
acc[yearMonth].push(post)
return acc
}, init)
}
async function getPostLinks() {
const rawPosts = await fetchSnapshotAll()
const rawPostsFormated = rawPosts.filter( (post: any) => post.typ === 'chatbot').map((post: any) => {
return {
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}
})
return postsByYearMonthTransform(rawPostsFormated)
async function refreshSnapshot() {
const bots: Snapshot.Snapshot[] = await fetchSnapshotAll()
postsByYearMonth.value = getBotPostLinks(bots)
}
onMounted(async () => {
postsByYearMonth.value = await getPostLinks()
})
function handleDelete(post: PostLink) {
function handleDelete(post: Snapshot.PostLink) {
const dialogBox = dialog.warning({
title: t('chat_snapshot.deletePost'),
content: post.title,
Expand All @@ -60,7 +46,7 @@ function handleDelete(post: PostLink) {
try {
dialogBox.loading = true
await fetchSnapshotDelete(post.uuid)
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
dialogBox.loading = false
nui_msg.success(t('chat_snapshot.deleteSuccess'))
Promise.resolve()
Expand All @@ -74,20 +60,43 @@ function handleDelete(post: PostLink) {
},
})
}
function handleShowCode(post: Snapshot.PostLink) {
const dialogBox = dialog.info({
title: t('bot.showCode'),
content: () => h('code', { class: 'whitespace-pre-wrap' }, genAPIHelper(post)),
positiveText: t('common.copy'),
onPositiveClick: () => {
// copy to clipboard
navigator.clipboard.writeText(genAPIHelper(post))
dialogBox.loading = false
nui_msg.success(t('common.success'))
},
})
}
function post_url(uuid: string): string {
return `#/bot/${uuid}`
}
function genAPIHelper(post: Snapshot.PostLink) {
return generateAPIHelper(post.uuid, apiToken.value, window.location.origin)
}
</script>

<template>
<div class="flex flex-col w-full h-full dark:text-white">
<header class="flex items-center justify-between h-16 z-30 border-b dark:border-neutral-800 bg-white/80 dark:bg-black/20 dark:text-white backdrop-blur">
<header
class="flex items-center justify-between h-16 z-30 border-b dark:border-neutral-800 bg-white/80 dark:bg-black/20 dark:text-white backdrop-blur">
<div class="flex items-center ml-10">
<svg
class="w-8 h-8 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
<svg class="w-8 h-8 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h1 class="text-xl font-semibold text-gray-900">
{{ $t('bot.all.title') }}
Expand All @@ -104,7 +113,8 @@ function handleDelete(post: PostLink) {
</header>
<div id="scrollRef" ref="scrollRef" class="h-full overflow-hidden overflow-y-auto">
<div class="max-w-screen-xl px-4 py-8 mx-auto">
<div v-for="[yearMonth, postsOfYearMonth] in Object.entries(postsByYearMonth)" :key="yearMonth" class="flex mb-2">
<div v-for="[yearMonth, postsOfYearMonth] in Object.entries(postsByYearMonth)" :key="yearMonth"
class="flex mb-2">
<h2 class="flex-none w-28 text-lg font-medium">
{{ yearMonth }}
</h2>
Expand All @@ -114,15 +124,16 @@ function handleDelete(post: PostLink) {
<div class="flex">
<time :datetime="post.date" class="mb-1 text-sm font-medium text-gray-600">{{
post.date
}}</time>
}}</time>
<div class="ml-2 text-sm" @click="handleDelete(post)">
<SvgIcon icon="ic:baseline-delete-forever" />
</div>
<div class="ml-4 cursor-pointer" @click="handleShowCode(post)">
<SvgIcon icon="ic:outline-code" />
</div>
</div>
<a
:href="post_url(post.uuid)" :title="post.title"
class="block text-xl font-semibold text-gray-900 hover:text-blue-600 mb-2"
>{{ post.title }}</a>
<a :href="post_url(post.uuid)" :title="post.title"
class="block text-xl font-semibold text-gray-900 hover:text-blue-600 mb-2">{{ post.title }}</a>
</div>
</li>
</ul>
Expand Down
45 changes: 10 additions & 35 deletions web/src/views/snapshot/all.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,29 @@ import { onMounted, ref } from 'vue'
import { NModal, useDialog, useMessage } from 'naive-ui'
import Search from './components/Search.vue'
import { fetchSnapshotAll, fetchSnapshotDelete } from '@/api'
import { displayLocaleDate, formatYearMonth } from '@/utils/date'
import { HoverButton, SvgIcon } from '@/components/common'
import { getSnapshotPostLinks } from '@/service/snapshot'
import { t } from '@/locales'
const dialog = useDialog()
const nui_msg = useMessage()
const search_visible = ref(false)
interface PostLink {
uuid: string
date: string
title: string
}
function post_url(uuid: string): string {
return `#/snapshot/${uuid}`
}
const postsByYearMonth = ref<Record<string, PostLink[]>>({})
function postsByYearMonthTransform(posts: PostLink[]) {
const init: Record<string, PostLink[]> = {}
return posts.reduce((acc, post) => {
const yearMonth = formatYearMonth(new Date(post.date))
if (!acc[yearMonth])
acc[yearMonth] = []
acc[yearMonth].push(post)
return acc
}, init)
}
async function getPostLinks() {
const rawPosts = await fetchSnapshotAll()
const rawPostsFormated = rawPosts.filter( (post: any) => post.typ === 'snapshot' ).map((post: any) => {
return {
uuid: post.uuid,
date: displayLocaleDate(post.createdAt),
title: post.title,
}
})
return postsByYearMonthTransform(rawPostsFormated)
}
const postsByYearMonth = ref<Record<string, Snapshot.PostLink[]>>({})
onMounted(async () => {
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
})
function handleDelete(post: PostLink) {
async function refreshSnapshot() {
const snapshots: Snapshot.Snapshot[] = await fetchSnapshotAll()
postsByYearMonth.value = getSnapshotPostLinks(snapshots)
}
function handleDelete(post: Snapshot.PostLink) {
const dialogBox = dialog.warning({
title: t('chat_snapshot.deletePost'),
content: post.title,
Expand All @@ -60,7 +35,7 @@ function handleDelete(post: PostLink) {
try {
dialogBox.loading = true
await fetchSnapshotDelete(post.uuid)
postsByYearMonth.value = await getPostLinks()
await refreshSnapshot()
dialogBox.loading = false
nui_msg.success(t('chat_snapshot.deleteSuccess'))
Promise.resolve()
Expand Down

0 comments on commit b4baae3

Please sign in to comment.