Преглед изворни кода

Merge pull request #10001 from weseek/pdf-converter-1.1.0

Release pdf converter 1.1.0
Yuki Takei пре 10 месеци
родитељ
комит
7650dac950
100 измењених фајлова са 524 додато и 187 уклоњено
  1. 1 0
      .devcontainer/app/devcontainer.json
  2. 3 0
      .devcontainer/app/postCreateCommand.sh
  3. 1 0
      .devcontainer/pdf-converter/devcontainer.json
  4. 2 2
      .github/workflows/ci-app.yml
  5. 1 1
      .github/workflows/ci-slackbot-proxy.yml
  6. 1 1
      .github/workflows/reusable-app-create-manifests.yml
  7. 23 5
      .github/workflows/reusable-app-prod.yml
  8. 1 1
      .github/workflows/reusable-app-reg-suit.yml
  9. 9 0
      .roo/mcp.json
  10. 13 0
      .vscode/settings.json
  11. 109 1
      CHANGELOG.md
  12. 9 7
      README.md
  13. 16 13
      README_JP.md
  14. 9 2
      apps/app/bin/swagger-jsdoc/definition-apiv1.js
  15. 23 3
      apps/app/bin/swagger-jsdoc/definition-apiv3.js
  16. 4 0
      apps/app/bin/swagger-jsdoc/generate-spec-apiv3.sh
  17. 28 18
      apps/app/docker/Dockerfile
  18. 12 9
      apps/app/package.json
  19. 2 0
      apps/app/playwright.config.ts
  20. 0 15
      apps/app/playwright/20-basic-features/presentation.spec.ts
  21. 19 13
      apps/app/playwright/20-basic-features/use-tools.spec.ts
  22. 26 5
      apps/app/public/static/locales/en_US/translation.json
  23. 26 6
      apps/app/public/static/locales/fr_FR/translation.json
  24. 27 7
      apps/app/public/static/locales/ja_JP/translation.json
  25. 26 6
      apps/app/public/static/locales/zh_CN/translation.json
  26. 29 1
      apps/app/resource/Contributor.js
  27. 1 1
      apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx
  28. 3 0
      apps/app/src/client/components/Admin/App/AwsSetting.tsx
  29. 3 0
      apps/app/src/client/components/Admin/App/AzureSetting.tsx
  30. 1 1
      apps/app/src/client/components/Admin/App/FileUploadSetting.tsx
  31. 3 0
      apps/app/src/client/components/Admin/App/GcsSetting.tsx
  32. 1 1
      apps/app/src/client/components/Admin/App/MaskedInput.tsx
  33. 1 1
      apps/app/src/client/components/Admin/App/PageBulkExportSettings.tsx
  34. 1 1
      apps/app/src/client/components/Admin/App/QuestionnaireSettings.tsx
  35. 1 1
      apps/app/src/client/components/Admin/Common/AdminInstallButtonRow.tsx
  36. 1 1
      apps/app/src/client/components/Admin/Common/AdminUpdateButtonRow.tsx
  37. 1 1
      apps/app/src/client/components/Admin/Common/LabeledProgressBar.tsx
  38. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeCssSetting.tsx
  39. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeFunctionOption.tsx
  40. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeFunctionSetting.tsx
  41. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeLayoutSetting.tsx
  42. 2 2
      apps/app/src/client/components/Admin/Customize/CustomizeLogoSetting.tsx
  43. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeNoscriptSetting.tsx
  44. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizePresentationSetting.tsx
  45. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeScriptSetting.tsx
  46. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeSidebarSetting.tsx
  47. 1 1
      apps/app/src/client/components/Admin/Customize/CustomizeThemeOptions.tsx
  48. 3 1
      apps/app/src/client/components/Admin/Customize/CustomizeThemeSetting.tsx
  49. 1 1
      apps/app/src/client/components/Admin/Customize/ThemeColorBox.tsx
  50. 1 1
      apps/app/src/client/components/Admin/ElasticsearchManagement/NormalizeIndicesControls.tsx
  51. 1 1
      apps/app/src/client/components/Admin/ElasticsearchManagement/ReconnectControls.tsx
  52. 1 1
      apps/app/src/client/components/Admin/ExportArchiveData/ArchiveFilesTable.tsx
  53. 1 1
      apps/app/src/client/components/Admin/ExportArchiveData/ArchiveFilesTableMenu.tsx
  54. 3 1
      apps/app/src/client/components/Admin/ExportArchiveData/SelectCollectionsModal.tsx
  55. 3 1
      apps/app/src/client/components/Admin/ExportArchiveDataPage.tsx
  56. 1 1
      apps/app/src/client/components/Admin/ForbiddenPage.tsx
  57. 1 1
      apps/app/src/client/components/Admin/FullTextSearchManagement.tsx
  58. 1 1
      apps/app/src/client/components/Admin/G2GDataTransfer.tsx
  59. 1 1
      apps/app/src/client/components/Admin/G2GDataTransferExportForm.tsx
  60. 1 1
      apps/app/src/client/components/Admin/G2GDataTransferStatusIcon.tsx
  61. 1 1
      apps/app/src/client/components/Admin/ImportData/GrowiArchive/ErrorViewer.tsx
  62. 1 1
      apps/app/src/client/components/Admin/ManageExternalAccount.tsx
  63. 1 1
      apps/app/src/client/components/Admin/MarkdownSetting/MarkDownSettingContents.tsx
  64. 1 1
      apps/app/src/client/components/Admin/MarkdownSetting/WhitelistInput.tsx
  65. 1 1
      apps/app/src/client/components/Admin/NotFoundPage.tsx
  66. 1 1
      apps/app/src/client/components/Admin/Notification/ManageGlobalNotification.tsx
  67. 1 1
      apps/app/src/client/components/Admin/Notification/NotificationTypeIcon.tsx
  68. 1 1
      apps/app/src/client/components/Admin/Security/LdapAuthTest.tsx
  69. 1 1
      apps/app/src/client/components/Admin/SlackIntegration/BotTypeCard.tsx
  70. 3 0
      apps/app/src/client/components/Admin/SlackIntegration/Bridge.tsx
  71. 1 1
      apps/app/src/client/components/Admin/SlackIntegration/CustomBotWithProxyConnectionStatus.tsx
  72. 1 1
      apps/app/src/client/components/Admin/SlackIntegration/CustomBotWithoutProxyConnectionStatus.tsx
  73. 2 1
      apps/app/src/client/components/Admin/SlackIntegration/MessageBasedOnConnection.jsx
  74. 3 0
      apps/app/src/client/components/Admin/SlackIntegration/SlackAppIntegrationControl.tsx
  75. 3 1
      apps/app/src/client/components/Admin/SlackIntegration/SlackIntegration.tsx
  76. 2 1
      apps/app/src/client/components/Admin/UserGroup/UserGroupDropdown.tsx
  77. 1 1
      apps/app/src/client/components/Admin/UserGroup/UserGroupTable.tsx
  78. 1 1
      apps/app/src/client/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx
  79. 3 1
      apps/app/src/client/components/Admin/UserGroupDetail/UserGroupPageList.tsx
  80. 1 1
      apps/app/src/client/components/Admin/UserGroupDetail/UserGroupUserModal.tsx
  81. 1 1
      apps/app/src/client/components/Admin/UserGroupDetail/UserGroupUserTable.tsx
  82. 1 1
      apps/app/src/client/components/Admin/Users/ExternalAccountTable.tsx
  83. 1 1
      apps/app/src/client/components/Admin/Users/GrantAdminButton.tsx
  84. 1 1
      apps/app/src/client/components/Admin/Users/GrantReadOnlyButton.tsx
  85. 1 1
      apps/app/src/client/components/Admin/Users/RevokeAdminButton.tsx
  86. 1 1
      apps/app/src/client/components/Admin/Users/RevokeAdminMenuItem.tsx
  87. 1 1
      apps/app/src/client/components/Admin/Users/RevokeReadOnlyMenuItem.tsx
  88. 1 1
      apps/app/src/client/components/Admin/Users/SortIcons.tsx
  89. 1 1
      apps/app/src/client/components/Admin/Users/StatusSuspendMenuItem.tsx
  90. 2 0
      apps/app/src/client/components/AlertSiteUrlUndefined.tsx
  91. 2 2
      apps/app/src/client/components/AuthorInfo/AuthorInfo.module.scss
  92. 1 1
      apps/app/src/client/components/AuthorInfo/AuthorInfo.tsx
  93. 1 1
      apps/app/src/client/components/Bookmarks/BookmarkFolderItemControl.tsx
  94. 3 1
      apps/app/src/client/components/Bookmarks/BookmarkFolderMenu.tsx
  95. 1 1
      apps/app/src/client/components/Bookmarks/BookmarkFolderNameInput.tsx
  96. 2 2
      apps/app/src/client/components/Bookmarks/BookmarkFolderTree.module.scss
  97. 1 1
      apps/app/src/client/components/Bookmarks/BookmarkItem.tsx
  98. 1 1
      apps/app/src/client/components/Bookmarks/BookmarkItemRenameInput.tsx
  99. 1 1
      apps/app/src/client/components/Bookmarks/DragAndDropWrapper.tsx
  100. 3 1
      apps/app/src/client/components/Comments.tsx

+ 1 - 0
.devcontainer/app/devcontainer.json

