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

merge master and resolve conflict

yuto-oweseek 4 лет назад
Родитель
Сommit
83bc04ae83
33 измененных файлов с 686 добавлено и 521 удалено
  1. 26 1
      CHANGELOG.md
  2. 1 1
      lerna.json
  3. 1 1
      package.json
  4. 2 2
      packages/app/docker/README.md
  5. 15 14
      packages/app/package.json
  6. 8 3
      packages/app/src/client/app.jsx
  7. 21 23
      packages/app/src/client/services/AppContainer.js
  8. 1 1
      packages/app/src/client/services/PageContainer.js
  9. 63 0
      packages/app/src/client/util/apiv1-client.ts
  10. 74 0
      packages/app/src/client/util/apiv3-client.ts
  11. 0 21
      packages/app/src/client/util/apiv3ErrorHandler.js
  12. 8 1
      packages/app/src/components/PageEditor/DrawioModal.jsx
  13. 17 25
      packages/app/src/components/PageList.jsx
  14. 92 32
      packages/app/src/components/Sidebar/RecentChanges.jsx
  15. 7 0
      packages/app/src/interfaces/page-tag-relation.ts
  16. 14 0
      packages/app/src/interfaces/page.ts
  17. 5 0
      packages/app/src/interfaces/paging-result.ts
  18. 9 0
      packages/app/src/interfaces/revision.ts
  19. 4 0
      packages/app/src/interfaces/tag.ts
  20. 18 0
      packages/app/src/interfaces/user.ts
  21. 78 7
      packages/app/src/server/routes/apiv3/page.js
  22. 33 0
      packages/app/src/stores/page.tsx
  23. 4 1
      packages/app/src/styles/_layout.scss
  24. 9 0
      packages/app/src/utils/swr-utils.ts
  25. 1 1
      packages/codemirror-textlint/package.json
  26. 1 1
      packages/core/package.json
  27. 1 1
      packages/plugin-attachment-refs/package.json
  28. 1 1
      packages/plugin-lsx/package.json
  29. 2 2
      packages/plugin-pukiwiki-like-linker/package.json
  30. 2 2
      packages/slack/package.json
  31. 3 3
      packages/slackbot-proxy/package.json
  32. 1 1
      packages/ui/package.json
  33. 164 376
      yarn.lock

+ 26 - 1
CHANGELOG.md

@@ -1,9 +1,34 @@
 # Changelog
 # Changelog
 
 
-## [Unreleased](https://github.com/weseek/growi/compare/v4.4.9...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v4.4.10...HEAD)
 
 
 *Please do not manually update this file. We've automated the process.*
 *Please do not manually update this file. We've automated the process.*
 
 
