feat(openapi): add delete app action

perf/livekit-chat-count
moonrailgun 2 years ago
parent 2dfe88b5dd
commit 380bc3d960

@ -1,7 +1,13 @@
import { useOpenAppInfo } from '../context'; import { useOpenAppInfo } from '../context';
import React from 'react'; import React from 'react';
import { FullModalField, Divider, SensitiveText } from '@capital/component'; import {
FullModalField,
Divider,
SensitiveText,
Button,
} from '@capital/component';
import { Translate } from '../../translate'; import { Translate } from '../../translate';
import { useOpenAppAction } from './useOpenAppAction';
import './Profile.less'; import './Profile.less';
/** /**
@ -10,6 +16,8 @@ import './Profile.less';
const Profile: React.FC = React.memo(() => { const Profile: React.FC = React.memo(() => {
const { appId, appSecret } = useOpenAppInfo(); const { appId, appSecret } = useOpenAppInfo();
const { handleDeleteApp } = useOpenAppAction();
return ( return (
<div className="plugin-openapi-app-info_profile"> <div className="plugin-openapi-app-info_profile">
<h2>{Translate.app.appcret}</h2> <h2>{Translate.app.appcret}</h2>
@ -22,11 +30,11 @@ const Profile: React.FC = React.memo(() => {
/> />
</div> </div>
{/* <Divider /> */} <Divider />
{/* <h2>{Translate.app.basicInfo}</h2> */}
{/* TODO */} <Button type="primary" danger={true} onClick={handleDeleteApp}>
{Translate.delete}
</Button>
</div> </div>
); );
}); });

@ -1,4 +1,10 @@
import { postRequest, useAsyncFn } from '@capital/common'; import {
openReconfirmModal,
postRequest,
showErrorToasts,
useAsyncFn,
useEvent,
} from '@capital/common';
import { useOpenAppInfo } from '../context'; import { useOpenAppInfo } from '../context';
import type { OpenAppBot, OpenAppCapability, OpenAppOAuth } from '../types'; import type { OpenAppBot, OpenAppCapability, OpenAppOAuth } from '../types';
@ -6,7 +12,7 @@ import type { OpenAppBot, OpenAppCapability, OpenAppOAuth } from '../types';
* *
*/ */
export function useOpenAppAction() { export function useOpenAppAction() {
const { refresh, appId, capability } = useOpenAppInfo(); const { refresh, appId, capability, onSelectApp } = useOpenAppInfo();
const [{ loading }, handleChangeAppCapability] = useAsyncFn( const [{ loading }, handleChangeAppCapability] = useAsyncFn(
async (targetCapability: OpenAppCapability, checked: boolean) => { async (targetCapability: OpenAppCapability, checked: boolean) => {
@ -56,8 +62,25 @@ export function useOpenAppAction() {
[appId, refresh] [appId, refresh]
); );
const handleDeleteApp = useEvent(() => {
openReconfirmModal({
onConfirm: async () => {
try {
await postRequest('/openapi/app/delete', {
appId,
});
onSelectApp(null);
await refresh();
} catch (err) {
showErrorToasts(err);
}
},
});
});
return { return {
loading, loading,
handleDeleteApp,
handleChangeAppCapability, handleChangeAppCapability,
handleUpdateOAuthInfo, handleUpdateOAuthInfo,
handleUpdateBotInfo, handleUpdateBotInfo,

@ -3,6 +3,7 @@ import { OpenApp } from './types';
interface OpenAppInfoContextProps extends OpenApp { interface OpenAppInfoContextProps extends OpenApp {
refresh: () => Promise<void>; refresh: () => Promise<void>;
onSelectApp: (appId: string | null) => void;
} }
const OpenAppInfoContext = React.createContext<OpenAppInfoContextProps>(null); const OpenAppInfoContext = React.createContext<OpenAppInfoContextProps>(null);
@ -12,6 +13,7 @@ export const OpenAppInfoProvider: React.FC<
React.PropsWithChildren<{ React.PropsWithChildren<{
appInfo: OpenApp; appInfo: OpenApp;
refresh: OpenAppInfoContextProps['refresh']; refresh: OpenAppInfoContextProps['refresh'];
onSelectApp: OpenAppInfoContextProps['onSelectApp'];
}> }>
> = (props) => { > = (props) => {
return ( return (
@ -19,6 +21,7 @@ export const OpenAppInfoProvider: React.FC<
value={{ value={{
...props.appInfo, ...props.appInfo,
refresh: props.refresh, refresh: props.refresh,
onSelectApp: props.onSelectApp,
}} }}
> >
{props.children} {props.children}

@ -50,7 +50,11 @@ const OpenApiMainPanel: React.FC = React.memo(() => {
<Loading spinning={loading} style={{ height: '100%' }}> <Loading spinning={loading} style={{ height: '100%' }}>
<div className="plugin-openapi-main-panel"> <div className="plugin-openapi-main-panel">
{appInfo ? ( {appInfo ? (
<OpenAppInfoProvider appInfo={appInfo} refresh={refresh}> <OpenAppInfoProvider
appInfo={appInfo}
onSelectApp={handleSetSelectedApp}
refresh={refresh}
>
<AppInfo /> <AppInfo />
</OpenAppInfoProvider> </OpenAppInfoProvider>
) : ( ) : (

@ -47,7 +47,7 @@ export function useOpenAppList() {
/** /**
* app * app
*/ */
handleSetSelectedApp(appId: string) { handleSetSelectedApp(appId: string | null) {
navigate({ navigate({
search: appendUrlSearch({ search: appendUrlSearch({
appId, appId,

@ -18,6 +18,10 @@ export const Translate = {
'zh-CN': '操作', 'zh-CN': '操作',
'en-US': 'Operation', 'en-US': 'Operation',
}), }),
delete: localTrans({
'zh-CN': '删除',
'en-US': 'Delete',
}),
enter: localTrans({ enter: localTrans({
'zh-CN': '进入', 'zh-CN': '进入',
'en-US': 'Enter', 'en-US': 'Enter',

@ -15,10 +15,15 @@ export { urlSearchStringify, urlSearchParse };
* url search * url search
*/ */
export function appendUrlSearch(obj: Record<string, string>): string { export function appendUrlSearch(obj: Record<string, string>): string {
return urlSearchStringify({ return urlSearchStringify(
{
...urlSearchParse(window.location.search, { ignoreQueryPrefix: true }), ...urlSearchParse(window.location.search, { ignoreQueryPrefix: true }),
...obj, ...obj,
}); },
{
skipNulls: true,
}
);
} }
/** /**

@ -4,10 +4,12 @@ import {
TcDbService, TcDbService,
TcContext, TcContext,
EntityError, EntityError,
NoPermissionError,
} from 'tailchat-server-sdk'; } from 'tailchat-server-sdk';
import _ from 'lodash'; import _ from 'lodash';
import { import {
filterAvailableAppCapability, filterAvailableAppCapability,
OpenApp,
OpenAppBot, OpenAppBot,
OpenAppDocument, OpenAppDocument,
OpenAppModel, OpenAppModel,
@ -60,6 +62,11 @@ class OpenAppService extends TcService {
appIcon: 'string', appIcon: 'string',
}, },
}); });
this.registerAction('delete', this.delete, {
params: {
appId: 'string',
},
});
this.registerAction('setAppCapability', this.setAppCapability, { this.registerAction('setAppCapability', this.setAppCapability, {
params: { params: {
appId: 'string', appId: 'string',
@ -185,6 +192,36 @@ class OpenAppService extends TcService {
return await this.transformDocuments(ctx, {}, doc); return await this.transformDocuments(ctx, {}, doc);
} }
/**
*
*/
async delete(
ctx: TcContext<{
appId: string;
}>
) {
const { appId } = ctx.params;
const userId = ctx.meta.userId;
const t = ctx.meta.t;
const appInfo: OpenApp = await this.localCall('get', {
appId,
});
if (String(appInfo.owner) !== userId) {
throw new NoPermissionError(t('没有操作权限'));
}
// 可能会出现ws机器人不会立即中断连接的问题不重要暂时不处理
await this.adapter.model.remove({
appId,
owner: userId,
});
return true;
}
/** /**
* *
*/ */

Loading…
Cancel
Save