@@ -24,6 +24,7 @@
     "vscode": {
       "extensions": [
         "dbaeumer.vscode-eslint",
+        "biomejs.biome",
         "mhutchie.git-graph",
         "eamodio.gitlens",
         "github.vscode-pull-request-github",

+ 3 - 0
.devcontainer/app/postCreateCommand.sh

@@ -11,6 +11,9 @@ mkdir -p /tmp/page-bulk-export
 sudo chown -R vscode:vscode /tmp/page-bulk-export
 sudo chmod 700 /tmp/page-bulk-export
 
+# Install uv
+curl -LsSf https://astral.sh/uv/install.sh | sh
+
 # Setup pnpm
 SHELL=bash pnpm setup
 eval "$(cat /home/vscode/.bashrc)"

+ 1 - 0
.devcontainer/pdf-converter/devcontainer.json

@@ -16,6 +16,7 @@
     "vscode": {
       "extensions": [
         "dbaeumer.vscode-eslint",
+        "biomejs.biome",
         "mhutchie.git-graph",
         "eamodio.gitlens"
       ],

+ 2 - 2
.github/workflows/ci-app.yml

@@ -74,7 +74,7 @@ jobs:
 
       - name: Lint
         run: |
-          turbo run lint --filter=!@growi/slackbot-proxy
+          turbo run lint --filter=@growi/app --filter=./packages/*
 
       - name: Slack Notification
         uses: weseek/ghaction-slack-notification@master
@@ -128,7 +128,7 @@ jobs:
 
       - name: Test
         run: |
-          turbo run test --filter=!@growi/slackbot-proxy --env-mode=loose
+          turbo run test --filter=@growi/app --filter=./packages/* --env-mode=loose
         env:
           MONGO_URI: mongodb://localhost:${{ job.services.mongodb.ports['27017'] }}/growi_test
 

+ 1 - 1
.github/workflows/ci-slackbot-proxy.yml

@@ -59,7 +59,7 @@ jobs:
 
     - name: Lint
       run: |
-        turbo run lint --filter=@growi/slackbot-proxy
+        turbo run lint --filter=@growi/slackbot-proxy --filter=@growi/slack
 
     - name: Slack Notification
       uses: weseek/ghaction-slack-notification@master

+ 1 - 1
.github/workflows/reusable-app-create-manifests.yml

@@ -45,7 +45,7 @@ jobs:
         password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
 
     - name: Create and push manifest images
-      uses: Noelware/docker-manifest-action@master
+      uses: Noelware/docker-manifest-action@0.4.3
       with:
         base-image: ${{ inputs.tags }}
         extra-images: ${{ steps.meta-extra-images.outputs.tags }}

+ 23 - 5
.github/workflows/reusable-app-prod.yml

@@ -262,12 +262,19 @@ jobs:
         MONGO_URI: mongodb://mongodb:27017/growi-playwright-guest-mode
         ELASTICSEARCH_URI: http://localhost:${{ job.services.elasticsearch.ports['9200'] }}/growi
 
-    - name: Upload test results
+    - name: Generate shard ID
+      id: shard-id
       if: always()
+      run: |
+        SHARD_ID=$(echo "${{ matrix.shard }}" | tr '/' '-')
+        echo "shard_id=${SHARD_ID}" >> $GITHUB_OUTPUT
+
+    - name: Upload test results
       uses: actions/upload-artifact@v4
+      if: always()
       with:
-        name: blob-report-${{ matrix.shard }}
-        path: blob-report
+        name: blob-report-${{ matrix.browser }}-${{ steps.shard-id.outputs.shard_id }}
+        path: ./apps/app/blob-report
         retention-days: 30
 
     - name: Slack Notification
@@ -302,10 +309,21 @@ jobs:
       run: |
         pnpm install --frozen-lockfile
 
+    - name: Download blob reports
+      uses: actions/download-artifact@v4
+      with:
+        pattern: blob-report-*
+        path: all-blob-reports
+        merge-multiple: true
+
     - name: Merge into HTML Report
       run: |
-        mkdir -p all-blob-reports
-        pnpm playwright merge-reports --reporter html ./all-blob-reports
+        mkdir -p playwright-report
+        if [ -z "$(ls all-blob-reports/*.zip all-blob-reports/*.blob 2>/dev/null || true)" ]; then
+          echo "<html><body><h1>No test results available</h1><p>This could be because tests were skipped or all artifacts were not available.</p></body></html>" > playwright-report/index.html
+        else
+          pnpm playwright merge-reports --reporter html all-blob-reports
+        fi
 
     - name: Upload HTML report
       uses: actions/upload-artifact@v4

+ 1 - 1
.github/workflows/reusable-app-reg-suit.yml

@@ -1,4 +1,4 @@
-name: Reusable build app workflow for production
+name: Reusable VRT reporting workflow for production
 
 on:
   workflow_call:

+ 9 - 0
.roo/mcp.json

@@ -0,0 +1,9 @@
+{
+  "mcpServers": {
+    "fetch": {
+      "command": "uvx",
+      "args": ["mcp-server-fetch"],
+      "alwaysAllow": ["fetch"]
+    }
+  }
+}

+ 13 - 0
.vscode/settings.json

@@ -3,6 +3,14 @@
 
   "eslint.workingDirectories": [{ "mode": "auto" }],
 
+  "[typescript]": {
+    "editor.defaultFormatter": "biomejs.biome"
+  },
+
+  "[javascript]": {
+    "editor.defaultFormatter": "biomejs.biome"
+  },
+
   // use vscode-stylelint
   // see https://github.com/stylelint/vscode-stylelint
   "stylelint.validate": ["css", "less", "scss"],
@@ -13,10 +21,14 @@
 
   "editor.codeActionsOnSave": {
     "source.fixAll.eslint": "explicit",
+    "source.fixAll.biome": "explicit",
+    "source.organizeImports.biome": "explicit",
     "source.fixAll.markdownlint": "explicit",
     "source.fixAll.stylelint": "explicit"
   },
 
+  "editor.formatOnSave": true,
+
   "githubPullRequests.ignoredPullRequestBranches": [
     "master"
   ],
@@ -28,4 +40,5 @@
   "typescript.surveys.enabled": false,
 
   "vitest.filesWatcherInclude": "**/*"
+
 }

+ 109 - 1
CHANGELOG.md

@@ -1,9 +1,117 @@
 # Changelog
 
-## [Unreleased](https://github.com/weseek/growi/compare/v7.2.0...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v7.2.5...HEAD)
 
 *Please do not manually update this file. We've automated the process.*
 
+## [v7.2.5](https://github.com/weseek/growi/compare/v7.2.4...v7.2.5) - 2025-05-28
+
+### 💎 Features
+
+* feat: Save attachment to VectorStore (#9906) @miya
+
+### 🚀 Improvement
+
+* imprv: Headers and CopyDropdown UX (#9973) @yuki-takei
+* imprv(api): Support Bearer token (#9971) @yuki-takei
+* imprv: Add orgId and appId to bulk export path (#9946) @arafubeatbox
+
+### 🐛 Bug Fixes
+
+* fix: Prevent submission during text composition in SearchTypeahead (#9977) @miya
+* fix(ai): First user message is not displayed (#9976) @miya
+* fix: Vectorstore file not rebuilt after page update (#9951) @miya
+
+### 🧰 Maintenance
+
+* ci(deps-dev): bump vite from 5.4.17 to 5.4.19 (#9911) @[dependabot[bot]](https://github.com/apps/dependabot)
+* support: Prevent SSRF for slack integration (#9952) @yuki-takei
+* support: Remark lsx package biome migration (#9948) @arafubeatbox
+* support: UI package biome migration (#9945) @arafubeatbox
+* support: Migrate linter/formatter to biome for @growi/slack package (#9917) @arafubeatbox
+
+## [v7.2.4](https://github.com/weseek/growi/compare/v7.2.3...v7.2.4) - 2025-05-15
+
+### 🐛 Bug Fixes
+
+* fix: Picture size (#9938) @yuki-takei
+
+## [v7.2.3](https://github.com/weseek/growi/compare/v7.2.2...v7.2.3) - 2025-05-14
+
+### 💎 Features
+
+* feat(ai): Unified merge view (#9643) @yuki-takei
+
+### 🚀 Improvement
+
+* imprv(ai): AI models and instructions (#9913) @yuki-takei
+* imprv(ai): Evaluate article headers (#9921) @yuki-takei
+* imprv(ai): Tidy up instructions (#9918) @yuki-takei
+* imprv: Disable page bulk export when file upload settings are not configured (#9900) @arafubeatbox
+* imprv: add contributors that has not been added to konami command (#9901) @Ryosei-Fukushima
+* imprv(ai): AI models and instructions (#9913) @yuki-takei
+* imprv: Hide summary mode switch in editor assistant mode (#9897) @miya
+* imprv: User picture tooltip (#9892) @yuki-takei
+* imprv: User picture tooltip (2) (#9898) @yuki-takei
+
+### 🐛 Bug Fixes
+
+* fix: PagePathHeader maxWidth for editor (#9930) @yuki-takei
+* fix: Pages list API (#9928) @yuki-takei
+* fix: Set OpenTelemetry resource attribute `service.instance.id` (#9902) @yuki-takei
+* fix: User picture tooltip (2) (#9898) @yuki-takei
+* fix: ConfigLoader.loadFromDB for JSON parsing error handling (#9890) @yuki-takei
+* fix: Profile image upload functionality and accepted file types (#9886) @yuki-takei
+* fix: Tooltip for UserPicture doesn't work (#9884) @yuki-takei
+
+### 🧰 Maintenance
+
+* support: Improve the official docker image size (#9874) @yuki-takei
+* support: Upgrade openai package (#9909) @yuki-takei
+* support(pdf-converter): Improve the official docker image size for pdf-converter (#9880) @yuki-takei
+* support: Improve the official docker image size (#9874) @yuki-takei
+
+## [v7.2.2](https://github.com/weseek/growi/compare/v7.2.1...v7.2.2) - 2025-04-17
+
+### 🐛 Bug Fixes
+
+* fix: Export page API is broken (#9870) @yuki-takei
+
+## [v7.2.1](https://github.com/weseek/growi/compare/v7.2.0...v7.2.1) - 2025-04-16
+
+### 💎 Features
+
+* feat: Page bulk export (pdf export included) (#9678) @arafubeatbox
+
+### 🚀 Improvement
+
+* imprv: Add util method to get react instance of growi via growifacade (#9775) @NaokiHigashi28
+* imprv: Adjust comment editor clickable area (#9840) @yuki-takei
+* imprv: Make user activation middleware securely (#9818) @yuki-takei
+* imprv: Prepare to upgrade React and Next.js (#9816) @yuki-takei
+
+### 🐛 Bug Fixes
+
+* fix: The order of multer middleware (#9772) @NaokiHigashi28
+* fix: growi pluginkit growifacade typo (#9812) @NaokiHigashi28
+* fix: Migration script to remove index for 'ns' from config collection (#9770) @yuki-takei
+* fix: Assistant remains default when made unpublished (#9763) @miya
+* fix: Fix layout when safari browse (#9744) @satof3
+* fix:  Prevent GrowiPlugin from being downloaded outside the plugin directory (#9712) @NaokiHigashi28
+* fix: The link for Telemetry of GROWI Docs (#9737) @yuki-takei
+
+### 🧰 Maintenance
+
+* ci(deps): bump next from 14.2.22 to 14.2.25 (#9761) @[dependabot[bot]](https://github.com/apps/dependabot)
+* ci(deps-dev): bump vite from 5.4.16 to 5.4.17 (#9837) @[dependabot[bot]](https://github.com/apps/dependabot)
+* ci(deps-dev): bump vite from 5.4.15 to 5.4.16 (#9830) @[dependabot[bot]](https://github.com/apps/dependabot)
+* support: Upgrade Next.js (#9825) @yuki-takei
+* support: Upgrade SWR (#9814) @yuki-takei
+* ci(deps-dev): bump vite from 5.4.14 to 5.4.15 (#9781) @[dependabot[bot]](https://github.com/apps/dependabot)
+* ci(deps): bump dependabot/fetch-metadata from 1 to 2 (#9636) @[dependabot[bot]](https://github.com/apps/dependabot)
+* ci(deps): bump docker/build-push-action from 4 to 6 (#9638) @[dependabot[bot]](https://github.com/apps/dependabot)
+* ci(deps): bump release-drafter/release-drafter from 5 to 6 (#9637) @[dependabot[bot]](https://github.com/apps/dependabot)
+
 ## [v7.2.0](https://github.com/weseek/growi/compare/v7.1.9...v7.2.0) - 2025-03-11
 
 ### 💎 Features

+ 9 - 7
README.md

@@ -2,12 +2,12 @@
 
 <p align="center">
   <a href="https://growi.org">
-    <img src="https://user-images.githubusercontent.com/1638767/38254268-d4476bbe-3793-11e8-964c-8865d690baff.png" width="240px">
+    <img src="https://github.com/user-attachments/assets/0acf1409-cea7-4f0e-841c-af5bd8be6711" width="360px">
   </a>
 </p>
 <p align="center">
-  <a href="https://github.com/weseek/growi/releases/latest"><img src="https://img.shields.io/github/release/weseek/growi.svg"></a>
-  <a href="https://communityinviter.com/apps/wsgrowi/invite/">join our Slack team</a>
+  <a href="https://github.com/weseek/growi/releases/latest"><img src="https://img.shields.io/github/release/weseek/growi.svg" alt="Latest version"></a>
+  <a href="https://communityinviter.com/apps/wsgrowi/invite/"><img src="https://img.shields.io/badge/Slack-Join%20Us-4A154B?style=flat&logo=slack&logoColor=white" alt="Slack - Join US"></a>
 </p>
 
 <p align="center">
@@ -16,12 +16,14 @@
 
 # GROWI
 
-[![Actions Status](https://github.com/weseek/growi/workflows/Node%20CI/badge.svg)](https://github.com/weseek/growi/actions)
 [![docker pulls](https://img.shields.io/docker/pulls/weseek/growi.svg)](https://hub.docker.com/r/weseek/growi/)
+[![CodeQL](https://github.com/weseek/growi/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/codeql-analysis.yml)
+[![Node CI for app development](https://github.com/weseek/growi/actions/workflows/ci-app.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/ci-app.yml)
+[![Node CI for app production](https://github.com/weseek/growi/actions/workflows/ci-app-prod.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/ci-app-prod.yml)
+
+## Demonstration
+<video src="https://private-user-images.githubusercontent.com/34241526/333079483-fee540d7-2fa6-46d7-833e-74014c5340e3.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTY0NDk2OTEsIm5iZiI6MTcxNjQ0OTM5MSwicGF0aCI6Ii8zNDI0MTUyNi8zMzMwNzk0ODMtZmVlNTQwZDctMmZhNi00NmQ3LTgzM2UtNzQwMTRjNTM0MGUzLm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA1MjMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNTIzVDA3Mjk1MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTBkYWFkMmYyYmIwMTI2YWE3ZmQzZTFiNWU3ZThkMDc5NDA5N2Q3YWE5ZGM1NDgwNjk0OGNjYjZmOTJkM2IzZGQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.FAvLseWBzE62yFA7wt26uERamvEVQdIGRVdBwk0uLhE"></video>
 
-|                                                     demonstration                                                     |
-| :-------------------------------------------------------------------------------------------------------------------: |
-| ![sample image](https://user-images.githubusercontent.com/42988650/70600974-6b29cc80-1c34-11ea-94ef-33c39c6a00dc.gif) |
 
 ## Table Of Contents
 

+ 16 - 13
README_JP.md

@@ -1,13 +1,14 @@
 - [English 🇺🇸](./README.md)
-  <p align="center">
-    <a href="https://growi.org">
-      <img src="https://user-images.githubusercontent.com/1638767/38254268-d4476bbe-3793-11e8-964c-8865d690baff.png" width="240px">
-    </a>
-  </p>
-  <p align="center">
-    <a href="https://github.com/weseek/growi/releases/latest"><img src="https://img.shields.io/github/release/weseek/growi.svg"></a>
-    <a href="https://communityinviter.com/apps/wsgrowi/invite/">join our Slack team</a>
-  </p>
+
+<p align="center">
+  <a href="https://growi.org">
+    <img src="https://github.com/user-attachments/assets/0acf1409-cea7-4f0e-841c-af5bd8be6711" width="360px">
+  </a>
+</p>
+<p align="center">
+  <a href="https://github.com/weseek/growi/releases/latest"><img src="https://img.shields.io/github/release/weseek/growi.svg" alt="Latest version"></a>
+  <a href="https://communityinviter.com/apps/wsgrowi/invite/"><img src="https://img.shields.io/badge/Slack-Join%20Us-4A154B?style=flat&logo=slack&logoColor=white" alt="Slack - Join US"></a>
+</p>
 
 <p align="center">
   <a href="https://docs.growi.org">ドキュメント</a> / <a href="https://demo.growi.org">デモ</a>
@@ -15,12 +16,14 @@
 
 # GROWI
 
-[![Actions Status](https://github.com/weseek/growi/workflows/Node%20CI/badge.svg)](https://github.com/weseek/growi/actions)
 [![docker pulls](https://img.shields.io/docker/pulls/weseek/growi.svg)](https://hub.docker.com/r/weseek/growi/)
+[![CodeQL](https://github.com/weseek/growi/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/codeql-analysis.yml)
+[![Node CI for app development](https://github.com/weseek/growi/actions/workflows/ci-app.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/ci-app.yml)
+[![Node CI for app production](https://github.com/weseek/growi/actions/workflows/ci-app-prod.yml/badge.svg)](https://github.com/weseek/growi/actions/workflows/ci-app-prod.yml)
+
+## デモ
+<video src="https://private-user-images.githubusercontent.com/34241526/333079216-cec7f7d8-c3cc-4ee7-bc94-167b056d4ce2.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTY0NDk0MDQsIm5iZiI6MTcxNjQ0OTEwNCwicGF0aCI6Ii8zNDI0MTUyNi8zMzMwNzkyMTYtY2VjN2Y3ZDgtYzNjYy00ZWU3LWJjOTQtMTY3YjA1NmQ0Y2UyLm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA1MjMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNTIzVDA3MjUwNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQ2M2IwZjc0ZGNhOWQxNWE4MGIyZTZlMzQ0ZDQ4MGZlNjEzMWE3MTQ1YmMwYzg3MmY1NWMyZWI2NzQ3NGIwMTkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.qLfu5120JrkdfpghXlLG8wCn0p4JNZ7W8AD3zUJTIYY"></video>
 
-|                                                 デモンストレーション                                                 |
-| :-------------------------------------------------------------------------------------------------------------------: |
-| ![sample image](https://user-images.githubusercontent.com/42988650/70600974-6b29cc80-1c34-11ea-94ef-33c39c6a00dc.gif) |
 
 ## 目次
 

+ 9 - 2
apps/app/bin/swagger-jsdoc/definition-apiv1.js

@@ -13,15 +13,22 @@ module.exports = {
   ],
   security: [
     {
-      api_key: [],
+      bearer: [],
+      accessTokenInQuery: [],
     },
   ],
   components: {
     securitySchemes: {
-      api_key: {
+      bearer: {
+        type: 'http',
+        scheme: 'bearer',
+        description: 'Access token generated by each GROWI users',
+      },
+      accessTokenInQuery: {
         type: 'apiKey',
         name: 'access_token',
         in: 'query',
+        description: 'Access token generated by each GROWI users',
       },
     },
   },

+ 23 - 3
apps/app/bin/swagger-jsdoc/definition-apiv3.js

@@ -13,21 +13,33 @@ module.exports = {
   ],
   security: [
     {
-      api_key: [],
+      bearer: [],
+      accessTokenInQuery: [],
     },
   ],
   components: {
     securitySchemes: {
-      api_key: {
+      bearer: {
+        type: 'http',
+        scheme: 'bearer',
+        description: 'Access token generated by each GROWI users',
+      },
+      accessTokenInQuery: {
         type: 'apiKey',
         name: 'access_token',
         in: 'query',
+        description: 'Access token generated by each GROWI users',
       },
       cookieAuth: {
         type: 'apiKey',
         in: 'cookie',
         name: 'connect.sid',
       },
+      transferHeaderAuth: {
+        type: 'apiKey',
+        in: 'header',
+        name: 'x-growi-transfer-key',
+      },
     },
   },
   'x-tagGroups': [
@@ -39,10 +51,11 @@ module.exports = {
         'BookmarkFolders',
         'Page',
         'Pages',
+        'PageListing',
         'Revisions',
         'ShareLinks',
         'Users',
-        '',
+        'UserUISettings',
         '',
       ],
     },
@@ -63,6 +76,7 @@ module.exports = {
       name: 'System Management API',
       tags: [
         'Home',
+        'Activity',
         'AdminHome',
         'AppSettings',
         'ExternalUserGroups',
@@ -71,14 +85,20 @@ module.exports = {
         'CustomizeSetting',
         'Import',
         'Export',
+        'GROWI to GROWI Transfer',
         'MongoDB',
         'NotificationSetting',
+        'Plugins',
+        'Questionnaire',
         'QuestionnaireSetting',
+        'SlackIntegration',
         'SlackIntegrationSettings',
         'SlackIntegrationSettings (with proxy)',
         'SlackIntegrationSettings (without proxy)',
         'SlackIntegrationLegacySetting',
         'ShareLink Management',
+        'Templates',
+        'Staff',
         'UserGroupRelations',
         'UserGroups',
         'Users Management',

+ 4 - 0
apps/app/bin/swagger-jsdoc/generate-spec-apiv3.sh

@@ -11,5 +11,9 @@ swagger-jsdoc \
   -o "${OUT}" \
   -d "${APP_PATH}/bin/swagger-jsdoc/definition-apiv3.js" \
   "${APP_PATH}/src/features/external-user-group/server/routes/apiv3/*.ts" \
+  "${APP_PATH}/src/features/questionnaire/server/routes/apiv3/*.ts" \
+  "${APP_PATH}/src/features/templates/server/routes/apiv3/*.ts" \
+  "${APP_PATH}/src/features/growi-plugin/server/routes/apiv3/**/*.ts" \
   "${APP_PATH}/src/server/routes/apiv3/**/*.{js,ts}" \
+  "${APP_PATH}/src/server/routes/login.js" \
   "${APP_PATH}/src/server/models/openapi/**/*.{js,ts}"

+ 28 - 18
apps/app/docker/Dockerfile

@@ -1,25 +1,31 @@
-# syntax = docker/dockerfile:1
+# syntax = docker/dockerfile:1.4
 
+ARG OPT_DIR="/opt"
+ARG PNPM_HOME="/root/.local/share/pnpm"
 
 ##
 ## base
 ##
 FROM node:20-slim AS base
 
-ENV optDir=/opt
+ARG OPT_DIR
+ARG PNPM_HOME
 
-WORKDIR ${optDir}
+WORKDIR $OPT_DIR
 
 # install tools
-RUN apt-get update && apt-get install -y ca-certificates wget curl --no-install-recommends
+RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
+    --mount=type=cache,target=/var/cache/apt,sharing=locked \
+  apt-get update && apt-get install -y ca-certificates wget curl --no-install-recommends
 
 # install pnpm
 RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" PNPM_VERSION="10.4.1" sh -
-ENV PNPM_HOME="/root/.local/share/pnpm"
+ENV PNPM_HOME=$PNPM_HOME
 ENV PATH="$PNPM_HOME:$PATH"
 
 # install turbo
-RUN pnpm add turbo --global
+RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
+  pnpm add turbo --global
 
 
 
@@ -28,14 +34,17 @@ RUN pnpm add turbo --global
 ##
 FROM base AS builder
 
-ENV optDir=/opt
+ENV PNPM_HOME=$PNPM_HOME
+ENV PATH="$PNPM_HOME:$PATH"
 
-WORKDIR ${optDir}
+WORKDIR $OPT_DIR
 
 COPY . .
 
-RUN pnpm add node-gyp --global
-RUN pnpm install ---frozen-lockfile
+RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
+  pnpm add node-gyp --global
+RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
+  pnpm install ---frozen-lockfile
 
 # build
 RUN turbo run clean
@@ -45,7 +54,7 @@ RUN turbo run build --filter @growi/app
 RUN pnpm deploy out --prod --filter @growi/app
 RUN rm -rf apps/app/node_modules && mv out/node_modules apps/app/node_modules
 RUN rm -rf apps/app/.next/cache
-RUN tar -zcf packages.tar.gz \
+RUN tar -zcf /tmp/packages.tar.gz \
   package.json \
   apps/app/.next \
   apps/app/config \
@@ -66,27 +75,28 @@ RUN tar -zcf packages.tar.gz \
 FROM node:20-slim
 LABEL maintainer="Yuki Takei <yuki@weseek.co.jp>"
 
+ARG OPT_DIR
+
 ENV NODE_ENV="production"
 
-ENV optDir=/opt
-ENV appDir=${optDir}/growi
+ENV appDir="$OPT_DIR/growi"
 
 # Add gosu
 # see: https://github.com/tianon/gosu/blob/1.13/INSTALL.md
-RUN set -eux; \
+RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
+    --mount=type=cache,target=/var/cache/apt,sharing=locked \
+  set -eux; \
 	apt-get update; \
 	apt-get install -y gosu; \
 	rm -rf /var/lib/apt/lists/*; \
 # verify that the binary works
 	gosu nobody true
 
-COPY --from=builder --chown=node:node \
-  ${optDir}/packages.tar.gz ${appDir}/
-
 # extract artifacts as 'node' user
 USER node
 WORKDIR ${appDir}
-RUN tar -zxf packages.tar.gz && rm packages.tar.gz
+RUN --mount=type=bind,from=builder,source=/tmp/packages.tar.gz,target=/tmp/packages.tar.gz \
+  tar -zxf /tmp/packages.tar.gz -C ${appDir}/
 
 COPY --chown=node:node --chmod=700 apps/app/docker/docker-entrypoint.sh /
 

+ 12 - 9
apps/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/app",
-  "version": "7.2.1-RC.0",
+  "version": "7.2.6-RC.0",
   "license": "MIT",
   "private": "true",
   "scripts": {
@@ -31,7 +31,7 @@
     "lint:styles": "stylelint \"src/**/*.scss\"",
     "lint:swagger2openapi:apiv3": "node node_modules/swagger2openapi/oas-validate tmp/openapi-spec-apiv3.json",
     "lint:swagger2openapi:apiv1": "node node_modules/swagger2openapi/oas-validate tmp/openapi-spec-apiv1.json",
-    "lint": "run-p lint:*",
+    "lint": "run-p lint:**",
     "prelint:swagger2openapi:apiv3": "pnpm run swagger2openapi:apiv3",
     "prelint:swagger2openapi:apiv1": "pnpm run swagger2openapi:apiv1",
     "test": "run-p test:*",
@@ -64,7 +64,7 @@
     "@aws-sdk/client-s3": "3.454.0",
     "@aws-sdk/s3-request-presigner": "3.454.0",
     "@azure/identity": "^4.4.1",
-    "@azure/openai": "^2.0.0-beta.2",
+    "@azure/openai": "^2.0.0",
     "@azure/storage-blob": "^12.16.0",
     "@browser-bunyan/console-formatted-stream": "^1.8.0",
     "@cspell/dynamic-import": "^8.15.4",
@@ -73,6 +73,7 @@
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
     "@growi/core": "workspace:^",
+    "@growi/pdf-converter-client": "workspace:^",
     "@growi/pluginkit": "workspace:^",
     "@growi/presentation": "workspace:^",
     "@growi/preset-templates": "workspace:^",
@@ -82,20 +83,20 @@
     "@growi/remark-growi-directive": "workspace:^",
     "@growi/remark-lsx": "workspace:^",
     "@growi/slack": "workspace:^",
-    "@growi/pdf-converter-client": "workspace:^",
     "@keycloak/keycloak-admin-client": "^18.0.0",
     "@opentelemetry/api": "^1.9.0",
     "@opentelemetry/auto-instrumentations-node": "^0.55.1",
     "@opentelemetry/exporter-metrics-otlp-grpc": "^0.57.0",
     "@opentelemetry/exporter-trace-otlp-grpc": "^0.57.0",
     "@opentelemetry/resources": "^1.28.0",
-    "@opentelemetry/semantic-conventions": "^1.28.0",
     "@opentelemetry/sdk-metrics": "^1.28.0",
     "@opentelemetry/sdk-node": "^0.57.0",
     "@opentelemetry/sdk-trace-node": "^1.28.0",
+    "@opentelemetry/semantic-conventions": "^1.28.0",
     "@slack/web-api": "^6.2.4",
     "@slack/webhook": "^6.0.0",
     "@types/async": "^3.2.24",
+    "@types/multer": "^1.4.12",
     "JSONStream": "^1.3.5",
     "archiver": "^5.3.0",
     "array.prototype.flatmap": "^1.2.2",
@@ -145,6 +146,7 @@
     "is-iso-date": "^0.0.1",
     "js-tiktoken": "^1.0.15",
     "js-yaml": "^4.1.0",
+    "jsonrepair": "^3.12.0",
     "katex": "^0.16.21",
     "ldapjs": "^3.0.2",
     "lucene-query-parser": "^1.2.0",
@@ -167,7 +169,7 @@
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
     "mustache": "^4.2.0",
-    "next": "^14.2.21",
+    "next": "^14.2.26",
     "next-dynamic-loading-props": "^0.1.1",
     "next-i18next": "^15.3.1",
     "next-superjson": "^0.0.4",
@@ -176,7 +178,7 @@
     "node-cron": "^3.0.2",
     "nodemailer": "^6.9.15",
     "nodemailer-ses-transport": "~1.5.0",
-    "openai": "^4.56.0",
+    "openai": "^4.96.2",
     "openid-client": "^5.4.0",
     "p-retry": "^4.0.0",
     "passport": "^0.6.0",
@@ -227,7 +229,7 @@
     "string-width": "=4.2.2",
     "superjson": "^1.9.1",
     "swagger-jsdoc": "^6.2.8",
-    "swr": "^2.2.2",
+    "swr": "^2.3.2",
     "throttle-debounce": "^5.0.0",
     "ts-deepmerge": "^6.2.0",
     "tslib": "^2.8.0",
@@ -246,7 +248,8 @@
     "xss": "^1.0.15",
     "y-mongodb-provider": "^0.2.0",
     "y-socket.io": "^1.1.3",
-    "yjs": "^13.6.18"
+    "yjs": "^13.6.18",
+    "zod": "^3.24.2"
   },
   "// comments for defDependencies": {
     "bootstrap": "v5.3.3 has a bug. refs: https://github.com/twbs/bootstrap/issues/39798",

+ 2 - 0
apps/app/playwright.config.ts

@@ -72,6 +72,8 @@ export default defineConfig({
     trace: 'on-first-retry',
 
     viewport: { width: 1400, height: 1024 },
+
+    screenshot: 'only-on-failure',
   },
 
   /* Configure projects for major browsers */

+ 0 - 15
apps/app/playwright/20-basic-features/presentation.spec.ts

@@ -10,19 +10,4 @@ test('Presentation', async({ page }) => {
   // check the content of the h1
   await expect(page.getByRole('application').getByRole('heading', { level: 1 }))
     .toHaveText(/Welcome to GROWI/);
-
-  // forward the slide with keyboard
-  await page.keyboard.press('ArrowRight');
-
-  // check the content of the h1
-  await expect(page.getByRole('application').getByRole('heading', { level: 1 }))
-    .toHaveText(/What can you do with GROWI?/);
-
-  // forward the slide with button
-  await page.getByRole('application').getByLabel('next slide').click();
-
-  // check the content of the h2
-  await expect(page.getByRole('application').getByRole('heading', { level: 2 }))
-    .toHaveText(/1. Knowledge Management: Create pages to store information and knowledge/);
-
 });

+ 19 - 13
apps/app/playwright/20-basic-features/use-tools.spec.ts

@@ -1,25 +1,31 @@
 import { test, expect, type Page } from '@playwright/test';
 
 const openPageItemControl = async(page: Page): Promise<void> => {
-  await expect(page.getByTestId('grw-contextual-sub-nav')).toBeVisible();
-  await page.getByTestId('grw-contextual-sub-nav').getByTestId('open-page-item-control-btn').click();
+  const nav = page.getByTestId('grw-contextual-sub-nav');
+  const button = nav.getByTestId('open-page-item-control-btn');
+
+  // Wait for navigation element to be visible and attached
+  await expect(nav).toBeVisible();
+  await nav.waitFor({ state: 'visible' });
+
+  // Wait for button to be visible, enabled and attached
+  await expect(button).toBeVisible();
+  await expect(button).toBeEnabled();
+  await button.waitFor({ state: 'visible' });
+
+  // Add a small delay to ensure the button is fully interactive
+  await page.waitForTimeout(100);
+
+  await button.click();
 };
 
-test('Page Deletion and PutBack is executed successfully', async({ page }) => {
-  await page.goto('/Sandbox/Bootstrap5');
+test('PageDeleteModal is shown successfully', async({ page }) => {
+  await page.goto('/Sandbox');
 
-  // Delete
   await openPageItemControl(page);
   await page.getByTestId('open-page-delete-modal-btn').click();
+
   await expect(page.getByTestId('page-delete-modal')).toBeVisible();
-  await page.getByTestId('delete-page-button').click();
-
-  // PutBack
-  await expect(page.getByTestId('trash-page-alert')).toBeVisible();
-  await page.getByTestId('put-back-button').click();
-  await expect(page.getByTestId('put-back-page-modal')).toBeVisible();
-  await page.getByTestId('put-back-execution-button').click();
-  await expect(page.getByTestId('trash-page-alert')).not.toBeVisible();
 });
 
 test('PageDuplicateModal is shown successfully', async({ page }) => {

+ 26 - 5
apps/app/public/static/locales/en_US/translation.json

@@ -154,6 +154,7 @@
   "In-App Notification": "Notifications",
   "AI Assistant": "AI Assistant",
   "Knowledge Assistant": "Knowledge Assistant (Beta)",
+  "Editor Assistant": "Editor Assistant (Beta)",
   "original_path": "Original path",
   "new_path": "New path",
   "duplicated_path": "Duplicated path",
@@ -344,6 +345,7 @@
       "file": "File only"
     },
     "editor_config": "Editor Config",
+    "editor_assistant": "Editor Assistant",
     "Show active line": "Show active line",
     "auto_format_table": "Auto format table",
     "overwrite_scopes": "{{operation}} and Overwrite scopes of all descendants",
@@ -493,19 +495,37 @@
     "latest_revision": "theirs",
     "selected_editable_revision": "Selected Page Body (Editable)"
   },
-  "sidebar_aichat": {
-    "instruction_label": "Assistant instructions",
+  "sidebar_ai_assistant": {
     "reference_pages_label": "Reference pages",
     "placeholder": "Ask me anything.",
+    "knowledge_assistant_placeholder": "Ask me anything.",
+    "editor_assistant_placeholder": "Can I help you with anything?",
     "summary_mode_label": "Summary mode",
     "summary_mode_help": "Concise answer within 2-3 sentences",
+    "extended_thinking_mode_label": "Extended Thinking Mode",
+    "extended_thinking_mode_help": "When enabled, the AI will take more time to think and provide a more comprehensive answer.",
     "caution_against_hallucination": "Please verify the information and check the sources.",
     "progress_label": "Generating answers",
     "failed_to_create_or_retrieve_thread": "Failed to create or retrieve thread",
     "budget_exceeded": "You have reached your usage limit for OpenAI's API. To use the Knowledge Assistant again, please add credits from the OpenAI billing page.",
     "budget_exceeded_for_growi_cloud": "You have reached your OpenAI API usage limit. To use the Knowledge Assistant again, please add credits from the GROWI.cloud admin page for Hosted users or from the OpenAI billing page for Owned users.",
     "error_message": "An error has occurred",
-    "show_error_detail": "Show error details"
+    "show_error_detail": "Show error details",
+    "discard": "Discard",
+    "accept": "Accept",
+    "use_assistant": "Use Assistant",
+    "remove_assistant": "Deselect the selected assistant",
+    "text_generation_by_editor_assistant_label": "Editor Assistant is generating text",
+    "preset_menu": {
+      "summarize": {
+        "title": "Summarize this article",
+        "prompt": "Please summarize the markdown content"
+      },
+      "correct": {
+        "title": "Correct errors in the text",
+        "prompt": "Please correct the errors in the markdown text"
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {
@@ -531,7 +551,7 @@
       "update_failed": "Failed to update assistant"
     },
     "edit_page_description": "Edit pages that the assistant can reference.<br> The assistant can reference up to {{limitLearnablePageCountPerAssistant}} pages including child pages.",
-    "default_instruction": "You are the knowledge assistant for this Wiki. Please provide support according to the following guidelines:\n\n- Analyze document relevance and connect information\n- Suggest new perspectives\n- Provide accurate information based on understanding the intent of questions\nI will provide information in a structured format when necessary.",
+    "default_instruction": "You are the knowledge assistant for this Wiki.\n\n## Multilingual Support:\nRespond in the same language the user uses in their input.\n",
     "add_page_button": "Add page",
     "page_mode_title": {
       "share": "Assistant Sharing",
@@ -767,7 +787,8 @@
     "export_cancel_warning": "The following export in progress will be canceled",
     "restart": "Restart",
     "format": "Format",
-    "started_on": "Started on"
+    "started_on": "Started on",
+    "file_upload_not_configured": "File upload settings are not configured"
   },
   "message": {
     "successfully_connected": "Successfully Connected!",

+ 26 - 6
apps/app/public/static/locales/fr_FR/translation.json

@@ -155,6 +155,7 @@
   "In-App Notification": "Notifications",
   "AI Assistant": "Assistant IA",
   "Knowledge Assistant": "Assistant de Connaissances (Bêta)",
+  "Editor Assistant": "Assistante de rédaction (Bêta)",
   "original_path": "Chemin originel",
   "new_path": "Nouveau chemin",
   "duplicated_path": "Chemin dupliqué",
@@ -345,6 +346,7 @@
       "file": "Fichier seulement"
     },
     "editor_config": "Préférences de l'éditeur",
+    "editor_assistant": "Assistant d'édition",
     "Show active line": "Surligner la ligne active",
     "auto_format_table": "Formatter les tableaux",
     "overwrite_scopes": "{{operation}} et écraser les scopes des pages enfants",
@@ -488,19 +490,36 @@
     "latest_revision": "les autres",
     "selected_editable_revision": "Corps de page sélectionné (Modifiable)"
   },
-  "sidebar_aichat": {
-    "instruction_label": "Instructions pour l'assistant",
+  "sidebar_ai_assistant": {
     "reference_pages_label": "Pages de référence",
-    "placeholder": "Demandez-moi n'importe quoi.",
+    "knowledge_assistant_placeholder": "Demandez-moi n'importe quoi.",
+    "editor_assistant_placeholder": "Puis-je vous aider ?",
     "summary_mode_label": "Mode résumé",
     "summary_mode_help": "Réponse concise en 2-3 phrases",
+    "extended_thinking_mode_label": "Mode réflexion approfondie",
+    "extended_thinking_mode_help": "Lorsqu'activé, l'IA prendra plus de temps pour réfléchir et fournir une réponse plus complète.",
     "caution_against_hallucination": "Veuillez vérifier les informations et consulter les sources.",
     "progress_label": "Génération des réponses",
     "failed_to_create_or_retrieve_thread": "Échec de la création ou de la récupération du fil de discussion",
     "budget_exceeded": "Vous avez atteint votre limite d'utilisation de l'API de l'OpenAI. Pour utiliser à nouveau l'assistant de connaissance, veuillez ajouter des crédits à partir de la page de facturation d'OpenAI.",
     "budget_exceeded_for_growi_cloud": "Vous avez atteint votre limite d'utilisation de l'API de l'OpenAI. Pour utiliser à nouveau l'assistant de connaissance, veuillez ajouter des crédits à partir de la page d'administration de GROWI.cloud pour les utilisateurs hébergés ou à partir de la page de facturation de l'OpenAI pour les utilisateurs propriétaires.",
     "error_message": "Erreur",
-    "show_error_detail": "Détails de l'exposition"
+    "show_error_detail": "Détails de l'exposition",
+    "discard": "Annuler",
+    "accept": "Accepter",
+    "use_assistant": "Utiliser l'assistant",
+    "remove_assistant": "Désélectionner l'assistant sélectionné",
+    "text_generation_by_editor_assistant_label": "L'assistant de rédaction génère du texte",
+    "preset_menu": {
+      "summarize": {
+        "title": "Résumer cet article'",
+        "prompt": "Veuillez résumer le contenu markdown"
+      },
+      "correct": {
+        "title": "Corriger les erreurs du texte",
+        "prompt": "Veuillez corriger les erreurs dans le texte markdown"
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {
@@ -526,7 +545,7 @@
       "update_failed": "Échec de la mise à jour de l'assistant"
     },
     "edit_page_description": "Modifier les pages que l'assistant peut référencer.<br> L'assistant peut référencer jusqu'à {{limitLearnablePageCountPerAssistant}} pages, y compris les pages enfants.",
-    "default_instruction": "Vous êtes l'assistant de connaissances pour ce Wiki. Veuillez fournir un support selon les directives suivantes :\n\n- Analyser la pertinence des documents et relier les informations\n- Proposer de nouvelles perspectives\n- Fournir des informations précises en comprenant l'intention des questions\nJe fournirai les informations sous forme structurée si nécessaire.",
+    "default_instruction": "Vous êtes l'assistant de connaissances pour ce Wiki.\n\n## Support multilingue :\nRépondez dans la même langue que celle utilisée par l'utilisateur dans sa requête.\n",
     "add_page_button": "Ajouter une page",
     "page_mode_title": {
       "share": "Partage de l'assistant",
@@ -762,7 +781,8 @@
     "export_cancel_warning": "Les exportations suivantes en cours seront annulées",
     "restart": "Redémarrage",
     "format": "Format",
-    "started_on": "Commencé le"
+    "started_on": "Commencé le",
+    "file_upload_not_configured": "Les paramètres de téléchargement de fichiers ne sont pas configurés"
   },
   "message": {
     "successfully_connected": "Connecté!",

+ 27 - 7
apps/app/public/static/locales/ja_JP/translation.json

@@ -155,6 +155,7 @@
   "In-App Notification": "通知",
   "AI Assistant": "AI アシスタント",
   "Knowledge Assistant": "ナレッジアシスタント (ベータ版)",
+  "Editor Assistant": "エディターアシスタント (ベータ版)",
   "original_path": "元のパス",
   "new_path": "新しいパス",
   "duplicated_path": "重複したパス",
@@ -376,7 +377,8 @@
       "text": "テキストのみ",
       "file": "ファイルのみ"
     },
-    "editor_config": "エディタ設定",
+    "editor_config": "エディター設定",
+    "editor_assistant": "エディターアシスタント",
     "Show active line": "アクティブ行をハイライト",
     "auto_format_table": "表の自動整形",
     "overwrite_scopes": "{{operation}}と同時に全ての配下ページのスコープを上書き",
@@ -526,19 +528,36 @@
     "latest_revision": "最新の本文",
     "selected_editable_revision": "保存するページ本文(編集可能)"
   },
-  "sidebar_aichat": {
-    "instruction_label": "アシスタントへの指示",
+  "sidebar_ai_assistant": {
     "reference_pages_label": "参照するページ",
-    "placeholder": "ききたいことを入力してください",
+    "knowledge_assistant_placeholder": "ききたいことを入力してください",
+    "editor_assistant_placeholder": "お手伝いできることはありますか?",
     "summary_mode_label": "要約モード",
     "summary_mode_help": "2~3文以内の簡潔な回答",
+    "extended_thinking_mode_label": "拡張思考モード",
+    "extended_thinking_mode_help": "有効にすると、AIはより時間をかけて考え、より包括的な回答を提供します。",
     "caution_against_hallucination": "情報が正しいか出典を確認しましょう",
     "progress_label": "回答を生成しています",
     "failed_to_create_or_retrieve_thread": "スレッドの作成または取得に失敗しました",
     "budget_exceeded": "OpenAI の API の利用上限に達しました。ナレッジアシスタントを再度利用するには OpenAI の請求ページからクレジットを追加してください。",
     "budget_exceeded_for_growi_cloud": "OpenAI の API の利用上限に達しました。ナレッジアシスタントを再度利用するには Hosted の場合は GROWI.cloud の管理画面から Owned の場合は OpenAI の請求ページからクレジットを追加してください。",
     "error_message": "エラーが発生しました",
-    "show_error_detail": "詳細を表示"
+    "show_error_detail": "詳細を表示",
+    "discard": "破棄",
+    "accept": "採用",
+    "use_assistant": "アシスタントを使用する",
+    "remove_assistant": "選択されているアシスタントの解除",
+    "text_generation_by_editor_assistant_label": "エディターアシスタントが文章を生成中",
+    "preset_menu": {
+      "summarize": {
+        "title": "この記事の要約をつくる",
+        "prompt": "マークダウンの内容を要約してください"
+      },
+      "correct": {
+        "title": "文章の誤りを修正する",
+        "prompt": "マークダウンの内の文章の誤りを修正してください"
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {
@@ -563,8 +582,8 @@
       "create_failed": "アシスタントの作成に失敗しました",
       "update_failed": "アシスタントの更新に失敗しました"
     },
-    "default_instruction": "あなたはこのWikiの知識アシスタントです。以下の方針で支援を行ってください:\n\n- 文書の関連性分析と情報の関連付け\n- 新しい視点の提案\n- 質問の意図を理解した的確な情報提供 必要に応じて構造化された形式で情報を提供します。",
     "edit_page_description": " アシスタントが参照するページを編集します。<br> 参照できるページは配下ページも含めて {{limitLearnablePageCountPerAssistant}} ページまでです。",
+    "default_instruction": "あなたはこのWikiの知識アシスタントです。\n\n## 多言語サポート:\nユーザーが入力で使用した言語と同じ言語で応答してください。\n",
     "add_page_button": "ページを追加する",
     "page_mode_title": {
       "share": "アシスタントの共有",
@@ -800,7 +819,8 @@
     "export_cancel_warning": "進行中の以下のエクスポートはキャンセルされます",
     "restart": "やり直す",
     "format": "形式",
-    "started_on": "開始日時"
+    "started_on": "開始日時",
+    "file_upload_not_configured": "ファイルアップロード設定が完了していません"
   },
   "message": {
     "successfully_connected": "接続に成功しました!",

+ 26 - 6
apps/app/public/static/locales/zh_CN/translation.json

@@ -160,6 +160,7 @@
   "In-App Notification": "通知",
   "AI Assistant": "AI助手",
   "Knowledge Assistant": "知识助手 (测试版)",
+  "Editor Assistant": "编辑助理 (测试版)",
   "original_path": "Original path",
   "new_path": "New path",
   "duplicated_path": "Duplicated path",
@@ -334,6 +335,7 @@
       "file": "仅文件"
     },
     "editor_config": "编辑器配置",
+    "editor_assistant": "编辑助手",
 		"Show active line": "显示活动行",
 		"auto_format_table": "自动格式化表格",
 		"overwrite_scopes": "{{operation}和覆盖所有子体的作用域",
@@ -483,19 +485,36 @@
     "latest_revision": "最新页面正文",
     "selected_editable_revision": "选定的可编辑页面正文"
   },
-  "sidebar_aichat": {
-    "instruction_label": "助手指令",
+  "sidebar_ai_assistant": {
     "reference_pages_label": "参考页面",
-    "placeholder": "问我任何问题。",
+    "knowledge_assistant_placeholder": "问我任何问题。",
+    "editor_assistant_placeholder": "有什么需要帮忙的吗?",
     "summary_mode_label": "摘要模式",
     "summary_mode_help": "简洁回答在2-3句话内",
+    "extended_thinking_mode_label": "延伸思考模式",
+    "extended_thinking_mode_help": "启用后,AI 将花更多时间思考并提供更全面的回答。",
     "caution_against_hallucination": "请核实信息并检查来源。",
     "progress_label": "生成答案中",
     "failed_to_create_or_retrieve_thread": "创建或获取线程失败",
     "budget_exceeded": "您已达到 OpenAI API 的使用上限。要再次使用知识助手,请从 OpenAI 账单页面添加点数。",
     "budget_exceeded_for_growi_cloud": "您已达到 OpenAI API 使用上限。如需再次使用知识助手,请从GROWI.cloud管理页面为托管用户添加点数,或从OpenAI计费页面为自有用户添加点数。",
     "error_message": "错误",
-    "show_error_detail": "显示详情"
+    "show_error_detail": "显示详情",
+    "discard": "丢弃",
+    "accept": "接受",
+    "use_assistant": "使用助手",
+    "remove_assistant": "取消选定的助手",
+    "text_generation_by_editor_assistant_label": "编辑助理正在生成文本",
+    "preset_menu": {
+      "summarize": {
+        "title": "为此文章创建摘要",
+        "prompt": "请总结这个 markdown 内容"
+      },
+      "correct": {
+        "title": "修正文本中的错误",
+        "prompt": "请修正 markdown 中的文本错误"
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {
@@ -521,7 +540,7 @@
       "update_failed": "更新助手失败"
     },
     "edit_page_description": "编辑助手可以参考的页面。<br> 助手可以参考最多 {{limitLearnablePageCountPerAssistant}} 个页面,包括子页面。",
-    "default_instruction": "您是这个Wiki的知识助手。请按照以下方针提供支持:\n\n- 分析文档相关性并连接信息\n- 提出新的观点\n- 理解问题意图并提供准确信息\n必要时我会以结构化的形式提供信息。",
+    "default_instruction": "您是这个Wiki的知识助手。\n\n## 多语言支持:\n请使用用户输入中使用的相同语言进行回复。\n",
     "add_page_button": "添加页面",
     "page_mode_title": {
       "share": "助理共享",
@@ -771,7 +790,8 @@
     "export_cancel_warning": "以下正在进行的导出将被取消",
     "restart": "重新开始",
     "format": "格式",
-    "started_on": "开始于"
+    "started_on": "开始于",
+    "file_upload_not_configured": "未配置文件上传设置"
   },
   "message": {
     "successfully_connected": "连接成功!",

+ 29 - 1
apps/app/resource/Contributor.js

@@ -17,6 +17,7 @@ const contributors = [
           { position: 'Titan', name: 'ryoh15' },
           { position: 'Haberion', name: 'hakumizuki' },
           { position: 'Undefined', name: 'miya' },
+          { position: 'Hoimi Slime', name: 'satof3' },
         ],
       },
       {
@@ -58,13 +59,32 @@ const contributors = [
           { name: 'yoshiro-s' },
           { name: 'kuimac' },
           { name: 'akira-sugiyama' },
+          { name: 'Ryosei-Fukushima' },
+          { name: 'kazutoweseek' },
+          { name: 'reiji-h' },
+          { name: 'atsuki-t' },
+          { name: 'moekumasaka' },
+          { name: 'WNomunomu' },
+          { name: 'abichan99911111' },
+          { name: 'naoki-higashi-28' },
+          { name: 'meiri-k' },
+          { name: 'soumaeda' },
+          { name: 'akin0ri' },
+          { name: 'ffujisawa' },
+          { name: 'maeshinshin' },
+          { name: 'arafubeatbox' },
+          { name: 'Shunm634-source' },
+          { name: 'kamij-i' },
+          { name: 'shironegi39' },
+          { name: 'ryo-h15' },
+          { name: 'jam411' },
         ],
       },
     ],
   },
   {
     order: 10,
-    sectionName: 'CONTRIBUTER',
+    sectionName: 'CONTRIBUTOR',
     additionalClass: '',
     memberGroups: [
       {
@@ -104,6 +124,13 @@ const contributors = [
           { name: 'tats-u' },
           { name: 'yamatomo717' },
           { name: 'tohutohu' },
+          { name: 'Lanhild' },
+          { name: 'urzk' },
+          { name: 'Mxchaeltrxn' },
+          { name: 'nakashimaki' },
+          { name: 'ToshihitoKon' },
+          { name: 'sakazuki' },
+          { name: 'Takahirostride' },
         ],
       },
     ],
@@ -140,6 +167,7 @@ const contributors = [
           { name: 'Crowi Team' },
           { position: 'Ambassador', name: 'Tsuyoshi Suzuki' },
           { name: 'JPCERT/CC' },
+          { name: 'goofmint' },
         ],
       },
       {

+ 1 - 1
apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 type EnvVarsTableProps = {
   envVars: Record<string, string | number | boolean>,

+ 3 - 0
apps/app/src/client/components/Admin/App/AwsSetting.tsx

@@ -1,5 +1,8 @@
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
+
 export type AwsSettingMoleculeProps = {
   s3ReferenceFileWithRelayMode
   s3Region

+ 3 - 0
apps/app/src/client/components/Admin/App/AzureSetting.tsx

@@ -1,7 +1,10 @@
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
 import MaskedInput from './MaskedInput';
 
+
 export type AzureSettingMoleculeProps = {
   azureReferenceFileWithRelayMode
   azureUseOnlyEnvVars

+ 1 - 1
apps/app/src/client/components/Admin/App/FileUploadSetting.tsx

@@ -1,4 +1,4 @@
-import type { ChangeEvent } from 'react';
+import type { ChangeEvent, JSX } from 'react';
 import React, { useCallback } from 'react';
 
 import { useTranslation } from 'next-i18next';

+ 3 - 0
apps/app/src/client/components/Admin/App/GcsSetting.tsx

@@ -1,5 +1,8 @@
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
+
 export type GcsSettingMoleculeProps = {
   gcsReferenceFileWithRelayMode
   gcsUseOnlyEnvVars

+ 1 - 1
apps/app/src/client/components/Admin/App/MaskedInput.tsx

@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 
 import styles from './MaskedInput.module.scss';
 

+ 1 - 1
apps/app/src/client/components/Admin/App/PageBulkExportSettings.tsx

@@ -1,5 +1,5 @@
 import {
-  useState, useCallback, useEffect,
+  useState, useCallback, useEffect, type JSX,
 } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';

+ 1 - 1
apps/app/src/client/components/Admin/App/QuestionnaireSettings.tsx

@@ -1,5 +1,5 @@
 import {
-  useState, useCallback, useEffect,
+  useState, useCallback, useEffect, type JSX,
 } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';

+ 1 - 1
apps/app/src/client/components/Admin/Common/AdminInstallButtonRow.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 type Props = {
   onClick: () => void,

+ 1 - 1
apps/app/src/client/components/Admin/Common/AdminUpdateButtonRow.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/Common/LabeledProgressBar.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { Progress } from 'reactstrap';
 

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeCssSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { Card, CardBody } from 'reactstrap';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeFunctionOption.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 type Props = {
   optionId: string

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeFunctionSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { Card, CardBody } from 'reactstrap';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeLayoutSetting.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useCallback, useEffect, useState,
+  useCallback, useEffect, useState, type JSX,
 } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';

+ 2 - 2
apps/app/src/client/components/Admin/Customize/CustomizeLogoSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useState, type JSX } from 'react';
 
 import { useTranslation } from 'react-i18next';
 
@@ -125,7 +125,7 @@ const CustomizeLogoSetting = (): JSX.Element => {
                     {isCustomizedLogoUploaded && (
                       <>
                         <p>
-                          <img src={CUSTOMIZED_LOGO} className="picture picture-lg " id="settingBrandLogo" width="64" />
+                          <img src={CUSTOMIZED_LOGO} id="settingBrandLogo" width="64" />
                         </p>
                         <button type="button" className="btn btn-danger" onClick={onClickDeleteBtn}>
                           { t('admin:customize_settings.delete_logo') }

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeNoscriptSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { PrismAsyncLight } from 'react-syntax-highlighter';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizePresentationSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeScriptSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { PrismAsyncLight } from 'react-syntax-highlighter';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeSidebarSetting.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/CustomizeThemeOptions.tsx

@@ -1,4 +1,4 @@
-import React, { useMemo } from 'react';
+import React, { useMemo, type JSX } from 'react';
 
 import { type GrowiThemeMetadata, GrowiThemeSchemeType } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 3 - 1
apps/app/src/client/components/Admin/Customize/CustomizeThemeSetting.tsx

@@ -1,4 +1,6 @@
-import React, { useCallback, useEffect, useState } from 'react';
+import React, {
+  useCallback, useEffect, useState, type JSX,
+} from 'react';
 
 import { PresetThemes, PresetThemesMetadatas } from '@growi/preset-themes';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Customize/ThemeColorBox.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import type { GrowiThemeMetadata } from '@growi/core';
 

+ 1 - 1
apps/app/src/client/components/Admin/ElasticsearchManagement/NormalizeIndicesControls.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/ElasticsearchManagement/ReconnectControls.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/ExportArchiveData/ArchiveFilesTable.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { format } from 'date-fns/format';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/ExportArchiveData/ArchiveFilesTableMenu.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 3 - 1
apps/app/src/client/components/Admin/ExportArchiveData/SelectCollectionsModal.tsx

@@ -1,4 +1,6 @@
-import React, { useCallback, useState, useEffect } from 'react';
+import React, {
+  useCallback, useState, useEffect, type JSX,
+} from 'react';
 
 import { useTranslation } from 'next-i18next';
 import {

+ 3 - 1
apps/app/src/client/components/Admin/ExportArchiveDataPage.tsx

@@ -1,4 +1,6 @@
-import React, { useCallback, useEffect, useState } from 'react';
+import React, {
+  useCallback, useEffect, useState, type JSX,
+} from 'react';
 
 import { useTranslation } from 'react-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/ForbiddenPage.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import DefaultErrorPage from 'next/error';
 import { useTranslation } from 'react-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/FullTextSearchManagement.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/G2GDataTransfer.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useCallback, useEffect, useState,
+  useCallback, useEffect, useState, type JSX,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/G2GDataTransferExportForm.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useState, useEffect, useCallback, useMemo,
+  useState, useEffect, useCallback, useMemo, type JSX,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/G2GDataTransferStatusIcon.tsx

@@ -1,4 +1,4 @@
-import React, { type ComponentPropsWithoutRef } from 'react';
+import React, { type ComponentPropsWithoutRef, type JSX } from 'react';
 
 import { LoadingSpinner } from '@growi/ui/dist/components';
 

+ 1 - 1
apps/app/src/client/components/Admin/ImportData/GrowiArchive/ErrorViewer.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { Modal, ModalHeader, ModalBody } from 'reactstrap';
 

+ 1 - 1
apps/app/src/client/components/Admin/ManageExternalAccount.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect } from 'react';
+import React, { useCallback, useEffect, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import Link from 'next/link';

+ 1 - 1
apps/app/src/client/components/Admin/MarkdownSetting/MarkDownSettingContents.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect } from 'react';
+import React, { useEffect, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { Card, CardBody } from 'reactstrap';

+ 1 - 1
apps/app/src/client/components/Admin/MarkdownSetting/WhitelistInput.tsx

@@ -1,4 +1,4 @@
-import { useCallback, useRef } from 'react';
+import { useCallback, useRef, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/NotFoundPage.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/Notification/ManageGlobalNotification.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useCallback, useMemo, useEffect, useState,
+  useCallback, useMemo, useEffect, useState, type JSX,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Notification/NotificationTypeIcon.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { UncontrolledTooltip } from 'reactstrap';
 

+ 1 - 1
apps/app/src/client/components/Admin/Security/LdapAuthTest.tsx

@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 

+ 1 - 1
apps/app/src/client/components/Admin/SlackIntegration/BotTypeCard.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { SlackbotType } from '@growi/slack';
 import { useTranslation } from 'next-i18next';

+ 3 - 0
apps/app/src/client/components/Admin/SlackIntegration/Bridge.tsx

@@ -1,7 +1,10 @@
 
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 import { UncontrolledTooltip } from 'reactstrap';
 
+
 const ProxyCircle = () => (
   <div className="grw-bridge-proxy-circle position-relative">
     <div className="circle position-absolute m-auto z-1 bg-primary border-light rounded-circle">

+ 1 - 1
apps/app/src/client/components/Admin/SlackIntegration/CustomBotWithProxyConnectionStatus.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import type { ConnectionStatus } from '@growi/slack';
 import Image from 'next/image';

+ 1 - 1
apps/app/src/client/components/Admin/SlackIntegration/CustomBotWithoutProxyConnectionStatus.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import type { ConnectionStatus } from '@growi/slack';
 import Image from 'next/image';

+ 2 - 1
apps/app/src/client/components/Admin/SlackIntegration/MessageBasedOnConnection.jsx

@@ -1,6 +1,7 @@
 import React from 'react';
-import PropTypes from 'prop-types';
+
 import { useTranslation } from 'next-i18next';
+import PropTypes from 'prop-types';
 
 
 const MessageBasedOnConnection = (props) => {

+ 3 - 0
apps/app/src/client/components/Admin/SlackIntegration/SlackAppIntegrationControl.tsx

@@ -1,6 +1,9 @@
 
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
+
 type Props = {
   slackAppIntegration: {
     _id: string,

+ 3 - 1
apps/app/src/client/components/Admin/SlackIntegration/SlackIntegration.tsx

@@ -1,4 +1,6 @@
-import React, { useState, useEffect, useCallback } from 'react';
+import React, {
+  useState, useEffect, useCallback, type JSX,
+} from 'react';
 
 import { SlackbotType } from '@growi/slack';
 import { LoadingSpinner } from '@growi/ui/dist/components';

+ 2 - 1
apps/app/src/client/components/Admin/UserGroup/UserGroupDropdown.tsx

@@ -1,4 +1,5 @@
-import React, { FC, useCallback } from 'react';
+import type { FC } from 'react';
+import React, { useCallback } from 'react';
 
 import type { IUserGroupHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/UserGroup/UserGroupTable.tsx

@@ -1,4 +1,4 @@
-import type { FC } from 'react';
+import type { FC, JSX } from 'react';
 import React, { useState, useEffect } from 'react';
 
 import type { IUserGroupHasId, IUserGroupRelation, IUserHasId } from '@growi/core';

+ 1 - 1
apps/app/src/client/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -1,5 +1,5 @@
 import React, {
-  useState, useCallback, useEffect,
+  useState, useCallback, useEffect, type JSX,
 } from 'react';
 
 import {

+ 3 - 1
apps/app/src/client/components/Admin/UserGroupDetail/UserGroupPageList.tsx

@@ -1,4 +1,6 @@
-import React, { useEffect, useState, useCallback } from 'react';
+import React, {
+  useEffect, useState, useCallback, type JSX,
+} from 'react';
 
 import type { IPageHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/UserGroupDetail/UserGroupUserModal.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import type { IUserGroupHasId, IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/UserGroupDetail/UserGroupUserTable.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import { UserPicture } from '@growi/ui/dist/components';
 import { format as dateFnsFormat } from 'date-fns/format';

+ 1 - 1
apps/app/src/client/components/Admin/Users/ExternalAccountTable.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IAdminExternalAccount } from '@growi/core';
 import { format as dateFnsFormat } from 'date-fns/format';

+ 1 - 1
apps/app/src/client/components/Admin/Users/GrantAdminButton.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Users/GrantReadOnlyButton.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Users/RevokeAdminButton.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Users/RevokeAdminMenuItem.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Users/RevokeReadOnlyMenuItem.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 1 - 1
apps/app/src/client/components/Admin/Users/SortIcons.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 type SortIconsProps = {
   onClick: (sortOrder: string) => void,

+ 1 - 1
apps/app/src/client/components/Admin/Users/StatusSuspendMenuItem.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { useTranslation } from 'next-i18next';

+ 2 - 0
apps/app/src/client/components/AlertSiteUrlUndefined.tsx

@@ -1,3 +1,5 @@
+import type { JSX } from 'react';
+
 import { useTranslation } from 'next-i18next';
 
 import { useSiteUrl } from '~/stores-universal/context';

+ 2 - 2
apps/app/src/client/components/AuthorInfo/AuthorInfo.module.scss

@@ -10,12 +10,12 @@ $date-font-size: 12px;
     font-size: $date-font-size;
   }
 
-  .picture {
+  .user-picture {
     width: 22px;
     height: 22px;
     border: 1px solid bs.$gray-300;
 
-    &.picture-xs {
+    &.user-picture-xs {
       width: 14px;
       height: 14px;
     }

+ 1 - 1
apps/app/src/client/components/AuthorInfo/AuthorInfo.tsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 
 import type { IUserHasId } from '@growi/core';
 import { isPopulated, type IUser, type Ref } from '@growi/core';

+ 1 - 1
apps/app/src/client/components/Bookmarks/BookmarkFolderItemControl.tsx

@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, type JSX } from 'react';
 
 import { useTranslation } from 'next-i18next';
 import {

+ 3 - 1
apps/app/src/client/components/Bookmarks/BookmarkFolderMenu.tsx

@@ -1,4 +1,6 @@
-import React, { useCallback, useMemo, useState } from 'react';
+import React, {
+  useCallback, useMemo, useState, type JSX,
+} from 'react';
 
 import { useTranslation } from 'next-i18next';
 import { DropdownItem, DropdownMenu, UncontrolledDropdown } from 'reactstrap';

+ 1 - 1
apps/app/src/client/components/Bookmarks/BookmarkFolderNameInput.tsx

@@ -1,4 +1,4 @@
-import type { ChangeEvent } from 'react';
+import type { ChangeEvent, JSX } from 'react';
 import { useCallback, useRef, useState } from 'react';
 
 import { useRect } from '@growi/ui/dist/utils';

+ 2 - 2
apps/app/src/client/components/Bookmarks/BookmarkFolderTree.module.scss

@@ -65,12 +65,12 @@ $grw-bookmark-item-padding-left: 35px;
       min-width: 30px;
       height: 50px;
 
-      .picture {
+      .user-picture {
         width: 16px;
         height: 16px;
         vertical-align: text-bottom;
 
-        &.picture-md {
+        &.user-picture-md {
           width: 20px;
           height: 20px;
         }

+ 1 - 1
apps/app/src/client/components/Bookmarks/BookmarkItem.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useState, type JSX } from 'react';
 
 import nodePath from 'path';
 

+ 1 - 1
apps/app/src/client/components/Bookmarks/BookmarkItemRenameInput.tsx

@@ -1,4 +1,4 @@
-import type { ChangeEvent } from 'react';
+import type { ChangeEvent, JSX } from 'react';
 import { useCallback, useRef, useState } from 'react';
 
 import { useRect } from '@growi/ui/dist/utils';

+ 1 - 1
apps/app/src/client/components/Bookmarks/DragAndDropWrapper.tsx

@@ -1,4 +1,4 @@
-import type { ReactNode } from 'react';
+import type { ReactNode, JSX } from 'react';
 
 import { useDrag, useDrop } from 'react-dnd';
 

+ 3 - 1
apps/app/src/client/components/Comments.tsx

@@ -1,4 +1,6 @@
-import React, { useEffect, useMemo, useRef } from 'react';
+import React, {
+  useEffect, useMemo, useRef, type JSX,
+} from 'react';
 
 import type { IRevisionHasId } from '@growi/core';
 import { pagePathUtils } from '@growi/core/dist/utils';

Неке датотеке нису приказане због велике количине промена