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

add UserUISettings model and router to CRUD

Yuki Takei 4 лет назад
Родитель
Сommit
d779bf77f9

+ 6 - 0
packages/app/src/interfaces/ui.ts

@@ -0,0 +1,6 @@
+export const SidebarContents = {
+  CUSTOM: 'custom',
+  RECENT: 'recent',
+} as const;
+export const AllSidebarContents = Object.values(SidebarContents);
+export type SidebarContents = typeof SidebarContents[keyof typeof SidebarContents];

+ 10 - 0
packages/app/src/interfaces/user-ui-settings.ts

@@ -0,0 +1,10 @@
+import { IUser } from './user';
+
+import { SidebarContents } from './ui';
+
+export interface IUserUISettings {
+  userId: IUser | string;
+  isSidebarCollapsed: boolean,
+  selectedSidebarContents: SidebarContents,
+  currentProductNavWidth: number,
+}

+ 26 - 0
packages/app/src/server/models/user-ui-settings.ts

@@ -0,0 +1,26 @@
+import {
+  Schema, Model, Document,
+} from 'mongoose';
+
+import { getOrCreateModel } from '@growi/core';
+
+import { SidebarContents as SidebarContentType } from '~/interfaces/ui';
+import { IUserUISettings } from '~/interfaces/user-ui-settings';
+
+
+export interface UserUISettingsDocument extends IUserUISettings, Document {}
+export type UserUISettingsModel = Model<UserUISettingsDocument>
+
+const schema = new Schema<IUserUISettings>({
+  user: { type: Schema.Types.ObjectId, ref: 'User', index: true },
+  isSidebarCollapsed: { type: Boolean, default: false },
+  selectedSidebarContents: {
+    type: String,
+    enum: SidebarContentType,
+    default: SidebarContentType.RECENT,
+  },
+  currentProductNavWidth: { type: Number },
+});
+
+
+export default getOrCreateModel<UserUISettingsDocument, UserUISettingsModel>('UserUISettings', schema);

+ 2 - 0
packages/app/src/server/routes/apiv3/index.js

@@ -53,5 +53,7 @@ module.exports = (crowi) => {
 
   router.use('/forgot-password', require('./forgot-password')(crowi));
 
+  router.use('/user-ui-settings', require('./user-ui-settings')(crowi));
+
   return router;
 };

+ 71 - 0
packages/app/src/server/routes/apiv3/user-ui-settings.ts

@@ -0,0 +1,71 @@
+import express from 'express';
+import { body } from 'express-validator';
+import { AllSidebarContents } from '~/interfaces/ui';
+
+import loggerFactory from '~/utils/logger';
+
+import UserUISettings from '../../models/user-ui-settings';
+import ErrorV3 from '../../models/vo/error-apiv3';
+
+const logger = loggerFactory('growi:routes:apiv3:user-ui-settings');
+
+const router = express.Router();
+
+module.exports = (crowi) => {
+  const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
+  const csrf = require('../../middlewares/csrf')(crowi);
+  const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
+
+  const validatorForPut = [
+    body('settings').exists().withMessage('The body param \'settings\' is required'),
+    body('settings.isSidebarCollapsed').optional().isBoolean(),
+    body('settings.selectedSidebarContents').optional().isIn(AllSidebarContents),
+    body('settings.currentProductNavWidth').optional().isNumeric(),
+  ];
+
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  router.get('/', loginRequiredStrictly, async(req: any, res: any) => {
+    const { user } = req;
+
+    try {
+      const updatedSettings = await UserUISettings.findOneAndUpdate(
+        { user: user._id },
+        { user: user._id },
+        { upsert: true },
+      );
+      return res.apiv3(updatedSettings);
+    }
+    catch (err) {
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(err));
+    }
+  });
+
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  router.put('/', loginRequiredStrictly, csrf, validatorForPut, apiV3FormValidator, async(req: any, res: any) => {
+    const { user } = req;
+    const { settings } = req.body;
+
+    // extract only necessary params
+    const updateData = {
+      isSidebarCollapsed: settings.isSidebarCollapsed,
+      selectedSidebarContents: settings.selectedSidebarContents,
+      currentProductNavWidth: settings.currentProductNavWidth,
+    };
+
+    try {
+      const updatedSettings = await UserUISettings.findOneAndUpdate(
+        { user: user._id },
+        { user: user._id, ...updateData },
+        { upsert: true },
+      );
+      return res.apiv3(updatedSettings);
+    }
+    catch (err) {
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(err));
+    }
+  });
+
+  return router;
+};

+ 1 - 6
packages/app/src/stores/ui.tsx

@@ -2,6 +2,7 @@ import { Key, useSWRConfig, SWRResponse } from 'swr';
 
 import { Breakpoint, addBreakpointListener } from '@growi/ui';
 
+import { SidebarContents } from '~/interfaces/ui';
 import loggerFactory from '~/utils/logger';
 
 import { sessionStorageMiddleware } from './middlewares/sync-to-storage';
@@ -23,12 +24,6 @@ export const EditorMode = {
 } as const;
 export type EditorMode = typeof EditorMode[keyof typeof EditorMode];
 
-export const SidebarContents = {
-  CUSTOM: 'custom',
-  RECENT: 'recent',
-} as const;
-export type SidebarContents = typeof SidebarContents[keyof typeof SidebarContents];
-
 
 /** **********************************************************
  *                          SWR Hooks