diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index bbf205f0296..3488bab7f5f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-18 +FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-20 # The node image includes a non-root user with sudo access. Use the # "remoteUser" property in devcontainer.json to use it. On Linux, update @@ -37,7 +37,9 @@ RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - RUN apt-get update \ - && apt-get -y install --no-install-recommends git-lfs \ + && apt-get -y install --no-install-recommends \ + git-lfs \ + iputils-ping net-tools dnsutils \ # Uncomment below lines to install Chromium # --- works only on AMD64 --- diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 328ff7c5997..e23078b6c42 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,6 +19,7 @@ "eamodio.gitlens", "github.vscode-pull-request-github", "cschleiden.vscode-github-actions", + "mongodb.mongodb-vscode", "msjsdiag.debugger-for-chrome", "firefox-devtools.vscode-firefox-debug", "editorconfig.editorconfig", @@ -34,7 +35,7 @@ // "shutdownAction": "none", // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "yarn global add turbo node-gyp && yarn install", + "postCreateCommand": "git-lfs pull & turbo run bootstrap", // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "node" diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index ed4a1832c51..123d2837ab2 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -31,17 +31,10 @@ services: image: mongo:6.0 restart: unless-stopped ports: - - 27017:27017 + - 27017 volumes: - /data/db - ogp: - image: ghcr.io/weseek/growi-unique-ogp:latest - ports: - - 8088:8088 - restart: unless-stopped - tty: true - # This container requires '../../growi-docker-compose' repository # cloned from https://github.com/weseek/growi-docker-compose.git elasticsearch: @@ -52,7 +45,7 @@ services: - version=8.7.0 restart: unless-stopped ports: - - 9200:9200 + - 9200 environment: - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms256m -Xmx256m" @@ -65,33 +58,6 @@ services: - /usr/share/elasticsearch/data - ../../growi-docker-compose/elasticsearch/v8/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml - #need to adjust kibana version based on elasticsearch version (use same version as elasticsearch version) - kibana: - image: docker.elastic.co/kibana/kibana:8.7.0 - restart: unless-stopped - environment: - ELASTICSEARCH_HOSTS: 'http://elasticsearch:9200' - ports: - - 5601:5601 - depends_on: - - elasticsearch - - # This container requires '../../growi-docker-compose' repository - # cloned from https://github.com/weseek/growi-docker-compose.git - hackmd: - build: - context: ../../growi-docker-compose/hackmd - restart: unless-stopped - environment: - - GROWI_URI=http://localhost:3000 - # define 'storage' option value - # see https://github.com/sequelize/cli/blob/7160d0/src/helpers/config-helper.js#L192 - - CMD_DB_URL=sqlite://dummyhost/hackmd/sqlite/codimd.db - - CMD_CSP_ENABLE=false - ports: - - 3010:3000 - volumes: - - /files/sqlite volumes: node_modules: node_modules_app: diff --git a/.github/workflows-archived/release-rc-v7.yml b/.github/workflows-archived/release-rc-v7.yml new file mode 100644 index 00000000000..72874e89d48 --- /dev/null +++ b/.github/workflows-archived/release-rc-v7.yml @@ -0,0 +1,81 @@ +name: Release Docker Images for RC (for dev/7.0.x) + +on: + push: + branches: + - dev/7.0.x + + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + +jobs: + + determine-tags: + runs-on: ubuntu-latest + + outputs: + TAGS: ${{ steps.meta.outputs.tags }} + TAGS_GHCR: ${{ steps.meta-ghcr.outputs.tags }} + + steps: + - uses: actions/checkout@v3 + + - name: Retrieve information from package.json + uses: myrotvorets/info-from-package-json-action@1.2.0 + id: package-json + + - name: Docker meta for docker.io + uses: docker/metadata-action@v4 + id: meta + with: + images: docker.io/weseek/growi + sep-tags: ',' + tags: | + type=raw,value=${{ steps.package-json.outputs.packageVersion }}.{{sha}} + + - name: Docker meta for ghcr.io + uses: docker/metadata-action@v4 + id: meta-ghcr + with: + images: ghcr.io/weseek/growi + sep-tags: ',' + tags: | + type=raw,value=${{ steps.package-json.outputs.packageVersion }}.{{sha}} + + + build-image-rc: + uses: weseek/growi/.github/workflows/reusable-app-build-image.yml@master + with: + image-name: weseek/growi + tag-temporary: latest-rc + secrets: + AWS_ROLE_TO_ASSUME_FOR_OIDC: ${{ secrets.AWS_ROLE_TO_ASSUME_FOR_OIDC }} + + + publish-image-rc: + needs: [determine-tags, build-image-rc] + + uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master + with: + tags: ${{ needs.determine-tags.outputs.TAGS }} + registry: docker.io + image-name: weseek/growi + tag-temporary: latest-rc + secrets: + DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} + + publish-image-rc-ghcr: + needs: [determine-tags, build-image-rc] + + uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master + with: + tags: ${{ needs.determine-tags.outputs.TAGS_GHCR }} + registry: ghcr.io + image-name: weseek/growi + tag-temporary: latest-rc + secrets: + DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_ON_GITHUB_PASSWORD }} + diff --git a/.github/workflows/ci-app-prod.yml b/.github/workflows/ci-app-prod.yml index 1b9561dd235..28021e02433 100644 --- a/.github/workflows/ci-app-prod.yml +++ b/.github/workflows/ci-app-prod.yml @@ -48,19 +48,19 @@ concurrency: jobs: - test-prod-node16: + test-prod-node18: uses: weseek/growi/.github/workflows/reusable-app-prod.yml@master with: - node-version: 16.x + node-version: 18.x skip-cypress: true secrets: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - test-prod-node18: + test-prod-node20: uses: weseek/growi/.github/workflows/reusable-app-prod.yml@master with: - node-version: 18.x + node-version: 20.x skip-cypress: ${{ contains( github.event.pull_request.labels.*.name, 'dependencies' ) }} cypress-report-artifact-name: Cypress report cypress-config-video: ${{ inputs.cypress-config-video || false }} @@ -68,15 +68,15 @@ jobs: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - run-reg-suit-node18: - needs: [test-prod-node18] + run-reg-suit-node20: + needs: [test-prod-node20] uses: weseek/growi/.github/workflows/reusable-app-reg-suit.yml@master if: always() with: - node-version: 18.x + node-version: 20.x skip-reg-suit: ${{ contains( github.event.pull_request.labels.*.name, 'dependencies' ) }} cypress-report-artifact-name: Cypress report secrets: diff --git a/.github/workflows/ci-app.yml b/.github/workflows/ci-app.yml index 51d82a93ff0..8104d9e29aa 100644 --- a/.github/workflows/ci-app.yml +++ b/.github/workflows/ci-app.yml @@ -27,7 +27,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - uses: actions/checkout@v3 @@ -43,10 +43,10 @@ jobs: with: path: | **/node_modules - key: node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} + key: node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} restore-keys: | - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Restore dist uses: actions/cache/restore@v3 @@ -54,9 +54,9 @@ jobs: path: | **/.turbo **/dist - key: dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} restore-keys: | - dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}- + dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Install dependencies run: | @@ -84,7 +84,7 @@ jobs: path: | **/.turbo **/dist - key: dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} test: @@ -92,7 +92,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] services: mongodb: @@ -115,10 +115,10 @@ jobs: with: path: | **/node_modules - key: node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} + key: node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} restore-keys: | - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Restore dist uses: actions/cache/restore@v3 @@ -126,9 +126,9 @@ jobs: path: | **/.turbo **/dist - key: dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} restore-keys: | - dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}- + dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Install dependencies run: | @@ -166,7 +166,7 @@ jobs: path: | **/.turbo **/dist - key: dist-app-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-ci-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} launch-dev: @@ -174,7 +174,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] services: mongodb: @@ -197,10 +197,10 @@ jobs: with: path: | **/node_modules - key: node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} + key: node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('apps/app/package.json') }} restore-keys: | - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- - node_modules-${{ runner.OS }}-node${{ matrix.node-version }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('**/yarn.lock') }}- + node_modules-7.x-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Restore dist uses: actions/cache/restore@v3 @@ -209,9 +209,9 @@ jobs: **/.turbo **/dist ${{ github.workspace }}/apps/app/.next - key: dist-app-dev-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-dev-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} restore-keys: | - dist-app-dev-${{ runner.OS }}-node${{ matrix.node-version }}- + dist-app-7.x-dev-${{ runner.OS }}-node${{ matrix.node-version }}- - name: Install dependencies run: | @@ -244,4 +244,4 @@ jobs: **/.turbo **/dist ${{ github.workspace }}/apps/app/.next - key: dist-app-dev-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} + key: dist-app-7.x-dev-${{ runner.OS }}-node${{ matrix.node-version }}-${{ hashFiles('node_modules/.cache/turbo/*-meta.json') }} diff --git a/.github/workflows/ci-slackbot-proxy.yml b/.github/workflows/ci-slackbot-proxy.yml index c660b453c0f..34e3c356e89 100644 --- a/.github/workflows/ci-slackbot-proxy.yml +++ b/.github/workflows/ci-slackbot-proxy.yml @@ -29,7 +29,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - uses: actions/checkout@v3 @@ -94,7 +94,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] services: mysql: @@ -179,7 +179,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] services: mysql: diff --git a/.github/workflows/list-unhealthy-branches.yml b/.github/workflows/list-unhealthy-branches.yml index 6824190748b..4ef6917f849 100644 --- a/.github/workflows/list-unhealthy-branches.yml +++ b/.github/workflows/list-unhealthy-branches.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: '16' + node-version: '18' - name: List branches id: list-branches diff --git a/.github/workflows/release-slackbot-proxy.yml b/.github/workflows/release-slackbot-proxy.yml index 4a267c72731..c53bf78cb4c 100644 --- a/.github/workflows/release-slackbot-proxy.yml +++ b/.github/workflows/release-slackbot-proxy.yml @@ -102,7 +102,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: '16' + node-version: '18' cache: 'yarn' cache-dependency-path: '**/yarn.lock' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b46969aeb80..aea81e5606e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: '18' + node-version: '20' cache: 'yarn' cache-dependency-path: '**/yarn.lock' @@ -189,7 +189,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: '18' + node-version: '20' cache: 'yarn' cache-dependency-path: '**/yarn.lock' diff --git a/.github/workflows/reusable-app-prod.yml b/.github/workflows/reusable-app-prod.yml index 8c693f17818..9147d1bbd69 100644 --- a/.github/workflows/reusable-app-prod.yml +++ b/.github/workflows/reusable-app-prod.yml @@ -27,6 +27,9 @@ jobs: steps: - uses: actions/checkout@v3 + with: + # retrieve local font files + lfs: true - uses: actions/setup-node@v3 with: @@ -50,9 +53,9 @@ jobs: with: path: | **/node_modules - key: node_modules-app-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} + key: node_modules-app-7.x-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - node_modules-app-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}- + node_modules-app-7.x-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}- - name: Install dependencies run: | @@ -67,10 +70,10 @@ jobs: **/.turbo **/dist ${{ github.workspace }}/apps/app/.next - key: dist-app-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ github.ref_name }}-${{ github.sha }} + key: dist-app-7.x-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ github.ref_name }}-${{ github.sha }} restore-keys: | - dist-app-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ github.ref_name }}- - dist-app-prod-${{ runner.OS }}-node${{ inputs.node-version }}- + dist-app-7.x-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ github.ref_name }}- + dist-app-7.x-prod-${{ runner.OS }}-node${{ inputs.node-version }}- - name: Build working-directory: ./apps/app @@ -162,9 +165,9 @@ jobs: with: path: | **/node_modules - key: node_modules-app-launch-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} + key: node_modules-app-7.x-launch-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - node_modules-app-launch-prod-${{ runner.OS }}-node${{ inputs.node-version }}- + node_modules-app-7.x-launch-prod-${{ runner.OS }}-node${{ inputs.node-version }}- - name: Install dependencies run: | @@ -253,9 +256,9 @@ jobs: with: path: | **/node_modules - key: node_modules-app-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} + key: node_modules-app-7.x-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - node_modules-app-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}- + node_modules-app-7.x-build-prod-${{ runner.OS }}-node${{ inputs.node-version }}- - name: Cache/Restore Cypress files uses: actions/cache@v3 diff --git a/.github/workflows/reusable-app-reg-suit.yml b/.github/workflows/reusable-app-reg-suit.yml index 37d1f0529a4..5128a2f168c 100644 --- a/.github/workflows/reusable-app-reg-suit.yml +++ b/.github/workflows/reusable-app-reg-suit.yml @@ -76,9 +76,9 @@ jobs: with: path: | **/node_modules - key: node_modules-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} + key: node_modules-7.x-${{ runner.OS }}-node${{ inputs.node-version }}-${{ hashFiles('**/yarn.lock') }} restore-keys: | - node_modules-${{ runner.OS }}-node${{ inputs.node-version }}- + node_modules-7.x-${{ runner.OS }}-node${{ inputs.node-version }}- - name: Install dependencies run: | diff --git a/.mergify.yml b/.mergify.yml index 82250acb8d7..6bcd81281ee 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -3,11 +3,11 @@ pull_request_rules: conditions: - author = dependabot[bot] - '#approved-reviews-by >= 1' - - check-success = "lint (18.x)" - - check-success = "test (18.x)" - - check-success = "launch-dev (18.x)" - - check-success = "test-prod-node16 / launch-prod" + - check-success = "lint (20.x)" + - check-success = "test (20.x)" + - check-success = "launch-dev (20.x)" - check-success = "test-prod-node18 / launch-prod" + - check-success = "test-prod-node20 / launch-prod" actions: merge: method: merge diff --git a/README.md b/README.md index 4e02d04b1f6..7b04bfc7dbd 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,7 @@ - **Features** - Create hierarchical pages with markdown -> [Try GROWI on the demo site](https://docs.growi.org/en/guide/getting-started/try_growi.html) - - Simultaneously edit with multiple people by [HackMD(CodiMD)](https://hackmd.io/) integration - - [GROWI Docs: HackMD(CodiMD) Integration](https://docs.growi.org/en/admin-guide/admin-cookbook/integrate-with-hackmd.html) + - Simultaneously edit with multiple people - Support Authentication with LDAP / Active Directory, OAuth - SSO(Single Sign On) with SAML - Slack/Mattermost, IFTTT Integration @@ -80,7 +79,7 @@ See [GROWI Docs: Environment Variables](https://docs.growi.org/en/admin-guide/ad ## Dependencies -- Node.js v16.x or v18.x +- Node.js v18.x or v20.x - npm 6.x - yarn - [Turborepo](https://turbo.build/repo) diff --git a/README_JP.md b/README_JP.md index 59057c9f7e8..512038083e4 100644 --- a/README_JP.md +++ b/README_JP.md @@ -37,8 +37,7 @@ - **主な機能** - マークダウンを使用してページを階層構造で作成することが可能です。 -> [デモサイトで GROWI を体験する](https://docs.growi.org/ja/guide/getting-started/try_growi.html)。 - - [HackMD(CodiMd)](https://hackmd.io/) と連携することで同時多人数編集が可能です。 - - [GROWI Docs: HackMD(CodiMD) 連携](https://docs.growi.org/ja/admin-guide/admin-cookbook/integrate-with-hackmd.html) + - 同時多人数編集が可能です。 - LDAP / Active Direcotry , OAuth 認証をサポートしています。 - SAML を用いた Single Sign On が可能です。 - Slack / Mattermost, IFTTT と連携することが可能です。 @@ -79,7 +78,7 @@ Crowi からの移行は **[こちら](https://docs.growi.org/en/admin-guide/mig ## 依存関係 -- Node.js v16.x or v18.x +- Node.js v18.x or v20.x - npm 6.x - yarn - [Turborepo](https://turbo.build/repo) diff --git a/apps/app/.env.development b/apps/app/.env.development index 6c34a3566e8..ba49ca0b1c6 100644 --- a/apps/app/.env.development +++ b/apps/app/.env.development @@ -13,8 +13,6 @@ MONGO_URI="mongodb://mongo:27017/growi" ELASTICSEARCH_URI="http://elasticsearch:9200/growi" ELASTICSEARCH_REQUEST_TIMEOUT=15000 ELASTICSEARCH_REJECT_UNAUTHORIZED=true -HACKMD_URI="http://localhost:3010" -HACKMD_URI_FOR_SERVER="http://hackmd:3000" OGP_URI="http://ogp:8088" QUESTIONNAIRE_SERVER_ORIGIN="http://host.docker.internal:3003" # DRAWIO_URI="http://localhost:8080/?offline=1&https=0" diff --git a/apps/app/.eslintignore b/apps/app/.eslintignore index 4a3269fe1ed..e8a2cf4fd62 100644 --- a/apps/app/.eslintignore +++ b/apps/app/.eslintignore @@ -2,8 +2,6 @@ /dist/** /transpiled/** /public/** -/src/client/legacy/thirdparty-js/** -/src/client/util/reveal/plugins/markdown.js /src/linter-checker/** /tmp/** /next-env.d.ts diff --git a/apps/app/src/components/PageEditor/CodeMirrorEditor.jsx b/apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.jsx similarity index 99% rename from apps/app/src/components/PageEditor/CodeMirrorEditor.jsx rename to apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.jsx index 21eb4ebe95b..0e7cf7664c0 100644 --- a/apps/app/src/components/PageEditor/CodeMirrorEditor.jsx +++ b/apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.jsx @@ -727,7 +727,7 @@ class CodeMirrorEditor extends AbstractEditor { renderCheatsheetModalButton() { return ( ); } @@ -739,7 +739,7 @@ class CodeMirrorEditor extends AbstractEditor {
{ this.state.isSimpleCheatsheetShown ? ( -
+
{cheatsheetModalButton}
@@ -747,7 +747,7 @@ class CodeMirrorEditor extends AbstractEditor {
) : ( -
+
{cheatsheetModalButton}
) @@ -760,7 +760,7 @@ class CodeMirrorEditor extends AbstractEditor { const { emojiSearchText } = this.state; return this.state.isEmojiPickerShown ? ( -
+
this.setState({ isEmojiPickerShown: false })} diff --git a/apps/app/src/components/PageEditor/CodeMirrorEditor.module.scss b/apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.module.scss similarity index 98% rename from apps/app/src/components/PageEditor/CodeMirrorEditor.module.scss rename to apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.module.scss index 7d795f97b4c..10e3cfbe498 100644 --- a/apps/app/src/components/PageEditor/CodeMirrorEditor.module.scss +++ b/apps/app/_obsolete/src/components/PageEditor/CodeMirrorEditor.module.scss @@ -1,4 +1,4 @@ -@use '~/styles/bootstrap/init' as bs; +@use '@growi/core/scss/bootstrap/init' as bs; .grw-codemirror-editor :global { @import '~codemirror/lib/codemirror'; diff --git a/apps/app/src/components/PageEditor/CommentMentionHelper.ts b/apps/app/_obsolete/src/components/PageEditor/CommentMentionHelper.ts similarity index 100% rename from apps/app/src/components/PageEditor/CommentMentionHelper.ts rename to apps/app/_obsolete/src/components/PageEditor/CommentMentionHelper.ts diff --git a/apps/app/_obsolete/src/components/PageEditor/ConflictDiffModal.tsx b/apps/app/_obsolete/src/components/PageEditor/ConflictDiffModal.tsx new file mode 100644 index 00000000000..6cccc45d47f --- /dev/null +++ b/apps/app/_obsolete/src/components/PageEditor/ConflictDiffModal.tsx @@ -0,0 +1,344 @@ +import React, { + useState, useEffect, useRef, useMemo, useCallback, +} from 'react'; + +import type { IRevisionOnConflict } from '@growi/core'; +import { UserPicture } from '@growi/ui/dist/components'; +import CodeMirror from 'codemirror/lib/codemirror'; +import { format, parseISO } from 'date-fns'; +import { useTranslation } from 'next-i18next'; +import { + Modal, ModalHeader, ModalBody, ModalFooter, +} from 'reactstrap'; + +import { useSaveOrUpdate } from '~/client/services/page-operation'; +import { toastError, toastSuccess } from '~/client/util/toastr'; +import { OptionsToSave } from '~/interfaces/page-operation'; +import { useCurrentPathname, useCurrentUser } from '~/stores/context'; +import { useCurrentPagePath, useSWRxCurrentPage, useCurrentPageId } from '~/stores/page'; +import { + useRemoteRevisionBody, useRemoteRevisionId, useRemoteRevisionLastUpdatedAt, useRemoteRevisionLastUpdateUser, useSetRemoteLatestPageData, +} from '~/stores/remote-latest-page'; + +import ExpandOrContractButton from '../ExpandOrContractButton'; +import { UncontrolledCodeMirror } from '../UncontrolledCodeMirror'; + +require('codemirror/lib/codemirror.css'); +require('codemirror/addon/merge/merge'); +require('codemirror/addon/merge/merge.css'); +const DMP = require('diff_match_patch'); + +Object.keys(DMP).forEach((key) => { window[key] = DMP[key] }); + +type ConflictDiffModalProps = { + isOpen?: boolean; + onClose?: (() => void); + markdownOnEdit: string; + optionsToSave: OptionsToSave | undefined; + afterResolvedHandler: () => void, +}; + +type ConflictDiffModalCoreProps = { + isOpen?: boolean; + onClose?: (() => void); + optionsToSave: OptionsToSave | undefined; + request: IRevisionOnConflictWithStringDate, + origin: IRevisionOnConflictWithStringDate, + latest: IRevisionOnConflictWithStringDate, + afterResolvedHandler: () => void, +}; + +type IRevisionOnConflictWithStringDate = Omit & { + createdAt: string +} + +const ConflictDiffModalCore = (props: ConflictDiffModalCoreProps): JSX.Element => { + const { + onClose, request, origin, latest, optionsToSave, afterResolvedHandler, + } = props; + + const { t } = useTranslation(''); + const [resolvedRevision, setResolvedRevision] = useState(''); + const [isRevisionselected, setIsRevisionSelected] = useState(false); + const [isModalExpanded, setIsModalExpanded] = useState(false); + const [codeMirrorRef, setCodeMirrorRef] = useState(null); + + const { data: remoteRevisionId } = useRemoteRevisionId(); + const { setRemoteLatestPageData } = useSetRemoteLatestPageData(); + const { data: pageId } = useCurrentPageId(); + const { data: currentPagePath } = useCurrentPagePath(); + const { data: currentPathname } = useCurrentPathname(); + + const saveOrUpdate = useSaveOrUpdate(); + + const uncontrolledRef = useRef(null); + + useEffect(() => { + if (codeMirrorRef != null) { + CodeMirror.MergeView(codeMirrorRef, { + value: origin.revisionBody, + origLeft: request.revisionBody, + origRight: latest.revisionBody, + lineNumbers: true, + collapseIdentical: true, + showDifferences: true, + highlightDifferences: true, + connect: 'connect', + readOnly: true, + revertButtons: false, + }); + } + }, [codeMirrorRef, origin.revisionBody, request.revisionBody, latest.revisionBody]); + + const close = useCallback(() => { + if (onClose != null) { + onClose(); + } + }, [onClose]); + + const onResolveConflict = useCallback(async() => { + if (currentPathname == null) { return } + // disable button after clicked + setIsRevisionSelected(false); + + const codeMirrorVal = uncontrolledRef.current?.editor.doc.getValue(); + + try { + const { page } = await saveOrUpdate( + codeMirrorVal, + { pageId, path: currentPagePath || currentPathname, revisionId: remoteRevisionId }, + optionsToSave, + ); + const remotePageData = { + remoteRevisionId: page.revision._id, + remoteRevisionBody: page.revision.body, + remoteRevisionLastUpdateUser: page.lastUpdateUser, + remoteRevisionLastUpdatedAt: page.updatedAt, + revisionIdHackmdSynced: page.revisionIdHackmdSynced, + hasDraftOnHackmd: page.hasDraftOnHackmd, + }; + setRemoteLatestPageData(remotePageData); + afterResolvedHandler(); + + close(); + + toastSuccess('Saved successfully'); + } + catch (error) { + toastError(`Error occured: ${error.message}`); + } + + }, [afterResolvedHandler, close, currentPagePath, currentPathname, optionsToSave, pageId, remoteRevisionId, saveOrUpdate, setRemoteLatestPageData]); + + // TODO: No longer support custom close icon in bootstrap v5 + // const resizeAndCloseButtons = useMemo(() => ( + //
+ // setIsModalExpanded(true)} + // contractWindow={() => setIsModalExpanded(false)} + // /> + // + //
+ // ), [isModalExpanded, close]); + + const isOpen = props.isOpen ?? false; + + return ( + + {/* */} + + error{t('modal_resolve_conflict.resolve_conflict')} + + + { isOpen + && ( +
+
+

{t('modal_resolve_conflict.resolve_conflict_message')}

+
+
+

{t('modal_resolve_conflict.requested_revision')}

+
+
+ +
+
+

updated by {request.user.username}

+

{request.createdAt}

+
+
+
+
+

{t('modal_resolve_conflict.origin_revision')}

+
+
+ +
+
+

updated by {origin.user.username}

+

{origin.createdAt}

+
+
+
+
+

{t('modal_resolve_conflict.latest_revision')}

+
+
+ +
+
+

updated by {latest.user.username}

+

{latest.createdAt}

+
+
+
+
{ setCodeMirrorRef(el) }}>
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+

{t('modal_resolve_conflict.selected_editable_revision')}

+ +
+
+
+ )} +
+ + + + +
+ ); +}; + + +export const ConflictDiffModal = (props: ConflictDiffModalProps): JSX.Element => { + const { + isOpen, onClose, optionsToSave, afterResolvedHandler, + } = props; + const { data: currentUser } = useCurrentUser(); + + // state for current page + const { data: currentPage } = useSWRxCurrentPage(); + + // state for latest page + const { data: remoteRevisionId } = useRemoteRevisionId(); + const { data: remoteRevisionBody } = useRemoteRevisionBody(); + const { data: remoteRevisionLastUpdateUser } = useRemoteRevisionLastUpdateUser(); + const { data: remoteRevisionLastUpdatedAt } = useRemoteRevisionLastUpdatedAt(); + + const currentTime: Date = new Date(); + + const isRemotePageDataInappropriate = remoteRevisionId == null || remoteRevisionBody == null || remoteRevisionLastUpdateUser == null; + + if (!isOpen || currentUser == null || currentPage == null || isRemotePageDataInappropriate) { + return <>; + } + + const currentPageCreatedAtFixed = typeof currentPage.updatedAt === 'string' + ? parseISO(currentPage.updatedAt) + : currentPage.updatedAt; + + const request: IRevisionOnConflictWithStringDate = { + revisionId: '', + revisionBody: props.markdownOnEdit, + createdAt: format(currentTime, 'yyyy/MM/dd HH:mm:ss'), + user: currentUser, + }; + const origin: IRevisionOnConflictWithStringDate = { + revisionId: currentPage?.revision._id, + revisionBody: currentPage?.revision.body, + createdAt: format(currentPageCreatedAtFixed, 'yyyy/MM/dd HH:mm:ss'), + user: currentPage?.lastUpdateUser, + }; + const latest: IRevisionOnConflictWithStringDate = { + revisionId: remoteRevisionId, + revisionBody: remoteRevisionBody, + createdAt: format(new Date(remoteRevisionLastUpdatedAt || currentTime.toString()), 'yyyy/MM/dd HH:mm:ss'), + user: remoteRevisionLastUpdateUser, + }; + + const propsForCore = { + isOpen, + onClose, + optionsToSave, + request, + origin, + latest, + afterResolvedHandler, + }; + + return ; +}; diff --git a/apps/app/src/components/Navbar/AppearanceModeDropdown.tsx b/apps/app/_obsolete/src/components/Sidebar/AppearanceModeDropdown.tsx similarity index 78% rename from apps/app/src/components/Navbar/AppearanceModeDropdown.tsx rename to apps/app/_obsolete/src/components/Sidebar/AppearanceModeDropdown.tsx index 466ad478403..4ef6a56e427 100644 --- a/apps/app/src/components/Navbar/AppearanceModeDropdown.tsx +++ b/apps/app/_obsolete/src/components/Sidebar/AppearanceModeDropdown.tsx @@ -10,10 +10,8 @@ import { useUserUISettings } from '~/client/services/user-ui-settings'; import { usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser } from '~/stores/ui'; import { Themes, useNextThemes } from '~/stores/use-next-themes'; -import MoonIcon from '../Icons/MoonIcon'; import SidebarDockIcon from '../Icons/SidebarDockIcon'; import SidebarDrawerIcon from '../Icons/SidebarDrawerIcon'; -import SunIcon from '../Icons/SunIcon'; type AppearanceModeDropdownProps = { isAuthenticated: boolean, @@ -75,20 +73,20 @@ export const AppearanceModeDropdown:FC = (props: Ap <>
{t(isEditMode ? 'personal_dropdown.sidebar_mode_editor' : 'personal_dropdown.sidebar_mode')}
-
-
+
+
-
+
preferDrawerModeSwitchModifiedHandler(!e.target.checked, isEditMode)} /> - +
@@ -101,16 +99,16 @@ export const AppearanceModeDropdown:FC = (props: Ap }, [isPreferDrawerMode, isPreferDrawerModeOnEdit, preferDrawerModeSwitchModifiedHandler, t]); return ( - <> +
{/* setting button */} {/* remove .dropdown-toggle for hide caret */} {/* See https://stackoverflow.com/a/44577512/13183572 */} - {/* dropdown */} -
+
{/* sidebar mode */} {renderSidebarModeSwitch(false)} @@ -129,38 +127,38 @@ export const AppearanceModeDropdown:FC = (props: Ap {dropdownDivider}
{t('personal_dropdown.color_mode')}
-
-
+
+
- + light_mode -
+
userPreferenceSwitchModifiedHandler(e.target.checked)} /> - +
- + dark_mode
-
-
-
+
+
+
followOsCheckboxModifiedHandler(e.target.checked)} /> - +
@@ -170,7 +168,7 @@ export const AppearanceModeDropdown:FC = (props: Ap
- +
); }; diff --git a/apps/app/_obsolete/src/styles/theme/_apply-colors-dark.scss b/apps/app/_obsolete/src/styles/theme/_apply-colors-dark.scss new file mode 100644 index 00000000000..2be401582c6 --- /dev/null +++ b/apps/app/_obsolete/src/styles/theme/_apply-colors-dark.scss @@ -0,0 +1,672 @@ +@use '@growi/core/scss/bootstrap/init' as *; + +@use '../variables' as var; +@use '../atoms/mixins/buttons' as mixins-buttons; +@use './mixins/count-badge'; +@use './mixins/hsl-button'; +@use './hsl-functions' as hsl; + +// determine optional variables +:root[data-bs-theme='dark'] { + $color-list: var(--color-list,var(--color-global)); + $bgcolor-list: var(--bgcolor-list,var(--bgcolor-global)); + $color-list-hover: var(--color-list-hover,var(--color-global)); + $color-list-active: var(--color-list-active,var(--color-reversal)); + $bgcolor-list-hover: var(--bgcolor-list-hover,var(--bgcolor-global)); + $bgcolor-list-active: var(--bgcolor-list-active,var(--primary)); + $color-table: var(--color-table,white); + $bgcolor-table: var(--bgcolor-table,#343a40); + $border-color-table: var(--border-color-table,lighten(#343a40, 7.5%)); + $color-table-hover: var(--color-table-hover,rgba(white, 0.075)); + $bgcolor-table-hover: var(--bgcolor-table-hover,lighten(#343a40, 7.5%)); + $bgcolor-sidebar-list-group: var(--bgcolor-sidebar-list-group,var(--bgcolor-list)); + $color-tags: var(--color-tags,#949494); + $bgcolor-tags: var(--bgcolor-tags,var(--dark)); + $border-color-global: var(--border-color-global,#{$gray-500}); + $border-color-toc: var(--border-color-toc,#{$border-color-global}); + $color-dropdown: var(--color-dropdown,var(--color-global)); + $bgcolor-dropdown: var(--bgcolor-dropdown,var(--bgcolor-global)); + $color-dropdown-link: var(--color-dropdown-link,var(--color-global)); + $color-dropdown-link-hover: var(--color-dropdown-link-hover,var(--light)); + $bgcolor-dropdown-link-hover: var(--bgcolor-dropdown-link-hover,hsl.lighten(var(--bgcolor-global), 15%)); + $color-dropdown-link-active: var(--color-dropdown-link-active,var(--light)); + $bgcolor-dropdown-link-active: var(--bgcolor-dropdown-link-active,var(--primary)); + $body-bg: var(--bgcolor-global); + $body-color: var(--color-global); + + // override bootstrap variables + // $text-muted: $gray-550; + $table-dark-color: $color-table; + $table-dark-bg: $bgcolor-table; + $table-dark-border-color: $border-color-table; + $table-dark-hover-color: $color-table-hover; + $table-dark-hover-bg: $bgcolor-table-hover; + $border-color: $border-color-global; + $dropdown-color: $color-dropdown; + $dropdown-bg: $bgcolor-dropdown; + $dropdown-link-color: $color-dropdown-link; + $dropdown-link-hover-color: $color-dropdown-link-hover; + $dropdown-link-hover-bg: $bgcolor-dropdown-link-hover; + $dropdown-link-active-color: $color-dropdown-link-active; + $dropdown-link-active-bg: $bgcolor-dropdown-link-active; + + @import './mixins/list-group'; + // TODO: activate (https://redmine.weseek.co.jp/issues/128307) + // @import './reboot-bootstrap-text'; + // @import './reboot-bootstrap-border-colors'; + // @import './reboot-bootstrap-tables'; + // @import './reboot-bootstrap-theme-colors'; + // @import 'hsl-reboot-bootstrap-theme-colors'; + // @import './reboot-bootstrap-dropdown'; + + + // TODO: activate (https://redmine.weseek.co.jp/issues/128307) + + // // List Group + // @include override-list-group-item( + // $color-list, + // $bgcolor-sidebar-list-group, + // $color-list-hover, + // $bgcolor-list-hover, + // $color-list-active, + // $bgcolor-list-active + // ); + // /* + // * Form + // */ + // input.form-control, + // select.form-control, + // select.form-select, + // textarea.form-control { + // color: var(--color-global); + // background-color: hsl.darken(var(--bgcolor-global), 5%); + // border-color: $border-color-global; + // &:focus { + // background-color: var(--bgcolor-global); + // } + // // FIXME: accent color + // // border: 1px solid darken($border, 30%); + // } + + // .form-control[disabled], + // .form-control[readonly] { + // color: hsl.lighten(var(--color-global),10%); + // background-color: hsl.lighten(var(--bgcolor-global),5%); + // } + + // TODO: theme-color() dropped in bootstrap v5 + // TODO: .input-group-prepend dropped in bootstrap v5 + // https://redmine.weseek.co.jp/issues/128307 + // .input-group > .input-group-prepend > .input-group-text { + // color: theme-color('light'); + // background-color: theme-color('secondary'); + // border: 1px solid theme-color('secondary'); + // border-right: none; + // &.text-muted { + // color: theme-color('light') !important; + // } + // } + + // .input-group input { + // border-color: $border-color-global; + // } + + // label.form-check-label::before { + // background-color: hsl.darken(var(--bgcolor-global),5%); + // } + + // .rbt-input-multi .rbt-input-main { + // color: black; + // } + // /* + // * Table + // */ + // .table { + // @extend .table-dark !optional; + // thead th { + // vertical-align: bottom; + // border-bottom: 2px solid #d6dadf; + // } + // } + + // /* + // * Card + // */ + // .card:not([class*='bg-']):not(.custom-card):not(.card-disabled) { + // @extend .bg-dark; + // } + + // .card.custom-card { + // border-color: var(--secondary); + // } + + // .card.card-disabled { + // background-color: lighten($dark, 10%); + // border-color: var(--secondary); + // } + + // /* + // * Pagination + // */ + // ul.pagination { + // li.page-item.disabled { + // button.page-link { + // color: $gray-400; + // } + // } + // li.page-item.active { + // button.page-link { + // color: hsl.contrast(var(--primary)); + // background-color: var(--primary); + // &:hover, + // &:focus { + // color: hsl.contrast(var(--primary)); + // background-color: var(--primary); + // } + // } + // } + // li.page-item { + // button.page-link { + // @extend .btn-dark; + // color: var(--primary); + // } + // } + // } + + // /* + // * GROWI Login form + // */ + // .nologin { + // // background color + // $color-gradient: #3c465c; + // background: linear-gradient(45deg, darken($color-gradient, 30%) 0%, hsla(340, 100%, 55%, 0) 70%), + // linear-gradient(135deg, darken(var.$growi-green, 30%) 10%, hsla(225, 95%, 50%, 0) 70%), + // linear-gradient(225deg, darken(var.$growi-blue, 20%) 10%, hsla(140, 90%, 50%, 0) 80%), + // linear-gradient(315deg, darken($color-gradient, 25%) 100%, hsla(35, 95%, 55%, 0) 70%); + + // .nologin-header { + // background-color: rgba(black, 0.5); + + // .logo { + // background-color: rgba(white, 0); + // fill: rgba(white, 0.5); + // } + + // h1 { + // color: rgba(white, 0.5); + // } + // } + + // .nologin-dialog { + // background-color: rgba(black, 0.5); + // .link-switch { + // color: #7b9bd5; + // &:hover { + // color: lighten(#7b9bd5,10%); + // } + // } + // } + + // .input-group { + // .input-group-text { + // color: darken(white, 30%); + // background-color: rgba($gray-700, 0.7); + // } + + // .form-control { + // color: white; + // background-color: rgba(#505050, 0.7); + // box-shadow: unset; + + // &::placeholder { + // color: darken(white, 30%); + // } + // } + // } + + // .btn-fill { + // .btn-label { + // color: $gray-300; + // } + // .btn-label-text { + // color: $gray-400; + // } + // } + + // .grw-external-auth-form { + // border-color: gray !important; + // } + + // .btn-external-auth-tab { + // @extend .btn-dark; + // } + + // // footer link text + // .link-growi-org { + // color: rgba(white, 0.4); + + // &:hover, + // &.focus { + // color: rgba(white, 0.7); + + // .growi { + // color: darken(var.$growi-green, 5%); + // } + + // .org { + // color: darken(var.$growi-blue, 5%); + // } + // } + // } + // } + + // /* + // * GROWI subnavigation + // */ + // .grw-drawer-toggler { + // @include button-variant($dark, $dark); + // @include mixins-buttons.button-svg-icon-variant($dark, $dark); + // color: $gray-400; + // box-shadow: none !important; + // } + + // /** + // * GROWI PagePathHierarchicalLink + // */ + // .grw-page-path-text-muted-container .grw-page-path-hierarchical-link a { + // color: $gray-400; + // } + + // /* + // * GROWI page list + // */ + // .page-list { + // .page-list-ul { + // > li { + // > span.page-list-meta { + // color: hsl.darken(var(--color-global),10%); + // } + // } + // } + + // // List group + // .list-group-item { + // &.active { + // background-color: hsl.lighten(var(--bgcolor-global),10%) !important; + // } + // &.list-group-item-action:hover { + // background-color: hsl.lighten(var(--bgcolor-global),10%) !important; + // } + // .page-list-snippet { + // color: hsl.darken(var(--color-global),10%); + // } + // } + // } + + // /* + // * GROWI ToC + // */ + // .revision-toc-content { + // ::marker { + // color: hsl.lighten(var(--color-global),30%); + // } + // } + + // /* + // * GROWI subnavigation + // */ + // .grw-subnav { + // background-color: var(--bgcolor-subnav); + // } + + // .grw-subnav-fixed-container .grw-subnav { + // background-color: hsl.alpha(var(--bgcolor-subnav),85%); + // } + + // .grw-page-editor-mode-manager { + // .btn-outline-primary { + // &:hover { + // color: var(--primary); + // background-color: $gray-700; + // } + // } + // } + + // // Search drop down + // #search-typeahead-asynctypeahead { + // background-color: var(--bgcolor-global); + // .table { + // background-color: transparent; + // } + // } + + // /* + // * GROWI Sidebar + // */ + // .grw-sidebar { + // --gray-500: hsl(var(--gray-500-hs),var(--gray-500-l)); + // --gray-500-hs: 210,13%; + // --gray-500-l: 61%; + // // List + // @include override-list-group-item( + // $color-list, + // $bgcolor-sidebar-list-group, + // $color-list-hover, + // $bgcolor-list-hover, + // $color-list-active, + // $bgcolor-list-active + // ); + // // Pagetree + // .grw-pagetree, .grw-foldertree { + // @include override-list-group-item-for-pagetree( + // var(--color-sidebar-context), + // hsl.lighten(var(--bgcolor-sidebar-context),8%), + // hsl.lighten(var(--bgcolor-sidebar-context),15%), + // hsl.darken(var(--color-sidebar-context),15%), + // hsl.darken(var(--color-sidebar-context),10%), + // hsl.lighten(var(--bgcolor-sidebar-context),18%), + // hsl.lighten(var(--bgcolor-sidebar-context),24%) + // ); + // .grw-pagetree-triangle-btn, .grw-foldertree-triangle-btn { + // @include mixins-buttons.button-outline-svg-icon-variant(var(--secondary), $gray-200); + // } + // .btn-page-item-control { + // @include hsl-button.button-outline-variant(var(--gray-500), var(--gray-500), var(--secondary), transparent); + // &:hover { + // background-color: hsl.lighten(var(--bgcolor-sidebar-context),20%); + // } + // &:not(:disabled):not(.disabled):active, + // &:not(:disabled):not(.disabled).active { + // background-color: hsl.lighten(var(--bgcolor-sidebar-context),34%); + // } + // box-shadow: none !important; + // } + // } + + // // bookmarks + // .grw-folder-tree-container { + // .grw-drop-item-area , .grw-foldertree-item-container { + // .grw-accept-drop-item { + // border-color: hsl.lighten(var(--bgcolor-sidebar-context), 30%) !important; + // } + // } + // } + // .private-legacy-pages-link { + // &:hover { + // background: var(--bgcolor-list-hover); + // } + // } + // } + + // .btn.btn-page-item-control { + // @include hsl-button.button-outline-variant(var(--gray-500), var(--gray-500), var(--secondary), transparent); + // &:hover { + // background-color: $gray-700; + // } + // &:not(:disabled):not(.disabled):active, + // &:not(:disabled):not(.disabled).active { + // color: $gray-200; + // background-color: $gray-600; + // } + // box-shadow: none !important; + // } + + // // Bookmark item on user page + // .grw-user-page-list-m { + // @include override-list-group-item($color-list, $bgcolor-sidebar-list-group, $color-list-hover, $bgcolor-list-hover, $color-list-active, $bgcolor-list-active); + // .grw-foldertree { + // @include override-list-group-item-for-pagetree( + // $body-color, + // hsl.lighten($body-bg, 8%), + // hsl.lighten($body-bg, 15%), + // hsl.darken($body-color, 15%), + // hsl.darken($body-color, 10%), + // hsl.lighten($body-bg, 18%), + // hsl.lighten($body-bg, 24%) + // ); + // .grw-foldertree-triangle-btn { + // @include mixins-buttons.button-outline-svg-icon-variant($secondary, $gray-200); + // } + // } + // .grw-folder-tree-container { + // .grw-drop-item-area , .grw-foldertree-item-container { + // .grw-accept-drop-item { + // border-color: hsl.lighten(var($body-bg), 30%) !important; + // } + // } + // } + // } + + // // Bookmark dropdown menu + // .grw-bookmark-folder-dropdown { + // .grw-bookmark-folder-menu { + // .form-control{ + // &:focus { + // color: $body-color + // } + // } + // .grw-bookmark-folder-menu-item { + // @include mixins-buttons.button-outline-svg-icon-variant($secondary, $gray-200); + // .grw-bookmark-folder-menu-item-title { + // color: $body-color + // } + // } + // } + // } + + // /* + // * Popover + // */ + // .popover { + // background-color: var(--bgcolor-global); + // border-color: var(--secondary); + // .popover-header { + // color: white; + // background-color: var(--secondary); + // border-color: var(--secondary); + // } + // .popover-body { + // color: inherit; + // } + + // TODO: Check renamed .arrow to .popover-arrow + // see: https://getbootstrap.com/docs/5.2/migration/#popovers + + // &.bs-popover-top .arrow { + // &::before { + // border-top-color: var(--secondary); + // } + + // &::after { + // border-top-color: var(--bgcolor-global); + // } + // } + // &.bs-popover-bottom .arrow { + // &::before { + // border-bottom-color: var(--secondary); + // } + + // &::after { + // border-bottom-color: var(--bgcolor-global); + // } + // } + // &.bs-popover-right .arrow { + // &::before { + // border-right-color: var(--secondary); + // } + + // &::after { + // border-right-color: var(--bgcolor-global); + // } + // } + // &.bs-popover-left .arrow { + // &::before { + // border-left-color: var(--secondary); + // } + + // &::after { + // border-left-color: var(--bgcolor-global); + // } + // } + // } + + // /* + // * GROWI Grid Edit Modal + // */ + // .grw-grid-edit-preview { + // background: $gray-900; + // } + + // /* + // * Slack + // */ + // .grw-slack-notification { + // background-color: transparent; + // $color-slack: #4b144c; + + // .form-control { + // background: var(--bgcolor-global); + // } + + // .form-check-label { + // &::before { + // background-color: var(--secondary); + // border-color: transparent; + // } + // &::after { + // background-color: darken($color-slack, 5%); + // background-image: url(/images/icons/slack/slack-logo-dark-off.svg); + // } + // } + + // .form-check-input:checked ~ .form-check-label { + // &::before { + // background-color: lighten($color-slack, 10%); + // } + // &::after { + // background-color: darken($color-slack, 5%); + // background-image: url(/images/icons/slack/slack-logo-dark-on.svg); + // } + // } + // .grw-slack-logo svg { + // fill: #dd80de; + // } + + // .grw-btn-slack { + // background-color: black; + // &:focus, + // &:hover { + // background-color: black; + // } + // } + + // .grw-btn-slack-triangle { + // color: var(--secondary); + // } + // } + + // /* + // * GROWI HandsontableModal + // */ + + // .handsontable td { + // color: black; + // } + + // .grw-hot-modal-navbar { + // background-color: var(--dark); + // } + + // .wiki { + // h1 { + // border-color: hsl.lighten(var(--border-color-theme),10%); + // } + // h2 { + // border-color: var(--border-color-theme); + // } + // } + + // /* + // * GROWI comment form + // */ + // .comment-form { + // #slack-mark-black { + // display: none; + // } + // } + + // .page-comment-form .comment-form-main { + // &:before { + // border-right-color: var(--bgcolor-global); + // } + // } + + // /* + // * GROWI tags + // */ + // .grw-tag-labels { + // .grw-tag-label { + // color: $color-tags; + // background-color: $bgcolor-tags; + // } + // } + + // mark.rbt-highlight-text { + // color: var(--color-global); + // } + + // /* + // * GROWI popular tags + // */ + // .grw-popular-tag-labels { + // .grw-tag-label { + // color: $color-tags; + // background-color: $bgcolor-tags; + // } + // } + + // /* + // * admin settings + // */ + // .admin-setting-header { + // border-color: $border-color-global; + // } + + // /* + // * grw-side-contents + // */ + // .grw-side-contents-sticky-container { + // .grw-count-badge { + // @include count-badge.count-badge($gray-400, $gray-700); + // } + + // .grw-border-vr { + // border-color: $border-color-toc; + // } + + // .revision-toc { + // border-color: $border-color-toc; + // } + // } + + // /* + // * drawio + // */ + // .drawio-viewer { + // border-color: $border-color-global; + // } + + // /* + // * modal + // */ + // .grw-modal-head { + // border-color: $border-color-global; + // } + + // /* + // * skeleton + // */ + // .grw-skeleton { + // background-color: hsl.lighten(var(--bgcolor-subnav),10%); + // } +} diff --git a/apps/app/src/styles/theme/_apply-colors-light.scss b/apps/app/_obsolete/src/styles/theme/_apply-colors-light.scss similarity index 94% rename from apps/app/src/styles/theme/_apply-colors-light.scss rename to apps/app/_obsolete/src/styles/theme/_apply-colors-light.scss index a0ba2d78ea9..54a0f09322c 100644 --- a/apps/app/src/styles/theme/_apply-colors-light.scss +++ b/apps/app/_obsolete/src/styles/theme/_apply-colors-light.scss @@ -1,12 +1,13 @@ +@use '@growi/core/scss/bootstrap/init' as *; + @use '../variables' as var; -@use '../bootstrap/init' as *; @use '../atoms/mixins/buttons' as mixins-buttons; @use './mixins/count-badge'; @use './mixins/hsl-button'; @use './hsl-functions' as hsl; // determine optional variables -:root[data-theme='light'] { +:root[data-bs-theme='light'] { $color-list: var(--color-list,var(--color-global)); $bgcolor-list: var(--bgcolor-list,var(--bgcolor-global)); $color-list-hover: var(--color-list-hover,var(--color-global)); @@ -49,12 +50,13 @@ $dropdown-link-active-bg: $bgcolor-dropdown-link-active; @import './mixins/list-group'; - @import './reboot-bootstrap-text'; - @import './reboot-bootstrap-border-colors'; - @import './reboot-bootstrap-tables'; - @import './reboot-bootstrap-theme-colors'; - @import 'hsl-reboot-bootstrap-theme-colors'; - @import './reboot-bootstrap-dropdown'; + // TODO: activate (https://redmine.weseek.co.jp/issues/128307) + // @import './reboot-bootstrap-text'; + // @import './reboot-bootstrap-border-colors'; + // @import './reboot-bootstrap-tables'; + // @import './reboot-bootstrap-theme-colors'; + // @import 'hsl-reboot-bootstrap-theme-colors'; + // @import './reboot-bootstrap-dropdown'; // List Group @include override-list-group-item( @@ -117,7 +119,7 @@ background-color: rgba(white, 0.5); .link-switch { color: #1939b8; - @include hover() { + &:hover { color: lighten(#1939b8,20%); } } @@ -178,9 +180,9 @@ /* * GROWI subnavigation */ - .grw-subnav { - background-color: var(--bgcolor-subnav); - } + // .grw-subnav { + // background-color: var(--bgcolor-subnav); + // } .grw-subnav-fixed-container .grw-subnav { background-color: hsl.alpha(var(--bgcolor-subnav),85%); @@ -205,9 +207,9 @@ /** * GROWI PagePathHierarchicalLink */ - .grw-page-path-text-muted-container .grw-page-path-hierarchical-link a { - color: $gray-600; - } + // .grw-page-path-text-muted-container .grw-page-path-hierarchical-link a { + // color: $gray-600; + // } /* * GROWI Sidebar */ @@ -264,7 +266,7 @@ --gray-500-hs: 210,13%; --gray-500-l: 61%; @include hsl-button.button-outline-variant(var(--gray-500), var(--primary), #{hsl.lighten(var(--primary), 52%)}, transparent); - @include hover() { + &:hover { background-color: hsl.lighten(var(--primary), 58%); } &:not(:disabled):not(.disabled):active, @@ -356,7 +358,7 @@ * GROWI Editor */ .grw-editor-navbar-bottom { - background-color: $gray-50; + background-color: $gray-100; #slack-mark-white { display: none; @@ -401,7 +403,7 @@ background: white; } - .custom-control-label { + .form-check-label { &::before { background-color: $gray-200; border-color: transparent; @@ -411,7 +413,7 @@ background-image: url(/images/icons/slack/slack-logo-off.svg); } } - .custom-control-input:checked ~ .custom-control-label { + .form-check-input:checked ~ .form-check-label { &::before { background-color: lighten($color-slack, 60%); } diff --git a/apps/app/src/styles/theme/_reboot-toastr-colors.scss b/apps/app/_obsolete/src/styles/theme/_reboot-toastr-colors.scss similarity index 100% rename from apps/app/src/styles/theme/_reboot-toastr-colors.scss rename to apps/app/_obsolete/src/styles/theme/_reboot-toastr-colors.scss diff --git a/apps/app/src/styles/theme/apply-colors.scss b/apps/app/_obsolete/src/styles/theme/apply-colors.scss similarity index 89% rename from apps/app/src/styles/theme/apply-colors.scss rename to apps/app/_obsolete/src/styles/theme/apply-colors.scss index 73bb045bf67..81b29b9da13 100644 --- a/apps/app/src/styles/theme/apply-colors.scss +++ b/apps/app/_obsolete/src/styles/theme/apply-colors.scss @@ -1,5 +1,6 @@ +@use '@growi/core/scss/bootstrap/init' as *; + @use '../variables' as var; -@use '../bootstrap/init' as *; @use '../mixins'; @use '../atoms/mixins/code'; @use './mixins/hsl-button'; @@ -41,12 +42,13 @@ $nav-tabs-link-active-bg: var(--bgcolor-global); $nav-tabs-link-active-border-color: $bordercolor-nav-tabs-active; $theme-colors: map-merge($theme-colors, ( primary: $primary )); -@import 'reboot-bootstrap-buttons'; -@import 'reboot-bootstrap-colors'; -@import 'reboot-bootstrap-theme-colors'; -@import 'hsl-reboot-bootstrap-theme-colors'; -@import 'reboot-bootstrap-nav'; -@import 'reboot-toastr-colors'; +// TODO: activate (https://redmine.weseek.co.jp/issues/128307) +// @import 'reboot-bootstrap-buttons'; +// @import 'reboot-bootstrap-colors'; +// @import 'reboot-bootstrap-theme-colors'; +// @import 'hsl-reboot-bootstrap-theme-colors'; +// @import 'reboot-bootstrap-nav'; +// @import 'reboot-toastr-colors'; // determine variables with bootstrap function (These variables can be used after importing bootstrap above) $color-modal-header: var(--color-modal-header,#{hsl.contrast(var(--primary))}); @@ -63,15 +65,17 @@ code:not([class^='language-']) { //== Apply to Bootstrap Elements // +// TODO: activate (https://redmine.weseek.co.jp/issues/128307) +// theme-color-level() dropped in bootstrap v5 // Alert link -@each $color, $value in $theme-colors { - .alert.alert-#{$color} { - a, - a:hover { - color: theme-color-level($color, $alert-color-level - 2); - } - } -} +// @each $color, $value in $theme-colors { +// .alert.alert-#{$color} { +// a, +// a:hover { +// color: theme-color-level($color, $alert-color-level - 2); +// } +// } +// } // Dropdown .grw-apperance-mode-dropdown { @@ -86,10 +90,12 @@ code:not([class^='language-']) { } } +// TODO: activate (https://redmine.weseek.co.jp/issues/128307) +// form-control-focus() dropped in bootstrap v5 // Form -.form-control { - @include form-control-focus(); -} +// .form-control { +// @include form-control-focus(); +// } // Tabs .nav.nav-tabs .nav-link.active { @@ -200,29 +206,24 @@ ul.pagination { $bgcolor-resize-button: var(--bgcolor-resize-button,white); $color-resize-button-hover: var(--color-resize-button-hover,var(--color-reversal)); $bgcolor-resize-button-hover: var(--bgcolor-resize-button-hover,#{hsl.lighten(var(--bgcolor-resize-button), 5%)}); - .grw-navigation-resize-button { - .hexagon-container svg { - .background { - fill: var(--bgcolor-resize-button); - } - .icon { - fill: var(--color-resize-button); - } - } - &:hover .hexagon-container svg { - .background { - fill: var(--bgcolor-resize-button-hover); - } - .icon { - fill: var(--color-resize-button-hover); - } - } - } - div.grw-global-navigation { - > div { - background-color: var(--bgcolor-sidebar); - } - } + // .grw-navigation-resize-button { + // .hexagon-container svg { + // .background { + // fill: var(--bgcolor-resize-button); + // } + // .icon { + // fill: var(--color-resize-button); + // } + // } + // &:hover .hexagon-container svg { + // .background { + // fill: var(--bgcolor-resize-button-hover); + // } + // .icon { + // fill: var(--color-resize-button-hover); + // } + // } + // } div.grw-contextual-navigation { > div { color: var(--color-sidebar-context); @@ -256,24 +257,24 @@ ul.pagination { } .grw-recent-changes-resize-button { - .custom-control-label::before { + .form-check-label::before { background-color: var(--primary); } - .custom-control-label::after { + .form-check-label::after { background-color: var(--bgcolor-global); } - .custom-control-input:not(:checked) + .custom-control-label::before { + .form-check-input:not(:checked) + .form-check-label::before { color: var(--bgcolor-global); } - .custom-control-input:checked + .custom-control-label::before { + .form-check-input:checked + .form-check-label::before { color: var(--bgcolor-global); background-color: var(--primary); border-color: var(--primary); } - .custom-control-input:checked + .custom-control-label::after { + .form-check-input:checked + .form-check-label::after { color: var(--bgcolor-global); } } @@ -336,7 +337,7 @@ ul.pagination { .modal-title { color: $color-modal-header; } - .close { + .btn-close { color: $color-modal-header; opacity: 0.5; @@ -357,7 +358,7 @@ ul.pagination { .grw-page-accessories-modal,.grw-descendants-page-list-modal { .modal-header { - .close { + .btn-close { color: #{hsl.contrast(var(--bgcolor-global))}; } } @@ -394,19 +395,13 @@ ul.pagination { /* * cards */ -.card.well { +.card.custom-card { color: var(--color-global); background-color: var(--bgcolor-card); border-color: var(--light); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } -.admin-bot-card { - .grw-botcard-title-active { - color: $gray-200; - } -} - /* * Form Slider */ @@ -481,7 +476,7 @@ ul.pagination { fill: var(--color-global); } - @include hover() { + &:hover { svg { fill: var(--color-global); } @@ -661,18 +656,6 @@ mark.rbt-highlight-text { background-color: var(--bgcolor-global); } -.grw-fab { - .btn-create-page { - svg { - fill: hsl.contrast(var(--primary)); - } - } - - .btn-scroll-to-top { - fill: $gray-900; - } -} - /* Slack Integration */ diff --git a/apps/app/bin/cdn/cdn-resources-downloader.ts b/apps/app/bin/cdn/cdn-resources-downloader.ts deleted file mode 100644 index 7135601157f..00000000000 --- a/apps/app/bin/cdn/cdn-resources-downloader.ts +++ /dev/null @@ -1,159 +0,0 @@ -import path from 'path'; -import { URL } from 'url'; -import urljoin from 'url-join'; -import { Transform } from 'stream'; -import replaceStream from 'replacestream'; - -import { cdnLocalScriptRoot, cdnLocalStyleRoot, cdnLocalStyleWebRoot } from '^/config/cdn'; -import * as cdnManifests from '^/resource/cdn-manifests'; - -import { CdnResource, CdnManifest } from '~/interfaces/cdn'; -import loggerFactory from '~/utils/logger'; -import { downloadTo } from '~/utils/download'; - -const logger = loggerFactory('growi:service:CdnResourcesDownloader'); - -export default class CdnResourcesDownloader { - - async downloadAndWriteAll(): Promise { - const cdnScriptResources: CdnResource[] = cdnManifests.js.map((manifest: CdnManifest) => { - return { manifest, outDir: cdnLocalScriptRoot }; - }); - - const cdnStyleResources: CdnResource[] = cdnManifests.style.map((manifest) => { - return { manifest, outDir: cdnLocalStyleRoot }; - }); - - const dlStylesOptions = { - replaceUrl: { - webroot: cdnLocalStyleWebRoot, - }, - }; - - return Promise.all([ - this.downloadScripts(cdnScriptResources), - this.downloadStyles(cdnStyleResources, dlStylesOptions), - ]); - } - - /** - * Download script files from CDN - * @param cdnResources JavaScript resource data - * @param options - */ - private async downloadScripts(cdnResources: CdnResource[], options?: any): Promise { - logger.debug('Downloading scripts', cdnResources); - - const opts = Object.assign({}, options); - const ext = opts.ext || 'js'; - - const promises = cdnResources.map((cdnResource) => { - const { manifest } = cdnResource; - - logger.info(`Processing CdnResource '${manifest.name}'`); - - return downloadTo( - manifest.url, - cdnResource.outDir, - `${manifest.name}.${ext}`, - ); - }); - - return Promise.all(promises); - } - - /** - * Download style sheet file from CDN - * Assets in CSS is also downloaded - * @param cdnResources CSS resource data - * @param options - */ - private async downloadStyles(cdnResources: CdnResource[], options?: any): Promise { - logger.debug('Downloading styles', cdnResources); - - const opts = Object.assign({}, options); - const ext = opts.ext || 'css'; - - // styles - const assetsResourcesStore: CdnResource[] = []; - const promisesForStyle = cdnResources.map((cdnResource) => { - const { manifest } = cdnResource; - - logger.info(`Processing CdnResource '${manifest.name}'`); - - let urlReplacer: Transform|null = null; - - // generate replaceStream instance - if (opts.replaceUrl != null) { - urlReplacer = this.generateReplaceUrlInCssStream(cdnResource, assetsResourcesStore, opts.replaceUrl.webroot); - } - - return downloadTo( - manifest.url, - cdnResource.outDir, - `${manifest.name}.${ext}`, - urlReplacer, - ); - }); - - // wait until all styles are downloaded - await Promise.all(promisesForStyle); - - logger.debug('Downloading assets', assetsResourcesStore); - - // assets in css - const promisesForAssets = assetsResourcesStore.map((cdnResource) => { - const { manifest } = cdnResource; - - logger.info(`Processing assts in css '${manifest.name}'`); - - return downloadTo( - manifest.url, - cdnResource.outDir, - manifest.name, - ); - }); - - return Promise.all(promisesForAssets); - } - - /** - * Generate replaceStream instance to replace 'url(..)' - * - * e.g. - * Before : url(../images/logo.svg) - * After : url(/path/to/webroot/${cdnResources.name}/logo.svg) - * - * @param cdnResource CSS resource data - * @param assetsResourcesStore An array to store CdnResource that is detected by 'url()' in CSS - * @param webroot - */ - private generateReplaceUrlInCssStream(cdnResource: CdnResource, assetsResourcesStore: CdnResource[], webroot: string): Transform { - return replaceStream( - /url\((?!['"]?data:)["']?(.+?)["']?\)/g, // https://regex101.com/r/Sds38A/3 - (match, url) => { - // generate URL Object - const parsedUrl = url.startsWith('http') - ? new URL(url) // when url is fqcn - : new URL(url, cdnResource.manifest.url); // when url is relative - const basename = path.basename(parsedUrl.pathname); - - logger.debug(`${cdnResource.manifest.name} has ${parsedUrl.toString()}`); - - // add assets metadata to download later - const replacedCdnResource = { - manifest: { - name: basename, - url: parsedUrl.toString(), - }, - outDir: path.join(cdnResource.outDir, cdnResource.manifest.name), - }; - assetsResourcesStore.push(replacedCdnResource); - - const replaceUrl = urljoin(webroot, cdnResource.manifest.name, basename); - return `url(${replaceUrl})`; - }, - ); - } - -} diff --git a/apps/app/bin/download-cdn-resources.ts b/apps/app/bin/download-cdn-resources.ts deleted file mode 100644 index 216149ef660..00000000000 --- a/apps/app/bin/download-cdn-resources.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * the tool for download CDN resources and save as file - * - * @author Yuki Takei - */ -import { envUtils } from '@growi/core/dist/utils'; - -import loggerFactory from '../src/utils/logger'; - -import CdnResourcesDownloader from './cdn/cdn-resources-downloader'; - -const logger = loggerFactory('growi:bin:download-cdn-resources'); - -// check env var -const noCdn: boolean = envUtils.toBoolean(process.env.NO_CDN); -if (!noCdn) { - logger.info('Using CDN. No resources are downloaded.'); - // exit - process.exit(0); -} - -logger.info('This is NO_CDN mode. Start to download resources.'); - - -const downloader = new CdnResourcesDownloader(); - -downloader.downloadAndWriteAll() - .then(() => { - logger.info('Download is completed successfully'); - }) - .catch((err) => { - logger.error(err); - }); diff --git a/apps/app/bin/github-actions/update-readme.sh b/apps/app/bin/github-actions/update-readme.sh index 9d29dc28532..29ef8885185 100644 --- a/apps/app/bin/github-actions/update-readme.sh +++ b/apps/app/bin/github-actions/update-readme.sh @@ -2,4 +2,4 @@ cd docker -sed -i -e "s/^\([*] \[\`\)[^\`]\+\(\`, \`6\.2\`, .\+\]\)\(.\+\/blob\/v\).\+\(\/apps\/app\/docker\/Dockerfile.\+\)$/\1${RELEASED_VERSION}\2\3${RELEASED_VERSION}\4/" README.md +sed -i -e "s/^\([*] \[\`\)[^\`]\+\(\`, \`7\.0\`, .\+\]\)\(.\+\/blob\/v\).\+\(\/apps\/app\/docker\/Dockerfile.\+\)$/\1${RELEASED_VERSION}\2\3${RELEASED_VERSION}\4/" README.md diff --git a/apps/app/config/logger/config.dev.js b/apps/app/config/logger/config.dev.js index fdda451ac0f..db513fd167f 100644 --- a/apps/app/config/logger/config.dev.js +++ b/apps/app/config/logger/config.dev.js @@ -25,7 +25,6 @@ module.exports = { // 'growi:lib:importer': 'debug', // 'growi:routes:page': 'debug', 'growi-plugin:*': 'debug', - // 'growi:InterceptorManager': 'debug', 'growi:service:search-delegator:elasticsearch': 'debug', 'growi:service:g2g-transfer': 'debug', 'growi:service:questionnaire': 'debug', diff --git a/apps/app/config/next-i18next.config.js b/apps/app/config/next-i18next.config.js index 28569b75f08..eef6aac4941 100644 --- a/apps/app/config/next-i18next.config.js +++ b/apps/app/config/next-i18next.config.js @@ -1,12 +1,14 @@ +const isDev = process.env.NODE_ENV === 'development'; + const path = require('path'); const { AllLang, Lang } = require('@growi/core'); const { isServer } = require('@growi/core/dist/utils'); -const I18nextChainedBackend = require('i18next-chained-backend').default; -const I18NextHttpBackend = require('i18next-http-backend'); +const I18nextChainedBackend = isDev ? require('i18next-chained-backend').default : undefined; +const I18NextHttpBackend = require('i18next-http-backend').default; const I18NextLocalStorageBackend = require('i18next-localstorage-backend').default; -const isDev = process.env.NODE_ENV === 'development'; +const HMRPlugin = isDev ? require('i18next-hmr/plugin').HMRPlugin : undefined; module.exports = { defaultLang: Lang.en_US, @@ -17,7 +19,12 @@ module.exports = { defaultNS: 'translation', localePath: path.resolve('./public/static/locales'), serializeConfig: false, - use: isServer() ? [] : [I18nextChainedBackend], + // eslint-disable-next-line no-nested-ternary + use: isDev + ? isServer() + ? [new HMRPlugin({ webpack: { server: true } })] + : [I18nextChainedBackend, new HMRPlugin({ webpack: { client: true } })] + : [], backend: { backends: isServer() ? [] : [I18NextLocalStorageBackend, I18NextHttpBackend], backendOptions: [ diff --git a/apps/app/docker/Dockerfile b/apps/app/docker/Dockerfile index bbbbd661313..c320e470cb1 100644 --- a/apps/app/docker/Dockerfile +++ b/apps/app/docker/Dockerfile @@ -4,7 +4,7 @@ ## ## base ## -FROM node:18-slim AS base +FROM node:20-slim AS base ENV optDir /opt @@ -18,7 +18,7 @@ RUN turbo prune --scope=@growi/app --docker ## ## deps-resolver ## -FROM node:18-slim AS deps-resolver +FROM node:20-slim AS deps-resolver ENV optDir /opt @@ -62,7 +62,7 @@ RUN tar -cf node_modules.tar \ ## ## builder ## -FROM node:18-slim AS builder +FROM node:20-slim AS builder ENV optDir /opt @@ -107,7 +107,7 @@ RUN tar -cf packages.tar \ ## ## release ## -FROM node:18-slim +FROM node:20-slim LABEL maintainer Yuki Takei ENV NODE_ENV production diff --git a/apps/app/docker/README.md b/apps/app/docker/README.md index 4a3d57c3ad2..e2179fc822b 100644 --- a/apps/app/docker/README.md +++ b/apps/app/docker/README.md @@ -10,8 +10,10 @@ GROWI Official docker image Supported tags and respective Dockerfile links ------------------------------------------------ -* [`6.3.0`, `6.3`, `6`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v6.3.0/apps/app/docker/Dockerfile) +* [`7.0.0`, `7.0`, `7`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v7.0.0/apps/app/docker/Dockerfile) +* [`6.3.2`, `6.3`, `6` (Dockerfile)](https://github.com/weseek/growi/blob/v6.3.2/apps/app/docker/Dockerfile) * [`6.2.4`, `6.2` (Dockerfile)](https://github.com/weseek/growi/blob/v6.2.4/apps/app/docker/Dockerfile) +* [`6.1.15`, `6.1` (Dockerfile)](https://github.com/weseek/growi/blob/v6.1.15/apps/app/docker/Dockerfile) What is GROWI? diff --git a/apps/app/next.config.js b/apps/app/next.config.js index 7c437f2742a..7af86af3c14 100644 --- a/apps/app/next.config.js +++ b/apps/app/next.config.js @@ -120,7 +120,7 @@ module.exports = async(phase, { defaultConfig }) => { // setup i18next-hmr if (!options.isServer && options.dev) { - const { I18NextHMRPlugin } = require('i18next-hmr/plugin'); + const { I18NextHMRPlugin } = require('i18next-hmr/webpack'); config.plugins.push(new I18NextHMRPlugin({ localesDir: localePath })); } diff --git a/apps/app/package.json b/apps/app/package.json index 74003f2a9ef..48c3423b3aa 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -1,6 +1,6 @@ { "name": "@growi/app", - "version": "6.3.2", + "version": "7.0.0-RC.0", "license": "MIT", "scripts": { "//// for production": "", @@ -55,14 +55,15 @@ "@aws-skd/*": "fix version above 3.186.0 that is required by mongodb@4.16.0", "@keycloak/keycloak-admin-client": "19.0.0 or above exports only ESM.", "escape-string-regexp": "5.0.0 or above exports only ESM", - "string-width": "5.0.0 or above exports only ESM.", - "remark-wiki-link": "!!DO NOT REMOVE!! including 'mdast-util-wiki-link' and 'micromark-extension-wiki-link' required by pukiwiki-like-linker" + "next-themes": "0.3.0 causes a type error: https://github.com/pacocoursey/next-themes/issues/122", + "remark-wiki-link": "!!DO NOT REMOVE!! including 'mdast-util-wiki-link' and 'micromark-extension-wiki-link' required by pukiwiki-like-linker", + "string-width": "5.0.0 or above exports only ESM." }, "dependencies": { "@akebifiky/remark-simple-plantuml": "^1.0.2", "@aws-sdk/client-s3": "3.454.0", "@aws-sdk/s3-request-presigner": "3.454.0", - "@azure/identity": "^3.3.2", + "@azure/identity": "^4.0.1", "@azure/storage-blob": "^12.16.0", "@browser-bunyan/console-formatted-stream": "^1.8.0", "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0", @@ -70,7 +71,7 @@ "@godaddy/terminus": "^4.9.0", "@google-cloud/storage": "^5.8.5", "@growi/core": "link:../../packages/core", - "@growi/hackmd": "link:../../packages/hackmd", + "@growi/custom-icons": "link:../../packages/custom-icons", "@growi/pluginkit": "link:../../packages/pluginkit", "@growi/preset-templates": "link:../../packages/preset-templates", "@growi/preset-themes": "link:../../packages/preset-themes", @@ -101,7 +102,7 @@ "connect-redis": "^4.0.4", "cookie-parser": "^1.4.5", "csurf": "^1.11.0", - "csv-to-markdown-table": "^1.1.0", + "csv-to-markdown-table": "^1.4.1", "date-fns": "^2.23.0", "dayjs": "^1.11.7", "detect-indent": "^7.0.0", @@ -123,15 +124,15 @@ "hast-util-select": "^5.0.5", "helmet": "^4.6.0", "http-errors": "^2.0.0", - "i18next": "^22.4.10", - "i18next-chained-backend": "^4.0.0", - "i18next-http-backend": "^2.0.0", - "i18next-localstorage-backend": "^4.0.0", + "i18next": "^23.10.1", + "i18next-chained-backend": "^4.6.2", + "i18next-http-backend": "^2.5.0", + "i18next-localstorage-backend": "^4.2.0", "is-absolute-url": "^4.0.1", "is-iso-date": "^0.0.1", "ldapjs": "^3.0.2", "lucene-query-parser": "^1.2.0", - "markdown-table": "^1.1.1", + "markdown-table": "^3.0.3", "md5": "^2.2.1", "mermaid": "^10.1.0", "method-override": "^3.0.0", @@ -144,8 +145,8 @@ "multer": "~1.4.0", "multer-autoreap": "^1.0.3", "mustache": "^4.2.0", - "next": "^13.3.0", - "next-i18next": "^13.2.1", + "next": "^14.1.3", + "next-i18next": "^15.2.0", "next-superjson": "^0.0.4", "next-themes": "^0.2.1", "nocache": "^3.0.1", @@ -163,7 +164,7 @@ "qs": "^6.11.1", "rate-limiter-flexible": "^2.3.7", "react": "^18.2.0", - "react-bootstrap-typeahead": "^5.2.2", + "react-bootstrap-typeahead": "^6.3.2", "react-card-flip": "^1.0.10", "react-datepicker": "^4.7.0", "react-disable": "^0.1.1", @@ -171,15 +172,16 @@ "react-dnd-html5-backend": "^14.1.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", - "react-i18next": "^12.2.0", + "react-i18next": "^14.1.0", "react-image-crop": "^8.3.0", "react-markdown": "^8.0.7", "react-multiline-clamp": "^2.0.0", "react-scroll": "^1.8.7", + "react-stickynode": "^4.1.0", "react-syntax-highlighter": "^15.5.0", - "react-toastify": "^9.1.1", + "react-toastify": "^9.1.3", "react-use-ripple": "^1.5.2", - "reactstrap": "^8.10.1", + "reactstrap": "^9.2.0", "reconnecting-websocket": "^4.4.0", "redis": "^3.0.2", "rehype-katex": "^6.0.2", @@ -195,12 +197,12 @@ "remark-toc": "^8.0.1", "remark-wiki-link": "^1.0.4", "sanitize-filename": "^1.6.3", - "socket.io": "^4.2.0", + "socket.io": "^4.7.2", "stream-to-promise": "^3.0.0", "string-width": "=4.2.2", "superjson": "^1.9.1", "swagger-jsdoc": "^6.1.0", - "swr": "^2.0.3", + "swr": "^2.2.2", "throttle-debounce": "^5.0.0", "uglifycss": "^0.0.29", "universal-bunyan": "^0.9.2", @@ -210,18 +212,21 @@ "usehooks-ts": "^2.6.0", "validator": "^13.7.0", "ws": "^8.3.0", - "xss": "^1.0.14" + "xss": "^1.0.14", + "y-mongodb-provider": "^0.1.7", + "y-socket.io": "^1.1.0", + "yjs": "^13.6.12" }, "// comments for defDependencies": { "@handsontable/react": "v3 requires handsontable >= 7.0.0.", "handsontable": "v7.0.0 or above is no loger MIT lisence." }, "devDependencies": { + "@growi/editor": "link:../../packages/editor", "@growi/presentation": "link:../../packages/presentation", "@growi/ui": "link:../../packages/ui", "@handsontable/react": "=2.1.0", - "@icon/themify-icons": "1.0.1-alpha.3", - "@next/bundle-analyzer": "^13.2.3", + "@next/bundle-analyzer": "^14.1.3", "@swc-node/jest": "^1.6.2", "@swc/jest": "^0.2.24", "@testing-library/react": "^14.1.2", @@ -229,47 +234,44 @@ "@types/express": "^4.17.11", "@types/jest": "^29.5.2", "@types/react-scroll": "^1.8.4", + "@types/throttle-debounce": "^5.0.1", "@types/unzip-stream": "^0.3.4", + "@types/url-join": "^4.0.2", "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^0.34.6", "autoprefixer": "^9.0.0", "babel-loader": "^8.2.5", - "bootstrap": "^4.6.1", - "codemirror": "^5.64.0", + "bootstrap": "^5.3.1", "connect-browser-sync": "^2.1.0", "diff2html": "^3.4.35", + "downshift": "^8.2.3", "eazy-logger": "^3.1.0", - "emoji-mart": "npm:panta82-emoji-mart@^3.0.1", "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-jest": "^26.5.3", "eslint-plugin-regex": "^1.8.0", - "font-awesome": "^4.7.0", "fslightbox-react": "^1.7.6", "handsontable": "=6.2.2", "happy-dom": "^13.2.0", - "i18next-hmr": "^1.11.0", + "i18next-hmr": "^3.0.4", "jest": "^29.5.0", "jest-date-mock": "^1.0.8", "jest-localstorage-mock": "^2.4.14", - "jquery": "^3.7.0", "load-css-file": "^1.0.0", "material-icons": "^1.11.3", "mongodb-memory-server-core": "^9.1.1", "morgan": "^1.10.0", "null-loader": "^4.0.1", - "penpal": "^4.0.0", "plantuml-encoder": "^1.2.5", - "popper.js": "^1.16.1", "prettier": "^1.19.1", "pretty-bytes": "^6.1.1", "react-codemirror2": "^6.0.0", "react-copy-to-clipboard": "^5.0.1", - "react-dropzone": "^11.2.4", + "react-dropzone": "^14.2.3", "react-hotkeys": "^2.0.0", + "react-input-autosize": "^3.0.0", "rehype-rewrite": "^3.0.6", "replacestream": "^4.0.3", "sass": "^1.53.0", - "simple-line-icons": "^2.5.5", "simple-load-script": "^1.0.2", "simplebar-react": "^2.3.6", "socket.io-client": "^4.2.0", diff --git a/apps/app/public/images/icons/slack/slack-logo-background.svg b/apps/app/public/images/icons/slack/slack-logo-background.svg new file mode 100644 index 00000000000..2c084ab50ec --- /dev/null +++ b/apps/app/public/images/icons/slack/slack-logo-background.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/public/images/icons/slack/slack-logo-dark-background.svg b/apps/app/public/images/icons/slack/slack-logo-dark-background.svg new file mode 100644 index 00000000000..64969bd7c2f --- /dev/null +++ b/apps/app/public/images/icons/slack/slack-logo-dark-background.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/public/images/icons/sublime.png b/apps/app/public/images/icons/sublime.png deleted file mode 100644 index 55503dfe580..00000000000 Binary files a/apps/app/public/images/icons/sublime.png and /dev/null differ diff --git a/apps/app/public/images/icons/vscode.png b/apps/app/public/images/icons/vscode.png new file mode 100644 index 00000000000..5d099233574 Binary files /dev/null and b/apps/app/public/images/icons/vscode.png differ diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index b28746c04d1..09433239904 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -38,10 +38,12 @@ "page_delete": "Page Delete", "page_delete_completely": "Page Delete Completely", "other_options": "Other options", - "deletion_explain": "Restricts users who can trash the selected single page.", - "complete_deletion_explain": "Restricts users who can completely delete selected single page.", - "recursive_deletion_explain": "Restricts users who can trash pages including descendants.", - "recursive_complete_deletion_explain": "Restricts users who can completely delete pages including descendants.", + "deletion_explanation": "Restricts users who can trash the selected single page.", + "complete_deletion_explanation": "Restricts users who can completely delete selected single page.", + "recursive_deletion_explanation": "Restricts users who can trash pages including descendants.", + "recursive_complete_deletion_explanation": "Restricts users who can completely delete pages including descendants.", + "is_all_group_membership_required_for_page_complete_deletion": "Users other than admin and page author are required to belong to all groups that are granted page access", + "is_all_group_membership_required_for_page_complete_deletion_explanation": "Effective when page access settings is set to \"Only specific groups\".", "inherit": "Inherit(Use the same setting as for a single page)", "admin_only": "Admin only", "admin_and_author": "Admin and author", @@ -496,8 +498,8 @@ "enable_marp_desc": "Marp can be used in presentation preview. This option may make you vulnerable to XSS.", "marp_official_site": "The Marp Official Site", "marp_official_site_link": "https://marp.app", - "presentation_docs" : "GROWI Docs - Create slides for a presentation", - "presentation_docs_link": "https://docs.growi.org/en/guide/features/presentation.html" + "marp_in_growi" : "GROWI Docs - Create slide using Marp", + "marp_in_growi_link": "https://docs.growi.org/en/guide/features/marp.html" }, "custom_title": "Custom title", "custom_title_detail": "You can customize <title> tag. Following placeholders will be automatically replaced:", @@ -565,10 +567,6 @@ "initialize_meta_datas": { "label": "Initialize page's like, read users and comment count", "desc": "Recommended NOT to check this when users will also be restored." - }, - "initialize_hackmd_related_datas": { - "label": "Initialize HackMD related data", - "desc": "Recommended to check this unless there is important drafts on HackMD." } }, "revisions": { @@ -748,7 +746,7 @@ "description1":"Temporarily issue new users by email addresses.", "description2":"A temporary password will be generated for the first login.", "invite_thru_email": "Send invitation email", - "mail_setting_link":"Email settings", + "mail_setting_link":"settingsEmail settings", "valid_email": "Valid email address is required", "temporary_password": "The created user has a temporary password", "send_new_password": "Please send the new password to the user.", @@ -836,9 +834,10 @@ "dropdown_desc": "Choose an action for private pages", "select_group": "Select a group", "no_groups": "No groups to select", - "publish_pages": "Publish all", + "publish_pages": "Publish pages that are publishable", "delete_pages": "Delete all", - "transfer_pages": "Transfer to another group" + "transfer_pages": "Transfer to another group", + "option_explanation": "A \"publishable\" page is a page visible only to the group you want to delete. Pages that can be viewed by other groups will not be published." }, "update_parent_confirm_modal": { "header": "The parent of the group will be changed", @@ -861,12 +860,12 @@ "return": "Return", "clear": "Clear", "activity_expiration_date": "Audit Log expiration date", - "activity_expiration_date_explain": "Created Audit Log are automatically deleted after the number of seconds set in the environment variable from the creation time", + "activity_expiration_date_explanation": "Created Audit Log are automatically deleted after the number of seconds set in the environment variable from the creation time", "fixed_by_env_var": "This is fixed by the env var {{key}}={{value}}.", "available_action_list": "Search / View All Available Actions", - "available_action_list_explain": "List of actions that can be searched/viewed in the current settings", + "available_action_list_explanation": "List of actions that can be searched/viewed in the current settings", "action_list": "Action List", - "disable_mode_explain": "Audit log is currently disabled. To enable it, set the environment variable AUDIT_LOG_ENABLED to true.", + "disable_mode_explanation": "Audit log is currently disabled. To enable it, set the environment variable AUDIT_LOG_ENABLED to true.", "docs_url": { "log_type": "https://docs.growi.org/en/admin-guide/admin-cookbook/audit-log-setup.html#log-types" } diff --git a/apps/app/public/static/locales/en_US/commons.json b/apps/app/public/static/locales/en_US/commons.json index dedbf2806b5..0ccb247d48b 100644 --- a/apps/app/public/static/locales/en_US/commons.json +++ b/apps/app/public/static/locales/en_US/commons.json @@ -42,6 +42,12 @@ } }, + "search_method_menu_item": { + "search_in_all": "Search in all", + "only_children_of_this_tree": "Only children of this tree", + "exact_mutch": "Exact match" + }, + "share_links": { "Share Link": "Share Link", "Page Path": "Page Path", @@ -68,6 +74,19 @@ "feedback": "Feedback" }, + "create_page_dropdown": { + "new_page": "Create New Page", + "todays": { + "desc": "Create today's memo", + "memo": "memo" + }, + "template": { + "desc": "Create/Edit template page", + "children": "Template for children", + "descendants": "Template for descendants" + } + }, + "copy_to_clipboard": { "Copy to clipboard": "Copy to clipboard", "Page path": "Page path", diff --git a/apps/app/public/static/locales/en_US/translation.json b/apps/app/public/static/locales/en_US/translation.json index c458be9a292..cb26c2946f6 100644 --- a/apps/app/public/static/locales/en_US/translation.json +++ b/apps/app/public/static/locales/en_US/translation.json @@ -10,12 +10,12 @@ "Duplicate": "Duplicate", "PathRecovery": "Path recovery", "Copy": "Copy", - "preview":"Preview", - "desktop":"Desktop", - "phone":"Smartphone", - "tablet":"Tablet", + "preview": "Preview", + "desktop": "Desktop", + "phone": "Smartphone", + "tablet": "Tablet", "Click to copy": "Click to copy", - "Rename" : "Rename", + "Rename": "Rename", "Move/Rename": "Move/Rename", "Redirected": "Redirected", "Unlinked": "Unlinked", @@ -44,9 +44,11 @@ "Error": "Error", "Warning": "Warning", "Sign in": "Sign in", + "Sign in with External auth": "Sign in with {{signin}}", "Sign up is here": "Sign up", "Sign in is here": "Sign in", "Sign up": "Sign up", + "or": "or", "Sign up with Google Account": "Sign up with Google Account", "Sign in with Google Account": "Sign in with Google Account", "Sign up with this Google Account": "Sign up with this Google Account", @@ -106,15 +108,14 @@ "Disclose E-mail": "Disclose E-mail", "page exists": "this page already exists", "Error occurred": "Error occurred", - "Create today's": "Create today's ...", - "Memo": "memo", "Input page name": "Input page name", "Input page name (optional)": "Input page name (optional)", + "Input parent page path": "Input parent page path", "New Page": "New page", "Create under": "Create page under below:", "V5 Page Migration": "Convert To V5 Compatibility", "GROWI.5.0_new_schema": "GROWI.5.0 new schema", - "See_more_detail_on_new_schema": "See more detail on {{title}} ", + "See_more_detail_on_new_schema": "See more detail on {{title}} external_link ", "external_account_management": "External Account Management", "UserGroup": "UserGroup", "Basic Settings": "Basic Settings", @@ -146,9 +147,10 @@ "wide_view": "Wide View", "Recent Changes": "Recent Changes", "Page Tree": "Page Tree", - "original_path":"Original path", - "new_path":"New path", - "duplicated_path":"Duplicated path", + "In-App Notification": "Notifications", + "original_path": "Original path", + "new_path": "New path", + "duplicated_path": "Duplicated path", "Link sharing is disabled": "Link sharing is disabled", "successfully_saved_the_page": "Successfully saved the page", "you_can_not_create_page_with_this_name": "You can not create page with this name", @@ -214,10 +216,10 @@ "Password": "Password", "Password Settings": "Password settings", "personal_settings": { - "disassociate_external_account": "Disassociate External Account", - "disassociate_external_account_desc": "Are you sure to disassociate the {{providerType}} account {{accountId}}?", - "set_new_password": "Set new Password", - "update_password": "Update password", + "disassociate_external_account": "Disassociate External Account", + "disassociate_external_account_desc": "Are you sure to disassociate the {{providerType}} account {{accountId}}?", + "set_new_password": "Set new Password", + "update_password": "Update password", "current_password": "Current password", "new_password": "New password", "new_password_confirm": "Re-enter new password", @@ -227,7 +229,7 @@ "Shere this page link to public": "Shere this page link to public", "share_link_list": "Share link list", "share_link_management": "Share Link Management", - "delete_all_share_links":"Delete all share links", + "delete_all_share_links": "Delete all share links", "expire": "Expiration", "Days": "Days", "Custom": "Custom", @@ -235,8 +237,8 @@ "enter_desc": "Enter description", "Unlimited": "unlimited", "Issue": "Issue", - "share_settings" :"Share settings", - "Invalid_Number_of_Date" : "You entered invalid value", + "share_settings": "Share settings", + "Invalid_Number_of_Date": "You entered invalid value", "link_sharing_is_disabled": "Link sharing is disabled" }, "API Settings": "API settings", @@ -251,6 +253,21 @@ "page_create": "Subscribe to the page when you create it." } }, + "ui_settings": { + "ui_settings": "UI Settings", + "side_bar_mode": { + "settings": "Sidebar mode settings", + "side_bar_mode_setting": "Set the sidebar mode", + "description": "You can set whether or not the sidebar will always be open when the screen width is large. If the screen width is small, the sidebar will always be closed." + } + }, + "color_mode_settings": { + "light": "Light", + "dark": "Dark", + "system": "System", + "settings": "Color mode settings", + "description": "Select whether to display in light mode, dark mode, or a system-specific display.
Only supported themes can be switched." + }, "editor_settings": { "editor_settings": "Editor Settings" }, @@ -293,10 +310,15 @@ "stale": "More than {{count}} year has passed since last update.", "stale_plural": "More than {{count}} years has passed since last update.", "expiration": "This share link will expire at {{expiredAt}}.", - "no_deadline":"This page has no expiration date" + "no_deadline": "This page has no expiration date" } }, "page_edit": { + "input_channels": "Slack channel name...", + "theme": "Theme", + "keymap": "Keymap", + "indent": "Indent", + "editor_config": "Editor Config", "Show active line": "Show active line", "auto_format_table": "Auto format table", "overwrite_scopes": "{{operation}} and Overwrite scopes of all descendants", @@ -314,7 +336,8 @@ "already_exists": "Page with the path already exists.", "outdated": "Page is updated someone and now outdated.", "user_not_admin": "Only admin user can delete", - "single_deletion_empty_pages": "Empty pages cannot be single deleted" + "single_deletion_empty_pages": "Empty pages cannot be single deleted", + "complete_deletion_not_allowed_for_user": "You are not allowed to delete this page completely" }, "page_history": { "revision_list": "Revision list", @@ -322,8 +345,8 @@ "comparing_source": "Source", "comparing_target": "Target", "comparing_revisions": "Comparing the difference", - "compare_latest":"Compare latest revision", - "compare_previous":"Compare previous revision" + "compare_latest": "Compare latest revision", + "compare_previous": "Compare previous revision" }, "modal_rename": { "label": { @@ -361,7 +384,7 @@ "deleted_pages_completely": "{{path}} has been deleted completely", "renamed_pages": "{{path}} has been renamed", "empty_trash": "The trash has been emptied", - "modal_empty":{ + "modal_empty": { "empty_the_trash": "Empty The Trash", "empty_the_trash_button": "Empty The Trash", "not_deletable_notice": "Some pages cannot be removed due to lack of permission.", @@ -375,10 +398,12 @@ "Current page name": "Current page name", "Recursively": "Recursively", "Duplicate without exist path": "Duplicate without exist path", - "Same page already exists": "Same page already exists" + "Same page already exists": "Same page already exists", + "Only duplicate user related pages": "Only duplicate pages you can access" }, "help": { - "recursive": "Duplicate children of under this path recursively" + "recursive": "Duplicate children of under this path recursively", + "only_inherit_user_related_groups": "If the page privilege is set to \"Only inside the group\", groups you do not belong to will lose access to the duplicated page" } }, "duplicated_pages": "{{fromPath}} has been duplicated", @@ -416,13 +441,13 @@ } }, "modal_resolve_conflict": { + "conflicts_with_new_body_on_server_side": "Conflict with new body on server side. Please select or edit the page body to resolve the conflict.", "file_conflicting_with_newer_remote": "This file is conflicting with newer remote file", "resolve_conflict_message": "Please select page body", "resolve_conflict": "Resolve Conflict", - "resolve_and_save" : "Resolve and save", - "select_revision" : "Select {{revision}}", + "resolve_and_save": "Resolve and save", + "select_revision": "Select {{revision}}", "requested_revision": "mine", - "origin_revision": "origin", "latest_revision": "theirs", "selected_editable_revision": "Selected Page Body (Editable)" }, @@ -449,7 +474,7 @@ "issue_share_link": "Succeeded to issue new share link", "remove_share_link": "Succeeded to remove {{count}} share links", "switch_disable_link_sharing_success": "Succeeded to update share link setting", - "failed_to_reset_password":"Failed to reset password", + "failed_to_reset_password": "Failed to reset password", "save_succeeded": "Saved successfully" }, "template": { @@ -466,7 +491,7 @@ "label": "Template for children", "desc": "Applies only to the same level pages which the template exists" }, - "decendants": { + "descendants": { "label": "Template for descendants", "desc": "Applies to all decendant pages" } @@ -502,27 +527,6 @@ "insert_image": "inserts an image", "open_sandbox": "Open Sandbox" }, - "hackmd": { - "hack_md": "HackMD", - "not_set_up": "HackMD is not set up.", - "used_for_not_found": "Can not use HackMD to a page that does not exist.", - "start_to_edit": "Start to edit with HackMD", - "clone_page_content": "Click to clone page content and start to edit.", - "unsaved_draft": "HackMD has unsaved draft.", - "draft_outdated": "DRAFT MAY BE OUTDATED", - "based_on_revision": "The current draft on HackMD is based on", - "view_outdated_draft": "View the outdated draft on HackMD", - "resume_to_edit": "Resume to edit with HackMD", - "discard_changes": "Discard changes of HackMD", - "integration_failed": "HackMD Integration failed", - "fail_to_connect": "GROWI client failed to connect to GROWI agent for HackMD.", - "check_configuration": "Check your configuration following the manual.", - "not_initialized": "HackmdEditor component has not initialized", - "someone_editing": "Someone editing this page on HackMD", - "this_page_has_draft": "This page has a draft on HackMD", - "need_to_associate_with_growi_to_use_hackmd_refer_to_this": "To use HackMD for simultaneous multi-person editing, need to associate HackMD with GROWI.Please refer to here.", - "need_to_make_page": "To use HackMD, please make a new page from the built-in editor." - }, "slack_notification": { "popover_title": "Slack Notification", "popover_desc": "Input channel name. You can notify multiple channels by entering a comma-separated list." @@ -536,12 +540,13 @@ "check_all": "Check all", "deletion_modal_header": "Delete page", "delete_completely": "Delete completely", - "include_certain_path" : "Include {{pathToInclude}} path ", - "delete_all_selected_page" : "Delete All", - "currently_not_implemented":"This is not currently implemented", - "search_again" : "Search again", - "number_of_list_to_display" : "Display", - "page_number_unit" : "pages", + "include_certain_path": "Include {{pathToInclude}} path ", + "delete_all_selected_page": "Delete All", + "currently_not_implemented": "This is not currently implemented", + "search_again": "Search again", + "number_of_list_to_display": "Display", + "page_number_unit": "pages", + "hit_number_unit": "hit", "sort_axis": { "relationScore": "Sort by relevance", "createdAt": "Creation date", @@ -557,7 +562,7 @@ "alert_desc1": "On this page, you can select pages with the checkbox and batch convert to the new v5 compatible format from the \"Bulk operation\" button at the top of the screen.", "nopages_title": "Congratulations. Ready to use GROWI v5!", "nopages_desc1": "Now all the pages you can manage seem to be in v5 compatible format.", - "detail_info": "See the detail information from Upgrading GROWI to v5.0.x .", + "detail_info": "See the detail information from Upgrading GROWI to v5.0.x external_link.", "modal": { "title": "Convert to new v5 compatible format", "converting_pages": "Converting pages", @@ -588,7 +593,7 @@ "sign_in_error": "Login error", "registration_successful": "Registration successful. Please wait for administrator approval.", "Setup": "Setup", - "enabled_ldap_has_configuration_problem":"LDAP is enabled but the configuration has something wrong.", + "enabled_ldap_has_configuration_problem": "LDAP is enabled but the configuration has something wrong.", "set_env_var_for_logs": "(Please set the environment variables DEBUG=crowi:service:PassportService to get the logs)" }, "invited": { @@ -615,21 +620,21 @@ "aws_sttings_required": "AWS settings required to use this function. Please ask the administrator.", "application_already_installed": "Application already installed.", "email_address_could_not_be_used": "This email address could not be used. (Make sure the allowed email address)", - "user_id_is_not_available":"This User ID is not available.", - "username_should_not_be_null":"Username should not be null. Please check Authentication Mechanism Settings on admin page", - "email_address_is_already_registered":"This email address is already registered.", - "can_not_register_maximum_number_of_users":"Can not register more than the maximum number of users.", - "email_settings_is_not_setup":"E-mail settings is not set up. Please ask the administrator.", + "user_id_is_not_available": "This User ID is not available.", + "username_should_not_be_null": "Username should not be null. Please check Authentication Mechanism Settings on admin page", + "email_address_is_already_registered": "This email address is already registered.", + "can_not_register_maximum_number_of_users": "Can not register more than the maximum number of users.", + "email_settings_is_not_setup": "E-mail settings is not set up. Please ask the administrator.", "email_authentication_is_not_enabled": "Email authentication is not enabled. Please ask the administrator.", - "failed_to_register":"Failed to register.", - "successfully_created":"The user {{username}} is successfully created.", - "can_not_activate_maximum_number_of_users":"Can not activate more than the maximum number of users.", - "failed_to_activate":"Failed to activate.", - "unable_to_use_this_user":"Unable to use this user.", - "complete_to_install1":"Complete to Install GROWI ! Please login as admin account.", - "complete_to_install2":"Complete to Install GROWI ! Please check each settings on this page first.", - "failed_to_create_admin_user":"Failed to create admin user. {{errMessage}}", - "successfully_send_email_auth":"We sent an email to {{email}}. Please click the URL in the email and complete the registration.", + "failed_to_register": "Failed to register.", + "successfully_created": "The user {{username}} is successfully created.", + "can_not_activate_maximum_number_of_users": "Can not activate more than the maximum number of users.", + "failed_to_activate": "Failed to activate.", + "unable_to_use_this_user": "Unable to use this user.", + "complete_to_install1": "Complete to Install GROWI ! Please login as admin account.", + "complete_to_install2": "Complete to Install GROWI ! Please check each settings on this page first.", + "failed_to_create_admin_user": "Failed to create admin user. {{errMessage}}", + "successfully_send_email_auth": "We sent an email to {{email}}. Please click the URL in the email and complete the registration.", "incorrect_token_or_expired_url": "The token is incorrect or the URL has expired.", "user_already_logged_in": "You cannot create a new account when you are logged in.", "registration_closed": "You are not authorized to create a new account.", @@ -644,22 +649,22 @@ "Username or E-mail has invalid characters": "Username or E-mail has invalid characters.", "Password minimum character should be more than 6 characters": "Password minimum character should be more than 6 characters.", "user_not_found": "User not found.", - "provider_duplicated_username_exception": "

DuplicatedUsernameException occured

Your {{ failedProviderForDuplicatedUsernameException }} authentication was succeeded, but a new user could not be created. See the issue #193.

" + "provider_duplicated_username_exception": "

cancelDuplicatedUsernameException occured

Your {{ failedProviderForDuplicatedUsernameException }} authentication was succeeded, but a new user could not be created. See the issue #193.

" }, - "grid_edit":{ - "create_bootstrap_4_grid":"Create Bootstrap 4 Grid", + "grid_edit": { + "create_bootstrap_4_grid": "Create Bootstrap 4 Grid", "grid_settings": "Grid Settings", - "grid_pattern":"Grid Pattern", - "division":"Divisions", - "smart_no":"Smartphone / No Break", - "break_point":"Break point by display size" + "grid_pattern": "Grid Pattern", + "division": "Divisions", + "smart_no": "Smartphone / No Break", + "break_point": "Break point by display size" }, - "validation":{ + "validation": { "aws_region": "For the region, enter the AWS region name. ex):us-east-1", - "aws_custom_endpoint":"For the custom endpoint, specify the URL that starts with http(s)://. Also, the trailing slash is not required.", - "failed_to_send_a_test_email":"Failed to send a test email using SMTP. Please check your settings." + "aws_custom_endpoint": "For the custom endpoint, specify the URL that starts with http(s)://. Also, the trailing slash is not required.", + "failed_to_send_a_test_email": "Failed to send a test email using SMTP. Please check your settings." }, - "forgot_password":{ + "forgot_password": { "forgot_password": "Forgot Password?", "send": "Send", "return_to_login": "Return to login", @@ -676,7 +681,7 @@ "password_and_confirm_password_does_not_match": "Password and confirm password does not match", "please_enable_mailer_alert": "The password reset feature is disabled because email setup has not been completed. Please ask administrator to complete the email setup." }, - "emoji" :{ + "emoji": { "title": "Pick an Emoji", "search": "Search", "clear": "Clear", @@ -706,7 +711,7 @@ "6": "Dark Skin Tone" } }, - "maintenance_mode":{ + "maintenance_mode": { "maintenance_mode": "Maintenance Mode", "growi_is_under_maintenance": "GROWI is under maintenance. Please wait until it ends.", "admin_page": "Admin Page", @@ -718,10 +723,10 @@ "you_cannot_move_this_page_now": "You cannot move this page now", "something_went_wrong_with_moving_page": "Something went wrong with moving page" }, - "duplicated_page_alert" : { + "duplicated_page_alert": { "same_page_name_exists": "Same page name exits as「{{pageName}}」", - "same_page_name_exists_at_path" : "Same page name as {{pageName}} exists at {{path}} ", - "select_page_to_see" : "Select a page to see" + "same_page_name_exists_at_path": "Same page name as {{pageName}} exists at {{path}} ", + "select_page_to_see": "Select a page to see" }, "user_group": { "select_group": "Select group", @@ -737,7 +742,7 @@ "isForbidden": "Authority not allowed to view", "currentPageGrantLabel": "Authorization for this page: ", "parentPageGrantLabel": "Authority of parent page: ", - "docLink": "For more information on modifying permissions, please refer to こちらのリンク" + "docLink": "For more information on modifying permissions, please refer to こちらのリンク" }, "radio_btn": { "restrected": "Only those who know the link", @@ -768,15 +773,15 @@ } } }, - "page_operation":{ + "page_operation": { "paths_recovered": "Paths recovered successfully", - "path_recovery_failed":"Path recovery failed" + "path_recovery_failed": "Path recovery failed" }, "footer": { "bookmarks": "Bookmarks", "recently_created": "Recently Created" }, - "bookmark_folder":{ + "bookmark_folder": { "bookmark_folder": "bookmark folder", "bookmark": "bookmark", "delete_modal": { @@ -794,7 +799,7 @@ "root": "root (default)" }, "v5_page_migration": { - "page_tree_not_avaliable" : "Page tree feature is not available yet.", + "page_tree_not_avaliable": "Page tree feature is not available yet.", "go_to_settings": "Go to settings to enable the feature" }, "questionnaire": { @@ -826,5 +831,22 @@ }, "rich_attachment": { "attachment_not_be_found": "The attachment could not be found" + }, + "page_select_modal": { + "select_page_location": "Select page location" + }, + "wip_page": { + "save_as_wip": "Save as WIP (still being written)", + "success_save_as_wip": "Successfully saved as a WIP page", + "fail_save_as_wip": "Failed to save as a WIP page", + "alert": "This page is still being written", + "publish_page": "Publish page", + "success_publish_page": "Page has been published", + "fail_publish_page": "Failed to publish the Page" + }, + "sidebar_header": { + "show_wip_page": "Show WIP", + "size_s": "Size: S", + "size_l": "Size: L" } } diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index ed2363d73a3..f8933ec5ea6 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -47,10 +47,12 @@ "page_delete": "ゴミ箱に入れる", "page_delete_completely": "完全に削除する", "other_options": "その他のオプション", - "deletion_explain": "ページをゴミ箱に入れることができるユーザーを制限します。", - "complete_deletion_explain": "ページを完全削除することができるユーザーを制限します。", - "recursive_deletion_explain": "子孫を含めたページをゴミ箱に入れることができるユーザーを制限します。", - "recursive_complete_deletion_explain": "子孫を含めたページを完全削除することができるユーザーを制限します。", + "deletion_explanation": "ページをゴミ箱に入れることができるユーザーを制限します。", + "complete_deletion_explanation": "ページを完全削除することができるユーザーを制限します。", + "recursive_deletion_explanation": "子孫を含めたページをゴミ箱に入れることができるユーザーを制限します。", + "recursive_complete_deletion_explanation": "子孫を含めたページを完全削除することができるユーザーを制限します。", + "is_all_group_membership_required_for_page_complete_deletion": "管理者とページ作者以外はページに対する権限を持つ全てのグループに所属している必要がある", + "is_all_group_membership_required_for_page_complete_deletion_explanation": "ページの権限設定が「特定のグループのみ」の場合有効になります。", "inherit": "単体のみと同じ", "admin_only": "管理者のみ可能", "admin_and_author": "管理者とページ作者が可能", @@ -506,8 +508,8 @@ "enable_marp_desc": "プレゼンテーション表示に Marp を利用できるようになります。ただし、XSS に対して脆弱になる恐れがあります。", "marp_official_site": "参考:Marp 公式サイト", "marp_official_site_link": "https://marp.app", - "presentation_docs" : "参考:GROWI Docs - プレゼンテーション機能を使う", - "presentation_docs_link": "https://docs.growi.org/ja/guide/features/presentation.html" + "marp_in_growi" : "参考:GROWI Docs - Marp でスライドを作成する", + "marp_in_growi_link": "https://docs.growi.org/ja/guide/features/marp.html" }, "custom_title": "カスタム Title", "custom_title_detail": "<title>タグのコンテンツをカスタマイズできます。以下のプレースホルダーは自動的に置換されます:", @@ -575,10 +577,6 @@ "initialize_meta_datas": { "label": "「いいね」「閲覧したユーザー」「コメント数」を初期化する", "desc": "users を同時に復元しない場合、このオプションは非推奨です。" - }, - "initialize_hackmd_related_datas": { - "label": "HackMD 関連データを初期化する", - "desc": "HackMD に重要な下書きデータがない限りはこのオプションをチェックすることを推奨します。" } }, "revisions": { @@ -758,7 +756,7 @@ "description1": "メールアドレスを使用して新規ユーザーを仮発行します。", "description2": "初回のログイン時に使用する仮パスワードが生成されます。", "invite_thru_email": "招待メールを送信する", - "mail_setting_link": "メールの設定", + "mail_setting_link": "settingsメールの設定", "valid_email": "メールアドレスを入力してください。", "temporary_password": "作成したユーザーは仮パスワードが設定されています。", "send_new_password": "新規発行したパスワードを、対象ユーザーへ連絡してください。", @@ -846,9 +844,10 @@ "dropdown_desc": "削除するグループの限定公開ページの処理を選択してください", "select_group": "グループを選択してください", "no_groups": "グループがありません", - "publish_pages": "全て公開する", + "publish_pages": "公開可能なページを公開する", "delete_pages": "全て削除する", - "transfer_pages": "全て他のグループに移譲する" + "transfer_pages": "全て他のグループに移譲する", + "option_explanation": "「公開可能なページ」とは、削除するグループにのみ限定公開されているページを指します。他のグループも閲覧可能なページは公開対象となりません。" }, "update_parent_confirm_modal": { "header": "グループの親が変更されます", @@ -871,12 +870,12 @@ "return": "戻る", "clear": "クリア", "activity_expiration_date": "監査ログの有効期限", - "activity_expiration_date_explain": "作成された監査ログは、作成時間から環境変数に設定した秒数後に自動的に削除されます", + "activity_expiration_date_explanation": "作成された監査ログは、作成時間から環境変数に設定した秒数後に自動的に削除されます", "fixed_by_env_var": "環境変数により固定されています {{key}}={{value}}.", "available_action_list": "検索 / 表示 可能なアクション一覧", - "available_action_list_explain": "現在の設定で検索 / 表示 可能なアクション一覧です", + "available_action_list_explanation": "現在の設定で検索 / 表示 可能なアクション一覧です", "action_list": "アクション一覧", - "disable_mode_explain": "現在、監査ログは無効になっています。有効にする場合は環境変数 AUDIT_LOG_ENABLED を true に設定してください。", + "disable_mode_explanation": "現在、監査ログは無効になっています。有効にする場合は環境変数 AUDIT_LOG_ENABLED を true に設定してください。", "docs_url": { "log_type": "https://docs.growi.org/ja/admin-guide/admin-cookbook/audit-log-setup.html#log-types" } diff --git a/apps/app/public/static/locales/ja_JP/commons.json b/apps/app/public/static/locales/ja_JP/commons.json index 1b85c379e20..bc8e336cc84 100644 --- a/apps/app/public/static/locales/ja_JP/commons.json +++ b/apps/app/public/static/locales/ja_JP/commons.json @@ -44,6 +44,12 @@ } }, + "search_method_menu_item": { + "search_in_all": "全てのページ", + "only_children_of_this_tree": "この階層下の子ページのみ", + "exact_mutch": "キーワードに完全一致した文字を含むページのみ" + }, + "share_links": { "Share Link": "共有用リンク", "Page Path": "ページパス", @@ -70,6 +76,19 @@ "feedback": "ご意見・ご要望" }, + "create_page_dropdown": { + "new_page": "新規ページ作成", + "todays": { + "desc": "今日のメモを作成", + "memo": "メモ" + }, + "template": { + "desc": "テンプレートページの作成/編集", + "children": "同一階層テンプレート", + "descendants": "下位層テンプレート" + } + }, + "copy_to_clipboard": { "Copy to clipboard": "クリップボードにコピー", "Page path": "ページ名", diff --git a/apps/app/public/static/locales/ja_JP/translation.json b/apps/app/public/static/locales/ja_JP/translation.json index 1c197a91820..8ba5dafdfbf 100644 --- a/apps/app/public/static/locales/ja_JP/translation.json +++ b/apps/app/public/static/locales/ja_JP/translation.json @@ -10,10 +10,10 @@ "Duplicate": "複製", "PathRecovery": "パスを修復", "Copy": "コピー", - "preview":"プレビュー", - "desktop":"パソコン", - "phone":"スマホ", - "tablet":"タブレット", + "preview": "プレビュー", + "desktop": "パソコン", + "phone": "スマホ", + "tablet": "タブレット", "Click to copy": "クリックでコピー", "Rename": "名前変更", "Move/Rename": "移動/名前変更", @@ -41,9 +41,11 @@ "Error": "エラー", "Warning": "注意", "Sign in": "ログイン", + "Sign in with External auth": "{{signin}} でログイン", "Sign up is here": "新規登録はこちら", "Sign in is here": "ログインはこちら", "Sign up": "新規登録", + "or": "または", "Sign up with Google Account": "Google で登録", "Sign in with Google Account": "Google でログイン", "Sign up with this Google Account": "この Google アカウントで登録します", @@ -105,15 +107,14 @@ "Disclose E-mail": "メールアドレスの公開", "page exists": "このページはすでに存在しています", "Error occurred": "エラーが発生しました", - "Create today's": "今日の◯◯を作成", - "Memo": "メモ", "Input page name": "ページ名を入力", "Input page name (optional)": "ページ名を入力(空欄OK)", + "Input parent page path": "親ページのパスを入力", "New Page": "新規ページ", "Create under": "ページを以下に作成", "V5 Page Migration": "V5 互換形式 への変換", "GROWI.5.0_new_schema": "GROWI.5.0における新スキーマについて", - "See_more_detail_on_new_schema": "詳しくは{{title}}を参照ください。", + "See_more_detail_on_new_schema": "詳しくは{{title}}external_linkを参照ください。", "external_account_management": "外部アカウント管理", "UserGroup": "グループ", "Basic Settings": "基本設定", @@ -147,9 +148,10 @@ "wide_view": "ワイドビュー", "Recent Changes": "最新の変更", "Page Tree": "ページツリー", - "original_path":"元のパス", - "new_path":"新しいパス", - "duplicated_path":"重複したパス", + "In-App Notification": "通知", + "original_path": "元のパス", + "new_path": "新しいパス", + "duplicated_path": "重複したパス", "Link sharing is disabled": "リンクのシェアは無効化されています", "successfully_saved_the_page": "ページが正常に保存されました", "you_can_not_create_page_with_this_name": "この名前でページを作成することはできません", @@ -214,7 +216,7 @@ }, "Password": "パスワード", "Password Settings": "パスワード設定", - "personal_settings":{ + "personal_settings": { "disassociate_external_account": "External Account の連携解除", "disassociate_external_account_desc": "{{providerType}} プロバイダーの {{accountId}} アカウントを連携解除します", "set_new_password": "パスワードを新規に設定", @@ -228,7 +230,7 @@ "Shere this page link to public": "外部に共有するリンクを発行する", "share_link_list": "共有リンクリスト", "share_link_management": "共有リンク管理", - "delete_all_share_links":"全ての共有リンクを削除します", + "delete_all_share_links": "全ての共有リンクを削除します", "expire": "有効期限", "Days": "日間", "Custom": "カスタム", @@ -236,8 +238,8 @@ "enter_desc": "概要を入力", "Unlimited": "無期限", "Issue": "発行", - "share_settings" :"共有設定", - "Invalid_Number_of_Date" : "有効期限の日数には整数を入力してください", + "share_settings": "共有設定", + "Invalid_Number_of_Date": "有効期限の日数には整数を入力してください", "link_sharing_is_disabled": "リンクのシェアは無効化されています" }, "API Settings": "API設定", @@ -252,6 +254,21 @@ "page_create": "ページを作成した時にそのページをサブスクライブします。" } }, + "ui_settings": { + "ui_settings": "UI設定", + "side_bar_mode": { + "settings": "サイドバーモードの設定", + "side_bar_mode_setting": "サイドバーのモードを設定する", + "description": "画面幅が大きい場合に、サイドバーを常時開いた状態にするかどうかを設定できます。画面幅が小さい場合はサイドバーは常に閉じた状態となります。" + } + }, + "color_mode_settings": { + "light": "ライト", + "dark": "ダーク", + "system": "システム", + "settings": "カラーモードの設定", + "description": "ライトモードかダークモード、もしくはシステム合わせた表示をするか選択します。
対応したテーマのみ切り替えることができます。" + }, "editor_settings": { "editor_settings": "エディター設定", "common_settings": { @@ -267,7 +284,7 @@ "no_zero_width_spaces": "ゼロ幅スペースを許可しません。", "period_in_list_item": "リストアイテムのピリオドの有無をチェックします。", "use_si_units": "SI単位系以外の使用を禁止します。" - }, + }, "japanese_settings": { "japanese_settings": "日本語設定", "ja_hiragana_keishikimeishi": "漢字よりひらがなで書かれた読みやすい形式名詞をチェックします。", @@ -321,7 +338,7 @@ "notice": { "version": "これは最新のバージョンではありません。", "redirected": "リダイレクト元 >>", - "redirected_period":"", + "redirected_period": "", "unlinked": "このページへのリダイレクトは削除されました。", "restricted": "このページの閲覧は制限されています", "stale": "このページは最終更新日から{{count}}年以上が経過しています。", @@ -330,6 +347,11 @@ } }, "page_edit": { + "input_channels": "チャンネル名", + "theme": "テーマ", + "keymap": "キーマップ", + "indent": "インデント", + "editor_config": "エディタ設定", "Show active line": "アクティブ行をハイライト", "auto_format_table": "表の自動整形", "overwrite_scopes": "{{operation}}と同時に全ての配下ページのスコープを上書き", @@ -347,7 +369,8 @@ "already_exists": "そのパスを持つページは既に存在しています。", "outdated": "ページが他のユーザーによって更新されました。", "user_not_admin": "権限のあるユーザーのみが削除できます", - "single_deletion_empty_pages": "空ページの単体削除はできません" + "single_deletion_empty_pages": "空ページの単体削除はできません", + "complete_deletion_not_allowed_for_user": "ページを完全に削除する権限がありません" }, "page_history": { "revision_list": "更新履歴", @@ -355,8 +378,8 @@ "comparing_source": "ソース", "comparing_target": "ターゲット", "comparing_revisions": "差分を比較する", - "compare_latest":"最新と比較", - "compare_previous":"1つ前のバージョンと比較" + "compare_latest": "最新と比較", + "compare_previous": "1つ前のバージョンと比較" }, "modal_rename": { "label": { @@ -394,7 +417,7 @@ "deleted_pages_completely": "{{path}} を完全に削除しました", "renamed_pages": "{{path}} を移動/名前変更しました", "empty_trash": "ゴミ箱を空にしました", - "modal_empty":{ + "modal_empty": { "empty_the_trash": "ゴミ箱を空にする", "empty_the_trash_button": "空にする", "not_deletable_notice": "権限がないため、いくつかのページは削除できません", @@ -408,10 +431,12 @@ "Current page name": "現在のページ名", "Recursively": "再帰的に複製", "Duplicate without exist path": "存在するパス以外を複製する", - "Same page already exists": "同じページがすでに存在します" + "Same page already exists": "同じページがすでに存在します", + "Only duplicate user related pages": "自分が閲覧可能なページのみを複製する" }, "help": { - "recursive": "配下のページも複製します" + "recursive": "配下のページも複製します", + "only_inherit_user_related_groups": "閲覧権限が「特定グループのみ」で設定されている場合、複製されたページを閲覧可能なグループ一覧から、自分が所属していないものは取り除かれます" } }, "duplicated_pages": "{{fromPath}} を複製しました", @@ -449,13 +474,13 @@ } }, "modal_resolve_conflict": { + "conflicts_with_new_body_on_server_side": "サーバー側の新しい本文と衝突します。ページ本文を選択または編集して衝突を解消してください。", "file_conflicting_with_newer_remote": "サーバー側の新しいファイルと衝突します。", "resolve_conflict_message": "ページ本文を選んでください", "resolve_conflict": "衝突を解消", - "resolve_and_save" : "解消し保存する", - "select_revision" : "{{revision}}にする", + "resolve_and_save": "解消し保存する", + "select_revision": "{{revision}}にする", "requested_revision": "送信された本文", - "origin_revision": "送信する前の本文", "latest_revision": "最新の本文", "selected_editable_revision": "保存するページ本文(編集可能)" }, @@ -482,7 +507,7 @@ "issue_share_link": "共有リンクを作成しました", "remove_share_link": "共有リンクを{{count}}件削除しました", "switch_disable_link_sharing_success": "共有リンクの設定を変更しました", - "failed_to_reset_password":"パスワードのリセットに失敗しました", + "failed_to_reset_password": "パスワードのリセットに失敗しました", "save_succeeded": "保存に成功しました" }, "template": { @@ -499,7 +524,7 @@ "label": "同一階層テンプレート", "desc": "テンプレートページが存在する階層にのみ適用されます" }, - "decendants": { + "descendants": { "label": "下位層テンプレート", "desc": "テンプレートページが存在する下位層のすべてのページに適用されます" } @@ -535,27 +560,6 @@ "insert_image": "で画像を挿入できます", "open_sandbox": "Sandbox を開く" }, - "hackmd":{ - "hack_md": "HackMD", - "not_set_up": "HackMD はセットアップされていません", - "used_for_not_found": "HackMD は新しいページの作成には利用できません", - "start_to_edit": "HackMD を開始する", - "clone_page_content": "ページを複製して編集を開始します", - "unsaved_draft": "HackMD のドラフトが保存されていません", - "draft_outdated": "ドラフトは古くなっている可能性があります", - "based_on_revision": "現在のドラフトは次の revision に基づいています", - "view_outdated_draft": "HackMD で古いドラフトを表示する", - "resume_to_edit": "HackMD で編集を再開する", - "discard_changes": "HackMD の変更を破棄する", - "integration_failed": "HackMD の統合に失敗しました", - "fail_to_connect": "GROWI クライアントが HackMD の GROWI agent に接続できませんでした。", - "check_configuration": "こちらのマニュアルから設定を確認してください", - "not_initialized": "HackMD コンポーネントは初期化されていません", - "someone_editing": "このページは、HackMD で編集されています。", - "this_page_has_draft": "このページは、HackMD のドラフトがあります。", - "need_to_associate_with_growi_to_use_hackmd_refer_to_this": "HackMD を利用して同時多人数編集を行うには、HackMD と GROWI を連携する必要があります。こちらを参照してください。", - "need_to_make_page": "HackMD を利用するためには、ビルトインエディタで新しいページを作成してください。" - }, "slack_notification": { "popover_title": "Slack 通知", "popover_desc": "チャンネル名を入れてください。カンマ区切りのリストを入力することで複数のチャンネルに通知することができます。" @@ -570,11 +574,12 @@ "deletion_modal_header": "以下のページを削除", "delete_completely": "完全に削除する", "include_certain_path": "{{pathToInclude}}下を含む ", - "delete_all_selected_page" : "一括削除", - "currently_not_implemented":"現在未実装の機能です", - "search_again" : "再検索", - "number_of_list_to_display" : "表示件数", - "page_number_unit" : "件", + "delete_all_selected_page": "一括削除", + "currently_not_implemented": "現在未実装の機能です", + "search_again": "再検索", + "number_of_list_to_display": "表示件数", + "page_number_unit": "件", + "hit_number_unit": "件", "sort_axis": { "relationScore": "関連度順", "createdAt": "作成日時", @@ -590,7 +595,7 @@ "alert_desc1": "このページでは、チェックボックスでページを選択し、画面上部の「一括操作」ボタンから新しい v5 互換形式に一括変換できます。", "nopages_title": "おめでとうございます。GROWI v5 を使う準備が完了しました!", "nopages_desc1": "今あなたが管理可能なページはすべて v5 互換形式になっているようです。", - "detail_info": "詳しくは GROWI v5.0.x へのアップグレード を参照ください。", + "detail_info": "詳しくは GROWI v5.0.x へのアップグレード external_link を参照ください。", "modal": { "title": "新しい v5 互換形式への変換", "converting_pages": "以下のページを変換します", @@ -621,7 +626,7 @@ "sign_in_error": "ログインエラー", "registration_successful": "登録が完了しました。管理者の承認をお待ちください。", "Setup": "セットアップ", - "enabled_ldap_has_configuration_problem":"LDAPは有効ですが、設定に問題があります。", + "enabled_ldap_has_configuration_problem": "LDAPは有効ですが、設定に問題があります。", "set_env_var_for_logs": "(ログを取得するためには、環境変数 DEBUG=crowi:service:PassportService を設定してください。)" }, "invited": { @@ -647,23 +652,23 @@ "sign_in_failure": "ログインに失敗しました。", "aws_sttings_required": "この機能にはAWS設定が必要です。管理者に訪ねて下さい。", "application_already_installed": "アプリケーションのインストールが完了しました。", - "email_address_could_not_be_used":"このメールアドレスは使用できません。(許可されたメールアドレスを確認してください。)", - "user_id_is_not_available":"このユーザーIDは使用できません。", - "username_should_not_be_null":"Username が null になっています 管理画面の認証機構設定にて設定の確認をしてください", - "email_address_is_already_registered":"このメールアドレスは既に登録されています。", - "can_not_register_maximum_number_of_users":"ユーザー数が上限を超えたため登録できません。", - "email_settings_is_not_setup":"E-mail 設定が完了していません。管理者に問い合わせてください。", + "email_address_could_not_be_used": "このメールアドレスは使用できません。(許可されたメールアドレスを確認してください。)", + "user_id_is_not_available": "このユーザーIDは使用できません。", + "username_should_not_be_null": "Username が null になっています 管理画面の認証機構設定にて設定の確認をしてください", + "email_address_is_already_registered": "このメールアドレスは既に登録されています。", + "can_not_register_maximum_number_of_users": "ユーザー数が上限を超えたため登録できません。", + "email_settings_is_not_setup": "E-mail 設定が完了していません。管理者に問い合わせてください。", "email_authentication_is_not_enabled": "メール認証が有効になっていません。管理者に問い合わせてください。", - "failed_to_register":"登録に失敗しました。", - "successfully_created":"{{username}} が作成されました。", - "can_not_activate_maximum_number_of_users":"ユーザーが上限に達したためアクティベートできません。", - "failed_to_activate":"アクティベートに失敗しました。", - "unable_to_use_this_user":"利用できないユーザーIDです。", - "complete_to_install1":"GROWI のインストールが完了しました!管理者アカウントでログインしてください。", - "complete_to_install2":"GROWI のインストールが完了しました!はじめに、このページで各種設定を確認してください。", - "failed_to_create_admin_user":"管理ユーザーの作成に失敗しました。{{errMessage}}", - "successfully_send_email_auth":"{{email}} にメールを送信しました。添付されたURLをクリックし、本登録を完了させてください", - "incorrect_token_or_expired_url":"トークンが正しくないか、URLの有効期限が切れています。", + "failed_to_register": "登録に失敗しました。", + "successfully_created": "{{username}} が作成されました。", + "can_not_activate_maximum_number_of_users": "ユーザーが上限に達したためアクティベートできません。", + "failed_to_activate": "アクティベートに失敗しました。", + "unable_to_use_this_user": "利用できないユーザーIDです。", + "complete_to_install1": "GROWI のインストールが完了しました!管理者アカウントでログインしてください。", + "complete_to_install2": "GROWI のインストールが完了しました!はじめに、このページで各種設定を確認してください。", + "failed_to_create_admin_user": "管理ユーザーの作成に失敗しました。{{errMessage}}", + "successfully_send_email_auth": "{{email}} にメールを送信しました。添付されたURLをクリックし、本登録を完了させてください", + "incorrect_token_or_expired_url": "トークンが正しくないか、URLの有効期限が切れています。", "user_already_logged_in": "ログイン中のため、新規アカウントを作成できませんでした。", "registration_closed": "新しいアカウントを作成する権限がありません。", "Username has invalid characters": "ユーザー名に不正な文字が含まれています.", @@ -677,22 +682,22 @@ "Username or E-mail has invalid characters": "ユーザー名または、メールアドレスに無効な文字があります", "Password minimum character should be more than 6 characters": "パスワードの最小文字数は6文字以上です", "user_not_found": "ユーザーが見つかりません", - "provider_duplicated_username_exception": "

エラー: DuplicatedUsernameException

{{ failedProviderForDuplicatedUsernameException }} 認証は成功しましたが、新しいユーザーを作成できませんでした。詳しくはこちら: #193.

" + "provider_duplicated_username_exception": "

cancelエラー: DuplicatedUsernameException

{{ failedProviderForDuplicatedUsernameException }} 認証は成功しましたが、新しいユーザーを作成できませんでした。詳しくはこちら: #193.

" }, - "grid_edit":{ - "create_bootstrap_4_grid":"Bootstrap 4 グリッドを作成", + "grid_edit": { + "create_bootstrap_4_grid": "Bootstrap 4 グリッドを作成", "grid_settings": "グリッド設定", - "grid_pattern":"グリッド パターン", - "division":"分割", - "smart_no":"スマホ / 分割なし", - "break_point":"画面サイズより分割" + "grid_pattern": "グリッド パターン", + "division": "分割", + "smart_no": "スマホ / 分割なし", + "break_point": "画面サイズより分割" }, - "validation":{ + "validation": { "aws_region": "リージョンには、AWSリージョン名を入力してください。例: ap-northeast-1", "aws_custom_endpoint": "カスタムエンドポイントは、http(s)://で始まるURLを指定してください。また、末尾の/は不要です。", - "failed_to_send_a_test_email":"SMTPを利用したテストメール送信に失敗しました。設定をみなおしてください。" + "failed_to_send_a_test_email": "SMTPを利用したテストメール送信に失敗しました。設定をみなおしてください。" }, - "forgot_password":{ + "forgot_password": { "forgot_password": "パスワードをお忘れですか?", "send": "送信", "return_to_login": "ログイン画面に戻る", @@ -705,11 +710,11 @@ "email_is_required": "メールを入力してください", "success_to_send_email": "メールを送信しました", "feature_is_unavailable": "この機能を利用することはできません。", - "incorrect_token_or_expired_url":"トークンが正しくないか、URLの有効期限が切れています。 以下のリンクからパスワードリセットリクエストを再送信してください。", + "incorrect_token_or_expired_url": "トークンが正しくないか、URLの有効期限が切れています。 以下のリンクからパスワードリセットリクエストを再送信してください。", "password_and_confirm_password_does_not_match": "パスワードと確認パスワードが一致しません", "please_enable_mailer_alert": "メール設定が完了していないため、パスワード再設定機能が無効になっています。メール設定を完了させるよう管理者に依頼してください。" }, - "emoji" :{ + "emoji": { "title": "絵文字を選択", "search": "探す", "clear": "リセット", @@ -739,7 +744,7 @@ "6": "肌の色が濃い" } }, - "maintenance_mode":{ + "maintenance_mode": { "maintenance_mode": "メンテナンスモード", "growi_is_under_maintenance": "GROWI はメンテナンス中です。終了するまでお待ちください", "admin_page": "管理画面へ", @@ -751,10 +756,10 @@ "you_cannot_move_this_page_now": "現在、このページを移動することはできません", "something_went_wrong_with_moving_page": "ページの移動に問題が発生しました" }, - "duplicated_page_alert" : { + "duplicated_page_alert": { "same_page_name_exists": "ページ名 「{{pageName}}」が重複しています", - "same_page_name_exists_at_path" : "”{{path}}” において ”{{pageName}}”というページは複数存在しています。", - "select_page_to_see" : "以下から遷移するページを選択してください。" + "same_page_name_exists_at_path": "”{{path}}” において ”{{pageName}}”というページは複数存在しています。", + "select_page_to_see": "以下から遷移するページを選択してください。" }, "user_group": { "select_group": "グループを選ぶ", @@ -770,7 +775,7 @@ "isForbidden": "権限の閲覧が許可されていません", "currentPageGrantLabel": "このページの権限: ", "parentPageGrantLabel": "親のページの権限: ", - "docLink": "権限の修正についての詳細はこちらのリンクを参照してください" + "docLink": "権限の修正についての詳細はこちらのリンクを参照してください" }, "radio_btn": { "restrected": "リンクを知っている人のみ", @@ -801,15 +806,15 @@ } } }, - "page_operation":{ + "page_operation": { "paths_recovered": "パスを修復しました", - "path_recovery_failed":"パスを修復できませんでした" + "path_recovery_failed": "パスを修復できませんでした" }, "footer": { "bookmarks": "ブックマーク", "recently_created": "最近作成したページ" }, - "bookmark_folder":{ + "bookmark_folder": { "bookmark_folder": "ブックマークフォルダ", "bookmark": "ブックマーク", "delete_modal": { @@ -827,7 +832,7 @@ "root": "root (default)" }, "v5_page_migration": { - "page_tree_not_avaliable" : "Page Tree 機能は現在使用できません。", + "page_tree_not_avaliable": "Page Tree 機能は現在使用できません。", "go_to_settings": "設定する" }, "questionnaire": { @@ -859,5 +864,22 @@ }, "rich_attachment": { "attachment_not_be_found": "アタッチメントが見つかりません" + }, + "page_select_modal": { + "select_page_location": "ページの場所を選択" + }, + "wip_page": { + "save_as_wip": "WIP (執筆途中) として保存", + "success_save_as_wip": "WIP ページとして保存しました", + "fail_save_as_wip": "WIP ページとして保存できませんでした", + "alert": "このページは執筆途中です", + "publish_page": "WIP を解除", + "success_publish_page": "WIP を解除しました", + "fail_publish_page": "WIP を解除できませんでした" + }, + "sidebar_header": { + "show_wip_page": "WIP を表示", + "size_s": "サイズ: S", + "size_l": "サイズ: L" } } diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index d192a6a0aa5..4eeb37300cd 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -47,10 +47,12 @@ "page_delete": "删除", "page_delete_completely": "彻底删除", "other_options": "其他选项", - "deletion_explain": "限制用户对选定的单一页面进行垃圾处理。", - "complete_deletion_explain": "限制可以完全删除所选单页的用户。", - "recursive_deletion_explain": "限制用户可以捣毁包括子孙在内的页面。", - "recursive_complete_deletion_explain": "限制可以完全删除页面的用户,包括子孙。", + "deletion_explanation": "限制用户对选定的单一页面进行垃圾处理。", + "complete_deletion_explanation": "限制可以完全删除所选单页的用户。", + "recursive_deletion_explanation": "限制用户可以捣毁包括子孙在内的页面。", + "recursive_complete_deletion_explanation": "限制可以完全删除页面的用户,包括子孙。", + "is_all_group_membership_required_for_page_complete_deletion": "除管理员和页面作者之外的用户必须属于被授予页面访问权限的所有组", + "is_all_group_membership_required_for_page_complete_deletion_explanation": "如果页面权限设置为\"仅限特定群体\",则会启用此功能。", "inherit": "继承(使用与单页相同的设置)。", "admin_only": "仅管理员", "admin_and_author": "管理员|作者", @@ -505,8 +507,8 @@ "enable_marp_desc": "Marp 可在演示视图中使用。该选项可能会使您受到 XSS 的攻击。", "marp_official_site": "参考资料:Marp 官方网站", "marp_official_site_link": "https://marp.app", - "presentation_docs" : "参考资料:GROWI Docs - Create slides for a presentation", - "presentation_docs_link": "https://docs.growi.org/en/guide/features/presentation.html" + "marp_in_growi" : "参考资料:GROWI Docs - Create slide using Marp", + "marp_in_growi_link": "https://docs.growi.org/en/guide/features/marp.html" }, "custom_title": "自定义标题", "custom_title_detail": "您可以自定义<;title>;标记。
&123;&123;sitename&&125;&125;将自动替换为应用程序名称,并且&123;&123;page&&125;&125;将替换为页面名称/路径。", @@ -574,10 +576,6 @@ "initialize_meta_datas": { "label": "Initialize page's like, read users and comment count", "desc": "Recommended NOT to check this when users will also be restored." - }, - "initialize_hackmd_related_datas": { - "label": "Initialize HackMD related data", - "desc": "Recommended to check this unless there is important drafts on HackMD." } }, "revisions": { @@ -756,7 +754,7 @@ "emails": "电子邮件", "description1": "通过电子邮件地址临时发布新用户。", "description2": "将为首次登录生成一个临时密码。", - "mail_setting_link": "Email settings", + "mail_setting_link": "settingsEmail settings", "valid_email": "需要有效的电子邮件地址", "invite_thru_email": "发送邀请电子邮件", "temporary_password": "创建的用户具有临时密码", @@ -845,9 +843,10 @@ "dropdown_desc": "为私人页选择操作", "select_group": "选择组", "no_groups": "没有可选择的组", - "publish_pages": "全部发布", + "publish_pages": "发布可以发布的页面", "delete_pages": "全部删除", - "transfer_pages": "转移到另一组" + "transfer_pages": "转移到另一组", + "option_explanation": "\"可发布页面\"是指仅对您要删除的群组可见的页面。其他群组可以查看的页面将不会被发布。" }, "update_parent_confirm_modal": { "header": "该组的父组被改变", @@ -870,12 +869,12 @@ "return": "返回", "clear": "清除", "activity_expiration_date": "审计日志的到期日", - "activity_expiration_date_explain": "创建的审计日志会在环境变量中设置的从创建时间算起的秒数后自动删除", + "activity_expiration_date_explanation": "创建的审计日志会在环境变量中设置的从创建时间算起的秒数后自动删除", "fixed_by_env_var": "这是由env var 修复的 {{key}}={{value}}.", "available_action_list": "搜索/查看 所有可用的行动", - "available_action_list_explain": "在当前配置中可以搜索/查看的行动列表", + "available_action_list_explanation": "在当前配置中可以搜索/查看的行动列表", "action_list": "行动清单", - "disable_mode_explain": "审计日志当前已禁用。 要启用它,请将环境变量 AUDIT_LOG_ENABLED 设置为 true。", + "disable_mode_explanation": "审计日志当前已禁用。 要启用它,请将环境变量 AUDIT_LOG_ENABLED 设置为 true。", "docs_url": { "log_type": "https://docs.growi.org/en/admin-guide/admin-cookbook/audit-log-setup.html#log-types" } diff --git a/apps/app/public/static/locales/zh_CN/commons.json b/apps/app/public/static/locales/zh_CN/commons.json index cd074f8f1b2..8b40274995d 100644 --- a/apps/app/public/static/locales/zh_CN/commons.json +++ b/apps/app/public/static/locales/zh_CN/commons.json @@ -45,6 +45,12 @@ } }, + "search_method_menu_item": { + "search_in_all": "所有页面", + "only_children_of_this_tree": "当前分支以下内容", + "exact_mutch": "完全匹配" + }, + "share_links": { "Share Link": "Share Link", "Page Path": "Page Path", @@ -71,6 +77,19 @@ "feedback": "意见和要求" }, + "create_page_dropdown": { + "new_page": "新页面", + "todays": { + "desc": "Create today's memo", + "memo": "memo" + }, + "template": { + "desc": "创建/编辑模板页", + "children": "子模板", + "descendants": "子代模板" + } + }, + "copy_to_clipboard": { "Copy to clipboard": "复制到剪贴板", "Page path": "页面路径", diff --git a/apps/app/public/static/locales/zh_CN/translation.json b/apps/app/public/static/locales/zh_CN/translation.json index 8bf4f15da7c..29cf5ea8618 100644 --- a/apps/app/public/static/locales/zh_CN/translation.json +++ b/apps/app/public/static/locales/zh_CN/translation.json @@ -4,59 +4,61 @@ }, "Help": "帮助", "view": "View", - "Edit": "编辑", - "Delete": "删除", - "delete_all": "删除所有", - "Duplicate": "复制", + "Edit": "编辑", + "Delete": "删除", + "delete_all": "删除所有", + "Duplicate": "复制", "PathRecovery": "路径恢复", - "Copy": "复制", - "preview":"预览", - "desktop":"电脑", - "phone":"手机", - "tablet":"平板", - "Login": "登录", - "Click to copy": "点击复制", + "Copy": "复制", + "preview": "预览", + "desktop": "电脑", + "phone": "手机", + "tablet": "平板", + "Login": "登录", + "Click to copy": "点击复制", "Rename": "重命名", - "Move/Rename": "移动/重命名", - "Redirected": "重定向", - "Unlinked": "Unlinked", + "Move/Rename": "移动/重命名", + "Redirected": "重定向", + "Unlinked": "Unlinked", "unlink_redirection": "取消链接重定向", "Done": "Done", "Cancel": "取消", - "Create": "创建", + "Create": "创建", "Description": "描述", - "Admin": "管理", - "administrator": "管理员", - "Tags": "Tags", + "Admin": "管理", + "administrator": "管理员", + "Tags": "Tags", "Close": "Close", - "Shortcuts": "快捷方式", + "Shortcuts": "快捷方式", "CustomSidebar": "Custom Sidebar", - "eg": "e.g.", - "add": "添加", - "Undo": "撤销", - "account_id": "用户Id", - "Initialize": "初始化", + "eg": "e.g.", + "add": "添加", + "Undo": "撤销", + "account_id": "用户Id", + "Initialize": "初始化", "Update": "更新", - "Update Page": "更新本页", - "Error": "误差", - "Warning": "警告", + "Update Page": "更新本页", + "Error": "误差", + "Warning": "警告", "Sign in": "登录", - "Sign up is here": "注册", - "Sign in is here": "登录", - "Sign up": "注册", - "Sign up with Google Account": "Sign up with Google Account", - "Sign in with Google Account": "Sign in with Google Account", - "Sign up with this Google Account": "Sign up with this Google Account", - "Example": "例如", - "Taro Yamada": "John Doe", + "Sign in with External auth": "Sign in with {{signin}}", + "Sign up is here": "注册", + "Sign in is here": "登录", + "Sign up": "注册", + "or": "或者", + "Sign up with Google Account": "Sign up with Google Account", + "Sign in with Google Account": "Sign in with Google Account", + "Sign up with this Google Account": "Sign up with this Google Account", + "Example": "例如", + "Taro Yamada": "John Doe", "Select": "请选择", "Required": "必需的", - "List View": "列表", - "Timeline View": "时间线", + "List View": "列表", + "Timeline View": "时间线", "History": "历史", "attachment_data": "Attachment Data", "No_attachments_yet": "暂无附件", - "Presentation Mode": "演示文稿", + "Presentation Mode": "演示文稿", "Not available for guest": "不提供给客人", "Not available in this version": "此版本中不提供", "No users have liked this yet": "还没有用户喜欢这个", @@ -73,78 +75,77 @@ "Specify Hierarchy": "指定层级", "Submitted the request to create the archive": "提交创建归档请求", "username": "用户名", - "Created": "创建", - "Last updated": "上次更新", - "Share": "分享", + "Created": "创建", + "Last updated": "上次更新", + "Share": "分享", "Share Link": "分享链接", - "Markdown Link": "Markdown链接", - "Create/Edit Template": "创建/编辑 模板页面", - "Unportalize": "未启动", - "Go to this version": "查看此版本", - "View diff": "查看差异", - "No diff": "无差异", - "User ID": "用户ID", - "Home": "首页", - "My Drafts": "My Drafts", - "User Settings": "用户设置", - "User Information": "用户信息", + "Markdown Link": "Markdown链接", + "Create/Edit Template": "创建/编辑 模板页面", + "Unportalize": "未启动", + "Go to this version": "查看此版本", + "View diff": "查看差异", + "No diff": "无差异", + "User ID": "用户ID", + "Home": "首页", + "My Drafts": "My Drafts", + "User Settings": "用户设置", + "User Information": "用户信息", "User Activation": "用户激活", - "Basic Info": "基础信息", - "Name": "姓名", - "Email": "邮箱", - "Language": "语言", - "English": "英语", - "Japanese": "日语", - "Chinese": "简体中文", - "Set Profile Image": "头像", - "Upload Image": "上传图片", - "Current Image": "当前图片", - "Delete Image": "删除图片", - "Delete this image?": "删除图片?", - "Updated": "更新", - "Upload new image": "上传新图像", - "Connected": "Connected", - "Show": "显示", - "Hide": "隐藏", + "Basic Info": "基础信息", + "Name": "姓名", + "Email": "邮箱", + "Language": "语言", + "English": "英语", + "Japanese": "日语", + "Chinese": "简体中文", + "Set Profile Image": "头像", + "Upload Image": "上传图片", + "Current Image": "当前图片", + "Delete Image": "删除图片", + "Delete this image?": "删除图片?", + "Updated": "更新", + "Upload new image": "上传新图像", + "Connected": "Connected", + "Show": "显示", + "Hide": "隐藏", "Loading": "加载...", - "Reset": "重置", - "Disclose E-mail": "显示邮箱", - "page exists": "页面已存在", - "Error occurred": "Error occurred", - "Create today's": "Create today's ...", - "Memo": "memo", - "Input page name": "Input page name", - "Input page name (optional)": "Input page name (optional)", - "New Page": "新页面", - "Create under": "Create page under below:", + "Reset": "重置", + "Disclose E-mail": "显示邮箱", + "page exists": "页面已存在", + "Error occurred": "Error occurred", + "Input page name": "Input page name", + "Input page name (optional)": "Input page name (optional)", + "Input parent page path": "Input parent page path", + "New Page": "新页面", + "Create under": "Create page under below:", "V5 Page Migration": "转换为V5的兼容性", "GROWI.5.0_new_schema": "GROWI.5.0 new schema", - "See_more_detail_on_new_schema": "更多详情请见 {{title}} ", + "See_more_detail_on_new_schema": "更多详情请见 {{title}} external_link ", "Markdown Settings": "Markdown设置", "external_account_management": "外部账户管理", "UserGroup": "用户组", "ChildUserGroup": "儿童用户组", - "Basic Settings": "基础设置", - "The contents entered here will be shown in the header etc": "此处输入的内容将显示在标题等中", - "Public": "公共", - "Anyone with the link": "任何人", - "Specified users only": "仅指定用户", - "Only me": "只有我", + "Basic Settings": "基础设置", + "The contents entered here will be shown in the header etc": "此处输入的内容将显示在标题等中", + "Public": "公共", + "Anyone with the link": "任何人", + "Specified users only": "仅指定用户", + "Only me": "只有我", "Only inside the group": "仅组内", "page_list": "Page List", - "Reselect the group": "重新选择组", - "Shareable link": "可分享链接", - "The whitelist of registration permission E-mail address": "注册许可电子邮件地址的白名单", - "Add tags for this page": "添加标签", + "Reselect the group": "重新选择组", + "Shareable link": "可分享链接", + "The whitelist of registration permission E-mail address": "注册许可电子邮件地址的白名单", + "Add tags for this page": "添加标签", "tag_list": "标签列表", "popular_tags": "流行标签", "Check All tags": "检查所有标签", - "You have no tag, You can set tags on pages": "你没有标签,可以在页面上设置标签", - "Show latest": "显示最新", - "Load latest": "家在最新", - "edited this page": "edited this page.", - "List Drafts": "草稿", - "Deleted Pages": "已删除页", + "You have no tag, You can set tags on pages": "你没有标签,可以在页面上设置标签", + "Show latest": "显示最新", + "Load latest": "家在最新", + "edited this page": "edited this page.", + "List Drafts": "草稿", + "Deleted Pages": "已删除页", "Disassociate": "解除关联", "No bookmarks yet": "暂无书签", "add_bookmark": "添加到书签", @@ -152,9 +153,10 @@ "wide_view": "视野开阔", "Recent Changes": "最新修改", "Page Tree": "页面树", - "original_path":"Original path", - "new_path":"New path", - "duplicated_path":"Duplicated path", + "In-App Notification": "通知", + "original_path": "Original path", + "new_path": "New path", + "duplicated_path": "Duplicated path", "Link sharing is disabled": "你不允许分享该链接", "successfully_saved_the_page": "成功地保存了该页面", "you_can_not_create_page_with_this_name": "您无法使用此名称创建页面", @@ -162,10 +164,10 @@ "Confirm": "确定", "Successfully requested": "进程成功接受", "copied_to_clipboard": "它已复制到剪贴板。", - "form_validation": { - "error_message": "有些值不正确", - "required": "%s 是必需的", - "invalid_syntax": "%s的语法无效。", + "form_validation": { + "error_message": "有些值不正确", + "required": "%s 是必需的", + "invalid_syntax": "%s的语法无效。", "title_required": "标题是必需的。", "field_required": "{{target}} 是必需的" }, @@ -178,63 +180,63 @@ "custom_navigation": { "no_pages_under_this_page": "There are no pages under this page." }, - "installer": { + "installer": { "tab": "创建账户", "title": "安装", - "setup": "安装", - "create_initial_account": "创建初始用户", - "initial_account_will_be_administrator_automatically": "初始帐户将自动成为管理员。", - "unavaliable_user_id": "用户ID不可用", + "setup": "安装", + "create_initial_account": "创建初始用户", + "initial_account_will_be_administrator_automatically": "初始帐户将自动成为管理员。", + "unavaliable_user_id": "用户ID不可用", "failed_to_install": "GROWI安装失败。请再试一次。", "failed_to_login_after_install": "安装后登录失败。重定向到登录表格..." - }, - "breaking_changes": { - "v346_using_basic_auth": "当前使用的基本身份验证在不久的将来将不再可用。从%s中删除设置" - }, - "page_register": { + }, + "breaking_changes": { + "v346_using_basic_auth": "当前使用的基本身份验证在不久的将来将不再可用。从%s中删除设置" + }, + "page_register": { "send_email": "发电子邮件", - "notice": { - "restricted": "需要管理员批准。", - "restricted_defail": "一旦管理员批准您的注册,您就可以访问此wiki。" - }, - "form_help": { - "email": "您必须有下面列出的电子邮件地址才能注册此wiki。", - "password": "密码长度必须至少为8个字符。", - "user_id": "您创建的网页的URL将包含您的用户ID。您的用户ID可以由字母、数字和一些符号组成。" - } - }, - "Settings": "设置", - "page_me": { - "form_help": { - "profile_image1": "图像上传设置未完成。", - "profile_image2": "设置AWS或启用本地上传。" - } - }, - "page_me_apitoken": { + "notice": { + "restricted": "需要管理员批准。", + "restricted_defail": "一旦管理员批准您的注册,您就可以访问此wiki。" + }, + "form_help": { + "email": "您必须有下面列出的电子邮件地址才能注册此wiki。", + "password": "密码长度必须至少为8个字符。", + "user_id": "您创建的网页的URL将包含您的用户ID。您的用户ID可以由字母、数字和一些符号组成。" + } + }, + "Settings": "设置", + "page_me": { + "form_help": { + "profile_image1": "图像上传设置未完成。", + "profile_image2": "设置AWS或启用本地上传。" + } + }, + "page_me_apitoken": { "api_token": "API Token", - "notice": { - "apitoken_issued": "API token 未发布。", - "update_token1": "您可以更新以生成新的API令牌。", - "update_token2": "您需要更新任何现有进程中的API令牌。" - } - }, - "Password": "密码", - "Password Settings": "密码设置", - "personal_settings": { - "disassociate_external_account": "解除与外部帐户的关联", - "disassociate_external_account_desc": "是否确实要解除与{{providerType}}帐户{{providerType}} 的关联?", - "set_new_password": "设置新密码", - "update_password": "更新密码", - "current_password": "当前密码", - "new_password": "新密码", - "new_password_confirm": "重复新密码", - "password_is_not_set": "密码未设置" - }, - "API Settings": "API设置", + "notice": { + "apitoken_issued": "API token 未发布。", + "update_token1": "您可以更新以生成新的API令牌。", + "update_token2": "您需要更新任何现有进程中的API令牌。" + } + }, + "Password": "密码", + "Password Settings": "密码设置", + "personal_settings": { + "disassociate_external_account": "解除与外部帐户的关联", + "disassociate_external_account_desc": "是否确实要解除与{{providerType}}帐户{{providerType}} 的关联?", + "set_new_password": "设置新密码", + "update_password": "更新密码", + "current_password": "当前密码", + "new_password": "新密码", + "new_password_confirm": "重复新密码", + "password_is_not_set": "密码未设置" + }, + "API Settings": "API设置", "Other Settings": "其他设置", - "API Token Settings": "API token 设置", - "Current API Token": "当前 API token", - "Update API Token": "更新 API token", + "API Token Settings": "API token 设置", + "Current API Token": "当前 API token", + "Update API Token": "更新 API token", "in_app_notification_settings": { "in_app_notification_settings": "在应用程序通知设置", "subscribe_settings": "自动订阅(接收通知)页面的设置", @@ -242,51 +244,71 @@ "page_create": "创建页面时订阅页面。" } }, + "ui_settings": { + "ui_settings": "用户界面设置", + "side_bar_mode": { + "settings": "侧边栏模式设置", + "side_bar_mode_setting": "设置侧边栏模式", + "description": "您可以设置当屏幕宽度较大时,侧边栏是否始终打开。 如果屏幕宽度较小,侧边栏将始终关闭。" + } + }, + "color_mode_settings": { + "light": "灯光", + "dark": "暗处", + "system": "系统", + "settings": "色彩模式设置", + "description": "选择是以浅色模式、深色模式还是系统特定的显示方式显示。
只能切换支持的主题。" + }, "editor_settings": { "editor_settings": "编辑器设置" }, - "search_help": { - "title": "搜索帮助", - "and": { - "syntax help": "用空格分隔", - "desc": "在标题或正文中同时包含{{word1}、{{word2}的搜索页" - }, - "exclude": { - "desc": "排除标题或正文中包含{{word}的页" - }, - "phrase": { - "syntax help": "用双引号括起来", - "desc": "包含短语“{{phrase}”的搜索页" - }, - "prefix": { - "desc": "只搜索标题以{{path}开头的页" - }, - "exclude_prefix": { - "desc": "排除标题以{{path}开头的页" - }, - "tag": { - "desc": "搜索带有{{tag}标记的页面" - }, - "exclude_tag": { - "desc": "排除带有{{tag}标记的页" - } - }, - "search": { - "search page bodies": "按[回车]键进行全文搜索" - }, - "page_page": { - "notice": { - "version": "这不是当前版本。", - "redirected": "您将从", + "search_help": { + "title": "搜索帮助", + "and": { + "syntax help": "用空格分隔", + "desc": "在标题或正文中同时包含{{word1}、{{word2}的搜索页" + }, + "exclude": { + "desc": "排除标题或正文中包含{{word}的页" + }, + "phrase": { + "syntax help": "用双引号括起来", + "desc": "包含短语“{{phrase}”的搜索页" + }, + "prefix": { + "desc": "只搜索标题以{{path}开头的页" + }, + "exclude_prefix": { + "desc": "排除标题以{{path}开头的页" + }, + "tag": { + "desc": "搜索带有{{tag}标记的页面" + }, + "exclude_tag": { + "desc": "排除带有{{tag}标记的页" + } + }, + "search": { + "search page bodies": "按[回车]键进行全文搜索" + }, + "page_page": { + "notice": { + "version": "这不是当前版本。", + "redirected": "您将从", "redirected_period": "", - "unlinked": "将网页重定向到此网页已被删除。", - "restricted": "访问此页受到限制", - "stale": "自上次更新以来,已超过{{count}年。", + "unlinked": "将网页重定向到此网页已被删除。", + "restricted": "访问此页受到限制", + "stale": "自上次更新以来,已超过{{count}年。", "stale_plural": "自上次更新以来已过去{{count}年以上。", "no_deadline": "This page has no expiration date" } }, "page_edit": { + "input_channels": "频道名", + "theme": "主题", + "keymap": "键表", + "indent": "缩进", + "editor_config": "编辑器配置", "Show active line": "显示活动行", "auto_format_table": "自动格式化表格", "overwrite_scopes": "{{operation}和覆盖所有子体的作用域", @@ -299,12 +321,13 @@ "display_the_page_when_posting_this_comment": "Display the page when posting this comment", "no_user_found": "未找到用户名" }, - "page_api_error": { - "notfound_or_forbidden": "未找到或禁止原始页。", - "already_exists": "具有该路径的页面已存在", - "outdated": "页面已被某人更新,现在已过时。", - "user_not_admin": "仅管理员用户可以删除", - "single_deletion_empty_pages": "空的页面不能被单一删除" + "page_api_error": { + "notfound_or_forbidden": "未找到或禁止原始页。", + "already_exists": "具有该路径的页面已存在", + "outdated": "页面已被某人更新,现在已过时。", + "user_not_admin": "仅管理员用户可以删除", + "single_deletion_empty_pages": "空的页面不能被单一删除", + "complete_deletion_not_allowed_for_user": "您无权永久删除该页面" }, "page_history": { "revision_list": "修订清单", @@ -312,11 +335,11 @@ "comparing_source": "源头", "comparing_target": "目标", "comparing_revisions": "比较两者的区别", - "compare_latest":"比較最新版本", - "compare_previous":"比較以前的版本" + "compare_latest": "比較最新版本", + "compare_previous": "比較以前的版本" }, - "modal_rename": { - "label": { + "modal_rename": { + "label": { "Move/Rename page": "页面 移动/重命名", "New page name": "新建页面名称", "Failed to get subordinated pages": "Failed to get subordinated pages", @@ -327,91 +350,93 @@ "Other options": "其他选项", "Do not update metadata": "不更新元数据", "Redirect": "重定向" - }, - "help": { + }, + "help": { "redirect": "Redirect to new page if someone accesses %s", "metadata": "Remains last update user and updated date as is", "recursive": "Move/Rename children of under %s recursively" - } - }, - "Put Back": "Put back", + } + }, + "Put Back": "Put back", "Delete Completely": "Delete completely", "page_has_been_reverted": "{{path}} 已还原", - "modal_delete": { - "delete_page": "Delete page", - "deleting_page": "Deleting page", - "delete_recursively": "Delete child pages recursively.", - "delete_completely": "Delete completely", - "delete_completely_restriction": "You don't have the authority to delete pages completely.", - "recursively": "Delete children of %s recursively.", - "completely": "Delete completely instead of putting it into trash." + "modal_delete": { + "delete_page": "Delete page", + "deleting_page": "Deleting page", + "delete_recursively": "Delete child pages recursively.", + "delete_completely": "Delete completely", + "delete_completely_restriction": "You don't have the authority to delete pages completely.", + "recursively": "Delete children of %s recursively.", + "completely": "Delete completely instead of putting it into trash." }, "deleted_page": "移到了垃圾箱。", "deleted_pages": "将 {{path}} 放入垃圾箱", "deleted_pages_completely": "{{path}} 已被完全删除", "renamed_pages": "移动/重命名 {{path}}", "empty_trash": "清空垃圾", - "modal_empty": { - "empty_the_trash": "清空垃圾", + "modal_empty": { + "empty_the_trash": "清空垃圾", "empty_the_trash_button": "清空垃圾", "not_deletable_notice": "由于缺乏权限,一些页面不能被删除", - "notice": "完全删除的页面是不可恢复的。" - }, - "modal_duplicate": { - "label": { - "Duplicate page": "Duplicate page", + "notice": "完全删除的页面是不可恢复的。" + }, + "modal_duplicate": { + "label": { + "Duplicate page": "Duplicate page", "New page name": "New page name", "Failed to get subordinated pages": "Failed to get subordinated pages", - "Current page name": "Current page name", + "Current page name": "Current page name", "Recursively": "Recursively", "Duplicate without exist path": "Duplicate without exist path", - "Same page already exists": "Same page already exists" + "Same page already exists": "Same page already exists", + "Only duplicate user related pages": "Only duplicate pages you can access" }, "help": { - "recursive": "Duplicate children of under this path recursively" + "recursive": "Duplicate children of under this path recursively", + "only_inherit_user_related_groups": "If the page privilege is set to \"Only inside the group\", groups you do not belong to will lose access to the duplicated page" } }, "duplicated_pages": "{{fromPath}} 已重复", - "modal_putback": { - "label": { - "Put Back Page": "Put back page", - "recursively": "Put back recursively" - }, - "help": { - "recursively": "Put back children of under %s recursively" - } - }, - "modal_shortcuts": { - "global": { - "title": "全局快捷方式", - "Open/Close shortcut help": "打开/关闭快捷方式帮助", - "Edit Page": "编辑页面", - "Create Page": "创建页面", + "modal_putback": { + "label": { + "Put Back Page": "Put back page", + "recursively": "Put back recursively" + }, + "help": { + "recursively": "Put back children of under %s recursively" + } + }, + "modal_shortcuts": { + "global": { + "title": "全局快捷方式", + "Open/Close shortcut help": "打开/关闭快捷方式帮助", + "Edit Page": "编辑页面", + "Create Page": "创建页面", "Search": "搜索", - "Show Contributors": "显示参与者", - "Konami Code": "Konami Code", - "konami_code_url": "https://en.wikipedia.org/wiki/Konami_Code" - }, - "editor": { - "title": "编辑器快捷方式", - "Indent": "缩进", - "Outdent": "回退缩进", - "Save Page": "保存页面", - "Delete Line": "删除行" - }, - "commentform": { - "title": "注释窗体快捷方式", - "Post": "提交" - } - }, + "Show Contributors": "显示参与者", + "Konami Code": "Konami Code", + "konami_code_url": "https://en.wikipedia.org/wiki/Konami_Code" + }, + "editor": { + "title": "编辑器快捷方式", + "Indent": "缩进", + "Outdent": "回退缩进", + "Save Page": "保存页面", + "Delete Line": "删除行" + }, + "commentform": { + "title": "注释窗体快捷方式", + "Post": "提交" + } + }, "modal_resolve_conflict": { + "conflicts_with_new_body_on_server_side": "与服务器端的新正文文本冲突。 请选择或编辑页面正文以解决冲突", "file_conflicting_with_newer_remote": "此文件与较新的远程文件冲突", "resolve_conflict_message": "选择页面正文", "resolve_conflict": "解决冲突", - "resolve_and_save" : "解决冲突并保存", - "select_revision" : "选择{{revision}}", + "resolve_and_save": "解决冲突并保存", + "select_revision": "选择{{revision}}", "requested_revision": "发送的页面正文", - "origin_revision": "发送前的页面正文", "latest_revision": "最新页面正文", "selected_editable_revision": "选定的可编辑页面正文" }, @@ -431,84 +456,63 @@ "preview": "Preview", "page_not_found_in_preview": "\"{{path}}\" is not a GROWI page." }, - "toaster": { + "toaster": { "file_upload_failed": "文件上传失败", "initialize_successed": "Succeeded to initialize {{target}}", "switch_disable_link_sharing_success": "成功更新分享链接设置", - "failed_to_reset_password":"Failed to reset password", + "failed_to_reset_password": "Failed to reset password", "save_succeeded": "已成功保存", "issue_share_link": "Succeeded to issue new share link" }, - "template": { - "modal_label": { + "template": { + "modal_label": { "Select template": "选择模板", - "Create/Edit Template Page": "创建/编辑模板页", - "Create template under": "在下面创建模板页" - }, - "option_label": { - "create/edit": "创建/编辑模板页。", - "select": "选择模板页面类型" - }, - "children": { - "label": "子模板", - "desc": "仅应用于模板存在的同一级别页" - }, - "decendants": { - "label": "子代模板", - "desc": "适用于所有分散页" - } - }, - "sandbox": { - "header": "标题", - "header_x": "标题{{index}", - "block": "段落", - "block_detail": "写一段", - "empty_line": "空行", - "line_break": "换行符", - "line_break_detail": "(2空格)换行", - "typography": "排版", - "italics": "斜体", - "bold": "加粗", - "italic_bold": "斜体加粗", - "strikethrough": "删除线", - "link": "链接", - "code_highlight": "代码突出显示", - "list": "列表", - "unordered_list_x": "无序列表{{index}}", - "ordered_list_x": "有序列表{{index}}", - "task": "任务", - "task_checked": "选中的", - "task_unchecked": "未选中的", - "quote": "引用", - "quote1": "你可以写", - "quote2": "多行引用", - "quote_nested": "嵌套引用", - "table": "表格", - "image": "图片", - "alt_text": "Alt文本", - "insert_image": "插入图像", - "open_sandbox": "开放式沙箱" - }, - "hackmd": { - "hack_md": "HackMD", - "not_set_up": "HackMD is not set up.", - "used_for_not_found": "Can not use HackMD to a page that does not exist.", - "start_to_edit": "Start to edit with HackMD", - "clone_page_content": "Click to clone page content and start to edit.", - "unsaved_draft": "HackMD has unsaved draft.", - "draft_outdated": "DRAFT MAY BE OUTDATED", - "based_on_revision": "The current draft on HackMD is based on", - "view_outdated_draft": "View the outdated draft on HackMD", - "resume_to_edit": "Resume to edit with HackMD", - "discard_changes": "Discard changes of HackMD", - "integration_failed": "HackMD Integration failed", - "fail_to_connect": "GROWI client failed to connect to GROWI agent for HackMD.", - "check_configuration": "Check your configuration following the manual.", - "not_initialized": "HackmdEditor component has not initialized", - "someone_editing": "Someone editing this page on HackMD", - "this_page_has_draft": "This page has a draft on HackMD", - "need_to_associate_with_growi_to_use_hackmd_refer_to_this": "若要使用HackMD的多人同时编辑功能,请先关联HackMD和GROWI。详情请参考这里。", - "need_to_make_page": "To use HackMD, please make a new page from the built-in editor." + "Create/Edit Template Page": "创建/编辑模板页", + "Create template under": "在下面创建模板页" + }, + "option_label": { + "create/edit": "创建/编辑模板页。", + "select": "选择模板页面类型" + }, + "children": { + "label": "子模板", + "desc": "仅应用于模板存在的同一级别页" + }, + "descendants": { + "label": "子代模板", + "desc": "适用于所有分散页" + } + }, + "sandbox": { + "header": "标题", + "header_x": "标题{{index}", + "block": "段落", + "block_detail": "写一段", + "empty_line": "空行", + "line_break": "换行符", + "line_break_detail": "(2空格)换行", + "typography": "排版", + "italics": "斜体", + "bold": "加粗", + "italic_bold": "斜体加粗", + "strikethrough": "删除线", + "link": "链接", + "code_highlight": "代码突出显示", + "list": "列表", + "unordered_list_x": "无序列表{{index}}", + "ordered_list_x": "有序列表{{index}}", + "task": "任务", + "task_checked": "选中的", + "task_unchecked": "未选中的", + "quote": "引用", + "quote1": "你可以写", + "quote2": "多行引用", + "quote_nested": "嵌套引用", + "table": "表格", + "image": "图片", + "alt_text": "Alt文本", + "insert_image": "插入图像", + "open_sandbox": "开放式沙箱" }, "slack_notification": { "popover_title": "Slack Notification", @@ -518,7 +522,7 @@ "Shere this page link to public": "Shere this page link to public", "share_link_list": "Share link list", "share_link_management": "Share Link Management", - "delete_all_share_links":"Delete all share links", + "delete_all_share_links": "Delete all share links", "expire": "Expiration", "Days": "Days", "Custom": "Custom", @@ -526,41 +530,42 @@ "enter_desc": "Enter description", "Unlimited": "unlimited", "Issue": "Issue", - "share_settings" :"Share settings", - "Invalid_Number_of_Date" : "You entered invalid value", + "share_settings": "Share settings", + "Invalid_Number_of_Date": "You entered invalid value", "link_sharing_is_disabled": "链接共享已被禁用" }, - "search_result": { + "search_result": { "title": "搜索", - "result_meta": "搜索结果:", - "deletion_mode_btn_lavel": "选择并删除页面", - "cancel": "取消", - "delete": "删除", - "check_all": "全部检查", - "deletion_modal_header": "删除页", - "delete_completely": "完全删除", + "result_meta": "搜索结果:", + "deletion_mode_btn_lavel": "选择并删除页面", + "cancel": "取消", + "delete": "删除", + "check_all": "全部检查", + "deletion_modal_header": "删除页", + "delete_completely": "完全删除", "include_certain_path": "包含 {{pathToInclude}} 路径 ", "delete_all_selected_page": "删除所有", "currently_not_implemented": "这是当前未实现的功能", - "search_again" : "再次搜索", - "number_of_list_to_display" : "显示器的数量", - "page_number_unit" : "例", + "search_again": "再次搜索", + "number_of_list_to_display": "显示器的数量", + "page_number_unit": "例", + "hit_number_unit": "例", "sort_axis": { "relationScore": "按相关性排序", "createdAt": "按创建日期排序", "updatedAt": "按更新日期排序" } - }, + }, "private_legacy_pages": { "title": "私人遗留页面", "bulk_operation": "批量操作", "convert_all_selected_pages": "全部转换为新的v5兼容格式", - "input_path_to_convert": "输入一个转换页面的路径", + "input_path_to_convert": "输入一个转换页面的路径", "alert_title": "存在旧的v4兼容格式的私人网页。", "alert_desc1": "在这一页,你可以用复选框选择页面,并通过屏幕上方的批量操作按钮批量转换为新的v5兼容格式。", "nopages_title": "恭喜你。准备使用GROWI v5!", "nopages_desc1": "现在你能管理的所有页面似乎都是v5兼容的格式。", - "detail_info": "请参见 升级GROWI到v5.0.x .的详细内容。", + "detail_info": "请参见 升级GROWI到v5.0.x external_link.的详细内容。", "modal": { "title": "转换为新的v5兼容格式", "converting_pages": "转换页面", @@ -586,14 +591,14 @@ "error_duplicate_pages_found": "发现多个具有相同路径名称的页面。请重新命名或删除并重试。" } }, - "login": { + "login": { "title": "登录", - "sign_in_error": "登录错误", - "registration_successful": "注册成功。请等待管理员批准", - "Setup": "安装程序", - "enabled_ldap_has_configuration_problem":"启用了LDAP,但配置有问题。", + "sign_in_error": "登录错误", + "registration_successful": "注册成功。请等待管理员批准", + "Setup": "安装程序", + "enabled_ldap_has_configuration_problem": "启用了LDAP,但配置有问题。", "set_env_var_for_logs": "(请设置环境变量 DEBUG=crowi:service:PassportService 以获得日志。)" - }, + }, "invited": { "invited": "邀请函", "discription_heading": "创建账户", @@ -605,35 +610,35 @@ "export_page_markdown": "以Markdown格式导出页面", "export_page_pdf": "以PDF格式导出页面" }, - "message": { - "successfully_connected": "连接成功!", - "fail_to_save_access_token": "无法保存访问令牌。请再试一次。", - "fail_to_fetch_access_token": "无法获取访问令牌。请重新连接。", - "successfully_disconnected": "成功断开连接!", + "message": { + "successfully_connected": "连接成功!", + "fail_to_save_access_token": "无法保存访问令牌。请再试一次。", + "fail_to_fetch_access_token": "无法获取访问令牌。请重新连接。", + "successfully_disconnected": "成功断开连接!", "strategy_has_not_been_set_up": "{{strategy}} 尚未设置", "ldap_user_not_valid": "Ldap user is no valid", "external_account_not_exist": "查找或创建外部账户失败", - "maximum_number_of_users": "注册的用户数不能超过最大值。", - "sign_in_failure": "登录失败。", - "aws_sttings_required": "使用此功能所需的AWS设置。请询问管理员。", - "application_already_installed": "应用程序已安装。", - "email_address_could_not_be_used": "无法使用此电子邮件地址。(确保允许的电子邮件地址)", + "maximum_number_of_users": "注册的用户数不能超过最大值。", + "sign_in_failure": "登录失败。", + "aws_sttings_required": "使用此功能所需的AWS设置。请询问管理员。", + "application_already_installed": "应用程序已安装。", + "email_address_could_not_be_used": "无法使用此电子邮件地址。(确保允许的电子邮件地址)", "user_id_is_not_available": "此用户ID不可用。", - "username_should_not_be_null":"用户名不应为空。请检查管理页面上的身份验证机制设置", - "email_address_is_already_registered": "此电子邮件地址已注册。", - "can_not_register_maximum_number_of_users": "注册的用户数不能超过最大值。", - "email_settings_is_not_setup":"邮箱设置未设置,请询问管理员。", + "username_should_not_be_null": "用户名不应为空。请检查管理页面上的身份验证机制设置", + "email_address_is_already_registered": "此电子邮件地址已注册。", + "can_not_register_maximum_number_of_users": "注册的用户数不能超过最大值。", + "email_settings_is_not_setup": "邮箱设置未设置,请询问管理员。", "email_authentication_is_not_enabled": "电子邮件验证未被激活, 请询问管理员。", - "failed_to_register": "注册失败。", - "successfully_created": "已成功创建用户{{username}。", - "can_not_activate_maximum_number_of_users": "无法激活超过最大用户数的用户。", - "failed_to_activate": "无法激活。", - "unable_to_use_this_user": "无法使用此用户。", - "complete_to_install1": "完成安装GROWI!请以管理员帐户登录。", - "complete_to_install2": "完成安装GROWI!请先检查此页上的每个设置。", - "failed_to_create_admin_user": "无法创建管理用户。{{errMessage}", - "successfully_send_email_auth":"我们向 {{email}} 发送了一封电子邮件。 请点击邮件中的网址并完成注册。", - "incorrect_token_or_expired_url":"令牌不正确或 URL 已过期。", + "failed_to_register": "注册失败。", + "successfully_created": "已成功创建用户{{username}。", + "can_not_activate_maximum_number_of_users": "无法激活超过最大用户数的用户。", + "failed_to_activate": "无法激活。", + "unable_to_use_this_user": "无法使用此用户。", + "complete_to_install1": "完成安装GROWI!请以管理员帐户登录。", + "complete_to_install2": "完成安装GROWI!请先检查此页上的每个设置。", + "failed_to_create_admin_user": "无法创建管理用户。{{errMessage}", + "successfully_send_email_auth": "我们向 {{email}} 发送了一封电子邮件。 请点击邮件中的网址并完成注册。", + "incorrect_token_or_expired_url": "令牌不正确或 URL 已过期。", "user_already_logged_in": "当你登录的时候,你不能创建一个新的账户。", "registration_closed": "你无权创建一个新的账户。", "Username has invalid characters": "用户名有无效字符", @@ -647,22 +652,22 @@ "Username or E-mail has invalid characters": "用户名或电子邮件有无效的字符", "Password minimum character should be more than 6 characters": "密码最小字符应超过6个字符", "user_not_found": "未找到用户", - "provider_duplicated_username_exception": "

发生了重复用户名异常

你的 {{ failedProviderForDuplicatedUsernameException }} 认证成功了,但不能创建新的用户。参见问题#193.

" - }, - "grid_edit":{ - "create_bootstrap_4_grid":"创建Bootstrap 4网格", + "provider_duplicated_username_exception": "

cancel发生了重复用户名异常

你的 {{ failedProviderForDuplicatedUsernameException }} 认证成功了,但不能创建新的用户。参见问题#193.

" + }, + "grid_edit": { + "create_bootstrap_4_grid": "创建Bootstrap 4网格", "grid_settings": "网格设置", "grid_pattern": "网格样式", - "division":"分割", - "smart_no":"手机/不分割", - "break_point":"按画面大小分割" + "division": "分割", + "smart_no": "手机/不分割", + "break_point": "按画面大小分割" }, - "validation":{ + "validation": { "aws_region": "关于地区,请输入AWS地区名,例如:ap-east-1", "aws_custom_endpoint": "关于自定义端点,请指定以http(s)://开头的URL,链接末尾不需要添加“/”", - "failed_to_send_a_test_email":"SMTP方式测试邮件发送失败,请检查相关设定。" + "failed_to_send_a_test_email": "SMTP方式测试邮件发送失败,请检查相关设定。" }, - "forgot_password":{ + "forgot_password": { "forgot_password": "忘记密码?", "send": "发送", "return_to_login": "返回登录", @@ -675,11 +680,11 @@ "email_is_required": "电子邮件是必需的", "success_to_send_email": "我发了一封电子邮件", "feature_is_unavailable": "此功能不可用", - "incorrect_token_or_expired_url":"令牌不正确或 URL 已过期。 请通过以下链接重新发送密码重置请求", + "incorrect_token_or_expired_url": "令牌不正确或 URL 已过期。 请通过以下链接重新发送密码重置请求", "password_and_confirm_password_does_not_match": "密码和确认密码不匹配", "please_enable_mailer_alert": "密码重置功能被禁用,因为电子邮件设置尚未完成。请要求管理员完成电子邮件的设置。" }, - "emoji" :{ + "emoji": { "title": "选择一个表情符号", "search": "搜索", "clear": "重置", @@ -709,7 +714,7 @@ "6": "深色肤色" } }, - "maintenance_mode":{ + "maintenance_mode": { "maintenance_mode": "维护模式", "growi_is_under_maintenance": "GROWI正在进行维护。请等待,直到它结束。", "admin_page": "管理员页", @@ -721,10 +726,10 @@ "you_cannot_move_this_page_now": "你现在不能移动这个页面", "something_went_wrong_with_moving_page": "移动页面时出了问题" }, - "duplicated_page_alert" : { + "duplicated_page_alert": { "same_page_name_exists": "页面名称「{{pageName}}」是重复的", - "same_page_name_exists_at_path" : "在”{{path}}” 中,有不止一个名为”{{pageName}}”的页面", - "select_page_to_see" : "请在下面选择你想去的页面。" + "same_page_name_exists_at_path": "在”{{path}}” 中,有不止一个名为”{{pageName}}”的页面", + "select_page_to_see": "请在下面选择你想去的页面。" }, "user_group": { "select_group": "选择组别", @@ -740,7 +745,7 @@ "isForbidden": "无权查看的机构", "currentPageGrantLabel": "本页的权限: ", "parentPageGrantLabel": "父页的权限: ", - "docLink": "关于修改授权的更多信息,请参见此此链接" + "docLink": "关于修改授权的更多信息,请参见此此链接" }, "radio_btn": { "restrected": "只有那些知道链接的人", @@ -771,9 +776,9 @@ } } }, - "page_operation":{ + "page_operation": { "paths_recovered": "成功恢复了页面路径", - "path_recovery_failed":"路径恢复失败" + "path_recovery_failed": "路径恢复失败" }, "footer": { "bookmarks": "书签", @@ -829,5 +834,22 @@ }, "rich_attachment": { "attachment_not_be_found": "没有找到附件" + }, + "page_select_modal": { + "select_page_location": "选择页面位置" + }, + "wip_page": { + "save_as_wip": "保存为 WIP(仍在撰写中)", + "success_save_as_wip": "成功保存为 WIP 页面", + "fail_save_as_wip": "保存为 WIP 页失败", + "alert": "本页仍在编写中", + "publish_page": "发布 WIP", + "success_publish_page": "WIP 已停用", + "fail_publish_page": "无法停用 WIP" + }, + "sidebar_header": { + "show_wip_page": "显示 WIP", + "size_s": "尺寸: S", + "size_l": "尺寸: L" } } diff --git a/apps/app/resource/cdn-manifests.js b/apps/app/resource/cdn-manifests.js deleted file mode 100644 index 9a57ae1e4a1..00000000000 --- a/apps/app/resource/cdn-manifests.js +++ /dev/null @@ -1,221 +0,0 @@ -module.exports = { - js: [ - { - name: 'basis', - // eslint-disable-next-line max-len - url: 'https://cdn.jsdelivr.net/combine/npm/jquery@3.4.0,npm/popper.js@1.15.0,npm/bootstrap@4.5.0/dist/js/bootstrap.min.js,npm/scrollpos-styler@0.7.1,npm/jquery-slimscroll@1.3.8/jquery.slimscroll.min.js', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'highlight', - url: 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.13.0/build/highlight.min.js', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'highlight-addons', - url: 'https://cdn.jsdelivr.net/combine/' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/dockerfile.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/go.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/gradle.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/json.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/less.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/plaintext.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/scss.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/typescript.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/yaml.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/swift.min.js,' - + 'gh/highlightjs/cdn-release@9.13.0/build/languages/kotlin.min.js,' - + 'npm/highlightjs-line-numbers.js@2.6.0/dist/highlightjs-line-numbers.min.js', - args: { - async: true, - integrity: '', - }, - }, - { - name: 'mathjax', - url: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js', - args: { - async: true, - integrity: '', - }, - }, - { - name: 'drawio-viewer', - url: 'https://jgraph.github.io/drawio/src/main/webapp/js/viewer.min.js', - args: { - async: true, - integrity: '', - }, - }, - { - name: 'codemirror-dialog', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/addon/dialog/dialog.min.js', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-keymap-vim', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/keymap/vim.min.js', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-keymap-emacs', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/keymap/emacs.min.js', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-keymap-sublime', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/keymap/sublime.min.js', - args: { - integrity: '', - }, - }, - { - name: 'redoc-standalone', - url: 'https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js', - args: { - integrity: '', - }, - }, - ], - style: [ - { - name: 'lato', - url: 'https://fonts.googleapis.com/css?family=Lato:400,700', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'Press Start 2P', - url: 'https://fonts.googleapis.com/css?family=Press+Start+2P', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'font-awesome', - url: 'https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'themify-icons', - url: 'https://cdn.jsdelivr.net/npm/cd-themify-icons@0.0.1/index.min.css', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'simple-line-icons', - url: 'https://cdn.jsdelivr.net/npm/simple-line-icons@2.4.1/css/simple-line-icons.min.css', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'material-icons', - url: 'https://cdn.jsdelivr.net/npm/material-icons@0.3.1/iconfont/material-icons.min.css', - groups: ['basis'], - args: { - integrity: '', - }, - }, - - { - name: 'animate.css', - url: 'https://cdn.jsdelivr.net/npm/animate.css@3.7.2/animate.min.css', - groups: ['basis'], - args: { - integrity: '', - }, - }, - { - name: 'highlight-theme-github', - url: 'https://cdn.jsdelivr.net/npm/highlight.js@9.13.0/styles/github.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-dialog', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/addon/dialog/dialog.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-eclipse', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/eclipse.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-elegant', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/elegant.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-neo', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/neo.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-mdn-like', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/mdn-like.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-material', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/material.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-dracula', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/dracula.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-monokai', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/monokai.min.css', - args: { - integrity: '', - }, - }, - { - name: 'codemirror-theme-twilight', - url: 'https://cdn.jsdelivr.net/npm/codemirror@5.64.0/theme/twilight.min.css', - args: { - integrity: '', - }, - }, - ], -}; diff --git a/apps/app/resource/fonts/MaterialSymbolsOutlined-opsz,wght,FILL@20..48,300,0..1.woff2 b/apps/app/resource/fonts/MaterialSymbolsOutlined-opsz,wght,FILL@20..48,300,0..1.woff2 new file mode 100644 index 00000000000..c632f72f366 --- /dev/null +++ b/apps/app/resource/fonts/MaterialSymbolsOutlined-opsz,wght,FILL@20..48,300,0..1.woff2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b607eb2ff757a116a1bf6bfac3702b38c8d5b2d20caa36654c31e8116c299ee7 +size 868836 diff --git a/apps/app/resource/locales/en_US/sandbox-bootstrap4.md b/apps/app/resource/locales/en_US/sandbox-bootstrap4.md deleted file mode 100644 index 77b587ec287..00000000000 --- a/apps/app/resource/locales/en_US/sandbox-bootstrap4.md +++ /dev/null @@ -1,253 +0,0 @@ -# Labels - -Primary -Secondary -Success -Info -Warning -Danger -Light -Dark - -Blue -Indigo -Purple -Pink -Red -Orange -Yellow -Green -Teal -Cyan - - -# Alerts - - - - - - - - - - -# Cards - -
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
- -# Wells - -## Default well - -
Look, I'm in a well!
- -## Optional classes - -
Look, I'm in a well!
- -# Typography - -## Lead body copy - -

Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.

- -## Marked text - -You can use the mark tag to highlight text. - -## Small text - -This line of text is meant to be treated as fine print. - -## Alignment classes - -
-
-

Left aligned text.

-

Center aligned text.

-

Right aligned text.

-

Justified text.

-

No wrap text.

-
-
- -## Transformation classes - -
-
-

Lowercased text.

-

Uppercased text.

-

Capitalized text.

-
-
- - -# Helper classes - -## Contextual colors - -
-
-

Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi. Fusce pellentesque quam nec magna maximus porta.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
- -## Contextual backgrounds - -
-
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
diff --git a/apps/app/resource/locales/en_US/sandbox-bootstrap5.md b/apps/app/resource/locales/en_US/sandbox-bootstrap5.md new file mode 100644 index 00000000000..c6521325be7 --- /dev/null +++ b/apps/app/resource/locales/en_US/sandbox-bootstrap5.md @@ -0,0 +1,169 @@ +# 1. Badges + +primary + +secondary + +success + +danger + +warning + +info + +light + +dark + + +# 2. Alerts + + + + + + + + + + + + + + + + + + +# 3. Cards + +
+
Header
+
+
Primary card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Secondary card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Success card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Danger card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Warning card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Info card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Light card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Dark card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ + +# 4. Colors +## Contextual colors +

Look, I'm in a well!

+

Look, I'm in a well!

+

Look, I'm in a well!

+ +## Contextual backgrounds +

Look, I'm in a well!

+

Look, I'm in a well!

+

Look, I'm in a well!

+ + +# 5. Collapse +## Displaying content + + Show content + + +
+
+ +- Content you want to display + - Content you want to display + +
+
+ +## Hiding content + + Hide content + + +
+
+ +- Content you want to hide + - Content you want to hide + +
+
+ + +# Official docs +- [Click here for Badges details](https://getbootstrap.jp/docs/5.3/components/badge/) +- [Click here for Alerts details](https://getbootstrap.jp/docs/5.3/components/alerts/) +- [Click here for Cards details](https://getbootstrap.jp/docs/5.3/components/card/) +- [Click here for Colors details](https://getbootstrap.jp/docs/5.3/utilities/colors/) +- [Click here for Collapse details](https://getbootstrap.jp/docs/5.3/components/collapse/) \ No newline at end of file diff --git a/apps/app/resource/locales/en_US/sandbox-diagrams.md b/apps/app/resource/locales/en_US/sandbox-diagrams.md index 6321f2a9444..f40fc70d587 100644 --- a/apps/app/resource/locales/en_US/sandbox-diagrams.md +++ b/apps/app/resource/locales/en_US/sandbox-diagrams.md @@ -1,4 +1,4 @@ -# :pencil: diagrams.net(former Draw.io) +# :pencil: diagrams.net(Draw.io) See [diagrams.net](https://diagrams.net) @@ -15,7 +15,7 @@ See [diagrams.net](https://diagrams.net) ``` -## AWS diagram +## AWS configuration diagram ``` drawio 3Zhdb5swFIZ/TS4XYRswuUzSr0mtVqmtejkZOASvgJHtfO3Xz+YjgdJqiaa1SbnBvD7G9vv4IJsRmeeba8nK9E7EkI2wE29G5GKEMfa9wNyssq0VhFyvVhaSx422Fx74b2hEp1GXPAbVC9RCZJqXfTESRQGR7mlMSrHuhyUi6/dasgUMhIeIZUP1mcc6rdUA071+A3yRtj0jf1LX5KwNbmaiUhaLdUcilyMyl0LoupRv5pBZ91pf6nZX79TuBiah0G80eFIgf4S/rCfYyVhowFRBI+xFIi9FYZthr3WvVaqYGxZy2+xRsugFpCndPN7dmtu0LJtuMxZBaswE2Te4HR7ezXA3cqW3ravGi9IW883CrpsxWyt3nIuQ24BZwrNsLjIhq2CSJOBHkdGVluIFOjUxnYSOY2pWIDU30G7tPO+F4pqLwsSEQmuRmwCmynp1JHwDZoizerS2HWzeNRR1JnENIgcttyakafANuQ3aZnG7Ph37vk8d6pAgoBO3rl131k3TIO0smVZjjZGLXUd7mKbQ2Ng+dvD+M+6n7xatUqDVgXTJ8XQVGZLFlJqEeYtsUl2fRRb7Y+QEJCCIBhQ5ExL0OBPHOReyqsre6VKnRjM+Vu4dxtg9nnEkFgXXYgh6ThFBV6cHmgRj10XUo9jByA1c90vk8/TeJvQ107Bm2wNpe8fTZiX/uWg6GRD3psSZeadH/C+p7RNvTAhxzaedUuoFwbkgf34w4i3Lw5gdSNw/nnhWvf9nsiyimtWBH/TCjPSzgCP/FXH3SwC/YJqFTMGBsOnxsONtwXIRh0PK1q/Z5PRymzgni3qwfW86X7FsCS113KcSLeXKWnNhd7hQxFN7nNlnk1GuuO2yqo+ZSqtg9BYXPwogTHYuQzw49Lzy2AxELGUEnc28OXgxuQA93AF2SEjIzB5j1X/7EdYNfJqcuU/uB/nUnpfP1ijvo4xC52SUNzTK/yij8DkZ5Q+Nov/HKPO4/2lT1XX+fZHLPw== @@ -27,8 +27,7 @@ See [diagrams.net](https://diagrams.net) See [PlantUML](http://plantuml.com/). -## Sequence diagram - +## Sequence Diagram ``` plantuml @startuml skinparam sequenceArrowThickness 2 @@ -63,7 +62,6 @@ deactivate A ## Class diagram - ``` plantuml @startuml @@ -155,7 +153,7 @@ State3 --> [*] : Aborted # :pencil: Mermaid -## Pie chart diagram +## Pie graph ```mermaid %%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% @@ -167,7 +165,7 @@ pie showData "Iron" : 5 ``` -## Gantt diagram +## Gantt chart ```mermaid gantt @@ -181,7 +179,7 @@ gantt another task : 24d ``` -## Gitgraph diagram +## Git tree diagram ```mermaid %%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true}} }%% @@ -202,14 +200,13 @@ gitGraph commit ``` -## Mindmap diagram +## Mind map ```mermaid mindmap root((mindmap)) Origins Long history - ::icon(fa fa-book) Popularisation British popular psychology author Tony Buzan Research diff --git a/apps/app/resource/locales/en_US/sandbox.md b/apps/app/resource/locales/en_US/sandbox.md index a179d5081bd..bbc2f12a9ee 100644 --- a/apps/app/resource/locales/en_US/sandbox.md +++ b/apps/app/resource/locales/en_US/sandbox.md @@ -1,439 +1,158 @@ -# :memo: Table of Contents +# What is Sandbox? +- In this page, you will find tips that help you to master GROWI +- Feel free to enrich the content of your pages with the references under this hierarchy -Add `ToC` after some `#` signs. -`Table of Contents` or `Table-of-Contents` is also OK. -``` -# ToC -``` - -## ToC - -# :memo: Block Elements +# :closed_book:Headings & Paragraphs +- By inserting headings and paragraphs, you can make the text on the page easier to read ## Headers - -Add one `#` per level at the start of the line +- Add `#` before the heading text to create a heading + - Depending on the number of `#`, the typeface size of headings would be different shown in the View screen + - Check the View screen on the right side to understand the effect of headings +- The number of `#` will decide the hierarchy level and help you to organize the contents ``` -# Header 1 -## Header 2 -### Header 3 -#### Header 4 -##### Header 5 -###### Header 6 +# First-level heading +## Second-level heading +### Third-level heading +#### Forth-level heading +##### Fifth-level heading +###### Sixth-level heading ``` -### Header 3 +## Break +- Insert two half-width spaces at the end of the sentence you want to break + - You can also change this in the Setting to break the line without half-width spaces + - Change the line break setting in the `Markdown Settings` sector of the admin page -#### Header 4 +#### Without line break +Paragraph 1 +Paragraph 2 -##### Header 5 +#### With line break +Paragraph 1 +Paragraph 2 -###### Header 6 +## Block +- Paragraphs can be created by inserting a blank table in the text +- Passage can be broken into sentences and make them easier to read -## Block paragraph +#### Without paragraph +Paragraph 1 +Paragraph 2 -Paragraphs are created by inserting a newline character -A paragraph can be created by pressing Enter at the end of the previous paragraph. +#### With paragraph +Paragraph 1 -``` -paragraph1 -(Blank line) -paragraph2 -``` +Paragraph 2 -paragraph1 -paragraph2 +# :green_book: Styling Text +- Various styles can be applied to enrich the textual expression of a sentence + - These styles also can be easily applied by selecting the toolbar icon at the bottom of the Edit screen -## Br new line +## Italic +- Enclose the text with an asterisk `*` or an underscore `_`. -Add two spaces before break. -***This behavior can be modified in the options menu.*** +#### Examples +- This sentence indicates emphasis with *Italic* +- This sentence indicates emphasis with _Italic_ -``` -foo -bar(two spaces) -baz -``` +## Bold +- Enclose the text with two asterisks `*` or two underscores `_` -foo -bar -baz +#### Example +- This sentence indicates emphasis with **Bold** +- This sentence indicates emphasis with __Bold__ -## Blockquotes - -Add one `>` per level at the start of the line - -``` -> quote -> quote ->> nested quotes -``` - -> quote -> quote ->> nested quotes +## Italic & Bold +- Enclose the text with three asterisks `*` or three underscores `_` -## Code +#### Example +- This sentence indicates emphasis with ***Italic & Bold*** +- This sentence indicates emphasis witH ___Italic & Bold___ -Wrap code with three back quotes or tildes. -``` -print 'foo' -``` +# :orange_book: Insert Lists +## Bulleted List +- Insert a bulleted list by starting a line with a hyphen `-`, a plus `+`, or an asterisk `*` -### Syntax highlight and file name +#### Example +- This sentence is present in the bulleted list + - This sentence is present in the bulleted list + - This sentence is present in the bulleted list + - This sentence is present in the bulleted list +- This sentence is present in the bulleted list + - This sentence is present in the bulleted list -- corresponding [highlight.js Demo](https://highlightjs.org/static/demo/) of common category +## Numbered List +- `Number.` at the beginning of a line to insert a numbered list +- Numbered list and bulleted list can also be combined for use +#### Example +1. This sentence is present in the numbered list + 1. This sentence is present in the numbered list + 1. This sentence is present in the numbered list + 1. This sentence is present in the numbered list + - This sentence is present in the bulleted list +1. This sentence is present in the bulleted list + - This sentence is present in the bulleted list -~~~ -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } +## Task List +- Insert an unchecked checkbox list by writing `[] ` + - Check the checkbox by writing `[x]` - this._mt = new Array(624); - this.setSeed(seed); -} -``` -~~~ +#### Example +- [ ] Task 1 + - [x] Task 1-1 + - [ ] Task 1-2 +- [x] Task 2 -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } - this._mt = new Array(624); - this.setSeed(seed); -} -``` +# :blue_book: Others +## Blockquotes +- Use quoted expressions by putting `>` at the beginning of the paragraph + - Multiple quotations can be expressed by using a sequence of `>` characters +- Lists and other elements can be used together within the blockquotes -### Inline code +#### Example +> - Quotation +> - Quotation +>> Multiple quotations need to insert more `>` -Words wrapped by `` `back quotes` `` will be formatted as inline code. +## Code +- It is possible to express the code by adding it in three `` ` `` +#### Example ``` -This is `Inline Code`. -``` - -This is `Inline Code`. - -## Pre-arranged text +Add codes here +Line breaks and paragraphs can be reflected in the code -Code blocks should be preceded by four spaces or one tab. - -``` - class Foo - def foo - print 'foo' - end - end +- List also can be used in code + - List also can be used in code ``` - class Foo - def foo - print 'foo' - end - end +## Inline Code +- Enclose words in `` ` `` to make inline code -## Horizontal Line +#### Example +Here is the `inline code` -Write three underscores `_`, or asterisks`*`. +## Horizontal lines +- Insert the horizontal line with three or more consecutive asterisks `*` or underscores `_` -``` +#### Example +Below is a horizontal line *** -___ ---- -``` -*** +Below is a horizontal line ___ ---- - - - -# :memo: Typography - -## Strong Text - -### Italic - -To italicize text, add one asterisk or underscores before and after a word or phrase. - -``` -This is *Italic* . -This is _Italic_ . -``` - -This is *Italic* . -This is _Italic_ . - -### Bold - -To make text bold, add two asterisks or underscores before and after a word or phrase. - -``` -This is **bold**. -This is __bold__. -``` - -This is **bold**. -This is __bold__. - -### Bold + Italic - -To bold and italicize text, add three asterisks or underscores before and after a word or phrase. - -``` -This is ***Italic & Bold***. -This is ___Italic & Bold___. -``` - -This is ***Italic & Bold***. -This is ___Italic & Bold___. - -# :memo: Images - -You can insert `` tag using `![description](URL)`. - -```markdown -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") -``` - -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") - -The size of the image can be set by using an HTML image tag - -```html - -``` - - - - -# :memo: Link - -## Markdown standard - -You can create links using `[Display text](URL)`. - -``` -[Google](https://www.google.co.jp/) -``` - -[Google](https://www.google.co.jp/) - -## Pukiwiki like linker - -This is the most flexible linker. -Both the page description and link address can be displayed on the page. - -``` -[[./Bootstrap4]] -Example of Bootstrap4 is [[here>./Bootstrap4]] -``` - -[[./Bootstrap4]] -Example of Bootstrap4 is [[here>./Bootstrap4]] - -# :memo: Lists - -## Ul Bulleted list - -To create an unordered list, add dashes (-), asterisks (*), or plus signs (+) in front of line items. -Items can be nested using indentation. - -``` -- List1 - - List1_1 - - List1_1_1 - - List1_1_2 - - List1_2 -- List2 -- List3 -``` - -- List1 - - List1_1 - - List1_1_1 - - List1_1_2 - - List1_2 -- List2 -- List3 - -## Ol Numbered List - -To create an ordered list, add line items with numbers followed by periods. -The numbers don’t have to be in numerical order, but the list should start with the number one. - -``` -1. Number list 1 - 1. Number list 1-1 - 1. Number list 1-2 -1. Number list 2 -1. Number list 3 -``` - -1. Number list 1 - 1. Number list 1-1 - 1. Number list 1-2 -1. Number list 2 -1. Number list 3 - - -## Check list - -``` -- [ ] Task 1 - - [x] Task 1.1 - - [ ] Task 1.2 -- [x] Task2 -``` - -- [ ] Task 1 - - [x] Task 1.1 - - [ ] Task 1.2 -- [x] Task2 - - -# :memo: Table - -## Markdown Standard - -```markdown -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -OR - -Left align | Right align | Center align -:--|--:|:-: -This | This | This -column | column | column -will | will | will -be | be | be -left | right | center -aligned | aligned | aligned -``` - -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -## TSV - -~~~ -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ - -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` - -## TSV with header - -~~~ -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ - -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` - -## CSV - -~~~ -``` csv -Content Cell,Content Cell -Content Cell,Content Cell -``` -~~~ - -``` csv -Content Cell,Content Cell -Content Cell,Content Cell -``` - -## CSV with header - -~~~ -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` -~~~ - -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` - - -# :memo: Footnote - -You can write a reference [^1] to a footnote. - -Long footnotes can be written as [^longnote]. - -[^1]: A_reference_to_the_first_footnote. - -[^longnote]: An_example_of_writing_a_footnote_in_multiple_blocks. - - Subsequent paragraphs are indented and belong to the previous footnote. - - -# :memo: Emoji - -:smiley: :smile: :laughing: :innocent: :drooling_face: - -:family: :man-boy: :man-girl: :man-girl-girl: :woman-girl-girl: - -:+1: :-1: :open_hands: :raised_hands: :point_right: - -:apple: :green_apple: :strawberry: :cake: :hamburger: - -:basketball: :football: :baseball: :volleyball: :8ball: - -:hearts: :broken_heart: :heartbeat: :heartpulse: :heart_decoration: -:watch: :gear: :gem: :wrench: :email: +# :ledger: More Applications +- [Bootstrap5](/Sandbox/Bootstrap5) -# :heavy_plus_sign: More.. +- [Diagrams](/Sandbox/Diagrams) -- Want to attach Bootstrap4 Tags? - - :arrow_right: [/Sandbox/Bootstrap4] -- Want to draw Diagrams? - - :arrow_right: [/Sandbox/Diagrams] -- Want to write Math Formulas? - - :arrow_right: [/Sandbox/Math] +- [Math](/Sandbox/Math) diff --git a/apps/app/resource/locales/en_US/welcome.md b/apps/app/resource/locales/en_US/welcome.md index 6de8289fe19..7701b49744b 100644 --- a/apps/app/resource/locales/en_US/welcome.md +++ b/apps/app/resource/locales/en_US/welcome.md @@ -1,64 +1,51 @@ -# :tada: Welcome to GROWI +# :tada: Welcome to GROWI -[![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest) -[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/weseek/growi/blob/master/LICENSE) +GROWI is an internal wiki & knowledge base tool for corporations and individuals. +With GROWI, members can easily share and edit information in a company, university seminar, or circle. -GROWI is a Wiki for Individuals and Corporations | A knowledge base tool. -Knowledge in companies, university laboratories, and clubs can be easily shared and anyone can edit the page. +Casually writing down the information you know and editing it together can **reduce tacit knowledge within the team**. +Let's increase the amount of information shared on a daily base! -We can easily write what we know and edit it together, we can **simplify the tacit knowledge (knowledge which is hard to explain with words) in our team**. -Let's increase the information exchange everyday. - -### :beginner: How to create a page easily - -- Start from "**Create**" button on the upper right, or the **Pencil Icon** on the lower right. - - The page title can be edited again later, don't worry about the title. - - On title input field, it's possible to create the page's hierarchy with half-width `/` (slash). - - (Example)Try entering `/category1/category2/page-title-we-want-to-create`. -- We can create a bullet point by adding `-` at the beginning of the line. -- We can also copy and paste, drag and drop attachments such as images, PDF, Word/Excel/PowerPoint, etc. -- Once we finished, press the "**Update**" button to publish the page. - - We can also save it by `Ctrl(⌘) + S`. - -For more information: [Create page](https://docs.growi.org/en/guide/features/create_page.html) - -
-
- Tips -
-
-
    -
  • Ctrl(⌘) + "/" to show quick help.
  • -
  • We can write HTML with Bootstrap 4.
  • -
-
+ -# :anchor: For administrator 〜After you construct the site〜 - -### :arrow_right: Do you will use a Wiki with more than one person? -- :heavy_check_mark: Let's invite some members. - - [Add/invite new members to the Wiki](https://docs.growi.org/en/admin-guide/management-cookbook/user-management.html#temporary-issuance-of-a-new-user) -### :arrow_right: Work with Slack to receive page and comment notifications. -- :heavy_check_mark: [Slack integration](https://docs.growi.org/en/admin-guide/management-cookbook/slack-integration/#overview) -### :arrow_right: Are you switching from another system? -- :heavy_check_mark: It's possible to import data from other GROWI, esa.io, Qiita:Team. - - [Import Data](https://docs.growi.org/en/admin-guide/management-cookbook/import.html) - -For more information: [Admin Guide](https://docs.growi.org/en/admin-guide/) - - -# Content List Example - -We can display the content list using a table and `$lsx`. - -| All page list (First 15 pages) | [/Sandbox] List of subordinate pages | -| ----------------------------------- | ------------------------------------ | -| $lsx(/,num=15) | $lsx(/Sandbox) | - -# Slack - -join our Slack team - -We welcome newcomers joining our slack channel to help improve GROWI. -In addition to discussing development, we are also happy to answer your questions when you join. +# :beginner: What can you do with GROWI? +## 1. Knowledge Management: Create pages to store information and knowledge +- How to create and edit pages? + - You can create a new page from the "Pencil Icon" in the upper left corner of the screen + - You can edit a page you have already created by clicking "Edit" in the upper right corner of the screen +- How to manage pages? + - GROWI manages pages in a **hierarchical** structure + - Example: ` /page A/page B/page C ` + - Apart from Hierarchy, pages can also be managed with Tags + +## 2. Information Retrieval: Search information in various ways +- Keyword search +- Search using various sidebars + - Search by Page Tree + - Search by Latest Changes + - Search by Tag, and more... + +## 3. Information Sharing: Easy to share both internally and externally +- You can send the URL and permalink of the page to your company members + - User Groups can be used to manage viewing privileges among members of the company +- GROWI also allows pages to be viewed by users outside the company who do not have an account + - Let's share information with users outside your company using shared links! + +#### :bulb: Check [Sandbox](/Sandbox) to learn more on how to edit pages! + + +# :wrench: For Administrators - Once GROWI is created + +### :arrow_right: Wanna use GROWI with multiple people? +- :heavy_check_mark: Invite your members! + - [Add or invite new members to GROWI](https://docs.growi.org/en/admin-guide/management-cookbook/user-management.html#temporary-issuance-of-a-new-user) + +### :arrow_right: Not satisfied with the current look of GROWI? +- :heavy_check_mark: No worry! Let's customize the theme of GROWI! + - [Customizing GROWI Themes](/admin/customize) + +### :arrow_right: GROWI security settings are not completed? +- :heavy_check_mark: Come to update your GROWI security settings! + - [Update GROWI security settings](/admin/security) diff --git a/apps/app/resource/locales/ja_JP/sandbox-bootstrap4.md b/apps/app/resource/locales/ja_JP/sandbox-bootstrap4.md deleted file mode 100644 index 77b587ec287..00000000000 --- a/apps/app/resource/locales/ja_JP/sandbox-bootstrap4.md +++ /dev/null @@ -1,253 +0,0 @@ -# Labels - -Primary -Secondary -Success -Info -Warning -Danger -Light -Dark - -Blue -Indigo -Purple -Pink -Red -Orange -Yellow -Green -Teal -Cyan - - -# Alerts - - - - - - - - - - -# Cards - -
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
- -# Wells - -## Default well - -
Look, I'm in a well!
- -## Optional classes - -
Look, I'm in a well!
- -# Typography - -## Lead body copy - -

Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.

- -## Marked text - -You can use the mark tag to highlight text. - -## Small text - -This line of text is meant to be treated as fine print. - -## Alignment classes - -
-
-

Left aligned text.

-

Center aligned text.

-

Right aligned text.

-

Justified text.

-

No wrap text.

-
-
- -## Transformation classes - -
-
-

Lowercased text.

-

Uppercased text.

-

Capitalized text.

-
-
- - -# Helper classes - -## Contextual colors - -
-
-

Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi. Fusce pellentesque quam nec magna maximus porta.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
- -## Contextual backgrounds - -
-
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
diff --git a/apps/app/resource/locales/ja_JP/sandbox-bootstrap5.md b/apps/app/resource/locales/ja_JP/sandbox-bootstrap5.md new file mode 100644 index 00000000000..fcc70cd4766 --- /dev/null +++ b/apps/app/resource/locales/ja_JP/sandbox-bootstrap5.md @@ -0,0 +1,258 @@ +# Bootstrap について +- GROWI では [Bootstrap](https://getbootstrap.jp/docs/5.3/getting-started/introduction/)(Bootstrap5)を活用して文章やテキストの装飾をすることが可能です +- 以下にて紹介する代表的な Bootstrap をそのまま引用し活用していただくことが可能です + +# 1. バッジ(Badges) + +テキスト + +テキスト + +テキスト + +テキスト + +テキスト + +テキスト + +テキスト + +テキスト + +--- + +#### 活用例 + +- 入社してすぐにやることリスト + 1. 自己紹介文を記載してください 必須 + 2. 振込先口座情報を記載してください 必須 + 3. SNS アカウントを記載してください 任意 + +--- + + + + +# 2. アラート(Alerts) + + + + + + + + + + + + + + + + + +--- + +#### 活用例 + + + +--- + + + + +# 3. カード(Cards) + +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +
+
見出しが入ります
+
+
小見出しが入ります
+

テキストが入りますテキストが入りますテキストが入りますテキストが入ります

+
+
+ +--- + +#### 活用例 + +
+
一口コラム
+
+
日本で最初のカレーライスのレシピとは?
+

日本で初めてカレーライスの調理法が紹介されたのは、1872年(明治5年)に出版された「西洋料理指南」という本でした。

+

使用する食材として「ネギ・ショウガ・ニンニク・バター・エビ・タイ・鶏・小麦粉・カレー粉」などが挙げられています。

+
+
+ +--- + + + + +# 4. カラー(Colors) +## テキストカラー +

テキストはこちら

+

テキストはこちら

+

テキストはこちら

+ +## 背景カラー +

テキストはこちら

+

テキストはこちら

+

テキストはこちら

+ +## テキスト&背景カラー +

テキストはこちら

+

テキストはこちら

+

テキストはこちら

+ +--- + +#### 活用例 + +-

プロジェクトにアサインされる場合はスタートアップを完了させておきましょう

+-

分からないことがあればまとめて質問しましょう

+ +--- + + + + +# 5. コラプス(Collapse) +- コラプスはコンテンツの 表示 / 非表示 の切り替えの際に活用できます + +## コンテンツの表示 + + コンテンツを表示する + + +
+
+ +- 表示させたいコンテンツの内容が入ります + - 表示させたいコンテンツの内容が入ります + +
+
+ + +## コンテンツの非表示 + + コンテンツを非表示にする + + +
+
+ +- 非表示にさせたいコンテンツの内容が入ります + - 非表示にさせたいコンテンツの内容が入ります + +
+
+ + +#### 活用例 + + 最終順位を確認する! + + +
+
+ +##### 優勝者は **Bさん** です!! + +| 対象者 | 点数 | 順位 | +| ------ | ---- | ---- | +| Aさん | 80pt | 2位 | +| Bさん | 95pt | 1位 | +| Cさん | 70pt | 3位 | + +
+
+ + + + + + +# 公式ドキュメント +- [バッジの詳細はこちら](https://getbootstrap.jp/docs/5.3/components/badge/) +- [アラートの詳細はこちら](https://getbootstrap.jp/docs/5.3/components/alerts/) +- [カード詳細はこちら](https://getbootstrap.jp/docs/5.3/components/card/) +- [カラーの詳細はこちら](https://getbootstrap.jp/docs/5.3/utilities/colors/) +- [コラプスの詳細はこちら](https://getbootstrap.jp/docs/5.3/components/collapse/) diff --git a/apps/app/resource/locales/ja_JP/sandbox-diagrams.md b/apps/app/resource/locales/ja_JP/sandbox-diagrams.md index 93fa911c4aa..829965a28b9 100644 --- a/apps/app/resource/locales/ja_JP/sandbox-diagrams.md +++ b/apps/app/resource/locales/ja_JP/sandbox-diagrams.md @@ -1,31 +1,87 @@ -# :pencil: diagrams.net(旧 Draw.io) +# GROWI での図形表現について +- GROWI では各種機能を活用することで様々な図形の表現が可能です + - 各種機能の特色を活かして図形の表現をしましょう -See [diagrams.net](https://diagrams.net) +# :pencil: Diagrams.net(旧 Draw.io) +- 図形の挿入時に全般的にご利用いただきやすい図形の挿入方法となります + - サービスの詳細は [こちら](https://www.drawio.com/) をご確認ください +- Edit 画面下部のツールバーより専用の編集画面を用いて図形を編集することが可能です -## アクティビティ図 +## 組織図 +``` drawio +7ZpRk5owEMc/TV47hBBIHkG59qUznfGh7SOVqEzROIin9tM3kaAk4J0noB3LeDNHlrDI/7dLNjEAjZb7z1m0XnzlMUuBbcV7gMbAtm3LgeKftBwKC7QIKSzzLImV7WyYJH9Y2VFZt0nMNlrHnPM0T9a6ccpXKzbNNVuUZXynd5vxVL/rOpqzmmEyjdK69XsS54vCSmzvbP/CkvmivDN0aXFmGZWd1ZNsFlHMdxUTCgEaZZznxdFyP2KpVK/Upbju5cLZ0xfL2Cq/5gK7uOA1Srfq2UCIAXkB1AWhBwIP+Ja0BGMQUBA6IBgB6qvvnh9KQTK+XcVM+rQACnaLJGeTdTSVZ3ciBoRtkS9T0YLicJak6YinPDtei+KIkdlU2Dd5xn+zyhl3StivmbyCr/KJupul2pV+diA/wl5/eiXIK8tytq+YlBqfGV+yPDuILuoschQqFZs2UaR2Z9CwjMNFBbKjbJGKrfnJ9Vl+caAIXMDn1XGYUrNV7MsQFq0VXzFdWp2DUCE7/JCNT7hs/lQ9j43xvtpzfFCtAkQZ2agJjWfJzxsodGSXuORRNme5Foos1nKvDqoCAjdwKG0ZS6M8edUztgmOusM3nogvd4oDx3K0OHCIwXfDt9mUqauqGWY6IrojDA1HhQY1R8dYOT32deFDOg2f+4XBP8LcRbaGCnnwRubWO446ZE4H5u2Yw27y3HQkdOqLedOoPTD/yLudgjfT81rm0HvHUYfM0cC8DXNY5nXbPDcd9ZjnsLk6F6V5IKpzF/gY+ONaFHyoFq9RN6rxaoQ8sAp3rDtW4Q0jqpgK+SHwoTygFiDuU6oObedxqkPcIDsBPpJzz5ACkXa+9ZSyY++BstvuMK60GVfEq6qjccVMPtNRh7XEMGdoV0vYWEOFS0E/zlx35Hi0L+bIGpi3y3PUDXPTUZ/M4cC81TwRG1UouXGeWCtnTUcdMh/WBloxR1if3mF043huOupxPEfD2kDLPCfdMDcd9cncGZi3WvclZrl947u9Nnvr8d3eMEUemF/PHHtG3X5rnpuO+szzYX7eMs9RN8xNRz0yb9gFIHde+PKvOCBBLQieYSWMXKi9KqFC+1p+bJgfhy4IEKD4uCUmAJQ+peiQwsep3jBDlb9wBMdFXywX2gmWHKgD/JfjMryI//ApOSBjx8ldOTTMIGT0Y7kDTHAQqtPn/M3DgQ9UvV7D+8fNdp78aU/KboHAeUrZsbHV5q6y10uq4D+R3XXuJrtonrexFkXQeTcwCv8C +``` +## 市場分析 ``` drawio -7Vxbc6M2FP41fnQGcTM8ZnNpH7YzO5PddvuIjWyzixHF8sbur6+EJUBIvoFEE8eeycQcSVzO+fjORZJHzsNq+1sR5cs/UAzTkW3F25HzOLJtEDiA/KOSHZMA19tLFkUSM1kteEn+hUxoMekmieFa6IgRSnGSi8IZyjI4w4IsKgr0Knabo1S8ah4toCR4mUWpLP0rifFyLw3sSS3/HSaLJb8y8MN9yyrindmTrJdRjF4bIudp5DwUCOH9t9X2AaZUe1wv+3HPB1qrGytghs8Z4Ab2fsivKN2wp2N3hnf8cckQolly8GmJVymRAfKV3HlO29c4KvALjjBtnydp+oBSVJQDHYt8fJ92xgX6CRstz88BaaMjUIafo1WSUix8jZZoFTEpMztw2bFqNLt3WGC4PagBUOmVIBKiFcTFjnThAxxmNQZGj53htTasw4y1bNiUyyIGpUV14lrb5AtT+CHlO2coPybQY4eowEu0QFmUPtXSplGoJhKC0/s0WWRENkUYoxVpgFl8T4FPT5LDbC9hGg4MGogYodh9J0LrzuOHf9PDynj0+Y6bjqgDbYoZbCGW4G4BMRe6aiMXMI1w8ku8gspmbOgXlJBr1+DwbAEcwGudYn8TbFRteaLraNfoltMOawkb1Y2eCRdXARc/xUz/Am78fzaIN4zXpaXuSQdg59u6kXxb0P+f0YJeJ8OI6nUJ6Z3nOT83ua/96fedJYQWaJPFMGYQfF0mGL7kUWmvV+IARIRGxYzhxrVkwogjGMxnKjz6swBO513xWBGRBsIIW5DgTNAgDGArGMPVwhjejTEuZwxXxRj+IIwhOYqLGePM64CWo7+sP/myv4Pu5OQbIqcHVBQ0iDvARs6zTEgEctPN+jQZvUP2AeAAvhr0Exhjn4lk4wz145+I8U4K5/ht05FARiU3daUjX0VH4VGzj9mJerKTHbTQ4/Vlp17xTCDBaQfXRvGEUf4mwKTPt6nAFB7nEE1garsUp7erk70X74Pm8zXEvQEXGvJRj8k6T8uHggRXxS1yVuLOtsVUW+W7zIXOoaUw/nWGzkD2VXCb4O/CUV/iCVVezEwa7ri6meaQexQBCjzNQXII+hMQUBHQ0zZZ4ySjaTw/4bTgjctompDHppHymbz0gQJoB7jDBdC8dvCBAuiO9MLfFDGu8QYJkicthPjuWWzTiRDkCvAtBNYClQPlHbMhsOueBxUz+VSooT7si97FmlU2rIXOfF5aU/JClevhgm9r2AyGp+2OpxwRoXksgruA5GajadmBYoZpjvT2Po28Rwr/DUZrhsRz34Y18XDEe36lB49j9wCe1ag35accR2QhW3JTnsJN2VrclFxlfsowNaUVkb8MvtKr0qhCDh0GT2mMJSvByTjBYLIiV1PrHJPFc1er+tYMixMOqvnJUe+boYy621rXlqhXdZ5VTpjTiXLuc9lpStlzQu+GFRgVXrnR/gNivGN2ozxHRHU48BmV9AV6R9mHfX9XD60sUgVqEOh2ySajN7mAqSedu4/jimcP5HNvJ50bKFFzPV+iAXOJWngZC4BzWaAR/06kAHhIitAc4FeW/7FZ5VxNxMlwCRvpdCYRz1KSiJZZ3EvrRK7f8lATt4kumZOCo/1715U8y9ICV9AAayM/U8F1aI/23uBa+YazChhm4eoAMZR1J75m+J0sa16URpYVEIMJIkv9ZrDMaeSccJXEcVlUSaMpTD9Fs5+L8tVp4GdefszliWzlKnuOUZXWNVHH3vrDNQ7rLnBaFW1NdY9x+6yOeAYt03WeZRtywtdAXCYKaQrK8sBkkDDds42F6Z6lWmbbnZ5oxf7GTqfZyT7KTtadNeHL4vWSUytvGIdGuElDrVWZ+j0s4ewnvVL24TI8Lxwuw/Msz1DIfF3ORXAtfVa98Zqy4FwsM4twnXYF0THoXORK7bc8ptthrr9Q61otPQ9ZI/cseTWqzuqbXHebodWq1MyV83J7AnxYXj5ZUzUUrJ1k/9Olgg+TfHTzAVXQJPqAEyufrTvXBWKgyPeBas5BfF5hfqsLWJmueuzWpIs8Ou/V1BHytXZb+v5EohZT2y09DptzV4D2Z4Hbu9561/sWE8639a0kOfofkn5wsiTpe1q4e9xK8s1UIHmCeowxOLWmSdYm3fKN5L8QYGAfvM6gr50zuY4c9CljeaCFmq91J7yqXivPpHXkWA7PIXJqt4UPD+gKljq9mK5hz33WlKgtVt7r5i+wSMjjUCq/mon9rnHARIHRPXAHn7a3RQj7QPM8KFDtzr8FHcaDjgO7jhrzoD5fQ9g37BAX5Y45A2sOO07upX/nNZDDq6BuHNqXQ2vUh47jCXDtVje5fLlJi2b946uj3OBof5GWTVVWgIZisnJr8J9JuYqT4rVaM3/bHXx61bdny5Uhc3MJQFV1vtb8Q9N6keqdEdMPQ7/E1Z4r5j/qM0D6QQ7rX+Tbd69/2NB5+g8= +7Vpbd+I2EP41esweW/L10XZg+9DtSTftafdRYAHayhY1JkB+fSVZMr4lMTTsZjdwOCB9M7rNfNKMDAAl2f5jgderTzwlDEAr3QN0CyCElmOLL4kcKsS2gqBClgVNNXYE7ukjMYoa3dKUbFqKJeespOs2OOd5TuZlC8NFwXdttQVn7VHXeEl6wP0csz76F03LVYUG0D/ivxC6XJmRbS+sJBk2ynolmxVO+a4BoQlAScF5WZWyfUKYtJ6xS9Vu+oS0nlhB8nJUA93iAbOtXpyeWHkwqy34Nk+JbGABFO9WtCT3azyX0p1wsMBWZcZEzRbFBWUs4YwXop6SBd4yMY94Uxb8H2JwAJFFAul0FPcnbGZEipLsG5BewEfCM1IWB6Gipb42u2YT9LVtd0fXeKHGVg23oECDWNNhWXd9tJgoaKMNGzB42X4kTyNJOlHLeU7a9mobl+xp+bcsf/BdXf3SEN3um5WDrlTGNUREQ+b21Es2zMX6qhGga+pf9FxU5TiGqplBFjwv7/WaBlimoQ3fFnO9bE9vTFwsidZyK4ikre3Vd2zDc+6A4wxWEIZL+tDelEPO1CPccSrmW/MG2U6LOI7f4UO1Gt2quYm6HXmdjmCno8oGvY4Ut+plj6JbeCG6wfF0a1DIP4lCp/D0dLr5b55uFmyxxLU7XYymm9+hG7oY3UzAfWW+2U2yfXBH0q3JNd3qu7Ft4HDz3xbbYDsquva5h9u3Y5s7QDZP5Q/SQS3Wef9uuRHcbFSCGAkF21vvVVJh5CoJNA4/gsjxU7xYtPQWeN7u+w+aiSQTWr+Rnfj8zDOcNxt4S/2NM5kD5bON/Ep4tsb5AUymIE6ASHEmAQh8EEVgIj4dEE+MKDSLE2ap1lf3qOCUPoxaMuotud2Ptt3ZZvias0d6502RF/mfZixezFYPT4+2WUsrjZi2+8K0Z0UXEXaqeu/Bp5iP0ZzcmA1XzUQQ2n12Lq/Z12gqG79aSrBrjJLzIsOsy/NzHTdBIEAgjoeYKkQ2iETBlZSNfY3EU0PiqRHZR9HzfhGwMue7tHBlz7BhWFGA6phQSOAZUSTdITRDF0yULyJbK4dQ2lxYPjTuCI3xI9M8cEzPZtDgpf0y7Jdx6GtdGMWJNFWv4WitJQzPCLvjG1pSngvZXARqIpRieWWk4pb+a0cho2kq5xZjRpcSYGRRNvQjDdd6/dxhXIYw/s4K/bAVVZHdv7RCbyA9sLtx/JxLq/czBNrtphQrLxqRNpSbJPLl9hBbK4I/WqSdeo/xFH++tfFhdfMnm9Pf1+trpP0B4sBIxw3HAXGio8apLw77SL71sZ0M0bpWboaRs8/4d2Lzp8w40TpBrZxov9ReiKbPuqyKtLDnjsQUYDca/1+XXcPyZcKybbXDsmsNhWX3QmHZ/xnCsrj/kpKWvBmYxX0iBrEnt15oKeQamK+B+S0GiT5THYmH3tCl2Je3sFjdjsMEREFbFKl+PBAr8HhfrkKLrwtRXYAvePNdB++T/HLphxXX6HuZ6Ou4zneMvjbsh19JE0u+JXEClciJ7NECsaOewQTqgY0HwolkZSeflE9uVCFK2oklkj3owrSbc0aGrWEkptwf5DVpNbMIIt4Qreqf55WLq/9f2P4FXN797R72PT742717usNF9fi/iurXiePfU9DkPw== ``` -## クラス図 +## AWS 構成図 +``` drawio +3Zhdb5swFIZ/TS4XYRswuUzSr0mtVqmtejkZOASvgJHtfO3Xz+YjgdJqiaa1SbnBvD7G9vv4IJsRmeeba8nK9E7EkI2wE29G5GKEMfa9wNyssq0VhFyvVhaSx422Fx74b2hEp1GXPAbVC9RCZJqXfTESRQGR7mlMSrHuhyUi6/dasgUMhIeIZUP1mcc6rdUA071+A3yRtj0jf1LX5KwNbmaiUhaLdUcilyMyl0LoupRv5pBZ91pf6nZX79TuBiah0G80eFIgf4S/rCfYyVhowFRBI+xFIi9FYZthr3WvVaqYGxZy2+xRsugFpCndPN7dmtu0LJtuMxZBaswE2Te4HR7ezXA3cqW3ravGi9IW883CrpsxWyt3nIuQ24BZwrNsLjIhq2CSJOBHkdGVluIFOjUxnYSOY2pWIDU30G7tPO+F4pqLwsSEQmuRmwCmynp1JHwDZoizerS2HWzeNRR1JnENIgcttyakafANuQ3aZnG7Ph37vk8d6pAgoBO3rl131k3TIO0smVZjjZGLXUd7mKbQ2Ng+dvD+M+6n7xatUqDVgXTJ8XQVGZLFlJqEeYtsUl2fRRb7Y+QEJCCIBhQ5ExL0OBPHOReyqsre6VKnRjM+Vu4dxtg9nnEkFgXXYgh6ThFBV6cHmgRj10XUo9jByA1c90vk8/TeJvQ107Bm2wNpe8fTZiX/uWg6GRD3psSZeadH/C+p7RNvTAhxzaedUuoFwbkgf34w4i3Lw5gdSNw/nnhWvf9nsiyimtWBH/TCjPSzgCP/FXH3SwC/YJqFTMGBsOnxsONtwXIRh0PK1q/Z5PRymzgni3qwfW86X7FsCS113KcSLeXKWnNhd7hQxFN7nNlnk1GuuO2yqo+ZSqtg9BYXPwogTHYuQzw49Lzy2AxELGUEnc28OXgxuQA93AF2SEjIzB5j1X/7EdYNfJqcuU/uB/nUnpfP1ijvo4xC52SUNzTK/yij8DkZ5Q+Nov/HKPO4/2lT1XX+fZHLPw== +``` +## 画像の編集 ``` drawio -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 ``` -## AWS 構成図 +# :pencil: Mermaid +- Mermaidとは、Markdownテキストでグラフを作成できるダイアグラムツールです + - サービスの詳細は [こちら](https://mermaid.js.org/) をご確認ください -``` drawio -3Zhdb5swFIZ/TS4XYRswuUzSr0mtVqmtejkZOASvgJHtfO3Xz+YjgdJqiaa1SbnBvD7G9vv4IJsRmeeba8nK9E7EkI2wE29G5GKEMfa9wNyssq0VhFyvVhaSx422Fx74b2hEp1GXPAbVC9RCZJqXfTESRQGR7mlMSrHuhyUi6/dasgUMhIeIZUP1mcc6rdUA071+A3yRtj0jf1LX5KwNbmaiUhaLdUcilyMyl0LoupRv5pBZ91pf6nZX79TuBiah0G80eFIgf4S/rCfYyVhowFRBI+xFIi9FYZthr3WvVaqYGxZy2+xRsugFpCndPN7dmtu0LJtuMxZBaswE2Te4HR7ezXA3cqW3ravGi9IW883CrpsxWyt3nIuQ24BZwrNsLjIhq2CSJOBHkdGVluIFOjUxnYSOY2pWIDU30G7tPO+F4pqLwsSEQmuRmwCmynp1JHwDZoizerS2HWzeNRR1JnENIgcttyakafANuQ3aZnG7Ph37vk8d6pAgoBO3rl131k3TIO0smVZjjZGLXUd7mKbQ2Ng+dvD+M+6n7xatUqDVgXTJ8XQVGZLFlJqEeYtsUl2fRRb7Y+QEJCCIBhQ5ExL0OBPHOReyqsre6VKnRjM+Vu4dxtg9nnEkFgXXYgh6ThFBV6cHmgRj10XUo9jByA1c90vk8/TeJvQ107Bm2wNpe8fTZiX/uWg6GRD3psSZeadH/C+p7RNvTAhxzaedUuoFwbkgf34w4i3Lw5gdSNw/nnhWvf9nsiyimtWBH/TCjPSzgCP/FXH3SwC/YJqFTMGBsOnxsONtwXIRh0PK1q/Z5PRymzgni3qwfW86X7FsCS113KcSLeXKWnNhd7hQxFN7nNlnk1GuuO2yqo+ZSqtg9BYXPwogTHYuQzw49Lzy2AxELGUEnc28OXgxuQA93AF2SEjIzB5j1X/7EdYNfJqcuU/uB/nUnpfP1ijvo4xC52SUNzTK/yij8DkZ5Q+Nov/HKPO4/2lT1XX+fZHLPw== +## 円グラフ + +```mermaid +%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% +pie showData + title プロジェクトメンバーにおける年代別構成比 + "20代" : 15 + "30代" : 36 + "40代~" : 22 ``` +## ガントチャート +```mermaid +gantt + title プロジェクト進捗状況 + dateFormat YYYY-MM-DD + section Tanaka + タスクA :a1, 2014-01-01, 30d + タスクB :after a1 , 20d + section Yamada + タスクC :2014-01-12 , 12d + タスクD : 24d +``` -# :pencil: PlantUML +## マインドマップ + +```mermaid +mindmap + root((mindmap)) + Origins + Long history + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness
and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + Pen and paper + Mermaid +``` -See [PlantUML](http://plantuml.com/). + +# :pencil: PlantUML +- PlantUML はオープンソースの UML 描画ツールです + - サービスの詳細は [こちら](https://plantuml.com/) をご確認ください ## シーケンス図 ``` plantuml @@ -60,7 +116,6 @@ deactivate A @enduml ``` - ## クラス図 ``` plantuml @startuml @@ -86,7 +141,6 @@ BaseClass <|-- net.unused.Person @enduml ``` - ## コンポーネント図 ``` plantuml @startuml @@ -123,7 +177,6 @@ database "MySql" { @enduml ``` - ## ステート図 ``` plantuml @@ -148,76 +201,3 @@ State3 --> [*] : Aborted @enduml ``` - - - -# :pencil: Mermaid - -## 円グラフ - -```mermaid -%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% -pie showData - title Key elements in Product X - "Calcium" : 42.96 - "Potassium" : 50.05 - "Magnesium" : 10.01 - "Iron" : 5 -``` - -## ガントチャート - -```mermaid -gantt - title A Gantt Diagram - dateFormat YYYY-MM-DD - section Section - A task :a1, 2014-01-01, 30d - Another task :after a1 , 20d - section Another - Task in sec :2014-01-12 , 12d - another task : 24d -``` - -## Git 樹形図 - -```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true}} }%% -gitGraph - commit id: "feat(api): ..." - commit id: "a" - commit id: "b" - commit id: "fix(client): .extra long label.." - branch c2 - commit id: "feat(modules): ..." - commit id: "test(client): ..." - checkout main - commit id: "fix(api): ..." - commit id: "ci: ..." - branch b1 - commit - branch b2 - commit -``` - -## マインドマップ - -```mermaid -mindmap - root((mindmap)) - Origins - Long history - ::icon(fa fa-book) - Popularisation - British popular psychology author Tony Buzan - Research - On effectiveness
and features - On Automatic creation - Uses - Creative techniques - Strategic planning - Argument mapping - Tools - Pen and paper - Mermaid -``` \ No newline at end of file diff --git a/apps/app/resource/locales/ja_JP/sandbox-math.md b/apps/app/resource/locales/ja_JP/sandbox-math.md index 59db436821c..215f53b2854 100644 --- a/apps/app/resource/locales/ja_JP/sandbox-math.md +++ b/apps/app/resource/locales/ja_JP/sandbox-math.md @@ -1,10 +1,10 @@ -# :pencil: Math - -See [KaTeX](https://katex.org/). +# Math について +- GROWI では [MathJax](https://www.mathjax.org/) を活用して文章内に数式を挿入することが可能です +- 以下にて紹介する代表的な MathJax の記法をそのまま引用し活用することが可能です ## Inline Formula -When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$ and they are +When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$ and they are $$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ ## The Lorenz Equations diff --git a/apps/app/resource/locales/ja_JP/sandbox.md b/apps/app/resource/locales/ja_JP/sandbox.md index ffd2dbfd1d2..31803fb19cb 100644 --- a/apps/app/resource/locales/ja_JP/sandbox.md +++ b/apps/app/resource/locales/ja_JP/sandbox.md @@ -1,19 +1,16 @@ -# :memo: 目次 +# Sandbox(サンドボックス)とは +- この階層下では、GROWI をより便利に活用するための活用術や活用ヒントを掲載しています +- この階層下のページ内容を組織内で自由に書き換えて GROWI の理解度を深めるために活用しましょう! -いくつかの `#` 記号に続けて `ToC` という文字列を記述します。 -`Table of Contents` または `Table-of-Contents` でも構いません。 -``` -# ToC -``` - -## ToC +# :memo:見出しや段落 +- 見出しや段落を挿入することで、ページ内の文章にメリハリがつき読みやすい文章を作成することが可能です -# :memo: Block Elements - -## Headers 見出し - -先頭に`#`をレベルの数だけ記述します。 +## 見出し(Headers) +- 行頭に `#` をレベルの数だけ記述することで見出しを作成することが可能です + - 各見出しに応じて View 画面に表示される際のデザインも異なります + - 各見出しに応じて View 画面右側に表示される目次が生成されます +- このページ内にもたくさんの見出しが活用されており、`#` の数に応じて内容をグルーピングすることで可能です ``` # 見出し1 @@ -24,382 +21,253 @@ ###### 見出し6 ``` -### 見出し3 - -#### 見出し4 - -##### 見出し5 - -###### 見出し6 +## 改行(Br) +- 改行したい文章の行末に半角スペースを2つ挿入することで改行をすることができます + - こちらの挙動は、設定画面から半角スペースなしで改行が反映されるように設定を変更することが可能です + - 「マークダウン設定_Line Break設定(/admin/markdown)」から変更が可能です -## Block 段落 +#### 改行がない場合 +文章 1 の内容が入ります +文章 2 の内容が入ります -空白行を挟むことで段落となります。 +#### 改行がある場合 +文章 1 の内容が入ります +文章 2 の内容が入ります -``` -段落1 -(空行) -段落2 -``` +## 段落(Block) +- 文章内で空白表を挿入することで段落を作成することが可能です +- 段落を作成することで文章の節目を作成し読みやすい文章を作成することができます -段落1 +#### 段落がない場合 +文章 1 の内容が入ります +文章 2 の内容が入ります -段落2 +#### 段落がある場合 +文章 1 の内容が入ります -## Br 改行 +文章 2 の内容が入ります -改行の前に半角スペース``を2つ記述します。 -***この挙動は、オプションで変更可能です*** -``` -hoge -fuga(スペース2つ) -piyo -``` +# :memo:文字の強調 +- 各種記述方法を適用させることで文内の文字の表現を豊かにすることが可能です + - これらの表現は Edit 画面下部のツールバーから該当のアイコンを選択することで簡単に適用させることも可能です -hoge -fuga -piyo +## 斜体(Italic) +- アスタリスク `*` もしくはアンダースコア `_` 1つで該当の文字列を囲みます -## Blockquotes 引用 +#### 活用例 +- この文章は *斜体が適用* されます +- この文章は _斜体が適用_ されます -先頭に`>`を記述します。ネストは`>`を多重に記述します。 +## 太字(Bold) +- アスタリスク `*` もしくはアンダースコア `_` 2つで該当の文字列を囲みます -``` -> 引用 -> 引用 ->> 多重引用 -``` +#### 活用例 +- この文章は **強調が適用** されます +- この文章は __強調が適用__ されます -> 引用 -> 引用 ->> 多重引用 +## 斜体 & 太字(Italic & Bold) +- アスタリスク `*` もしくはアンダースコア `_` 3つで該当の文字列を囲みます -## Code コード +#### 活用例 +- この文章は ***斜体 & 太字が適用*** されます +- この文章は ___斜体 & 太字が適用___ されます -`` `バッククオート` `` 3つ、あるいはチルダ`~`3つで囲みます。 -``` -print 'hoge' -``` +# :memo:リストの挿入 +## 箇条書きリスト +- ハイフン `-`、プラス `+`、アスタリスク `*` を行頭に記述することで、箇条書きのリストを挿入することでができます + - タブを活用することで前の行のリストに紐づくリストを挿入することも可能です -### シンタックスハイライトとファイル名 - -- [highlight.js Demo](https://highlightjs.org/static/demo/) の common カテゴリ内の言語に対応しています +#### 活用例 +- この文章は箇条書きリストで表現しています + - この文章は箇条書きリストで表現しています + - この文章は箇条書きリストで表現しています + - この文章は箇条書きリストで表現しています +- この文章は箇条書きリストで表現しています + - この文章は箇条書きリストで表現しています +## 番号付きリスト +- `番号.` を行頭に記述することで、番号付きのリストを挿入することができます + - タブを活用することで前の行のリストに紐づくリストを挿入することも可能です +- 番号付きリストと箇条書きリストを組み合わせて活用することも可能です -~~~ -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } - - this._mt = new Array(624); - this.setSeed(seed); -} -``` -~~~ - -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } - - this._mt = new Array(624); - this.setSeed(seed); -} -``` +#### 活用例 +1. この文章は番号付きリストで表現しています + 1. この文章は番号付きリストで表現しています + 1. この文章は番号付きリストで表現しています + 1. この文章は番号付きリストで表現しています + - この文章は箇条書きリストで表現しています +1. この文章は箇条書きリストで表現しています + - この文章は箇条書きリストで表現しています -### インラインコード - -`` `バッククオート` `` で単語を囲むとインラインコードになります。 - -``` -これは `インラインコード`です。 -``` - -これは `インラインコード`です。 - -## pre 整形済みテキスト - -半角スペース4個もしくはタブで、コードブロックをpre表示できます - -``` - class Hoge - def hoge - print 'hoge' - end - end -``` - - class Hoge - def hoge - print 'hoge' - end - end - -## Hr 水平線 - -アンダースコア`_` 、アスタリスク`*`を3つ以上連続して記述します。 - -``` -*** -___ ---- -``` - -*** -___ ---- - - - -# :memo: Typography - -## 強調 - -### em - -アスタリスク`*`もしくはアンダースコア`_`1個で文字列を囲みます。 +## タスクリスト +- `[] ` を記述することでリストに対して未チェックのチェックボックスを挿入することができます + - `[x] ` を記述することでチェック済みのチェックボックスを挿入することができます -``` -これは *イタリック* です -これは _イタリック_ です -``` +#### 活用例 +- [ ] タスク 1 + - [x] タスク 1-1 + - [ ] タスク 1-2 +- [x] タスク2 -これは *イタリック* です -これは _イタリック_ です -### strong +# :memo:表の挿入 +## Markdown 標準 +- Markdown で記載できる標準的な形式の表です -アスタリスク`*`もしくはアンダースコア`_`2個で文字列を囲みます。 +#### 活用例 +| 左揃え | 右揃え | 中央揃え | +| :------------------- | -------------------: | :--------------------: | +| この列は | この列は | この列は | +| 左揃えで表示されます | 右揃えで表示されます | 中央揃えで表示されます | +## TSV +#### 活用例 +``` tsv +10:00 集合 +10:20 移動 ``` -これは **ボールド** です -これは __ボールド__ です -``` - -これは **ボールド** です -これは __ボールド__ です -### em + strong - -アスタリスク`*`もしくはアンダースコア`_`3個で文字列を囲みます。 - -``` -これは ***イタリック&ボールド*** です -これは ___イタリック&ボールド___ です +## TSV(ヘッダー付き) +#### 活用例 +``` tsv-h +時間 行動 +10:00 集合 +10:20 移動 ``` -これは ***イタリック&ボールド*** です -これは ___イタリック&ボールド___ です - -# :memo: Images - -`![Alt文字列](URL)` で``タグを挿入できます。 - -```markdown -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") +## CSV +#### 活用例 +``` csv +11:00,MTG +12:00,昼食 ``` -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") - -画像の大きさなどの指定をする場合はimgタグを使用します。 - -```html - +## CSV(ヘッダー付き) +#### 活用例 +``` csv-h +時間,行動 +11:00,MTG +12:00,昼食 ``` - - - -# :memo: Link +# :memo:リンクの挿入 ## Markdown 標準 +- Markdown で記載できる標準的な形式のリンクです +- `[表示されるテキスト](リンク先のURL)`でリンクに変換されます -`[表示テキスト](URL)`でリンクに変換されます。 - -``` -[Google](https://www.google.co.jp/) -``` - +#### 活用例 [Google](https://www.google.co.jp/) ## Pukiwiki like linker +- もっとも柔軟なリンクの形式です +- 記述中のページを基点とした相対リンクと、表示テキストに対するリンクを同時に実現できます -最も柔軟な Linker です。 -記述中のページを基点とした相対リンクと、表示テキストに対するリンクを同時に実現できます。 +#### 活用例 +Bootstrap によるページの装飾方法の記述方法は [[こちらをご確認ください>./Bootstrap5]] -``` -[[./Bootstrap4]] -Bootstrap4のExampleは[[こちら>./Bootstrap4]] -``` -[[./Bootstrap4]] -Bootstrap4のExampleは[[こちら>./Bootstrap4]] +# :memo:画像の挿入 +## 画像(Images)の挿入 +- `![Alt文字列](URL)` で``タグを挿入できます -# :memo: Lists +#### 活用例 +![Minion](https://octodex.github.com/images/minion.png) -## Ul 箇条書きリスト +## 画像のサイズ指定 +- 画像の大きさなどを指定する場合はimgタグを使用します -ハイフン`-`、プラス`+`、アスタリスク`*`のいずれかを先頭に記述します。 -ネストはタブで表現します。 +#### 活用例 + -``` -- リスト1 - - リスト1_1 - - リスト1_1_1 - - リスト1_1_2 - - リスト1_2 -- リスト2 -- リスト3 -``` -- リスト1 - - リスト1_1 - - リスト1_1_1 - - リスト1_1_2 - - リスト1_2 -- リスト2 -- リスト3 +# :memo:コンテンツやページの表示 +## 目次(ToC) +- いくつかの `#` 記号に続けて `ToC` を記述することでページ内に目次を生成することができます + - `ToC` は `Table of Contents` または `Table-of-Contents` でも適用されます +- 生成される目次は、ページ内で `ToC` を記述した以降の部分の目次となります -## Ol 番号付きリスト +#### 活用例 +##### ToC -`番号.`を先頭に記述します。ネストはタブで表現します。 -番号は自動的に採番されるため、すべての行を1.と記述するのがお勧めです。 +## 配下ページの表示(lsx) +- ページ内に `$lsx()` を記述することで配下に作成されているページを表示することができます +- 各種オプションを指定することで表示される配下ページを操作することができます + - lsx の詳細は [GROWI 公式ドキュメント](https://docs.growi.org/ja/guide/features/lsx.html) をご確認ください -``` -1. 番号付きリスト1 - 1. 番号付きリスト1-1 - 1. 番号付きリスト1-2 -1. 番号付きリスト2 -1. 番号付きリスト3 -``` +#### 活用例 +$lsx() -1. 番号付きリスト1 - 1. 番号付きリスト1-1 - 1. 番号付きリスト1-2 -1. 番号付きリスト2 -1. 番号付きリスト3 +# :memo:その他の基本的な表現 +## 引用(Blockquotes) +- 行頭に `>` を記述することで引用表現をすることが可能です + - 多重引用の際は `>` を複数個連続で記述することで表現が可能です +- 引用内でリストなどの要素を併用することも可能です +#### 活用例 +> - 引用する文章が入ります +> - 引用する文章が入ります +>> 多重引用したい文章の場合は複数個の挿入が必要です -## タスクリスト +## コード(Code) +- `` ` `` 3つで囲むことでコードの表現をすることが可能です +#### 活用例 ``` -- [ ] タスク 1 - - [x] タスク 1.1 - - [ ] タスク 1.2 -- [x] タスク2 -``` - -- [ ] タスク 1 - - [x] タスク 1.1 - - [ ] タスク 1.2 -- [x] タスク2 - - -# :memo: Table +コードが入ります +改行や段落をコード内で反映させることが可能です -## Markdown 標準 - -```markdown -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -OR - -Left align | Right align | Center align -:--|--:|:-: -This | This | This -column | column | column -will | will | will -be | be | be -left | right | center -aligned | aligned | aligned +- リストもコード内での表現が可能です + - リストもコード内での表現が可能です ``` -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -## TSV +## インラインコード +- `` ` `` で単語を囲むとインラインコードになります -~~~ -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ +#### 活用例 +こちらは `インラインコード` です -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` - -## TSV (ヘッダー付き) - -~~~ -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ - -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` +## シンタックスハイライトとファイル名 +- [highlight.js Demo](https://highlightjs.org/static/demo/) の common カテゴリ内の言語に対応しています -## CSV +#### 活用例 +```javascript:mersenne-twister.js +function MersenneTwister(seed) { + if (arguments.length == 0) { + seed = new Date().getTime(); + } -~~~ -``` csv -Content Cell,Content Cell -Content Cell,Content Cell + this._mt = new Array(624); + this.setSeed(seed); +} ``` -~~~ -``` csv -Content Cell,Content Cell -Content Cell,Content Cell -``` +## pre 整形済みテキスト +- 半角スペース4個もしくはタブで、コードブロックを pre 表示できます -## CSV (ヘッダー付き) +#### 活用例 + class Hoge + def hoge + print 'hoge' + end + end -~~~ -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` -~~~ +## 水平線(Hr) +- アスタリスク `*` もしくはアンダースコア `_` を3つ以上連続して記述することで水平線を挿入できます -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` +#### 活用例 +以下に水平線が挿入されます +*** +以下に水平線が挿入されます +___ -# :memo: Footnote +## 脚注(Footnote) +- 脚注 `[^1]` と脚注への参照 `[^1]:` を作成することができます +#### 活用例 脚注への参照[^1]を書くことができます。 長い脚注は[^longnote]のように書くことができます。 @@ -410,9 +278,7 @@ Content Cell,Content Cell 後続の段落はインデントされて、前の脚注に属します。 - -# :memo: Emoji - +## 絵文字(Emoji) :smiley: :smile: :laughing: :innocent: :drooling_face: :family: :man-boy: :man-girl: :man-girl-girl: :woman-girl-girl: @@ -428,12 +294,9 @@ Content Cell,Content Cell :watch: :gear: :gem: :wrench: :email: +# :memo:さらに応用的な表現 +- [ページの装飾方法(Bootstrap5)](/Sandbox/Bootstrap5) -# :heavy_plus_sign: 更に… +- [図形の表現方法(Diagrams)](/Sandbox/Diagrams) -- Bootstrap4 のタグを使う - - :arrow_right: [/Sandbox/Bootstrap4] -- 図表を書く - - :arrow_right: [/Sandbox/Diagrams] -- 数式を書く - - :arrow_right: [/Sandbox/Math] +- [数式の表現方法(Math)](/Sandbox/Math) diff --git a/apps/app/resource/locales/ja_JP/welcome.md b/apps/app/resource/locales/ja_JP/welcome.md index a45b9389439..597ea2cc16c 100644 --- a/apps/app/resource/locales/ja_JP/welcome.md +++ b/apps/app/resource/locales/ja_JP/welcome.md @@ -1,60 +1,51 @@ # :tada: GROWI へようこそ -[![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest) -[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/weseek/growi/blob/master/LICENSE) -GROWI は個人・法人向けの Wiki | ナレッジベースツールです。 +GROWI は法人・個人向けの wiki | ナレッジベースツールです。 会社や大学の研究室、サークルでのナレッジ情報を簡単に共有でき、作られたページは誰でも編集が可能です。 知っている情報をカジュアルに書き出しみんなで編集することで、**チーム内での暗黙知を減らす**ことができます。 -当たり前に共有される情報を日々増やしていきましょう。 - -### :beginner: 簡単なページの作り方 - -- 右上の "**作成**"ボタンまたは右下の**鉛筆アイコン**のボタンからページを書き始めることができます - - ページタイトルは後から変更できますので、適当に入力しても大丈夫です - - タイトル入力欄では、半角の `/` (スラッシュ) でページ階層を作れます - - (例)`/カテゴリ1/カテゴリ2/作りたいページタイトル` のように入力してみてください -- `- ` を行頭につけると、この文章のような箇条書きを書くことができます -- 画像やPDF、Word/Excel/PowerPointなどの添付ファイルも、コピー&ペースト、ドラッグ&ドロップで貼ることができます -- 書けたら "**更新**" ボタンを押してページを公開しましょう - - `Ctrl(⌘) + S` でも保存できます - -さらに詳しくはこちら: [ページを作成する](https://docs.growi.org/ja/guide/features/create_page.html) - -
-
Tips
-
    -
  • Ctrl(⌘) + "/" でショートカットヘルプを表示します
  • -
  • HTML/CSS の記述には、Bootstrap 4 を利用できます
  • -
-
- - -# :anchor: 管理者の方へ 〜Wikiを作ったら〜 - -### :arrow_right: 複数人でWikiを使いますか? -- :heavy_check_mark: メンバーを招待しましょう - - [Wikiに新しいメンバーを追加・招待する](https://docs.growi.org/ja/admin-guide/management-cookbook/user-management.html#%E6%96%B0%E8%A6%8F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E4%BB%AE%E7%99%BA%E8%A1%8C) -### :arrow_right: Slackと連携してページやコメントの通知を受け取りましょう -- :heavy_check_mark: [Slack連携](https://docs.growi.org/ja/admin-guide/management-cookbook/slack-integration/#%E6%A6%82%E8%A6%81) -### :arrow_right: 他のシステムからの乗り換えですか? -- :heavy_check_mark: 他の GROWI、esa. io、Qiita:Team のデータをインポートすることが出来ます - - [データのインポート](https://docs.growi.org/ja/admin-guide/management-cookbook/import.html) - -さらに詳しくはこちら: [管理者ガイド](https://docs.growi.org/ja/admin-guide/) - +当たり前に共有される情報を日々増やしていきましょう! -# コンテンツリストアップ例 - -テーブルと `$lsx` を使ってコンテンツリストを表示できます。 - -| 全てのページリスト (First 15 pages) | [/Sandbox] 配下ページ一覧 | -| ----------------------------------- | ------------------------- | -| $lsx(/,num=15) | $lsx(/Sandbox) | - -# Slack - -join our Slack team + -GROWI をより良いものにするために、是非 Slack に参加してください。 -開発に関する議論を行っている他、導入時の質問等も受け付けています。 +# :beginner: GROWI でできること +## 1. **【情報の蓄積】** ページを作成し情報やナレッジの蓄積ができます +- ページの作成と編集方法 + - 画面左上の「鉛筆アイコン」から新規でページを作成することが可能です + - 作成済みのページは画面右上の「Edit」からページを編集することが可能です +- ページの管理方法 + - GROWI ではページを「階層構造」で管理します + - ` /ページa/ページb/ページc ` のような構造 + - 「階層構造」とは別に「タグ」でもページを管理することが可能です + +## 2. **【情報の検索】** 情報やナレッジは様々な方法で検索できます +- キーワード検索 +- 各種サイドバーを活用した検索 + - 「ページツリー」からの検索 + - 「最新の変更」からの検索 + - 「タグ」からの検索 など… + +## 3. **【情報の共有】** 情報やナレッジは社内外を問わず簡単に共有可能です +- 社内のメンバーに対してはページの URL やパーマリンクを送ることで共有が可能です + - 社内のメンバー内でも「ユーザーグループ」を活用することで閲覧権限の管理をすることが可能です +- アカウントを保有していない社外のユーザーのページ閲覧を可能にすることも可能です + - 「共有リンク」を活用し社外のユーザーに情報を共有しましょう + +#### :bulb:ページの編集方法が分からないときは [Sandbox](/Sandbox) を確認してみましょう! + + +# :wrench:管理者の方へ ~ GROWI を作成したら~ + +### :arrow_right: 複数人で GROWI を使いますか? +- :heavy_check_mark: メンバーを招待しましょう! + - [GROWI に新しいメンバーを追加・招待する](https://docs.growi.org/ja/admin-guide/management-cookbook/user-management.html#%E6%96%B0%E8%A6%8F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E4%BB%AE%E7%99%BA%E8%A1%8C) + +### :arrow_right: GROWI の見た目はこのままで満足ですか? +- :heavy_check_mark: GROWI の見た目をカスタイマイズしましょう! + - [GROWI のテーマをカスタイマイズする](/admin/customize) + +### :arrow_right: GROWI のセキュリティ設定は完了していますか? +- :heavy_check_mark: GROWI のセキュリティ設定を更新しましょう! + - [GROWI のセキュリティ設定を更新する](/admin/security) diff --git a/apps/app/resource/locales/zh_CN/sandbox-bootstrap4.md b/apps/app/resource/locales/zh_CN/sandbox-bootstrap4.md deleted file mode 100644 index 77b587ec287..00000000000 --- a/apps/app/resource/locales/zh_CN/sandbox-bootstrap4.md +++ /dev/null @@ -1,253 +0,0 @@ -# Labels - -Primary -Secondary -Success -Info -Warning -Danger -Light -Dark - -Blue -Indigo -Purple -Pink -Red -Orange -Yellow -Green -Teal -Cyan - - -# Alerts - - - - - - - - - - -# Cards - -
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
-
-
Header
-
-
Primary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Secondary card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Success card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Danger card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Warning card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Info card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Light card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
-
Header
-
-
Dark card title
-

Some quick example text to build on the card title and make up the bulk of the card's content.

-
-
-
- -
- -# Wells - -## Default well - -
Look, I'm in a well!
- -## Optional classes - -
Look, I'm in a well!
- -# Typography - -## Lead body copy - -

Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.

- -## Marked text - -You can use the mark tag to highlight text. - -## Small text - -This line of text is meant to be treated as fine print. - -## Alignment classes - -
-
-

Left aligned text.

-

Center aligned text.

-

Right aligned text.

-

Justified text.

-

No wrap text.

-
-
- -## Transformation classes - -
-
-

Lowercased text.

-

Uppercased text.

-

Capitalized text.

-
-
- - -# Helper classes - -## Contextual colors - -
-
-

Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi. Fusce pellentesque quam nec magna maximus porta.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
- -## Contextual backgrounds - -
-
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-

Sed luctus venenatis tellus, in aliquam ligula scelerisque eget.

-

Ut vel lorem aliquet, rhoncus libero at, condimentum mi.

-

Nullam id dolor id nibh ultricies vehicula ut id elit.

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-

Maecenas sed diam eget risus varius blandit sit amet non magna.

-

Etiam porta sem malesuada magna mollis euismod.

-

Donec ullamcorper nulla non metus auctor fringilla.

-
-
diff --git a/apps/app/resource/locales/zh_CN/sandbox-bootstrap5.md b/apps/app/resource/locales/zh_CN/sandbox-bootstrap5.md new file mode 100644 index 00000000000..c199eb8ff17 --- /dev/null +++ b/apps/app/resource/locales/zh_CN/sandbox-bootstrap5.md @@ -0,0 +1,169 @@ +# 1. Badges + +primary + +secondary + +success + +danger + +warning + +info + +light + +dark + + +# 2. Alerts + + + + + + + + + + + + + + + + + + +# 3. Cards + +
+
Header
+
+
Primary card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Secondary card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Success card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Danger card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Warning card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Info card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Light card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ +
+
Header
+
+
Dark card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+
+
+ + +# 4. Colors +## 背景颜色 +

Look, I'm in a well!

+

Look, I'm in a well!

+

Look, I'm in a well!

+ +## 背景情况 +

Look, I'm in a well!

+

Look, I'm in a well!

+

Look, I'm in a well!

+ + +# 5. Collapse +## 显示内容 + + Show content + + +
+
+ +- Content you want to display + - Content you want to display + +
+
+ +## 隐藏内容 + + Hide content + + +
+
+ +- Content you want to hide + - Content you want to hide + +
+
+ + +# 官方文件 +- [点击此处了解徽章详情](https://getbootstrap.com/docs/5.3/components/badge/) +- [单击此处了解警报详情](https://getbootstrap.com/docs/5.3/components/alerts/) +- [点击此处了解贺卡详情](https://getbootstrap.com/docs/5.3/components/card/) +- [点击此处了解颜色详情](https://getbootstrap.com/docs/5.3/utilities/colors/) +- [点击此处查看折叠详情](https://getbootstrap.com/docs/5.3/components/collapse/) \ No newline at end of file diff --git a/apps/app/resource/locales/zh_CN/sandbox-diagrams.md b/apps/app/resource/locales/zh_CN/sandbox-diagrams.md index 6321f2a9444..f40fc70d587 100644 --- a/apps/app/resource/locales/zh_CN/sandbox-diagrams.md +++ b/apps/app/resource/locales/zh_CN/sandbox-diagrams.md @@ -1,4 +1,4 @@ -# :pencil: diagrams.net(former Draw.io) +# :pencil: diagrams.net(Draw.io) See [diagrams.net](https://diagrams.net) @@ -15,7 +15,7 @@ See [diagrams.net](https://diagrams.net) ``` -## AWS diagram +## AWS configuration diagram ``` drawio 3Zhdb5swFIZ/TS4XYRswuUzSr0mtVqmtejkZOASvgJHtfO3Xz+YjgdJqiaa1SbnBvD7G9vv4IJsRmeeba8nK9E7EkI2wE29G5GKEMfa9wNyssq0VhFyvVhaSx422Fx74b2hEp1GXPAbVC9RCZJqXfTESRQGR7mlMSrHuhyUi6/dasgUMhIeIZUP1mcc6rdUA071+A3yRtj0jf1LX5KwNbmaiUhaLdUcilyMyl0LoupRv5pBZ91pf6nZX79TuBiah0G80eFIgf4S/rCfYyVhowFRBI+xFIi9FYZthr3WvVaqYGxZy2+xRsugFpCndPN7dmtu0LJtuMxZBaswE2Te4HR7ezXA3cqW3ravGi9IW883CrpsxWyt3nIuQ24BZwrNsLjIhq2CSJOBHkdGVluIFOjUxnYSOY2pWIDU30G7tPO+F4pqLwsSEQmuRmwCmynp1JHwDZoizerS2HWzeNRR1JnENIgcttyakafANuQ3aZnG7Ph37vk8d6pAgoBO3rl131k3TIO0smVZjjZGLXUd7mKbQ2Ng+dvD+M+6n7xatUqDVgXTJ8XQVGZLFlJqEeYtsUl2fRRb7Y+QEJCCIBhQ5ExL0OBPHOReyqsre6VKnRjM+Vu4dxtg9nnEkFgXXYgh6ThFBV6cHmgRj10XUo9jByA1c90vk8/TeJvQ107Bm2wNpe8fTZiX/uWg6GRD3psSZeadH/C+p7RNvTAhxzaedUuoFwbkgf34w4i3Lw5gdSNw/nnhWvf9nsiyimtWBH/TCjPSzgCP/FXH3SwC/YJqFTMGBsOnxsONtwXIRh0PK1q/Z5PRymzgni3qwfW86X7FsCS113KcSLeXKWnNhd7hQxFN7nNlnk1GuuO2yqo+ZSqtg9BYXPwogTHYuQzw49Lzy2AxELGUEnc28OXgxuQA93AF2SEjIzB5j1X/7EdYNfJqcuU/uB/nUnpfP1ijvo4xC52SUNzTK/yij8DkZ5Q+Nov/HKPO4/2lT1XX+fZHLPw== @@ -27,8 +27,7 @@ See [diagrams.net](https://diagrams.net) See [PlantUML](http://plantuml.com/). -## Sequence diagram - +## Sequence Diagram ``` plantuml @startuml skinparam sequenceArrowThickness 2 @@ -63,7 +62,6 @@ deactivate A ## Class diagram - ``` plantuml @startuml @@ -155,7 +153,7 @@ State3 --> [*] : Aborted # :pencil: Mermaid -## Pie chart diagram +## Pie graph ```mermaid %%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% @@ -167,7 +165,7 @@ pie showData "Iron" : 5 ``` -## Gantt diagram +## Gantt chart ```mermaid gantt @@ -181,7 +179,7 @@ gantt another task : 24d ``` -## Gitgraph diagram +## Git tree diagram ```mermaid %%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'rotateCommitLabel': true}} }%% @@ -202,14 +200,13 @@ gitGraph commit ``` -## Mindmap diagram +## Mind map ```mermaid mindmap root((mindmap)) Origins Long history - ::icon(fa fa-book) Popularisation British popular psychology author Tony Buzan Research diff --git a/apps/app/resource/locales/zh_CN/sandbox.md b/apps/app/resource/locales/zh_CN/sandbox.md index 0284085d99a..4e367d3b54b 100644 --- a/apps/app/resource/locales/zh_CN/sandbox.md +++ b/apps/app/resource/locales/zh_CN/sandbox.md @@ -1,439 +1,160 @@ -# :memo: Table of Contents +# 什么是沙盒? +- 在本页中,您可以找到帮助您掌握 GROWI 的技巧。 +- 您可以在此层级下的参考资料中丰富您的网页内容 -Add `ToC` after some `#` signs. -`Table of Contents` or `Table-of-Contents` is also OK. -``` -# ToC -``` - -## ToC - -# :memo: Block Elements - -## Headers +# :closed_book:标题和段落 +- 通过插入标题和段落,可以使页面上的文字更易于阅读 -Add one `#` per level at the start of the line +## 标题 +- 在标题文字前添加 `#` 以创建标题 + - 在 "视图 "屏幕中,标题的字体大小会因 "#"的数量而异 + - 查看右侧的 "视图 "屏幕,了解标题的效果 +- `#`的数量将决定层次结构的级别,并帮助您组织内容 ``` -# Header 1 -## Header 2 -### Header 3 -#### Header 4 -##### Header 5 -###### Header 6 +# 一级标题 +## 二级标题 +### 三级标题 +#### 第四级标题 +##### 第五级标题 +###### 第六级标题 ``` -### Header 3 +### 断句 +- 在要换行的句子末尾插入两个半宽空格 + - 您也可以在 "设置 "中进行更改,使换行不使用半宽空格 + - 在管理页面的 "Markdown 设置 "部分更改换行设置 -#### Header 4 +#### 无换行 +段落 1 +第 2 段 -##### Header 5 +#### 有换行符 +段落 1 +第 2 段 -###### Header 6 +## 段落 +- 在文本中插入空白表格即可创建段落 +- 可将段落分成若干句子,使其更易于阅读 -## Block paragraph +#### 无段落 +段落 1 +第 2 段 -Pararaphs are created by inserting a newline character -A paragraph can be created by pressing Enter at the end of the previous paragraph. +#### 有段落 +第 1 段 -``` -paragraph1 -(Blank line) -paragraph2 -``` +第 2 段 -paragraph1 -paragraph2 +# :green_book: 文本样式 +- 可以使用各种样式来丰富句子的文字表达方式 + - 选择 "编辑 "屏幕底部的工具栏图标,也可以轻松应用这些样式 -## Br new line +##斜体 +- 用星号`*`或下划线`_`括住文本。 -Add two spaces before break. -***This behaviour can be modified in the options menu.*** +#### 示例 +- 这句话用*斜体*表示强调 +- 这句话用 _Italic_ 表示强调 -``` -hoge -fuga(two spaces) -piyo -``` +## 粗体 +- 用两个星号`*`或两个下划线`_`括住文本。 -hoge -fuga -piyo +#### 示例 +- 这句话用 ** 粗体** 表示强调 +- 这句话用__粗体__表示强调 -## Blockquotes +## 斜体和粗体 +- 用三个星号`*`或三个下划线`_`括起来 -Add one `>` per level at the start of the line +#### 示例 +- 本句用***斜体和粗体***表示强调 +- 本句用____斜体和粗体____表示强调 -``` -> quote -> quote ->> nested quotes -``` -> quote -> quote ->> nested quotes +# :orange_book: 插入列表 +## 缩略图列表 +- 用连字符 `-`、加号 `+` 或星号 `*` 开头一行,插入一个项目符号列表 -## Code +#### 示例 +- 这句话出现在项目符号列表中 + - 这句话出现在项目符号列表中 + - 这句话出现在项目符号列表中 + - 这句话出现在项目符号列表中 +- 此句出现在项目符号列表中 + - 此句子出现在项目符号列表中 -Wrap code with three back quotes or tildes. +## 编号列表 +- 在行首添加 `Number.` 以插入编号列表 +- 编号列表和项目符号列表也可合并使用 -``` -print 'hoge' -``` +#### 示例 +1. 编号列表中有这样一句话 + 1. 编号列表中包含这句话 + 1. 该句子出现在编号表中 + 1. 此句出现在编号列表中 + - 此句出现在项目符号列表中 +1. 此句出现在项目符号列表中 + - 此句出现在项目符号列表中 -### Syntax highlight and file name +##任务列表 +- 通过书写 `[] ` 插入未选中复选框列表 + - 通过书写 `[x]` 选中复选框 -- corresponding [highlight.js Demo](https://highlightjs.org/static/demo/) of common category +#### 示例 +- [ ] 任务 1 + - [x] 任务 1-1 + - [ ] 任务 1-2 +- [x] 任务 2 -~~~ -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } +# :blue_book: 其他 +### 引号 +- 在段落开头加上`>`,使用引号表达式 + - 使用`>`字符序列可表达多个引号 +- 列表和其他元素可在方括号内一起使用 - this._mt = new Array(624); - this.setSeed(seed); -} -``` -~~~ +#### 示例 +> - 引号 +> - 引号 +>> 多个引号需要插入更多的 `>` 字符 -```javascript:mersenne-twister.js -function MersenneTwister(seed) { - if (arguments.length == 0) { - seed = new Date().getTime(); - } +## 代码 +- 可以通过将代码添加到三个 `` `` `` 中来表达代码 - this._mt = new Array(624); - this.setSeed(seed); -} +#### 示例 ``` +在此处添加代码 +代码中可以体现换行和段落 -### Inline code - -Words wrapped by `` `back quotes` `` will be formatted as inline code. - -``` -This is `Inline Code`. +- 代码中也可使用列表 + - 也可在代码中使用列表 ``` -This is `Inline Code`. +## 内联代码 -## Pre-arranged text -Code blocks should be preceded by four spaces or one tab. -``` - class Hoge - def hoge - print 'hoge' - end - end -``` - class Hoge - def hoge - print 'hoge' - end - end +#### 示例 +以下是内联代码 -## Horizontal Line +## 水平线 +- 用三个或三个以上连续的星号`*`或下划线`_`插入水平线 -Write three underscores `_`, or asterisks`*`. - -``` +#### 示例 +以下是水平线 *** -___ ---- -``` -*** +下面是水平线 ___ ---- - - - -# :memo: Typography - -## Strong Text - -### Italic - -To italicize text, add One asterisk or underscores before and after a word or phrase. - -``` -This is *Italic* . -This is _Italic_ . -``` - -This is *Italic* . -This is _Italic_ . - -### Bold - -To bold text, add two asterisks or underscores before and after a word or phrase. - -``` -This is **bold**. -This is __bold__. -``` - -This is **bold**. -This is __bold__. - -### Bold + Italic - -To bold and italicize text, add three asterisks or underscores before and after a word or phrase. - -``` -This is ***Italic & Bold***. -This is ___Italic & Bold___. -``` - -This is ***Italic & Bold***. -This is ___Italic & Bold___. - -# :memo: Images - -You can insert `` tag using `![description](URL)`. - -```markdown -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") -``` - -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") - -The size of the image can be set by using an HTML image tag - -```html - -``` - - - - -# :memo: Link - -## Markdown standard - -You can create links using `[Display text](URL)`. - -``` -[Google](https://www.google.co.jp/) -``` - -[Google](https://www.google.co.jp/) - -## Pukiwiki like linker - -This is the most flexible linker. -Both the page description and link address can be displayed on the page. - -``` -[[./Bootstrap4]] -Example of Bootstrap4 is [[here>./Bootstrap4]] -``` - -[[./Bootstrap4]] -Example of Bootstrap4 is [[here>./Bootstrap4]] - -# :memo: Lists - -## Ul Bulleted list - -To create an unordered list, add dashes (-), asterisks (*), or plus signs (+) in front of line items. -Items can be nested using indentation. - -``` -- List1 - - List1_1 - - List1_1_1 - - List1_1_2 - - List1_2 -- List2 -- List3 -``` - -- List1 - - List1_1 - - List1_1_1 - - List1_1_2 - - List1_2 -- List2 -- List3 - -## Ol Numbered List - -To create an ordered list, add line items with numbers followed by periods. -The numbers don’t have to be in numerical order, but the list should start with the number one. - -``` -1. Number list 1 - 1. Number list 1-1 - 1. Number list 1-2 -1. Number list 2 -1. Number list 3 -``` - -1. Number list 1 - 1. Number list 1-1 - 1. Number list 1-2 -1. Number list 2 -1. Number list 3 - - -## Check list - -``` -- [ ] Task 1 - - [x] Task 1.1 - - [ ] Task 1.2 -- [x] Task2 -``` - -- [ ] Task 1 - - [x] Task 1.1 - - [ ] Task 1.2 -- [x] Task2 - - -# :memo: Table - -## Markdown Standard - -```markdown -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -OR - -Left align | Right align | Center align -:--|--:|:-: -This | This | This -column | column | column -will | will | will -be | be | be -left | right | center -aligned | aligned | aligned -``` - -| Left align | Right align | Center align | -|:-----------|------------:|:------------:| -| This | This | This | -| column | column | column | -| will | will | will | -| be | be | be | -| left | right | center | -| aligned | aligned | aligned | - -## TSV - -~~~ -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ - -``` tsv -Content Cell Content Cell -Content Cell Content Cell -``` - -## TSV with header - -~~~ -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` -~~~ - -``` tsv-h -First Header Second Header -Content Cell Content Cell -Content Cell Content Cell -``` - -## CSV - -~~~ -``` csv -Content Cell,Content Cell -Content Cell,Content Cell -``` -~~~ - -``` csv -Content Cell,Content Cell -Content Cell,Content Cell -``` - -## CSV with header - -~~~ -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` -~~~ - -``` csv-h -First Header,Second Header -Content Cell,Content Cell -Content Cell,Content Cell -``` - - -# :memo: Footnote - -You can write a reference [^1] to a footnote. - -Long footnotes can be written as [^longnote]. - -[^1]: A_reference_to_the_first_footnote. - -[^longnote]: An_example_of_writing_a_footnote_in_multiple_blocks. - - Subsequent paragraphs are indented and belong to the previous footnote. - - -# :memo: Emoji - -:smiley: :smile: :laughing: :innocent: :drooling_face: - -:family: :man-boy: :man-girl: :man-girl-girl: :woman-girl-girl: - -:+1: :-1: :open_hands: :raised_hands: :point_right: - -:apple: :green_apple: :strawberry: :cake: :hamburger: - -:basketball: :football: :baseball: :volleyball: :8ball: - -:hearts: :broken_heart: :heartbeat: :heartpulse: :heart_decoration: -:watch: :gear: :gem: :wrench: :email: +# :ledger: 更多应用 +- [Bootstrap5](/Sandbox/Bootstrap5) -# :heavy_plus_sign: More.. +- [Diagrams](/Sandbox/Diagrams) -- Try to attach Bootstrap4 Tags? - - :arrow_right: [/Sandbox/Bootstrap4] -- Try to draw Diagrams? - - :arrow_right: [/Sandbox/Diagrams] -- Try to write Math Formulas? - - :arrow_right: [/Sandbox/Math] +- [Math](/Sandbox/Math) \ No newline at end of file diff --git a/apps/app/resource/locales/zh_CN/welcome.md b/apps/app/resource/locales/zh_CN/welcome.md index d360dfe7760..e922cf0af26 100644 --- a/apps/app/resource/locales/zh_CN/welcome.md +++ b/apps/app/resource/locales/zh_CN/welcome.md @@ -1,64 +1,51 @@ -# :tada: 欢迎来到GROWI +# :tada: 欢迎访问 GROWI -[![GitHub Releases](https://img.shields.io/github/release/weseek/growi.svg)](https://github.com/weseek/growi/releases/latest) -[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/weseek/growi/blob/master/LICENSE) +GROWI 是面向企业和个人的维基知识库工具。 +知识信息可以在公司、大学实验室和俱乐部中轻松共享,任何人都可以编辑创建的页面。 -GROWI是一个针对个人和公司的Wiki - 一个知识库工具。 -公司、大学实验室和俱乐部的知识可以轻松共享,任何人都可以编辑页面。 +随手写下你所知道的信息,然后一起编辑,可以减少团队中的隐性知识。 +理所当然地增加每天共享的信息量! -我们可以很容易地写下我们知道的东西,并一起编辑,我们可以**简化我们团队中的隐性知识(难以用语言解释的知识)**。 -让我们每天增加信息交流。 - -### :beginner: 如何轻松制作一个页面 - -- 从右上方的 "**创建**"按钮,或右下方的**铅笔图标开始。 - - 页面标题以后可以再编辑,不用担心标题的问题。 - - 在标题输入栏,可以用半宽的`/`(斜线)创建页面的层次。 - - 例子)尝试输入`/category1/category2/page-title-we-want-to-create`。 -- 我们可以通过在行首添加`-`来创建一个要点。 -- 我们还可以复制和粘贴,拖放附件,如图片、PDF、Word/Excel/PowerPoint等。 -- 一旦我们完成了,按 "**更新**"按钮来发布页面。 - - 我们也可以通过`Ctrl(⌘) + S`来保存。 - -了解更多信息: [Create page](https://docs.growi.org/en/guide/features/create_page.html) - -
-
- Tips -
-
- -
+ -# :anchor: 对于管理员来说 〜如果你创建了一个Wiki〜 - -### :arrow_right: 你会和多个人一起使用Wiki吗? -- :heavy_check_mark: 让我们邀请一些成员。 - - [Add/invite new members to the Wiki](https://docs.growi.org/en/admin-guide/management-cookbook/user-management.html#temporary-issuance-of-a-new-user) -### :arrow_right: 与Slack合作,接收页面和评论通知。 -- :heavy_check_mark: [Slack integration](https://docs.growi.org/en/admin-guide/management-cookbook/slack-integration/#overview) -### :arrow_right: 你是否从另一个系统转换? -- :heavy_check_mark: 可以从其他GROWI, esa.io, Qiita:Team导入数据。 - - [Import Data](https://docs.growi.org/en/admin-guide/management-cookbook/import.html) - -了解更多信息: [Admin Guide](https://docs.growi.org/en/admin-guide/) - - -# 内容列表示例 - -你可以用一个表格和`$lsx`来显示内容列表。 - -| 所有页面列表(前15页) | [/Sandbox] 下级页面列表 | -| ---------------------------| ------------------------| -| $lsx(/,num=15) | $lsx(/Sandbox) | - -# Slack - -join our Slack team - -我们欢迎新人加入我们的slack频道,帮助改善Growi。 -除了讨论发展问题,我们也很乐意在你加入时回答你的问题。 +# :beginner: 使用 GROWI 可以做什么 +## 1. 可以创建页面来存储信息和知识。 +- 如何创建和编辑页面 + - 可以通过屏幕左上角的 "铅笔图标 "创建新页面。 + - 点击屏幕右上角的 "编辑 "可编辑已创建的页面。 +- 如何管理页面 + - GROWI 采用 "分层结构 "管理页面。 + - ` /page a/page b/page c ` 结构类似。 + - 除了 "层次结构",还可以通过 "标签 "来管理页面。 + +## 2. 检索信息和知识的方式有以下几种。 +- 关键词搜索 +- 使用各种侧边栏进行搜索。 + - 按 "页面树 "搜索。 + - 按 "最新更改 "搜索。 + - 按 "标签 "搜索 例如... + +## 3. 信息和知识可以很容易地在内部和外部共享。 +- 内部成员可通过发送页面的 URL 或 URL 链接获得通知。 + - 使用 "用户组 "可以管理公司成员内部的查看权限。 +- 还可以允许未持有账户的外部用户查看页面。 + - 使用 "共享链接 "与公司以外的用户共享信息。 + +#### :bulb:如果不确定如何编辑页面,请选中 [Sandbox](/Sandbox)! + + +# :wrench:针对管理员 - GROWI 创建后 + +### :arrow_right: 您是否与多人一起使用 GROWI? +- :heavy_check_mark: 邀请您的会员 + - [添加和邀请新成员加入 GROWI](https://docs.growi.org/en/admin-guide/management-cookbook/user-management.html#%E6%96%B0%E8%A6%8F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E4%BB%AE%E7%99%BA%E8%A1%8C) + +### :arrow_right: 您对 GROWI 现在的样子满意吗? +- :heavy_check_mark: 定制 GROWI 的外观和感觉! + - [定制 GROWI 主题](/admin/customize) + +### :arrow_right: GROWI 安全配置是否已完成? +- :heavy_check_mark: 更新您的 GROWI 安全设置! + - [更新 GROWI 安全设置](/admin/security) diff --git a/apps/app/src/client/models/MarkdownTable.js b/apps/app/src/client/models/MarkdownTable.js index 4e660d84936..a9147e06463 100644 --- a/apps/app/src/client/models/MarkdownTable.js +++ b/apps/app/src/client/models/MarkdownTable.js @@ -1,5 +1,5 @@ import csvToMarkdown from 'csv-to-markdown-table'; -import markdownTable from 'markdown-table'; +import { markdownTable } from 'markdown-table'; import stringWidth from 'string-width'; // https://github.com/markdown-it/markdown-it/blob/d29f421927e93e88daf75f22089a3e732e195bd2/lib/rules_block/table.js#L83 diff --git a/apps/app/src/client/services/AdminGeneralSecurityContainer.js b/apps/app/src/client/services/AdminGeneralSecurityContainer.js index 9cf0d3227a0..aefa9692d80 100644 --- a/apps/app/src/client/services/AdminGeneralSecurityContainer.js +++ b/apps/app/src/client/services/AdminGeneralSecurityContainer.js @@ -32,6 +32,7 @@ export default class AdminGeneralSecurityContainer extends Container { currentPageRecursiveDeletionAuthority: PageRecursiveDeleteConfigValue.Inherit, currentPageCompleteDeletionAuthority: PageSingleDeleteCompConfigValue.AdminOnly, currentPageRecursiveCompleteDeletionAuthority: PageRecursiveDeleteCompConfigValue.Inherit, + isAllGroupMembershipRequiredForPageCompleteDeletion: true, previousPageRecursiveDeletionAuthority: null, previousPageRecursiveCompleteDeletionAuthority: null, expandOtherOptionsForDeletion: false, @@ -73,6 +74,7 @@ export default class AdminGeneralSecurityContainer extends Container { currentPageCompleteDeletionAuthority: generalSetting.pageCompleteDeletionAuthority, currentPageRecursiveDeletionAuthority: generalSetting.pageRecursiveDeletionAuthority, currentPageRecursiveCompleteDeletionAuthority: generalSetting.pageRecursiveCompleteDeletionAuthority, + isAllGroupMembershipRequiredForPageCompleteDeletion: generalSetting.isAllGroupMembershipRequiredForPageCompleteDeletion, isShowRestrictedByOwner: !generalSetting.hideRestrictedByOwner, isShowRestrictedByGroup: !generalSetting.hideRestrictedByGroup, isUsersHomepageDeletionEnabled: generalSetting.isUsersHomepageDeletionEnabled, @@ -154,6 +156,13 @@ export default class AdminGeneralSecurityContainer extends Container { this.setState({ currentPageRecursiveCompleteDeletionAuthority: val }); } + /** + * Switch isAllGroupMembershipRequiredForPageCompleteDeletion + */ + switchIsAllGroupMembershipRequiredForPageCompleteDeletion() { + this.setState({ isAllGroupMembershipRequiredForPageCompleteDeletion: !this.state.isAllGroupMembershipRequiredForPageCompleteDeletion }); + } + /** * Change previousPageRecursiveDeletionAuthority */ @@ -225,6 +234,7 @@ export default class AdminGeneralSecurityContainer extends Container { pageCompleteDeletionAuthority: this.state.currentPageCompleteDeletionAuthority, pageRecursiveDeletionAuthority: this.state.currentPageRecursiveDeletionAuthority, pageRecursiveCompleteDeletionAuthority: this.state.currentPageRecursiveCompleteDeletionAuthority, + isAllGroupMembershipRequiredForPageCompleteDeletion: this.state.isAllGroupMembershipRequiredForPageCompleteDeletion, hideRestrictedByGroup: !this.state.isShowRestrictedByGroup, hideRestrictedByOwner: !this.state.isShowRestrictedByOwner, isUsersHomepageDeletionEnabled: this.state.isUsersHomepageDeletionEnabled, diff --git a/apps/app/src/client/services/create-page/index.ts b/apps/app/src/client/services/create-page/index.ts new file mode 100644 index 00000000000..140966f93cf --- /dev/null +++ b/apps/app/src/client/services/create-page/index.ts @@ -0,0 +1,2 @@ +export * from './use-create-page-and-transit'; +export * from './use-create-template-page'; diff --git a/apps/app/src/client/services/create-page/use-create-page-and-transit.tsx b/apps/app/src/client/services/create-page/use-create-page-and-transit.tsx new file mode 100644 index 00000000000..08f4b1fd775 --- /dev/null +++ b/apps/app/src/client/services/create-page/use-create-page-and-transit.tsx @@ -0,0 +1,110 @@ +import { useCallback, useState } from 'react'; + +import { useRouter } from 'next/router'; + +import { createPage, exist } from '~/client/services/page-operation'; +import type { IApiv3PageCreateParams } from '~/interfaces/apiv3'; +import { useCurrentPagePath } from '~/stores/page'; +import { EditorMode, useEditorMode } from '~/stores/ui'; +import loggerFactory from '~/utils/logger'; + +const logger = loggerFactory('growi:Navbar:GrowiContextualSubNavigation'); + +/** + * Invoked when creation and transition has finished + */ +type OnCreated = () => void; +/** + * Invoked when either creation or transition has aborted + */ +type OnAborted = () => void; +/** + * Always invoked after processing is terminated + */ +type OnTerminated = () => void; + +type CreatePageAndTransitOpts = { + shouldCheckPageExists?: boolean, + onCreationStart?: OnCreated, + onCreated?: OnCreated, + onAborted?: OnAborted, + onTerminated?: OnTerminated, +} + +type CreatePageAndTransit = ( + params: IApiv3PageCreateParams, + opts?: CreatePageAndTransitOpts, +) => Promise; + +type UseCreatePageAndTransit = () => { + isCreating: boolean, + createAndTransit: CreatePageAndTransit, +}; + +export const useCreatePageAndTransit: UseCreatePageAndTransit = () => { + + const router = useRouter(); + + const { data: currentPagePath } = useCurrentPagePath(); + const { mutate: mutateEditorMode } = useEditorMode(); + + const [isCreating, setCreating] = useState(false); + + const createAndTransit: CreatePageAndTransit = useCallback(async(params, opts = {}) => { + const { + shouldCheckPageExists, + onCreationStart, onCreated, onAborted, onTerminated, + } = opts; + + // check the page existence + if (shouldCheckPageExists && params.path != null) { + const pagePath = params.path; + + try { + const { isExist } = await exist(pagePath); + + if (isExist) { + // routing + if (pagePath !== currentPagePath) { + await router.push(`${pagePath}#edit`); + } + mutateEditorMode(EditorMode.Editor); + onAborted?.(); + return; + } + } + catch (err) { + throw err; + } + finally { + onTerminated?.(); + } + } + + // create and transit + try { + setCreating(true); + onCreationStart?.(); + + const response = await createPage(params); + + await router.push(`/${response.page._id}#edit`); + mutateEditorMode(EditorMode.Editor); + + onCreated?.(); + } + catch (err) { + throw err; + } + finally { + onTerminated?.(); + setCreating(false); + } + + }, [currentPagePath, mutateEditorMode, router]); + + return { + isCreating, + createAndTransit, + }; +}; diff --git a/apps/app/src/client/services/create-page/use-create-template-page.ts b/apps/app/src/client/services/create-page/use-create-template-page.ts new file mode 100644 index 00000000000..524efa044e3 --- /dev/null +++ b/apps/app/src/client/services/create-page/use-create-template-page.ts @@ -0,0 +1,40 @@ +import { useCallback } from 'react'; + +import { Origin } from '@growi/core'; +import { isCreatablePage } from '@growi/core/dist/utils/page-path-utils'; +import { normalizePath } from '@growi/core/dist/utils/path-utils'; + +import type { LabelType } from '~/interfaces/template'; +import { useCurrentPagePath } from '~/stores/page'; + + +import { useCreatePageAndTransit } from './use-create-page-and-transit'; + +type UseCreateTemplatePage = () => { + isCreatable: boolean, + isCreating: boolean, + createTemplate?: (label: LabelType) => Promise, +} + +export const useCreateTemplatePage: UseCreateTemplatePage = () => { + + const { data: currentPagePath, isLoading: isLoadingPagePath } = useCurrentPagePath(); + + const { isCreating, createAndTransit } = useCreatePageAndTransit(); + const isCreatable = currentPagePath != null && isCreatablePage(normalizePath(`${currentPagePath}/_template`)); + + const createTemplate = useCallback(async(label: LabelType) => { + if (isLoadingPagePath || !isCreatable) return; + + return createAndTransit( + { path: normalizePath(`${currentPagePath}/${label}`), wip: false, origin: Origin.View }, + { shouldCheckPageExists: true }, + ); + }, [currentPagePath, isCreatable, isLoadingPagePath, createAndTransit]); + + return { + isCreatable, + isCreating, + createTemplate: isCreatable ? createTemplate : undefined, + }; +}; diff --git a/apps/app/src/client/services/layout.ts b/apps/app/src/client/services/layout.ts index 49a83aad041..1998a06d571 100644 --- a/apps/app/src/client/services/layout.ts +++ b/apps/app/src/client/services/layout.ts @@ -1,7 +1,6 @@ import type { IPage } from '@growi/core'; import { useIsContainerFluid } from '~/stores/context'; -import { useSWRxCurrentPage } from '~/stores/page'; import { useEditorMode } from '~/stores/ui'; export const useEditorModeClassName = (): string => { @@ -10,17 +9,29 @@ export const useEditorModeClassName = (): string => { return `${getClassNamesByEditorMode().join(' ') ?? ''}`; }; -export const useCurrentGrowiLayoutFluidClassName = (initialPage?: IPage): string => { - const { data: currentPage } = useSWRxCurrentPage(); - +const useDetermineExpandContent = (expandContentWidth?: boolean | null): boolean => { const { data: dataIsContainerFluid } = useIsContainerFluid(); - const page = currentPage ?? initialPage; - const isContainerFluidEachPage = page == null || !('expandContentWidth' in page) - ? null - : page.expandContentWidth; const isContainerFluidDefault = dataIsContainerFluid; - const isContainerFluid = isContainerFluidEachPage ?? isContainerFluidDefault; + return expandContentWidth ?? isContainerFluidDefault ?? false; +}; + +export const useShouldExpandContent = (data?: IPage | boolean | null): boolean => { + const expandContentWidth = (() => { + // when data is null + if (data == null) { + return null; + } + // when data is boolean + if (data === true || data === false) { + return data; + } + // when IPage does not have expandContentWidth + if (!('expandContentWidth' in data)) { + return null; + } + return data.expandContentWidth; + })(); - return isContainerFluid ? 'growi-layout-fluid' : ''; + return useDetermineExpandContent(expandContentWidth); }; diff --git a/apps/app/src/client/services/page-operation.ts b/apps/app/src/client/services/page-operation.ts index af7b51a3a0c..33dcbf376a3 100644 --- a/apps/app/src/client/services/page-operation.ts +++ b/apps/app/src/client/services/page-operation.ts @@ -1,20 +1,24 @@ import { useCallback } from 'react'; -import { SubscriptionStatusType, type Nullable } from '@growi/core'; +import type { IPageHasId } from '@growi/core'; +import { SubscriptionStatusType } from '@growi/core'; import urljoin from 'url-join'; -import { OptionsToSave } from '~/interfaces/page-operation'; -import { useEditingMarkdown, useIsEnabledUnsavedWarning, usePageTagsForEditors } from '~/stores/editor'; +import type { + IApiv3PageCreateParams, IApiv3PageCreateResponse, IApiv3PageUpdateParams, IApiv3PageUpdateResponse, +} from '~/interfaces/apiv3'; +import { useEditingMarkdown, usePageTagsForEditors } from '~/stores/editor'; import { useCurrentPageId, useSWRMUTxCurrentPage, useSWRxTagsInfo } from '~/stores/page'; import { useSetRemoteLatestPageData } from '~/stores/remote-latest-page'; import loggerFactory from '~/utils/logger'; import { apiPost } from '../util/apiv1-client'; -import { apiv3Post, apiv3Put } from '../util/apiv3-client'; +import { apiv3Get, apiv3Post, apiv3Put } from '../util/apiv3-client'; import { toastError } from '../util/toastr'; const logger = loggerFactory('growi:services:page-operation'); + export const toggleSubscribe = async(pageId: string, currentStatus: SubscriptionStatusType | undefined): Promise => { try { const newStatus = currentStatus === SubscriptionStatusType.SUBSCRIBE @@ -87,91 +91,9 @@ export const resumeRenameOperation = async(pageId: string): Promise => { await apiv3Post('/pages/resume-rename', { pageId }); }; -// TODO: define return type -const createPage = async(pagePath: string, markdown: string, tmpParams: OptionsToSave) => { - // clone - const params = Object.assign(tmpParams, { - path: pagePath, - body: markdown, - }); - - const res = await apiv3Post('/pages/', params); - const { page, tags, revision } = res.data; - - return { page, tags, revision }; -}; - -// TODO: define return type -const updatePage = async(pageId: string, revisionId: string, markdown: string, tmpParams: OptionsToSave) => { - // clone - const params = Object.assign(tmpParams, { - page_id: pageId, - revision_id: revisionId, - body: markdown, - }); - - const res: any = await apiPost('/pages.update', params); - if (!res.ok) { - throw new Error(res.error); - } - return res; -}; - -type PageInfo= { - path: string, - pageId: Nullable, - revisionId: Nullable, -} - -type SaveOrUpdateFunction = (markdown: string, pageInfo: PageInfo, optionsToSave?: OptionsToSave) => any; - -// TODO: define return type -export const useSaveOrUpdate = (): SaveOrUpdateFunction => { - /* eslint-disable react-hooks/rules-of-hooks */ - const { mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning(); - /* eslint-enable react-hooks/rules-of-hooks */ - - return useCallback(async(markdown: string, pageInfo: PageInfo, optionsToSave?: OptionsToSave) => { - const { path, pageId, revisionId } = pageInfo; - - const options: OptionsToSave = Object.assign({}, optionsToSave); - /* - * Note: variable "markdown" will be received from params - * please delete the following code after implemating HackMD editor function - */ - // let markdown; - // if (editorMode === EditorMode.HackMD) { - // const pageEditorByHackmd = this.appContainer.getComponentInstance('PageEditorByHackmd'); - // markdown = await pageEditorByHackmd.getMarkdown(); - // // set option to sync - // options.isSyncRevisionToHackmd = true; - // revisionId = this.state.revisionIdHackmdSynced; - // } - // else { - // const pageEditor = this.appContainer.getComponentInstance('PageEditor'); - // const pageEditor = getComponentInstance('PageEditor'); - // markdown = pageEditor.getMarkdown(); - // } - - let res; - if (pageId == null || revisionId == null) { - res = await createPage(path, markdown, options); - } - else { - if (revisionId == null) { - const msg = '\'revisionId\' is required to update page'; - throw new Error(msg); - } - res = await updatePage(pageId, revisionId, markdown, options); - } - - // The updateFn should be a promise or asynchronous function to handle the remote mutation - // it should return updated data. see: https://swr.vercel.app/docs/mutation#optimistic-updates - // Moreover, `async() => false` does not work since it's too fast to be calculated. - await mutateIsEnabledUnsavedWarning(new Promise(r => setTimeout(() => r(false), 10)), { optimisticData: () => false }); - - return res; - }, [mutateIsEnabledUnsavedWarning]); +export const createPage = async(params: IApiv3PageCreateParams): Promise => { + const res = await apiv3Post('/page', params); + return res.data; }; export type UpdateStateAfterSaveOption = { @@ -198,7 +120,7 @@ export const useUpdateStateAfterSave = (pageId: string|undefined|null, opts?: Up await mutateCurrentPageId(pageId); const updatedPage = await mutateCurrentPage(); - if (updatedPage == null) { return } + if (updatedPage == null || updatedPage.revision == null) { return } // supress to mutate only when updated from built-in editor // and see: https://github.com/weseek/growi/pull/7118 @@ -212,8 +134,6 @@ export const useUpdateStateAfterSave = (pageId: string|undefined|null, opts?: Up remoteRevisionBody: updatedPage.revision.body, remoteRevisionLastUpdateUser: updatedPage.lastUpdateUser, remoteRevisionLastUpdatedAt: updatedPage.updatedAt, - revisionIdHackmdSynced: updatedPage.revisionHackmdSynced?.toString(), - hasDraftOnHackmd: updatedPage.hasDraftOnHackmd, }; setRemoteLatestPageData(remoterevisionData); @@ -225,3 +145,23 @@ export const useUpdateStateAfterSave = (pageId: string|undefined|null, opts?: Up export const unlink = async(path: string): Promise => { await apiPost('/pages.unlink', { path }); }; + + +interface PageExistResponse { + isExist: boolean, +} + +export const exist = async(path: string): Promise => { + const res = await apiv3Get('/page/exist', { path }); + return res.data; +}; + +export const publish = async(pageId: string): Promise => { + const res = await apiv3Put(`/page/${pageId}/publish`); + return res.data; +}; + +export const unpublish = async(pageId: string): Promise => { + const res = await apiv3Put(`/page/${pageId}/unpublish`); + return res.data; +}; diff --git a/apps/app/src/client/services/side-effects/drawio-modal-launcher-for-view.ts b/apps/app/src/client/services/side-effects/drawio-modal-launcher-for-view.ts index df5890d1843..906b9a572b8 100644 --- a/apps/app/src/client/services/side-effects/drawio-modal-launcher-for-view.ts +++ b/apps/app/src/client/services/side-effects/drawio-modal-launcher-for-view.ts @@ -1,15 +1,16 @@ import { useCallback, useEffect } from 'react'; -import EventEmitter from 'events'; +import type EventEmitter from 'events'; +import { Origin } from '@growi/core'; import type { DrawioEditByViewerProps } from '@growi/remark-drawio'; -import { useSaveOrUpdate } from '~/client/services/page-operation'; -import mdu from '~/components/PageEditor/MarkdownDrawioUtil'; -import type { OptionsToSave } from '~/interfaces/page-operation'; +import { extractRemoteRevisionDataFromErrorObj, updatePage as _updatePage } from '~/client/services/update-page'; +import { replaceDrawioInMarkdown } from '~/components/Page/markdown-drawio-util-for-view'; import { useShareLinkId } from '~/stores/context'; -import { useDrawioModal } from '~/stores/modal'; -import { useSWRxCurrentPage, useSWRxTagsInfo } from '~/stores/page'; +import { useConflictDiffModal, useDrawioModal } from '~/stores/modal'; +import { useSWRxCurrentPage } from '~/stores/page'; +import { type RemoteRevisionData, useSetRemoteLatestPageData } from '~/stores/remote-latest-page'; import loggerFactory from '~/utils/logger'; @@ -30,51 +31,70 @@ export const useDrawioModalLauncherForView = (opts?: { const { data: shareLinkId } = useShareLinkId(); const { data: currentPage } = useSWRxCurrentPage(); - const { data: tagsInfo } = useSWRxTagsInfo(currentPage?._id); const { open: openDrawioModal } = useDrawioModal(); - const saveOrUpdate = useSaveOrUpdate(); + const { open: openConflictDiffModal, close: closeConflictDiffModal } = useConflictDiffModal(); - const saveByDrawioModal = useCallback(async(drawioMxFile: string, bol: number, eol: number) => { - if (currentPage == null || tagsInfo == null || shareLinkId != null) { + const { setRemoteLatestPageData } = useSetRemoteLatestPageData(); + + // eslint-disable-next-line max-len + const updatePage = useCallback(async(revisionId:string, newMarkdown: string, onConflict: (conflictData: RemoteRevisionData, newMarkdown: string) => void) => { + if (currentPage == null || currentPage.revision == null || shareLinkId != null) { return; } - const currentMarkdown = currentPage.revision.body; - const newMarkdown = mdu.replaceDrawioInMarkdown(drawioMxFile, currentMarkdown, bol, eol); - - const grantUserGroupIds = currentPage.grantedGroups.map((g) => { - return { - type: g.type, - item: g.item._id, - }; - }); - - const optionsToSave: OptionsToSave = { - isSlackEnabled: false, - slackChannels: '', - grant: currentPage.grant, - grantUserGroupIds, - pageTags: tagsInfo.tags, - }; - try { - const currentRevisionId = currentPage.revision._id; - await saveOrUpdate( - newMarkdown, - { pageId: currentPage._id, path: currentPage.path, revisionId: currentRevisionId }, - optionsToSave, - ); - + await _updatePage({ + pageId: currentPage._id, + revisionId, + body: newMarkdown, + origin: Origin.View, + }); + + closeConflictDiffModal(); opts?.onSaveSuccess?.(); } catch (error) { + const remoteRevidsionData = extractRemoteRevisionDataFromErrorObj(error); + if (remoteRevidsionData != null) { + onConflict(remoteRevidsionData, newMarkdown); + } + logger.error('failed to save', error); opts?.onSaveError?.(error); } - }, [currentPage, opts, saveOrUpdate, shareLinkId, tagsInfo]); + }, [closeConflictDiffModal, currentPage, opts, shareLinkId]); + + // eslint-disable-next-line max-len + const generateResolveConflictHandler = useCallback((revisionId: string, onConflict: (conflictData: RemoteRevisionData, newMarkdown: string) => void) => { + return async(newMarkdown: string) => { + await updatePage(revisionId, newMarkdown, onConflict); + }; + }, [updatePage]); + + const onConflictHandler = useCallback((remoteRevidsionData: RemoteRevisionData, newMarkdown: string) => { + setRemoteLatestPageData(remoteRevidsionData); + + const resolveConflictHandler = generateResolveConflictHandler(remoteRevidsionData.remoteRevisionId, onConflictHandler); + if (resolveConflictHandler == null) { + return; + } + + openConflictDiffModal(newMarkdown, resolveConflictHandler); + }, [generateResolveConflictHandler, openConflictDiffModal, setRemoteLatestPageData]); + + const saveByDrawioModal = useCallback(async(drawioMxFile: string, bol: number, eol: number) => { + if (currentPage == null || currentPage.revision == null) { + return; + } + + const currentRevisionId = currentPage.revision._id; + const currentMarkdown = currentPage.revision.body; + const newMarkdown = replaceDrawioInMarkdown(drawioMxFile, currentMarkdown, bol, eol); + await updatePage(currentRevisionId, newMarkdown, onConflictHandler); + }, [currentPage, onConflictHandler, updatePage]); // set handler to open DrawioModal useEffect(() => { diff --git a/apps/app/src/client/services/side-effects/hackmd-draft-updated.ts b/apps/app/src/client/services/side-effects/hackmd-draft-updated.ts deleted file mode 100644 index 3699fb52f0c..00000000000 --- a/apps/app/src/client/services/side-effects/hackmd-draft-updated.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useCallback, useEffect } from 'react'; - -import { SocketEventName } from '~/interfaces/websocket'; -import { useIsHackmdDraftUpdatingInRealtime } from '~/stores/hackmd'; -import { useCurrentPageId } from '~/stores/page'; -import { useGlobalSocket } from '~/stores/websocket'; - -export const useHackmdDraftUpdatedEffect = (): void => { - - const { data: currentPageId } = useCurrentPageId(); - const { mutate: mutateIsHackmdDraftUpdatingInRealtime } = useIsHackmdDraftUpdatingInRealtime(); - - const { data: socket } = useGlobalSocket(); - - const setIsHackmdDraftUpdatingInRealtime = useCallback((data) => { - const { s2cMessagePageUpdated } = data; - if (s2cMessagePageUpdated.pageId === currentPageId) { - mutateIsHackmdDraftUpdatingInRealtime(true); - } - }, [currentPageId, mutateIsHackmdDraftUpdatingInRealtime]); - - // listen socket for hackmd saved - useEffect(() => { - - if (socket == null) { return } - - socket.on(SocketEventName.EditingWithHackmd, setIsHackmdDraftUpdatingInRealtime); - - return () => { - socket.off(SocketEventName.EditingWithHackmd, setIsHackmdDraftUpdatingInRealtime); - }; - }, [setIsHackmdDraftUpdatingInRealtime, socket]); -}; diff --git a/apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts b/apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts index e8cbdcfa213..63cdf90ec89 100644 --- a/apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts +++ b/apps/app/src/client/services/side-effects/handsontable-modal-launcher-for-view.ts @@ -1,14 +1,16 @@ import { useCallback, useEffect } from 'react'; -import EventEmitter from 'events'; +import type EventEmitter from 'events'; -import MarkdownTable from '~/client/models/MarkdownTable'; -import { useSaveOrUpdate } from '~/client/services/page-operation'; -import mtu from '~/components/PageEditor/MarkdownTableUtil'; -import type { OptionsToSave } from '~/interfaces/page-operation'; +import { Origin } from '@growi/core'; + +import type MarkdownTable from '~/client/models/MarkdownTable'; +import { extractRemoteRevisionDataFromErrorObj, updatePage as _updatePage } from '~/client/services/update-page'; +import { getMarkdownTableFromLine, replaceMarkdownTableInMarkdown } from '~/components/Page/markdown-table-util-for-view'; import { useShareLinkId } from '~/stores/context'; -import { useHandsontableModal } from '~/stores/modal'; -import { useSWRxCurrentPage, useSWRxTagsInfo } from '~/stores/page'; +import { useHandsontableModal, useConflictDiffModal } from '~/stores/modal'; +import { useSWRxCurrentPage } from '~/stores/page'; +import { type RemoteRevisionData, useSetRemoteLatestPageData } from '~/stores/remote-latest-page'; import loggerFactory from '~/utils/logger'; @@ -29,51 +31,70 @@ export const useHandsontableModalLauncherForView = (opts?: { const { data: shareLinkId } = useShareLinkId(); const { data: currentPage } = useSWRxCurrentPage(); - const { data: tagsInfo } = useSWRxTagsInfo(currentPage?._id); const { open: openHandsontableModal } = useHandsontableModal(); - const saveOrUpdate = useSaveOrUpdate(); + const { open: openConflictDiffModal, close: closeConflictDiffModal } = useConflictDiffModal(); - const saveByHandsontableModal = useCallback(async(table: MarkdownTable, bol: number, eol: number) => { - if (currentPage == null || tagsInfo == null || shareLinkId != null) { + const { setRemoteLatestPageData } = useSetRemoteLatestPageData(); + + // eslint-disable-next-line max-len + const updatePage = useCallback(async(revisionId:string, newMarkdown: string, onConflict: (conflictData: RemoteRevisionData, newMarkdown: string) => void) => { + if (currentPage == null || currentPage.revision == null || shareLinkId != null) { return; } - const currentMarkdown = currentPage.revision.body; - const newMarkdown = mtu.replaceMarkdownTableInMarkdown(table, currentMarkdown, bol, eol); - - const grantUserGroupIds = currentPage.grantedGroups.map((g) => { - return { - type: g.type, - item: g.item._id, - }; - }); - - const optionsToSave: OptionsToSave = { - isSlackEnabled: false, - slackChannels: '', - grant: currentPage.grant, - grantUserGroupIds, - pageTags: tagsInfo.tags, - }; - try { - const currentRevisionId = currentPage.revision._id; - await saveOrUpdate( - newMarkdown, - { pageId: currentPage._id, path: currentPage.path, revisionId: currentRevisionId }, - optionsToSave, - ); - + await _updatePage({ + pageId: currentPage._id, + revisionId, + body: newMarkdown, + origin: Origin.View, + }); + + closeConflictDiffModal(); opts?.onSaveSuccess?.(); } catch (error) { + const remoteRevidsionData = extractRemoteRevisionDataFromErrorObj(error); + if (remoteRevidsionData != null) { + onConflict?.(remoteRevidsionData, newMarkdown); + } + logger.error('failed to save', error); opts?.onSaveError?.(error); } - }, [currentPage, opts, saveOrUpdate, shareLinkId, tagsInfo]); + }, [closeConflictDiffModal, currentPage, opts, shareLinkId]); + + // eslint-disable-next-line max-len + const generateResolveConflictHandler = useCallback((revisionId: string, onConflict: (conflictData: RemoteRevisionData, newMarkdown: string) => void) => { + return async(newMarkdown: string) => { + await updatePage(revisionId, newMarkdown, onConflict); + }; + }, [updatePage]); + + const onConflictHandler = useCallback((remoteRevidsionData: RemoteRevisionData, newMarkdown: string) => { + setRemoteLatestPageData(remoteRevidsionData); + + const resolveConflictHandler = generateResolveConflictHandler(remoteRevidsionData.remoteRevisionId, onConflictHandler); + if (resolveConflictHandler == null) { + return; + } + openConflictDiffModal(newMarkdown, resolveConflictHandler); + }, [generateResolveConflictHandler, openConflictDiffModal, setRemoteLatestPageData]); + + const saveByHandsontableModal = useCallback(async(table: MarkdownTable, bol: number, eol: number) => { + if (currentPage == null || currentPage.revision == null) { + return; + } + + const currentRevisionId = currentPage.revision._id; + const currentMarkdown = currentPage.revision.body; + const newMarkdown = replaceMarkdownTableInMarkdown(table, currentMarkdown, bol, eol); + + await updatePage(currentRevisionId, newMarkdown, onConflictHandler); + }, [currentPage, onConflictHandler, updatePage]); // set handler to open HandsonTableModal useEffect(() => { @@ -82,9 +103,11 @@ export const useHandsontableModalLauncherForView = (opts?: { } const handler = (bol: number, eol: number) => { + if (currentPage.revision == null) return; + const markdown = currentPage.revision.body; - const currentMarkdownTable = mtu.getMarkdownTableFromLine(markdown, bol, eol); - openHandsontableModal(currentMarkdownTable, undefined, false, table => saveByHandsontableModal(table, bol, eol)); + const currentMarkdownTable = getMarkdownTableFromLine(markdown, bol, eol); + openHandsontableModal(currentMarkdownTable, false, table => saveByHandsontableModal(table, bol, eol)); }; globalEmitter.on('launchHandsonTableModal', handler); diff --git a/apps/app/src/client/services/side-effects/page-updated.ts b/apps/app/src/client/services/side-effects/page-updated.ts index 19fe05cd7ab..767b7ac8048 100644 --- a/apps/app/src/client/services/side-effects/page-updated.ts +++ b/apps/app/src/client/services/side-effects/page-updated.ts @@ -1,45 +1,65 @@ import { useCallback, useEffect } from 'react'; +import { useGlobalSocket } from '@growi/core/dist/swr'; + import { SocketEventName } from '~/interfaces/websocket'; -import { useCurrentPageId } from '~/stores/page'; -import { useSetRemoteLatestPageData } from '~/stores/remote-latest-page'; -import { useGlobalSocket } from '~/stores/websocket'; +import { usePageStatusAlert } from '~/stores/alert'; +import { useSWRxCurrentPage, useSWRMUTxCurrentPage } from '~/stores/page'; +import { useSetRemoteLatestPageData, type RemoteRevisionData } from '~/stores/remote-latest-page'; +import { useEditorMode, EditorMode } from '~/stores/ui'; + export const usePageUpdatedEffect = (): void => { const { setRemoteLatestPageData } = useSetRemoteLatestPageData(); const { data: socket } = useGlobalSocket(); - const { data: currentPageId } = useCurrentPageId(); + const { data: editorMode } = useEditorMode(); + const { data: currentPage } = useSWRxCurrentPage(); + const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); + const { open: openPageStatusAlert, close: closePageStatusAlert } = usePageStatusAlert(); - const setLatestRemotePageData = useCallback((data) => { + const remotePageDataUpdateHandler = useCallback((data) => { + // Set remote page data const { s2cMessagePageUpdated } = data; - const remoteData = { + const remoteData: RemoteRevisionData = { remoteRevisionId: s2cMessagePageUpdated.revisionId, remoteRevisionBody: s2cMessagePageUpdated.revisionBody, remoteRevisionLastUpdateUser: s2cMessagePageUpdated.remoteLastUpdateUser, remoteRevisionLastUpdatedAt: s2cMessagePageUpdated.revisionUpdateAt, - revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced, - hasDraftOnHackmd: s2cMessagePageUpdated.hasDraftOnHackmd, }; - if (currentPageId != null && currentPageId === s2cMessagePageUpdated.pageId) { + if (currentPage?._id != null && currentPage._id === s2cMessagePageUpdated.pageId) { setRemoteLatestPageData(remoteData); - } - }, [currentPageId, setRemoteLatestPageData]); + // Open PageStatusAlert + const currentRevisionId = currentPage?.revision?._id; + const remoteRevisionId = s2cMessagePageUpdated.revisionId; + const isRevisionOutdated = (currentRevisionId != null || remoteRevisionId != null) && currentRevisionId !== remoteRevisionId; + + // !!CAUTION!! Timing of calling openPageStatusAlert may clash with components/PageEditor/conflict.tsx + if (isRevisionOutdated && editorMode === EditorMode.View) { + openPageStatusAlert({ hideEditorMode: EditorMode.Editor, onRefleshPage: mutateCurrentPage }); + } + + // Clear cache + if (!isRevisionOutdated) { + closePageStatusAlert(); + } + } + }, [currentPage?._id, currentPage?.revision?._id, editorMode, mutateCurrentPage, openPageStatusAlert, closePageStatusAlert, setRemoteLatestPageData]); // listen socket for someone updating this page useEffect(() => { if (socket == null) { return } - socket.on(SocketEventName.PageUpdated, setLatestRemotePageData); + socket.on(SocketEventName.PageUpdated, remotePageDataUpdateHandler); return () => { - socket.off(SocketEventName.PageUpdated, setLatestRemotePageData); + socket.off(SocketEventName.PageUpdated, remotePageDataUpdateHandler); }; - }, [setLatestRemotePageData, socket]); + }, [remotePageDataUpdateHandler, socket]); }; diff --git a/apps/app/src/client/services/update-page/conflict.tsx b/apps/app/src/client/services/update-page/conflict.tsx new file mode 100644 index 00000000000..5827b805382 --- /dev/null +++ b/apps/app/src/client/services/update-page/conflict.tsx @@ -0,0 +1,22 @@ +import type { ErrorV3 } from '@growi/core/dist/models'; + +import { PageUpdateErrorCode } from '~/interfaces/apiv3'; +import { type RemoteRevisionData } from '~/stores/remote-latest-page'; + +export const extractRemoteRevisionDataFromErrorObj = (errors: Array): RemoteRevisionData | undefined => { + for (const error of errors) { + if (error.code === PageUpdateErrorCode.CONFLICT) { + + const latestRevision = error.args.returnLatestRevision; + + const remoteRevidsionData = { + remoteRevisionId: latestRevision.revisionId, + remoteRevisionBody: latestRevision.revisionBody, + remoteRevisionLastUpdateUser: latestRevision.user, + remoteRevisionLastUpdatedAt: latestRevision.createdAt, + }; + + return remoteRevidsionData; + } + } +}; diff --git a/apps/app/src/client/services/update-page/index.ts b/apps/app/src/client/services/update-page/index.ts new file mode 100644 index 00000000000..c7c8f67fb30 --- /dev/null +++ b/apps/app/src/client/services/update-page/index.ts @@ -0,0 +1,9 @@ +import { apiv3Put } from '~/client/util/apiv3-client'; +import type { IApiv3PageUpdateParams, IApiv3PageUpdateResponse } from '~/interfaces/apiv3'; + +export * from './conflict'; + +export const updatePage = async(params: IApiv3PageUpdateParams): Promise => { + const res = await apiv3Put('/page', params); + return res.data; +}; diff --git a/apps/app/src/client/services/use-toastr-on-error.tsx b/apps/app/src/client/services/use-toastr-on-error.tsx new file mode 100644 index 00000000000..3449583ae62 --- /dev/null +++ b/apps/app/src/client/services/use-toastr-on-error.tsx @@ -0,0 +1,18 @@ +import { useCallback } from 'react'; + +import { useTranslation } from 'react-i18next'; + +import { toastError } from '~/client/util/toastr'; + +export const useToastrOnError = (method?: (param?: P) => Promise): (param?: P) => Promise => { + const { t } = useTranslation('commons'); + + return useCallback(async(param) => { + try { + return await method?.(param); + } + catch (err) { + toastError(t('toaster.create_failed', { target: 'a page' })); + } + }, [method, t]); +}; diff --git a/apps/app/src/client/services/user-ui-settings.ts b/apps/app/src/client/services/user-ui-settings.ts index dbd951f86ec..2905e44492c 100644 --- a/apps/app/src/client/services/user-ui-settings.ts +++ b/apps/app/src/client/services/user-ui-settings.ts @@ -17,22 +17,17 @@ const _putUserUISettingsInBulk = (): Promise> => const _putUserUISettingsInBulkDebounced = debounce(1500, _putUserUISettingsInBulk); -type ScheduleToPutFunction = (settings: Partial) => Promise>; -const scheduleToPut: ScheduleToPutFunction = (settings: Partial): Promise> => { +export const scheduleToPut = (settings: Partial): void => { settingsForBulk = { ...settingsForBulk, ...settings, }; - return _putUserUISettingsInBulkDebounced(); + _putUserUISettingsInBulkDebounced(); }; -type UserUISettingsUtil = { - scheduleToPut: ScheduleToPutFunction | (() => void), -} -export const useUserUISettings = (): UserUISettingsUtil => { +export const updateUserUISettings = async(settings: Partial): Promise> => { + const result = await apiv3Put('/user-ui-settings', { settings }); - return { - scheduleToPut, - }; + return result; }; diff --git a/apps/app/src/client/util/apiv1-client.ts b/apps/app/src/client/util/apiv1-client.ts index e429482f121..9769e64a379 100644 --- a/apps/app/src/client/util/apiv1-client.ts +++ b/apps/app/src/client/util/apiv1-client.ts @@ -1,4 +1,4 @@ -import * as urljoin from 'url-join'; +import urljoin from 'url-join'; import axios from '~/utils/axios'; diff --git a/apps/app/src/client/util/apiv3-client.ts b/apps/app/src/client/util/apiv3-client.ts index ee7682d8926..88f814a4fca 100644 --- a/apps/app/src/client/util/apiv3-client.ts +++ b/apps/app/src/client/util/apiv3-client.ts @@ -1,6 +1,6 @@ // eslint-disable-next-line no-restricted-imports import { AxiosResponse } from 'axios'; -import * as urljoin from 'url-join'; +import urljoin from 'url-join'; // eslint-disable-next-line no-restricted-imports diff --git a/apps/app/src/client/util/bookmark-utils.ts b/apps/app/src/client/util/bookmark-utils.ts index fd95b50c184..80e4b33c305 100644 --- a/apps/app/src/client/util/bookmark-utils.ts +++ b/apps/app/src/client/util/bookmark-utils.ts @@ -1,6 +1,6 @@ import type { IRevision, Ref } from '@growi/core'; -import { BookmarkFolderItems } from '~/interfaces/bookmark-info'; +import type { BookmarkFolderItems } from '~/interfaces/bookmark-info'; import { apiv3Delete, apiv3Post, apiv3Put } from './apiv3-client'; @@ -31,7 +31,7 @@ export const deleteBookmarkFolder = async(bookmarkFolderId: string): Promise, newPagePath: string): Promise => { +export const renamePage = async(pageId: string, revisionId: Ref | undefined, newPagePath: string): Promise => { await apiv3Put('/pages/rename', { pageId, revisionId, newPagePath }); }; diff --git a/apps/app/src/client/util/codemirror/autorefresh.ext.js b/apps/app/src/client/util/codemirror/autorefresh.ext.js deleted file mode 100644 index fc0d32e0fbe..00000000000 --- a/apps/app/src/client/util/codemirror/autorefresh.ext.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * extends codemirror/addon/display/autorefresh - * - * @author Yuki Takei - * @see https://codemirror.net/addon/display/autorefresh.js - * @see https://github.com/scniro/react-codemirror2/issues/83#issuecomment-398825212 - */ -/* eslint-disable */ - -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - mod(require("codemirror")); -})(function(CodeMirror) { - "use strict" - - CodeMirror.defineOption("autoRefresh", false, function(cm, val) { - if (cm.state.autoRefresh) { - stopListening(cm, cm.state.autoRefresh) - cm.state.autoRefresh = null - } - if (val && (val.force || cm.display.wrapper.offsetHeight == 0)) - startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250}) - }) - - function startListening(cm, state) { - function check() { - if (cm.display.wrapper.offsetHeight) { - stopListening(cm, state) - if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight) - cm.refresh() - } else { - state.timeout = setTimeout(check, state.delay) - } - } - state.timeout = setTimeout(check, state.delay) - state.hurry = function() { - clearTimeout(state.timeout) - state.timeout = setTimeout(check, 50) - } - CodeMirror.on(window, "mouseup", state.hurry) - CodeMirror.on(window, "keyup", state.hurry) - } - - function stopListening(_cm, state) { - clearTimeout(state.timeout) - CodeMirror.off(window, "mouseup", state.hurry) - CodeMirror.off(window, "keyup", state.hurry) - } -}); diff --git a/apps/app/src/client/util/codemirror/drawio-fold.ext.js b/apps/app/src/client/util/codemirror/drawio-fold.ext.js deleted file mode 100644 index 3a39e478c61..00000000000 --- a/apps/app/src/client/util/codemirror/drawio-fold.ext.js +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable */ - -import mdu from '../../../components/PageEditor/MarkdownDrawioUtil.js'; - -(function(mod) { - mod(require("codemirror")); -})(function(CodeMirror) { - "use strict" - - CodeMirror.registerGlobalHelper('fold', 'drawio', function (mode, cm) { - return true; - }, function(cm, start) { - function isBeginningOfDrawio(lineNo) { - let line = cm.getLine(lineNo); - let match = mdu.lineBeginPartOfDrawioRE.exec(line); - if (match) { - return true; - } - return false; - } - function isEndOfDrawio(lineNo) { - let line = cm.getLine(lineNo); - let match = mdu.lineEndPartOfDrawioRE.exec(line); - if (match) { - return true; - } - return false; - } - - let drawio = isBeginningOfDrawio(start.line); - if (drawio === false) { return; } - - let lastLine = cm.lastLine(); - let end = start.line; - while(end < lastLine) { - end += 1; - if (isEndOfDrawio(end)) { - break; - } - } - - return { - from: CodeMirror.Pos(start.line, cm.getLine(start.line).length), - to: CodeMirror.Pos(end, cm.getLine(end).length) - }; - }); -}); diff --git a/apps/app/src/client/util/codemirror/gfm-growi.mode.js b/apps/app/src/client/util/codemirror/gfm-growi.mode.js deleted file mode 100644 index fc1944881df..00000000000 --- a/apps/app/src/client/util/codemirror/gfm-growi.mode.js +++ /dev/null @@ -1,19 +0,0 @@ -// https://discuss.codemirror.net/t/cm-header-margin-padding-height/75/5 -window.CodeMirror.defineMode('gfm-growi', (cmConfig, modeCfg) => { - // based on Markdown (GitHub-flavour) mode - // https://codemirror.net/doc/manual.html#option_mode - // https://codemirror.net/mode/index.html - modeCfg.name = 'gfm'; - modeCfg.highlightFormatting = true; - const mode = window.CodeMirror.getMode(cmConfig, modeCfg); - - const origToken = mode.token; - mode.token = function(stream, state) { - let classes = origToken(stream, state) || ''; - // https://regex101.com/r/Fep0w2/1 - classes = classes.replace(/(^| )header(\S*)/g, '$1header$2 line-grw-cm-header-line'); - return /^\s*$/.test(classes) ? null : classes; - }; - - return mode; -}); diff --git a/apps/app/src/client/util/codemirror/update-display-util.ext.js b/apps/app/src/client/util/codemirror/update-display-util.ext.js deleted file mode 100644 index b23a40a8839..00000000000 --- a/apps/app/src/client/util/codemirror/update-display-util.ext.js +++ /dev/null @@ -1,41 +0,0 @@ -import { sawCollapsedSpans } from 'codemirror/src/line/saw_special_spans'; -import { getLine } from 'codemirror/src/line/utils_line'; -import { heightAtLine, visualLineEndNo, visualLineNo } from 'codemirror/src/line/spans'; -import { DisplayUpdate } from 'codemirror/src/display/update_display'; -import { adjustView } from 'codemirror/src/display/view_tracking'; - -class UpdateDisplayUtil { - - /** - * Transplant 'updateDisplayIfNeeded' method to fix weseek/growi#703 - * - * @see https://github.com/weseek/growi/issues/703 - * @see https://github.com/codemirror/CodeMirror/blob/5.42.0/src/display/update_display.js#L125 - * - * @param {CodeMirror} cm - */ - static forceUpdateViewOffset(cm) { - const doc = cm.doc; - const display = cm.display; - - const update = new DisplayUpdate(cm, cm.getViewport()); - - // Compute a suitable new viewport (from & to) - const end = doc.first + doc.size; - let from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); - let to = Math.min(end, update.visible.to + cm.options.viewportMargin); - if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); - if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from); - to = visualLineEndNo(cm.doc, to); - } - adjustView(cm, from, to); - - display.viewOffset = heightAtLine(getLine(doc, display.viewFrom)); - } - -} - - -export default UpdateDisplayUtil; diff --git a/apps/app/src/components/Admin/AdminHome/AdminHome.jsx b/apps/app/src/components/Admin/AdminHome/AdminHome.jsx index 9ecf1009f32..5e735a5a930 100644 --- a/apps/app/src/components/Admin/AdminHome/AdminHome.jsx +++ b/apps/app/src/components/Admin/AdminHome/AdminHome.jsx @@ -52,7 +52,7 @@ const AdminHome = (props) => {


- + {t('admin:maintenance_mode.end_maintenance_mode')}
@@ -65,7 +65,7 @@ const AdminHome = (props) => {
{t('admin:v5_page_migration.migration_desc')} - + {t('admin:v5_page_migration.upgrade_to_v5')}
@@ -115,7 +115,7 @@ const AdminHome = (props) => { {t('admin:admin_top:copy_prefilled_host_information:done')} {/* eslint-disable-next-line react/no-danger */} - +
diff --git a/apps/app/src/components/Admin/App/AppSetting.jsx b/apps/app/src/components/Admin/App/AppSetting.jsx index 25912f5b5f1..974cc8dcaa3 100644 --- a/apps/app/src/components/Admin/App/AppSetting.jsx +++ b/apps/app/src/components/Admin/App/AppSetting.jsx @@ -34,13 +34,13 @@ const AppSetting = (props) => { return ( -
- +
+
{ adminAppContainer.changeTitle(e.target.value); }} @@ -50,9 +50,9 @@ const AppSetting = (props) => {
-
+
@@ -60,7 +60,7 @@ const AppSetting = (props) => { { adminAppContainer.changeConfidential(e.target.value); }} @@ -70,9 +70,9 @@ const AppSetting = (props) => {
-
+
@@ -83,11 +83,11 @@ const AppSetting = (props) => { const fixedT = i18n.getFixedT(locale, 'admin'); return ( -
+
{ adminAppContainer.changeGlobalLang(e.target.value); }} /> - +
); }) @@ -103,53 +103,53 @@ const AppSetting = (props) => {
-
+
-
+
{ adminAppContainer.changeIsEmailPublishedForNewUserShow(true) }} /> - +
-
+
{ adminAppContainer.changeIsEmailPublishedForNewUserShow(false) }} /> - +
-
+
-
+
{ @@ -157,7 +157,7 @@ const AppSetting = (props) => { }} />
diff --git a/apps/app/src/components/Admin/App/AwsSetting.tsx b/apps/app/src/components/Admin/App/AwsSetting.tsx index 9e2bf482c27..71dd2368c17 100644 --- a/apps/app/src/components/Admin/App/AwsSetting.tsx +++ b/apps/app/src/components/Admin/App/AwsSetting.tsx @@ -21,8 +21,8 @@ export const AwsSettingMolecule = (props: AwsSettingMoleculeProps): JSX.Element return ( <> -
-
-
-