Skip to content

Commit

Permalink
✨ feat: Add Rank
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Dec 26, 2024
1 parent 8bbb9d2 commit 5e76458
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/app/(main)/profile/stats/Client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import TotalAssistants from './features/TotalAssistants';
import TotalMessages from './features/TotalMessages';
import TotalTopics from './features/TotalTopics';

const Client = memo<{ mobile?: boolean }>(() => {
const Client = memo<{ mobile?: boolean }>(({ mobile }) => {
const { t } = useTranslation('auth');

return (
Expand All @@ -26,7 +26,7 @@ const Client = memo<{ mobile?: boolean }>(() => {
<TotalMessages />
</Grid>
</FormGroup>
<Grid rows={2}>
<Grid gap={mobile ? undefined : 48} rows={2}>
<FormGroup
style={FORM_STYLE.style}
title={t('stats.assistantsRank.title')}
Expand Down
51 changes: 49 additions & 2 deletions src/app/(main)/profile/stats/features/AssistantsRank.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,60 @@
import { BarList } from '@lobehub/charts';
import { Avatar } from '@lobehub/ui';
import { useTheme } from 'antd-style';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import qs from 'query-string';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { DEFAULT_AVATAR } from '@/const/meta';
import { useClientDataSWR } from '@/libs/swr';
import { sessionService } from '@/services/session';

export const AssistantsRank = memo(() => {
const { t } = useTranslation('auth');
const { t } = useTranslation(['auth', 'chat']);
const theme = useTheme();
const router = useRouter();
const { data, isLoading } = useClientDataSWR('rank-sessions', async () =>
sessionService.rankSessions(),
);

return (
<BarList
data={[]}
data={
data?.map((item) => {
const link = qs.stringifyUrl({
query: {
session: item.id,
},
url: '/chat',
});
return {
icon: (
<Avatar
alt={item.title || t('defaultAgent', { ns: 'chat' })}
avatar={item.avatar || DEFAULT_AVATAR}
background={item.backgroundColor || theme.colorFillSecondary}
size={28}
style={{
backdropFilter: 'blur(8px)',
}}
/>
),
link,
name: (
<Link href={link} style={{ color: 'inherit' }}>
{item.title || t('defaultAgent', { ns: 'chat' })}
</Link>
),
value: item.count,
};
}) || []
}
height={420}
leftLabel={t('stats.assistantsRank.left')}
loading={isLoading}
onValueChange={(item) => router.push(item.link)}
rightLabel={t('stats.assistantsRank.right')}
/>
);
Expand Down
46 changes: 45 additions & 1 deletion src/app/(main)/profile/stats/features/TopicsRank.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
import { BarList } from '@lobehub/charts';
import { Icon } from '@lobehub/ui';
import { useTheme } from 'antd-style';
import { MessageSquareIcon } from 'lucide-react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import qs from 'query-string';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';

import { useClientDataSWR } from '@/libs/swr';
import { topicService } from '@/services/topic';

export const TopicsRank = memo(() => {
const { t } = useTranslation('auth');
const theme = useTheme();
const router = useRouter();
const { data, isLoading } = useClientDataSWR('rank-topics', async () =>
topicService.rankTopics(),
);

return (
<BarList
data={[]}
data={
data?.map((item) => {
const link = qs.stringifyUrl({
query: {
session: item.sessionId,
topic: item.id,
},
url: '/chat',
});
return {
icon: (
<Icon
color={theme.colorTextDescription}
icon={MessageSquareIcon}
size={{ fontSize: 16 }}
/>
),
link,
name: (
<Link href={link} style={{ color: 'inherit' }}>
{item.title}
</Link>
),
value: item.count,
};
}) || []
}
height={420}
leftLabel={t('stats.topicsRank.left')}
loading={isLoading}
onValueChange={(item) => router.push(item.link)}
rightLabel={t('stats.topicsRank.right')}
/>
);
Expand Down
4 changes: 3 additions & 1 deletion src/app/(main)/profile/stats/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';

import Client from './Client';

Expand All @@ -13,7 +14,8 @@ export const generateMetadata = async () => {
};

const Page = async () => {
return <Client />;
const mobile = await isMobileDevice();
return <Client mobile={mobile} />;
};

export default Page;
27 changes: 26 additions & 1 deletion src/database/server/models/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
agentsToSessions,
sessionGroups,
sessions,
topics,
} from '../../schemas';

export class SessionModel {
Expand Down Expand Up @@ -118,7 +119,31 @@ export class SessionModel {
return result[0].count;
};

rank = async () => {};
rank = async (): Promise<
{
avatar: string | null;
backgroundColor: string | null;
count: number;
id: string;
title: string | null;
}[]
> => {
return this.db
.select({
avatar: agents.avatar,
backgroundColor: agents.backgroundColor,
count: count(topics.id).as('count'),
id: sessions.id,
title: agents.title,
})
.from(sessions)
.leftJoin(topics, eq(sessions.id, topics.sessionId))
.leftJoin(agentsToSessions, eq(sessions.id, agentsToSessions.sessionId))
.leftJoin(agents, eq(agentsToSessions.agentId, agents.id))
.groupBy(sessions.id, agentsToSessions.agentId, agents.id)
.orderBy(desc(sql`count`))
.limit(10);
};

hasMoreThanN = async (n: number): Promise<boolean> => {
const result = await this.db
Expand Down
22 changes: 21 additions & 1 deletion src/database/server/models/topic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,27 @@ export class TopicModel {
return result[0].count;
};

rank = async () => {};
rank = async (): Promise<
{
count: number;
id: string;
sessionId: string | null;
title: string | null;
}[]
> => {
return this.db
.select({
count: count(messages.id).as('count'),
id: topics.id,
sessionId: topics.sessionId,
title: topics.title,
})
.from(topics)
.leftJoin(messages, eq(topics.id, messages.topicId))
.groupBy(topics.id)
.orderBy(desc(sql`count`))
.limit(10);
};

// **************** Create *************** //

Expand Down
2 changes: 1 addition & 1 deletion src/locales/default/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default {
assistants: '助手数',
assistantsRank: {
left: '助手名称',
right: '消息数',
right: '话题数',
title: '助手使用率',
},
heatmaps: {
Expand Down
5 changes: 5 additions & 0 deletions src/services/session/_deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export class ClientService implements ISessionService {
return SessionModel.count();
}

// @ts-ignore
async rankSessions() {
throw new Error('Method not implemented.');
}

async hasSessions() {
return (await this.countSessions()) !== 0;
}
Expand Down
15 changes: 14 additions & 1 deletion src/services/session/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,20 @@ export interface ISessionService {
* @deprecated
*/
getSessionsByType(type?: 'agent' | 'group' | 'all'): Promise<LobeSessions>;
countSessions(): Promise<number>;
countSessions(params?: {
endDate?: string;
range?: [string, string];
startDate?: string;
}): Promise<number>;
rankSessions(): Promise<
{
avatar: string | null;
count: number;
id: string;
title: string | null;
backgroundColor: string | null;
}[]
>;
searchSessions(keyword: string): Promise<LobeSessions>;

updateSession(id: string, data: Partial<UpdateSessionParams>): Promise<any>;
Expand Down
5 changes: 5 additions & 0 deletions src/services/topic/_deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export class ClientService implements ITopicService {
return TopicModel.count();
}

// @ts-ignore
async rankTopics() {
throw new Error('Method not implemented.');
}

async updateTopicFavorite(id: string, favorite?: boolean) {
return this.updateTopic(id, { favorite });
}
Expand Down
9 changes: 8 additions & 1 deletion src/services/topic/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ export class ClientService extends BaseClientService implements ITopicService {
return this.topicModel.count(params);
}

async rankTopics() {
async rankTopics(): Promise<
{
count: number;
id: string;
sessionId: string | null;
title: string | null;
}[]
> {
return this.topicModel.rank();
}

Expand Down
9 changes: 8 additions & 1 deletion src/services/topic/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ export class ServerService implements ITopicService {
return lambdaClient.topic.countTopics.query(params);
}

rankTopics = async () => {
rankTopics = async (): Promise<
{
count: number;
id: string;
sessionId: string | null;
title: string | null;
}[]
> => {
return lambdaClient.topic.rankTopics.query();
}

Expand Down
8 changes: 8 additions & 0 deletions src/services/topic/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ export interface ITopicService {
getTopics(params: QueryTopicParams): Promise<ChatTopic[]>;
getAllTopics(): Promise<ChatTopic[]>;
countTopics(): Promise<number>;
rankTopics(): Promise<
{
id: string;
title: string | null;
count: number;
sessionId: string | null;
}[]
>;
searchTopics(keyword: string, sessionId?: string): Promise<ChatTopic[]>;

updateTopic(id: string, data: Partial<ChatTopic>): Promise<any>;
Expand Down

0 comments on commit 5e76458

Please sign in to comment.