Просмотр исходного кода

Merge pull request #4479 from weseek/imprv/#78956-apply-popurate-to-growi-way

Imprv/#78956 apply popurate to growi way
Yuki Takei 4 лет назад
Родитель
Сommit
f9a9f2ba2f

+ 3 - 2
packages/app/package.json

@@ -55,8 +55,8 @@
     "@browser-bunyan/console-formatted-stream": "^1.6.2",
     "@browser-bunyan/console-formatted-stream": "^1.6.2",
     "@google-cloud/storage": "^5.8.5",
     "@google-cloud/storage": "^5.8.5",
     "@growi/plugin-attachment-refs": "^4.4.3-RC.0",
     "@growi/plugin-attachment-refs": "^4.4.3-RC.0",
-    "@growi/plugin-pukiwiki-like-linker": "^4.4.3-RC.0",
     "@growi/plugin-lsx": "^4.4.3-RC.0",
     "@growi/plugin-lsx": "^4.4.3-RC.0",
+    "@growi/plugin-pukiwiki-like-linker": "^4.4.3-RC.0",
     "@growi/slack": "^4.4.3-RC.0",
     "@growi/slack": "^4.4.3-RC.0",
     "@promster/express": "^5.0.1",
     "@promster/express": "^5.0.1",
     "@promster/server": "^6.0.0",
     "@promster/server": "^6.0.0",
@@ -96,7 +96,6 @@
     "graceful-fs": "^4.1.11",
     "graceful-fs": "^4.1.11",
     "growi-commons": "^5.0.4",
     "growi-commons": "^5.0.4",
     "helmet": "^4.6.0",
     "helmet": "^4.6.0",
-    "nocache": "^3.0.1",
     "http-errors": "~1.6.2",
     "http-errors": "~1.6.2",
     "i18next": "^20.3.2",
     "i18next": "^20.3.2",
     "i18next-express-middleware": "^2.0.0",
     "i18next-express-middleware": "^2.0.0",
@@ -114,6 +113,7 @@
     "mongoose-unique-validator": "^2.0.3",
     "mongoose-unique-validator": "^2.0.3",
     "multer": "~1.4.0",
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
     "multer-autoreap": "^1.0.3",
+    "nocache": "^3.0.1",
     "nodemailer": "^6.6.2",
     "nodemailer": "^6.6.2",
     "nodemailer-ses-transport": "~1.5.0",
     "nodemailer-ses-transport": "~1.5.0",
     "openid-client": "=2.5.0",
     "openid-client": "=2.5.0",
@@ -157,6 +157,7 @@
     "@handsontable/react": "=2.1.0",
     "@handsontable/react": "=2.1.0",
     "@types/compression": "^1.7.0",
     "@types/compression": "^1.7.0",
     "@types/express": "^4.17.11",
     "@types/express": "^4.17.11",
+    "@types/mongoose-paginate-v2": "1.3.9",
     "@types/multer": "^1.4.5",
     "@types/multer": "^1.4.5",
     "@types/react-dom": "^17.0.9",
     "@types/react-dom": "^17.0.9",
     "autoprefixer": "^9.0.0",
     "autoprefixer": "^9.0.0",

+ 2 - 2
packages/app/src/components/InAppNotification/InAppNotificationDropdown.tsx

@@ -86,10 +86,10 @@ const InAppNotificationDropdown: FC = (props) => {
     */
     */
 
 
   const fetchNotificationList = async(props) => {
   const fetchNotificationList = async(props) => {
-    console.log('propsappContainerHoge', props.appContainer);
     const limit = 6;
     const limit = 6;
     try {
     try {
-      const notifications = await props.appContainer.apiv3Get('/in-app-notification/list', { limit });
+      const inAppNotificationList = await props.appContainer.apiv3Get('/in-app-notification/list', { limit });
+
       // setNotifications(notifications);
       // setNotifications(notifications);
       // setIsLoaded(true);
       // setIsLoaded(true);
     }
     }

+ 8 - 18
packages/app/src/server/models/in-app-notification.ts

@@ -1,7 +1,9 @@
 import {
 import {
-  Types, Document, Model, Schema /* , Query */,
+  Types, Document, PaginateModel, Schema, /* , Query */
 } from 'mongoose';
 } from 'mongoose';
+import mongoosePaginate from 'mongoose-paginate-v2';
 import ActivityDefine from '../util/activityDefine';
 import ActivityDefine from '../util/activityDefine';
+import { ActivityDocument } from './activity';
 import { getOrCreateModel } from '../util/mongoose-utils';
 import { getOrCreateModel } from '../util/mongoose-utils';
 import loggerFactory from '../../utils/logger';
 import loggerFactory from '../../utils/logger';
 
 
@@ -18,13 +20,14 @@ export interface InAppNotificationDocument extends Document {
   targetModel: string
   targetModel: string
   target: Types.ObjectId
   target: Types.ObjectId
   action: string
   action: string
-  activities: Types.ObjectId[]
+  activities: ActivityDocument[]
   status: string
   status: string
   createdAt: Date
   createdAt: Date
 }
 }
 
 
-export interface InAppNotificationModel extends Model<InAppNotificationDocument> {
-  findLatestInAppNotificationsByUser(user: Types.ObjectId, skip: number, offset: number): Promise<InAppNotificationDocument[]>
+
+export interface InAppNotificationModel extends PaginateModel<InAppNotificationDocument> {
+  findLatestInAppNotificationsByUser(user: Types.ObjectId, skip: number, offset: number)
   getUnreadCountByUser(user: Types.ObjectId): Promise<number | undefined>
   getUnreadCountByUser(user: Types.ObjectId): Promise<number | undefined>
   open(user, id: Types.ObjectId): Promise<InAppNotificationDocument | null>
   open(user, id: Types.ObjectId): Promise<InAppNotificationDocument | null>
   read(user) /* : Promise<Query<any>> */
   read(user) /* : Promise<Query<any>> */
@@ -74,6 +77,7 @@ const inAppNotificationSchema = new Schema<InAppNotificationDocument, InAppNotif
     default: Date.now,
     default: Date.now,
   },
   },
 });
 });
