mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-04-05 00:56:32 +00:00
Merge branch 'main' into refactor-tab-layout
This commit is contained in:
commit
4fb350c7a7
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@ -27,6 +27,10 @@ updates:
|
|||||||
- "@tiptap/pm"
|
- "@tiptap/pm"
|
||||||
- "@tiptap/react"
|
- "@tiptap/react"
|
||||||
- "@tiptap/starter-kit"
|
- "@tiptap/starter-kit"
|
||||||
|
vitest-ecosystem:
|
||||||
|
patterns:
|
||||||
|
- "vitest"
|
||||||
|
- "@vitest/*"
|
||||||
labels:
|
labels:
|
||||||
- "dependencies"
|
- "dependencies"
|
||||||
- "javascript"
|
- "javascript"
|
||||||
|
|||||||
4
.github/workflows/deploy.docs.yml
vendored
4
.github/workflows/deploy.docs.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
|||||||
# Specify runner + build & upload the static files as an artifact
|
# Specify runner + build & upload the static files as an artifact
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Install Dependencies & Build Library
|
- name: Install Dependencies & Build Library
|
||||||
|
|||||||
8
.github/workflows/test.backend.seed.yml
vendored
8
.github/workflows/test.backend.seed.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
changes: ${{ steps.filter.outputs.match }}
|
changes: ${{ steps.filter.outputs.match }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -27,10 +27,10 @@ jobs:
|
|||||||
WORKING_DIRECTORY: ./
|
WORKING_DIRECTORY: ./
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ jobs:
|
|||||||
# WORKING_DIRECTORY: ./
|
# WORKING_DIRECTORY: ./
|
||||||
# steps:
|
# steps:
|
||||||
# - name: Checkout code
|
# - name: Checkout code
|
||||||
# uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
#
|
#
|
||||||
# - name: Build Docker Development
|
# - name: Build Docker Development
|
||||||
# run: docker compose build
|
# run: docker compose build
|
||||||
|
|||||||
6
.github/workflows/test.build.docker.yml
vendored
6
.github/workflows/test.build.docker.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
changes: ${{ steps.filter.outputs.build-docker }}
|
changes: ${{ steps.filter.outputs.build-docker }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -27,7 +27,7 @@ jobs:
|
|||||||
WORKING_DIRECTORY: ./
|
WORKING_DIRECTORY: ./
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
|
|
||||||
- name: Build Docker Production
|
- name: Build Docker Production
|
||||||
run: docker compose -f docker-compose.yml build
|
run: docker compose -f docker-compose.yml build
|
||||||
@ -42,7 +42,7 @@ jobs:
|
|||||||
# WORKING_DIRECTORY: ./
|
# WORKING_DIRECTORY: ./
|
||||||
# steps:
|
# steps:
|
||||||
# - name: Checkout code
|
# - name: Checkout code
|
||||||
# uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
#
|
#
|
||||||
# - name: Build Docker Development
|
# - name: Build Docker Development
|
||||||
# run: docker compose build
|
# run: docker compose build
|
||||||
|
|||||||
10
.github/workflows/test.build.lib.yml
vendored
10
.github/workflows/test.build.lib.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
build: ${{ steps.filter.outputs.build }}
|
build: ${{ steps.filter.outputs.build }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -24,8 +24,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Install Dependencies & Build Library
|
- name: Install Dependencies & Build Library
|
||||||
@ -44,8 +44,8 @@ jobs:
|
|||||||
app: [examples/1-basic-map, examples/2-static-layers, examples/3-tags ]
|
app: [examples/1-basic-map, examples/2-static-layers, examples/3-tags ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Link Utopia-UI in Example App
|
- name: Link Utopia-UI in Example App
|
||||||
|
|||||||
10
.github/workflows/test.docs.lib.yml
vendored
10
.github/workflows/test.docs.lib.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
docs: ${{ steps.filter.outputs.docs }}
|
docs: ${{ steps.filter.outputs.docs }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -25,8 +25,8 @@ jobs:
|
|||||||
# needs: files-changed
|
# needs: files-changed
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
# - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
# - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
# - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
# with:
|
# with:
|
||||||
# node-version-file: './.tool-versions'
|
# node-version-file: './.tool-versions'
|
||||||
# - name: Frontend | Build
|
# - name: Frontend | Build
|
||||||
@ -41,8 +41,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
COVERAGE_REQUIRED: 0
|
COVERAGE_REQUIRED: 0
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Docs
|
- name: Docs
|
||||||
|
|||||||
8
.github/workflows/test.e2e.yml
vendored
8
.github/workflows/test.e2e.yml
vendored
@ -12,10 +12,10 @@ jobs:
|
|||||||
test_failed: ${{ steps.report-results.outputs.test_failed }}
|
test_failed: ${{ steps.report-results.outputs.test_failed }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5.0.0
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v5.0.0
|
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5.0.0
|
||||||
with:
|
with:
|
||||||
node-version-file: ./.tool-versions
|
node-version-file: ./.tool-versions
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@ -156,10 +156,10 @@ jobs:
|
|||||||
if: failure() && needs.cypress-e2e-tests.result == 'failure'
|
if: failure() && needs.cypress-e2e-tests.result == 'failure'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5.0.0
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v5.0.0
|
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5.0.0
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
6
.github/workflows/test.lint.cypress.yml
vendored
6
.github/workflows/test.lint.cypress.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
cypress: ${{ steps.filter.outputs.cypress }}
|
cypress: ${{ steps.filter.outputs.cypress }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.0
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5.0.0
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -25,8 +25,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.0
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5.0.0
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v5.0.0
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5.0.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
|
|||||||
6
.github/workflows/test.lint.frontend.yml
vendored
6
.github/workflows/test.lint.frontend.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
lint: ${{ steps.filter.outputs.lint }}
|
lint: ${{ steps.filter.outputs.lint }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -24,8 +24,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
|
|||||||
22
.github/workflows/test.lint.lib.examples.yml
vendored
22
.github/workflows/test.lint.lib.examples.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
lint: ${{ steps.filter.outputs.lint }}
|
lint: ${{ steps.filter.outputs.lint }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -24,8 +24,8 @@ jobs:
|
|||||||
# needs: files-changed
|
# needs: files-changed
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
# - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
# - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
# - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
# with:
|
# with:
|
||||||
# node-version-file: './.tool-versions'
|
# node-version-file: './.tool-versions'
|
||||||
# - name: Frontend | Build
|
# - name: Frontend | Build
|
||||||
@ -38,8 +38,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -52,8 +52,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -66,8 +66,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
@ -80,8 +80,8 @@ jobs:
|
|||||||
# needs: files-changed
|
# needs: files-changed
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
# - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
# - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
# - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
# with:
|
# with:
|
||||||
# node-version-file: './.tool-versions'
|
# node-version-file: './.tool-versions'
|
||||||
# - name: Frontend | Unit
|
# - name: Frontend | Unit
|
||||||
|
|||||||
6
.github/workflows/test.lint.lib.yml
vendored
6
.github/workflows/test.lint.lib.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
lint: ${{ steps.filter.outputs.lint }}
|
lint: ${{ steps.filter.outputs.lint }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -24,8 +24,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Lint
|
- name: Lint
|
||||||
|
|||||||
6
.github/workflows/test.unit.lib.yml
vendored
6
.github/workflows/test.unit.lib.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
unit: ${{ steps.filter.outputs.unit }}
|
unit: ${{ steps.filter.outputs.unit }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
@ -24,8 +24,8 @@ jobs:
|
|||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.7
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.1.7
|
||||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4.0.3
|
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.tool-versions'
|
node-version-file: '.tool-versions'
|
||||||
- name: Unit
|
- name: Unit
|
||||||
|
|||||||
@ -17,39 +17,39 @@
|
|||||||
"@heroicons/react": "^2.1.1",
|
"@heroicons/react": "^2.1.1",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@types/geojson": "^7946.0.10",
|
"@types/geojson": "^7946.0.10",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-rnd": "^10.4.1",
|
"react-rnd": "^10.4.1",
|
||||||
"react-router-dom": "^7.10.1",
|
"react-router-dom": "^7.13.0",
|
||||||
"utopia-ui": "^3.0.112",
|
"utopia-ui": "^3.0.112",
|
||||||
"vite-tsconfig-paths": "^5.1.4"
|
"vite-tsconfig-paths": "^6.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.1",
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
"@types/node": "^24.10.2",
|
"@types/node": "^25.2.0",
|
||||||
"@types/react": "^18.2.79",
|
"@types/react": "^18.2.79",
|
||||||
"@types/react-dom": "^18.2.25",
|
"@types/react-dom": "^18.2.25",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
"daisyui": "^5.5.14",
|
"daisyui": "^5.5.17",
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^9.39.2",
|
||||||
"eslint-import-resolver-typescript": "^4.4.4",
|
"eslint-import-resolver-typescript": "^4.4.4",
|
||||||
"eslint-plugin-import-x": "^4.16.1",
|
"eslint-plugin-import-x": "^4.16.1",
|
||||||
"eslint-plugin-json": "^4.0.1",
|
"eslint-plugin-json": "^4.0.1",
|
||||||
"eslint-plugin-no-catch-all": "^1.1.0",
|
"eslint-plugin-no-catch-all": "^1.1.0",
|
||||||
"eslint-plugin-prettier": "^5.5.4",
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
"eslint-plugin-promise": "^7.2.1",
|
"eslint-plugin-promise": "^7.2.1",
|
||||||
"eslint-plugin-react": "^7.31.8",
|
"eslint-plugin-react": "^7.31.8",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.4.26",
|
"eslint-plugin-react-refresh": "^0.5.0",
|
||||||
"eslint-plugin-security": "^3.0.1",
|
"eslint-plugin-security": "^3.0.1",
|
||||||
"globals": "^16.3.0",
|
"globals": "^17.3.0",
|
||||||
"postcss": "^8.4.30",
|
"postcss": "^8.4.30",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.9.0",
|
"typescript-eslint": "^8.9.0",
|
||||||
"vite": "^7.3.0",
|
"vite": "^7.3.1",
|
||||||
"vite-plugin-pwa": "^1.2.0"
|
"vite-plugin-pwa": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,17 @@ import { directusClient } from './directus'
|
|||||||
import type { MyCollections } from './directus'
|
import type { MyCollections } from './directus'
|
||||||
import type { ItemsApi } from 'utopia-ui'
|
import type { ItemsApi } from 'utopia-ui'
|
||||||
|
|
||||||
|
// Fields to request when fetching items to include all relational data
|
||||||
|
const ITEM_FIELDS = [
|
||||||
|
'*',
|
||||||
|
'secrets.*',
|
||||||
|
'to.*',
|
||||||
|
'relations.*',
|
||||||
|
'user_created.*',
|
||||||
|
'markerIcon.*',
|
||||||
|
{ offers: ['*'], needs: ['*'], gallery: ['*.*'] } as any,
|
||||||
|
]
|
||||||
|
|
||||||
export class itemsApi<T> implements ItemsApi<T> {
|
export class itemsApi<T> implements ItemsApi<T> {
|
||||||
collectionName: keyof MyCollections
|
collectionName: keyof MyCollections
|
||||||
filter: any
|
filter: any
|
||||||
@ -43,15 +54,7 @@ export class itemsApi<T> implements ItemsApi<T> {
|
|||||||
try {
|
try {
|
||||||
const result = await directusClient.request<T[]>(
|
const result = await directusClient.request<T[]>(
|
||||||
readItems(this.collectionName as never, {
|
readItems(this.collectionName as never, {
|
||||||
fields: [
|
fields: ITEM_FIELDS,
|
||||||
'*',
|
|
||||||
'secrets.*',
|
|
||||||
'to.*',
|
|
||||||
'relations.*',
|
|
||||||
'user_created.*',
|
|
||||||
'markerIcon.*',
|
|
||||||
{ offers: ['*'], needs: ['*'], gallery: ['*.*'] } as any,
|
|
||||||
],
|
|
||||||
filter: this.filter,
|
filter: this.filter,
|
||||||
limit: -1,
|
limit: -1,
|
||||||
}),
|
}),
|
||||||
@ -70,7 +73,11 @@ export class itemsApi<T> implements ItemsApi<T> {
|
|||||||
|
|
||||||
async getItem(id: string): Promise<T> {
|
async getItem(id: string): Promise<T> {
|
||||||
try {
|
try {
|
||||||
const result = await directusClient.request(readItem(this.collectionName as never, id))
|
const result = await directusClient.request(
|
||||||
|
readItem(this.collectionName as never, id, {
|
||||||
|
fields: ITEM_FIELDS,
|
||||||
|
}),
|
||||||
|
)
|
||||||
return result as T
|
return result as T
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
@ -82,13 +89,18 @@ export class itemsApi<T> implements ItemsApi<T> {
|
|||||||
async createItem(item: T & { id?: string }): Promise<T> {
|
async createItem(item: T & { id?: string }): Promise<T> {
|
||||||
try {
|
try {
|
||||||
const result = await directusClient.request(
|
const result = await directusClient.request(
|
||||||
createItem(this.collectionName, {
|
createItem(
|
||||||
...item,
|
this.collectionName,
|
||||||
...(this.customParameter && this.customParameter),
|
{
|
||||||
...(this.layerId && { layer: this.layerId }),
|
...item,
|
||||||
...(this.layerId && { layer: this.layerId }),
|
...(this.customParameter && this.customParameter),
|
||||||
...(this.mapId && { map: this.mapId }),
|
...(this.layerId && { layer: this.layerId }),
|
||||||
}),
|
...(this.mapId && { map: this.mapId }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: ITEM_FIELDS,
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return result as T
|
return result as T
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@ -100,7 +112,11 @@ export class itemsApi<T> implements ItemsApi<T> {
|
|||||||
|
|
||||||
async updateItem(item: T & { id?: string }): Promise<T> {
|
async updateItem(item: T & { id?: string }): Promise<T> {
|
||||||
try {
|
try {
|
||||||
const result = await directusClient.request(updateItem(this.collectionName, item.id!, item))
|
const result = await directusClient.request(
|
||||||
|
updateItem(this.collectionName, item.id!, item, {
|
||||||
|
fields: ITEM_FIELDS,
|
||||||
|
}),
|
||||||
|
)
|
||||||
return result as T
|
return result as T
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
|
|||||||
@ -54,48 +54,9 @@ docker exec -t utopia-map-database-1 pg_dumpall -c -U directus > dump.sql
|
|||||||
|
|
||||||
Assuming you run docker-compose with the default postgress credentials and have the dump in cwd as ./dump.sql, execute:
|
Assuming you run docker-compose with the default postgress credentials and have the dump in cwd as ./dump.sql, execute:
|
||||||
|
|
||||||
Find current schema name:
|
Drop database:
|
||||||
```
|
```
|
||||||
echo "SELECT CURRENT_SCHEMA, CURRENT_SCHEMA();" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql -v ON_ERROR_STOP=1 --username directus directus" < ./backend/scripts/drop-database.sql
|
||||||
```
|
|
||||||
> current_schema | current_schema
|
|
||||||
> ----------------+----------------
|
|
||||||
> public | public
|
|
||||||
> (1 row)
|
|
||||||
|
|
||||||
Drop schemata (loses all data):
|
|
||||||
```
|
|
||||||
echo "DROP SCHEMA public CASCADE;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
|
|
||||||
echo "DROP SCHEMA tiger CASCADE;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
|
|
||||||
echo "DROP SCHEMA tiger_data CASCADE;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
|
|
||||||
echo "DROP SCHEMA topology CASCADE;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
```
|
|
||||||
> drop cascades to table ...
|
|
||||||
> ...
|
|
||||||
> DROP SCHEMA
|
|
||||||
|
|
||||||
Create the public schema again:
|
|
||||||
```
|
|
||||||
echo "CREATE SCHEMA public;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify schemata:
|
|
||||||
```
|
|
||||||
echo "select schema_name from information_schema.schemata;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus"
|
|
||||||
```
|
|
||||||
|
|
||||||
Verify database is empty:
|
|
||||||
```
|
|
||||||
echo "\dt" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus directus"
|
|
||||||
```
|
|
||||||
> Did not find any relations.
|
|
||||||
|
|
||||||
Create admin role & grant it:
|
|
||||||
```
|
|
||||||
echo "CREATE ROLE admin;" | docker exec -i utopia-map-database-1 /bin/bash -c "PGPASSWORD=directus psql --username directus directus"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Apply dump:
|
Apply dump:
|
||||||
|
|||||||
8
backend/scripts/drop-database.sql
Normal file
8
backend/scripts/drop-database.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- CAUTION: THIS SCRIPT DROPS ALL DATA IN YOUR DATABASE!
|
||||||
|
DROP SCHEMA public CASCADE;
|
||||||
|
DROP SCHEMA tiger CASCADE;
|
||||||
|
DROP SCHEMA tiger_data CASCADE;
|
||||||
|
DROP SCHEMA topology CASCADE;
|
||||||
|
|
||||||
|
CREATE SCHEMA public;
|
||||||
|
CREATE ROLE admin;
|
||||||
3
backend/scripts/update-user-passwords.sql
Normal file
3
backend/scripts/update-user-passwords.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
-- Selects passwords and emails and creates a script to update user passwords in a database.
|
||||||
|
-- This is used to port users between instances as directus cannot import user passwords
|
||||||
|
SELECT CONCAT('UPDATE public.directus_users SET password=''', password, ''' WHERE email=''', email, ''';') FROM public.directus_users;
|
||||||
409
docs/PERFORMANCE_OPTIMIZATION_PLAN.md
Normal file
409
docs/PERFORMANCE_OPTIMIZATION_PLAN.md
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
# Performance-Optimierungsplan für Utopia Map
|
||||||
|
|
||||||
|
## Zusammenfassung der Analyse
|
||||||
|
|
||||||
|
Die Performance-Analyse hat drei Hauptbereiche mit Optimierungspotenzial identifiziert:
|
||||||
|
|
||||||
|
1. **React Component Re-Renders** - Unnötige Re-Renders durch Context-Architektur
|
||||||
|
2. **Map/Leaflet Performance** - Marker-Rendering und Clustering-Konfiguration
|
||||||
|
3. **Animations/Transitions** - CSS-Optimierungen für flüssigere Übergänge
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kritische Probleme (Höchste Priorität)
|
||||||
|
|
||||||
|
### 1. MarkerClusterGroup Konfiguration
|
||||||
|
**Datei:** `lib/src/Components/Map/UtopiaMapInner.tsx:329-337`
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// PROBLEM: Alle Marker bleiben im DOM, auch wenn off-screen
|
||||||
|
removeOutsideVisibleBounds={false}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:** `removeOutsideVisibleBounds={true}` setzen
|
||||||
|
|
||||||
|
### 2. Marker ohne Memoization
|
||||||
|
**Datei:** `lib/src/Components/Item/PopupView.tsx:95-183`
|
||||||
|
|
||||||
|
- Alle Marker werden bei jedem State-Change neu gerendert
|
||||||
|
- Inline Event-Handler erstellen neue Funktionen pro Marker
|
||||||
|
- `MarkerIconFactory` wird für jeden Marker bei jedem Render aufgerufen
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Marker-Komponente mit `React.memo` wrappen
|
||||||
|
- Event-Handler mit `useCallback` memoizen
|
||||||
|
- Icon-Erstellung mit `useMemo` cachen
|
||||||
|
|
||||||
|
### 3. Item-Mutation während Render
|
||||||
|
**Datei:** `lib/src/Components/Item/PopupView.tsx:98-106`
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// PROBLEM: Direkte Mutation des Item-Objekts
|
||||||
|
item.text += '\n\n'
|
||||||
|
item.tags.map((tag) => {
|
||||||
|
item.text += `#${encodeTag(tag)}`
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:** Immutable Kopie erstellen oder Berechnung in useMemo verschieben
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hohe Priorität
|
||||||
|
|
||||||
|
### 4. Context Provider Nesting
|
||||||
|
**Datei:** `lib/src/Components/AppShell/ContextWrapper.tsx:55-94`
|
||||||
|
|
||||||
|
10 verschachtelte Context-Provider verursachen Kaskaden-Re-Renders.
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- AppState in separate Contexts aufteilen (UI-State, Theme, Assets)
|
||||||
|
- `useMemo` für Context-Values verwenden
|
||||||
|
|
||||||
|
### 5. getItemTags O(n) Suche
|
||||||
|
**Datei:** `lib/src/Components/Map/hooks/useTags.tsx:92-118`
|
||||||
|
|
||||||
|
Lineare Suche für jeden Tag-Match bei jedem Item.
|
||||||
|
|
||||||
|
**Fix:** Map/Set für O(1) Lookups verwenden
|
||||||
|
|
||||||
|
### 6. ProfileForm teure Effect-Berechnung
|
||||||
|
**Datei:** `lib/src/Components/Profile/ProfileForm.tsx:93-143`
|
||||||
|
|
||||||
|
- Mehrere O(n) Array-Suchen
|
||||||
|
- Effect läuft bei jeder Items/Tags Änderung
|
||||||
|
|
||||||
|
**Fix:** `useMemo` für berechnete Werte
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mittlere Priorität
|
||||||
|
|
||||||
|
### 7. SetAppState - 4 separate Effects
|
||||||
|
**Datei:** `lib/src/Components/AppShell/SetAppState.tsx:20-34`
|
||||||
|
|
||||||
|
4 separate Effects statt einem gebatchten Update.
|
||||||
|
|
||||||
|
**Fix:** Zu einem Effect zusammenfassen
|
||||||
|
|
||||||
|
### 8. Fehlende React.memo
|
||||||
|
- `HeaderView` - `lib/src/Components/Map/Subcomponents/ItemPopupComponents/HeaderView/index.tsx`
|
||||||
|
- `RelationCard` - `lib/src/Components/Profile/Subcomponents/RelationCard.tsx`
|
||||||
|
- `ItemViewPopup` - `lib/src/Components/Map/Subcomponents/ItemViewPopup.tsx`
|
||||||
|
- `FlexView` Template-Komponenten - `lib/src/Components/Profile/Templates/FlexView.tsx`
|
||||||
|
|
||||||
|
### 9. GalleryView ohne useMemo
|
||||||
|
**Datei:** `lib/src/Components/Profile/Subcomponents/GalleryView.tsx:22-39`
|
||||||
|
|
||||||
|
Images-Array wird bei jedem Render neu berechnet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Animation Optimierungen
|
||||||
|
|
||||||
|
### 10. Zu lange Transition-Zeiten
|
||||||
|
**Datei:** `app/src/App.css:18-21`
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* PROBLEM: 1000ms ist zu langsam */
|
||||||
|
.transition-fade {
|
||||||
|
transition: opacity 1000ms ease;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:** Auf 300-400ms reduzieren
|
||||||
|
|
||||||
|
### 11. Margin statt Transform für Sidebar
|
||||||
|
**Dateien:**
|
||||||
|
- `lib/src/Components/AppShell/SideBar.tsx`
|
||||||
|
- `lib/src/Components/AppShell/Content.tsx`
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// PROBLEM: Margin-Transitions verursachen Layout-Reflows
|
||||||
|
tw:ml-48 tw:transition-all
|
||||||
|
|
||||||
|
// BESSER: GPU-beschleunigte Transforms
|
||||||
|
tw:translate-x-48 tw:transition-transform
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12. Modal Animation Konflikte
|
||||||
|
**Datei:** `lib/src/Components/Gaming/Modal.tsx:23-24`
|
||||||
|
|
||||||
|
`tw:transition-none` auf modal-box überschreibt Container-Transition.
|
||||||
|
|
||||||
|
### 13. DialogModal DOM-Manipulation
|
||||||
|
**Datei:** `lib/src/Components/Templates/DialogModal.tsx`
|
||||||
|
|
||||||
|
Direkte style/classList Manipulation verursacht Layout-Thrashing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Empfohlene Implementierungsreihenfolge
|
||||||
|
|
||||||
|
### Phase 1: Quick Wins (Sofort umsetzbar)
|
||||||
|
1. `removeOutsideVisibleBounds={true}` setzen
|
||||||
|
2. App.css Transition von 1000ms auf 300ms reduzieren
|
||||||
|
3. SetAppState Effects zusammenfassen
|
||||||
|
|
||||||
|
### Phase 2: Memoization (Mittlerer Aufwand)
|
||||||
|
4. Marker-Komponente mit React.memo wrappen
|
||||||
|
5. MarkerIconFactory Ergebnisse cachen
|
||||||
|
6. HeaderView, RelationCard, ItemViewPopup mit React.memo
|
||||||
|
7. GalleryView images mit useMemo
|
||||||
|
|
||||||
|
### Phase 3: Architektur (Höherer Aufwand)
|
||||||
|
8. getItemTags auf Map-basierte Lookups umstellen
|
||||||
|
9. ProfileForm Berechnungen optimieren
|
||||||
|
10. Item-Mutation in PopupView beheben
|
||||||
|
|
||||||
|
### Phase 4: CSS/Animation
|
||||||
|
11. Sidebar Margin → Transform Migration
|
||||||
|
12. Modal Animation Konflikte beheben
|
||||||
|
13. will-change Hints hinzufügen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Erwartete Verbesserungen
|
||||||
|
|
||||||
|
- **30-50% weniger Re-Renders** durch Memoization
|
||||||
|
- **Flüssigere Map-Interaktion** durch Marker-Optimierungen
|
||||||
|
- **Schnellere Übergänge** durch kürzere Transition-Zeiten
|
||||||
|
- **Weniger Layout-Thrashing** durch Transform statt Margin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kritische Dateien
|
||||||
|
|
||||||
|
| Datei | Änderungen |
|
||||||
|
|-------|------------|
|
||||||
|
| `UtopiaMapInner.tsx` | Cluster-Config, Event-Handler |
|
||||||
|
| `PopupView.tsx` | Marker-Memoization, Item-Mutation |
|
||||||
|
| `useTags.tsx` | Map-basierte Lookups |
|
||||||
|
| `ProfileForm.tsx` | useMemo für Berechnungen |
|
||||||
|
| `SetAppState.tsx` | Effects zusammenfassen |
|
||||||
|
| `App.css` | Transition-Zeiten |
|
||||||
|
| `SideBar.tsx` / `Content.tsx` | Transform statt Margin |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Messstrategie & Erfolgsmetriken
|
||||||
|
|
||||||
|
### Baseline-Messung (vor Optimierungen)
|
||||||
|
|
||||||
|
#### 1. React DevTools Profiler
|
||||||
|
```bash
|
||||||
|
# Chrome Extension: React Developer Tools
|
||||||
|
# Profiler Tab → Record → Interaktionen durchführen → Stop
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu messende Szenarien:**
|
||||||
|
- [ ] Map laden mit 100+ Markern → Render-Zeit notieren
|
||||||
|
- [ ] Filter-Tag hinzufügen/entfernen → Re-Render-Count
|
||||||
|
- [ ] Sidebar öffnen/schließen → Render-Zeit
|
||||||
|
- [ ] Item-Popup öffnen → Zeit bis vollständig gerendert
|
||||||
|
- [ ] Zwischen Items navigieren → Transition-Smoothness
|
||||||
|
|
||||||
|
**Metriken:**
|
||||||
|
| Szenario | Baseline | Nach Phase 1 | Nach Phase 2 | Ziel |
|
||||||
|
|----------|----------|--------------|--------------|------|
|
||||||
|
| Initial Map Render | ___ ms | ___ ms | ___ ms | <500ms |
|
||||||
|
| Marker Re-Renders | ___ count | ___ count | ___ count | <10 |
|
||||||
|
| Tag Filter Toggle | ___ ms | ___ ms | ___ ms | <100ms |
|
||||||
|
| Sidebar Toggle | ___ ms | ___ ms | ___ ms | <50ms |
|
||||||
|
| Popup Open | ___ ms | ___ ms | ___ ms | <200ms |
|
||||||
|
|
||||||
|
#### 2. Chrome DevTools Performance Panel
|
||||||
|
```
|
||||||
|
F12 → Performance Tab → Record → Interaktionen → Stop
|
||||||
|
```
|
||||||
|
|
||||||
|
**Zu messen:**
|
||||||
|
- **FPS während Animationen** (Ziel: konstant 60 FPS)
|
||||||
|
- **Long Tasks** (>50ms) identifizieren
|
||||||
|
- **Layout Shifts** bei Sidebar/Modal
|
||||||
|
- **Scripting vs Rendering Zeit**
|
||||||
|
|
||||||
|
#### 3. Lighthouse Performance Score
|
||||||
|
```bash
|
||||||
|
# Chrome DevTools → Lighthouse → Performance
|
||||||
|
```
|
||||||
|
|
||||||
|
**Metriken:**
|
||||||
|
| Metrik | Baseline | Ziel |
|
||||||
|
|--------|----------|------|
|
||||||
|
| Performance Score | ___ | >90 |
|
||||||
|
| First Contentful Paint | ___ s | <1.5s |
|
||||||
|
| Largest Contentful Paint | ___ s | <2.5s |
|
||||||
|
| Total Blocking Time | ___ ms | <200ms |
|
||||||
|
| Cumulative Layout Shift | ___ | <0.1 |
|
||||||
|
|
||||||
|
#### 4. Custom Performance Markers (Optional)
|
||||||
|
```tsx
|
||||||
|
// Kann in kritischen Komponenten eingefügt werden:
|
||||||
|
useEffect(() => {
|
||||||
|
performance.mark('PopupView-render-start')
|
||||||
|
return () => {
|
||||||
|
performance.mark('PopupView-render-end')
|
||||||
|
performance.measure('PopupView-render',
|
||||||
|
'PopupView-render-start',
|
||||||
|
'PopupView-render-end')
|
||||||
|
console.log(performance.getEntriesByName('PopupView-render'))
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testszenarien für Vergleich
|
||||||
|
|
||||||
|
#### Szenario A: Große Datenmenge
|
||||||
|
1. Map mit 200+ Items laden
|
||||||
|
2. 3 Filter-Tags aktivieren
|
||||||
|
3. Zwischen 5 Items navigieren
|
||||||
|
4. Sidebar 3x öffnen/schließen
|
||||||
|
|
||||||
|
#### Szenario B: Schnelle Interaktionen
|
||||||
|
1. Rapid Tag-Toggle (5x schnell hintereinander)
|
||||||
|
2. Item-Popup öffnen → schließen → nächstes öffnen
|
||||||
|
3. Sidebar während Map-Pan öffnen
|
||||||
|
|
||||||
|
#### Szenario C: Animation Smoothness
|
||||||
|
1. Sidebar-Animation beobachten (ruckelt?)
|
||||||
|
2. Modal öffnen/schließen
|
||||||
|
3. Zwischen Profile-Views wechseln
|
||||||
|
|
||||||
|
### Erfolgs-Kriterien
|
||||||
|
|
||||||
|
| Phase | Erfolgskriterium |
|
||||||
|
|-------|------------------|
|
||||||
|
| Phase 1 (Quick Wins) | Lighthouse Score +10 Punkte, keine sichtbaren Ruckler bei Sidebar |
|
||||||
|
| Phase 2 (Memoization) | Re-Render Count -50%, Marker-Interaktion <100ms |
|
||||||
|
| Phase 3 (Architektur) | Initial Load <500ms bei 200 Items |
|
||||||
|
| Phase 4 (CSS) | Konstant 60 FPS bei allen Animationen |
|
||||||
|
|
||||||
|
### Automatisierte Performance-Tests mit Vitest
|
||||||
|
|
||||||
|
#### Setup
|
||||||
|
|
||||||
|
Neue Datei: `lib/src/__tests__/performance.bench.ts`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { describe, bench, expect } from 'vitest'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import { performance } from 'perf_hooks'
|
||||||
|
|
||||||
|
// Utility für Performance-Messung
|
||||||
|
const measureRender = async (Component: React.FC, props: any) => {
|
||||||
|
const start = performance.now()
|
||||||
|
const { unmount } = render(<Component {...props} />)
|
||||||
|
const end = performance.now()
|
||||||
|
unmount()
|
||||||
|
return end - start
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Performance Benchmarks', () => {
|
||||||
|
|
||||||
|
// Marker Rendering
|
||||||
|
bench('render 100 markers', async () => {
|
||||||
|
const items = generateMockItems(100)
|
||||||
|
await measureRender(PopupView, { items })
|
||||||
|
}, { time: 1000 })
|
||||||
|
|
||||||
|
bench('render 500 markers', async () => {
|
||||||
|
const items = generateMockItems(500)
|
||||||
|
await measureRender(PopupView, { items })
|
||||||
|
}, { time: 2000 })
|
||||||
|
|
||||||
|
// Tag Filter Performance
|
||||||
|
bench('filter toggle with 100 items', async () => {
|
||||||
|
// Simuliert Tag-Filter Toggle
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sidebar Animation
|
||||||
|
bench('sidebar open/close cycle', async () => {
|
||||||
|
// Misst Sidebar-Toggle
|
||||||
|
})
|
||||||
|
|
||||||
|
// ProfileForm Rendering
|
||||||
|
bench('ProfileForm with complex item', async () => {
|
||||||
|
const item = generateComplexItem()
|
||||||
|
await measureRender(ProfileForm, { item })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vitest Config Erweiterung
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// vitest.config.ts - benchmark mode hinzufügen
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
benchmark: {
|
||||||
|
include: ['**/*.bench.ts'],
|
||||||
|
reporters: ['default', 'json'],
|
||||||
|
outputFile: './benchmark-results.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### NPM Script
|
||||||
|
|
||||||
|
```json
|
||||||
|
// package.json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"test:perf": "vitest bench",
|
||||||
|
"test:perf:baseline": "vitest bench --outputFile=baseline.json",
|
||||||
|
"test:perf:compare": "vitest bench --compare=baseline.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Performance-Grenzwerte
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// lib/src/__tests__/performance.thresholds.ts
|
||||||
|
export const PERF_THRESHOLDS = {
|
||||||
|
MARKER_RENDER_100: 500, // ms
|
||||||
|
MARKER_RENDER_500: 2000, // ms
|
||||||
|
TAG_FILTER_TOGGLE: 100, // ms
|
||||||
|
SIDEBAR_TOGGLE: 50, // ms
|
||||||
|
POPUP_OPEN: 200, // ms
|
||||||
|
PROFILE_RENDER: 300, // ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// In Tests verwenden:
|
||||||
|
expect(renderTime).toBeLessThan(PERF_THRESHOLDS.MARKER_RENDER_100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### CI Integration (Optional)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/performance.yml
|
||||||
|
name: Performance Benchmarks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
benchmark:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run test:perf
|
||||||
|
- name: Compare with baseline
|
||||||
|
run: npm run test:perf:compare
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dokumentation der Messungen
|
||||||
|
|
||||||
|
Vor jeder Phase:
|
||||||
|
1. Baseline-Werte in Tabelle eintragen
|
||||||
|
2. Screenshots von DevTools Profiler speichern
|
||||||
|
3. Lighthouse Report als PDF exportieren
|
||||||
|
|
||||||
|
Nach jeder Phase:
|
||||||
|
1. Neue Werte eintragen
|
||||||
|
2. Vergleich dokumentieren
|
||||||
|
3. Bei Regression: Ursache analysieren
|
||||||
@ -43,7 +43,7 @@
|
|||||||
"author": "Anton Tranelis",
|
"author": "Anton Tranelis",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.1",
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
|
||||||
"@eslint/js": "^9.36.0",
|
"@eslint/js": "^9.36.0",
|
||||||
"@rollup/plugin-alias": "^6.0.0",
|
"@rollup/plugin-alias": "^6.0.0",
|
||||||
"@rollup/plugin-commonjs": "^29.0.0",
|
"@rollup/plugin-commonjs": "^29.0.0",
|
||||||
@ -51,47 +51,47 @@
|
|||||||
"@rollup/plugin-typescript": "^12.3.0",
|
"@rollup/plugin-typescript": "^12.3.0",
|
||||||
"@tailwindcss/postcss": "^4.1.18",
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.3.1",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/geojson": "^7946.0.14",
|
"@types/geojson": "^7946.0.14",
|
||||||
"@types/leaflet": "^1.9.21",
|
"@types/leaflet": "^1.9.21",
|
||||||
"@types/leaflet.markercluster": "^1.5.5",
|
"@types/leaflet.markercluster": "^1.5.5",
|
||||||
"@types/react": "^18.2.0",
|
"@types/react": "^18.2.0",
|
||||||
"@types/react-dom": "^18.0.5",
|
"@types/react-dom": "^18.0.5",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"@vitest/coverage-v8": "^3.0.5",
|
"@vitest/coverage-v8": "^4.0.18",
|
||||||
"cypress": "^15.7.1",
|
"cypress": "^15.10.0",
|
||||||
"daisyui": "^5.5.14",
|
"daisyui": "^5.5.17",
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^9.39.2",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-import-resolver-typescript": "^4.4.4",
|
"eslint-import-resolver-typescript": "^4.4.4",
|
||||||
"eslint-plugin-import-x": "^4.16.1",
|
"eslint-plugin-import-x": "^4.16.1",
|
||||||
"eslint-plugin-json": "^4.0.1",
|
"eslint-plugin-json": "^4.0.1",
|
||||||
"eslint-plugin-no-catch-all": "^1.1.0",
|
"eslint-plugin-no-catch-all": "^1.1.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
"eslint-plugin-promise": "^7.2.1",
|
"eslint-plugin-promise": "^7.2.1",
|
||||||
"eslint-plugin-react": "^7.31.8",
|
"eslint-plugin-react": "^7.31.8",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.4.26",
|
"eslint-plugin-react-refresh": "^0.5.0",
|
||||||
"eslint-plugin-security": "^3.0.1",
|
"eslint-plugin-security": "^3.0.1",
|
||||||
"globals": "^16.3.0",
|
"globals": "^17.3.0",
|
||||||
"happy-dom": "^20.0.11",
|
"happy-dom": "^20.5.0",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
"prettier": "^3.7.4",
|
"prettier": "^3.8.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"rollup": "^4.53.5",
|
"rollup": "^4.57.1",
|
||||||
"rollup-plugin-dts": "^6.3.0",
|
"rollup-plugin-dts": "^6.3.0",
|
||||||
"rollup-plugin-postcss": "^4.0.2",
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
"rollup-plugin-svg": "^2.0.0",
|
"rollup-plugin-svg": "^2.0.0",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"typedoc": "^0.28.15",
|
"typedoc": "^0.28.16",
|
||||||
"typedoc-plugin-coverage": "^4.0.2",
|
"typedoc-plugin-coverage": "^4.0.2",
|
||||||
"typedoc-plugin-missing-exports": "^4.1.2",
|
"typedoc-plugin-missing-exports": "^4.1.2",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.9.0",
|
"typescript-eslint": "^8.9.0",
|
||||||
"vite": "^7.3.0",
|
"vite": "^7.3.1",
|
||||||
"vite-plugin-svgr": "^4.3.0",
|
"vite-plugin-svgr": "^4.3.0",
|
||||||
"vitest": "^3.0.5"
|
"vitest": "^4.0.16"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@ -111,27 +111,27 @@
|
|||||||
"@tiptap/pm": "^3.6.5",
|
"@tiptap/pm": "^3.6.5",
|
||||||
"@tiptap/react": "^3.13.0",
|
"@tiptap/react": "^3.13.0",
|
||||||
"@tiptap/starter-kit": "^3.13.0",
|
"@tiptap/starter-kit": "^3.13.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.4",
|
||||||
"browser-image-compression": "^2.0.2",
|
"browser-image-compression": "^2.0.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet.locatecontrol": "^0.79.0",
|
"leaflet.locatecontrol": "^0.79.0",
|
||||||
"maplibre-gl": "^5.15.0",
|
"maplibre-gl": "^5.17.0",
|
||||||
"radash": "^12.1.0",
|
"radash": "^12.1.0",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-dropzone": "^14.3.8",
|
"react-dropzone": "^14.4.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-image-crop": "^11.0.10",
|
"react-image-crop": "^11.0.10",
|
||||||
"react-inlinesvg": "^4.2.0",
|
"react-inlinesvg": "^4.2.0",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-leaflet-cluster": "^3.1.1",
|
"react-leaflet-cluster": "^3.1.1",
|
||||||
"react-markdown": "^9.0.1",
|
"react-markdown": "^9.0.1",
|
||||||
"react-photo-album": "^3.3.0",
|
"react-photo-album": "^3.4.0",
|
||||||
"react-qr-code": "^2.0.16",
|
"react-qr-code": "^2.0.16",
|
||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
"remark-breaks": "^4.0.0",
|
"remark-breaks": "^4.0.0",
|
||||||
"tiptap-markdown": "^0.9.0",
|
"tiptap-markdown": "^0.9.0",
|
||||||
"yet-another-react-lightbox": "^3.27.0"
|
"yet-another-react-lightbox": "^3.28.0"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
"#assets/*": "./src/assets/*",
|
"#assets/*": "./src/assets/*",
|
||||||
|
|||||||
@ -10,7 +10,6 @@ export default defineConfig({
|
|||||||
environment: 'happy-dom',
|
environment: 'happy-dom',
|
||||||
setupFiles: ['setupTest.ts'],
|
setupFiles: ['setupTest.ts'],
|
||||||
coverage: {
|
coverage: {
|
||||||
all: true,
|
|
||||||
include: ['src/**/*.{js,jsx,ts,tsx}'],
|
include: ['src/**/*.{js,jsx,ts,tsx}'],
|
||||||
exclude: [...configDefaults.exclude, 'src/**/*.cy.tsx'],
|
exclude: [...configDefaults.exclude, 'src/**/*.cy.tsx'],
|
||||||
reporter: ['html', 'json-summary'],
|
reporter: ['html', 'json-summary'],
|
||||||
|
|||||||
1327
package-lock.json
generated
1327
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user