-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implementions of announcement creation function #8715
base: feat/announcement-function
Are you sure you want to change the base?
Changes from 30 commits
6451ce7
b2fee4e
a2b50b2
5b5ddb8
26b3786
b9db316
4b9bcc0
7bc44a5
331794e
3064298
924d3e7
bbf853a
a6df789
9f992b9
f1b99be
12fdce9
ba7fad9
c15a124
fc4662d
d9f2013
bf6a25d
dbe2818
c83a629
c88e3ef
ca53ba1
7a28945
9cd6f18
f6de616
a8a2761
950f254
7eb1c6c
c60ac35
d560f70
bd33ca5
a87b1ca
615e657
1481713
6dc961f
7736dde
f52a5f5
c6893d4
45e69ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { | ||
IPage, IUser, IUserHasId, Ref, | ||
} from '@growi/core'; | ||
|
||
import { type IAnnouncement, type ParamsForAnnouncement } from '~/interfaces/announcement'; | ||
|
||
import { apiv3Post } from '../../../../client/util/apiv3-client'; | ||
import { toastError } from '../../../../client/util/toastr'; | ||
|
||
export const createAnnouncement = async(params: ParamsForAnnouncement): Promise<void> => { | ||
|
||
try { | ||
await apiv3Post('/announcement/doAnnouncement', params); | ||
} | ||
catch (err) { | ||
toastError(err); | ||
} | ||
|
||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,10 @@ | ||
import { | ||
Types, Document, Schema, Model, | ||
} from 'mongoose'; | ||
import type { Types, Document, Model } from 'mongoose'; | ||
import { Schema } from 'mongoose'; | ||
|
||
import { IAnnouncement } from '../../../../interfaces/announcement'; | ||
import type { IAnnouncement } from '../../../../interfaces/announcement'; | ||
import { getOrCreateModel } from '../../../../server/util/mongoose-utils'; | ||
import { AnnouncementStatuses } from '../events/announcement-utils'; | ||
|
||
type AnnouncementStatuses = typeof AnnouncementStatuses; | ||
|
||
export interface AnnouncementDocument extends IAnnouncement, Document { | ||
_id: Types.ObjectId | ||
} | ||
|
@@ -58,6 +55,12 @@ const AnnouncementSchema = new Schema<AnnouncementDocument>({ | |
], | ||
}, {}); | ||
|
||
AnnouncementSchema.statics.createByParameters = async function(parameters): Promise<IAnnouncement> { | ||
const announcement = await this.create(parameters) as IAnnouncement; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as を使わず記述してください There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as を消去し、修正しました。 |
||
|
||
return announcement; | ||
}; | ||
|
||
const Announcement = getOrCreateModel<AnnouncementDocument, AnnouncementModel>('Announcement', AnnouncementSchema); | ||
|
||
export { Announcement }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import type { IPage } from '@growi/core'; | ||
|
||
import { Announcement, AnnouncementStatuses } from '~/features/announcement'; | ||
import type { IAnnouncement, ParamsForAnnouncement } from '~/interfaces/announcement'; | ||
|
||
import type Crowi from '../../../../server/crowi'; | ||
import type { ActivityDocument } from '../../../../server/models/activity'; | ||
import type { PreNotifyProps } from '../../../../server/service/pre-notify'; | ||
|
||
export default class AnnouncementService { | ||
|
||
crowi!: Crowi; | ||
|
||
activityEvent: any; | ||
|
||
constructor(crowi: Crowi) { | ||
this.crowi = crowi; | ||
this.activityEvent = crowi.event('activity'); | ||
|
||
this.getReadRate = this.getReadRate.bind(this); | ||
this.insertAnnouncement = this.insertAnnouncement.bind(this); | ||
this.doAnnounce = this.doAnnounce.bind(this); | ||
|
||
} | ||
|
||
getReadRate = async() => {}; | ||
|
||
insertAnnouncement = async( | ||
params: ParamsForAnnouncement, | ||
): Promise<void> => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private を付けよう There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private method にしました。 |
||
|
||
const { | ||
sender, comment, emoji, isReadReceiptTrackingEnabled, pageId, receivers, | ||
} = params; | ||
|
||
const announcement: IAnnouncement = { | ||
sender, | ||
comment, | ||
emoji, | ||
isReadReceiptTrackingEnabled, | ||
pageId, | ||
receivers: receivers.map((receiver) => { | ||
return { | ||
receiver, | ||
readStatus: AnnouncementStatuses.STATUS_UNREAD, | ||
}; | ||
}), | ||
}; | ||
|
||
const operation = [{ | ||
insertOne: { | ||
document: announcement, | ||
}, | ||
}]; | ||
|
||
await Announcement.bulkWrite(operation); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bulkWrite しないといけない理由ある? |
||
|
||
return; | ||
|
||
}; | ||
|
||
doAnnounce = async(activity: ActivityDocument, target: IPage, params: ParamsForAnnouncement): Promise<void> => { | ||
|
||
this.insertAnnouncement(params); | ||
|
||
const preNotify = async(props: PreNotifyProps) => { | ||
|
||
const { notificationTargetUsers } = props; | ||
|
||
notificationTargetUsers?.push(...params.receivers); | ||
}; | ||
|
||
this.activityEvent.emit('updated', activity, target, preNotify); | ||
|
||
}; | ||
|
||
} | ||
|
||
module.exports = AnnouncementService; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ExternalAccountService を参考に、singleton instance をこのモジュールで export するようにしてください There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. singleton instanceをexportするようにしました。 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import type { Router } from 'express'; | ||
import { | ||
body, param, query, validationResult, | ||
} from 'express-validator'; | ||
|
||
import { SupportedTargetModel, SupportedAction } from '~/interfaces/activity'; | ||
import type { ParamsForAnnouncement } from '~/interfaces/announcement'; | ||
import type { CrowiRequest } from '~/interfaces/crowi-request'; | ||
import type Crowi from '~/server/crowi'; | ||
|
||
|
||
const express = require('express'); | ||
|
||
const router = express.Router(); | ||
|
||
module.exports = (crowi: Crowi): Router => { | ||
|
||
const { Page } = crowi.models; | ||
|
||
const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi); | ||
|
||
const validators = { | ||
doAnnouncement: [ | ||
body('sender').exists({ checkFalsy: true }), | ||
body('comment').optional({ nullable: true }).isString(), | ||
body('emoji').optional({ nullable: true }).isString(), | ||
body('isReadReceiptTrackingEnabled').exists().isBoolean(), | ||
body('pageId').exists({ checkFalsy: true }), | ||
body('receivers').exists({ checkFalsy: true }).isArray(), | ||
], | ||
}; | ||
|
||
router.post('/doAnnouncement', loginRequiredStrictly, validators.doAnnouncement, async(req: CrowiRequest) => { | ||
|
||
const params: ParamsForAnnouncement = req.body; | ||
|
||
const page = await Page.findById(params.pageId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. req.paramsではpageIdが正しく取得できなかったため、この形にしています。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. クライアントのリクエスト方法がパスパラメーターで取得できるかたちになっていないのでは? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /:id を用いることで、pageIdをパスパラメータで取得できるようにしました。 |
||
|
||
const parametersForActivity = { | ||
ip: req.ip, | ||
endpoint: req.originalUrl, | ||
user: req.user?._id, | ||
target: page, | ||
targetModel: SupportedTargetModel.MODEL_ANNOUNCEMENT, | ||
action: SupportedAction.ACTION_USER_ANNOUNCE, | ||
snapshot: { | ||
username: req.user?.username, | ||
}, | ||
}; | ||
|
||
const activity = await crowi.activityService.createActivity(parametersForActivity); | ||
miya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
crowi.announcementService.doAnnounce(activity, page, params); | ||
|
||
}); | ||
|
||
return router; | ||
|
||
}; | ||
miya marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,9 @@ module.exports = function(crowi, app) { | |
const preNotify = async(props) => { | ||
const adminUsers = await User.findAdmins(); | ||
|
||
props.push(...adminUsers); | ||
const { notificationTargetUsers } = props; | ||
|
||
notificationTargetUsers.push(...adminUsers); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これは現存する何かしらのバグの修正? |
||
}; | ||
|
||
await activityEvent.emit('updated', activity, user, preNotify); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toastr の表示は view の責務
このユーティリティは DAO/サービス層に分類されるので不適切