+inAppNotificationSchema.plugin(mongoosePaginate);
 
 
 const transform = (doc, ret) => {
 const transform = (doc, ret) => {
   // delete ret.activities
   // delete ret.activities
@@ -84,20 +88,6 @@ inAppNotificationSchema.index({
   user: 1, target: 1, action: 1, createdAt: 1,
   user: 1, target: 1, action: 1, createdAt: 1,
 });
 });
 
 
-inAppNotificationSchema.statics.findLatestInAppNotificationsByUser = async function(user, limitNum, offset) {
-  const limit = limitNum || 10;
-
-  // TODO: improve populate refer to GROWI way by #78756
-  const notificatins = await InAppNotification.find({ user });
-  // .sort({ createdAt: -1 })
-  // .skip(offset)
-  // .limit(limit)
-  // .populate(['user', 'target'])
-  // .populate({ path: 'activities', populate: { path: 'user' } })
-  // .exec();
-  return notificatins;
-};
-
 inAppNotificationSchema.statics.STATUS_UNOPENED = function() {
 inAppNotificationSchema.statics.STATUS_UNOPENED = function() {
   return STATUS_UNOPENED;
   return STATUS_UNOPENED;
 };
 };

+ 1 - 0
packages/app/src/server/models/index.js

@@ -1,4 +1,5 @@
 module.exports = {
 module.exports = {
+  Activity: require('./activity'),
   Page: require('./page'),
   Page: require('./page'),
   // TODO GW-2746 bulk export pages
   // TODO GW-2746 bulk export pages
   // PageArchive: require('./page-archive'),
   // PageArchive: require('./page-archive'),

+ 4 - 29
packages/app/src/server/routes/apiv3/in-app-notification.ts

@@ -9,8 +9,9 @@ module.exports = (crowi) => {
   const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
   const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
   const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
   const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
   const csrf = require('../../middlewares/csrf')(crowi);
   const csrf = require('../../middlewares/csrf')(crowi);
+  const inAppNotificationService = crowi.inAppNotificationService;
 
 
-  router.get('/list', accessTokenParser, loginRequiredStrictly, (req, res) => {
+  router.get('/list', accessTokenParser, loginRequiredStrictly, async(req, res) => {
     const user = req.user;
     const user = req.user;
 
 
     let limit = 10;
     let limit = 10;
@@ -25,35 +26,9 @@ module.exports = (crowi) => {
 
 
     const requestLimit = limit + 1;
     const requestLimit = limit + 1;
 
 
+    const latestInAppNotificationList = await inAppNotificationService.getLatestNotificationsByUser(user._id, requestLimit, offset);
+    return latestInAppNotificationList;
 
 
-    /**
-     * TODO: GW-7482
-     *   -  Replace then/catch to async/awai
-     *   -  Use mongoose-paginate-v2 for paging
-     */
-    InAppNotification.findLatestInAppNotificationsByUser(user._id, requestLimit, offset)
-      .then((notifications) => {
-        let hasPrev = false;
-        if (offset > 0) {
-          hasPrev = true;
-        }
-
-        let hasNext = false;
-        if (notifications.length > limit) {
-          hasNext = true;
-        }
-
-        const result = {
-          notifications: notifications.slice(0, limit),
-          hasPrev,
-          hasNext,
-        };
-
-        return res.apiv3(result);
-      })
-      .catch((err) => {
-        return res.apiv3Err(err);
-      });
   });
   });
 
 
   router.get('/status', accessTokenParser, loginRequiredStrictly, async(req, res) => {
   router.get('/status', accessTokenParser, loginRequiredStrictly, async(req, res) => {

+ 58 - 0
packages/app/src/server/service/in-app-notification.ts

@@ -70,6 +70,64 @@ export default class InAppNotificationService {
     return;
     return;
   }
   }
 
 
+  getLatestNotificationsByUser = async(userId, limitNum, offset) => {
+
+    try {
+      const pagenatedInAppNotifications = await InAppNotification.paginate(
+        { user: userId },
+        {
+          sort: { createdAt: -1 },
+          offset,
+          limit: limitNum || 10,
+          populate: [
+            { path: 'user' },
+            { path: 'target' },
+            { path: 'activities', populate: { path: 'user' } },
+          ],
+        },
+      );
+    }
+    catch (err) {
+      logger.error('Error', err);
+      throw new Error(err);
+    }
+
+    try {
+      /**
+       * TODO: return results including notifications,hasPrev and hasNext by #78991
+       * refer to https://github.com/crowi/crowi/blob/eecf2bc821098d2516b58104fe88fae81497d3ea/lib/controllers/notification.ts
+       */
+      // Notification.findLatestNotificationsByUser(user._id, requestLimit, offset)
+      // .then(function (notifications) {
+      //   let hasPrev = false
+      //   if (offset > 0) {
+      //     hasPrev = true
+      //   }
+
+      //   let hasNext = false
+      //   if (notifications.length > limit) {
+      //     hasNext = true
+      //   }
+
+      //   const result = {
+      //     notifications: notifications.slice(0, limit),
+      //     hasPrev: hasPrev,
+      //     hasNext: hasNext,
+      //   }
+
+      //   return res.json(ApiResponse.success(result))
+      // })
+      // .catch(function (err) {
+      //   return res.json(ApiResponse.error(err))
+      // })
+
+    }
+    catch (err) {
+      logger.error('Error', err);
+      throw new Error(err);
+    }
+  }
+
   // inAppNotificationSchema.virtual('actionUsers').get(function(this: InAppNotificationDocument) {
   // inAppNotificationSchema.virtual('actionUsers').get(function(this: InAppNotificationDocument) {
   //   const Activity = getModelSafely('Activity') || require('../models/activity')(this.crowi);
   //   const Activity = getModelSafely('Activity') || require('../models/activity')(this.crowi);
   //   return Activity.getActionUsersFromActivities((this.activities as any) as ActivityDocument[]);
   //   return Activity.getActionUsersFromActivities((this.activities as any) as ActivityDocument[]);

+ 15 - 1
yarn.lock

@@ -2914,6 +2914,20 @@
     "@types/bson" "*"
     "@types/bson" "*"
     "@types/node" "*"
     "@types/node" "*"
 
 
+"@types/mongoose-paginate-v2@1.3.9":
+  version "1.3.9"
+  resolved "https://registry.yarnpkg.com/@types/mongoose-paginate-v2/-/mongoose-paginate-v2-1.3.9.tgz#a211bf0da49473e9e1f1a65d3aacbd5d5ff0408c"
+  integrity sha512-NHqTgOZRmi7gd/IkRJ2VXo88m0efKatLFrG63VEcAB98nO6nzbeRaXPUUgEFJ2Le6vleTE0WqvAuL0gO5IQF5A==
+  dependencies:
+    "@types/mongoose" "*"
+
+"@types/mongoose@*":
+  version "5.11.97"
+  resolved "https://registry.yarnpkg.com/@types/mongoose/-/mongoose-5.11.97.tgz#80b0357f3de6807eb597262f52e49c3e13ee14d8"
+  integrity sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==
+  dependencies:
+    mongoose "*"
+
 "@types/multer@^1.4.5":
 "@types/multer@^1.4.5":
   version "1.4.5"
   version "1.4.5"
   resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.5.tgz#db0557562307e9adb6661a9500c334cd7ddd0cd9"
   resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.5.tgz#db0557562307e9adb6661a9500c334cd7ddd0cd9"
@@ -13305,7 +13319,7 @@ mongoose-valid8@>=1.6.18:
     lodash ">=4.17.15"
     lodash ">=4.17.15"
     validator ">=13.0.0"
     validator ">=13.0.0"
 
 
-mongoose@5.12.13:
+mongoose@*, mongoose@5.12.13:
   version "5.12.13"
   version "5.12.13"
   resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.12.13.tgz#6707fb2f6284536bb6367c94ccc3ce85475a387d"
   resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.12.13.tgz#6707fb2f6284536bb6367c94ccc3ce85475a387d"
   integrity sha512-QGn1FCzZ8Z+mMGVg8oR2kQw4NmhLloCHsw1NqKWg3Yr7WfPzkE4pe7s9P6o5pkYGsku17n9mqMHowne7EFK/zQ==
   integrity sha512-QGn1FCzZ8Z+mMGVg8oR2kQw4NmhLloCHsw1NqKWg3Yr7WfPzkE4pe7s9P6o5pkYGsku17n9mqMHowne7EFK/zQ==