+## [v4.4.10](https://github.com/weseek/growi/compare/v4.4.9...v4.4.10) - 2021-11-08
+
+### 🚀 Improvement
+
+- imprv: Sidebar content header style (#4526) @yuki-takei
+
+### 🐛 Bug Fixes
+
+- fix: /pages/info API is broken (#4602) @yuki-takei
+- fix: blackboard theme location in theme list (#4506) @ayaka0417
+
+### 🧰 Maintenance
+
+- support: Use SWR (#4487) @yuki-takei
+- support: Replaced PageList with SWR (#4498) @takayuki-t
+- support: Improve devcontainer (#4510) @yuki-takei
+- support: Update passport-ldpauth from ^2.0.0 to ^3.0.1 (#4578) @LuqmanHakim-Grune
+- ci(deps): bump validator from 13.6.0 to 13.7.0 (#4588) @dependabot
+- ci(deps-dev): bump stylelint from 13.2.0 to 14.0.1 (#4583) @dependabot
+- Bump browserslist from 4.0.1 to 4.16.6 (#3776) @dependabot
+- ci(deps-dev): bump colors from 1.2.5 to 1.4.0 (#4365) @dependabot
+- ci(deps-dev): bump on-headers from 1.0.1 to 1.0.2 (#4366) @dependabot
+- ci(deps-dev): bump jquery-ui from 1.12.1 to 1.13.0 (#4549) @dependabot
+- docs(page): Add docs to /page/info api (#4531) @Mxchaeltrxn
+
 ## [v4.4.9](https://github.com/weseek/growi/compare/v4.4.8...v4.4.9) - 2021-10-18
 ## [v4.4.9](https://github.com/weseek/growi/compare/v4.4.8...v4.4.9) - 2021-10-18
 
 
 ### 💎 Features
 ### 💎 Features

+ 1 - 1
lerna.json

@@ -1,7 +1,7 @@
 {
 {
   "npmClient": "yarn",
   "npmClient": "yarn",
   "useWorkspaces": true,
   "useWorkspaces": true,
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "packages": [
   "packages": [
     "packages/*"
     "packages/*"
   ]
   ]

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "growi",
   "name": "growi",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "Team collaboration software using markdown",
   "description": "Team collaboration software using markdown",
   "tags": [
   "tags": [
     "wiki",
     "wiki",

+ 2 - 2
packages/app/docker/README.md

@@ -10,8 +10,8 @@ GROWI Official docker image
 Supported tags and respective Dockerfile links
 Supported tags and respective Dockerfile links
 ------------------------------------------------
 ------------------------------------------------
 
 
-* [`4.4.9`, `4.4`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.9/docker/Dockerfile)
-* [`4.4.9-nocdn`, `4.4-nocdn`, `4-nocdn`, `latest-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.9/docker/Dockerfile)
+* [`4.4.10`, `4.4`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.10/docker/Dockerfile)
+* [`4.4.10-nocdn`, `4.4-nocdn`, `4-nocdn`, `latest-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.4.10/docker/Dockerfile)
 * [`4.3.3`, `4.3` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 * [`4.3.3`, `4.3` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 * [`4.3.3-nocdn`, `4.3-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 * [`4.3.3-nocdn`, `4.3-nocdn` (Dockerfile)](https://github.com/weseek/growi/blob/v4.3.3/docker/Dockerfile)
 
 

+ 15 - 14
packages/app/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/app",
   "name": "@growi/app",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
     "//// for production": "",
     "//// for production": "",
@@ -33,7 +33,7 @@
     "predev:ci": "run-p resources:*",
     "predev:ci": "run-p resources:*",
     "lint:typecheck": "npx tsc",
     "lint:typecheck": "npx tsc",
     "lint:eslint": "eslint --quiet \"**/*.{js,jsx,ts,tsx}\"",
     "lint:eslint": "eslint --quiet \"**/*.{js,jsx,ts,tsx}\"",
-    "lint:styles": "stylelint src/**/*.scss",
+    "lint:styles": "stylelint src/**/*.scss --custom-syntax postcss-scss",
     "lint:swagger2openapi": "node node_modules/.bin/oas-validate tmp/swagger.json",
     "lint:swagger2openapi": "node node_modules/.bin/oas-validate tmp/swagger.json",
     "lint": "run-p lint:*",
     "lint": "run-p lint:*",
     "test": "cross-env NODE_ENV=test jest --passWithNoTests -- ",
     "test": "cross-env NODE_ENV=test jest --passWithNoTests -- ",
@@ -57,11 +57,11 @@
     "@browser-bunyan/console-formatted-stream": "^1.6.2",
     "@browser-bunyan/console-formatted-stream": "^1.6.2",
     "@godaddy/terminus": "^4.9.0",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/codemirror-textlint": "^4.4.10-RC.0",
-    "@growi/plugin-attachment-refs": "^4.4.10-RC.0",
-    "@growi/plugin-pukiwiki-like-linker": "^4.4.10-RC.0",
-    "@growi/plugin-lsx": "^4.4.10-RC.0",
-    "@growi/slack": "^4.4.10-RC.0",
+    "@growi/codemirror-textlint": "^4.4.11-RC.0",
+    "@growi/plugin-attachment-refs": "^4.4.11-RC.0",
+    "@growi/plugin-lsx": "^4.4.11-RC.0",
+    "@growi/plugin-pukiwiki-like-linker": "^4.4.11-RC.0",
+    "@growi/slack": "^4.4.11-RC.0",
     "@promster/express": "^5.1.0",
     "@promster/express": "^5.1.0",
     "@promster/server": "^6.0.3",
     "@promster/server": "^6.0.3",
     "@slack/events-api": "^3.0.0",
     "@slack/events-api": "^3.0.0",
@@ -72,7 +72,7 @@
     "array.prototype.flatmap": "^1.2.2",
     "array.prototype.flatmap": "^1.2.2",
     "async-canvas-to-blob": "^1.0.3",
     "async-canvas-to-blob": "^1.0.3",
     "aws-sdk": "^2.88.0",
     "aws-sdk": "^2.88.0",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "body-parser": "^1.18.2",
     "body-parser": "^1.18.2",
     "browser-bunyan": "^1.6.3",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
     "bunyan": "^1.8.15",
@@ -122,11 +122,11 @@
     "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",
-    "passport": "^0.4.0",
+    "passport": "^0.5.0",
     "passport-github": "^1.1.0",
     "passport-github": "^1.1.0",
     "passport-google-oauth20": "^2.0.0",
     "passport-google-oauth20": "^2.0.0",
     "passport-http": "^0.3.0",
     "passport-http": "^0.3.0",
-    "passport-ldapauth": "^2.0.0",
+    "passport-ldapauth": "^3.0.1",
     "passport-local": "^1.0.0",
     "passport-local": "^1.0.0",
     "passport-saml": "^2.2.0",
     "passport-saml": "^2.2.0",
     "passport-twitter": "^1.0.4",
     "passport-twitter": "^1.0.4",
@@ -158,7 +158,7 @@
     "@alienfast/i18next-loader": "^1.0.16",
     "@alienfast/i18next-loader": "^1.0.16",
     "@atlaskit/drawer": "^5.3.7",
     "@atlaskit/drawer": "^5.3.7",
     "@atlaskit/navigation-next": "^8.0.5",
     "@atlaskit/navigation-next": "^8.0.5",
-    "@growi/ui": "^4.4.10-RC.0",
+    "@growi/ui": "^4.4.11-RC.0",
     "@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",
@@ -202,7 +202,6 @@
     "mini-css-extract-plugin": "^0.9.0",
     "mini-css-extract-plugin": "^0.9.0",
     "morgan": "^1.10.0",
     "morgan": "^1.10.0",
     "node-dev": "^4.0.0",
     "node-dev": "^4.0.0",
-    "node-sass": "^4.14.1",
     "normalize-path": "^3.0.0",
     "normalize-path": "^3.0.0",
     "null-loader": "^3.0.0",
     "null-loader": "^3.0.0",
     "on-headers": "^1.0.1",
     "on-headers": "^1.0.1",
@@ -224,15 +223,17 @@
     "reactstrap": "^8.9.0",
     "reactstrap": "^8.9.0",
     "replacestream": "^4.0.3",
     "replacestream": "^4.0.3",
     "reveal.js": "^3.5.0",
     "reveal.js": "^3.5.0",
-    "sass-loader": "^8.0.0",
+    "sass": "^1.43.4",
+    "sass-loader": "^10.1.1",
     "simple-load-script": "^1.0.2",
     "simple-load-script": "^1.0.2",
     "socket.io-client": "^4.2.0",
     "socket.io-client": "^4.2.0",
     "sticky-events": "^3.1.3",
     "sticky-events": "^3.1.3",
     "style-loader": "^1.0.0",
     "style-loader": "^1.0.0",
     "styled-components": "^5.0.1",
     "styled-components": "^5.0.1",
-    "stylelint": "^13.2.0",
+    "stylelint": "^14.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "swagger2openapi": "^5.3.1",
     "swagger2openapi": "^5.3.1",
+    "swr": "^1.0.1",
     "terser-webpack-plugin": "^4.1.0",
     "terser-webpack-plugin": "^4.1.0",
     "throttle-debounce": "^2.0.0",
     "throttle-debounce": "^2.0.0",
     "toastr": "^2.1.2",
     "toastr": "^2.1.2",

+ 8 - 3
packages/app/src/client/app.jsx

@@ -3,7 +3,10 @@ import ReactDOM from 'react-dom';
 import { Provider } from 'unstated';
 import { Provider } from 'unstated';
 import { I18nextProvider } from 'react-i18next';
 import { I18nextProvider } from 'react-i18next';
 
 
+import { SWRConfig } from 'swr';
+
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
+import { swrGlobalConfiguration } from '~/utils/swr-utils';
 
 
 import ErrorBoundary from '../components/ErrorBoudary';
 import ErrorBoundary from '../components/ErrorBoudary';
 import Sidebar from '../components/Sidebar';
 import Sidebar from '../components/Sidebar';
@@ -156,9 +159,11 @@ Object.keys(componentMappings).forEach((key) => {
     ReactDOM.render(
     ReactDOM.render(
       <I18nextProvider i18n={i18n}>
       <I18nextProvider i18n={i18n}>
         <ErrorBoundary>
         <ErrorBoundary>
-          <Provider inject={injectableContainers}>
-            {componentMappings[key]}
-          </Provider>
+          <SWRConfig value={swrGlobalConfiguration}>
+            <Provider inject={injectableContainers}>
+              {componentMappings[key]}
+            </Provider>
+          </SWRConfig>
         </ErrorBoundary>
         </ErrorBoundary>
       </I18nextProvider>,
       </I18nextProvider>,
       elem,
       elem,

+ 21 - 23
packages/app/src/client/services/AppContainer.js

@@ -1,10 +1,13 @@
 import { Container } from 'unstated';
 import { Container } from 'unstated';
 
 
-import urljoin from 'url-join';
-
-import axios from '~/utils/axios';
 import InterceptorManager from '~/services/interceptor-manager';
 import InterceptorManager from '~/services/interceptor-manager';
 
 
+import {
+  apiDelete, apiGet, apiPost, apiRequest,
+} from '../util/apiv1-client';
+import {
+  apiv3Delete, apiv3Get, apiv3Post, apiv3Put,
+} from '../util/apiv3-client';
 import emojiStrategy from '../util/emojione/emoji_strategy_shrinked.json';
 import emojiStrategy from '../util/emojione/emoji_strategy_shrinked.json';
 import GrowiRenderer from '../util/GrowiRenderer';
 import GrowiRenderer from '../util/GrowiRenderer';
 
 
@@ -12,10 +15,8 @@ import {
   mediaQueryListForDarkMode,
   mediaQueryListForDarkMode,
   applyColorScheme,
   applyColorScheme,
 } from '../util/color-scheme';
 } from '../util/color-scheme';
-import Apiv1ErrorHandler from '../util/apiv1ErrorHandler';
 
 
 import { i18nFactory } from '../util/i18n';
 import { i18nFactory } from '../util/i18n';
-import apiv3ErrorHandler from '../util/apiv3ErrorHandler';
 
 
 /**
 /**
  * Service container related to options for Application
  * Service container related to options for Application
@@ -28,13 +29,11 @@ export default class AppContainer extends Container {
 
 
     this.state = {
     this.state = {
       preferDarkModeByMediaQuery: false,
       preferDarkModeByMediaQuery: false,
-
-      // stetes for contents
-      recentlyUpdatedPages: [],
     };
     };
 
 
+    // get csrf token from body element
+    // DO NOT REMOVE: uploading attachment data requires appContainer.csrfToken
     const body = document.querySelector('body');
     const body = document.querySelector('body');
-
     this.csrfToken = body.dataset.csrftoken;
     this.csrfToken = body.dataset.csrftoken;
 
 
     this.config = JSON.parse(document.getElementById('growi-context-hydrate').textContent || '{}');
     this.config = JSON.parse(document.getElementById('growi-context-hydrate').textContent || '{}');
@@ -60,17 +59,21 @@ export default class AppContainer extends Container {
     this.componentInstances = {};
     this.componentInstances = {};
     this.rendererInstances = {};
     this.rendererInstances = {};
 
 
-    this.apiGet = this.apiGet.bind(this);
-    this.apiPost = this.apiPost.bind(this);
-    this.apiDelete = this.apiDelete.bind(this);
-    this.apiRequest = this.apiRequest.bind(this);
+    this.apiGet = apiGet;
+    this.apiPost = apiPost;
+    this.apiDelete = apiDelete;
+    this.apiRequest = apiRequest;
+
+    this.apiv3Get = apiv3Get;
+    this.apiv3Post = apiv3Post;
+    this.apiv3Put = apiv3Put;
+    this.apiv3Delete = apiv3Delete;
 
 
-    this.apiv3Root = '/_api/v3';
     this.apiv3 = {
     this.apiv3 = {
-      get: this.apiv3Get.bind(this),
-      post: this.apiv3Post.bind(this),
-      put: this.apiv3Put.bind(this),
-      delete: this.apiv3Delete.bind(this),
+      get: apiv3Get,
+      post: apiv3Post,
+      put: apiv3Put,
+      delete: apiv3Delete,
     };
     };
   }
   }
 
 
@@ -279,11 +282,6 @@ export default class AppContainer extends Container {
     });
     });
   }
   }
 
 
-  async retrieveRecentlyUpdated() {
-    const { data } = await this.apiv3Get('/pages/recent');
-    this.setState({ recentlyUpdatedPages: data.pages });
-  }
-
   launchHandsontableModal(componentKind, beginLineNumber, endLineNumber) {
   launchHandsontableModal(componentKind, beginLineNumber, endLineNumber) {
     let targetComponent;
     let targetComponent;
     switch (componentKind) {
     switch (componentKind) {

+ 1 - 1
packages/app/src/client/services/PageContainer.js

@@ -279,7 +279,7 @@ export default class PageContainer extends Container {
         data: {
         data: {
           likerIds, sumOfLikers, isLiked, seenUserIds, sumOfSeenUsers, isSeen,
           likerIds, sumOfLikers, isLiked, seenUserIds, sumOfSeenUsers, isSeen,
         },
         },
-      } = await this.appContainer.apiv3Get('/page/info', { _id: this.state.pageId });
+      } = await this.appContainer.apiv3Get('/page/info', { pageId: this.state.pageId });
 
 
       await this.setState({
       await this.setState({
         sumOfLikers,
         sumOfLikers,

+ 63 - 0
packages/app/src/client/util/apiv1-client.ts

@@ -0,0 +1,63 @@
+import * as urljoin from 'url-join';
+
+import axios from '~/utils/axios';
+
+const apiv1Root = '/_api';
+
+// get csrf token from body element
+const body = document.querySelector('body');
+const csrfToken = body?.dataset.csrftoken;
+
+
+type ParamWithCsrfKey = {
+  _csrf: string,
+}
+
+class Apiv1ErrorHandler extends Error {
+
+  code;
+
+  constructor(message = '', code = '') {
+    super();
+
+    this.message = message;
+    this.code = code;
+  }
+
+}
+
+export async function apiRequest(method: string, path: string, params: unknown): Promise<unknown> {
+  const res = await axios[method](urljoin(apiv1Root, path), params);
+
+  if (res.data.ok) {
+    return res.data;
+  }
+
+  // Return error code if code is exist
+  if (res.data.code != null) {
+    const error = new Apiv1ErrorHandler(res.data.error, res.data.code);
+    throw error;
+  }
+
+  throw new Error(res.data.error);
+}
+
+export async function apiGet(path: string, params: unknown = {}): Promise<unknown> {
+  return apiRequest('get', path, { params });
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiPost(path: string, params: any & ParamWithCsrfKey = {}): Promise<unknown> {
+  if (params._csrf == null) {
+    params._csrf = csrfToken;
+  }
+  return apiRequest('post', path, params);
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiDelete(path: string, params: any & ParamWithCsrfKey = {}): Promise<unknown> {
+  if (params._csrf == null) {
+    params._csrf = csrfToken;
+  }
+  return apiRequest('delete', path, { data: params });
+}

+ 74 - 0
packages/app/src/client/util/apiv3-client.ts

@@ -0,0 +1,74 @@
+import * as urljoin from 'url-join';
+
+// eslint-disable-next-line no-restricted-imports
+import { AxiosResponse } from 'axios';
+
+import loggerFactory from '~/utils/logger';
+import axios from '~/utils/axios';
+import { toArrayIfNot } from '~/utils/array-utils';
+
+const apiv3Root = '/_api/v3';
+
+const logger = loggerFactory('growi:apiv3');
+
+// get csrf token from body element
+const body = document.querySelector('body');
+const csrfToken = body?.dataset.csrftoken;
+
+
+type ParamWithCsrfKey = {
+  _csrf: string,
+}
+
+const apiv3ErrorHandler = (_err) => {
+  // extract api errors from general 400 err
+  const err = _err.response ? _err.response.data.errors : _err;
+  const errs = toArrayIfNot(err);
+
+  for (const err of errs) {
+    logger.error(err.message);
+  }
+
+  return errs;
+};
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiv3Request<T = any>(method: string, path: string, params: unknown): Promise<AxiosResponse<T>> {
+  try {
+    const res = await axios[method](urljoin(apiv3Root, path), params);
+    return res.data;
+  }
+  catch (err) {
+    const errors = apiv3ErrorHandler(err);
+    throw errors;
+  }
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiv3Get<T = any>(path: string, params: unknown = {}): Promise<AxiosResponse<T>> {
+  return apiv3Request('get', path, { params });
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiv3Post<T = any>(path: string, params: any & ParamWithCsrfKey = {}): Promise<AxiosResponse<T>> {
+  if (params._csrf == null) {
+    params._csrf = csrfToken;
+  }
+  return apiv3Request('post', path, params);
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiv3Put<T = any>(path: string, params: any & ParamWithCsrfKey = {}): Promise<AxiosResponse<T>> {
+  if (params._csrf == null) {
+    params._csrf = csrfToken;
+  }
+  return apiv3Request('put', path, params);
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export async function apiv3Delete<T = any>(path: string, params: any & ParamWithCsrfKey = {}): Promise<AxiosResponse<T>> {
+  if (params._csrf == null) {
+    params._csrf = csrfToken;
+  }
+  return apiv3Request('delete', path, { params });
+}

+ 0 - 21
packages/app/src/client/util/apiv3ErrorHandler.js

@@ -1,21 +0,0 @@
-// API v3 sends an array of errors in res.data.errors.
-// API v3 errors need to extracted from an error object in order to properly handle them.
-
-import loggerFactory from '~/utils/logger';
-import { toArrayIfNot } from '~/utils/array-utils';
-
-const logger = loggerFactory('growi:apiv3');
-
-const apiv3ErrorHandler = (_err, header = 'Error') => {
-  // extract api errors from general 400 err
-  const err = _err.response ? _err.response.data.errors : _err;
-  const errs = toArrayIfNot(err);
-
-  for (const err of errs) {
-    logger.error(err.message);
-  }
-
-  return errs;
-};
-
-export default apiv3ErrorHandler;

+ 8 - 1
packages/app/src/components/PageEditor/DrawioModal.jsx

@@ -135,7 +135,14 @@ class DrawioModal extends React.PureComponent {
 
 
   render() {
   render() {
     return (
     return (
-      <Modal isOpen={this.state.show} toggle={this.cancel} className="drawio-modal" size="xl" keyboard={false}>
+      <Modal
+        isOpen={this.state.show}
+        toggle={this.cancel}
+        backdrop="static"
+        className="drawio-modal"
+        size="xl"
+        keyboard={false}
+      >
         <ModalBody className="p-0">
         <ModalBody className="p-0">
           {/* Loading spinner */}
           {/* Loading spinner */}
           <div className="w-100 h-100 position-absolute d-flex">
           <div className="w-100 h-100 position-absolute d-flex">

+ 17 - 25
packages/app/src/components/PageList.jsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useCallback, useState } from 'react';
+import React, { useState } from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import { withTranslation } from 'react-i18next';
 
 
@@ -8,39 +8,33 @@ import { withUnstatedContainers } from './UnstatedUtils';
 import AppContainer from '~/client/services/AppContainer';
 import AppContainer from '~/client/services/AppContainer';
 import PageContainer from '~/client/services/PageContainer';
 import PageContainer from '~/client/services/PageContainer';
 
 
+import { useSWRxPageList } from '~/stores/page';
+
 import PaginationWrapper from './PaginationWrapper';
 import PaginationWrapper from './PaginationWrapper';
 
 
 
 
 const PageList = (props) => {
 const PageList = (props) => {
   const { appContainer, pageContainer, t } = props;
   const { appContainer, pageContainer, t } = props;
   const { path } = pageContainer.state;
   const { path } = pageContainer.state;
-  const [pages, setPages] = useState(null);
-  const [isLoading, setIsLoading] = useState(true);
 
 
   const [activePage, setActivePage] = useState(1);
   const [activePage, setActivePage] = useState(1);
-  const [totalPages, setTotalPages] = useState(0);
-  const [limit, setLimit] = useState(Infinity);
+
+  const { data: pagesListData, error: errors } = useSWRxPageList(path, activePage);
 
 
   function setPageNumber(selectedPageNumber) {
   function setPageNumber(selectedPageNumber) {
     setActivePage(selectedPageNumber);
     setActivePage(selectedPageNumber);
   }
   }
 
 
-  const updatePageList = useCallback(async() => {
-    const page = activePage;
-    const res = await appContainer.apiv3Get('/pages/list', { path, page });
-
-    setPages(res.data.pages);
-    setIsLoading(false);
-    setTotalPages(res.data.totalCount);
-    setLimit(res.data.limit);
-  }, [appContainer, path, activePage]);
-
-  useEffect(() => {
-    updatePageList();
-  }, [updatePageList]);
-
+  if (errors != null) {
+    return (
+      <div className="my-5">
+        {/* eslint-disable-next-line react/no-array-index-key */}
+        {errors.map((error, index) => <div key={index} className="text-danger">{error.message}</div>)}
+      </div>
+    );
+  }
 
 
-  if (isLoading) {
+  if (pagesListData == null) {
     return (
     return (
       <div className="wiki">
       <div className="wiki">
         <div className="text-muted text-center">
         <div className="text-muted text-center">
@@ -51,7 +45,7 @@ const PageList = (props) => {
   }
   }
 
 
   const liClasses = props.liClasses.join(' ');
   const liClasses = props.liClasses.join(' ');
-  const pageList = pages.map(page => (
+  const pageList = pagesListData.items.map(page => (
     <li key={page._id} className={liClasses}>
     <li key={page._id} className={liClasses}>
       <Page page={page} />
       <Page page={page} />
     </li>
     </li>
@@ -81,14 +75,12 @@ const PageList = (props) => {
       <PaginationWrapper
       <PaginationWrapper
         activePage={activePage}
         activePage={activePage}
         changePage={setPageNumber}
         changePage={setPageNumber}
-        totalItemsCount={totalPages}
-        pagingLimit={limit}
+        totalItemsCount={pagesListData.totalCount}
+        pagingLimit={pagesListData.limit}
         align="center"
         align="center"
       />
       />
     </div>
     </div>
   );
   );
-
-
 };
 };
 
 
 const PageListWrapper = withUnstatedContainers(PageList, [AppContainer, PageContainer]);
 const PageListWrapper = withUnstatedContainers(PageList, [AppContainer, PageContainer]);

+ 92 - 32
packages/app/src/components/Sidebar/RecentChanges.jsx

@@ -1,20 +1,23 @@
-import React from 'react';
+import React, {
+  useCallback, useEffect, useState,
+} from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 
 
-import { withTranslation } from 'react-i18next';
+import { useTranslation, withTranslation } from 'react-i18next';
 
 
 import { UserPicture } from '@growi/ui';
 import { UserPicture } from '@growi/ui';
 import { DevidedPagePath } from '@growi/core';
 import { DevidedPagePath } from '@growi/core';
+
 import PagePathHierarchicalLink from '~/components/PagePathHierarchicalLink';
 import PagePathHierarchicalLink from '~/components/PagePathHierarchicalLink';
+import { apiv3Get } from '~/client/util/apiv3-client';
+import { toastError } from '~/client/util/apiNotification';
+import { useSWRxRecentlyUpdated } from '~/stores/page';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import LinkedPagePath from '~/models/linked-page-path';
 import LinkedPagePath from '~/models/linked-page-path';
 
 
 import FootstampIcon from '../FootstampIcon';
 import FootstampIcon from '../FootstampIcon';
 
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-import AppContainer from '~/client/services/AppContainer';
-import { toastError } from '~/client/util/apiNotification';
 
 
 import FormattedDistanceDate from '../FormattedDistanceDate';
 import FormattedDistanceDate from '../FormattedDistanceDate';
 
 
@@ -119,17 +122,82 @@ function SmallPageItem({ page }) {
 SmallPageItem.propTypes = {
 SmallPageItem.propTypes = {
   page: PropTypes.any,
   page: PropTypes.any,
 };
 };
-class RecentChanges extends React.Component {
+
+
+const RecentChanges = () => {
+
+  const { t } = useTranslation();
+  const { data: pages, error, mutate } = useSWRxRecentlyUpdated();
+
+  if (error != null) {
+    toastError(error, 'Error occurred in updating History');
+  }
+
+  const [isRecentChangesSidebarSmall, setIsRecentChangesSidebarSmall] = useState(false);
+
+  const retrieveSizePreferenceFromLocalStorage = useCallback(() => {
+    if (window.localStorage.isRecentChangesSidebarSmall === 'true') {
+      setIsRecentChangesSidebarSmall(true);
+    }
+  });
+
+  const changeSizeHandler = useCallback((e) => {
+    setIsRecentChangesSidebarSmall(e.target.checked);
+    window.localStorage.setItem('isRecentChangesSidebarSmall', e.target.checked);
+  }, []);
+
+  // componentDidMount
+  useEffect(() => {
+    retrieveSizePreferenceFromLocalStorage();
+  }, [retrieveSizePreferenceFromLocalStorage]);
+
+  return (
+    <>
+      <div className="grw-sidebar-content-header p-3 d-flex">
+        <h3 className="mb-0  text-nowrap">{t('Recent Changes')}</h3>
+        <button type="button" className="btn btn-sm ml-auto grw-btn-reload" onClick={() => mutate()}>
+          <i className="icon icon-reload"></i>
+        </button>
+        <div className="d-flex align-items-center">
+          <div className="grw-recent-changes-resize-button custom-control custom-switch ml-1">
+            <input
+              id="recentChangesResize"
+              className="custom-control-input"
+              type="checkbox"
+              checked={isRecentChangesSidebarSmall}
+              onChange={changeSizeHandler}
+            />
+            <label className="custom-control-label" htmlFor="recentChangesResize">
+            </label>
+          </div>
+        </div>
+      </div>
+      <div className="grw-sidebar-content-body grw-recent-changes p-3">
+        <ul className="list-group list-group-flush">
+          {(pages || []).map(page => (isRecentChangesSidebarSmall
+            ? <SmallPageItem key={page._id} page={page} />
+            : <LargePageItem key={page._id} page={page} />))}
+        </ul>
+      </div>
+    </>
+  );
+
+};
+
+// export default RecentChanges;
+
+
+class DeprecatedRecentChanges extends React.Component {
 
 
   static propTypes = {
   static propTypes = {
     t: PropTypes.func.isRequired, // i18next
     t: PropTypes.func.isRequired, // i18next
-    appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   };
   };
 
 
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
     this.state = {
     this.state = {
       isRecentChangesSidebarSmall: false,
       isRecentChangesSidebarSmall: false,
+      recentlyUpdatedPages: [],
     };
     };
     this.reloadData = this.reloadData.bind(this);
     this.reloadData = this.reloadData.bind(this);
   }
   }
@@ -143,10 +211,9 @@ class RecentChanges extends React.Component {
   }
   }
 
 
   async reloadData() {
   async reloadData() {
-    const { appContainer } = this.props;
-
     try {
     try {
-      await appContainer.retrieveRecentlyUpdated();
+      const { data } = await apiv3Get('/pages/recent');
+      this.setState({ recentlyUpdatedPages: data.pages });
     }
     }
     catch (error) {
     catch (error) {
       logger.error('failed to save', error);
       logger.error('failed to save', error);
@@ -171,32 +238,30 @@ class RecentChanges extends React.Component {
 
 
   render() {
   render() {
     const { t } = this.props;
     const { t } = this.props;
-    const { recentlyUpdatedPages } = this.props.appContainer.state;
 
 
     return (
     return (
       <>
       <>
         <div className="grw-sidebar-content-header p-3 d-flex">
         <div className="grw-sidebar-content-header p-3 d-flex">
-          <h3 className="mb-0  text-nowrap">{t('Recent Changes')}</h3>
-          <button type="button" className="btn btn-sm ml-auto grw-btn-reload" onClick={this.reloadData}>
+          <h3 className="mb-0">{t('Recent Changes')}</h3>
+          {/* <h3 className="mb-0">{t('Recent Created')}</h3> */} {/* TODO: impl switching */}
+          <button type="button" className="btn btn-sm ml-auto grw-btn-reload-rc" onClick={this.reloadData}>
             <i className="icon icon-reload"></i>
             <i className="icon icon-reload"></i>
           </button>
           </button>
-          <div className="d-flex align-items-center">
-            <div className="grw-recent-changes-resize-button custom-control custom-switch ml-1">
-              <input
-                id="recentChangesResize"
-                className="custom-control-input"
-                type="checkbox"
-                checked={this.state.isRecentChangesSidebarSmall}
-                onChange={this.changeSizeHandler}
-              />
-              <label className="custom-control-label" htmlFor="recentChangesResize">
-              </label>
-            </div>
+          <div className="grw-recent-changes-resize-button custom-control custom-switch ml-2">
+            <input
+              id="recentChangesResize"
+              className="custom-control-input"
+              type="checkbox"
+              checked={this.state.isRecentChangesSidebarSmall}
+              onChange={this.changeSizeHandler}
+            />
+            <label className="custom-control-label" htmlFor="recentChangesResize">
+            </label>
           </div>
           </div>
         </div>
         </div>
         <div className="grw-sidebar-content-body grw-recent-changes p-3">
         <div className="grw-sidebar-content-body grw-recent-changes p-3">
           <ul className="list-group list-group-flush">
           <ul className="list-group list-group-flush">
-            {recentlyUpdatedPages.map(page => (this.state.isRecentChangesSidebarSmall
+            {this.state.recentlyUpdatedPages.map(page => (this.state.isRecentChangesSidebarSmall
               ? <SmallPageItem key={page._id} page={page} />
               ? <SmallPageItem key={page._id} page={page} />
               : <LargePageItem key={page._id} page={page} />))}
               : <LargePageItem key={page._id} page={page} />))}
           </ul>
           </ul>
@@ -207,10 +272,5 @@ class RecentChanges extends React.Component {
 
 
 }
 }
 
 
-/**
- * Wrapper component for using unstated
- */
-const RecentChangesWrapper = withUnstatedContainers(RecentChanges, [AppContainer]);
-
 
 
-export default withTranslation()(RecentChangesWrapper);
+export default withTranslation()(DeprecatedRecentChanges);

+ 7 - 0
packages/app/src/interfaces/page-tag-relation.ts

@@ -0,0 +1,7 @@
+import { IPage } from './page';
+import { ITag } from './tag';
+
+export type IPageTagRelation = {
+  relatedPage: IPage,
+  relatedTag: ITag,
+}

+ 14 - 0
packages/app/src/interfaces/page.ts

@@ -0,0 +1,14 @@
+import { IUser } from './user';
+import { IRevision } from './revision';
+import { ITag } from './tag';
+
+export type IPage = {
+  path: string,
+  status: string,
+  revision: IRevision,
+  tags: ITag[],
+  creator: IUser,
+  createdAt: Date,
+  updatedAt: Date,
+  seenUsers: string[]
+}

+ 5 - 0
packages/app/src/interfaces/paging-result.ts

@@ -0,0 +1,5 @@
+export type IPagingResult<T> = {
+  items: T[],
+  totalCount: number,
+  limit: number,
+}

+ 9 - 0
packages/app/src/interfaces/revision.ts

@@ -0,0 +1,9 @@
+import { IUser } from './user';
+
+export type IRevision = {
+  body: string,
+  author: IUser,
+  hasDiffToPrev: boolean;
+  createdAt: Date,
+  updatedAt: Date,
+}

+ 4 - 0
packages/app/src/interfaces/tag.ts

@@ -0,0 +1,4 @@
+export type ITag = {
+  name: string,
+  createdAt: Date;
+}

+ 18 - 0
packages/app/src/interfaces/user.ts

@@ -0,0 +1,18 @@
+export type IUser = {
+  name: string;
+  username: string;
+  imageUrlCached: string;
+  admin: boolean;
+}
+
+export type IUserGroupRelation = {
+  relatedGroup: IUserGroup,
+  relatedUser: IUser,
+  createdAt: Date,
+}
+
+export type IUserGroup = {
+  userGroupId:string;
+  name: string;
+  createdAt: Date;
+}

+ 78 - 7
packages/app/src/server/routes/apiv3/page.js

@@ -112,6 +112,52 @@ const ErrorV3 = require('../../models/vo/error-apiv3');
  *          bool:
  *          bool:
  *            type: boolean
  *            type: boolean
  *            description: boolean for like status
  *            description: boolean for like status
+ *
+ *      PageInfo:
+ *        description: PageInfo
+ *        type: object
+ *        required:
+ *          - isSeen
+ *          - sumOfLikers
+ *          - likerIds
+ *          - sumOfSeenUsers
+ *          - seenUserIds
+ *        properties:
+ *          isSeen:
+ *            type: boolean
+ *            description: Whether the page has ever been seen
+ *          isLiked:
+ *            type: boolean
+ *            description: Whether the page is liked by the logged in user
+ *          sumOfLikers:
+ *            type: number
+ *            description: Number of users who have liked the page
+ *          likerIds:
+ *            type: array
+ *            items:
+ *              type: string
+ *            description: Ids of users who have liked the page
+ *            example: ["5e07345972560e001761fa63"]
+ *          sumOfSeenUsers:
+ *            type: number
+ *            description: Number of users who have seen the page
+ *          seenUserIds:
+ *            type: array
+ *            items:
+ *              type: string
+ *            description: Ids of users who have seen the page
+ *            example: ["5e07345972560e001761fa63"]
+ *
+ *      PageParams:
+ *        description: PageParams
+ *        type: object
+ *        required:
+ *          - pageId
+ *        properties:
+ *          pageId:
+ *            type: string
+ *            description: page ID
+ *            example: 5e07345972560e001761fa63
  */
  */
 module.exports = (crowi) => {
 module.exports = (crowi) => {
   const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
   const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
@@ -130,6 +176,9 @@ module.exports = (crowi) => {
       body('pageId').isString(),
       body('pageId').isString(),
       body('bool').isBoolean(),
       body('bool').isBoolean(),
     ],
     ],
+    info: [
+      query('pageId').isMongoId().withMessage('pageId is required'),
+    ],
     export: [
     export: [
       query('format').isString().isIn(['md', 'pdf']),
       query('format').isString().isIn(['md', 'pdf']),
       query('revisionId').isString(),
       query('revisionId').isString(),
@@ -208,10 +257,34 @@ module.exports = (crowi) => {
     }
     }
   });
   });
 
 
-  router.get(('/info', loginRequired), async(req, res) => {
+  /**
+   * @swagger
+   *
+   *    /page/info:
+   *      get:
+   *        tags: [Page]
+   *        summary: /page/info
+   *        description: Retrieve current page info
+   *        operationId: getPageInfo
+   *        requestBody:
+   *          content:
+   *            application/json:
+   *              schema:
+   *                $ref: '#/components/schemas/PageParams'
+   *        responses:
+   *          200:
+   *            description: Successfully retrieved current page info.
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  $ref: '#/components/schemas/PageInfo'
+   *          500:
+   *            description: Internal server error.
+   */
+  router.get('/info', loginRequired, validator.info, apiV3FormValidator, async(req, res) => {
+    const { pageId } = req.query;
 
 
     try {
     try {
-      const pageId = req.query._id;
       const page = await Page.findById(pageId);
       const page = await Page.findById(pageId);
 
 
       const guestUserResponse = {
       const guestUserResponse = {
@@ -222,11 +295,9 @@ module.exports = (crowi) => {
         isSeen: page.seenUsers.length > 0,
         isSeen: page.seenUsers.length > 0,
       };
       };
 
 
-      {
-        const isGuestUser = !req.user;
-        if (isGuestUser) {
-          return res.apiv3(guestUserResponse);
-        }
+      const isGuestUser = !req.user;
+      if (isGuestUser) {
+        return res.apiv3(guestUserResponse);
       }
       }
 
 
       const userResponse = { ...guestUserResponse, isLiked: page.isLiked(req.user) };
       const userResponse = { ...guestUserResponse, isLiked: page.isLiked(req.user) };

+ 33 - 0
packages/app/src/stores/page.tsx

@@ -0,0 +1,33 @@
+import useSWR, { SWRResponse } from 'swr';
+
+import { apiv3Get } from '~/client/util/apiv3-client';
+
+import { IPage } from '~/interfaces/page';
+import { IPagingResult } from '~/interfaces/paging-result';
+
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export const useSWRxRecentlyUpdated = <Data, Error>(): SWRResponse<IPage[], Error> => {
+  return useSWR(
+    '/pages/recent',
+    endpoint => apiv3Get<{ pages: IPage[] }>(endpoint).then(response => response.data?.pages),
+  );
+};
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export const useSWRxPageList = (
+    path: string,
+    pageNumber?: number,
+): SWRResponse<IPagingResult<IPage>, Error> => {
+  const page = pageNumber || 1;
+  return useSWR(
+    `/pages/list?path=${path}&page=${page}`,
+    endpoint => apiv3Get<{pages: IPage[], totalCount: number, limit: number}>(endpoint).then((response) => {
+      return {
+        items: response.data.pages,
+        totalCount: response.data.totalCount,
+        limit: response.data.limit,
+      };
+    }),
+  );
+};

+ 4 - 1
packages/app/src/styles/_layout.scss

@@ -99,11 +99,14 @@ body.growi-layout-fluid .grw-container-convertible {
 
 
 // printable style
 // printable style
 @media print {
 @media print {
-  padding: 30px;
+  body {
+    padding: 30px;
+  }
 
 
   a:after {
   a:after {
     display: none !important;
     display: none !important;
   }
   }
+
   .main {
   .main {
     header {
     header {
       border-bottom: solid 1px $secondary;
       border-bottom: solid 1px $secondary;

+ 9 - 0
packages/app/src/utils/swr-utils.ts

@@ -0,0 +1,9 @@
+import { SWRConfiguration } from 'swr';
+
+import axios from './axios';
+
+export const swrGlobalConfiguration: SWRConfiguration = {
+  fetcher: url => axios.get(url).then(res => res.data),
+  revalidateOnFocus: false,
+  errorRetryCount: 1,
+};

+ 1 - 1
packages/codemirror-textlint/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/codemirror-textlint",
   "name": "@growi/codemirror-textlint",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/index.js",
   "main": "dist/index.js",
   "scripts": {
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/core",
   "name": "@growi/core",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI Core Libraries",
   "description": "GROWI Core Libraries",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 1 - 1
packages/plugin-attachment-refs/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/plugin-attachment-refs",
   "name": "@growi/plugin-attachment-refs",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI Plugin to add ref/refimg/refs/refsimg tags",
   "description": "GROWI Plugin to add ref/refimg/refs/refsimg tags",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 1 - 1
packages/plugin-lsx/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/plugin-lsx",
   "name": "@growi/plugin-lsx",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI plugin to list pages",
   "description": "GROWI plugin to list pages",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 2 - 2
packages/plugin-pukiwiki-like-linker/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/plugin-pukiwiki-like-linker",
   "name": "@growi/plugin-pukiwiki-like-linker",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI plugin to add PukiwikiLikeLinker",
   "description": "GROWI plugin to add PukiwikiLikeLinker",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [
@@ -22,7 +22,7 @@
   },
   },
   "devDependencies": {
   "devDependencies": {
     "browser-bunyan": "^1.6.3",
     "browser-bunyan": "^1.6.3",
-    "stylelint": "^13.2.0",
+    "stylelint": "^14.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "stylelint-config-recess-order": "^2.0.1",
     "tsc-alias": "^1.2.9"
     "tsc-alias": "^1.2.9"
   }
   }

+ 2 - 2
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/slack",
   "name": "@growi/slack",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/index.js",
   "main": "dist/index.js",
   "typings": "dist/index.d.ts",
   "typings": "dist/index.d.ts",
@@ -14,7 +14,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@slack/oauth": "^2.0.1",
     "@slack/oauth": "^2.0.1",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "browser-bunyan": "^1.6.3",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
     "bunyan": "^1.8.15",
     "extensible-custom-error": "^0.0.7",
     "extensible-custom-error": "^0.0.7",

+ 3 - 3
packages/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/slackbot-proxy",
   "name": "@growi/slackbot-proxy",
-  "version": "4.4.10-slackbot-proxy.0",
+  "version": "4.4.11-slackbot-proxy.0",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
@@ -25,7 +25,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^4.4.10-RC.0",
+    "@growi/slack": "^4.4.11-RC.0",
     "@slack/oauth": "^2.0.1",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",
     "@tsed/common": "^6.43.0",
@@ -33,7 +33,7 @@
     "@tsed/platform-express": "^6.43.0",
     "@tsed/platform-express": "^6.43.0",
     "@tsed/swagger": "^6.43.0",
     "@tsed/swagger": "^6.43.0",
     "@tsed/typeorm": "^6.43.0",
     "@tsed/typeorm": "^6.43.0",
-    "axios": "^0.21.1",
+    "axios": "^0.24.0",
     "browser-bunyan": "^1.6.3",
     "browser-bunyan": "^1.6.3",
     "bunyan": "^1.8.15",
     "bunyan": "^1.8.15",
     "compression": "^1.7.4",
     "compression": "^1.7.4",

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/ui",
   "name": "@growi/ui",
-  "version": "4.4.10-RC.0",
+  "version": "4.4.11-RC.0",
   "description": "GROWI UI Libraries",
   "description": "GROWI UI Libraries",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

Разница между файлами не показана из-за своего большого размера
+ 164 - 376
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов