feat: web notification (#1573)
Co-authored-by: sealday <sealday@gmail.com> Reviewed-on: daoyoucloud/tachybase#1573
This commit is contained in:
parent
2425e43621
commit
4b5d09a3cf
@ -1,17 +0,0 @@
|
|||||||
import { Plugin } from '../../application/Plugin';
|
|
||||||
|
|
||||||
export class PluginWebNotification extends Plugin {
|
|
||||||
async afterLoad() {
|
|
||||||
// 请求用户授予权限
|
|
||||||
if (Notification.permission !== 'denied') {
|
|
||||||
await Notification.requestPermission();
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
const notification = new Notification('通知标题:', {
|
|
||||||
body: '通知内容',
|
|
||||||
icon: 'https://www.example.com/icon.png', // 通知的图标 URL
|
|
||||||
});
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,5 +8,4 @@ export * from './custom-components/CustomField';
|
|||||||
export * from './fields/AssociatedField';
|
export * from './fields/AssociatedField';
|
||||||
export * from './fields/CalcResult';
|
export * from './fields/CalcResult';
|
||||||
export * from './fields/Expression';
|
export * from './fields/Expression';
|
||||||
export * from './system/OnlineUserProvider';
|
|
||||||
export * from './excel-table/ExcelFile';
|
export * from './excel-table/ExcelFile';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { css, useAPIClient, useApp } from '@tachybase/client';
|
import { PinnedPluginListProvider, SchemaComponentOptions, useAPIClient, useApp, useToken } from '@tachybase/client';
|
||||||
import { uid } from '@tachybase/schema';
|
import { uid } from '@tachybase/schema';
|
||||||
|
|
||||||
import { Button, Dropdown } from 'antd';
|
import { Button, Dropdown } from 'antd';
|
||||||
@ -9,6 +9,7 @@ const OnlineUserManger = () => {
|
|||||||
const app = useApp();
|
const app = useApp();
|
||||||
const [onlineUserItems, setOnlineUserItems] = useState([]);
|
const [onlineUserItems, setOnlineUserItems] = useState([]);
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
|
const { token } = useToken();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
app.ws.on('message', (event: MessageEvent) => {
|
app.ws.on('message', (event: MessageEvent) => {
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
@ -38,32 +39,21 @@ const OnlineUserManger = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown menu={{ items: onlineUserItems }}>
|
<Dropdown menu={{ items: onlineUserItems }}>
|
||||||
<Button style={{ width: 'auto' }} type="text">
|
<Button style={{ width: 'auto', color: token.colorTextHeaderMenu }} type="text">
|
||||||
在线 {_.size(onlineUserItems)} 人
|
在线 {_.size(onlineUserItems)} 人
|
||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OnlineUserDropdown = () => {
|
export const OnlineUserProvider = (props) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<PinnedPluginListProvider
|
||||||
className={css`
|
items={{
|
||||||
.ant-btn {
|
ou: { order: 230, component: 'OnlineUserManger', pin: true, isPublic: true },
|
||||||
border: 0;
|
}}
|
||||||
height: var(--tb-header-height);
|
|
||||||
width: 46px;
|
|
||||||
border-radius: 0;
|
|
||||||
background: none;
|
|
||||||
color: rgba(255, 255, 255, 0.65) !important;
|
|
||||||
&:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
style={{ display: 'inline-block' }}
|
|
||||||
>
|
>
|
||||||
<OnlineUserManger />
|
<SchemaComponentOptions components={{ OnlineUserManger }}>{props.children}</SchemaComponentOptions>
|
||||||
</div>
|
</PinnedPluginListProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -0,0 +1,9 @@
|
|||||||
|
import { Plugin } from '@tachybase/client';
|
||||||
|
|
||||||
|
import { OnlineUserProvider } from './OnlineUserProvider';
|
||||||
|
|
||||||
|
export class PluginOnlineUsers extends Plugin {
|
||||||
|
async load() {
|
||||||
|
this.app.use(OnlineUserProvider);
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ import { DepartmentsPlugin } from './features/departments';
|
|||||||
import { EmbedPlugin } from './features/embed';
|
import { EmbedPlugin } from './features/embed';
|
||||||
import { PluginFieldAppends } from './features/field-appends';
|
import { PluginFieldAppends } from './features/field-appends';
|
||||||
import { PluginHeraVersion } from './features/hera-version';
|
import { PluginHeraVersion } from './features/hera-version';
|
||||||
|
import { PluginOnlineUsers } from './features/online-users';
|
||||||
import { PluginOutbound } from './features/outbound';
|
import { PluginOutbound } from './features/outbound';
|
||||||
import { PluginPDF } from './features/pdf';
|
import { PluginPDF } from './features/pdf';
|
||||||
import { PluginSheet } from './features/sheet';
|
import { PluginSheet } from './features/sheet';
|
||||||
@ -62,6 +63,7 @@ export class PluginCoreClient extends Plugin {
|
|||||||
await this.app.pm.add(PluginPDF);
|
await this.app.pm.add(PluginPDF);
|
||||||
await this.app.pm.add(PluginOutbound);
|
await this.app.pm.add(PluginOutbound);
|
||||||
// await this.app.pm.add(PluginModeHighlight);
|
// await this.app.pm.add(PluginModeHighlight);
|
||||||
|
await this.app.pm.add(PluginOnlineUsers);
|
||||||
await this.app.pm.add(PluginFieldAppends);
|
await this.app.pm.add(PluginFieldAppends);
|
||||||
await this.app.pm.add(PluginCustomComponents);
|
await this.app.pm.add(PluginCustomComponents);
|
||||||
await this.app.pm.add(PluginSheet);
|
await this.app.pm.add(PluginSheet);
|
||||||
|
@ -10,6 +10,7 @@ import { MessageNotificationProvider } from './MessageNotificationProvider';
|
|||||||
import { MessagePage } from './MessagePage';
|
import { MessagePage } from './MessagePage';
|
||||||
import { MessageProvider } from './MessageProvider';
|
import { MessageProvider } from './MessageProvider';
|
||||||
import { SubscriptionManager } from './SubscriptionManager';
|
import { SubscriptionManager } from './SubscriptionManager';
|
||||||
|
import { PluginWebNotification } from './web-notification/PluginWebNotification';
|
||||||
|
|
||||||
interface MessageType {
|
interface MessageType {
|
||||||
title: string;
|
title: string;
|
||||||
@ -20,7 +21,7 @@ export class PluginMessagesClient extends Plugin {
|
|||||||
private _messageTypes: MessageType[] = [];
|
private _messageTypes: MessageType[] = [];
|
||||||
|
|
||||||
async afterAdd() {
|
async afterAdd() {
|
||||||
// await this.app.pm.add()
|
await this.app.pm.add(PluginWebNotification, { name: 'message-web' });
|
||||||
}
|
}
|
||||||
|
|
||||||
async beforeLoad() {}
|
async beforeLoad() {}
|
||||||
@ -71,11 +72,6 @@ export class PluginMessagesClient extends Plugin {
|
|||||||
Component: SubscriptionManager,
|
Component: SubscriptionManager,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registe({
|
|
||||||
name: 'browser',
|
|
||||||
title: lang('Browser notification'),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.registe({
|
this.registe({
|
||||||
name: 'sms',
|
name: 'sms',
|
||||||
title: lang('SMS notification'),
|
title: lang('SMS notification'),
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
import { Plugin } from '@tachybase/client';
|
||||||
|
|
||||||
|
import PluginMessagesClient from '..';
|
||||||
|
import { lang } from '../locale';
|
||||||
|
|
||||||
|
export class PluginWebNotification extends Plugin {
|
||||||
|
async afterLoad() {
|
||||||
|
// 请求用户授予权限
|
||||||
|
if (Notification.permission !== 'denied') {
|
||||||
|
await Notification.requestPermission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async load() {
|
||||||
|
this.pm.get(PluginMessagesClient).registe({
|
||||||
|
name: 'browser',
|
||||||
|
title: lang('Browser notification'),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.app.ws.on('message', (event: MessageEvent) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
if (data?.type === 'messages') {
|
||||||
|
const message = data.payload.message;
|
||||||
|
const notification = new Notification(message.title, {
|
||||||
|
body: message.content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
|
import { Model } from '@tachybase/database';
|
||||||
import { PluginWorkflow } from '@tachybase/plugin-workflow';
|
import { PluginWorkflow } from '@tachybase/plugin-workflow';
|
||||||
import { Plugin } from '@tachybase/server';
|
import { Gateway, Plugin } from '@tachybase/server';
|
||||||
|
|
||||||
import { MessageInstruction } from './instructions/message-instruction';
|
import { MessageInstruction } from './instructions/message-instruction';
|
||||||
|
|
||||||
@ -9,8 +10,20 @@ export class PluginMessagesServer extends Plugin {
|
|||||||
async beforeLoad() {}
|
async beforeLoad() {}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
|
const appName = this.app.name;
|
||||||
const workflowPlugin = this.app.getPlugin<PluginWorkflow>(PluginWorkflow);
|
const workflowPlugin = this.app.getPlugin<PluginWorkflow>(PluginWorkflow);
|
||||||
workflowPlugin.registerInstruction('message-instruction', MessageInstruction);
|
workflowPlugin.registerInstruction('message-instruction', MessageInstruction);
|
||||||
|
this.db.on('messages.afterCreate', async (message: Model, options) => {
|
||||||
|
const gateway = Gateway.getInstance();
|
||||||
|
const ws = gateway['wsServer'];
|
||||||
|
|
||||||
|
ws.sendToConnectionsByTag('app', appName, {
|
||||||
|
type: 'messages',
|
||||||
|
payload: {
|
||||||
|
message: message.toJSON(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async install() {}
|
async install() {}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
/node_modules
|
||||||
|
/src
|
1
packages/plugins/@tachybase/plugin-online-user/README.md
Normal file
1
packages/plugins/@tachybase/plugin-online-user/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# @tachybase/plugin-online-user
|
2
packages/plugins/@tachybase/plugin-online-user/client.d.ts
vendored
Normal file
2
packages/plugins/@tachybase/plugin-online-user/client.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './dist/client';
|
||||||
|
export { default } from './dist/client';
|
1
packages/plugins/@tachybase/plugin-online-user/client.js
Normal file
1
packages/plugins/@tachybase/plugin-online-user/client.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./dist/client/index.js');
|
11
packages/plugins/@tachybase/plugin-online-user/package.json
Normal file
11
packages/plugins/@tachybase/plugin-online-user/package.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "@tachybase/plugin-online-user",
|
||||||
|
"version": "0.22.4",
|
||||||
|
"main": "dist/server/index.js",
|
||||||
|
"dependencies": {},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tachybase/client": "workspace:*",
|
||||||
|
"@tachybase/server": "workspace:*",
|
||||||
|
"@tachybase/test": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
2
packages/plugins/@tachybase/plugin-online-user/server.d.ts
vendored
Normal file
2
packages/plugins/@tachybase/plugin-online-user/server.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './dist/server';
|
||||||
|
export { default } from './dist/server';
|
1
packages/plugins/@tachybase/plugin-online-user/server.js
Normal file
1
packages/plugins/@tachybase/plugin-online-user/server.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./dist/server/index.js');
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Plugin } from '@tachybase/client';
|
||||||
|
|
||||||
|
export class PluginOnlineUserClient extends Plugin {
|
||||||
|
async afterAdd() {
|
||||||
|
// await this.app.pm.add()
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeLoad() {}
|
||||||
|
|
||||||
|
// You can get and modify the app instance here
|
||||||
|
async load() {
|
||||||
|
console.log(this.app);
|
||||||
|
// this.app.addComponents({})
|
||||||
|
// this.app.addScopes({})
|
||||||
|
// this.app.addProvider()
|
||||||
|
// this.app.addProviders()
|
||||||
|
// this.app.router.add()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginOnlineUserClient;
|
@ -0,0 +1,2 @@
|
|||||||
|
export * from './server';
|
||||||
|
export { default } from './server';
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './plugin';
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Plugin } from '@tachybase/server';
|
||||||
|
|
||||||
|
export class PluginOnlineUserServer extends Plugin {
|
||||||
|
async afterAdd() {}
|
||||||
|
|
||||||
|
async beforeLoad() {}
|
||||||
|
|
||||||
|
async load() {}
|
||||||
|
|
||||||
|
async install() {}
|
||||||
|
|
||||||
|
async afterEnable() {}
|
||||||
|
|
||||||
|
async afterDisable() {}
|
||||||
|
|
||||||
|
async remove() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginOnlineUserServer;
|
@ -43,6 +43,7 @@
|
|||||||
"@tachybase/plugin-multi-app-manager": "workspace:*",
|
"@tachybase/plugin-multi-app-manager": "workspace:*",
|
||||||
"@tachybase/plugin-multi-app-share-collection": "workspace:*",
|
"@tachybase/plugin-multi-app-share-collection": "workspace:*",
|
||||||
"@tachybase/plugin-oidc": "workspace:*",
|
"@tachybase/plugin-oidc": "workspace:*",
|
||||||
|
"@tachybase/plugin-online-user": "workspace:*",
|
||||||
"@tachybase/plugin-saml": "workspace:*",
|
"@tachybase/plugin-saml": "workspace:*",
|
||||||
"@tachybase/plugin-sequence-field": "workspace:*",
|
"@tachybase/plugin-sequence-field": "workspace:*",
|
||||||
"@tachybase/plugin-sms-auth": "workspace:*",
|
"@tachybase/plugin-sms-auth": "workspace:*",
|
||||||
|
@ -18,6 +18,7 @@ export class PresetTachyBase extends Plugin {
|
|||||||
'acl',
|
'acl',
|
||||||
'messages',
|
'messages',
|
||||||
// optional plugins, default enabled
|
// optional plugins, default enabled
|
||||||
|
'online-user',
|
||||||
'action-bulk-edit',
|
'action-bulk-edit',
|
||||||
'action-bulk-update',
|
'action-bulk-update',
|
||||||
'action-duplicate',
|
'action-duplicate',
|
||||||
|
@ -3656,6 +3656,18 @@ importers:
|
|||||||
specifier: ^6.25.1
|
specifier: ^6.25.1
|
||||||
version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
|
||||||
|
packages/plugins/@tachybase/plugin-online-user:
|
||||||
|
dependencies:
|
||||||
|
'@tachybase/client':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../core/client
|
||||||
|
'@tachybase/server':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../core/server
|
||||||
|
'@tachybase/test':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../core/test
|
||||||
|
|
||||||
packages/plugins/@tachybase/plugin-print-template:
|
packages/plugins/@tachybase/plugin-print-template:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@bull-board/api':
|
'@bull-board/api':
|
||||||
@ -4512,6 +4524,9 @@ importers:
|
|||||||
'@tachybase/plugin-oidc':
|
'@tachybase/plugin-oidc':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/@tachybase/plugin-oidc
|
version: link:../../plugins/@tachybase/plugin-oidc
|
||||||
|
'@tachybase/plugin-online-user':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../plugins/@tachybase/plugin-online-user
|
||||||
'@tachybase/plugin-saml':
|
'@tachybase/plugin-saml':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../plugins/@tachybase/plugin-saml
|
version: link:../../plugins/@tachybase/plugin-saml
|
||||||
|
Loading…
Reference in New Issue
Block a user