Shun Miyazawa 4 лет назад
Родитель
Сommit
8b2c0505f5

+ 3 - 3
packages/app/src/components/Admin/AuditLog/SelectQueryDropdown.tsx

@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
 type SelectQueryDropdownProps = {
   dropdownLabel: string
   dropdownItemList: string[]
-  setQueryHandler: (query: string) => void
+  setQueryHandler: (query: string | undefined) => void
 }
 
 export const SelectQueryDropdown: FC<SelectQueryDropdownProps> = (props: SelectQueryDropdownProps) => {
@@ -14,7 +14,7 @@ export const SelectQueryDropdown: FC<SelectQueryDropdownProps> = (props: SelectQ
 
   const { dropdownLabel, dropdownItemList, setQueryHandler } = props;
 
-  const [selectedItem, setSelectedItem] = useState('');
+  const [selectedItem, setSelectedItem] = useState<string | undefined>(undefined);
 
   const onClickItemButton = useCallback((item) => {
     if (setQueryHandler == null) {
@@ -28,7 +28,7 @@ export const SelectQueryDropdown: FC<SelectQueryDropdownProps> = (props: SelectQ
     <div className="btn-group mr-2 mb-3">
       <div className="dropdown">
         <button className="btn btn-outline-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown">
-          {selectedItem !== '' ? selectedItem : t(`admin:audit_log_management.${dropdownLabel}`)}
+          {selectedItem === undefined ? t(`admin:audit_log_management.${dropdownLabel}`) : selectedItem}
         </button>
         <ul className="dropdown-menu" aria-labelledby="dropdownMenuButton">
           {

+ 12 - 8
packages/app/src/components/Admin/AuditLogManagement.tsx

@@ -18,9 +18,13 @@ export const AuditLogManagement: FC = () => {
 
   const [activePage, setActivePage] = useState<number>(1);
   const offset = (activePage - 1) * PAGING_LIMIT;
-  const [actionQuery, setActionQuery] = useState('');
+  const [actionQuery, setActionQuery] = useState<string | undefined>(undefined);
 
-  const { data: activityListData, error } = useSWRxActivityList(PAGING_LIMIT, offset);
+  const query = {
+    action: actionQuery,
+  };
+
+  const { data: activityListData, error } = useSWRxActivityList(PAGING_LIMIT, offset, query);
   const activityList = activityListData?.docs != null ? activityListData.docs : [];
   const totalActivityNum = activityListData?.totalDocs != null ? activityListData.totalDocs : 0;
   const isLoading = activityListData === undefined && error == null;
@@ -33,6 +37,12 @@ export const AuditLogManagement: FC = () => {
     <div data-testid="admin-auditlog">
       <h2>{t('AuditLog')}</h2>
 
+      <SelectQueryDropdown
+        dropdownLabel="select_action"
+        dropdownItemList={AllSupportedActionType}
+        setQueryHandler={setActionQuery}
+      />
+
       { isLoading
         ? (
           <div className="text-muted text-center mb-5">
@@ -41,12 +51,6 @@ export const AuditLogManagement: FC = () => {
         )
         : (
           <>
-            <SelectQueryDropdown
-              dropdownLabel="select_action"
-              dropdownItemList={AllSupportedActionType}
-              setQueryHandler={setActionQuery}
-            />
-
             <ActivityTable activityList={activityList} />
             <PaginationWrapper
               activePage={activePage}

+ 1 - 1
packages/app/src/interfaces/activity.ts

@@ -48,7 +48,7 @@ export const AllSupportedActionType = Object.values(SUPPORTED_ACTION_TYPE);
 
 type supportedTargetModelType = typeof SUPPORTED_TARGET_MODEL_TYPE[keyof typeof SUPPORTED_TARGET_MODEL_TYPE];
 // type supportedEventModelType = typeof SUPPORTED_EVENT_MODEL_TYPE[keyof typeof SUPPORTED_EVENT_MODEL_TYPE];
-type supportedActionType = typeof SUPPORTED_ACTION_TYPE[keyof typeof SUPPORTED_ACTION_TYPE];
+export type supportedActionType = typeof SUPPORTED_ACTION_TYPE[keyof typeof SUPPORTED_ACTION_TYPE];
 
 export type IActivity = {
   user?: IUser

+ 2 - 2
packages/app/src/server/models/activity.ts

@@ -104,9 +104,9 @@ activitySchema.post('save', async(savedActivity: ActivityDocument) => {
   activityEvent.emit('create', targetUsers, savedActivity);
 });
 
-activitySchema.statics.getPaginatedActivity = async function(limit: number, offset: number) {
+activitySchema.statics.getPaginatedActivity = async function(limit: number, offset: number, query) {
   const paginateResult = await this.paginate(
-    {},
+    query,
     {
       limit,
       offset,

+ 4 - 2
packages/app/src/server/routes/apiv3/activity.ts

@@ -20,12 +20,13 @@ const validator = {
   list: [
     query('limit').optional().isInt({ max: 100 }).withMessage('limit must be a number less than or equal to 100'),
     query('offset').optional().isInt().withMessage('page must be a number'),
+    query('query').optional().isString().withMessage('query must be a string'),
   ],
 };
 
 const apiLimiter = rateLimit({
   windowMs: 15 * 60 * 1000, // 15 minutes
-  max: 10, // limit each IP to 10 requests per windowMs
+  max: 30, // limit each IP to 30 requests per windowMs
   message:
     'Too many requests sent from this IP, please try again after 15 minutes.',
 });
@@ -41,9 +42,10 @@ module.exports = (crowi: Crowi): Router => {
   router.get('/', apiLimiter, accessTokenParser, loginRequiredStrictly, adminRequired, validator.list, apiV3FormValidator, async(req: Request, res: ApiV3Response) => {
     const limit = req.query.limit || await crowi.configManager?.getConfig('crowi', 'customize:showPageLimitationS') || 10;
     const offset = req.query.offset || 1;
+    const query = req.query.query as string || '';
 
     try {
-      const paginationResult = await Activity.getPaginatedActivity(limit, offset);
+      const paginationResult = await Activity.getPaginatedActivity(limit, offset, JSON.parse(query));
 
       const User = crowi.model('User');
       const serializedDocs = paginationResult.docs.map((doc: IActivity) => {

+ 9 - 3
packages/app/src/stores/activity.ts

@@ -5,9 +5,15 @@ import { apiv3Get } from '../client/util/apiv3-client';
 import { IActivityHasId } from '../interfaces/activity';
 import { PaginateResult } from '../interfaces/mongoose-utils';
 
-export const useSWRxActivityList = (limit?: number, offset?: number): SWRResponse<PaginateResult<IActivityHasId>, Error> => {
+type IQuery = {
+  action?: string
+}
+
+export const useSWRxActivityList = (limit?: number, offset?: number, query?: IQuery): SWRResponse<PaginateResult<IActivityHasId>, Error> => {
+  const stringifiedQuery = JSON.stringify(query);
   return useSWRImmutable(
-    ['/activity', limit, offset],
-    (endpoint, limit, offset) => apiv3Get(endpoint, { limit, offset }).then(result => result.data.serializedPaginationResult),
+    ['/activity', limit, offset, stringifiedQuery],
+    (endpoint, limit, offset, stringifiedQuery) => apiv3Get(endpoint, { limit, offset, query: stringifiedQuery })
+      .then(result => result.data.serializedPaginationResult),
   );
 };