feat: add file filter chat files checkbox(use for remove unused chat files)

pull/249/head
moonrailgun 8 months ago
parent 3cea16ee60
commit c4e70efb61

@ -1653,8 +1653,8 @@ importers:
specifier: workspace:^
version: link:../packages/sdk
tushan:
specifier: ^0.3.4
version: 0.3.4(prop-types@15.8.1)(ts-node@10.9.1)
specifier: ^0.3.9
version: 0.3.9(prop-types@15.8.1)(ts-node@10.9.1)
vite-express:
specifier: 0.8.0
version: 0.8.0(patch_hash=u6touqej4dt3zxnslnszarl7vq)(express@4.18.2)(vite@4.2.0)
@ -33333,8 +33333,8 @@ packages:
domino: 2.1.6
dev: false
/tushan@0.3.4(prop-types@15.8.1)(ts-node@10.9.1):
resolution: {integrity: sha512-y2z1wUaZTFO9MJj+sMJzn9xQ08VvdUwEWgVsRRiUKEaSkTOUHl2qqGDrE961X/gGnGcW/yHdzBYObwL44jUxiA==}
/tushan@0.3.9(prop-types@15.8.1)(ts-node@10.9.1):
resolution: {integrity: sha512-qKA6NdWkstPKYE0BaxLZFiPnWXCjpiO5voZxzqln2y0FRp1hG7Zb+gChBQWyrZulAmAVjBiABjOBajpuyu7bqw==}
dependencies:
'@arco-design/web-react': 2.51.0(@types/react@18.0.20)(react-dom@18.2.0)(react@18.2.0)
'@tanstack/react-query': 4.33.0(react-dom@18.2.0)(react@18.2.0)
@ -33355,7 +33355,7 @@ packages:
immer: 9.0.21
jsonexport: 3.2.0
lodash-es: 4.17.21
postcss: 8.4.21
postcss: 8.4.27
qs: 6.11.1
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)

@ -29,7 +29,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailchat-server-sdk": "workspace:^",
"tushan": "^0.3.4",
"tushan": "^0.3.9",
"vite-express": "0.8.0"
},
"devDependencies": {

@ -159,6 +159,7 @@ export const fileFields = [
createFileSizeField('size', {
list: {
width: 120,
sort: true,
},
}),
createTextField('metaData.content-type'),
@ -170,7 +171,11 @@ export const fileFields = [
width: 80,
},
}),
createDateTimeField('createdAt'),
createDateTimeField('createdAt', {
list: {
sort: true,
},
}),
];
export const mailFields = [

@ -1,17 +1,26 @@
import filesize from 'filesize';
import React from 'react';
import React, { useState } from 'react';
import {
createTextField,
ListTable,
useAsync,
useTranslation,
Typography,
styled,
Checkbox,
} from 'tushan';
import { fileFields } from '../fields';
import { request } from '../request';
const Row = styled.div`
display: flex;
gap: 20px;
justify-content: end;
`;
export const FileList: React.FC = React.memo(() => {
const { t } = useTranslation();
const [isOnlyChatFiles, setIsOnlyChatFiles] = useState(false);
const { value: totalSize = 0 } = useAsync(async () => {
const { data } = await request.get('/file/filesizeSum');
@ -20,9 +29,19 @@ export const FileList: React.FC = React.memo(() => {
return (
<>
<Typography.Paragraph style={{ textAlign: 'right' }}>
{t('custom.file.fileTotalSize')}: {filesize(totalSize)}
</Typography.Paragraph>
<Row>
<Checkbox
checked={isOnlyChatFiles}
onClick={() => {
setIsOnlyChatFiles(!isOnlyChatFiles);
}}
>
Only show chat files
</Checkbox>
<Typography.Paragraph>
{t('custom.file.fileTotalSize')}: {filesize(totalSize)}
</Typography.Paragraph>
</Row>
<ListTable
filter={[
createTextField('q', {
@ -33,6 +52,7 @@ export const FileList: React.FC = React.memo(() => {
action={{ detail: true, delete: true }}
batchAction={{ delete: true }}
showSizeChanger={true}
meta={isOnlyChatFiles ? 'onlyChat' : undefined}
/>
</>
);

@ -10,10 +10,14 @@ import userModel from '../../../../models/user/user';
import messageModel from '../../../../models/chat/message';
import fileModel from '../../../../models/file';
import groupModel from '../../../../models/group/group';
import { raExpressMongoose } from '../middleware/express-mongoose-ra-json-server';
import {
raExpressMongoose,
virtualId,
} from '../middleware/express-mongoose-ra-json-server';
import { cacheRouter } from './cache';
import discoverModel from '../../../../plugins/com.msgbyte.discover/models/discover';
import { analyticsRouter } from './analytics';
import _ from 'lodash';
const router = Router();
@ -292,6 +296,51 @@ router.delete('/file/:id', auth(), async (req, res) => {
router.use(
'/file',
auth(),
async (req, res, next) => {
const onlyChatFile = req.query.meta === 'onlyChat';
if (!onlyChatFile) {
return next();
}
// only return chatted file rather than all file
const result = await fileModel
.aggregate()
.lookup({
from: 'users',
localField: 'url',
foreignField: 'avatar',
as: 'avatarMatchedUser',
})
.match({
'avatarMatchedUser.0': { $exists: false },
})
.project({
avatarMatchedUser: 0,
})
.facet({
metadata: [{ $count: 'total' }],
data: [
{
$sort: {
[typeof req.query._sort === 'string'
? req.query._sort === 'id'
? '_id'
: req.query._sort
: '_id']: req.query._order === 'ASC' ? 1 : -1,
},
},
{ $skip: Number(req.query._start) },
{ $limit: Number(req.query._end) - Number(req.query._start) },
],
})
.exec();
const list = _.get(result, '0.data');
const total = _.get(result, '0.metadata.0.total');
return res.set('X-Total-Count', total).json(virtualId(list)).end();
},
raExpressMongoose(fileModel, {
q: ['objectName'],
allowedRegexFields: ['objectName'],

@ -20,6 +20,7 @@ import { User } from './user/user';
},
})
@index({ bucketName: 1, objectName: 1 })
@index({ url: 1 })
export class File extends TimeStamps implements Base {
_id: Types.ObjectId;
id: string;

@ -5,6 +5,7 @@ import {
ReturnModelType,
modelOptions,
Severity,
index,
} from '@typegoose/typegoose';
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';
import type { Types } from 'mongoose';
@ -32,6 +33,7 @@ export interface UserLoginRes extends User {
allowMixed: Severity.ALLOW,
},
})
@index({ avatar: 1 })
export class User extends TimeStamps implements Base {
_id: Types.ObjectId;
id: string;

Loading…
Cancel
Save