diff --git a/.env.example b/.env.example index 0ef4d2191..90efa8b41 100644 --- a/.env.example +++ b/.env.example @@ -15,12 +15,15 @@ RABBITMQ_USER="plane" RABBITMQ_PASSWORD="plane" RABBITMQ_VHOST="plane" +LISTEN_HTTP_PORT=80 +LISTEN_HTTPS_PORT=443 + # AWS Settings AWS_REGION="" AWS_ACCESS_KEY_ID="access-key" AWS_SECRET_ACCESS_KEY="secret-key" AWS_S3_ENDPOINT_URL="http://plane-minio:9000" -# Changing this requires change in the nginx.conf for uploads if using minio setup +# Changing this requires change in the proxy config for uploads if using minio setup AWS_S3_BUCKET_NAME="uploads" # Maximum file upload limit FILE_SIZE_LIMIT=5242880 @@ -36,8 +39,15 @@ DOCKERIZED=1 # deprecated # set to 1 If using the pre-configured minio setup USE_MINIO=1 -# Nginx Configuration -NGINX_PORT=80 +# If SSL Cert to be generated, set CERT_EMAIl="email " +CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory +TRUSTED_PROXIES=0.0.0.0/0 +SITE_ADDRESS=:80 +CERT_EMAIL= + +# For DNS Challenge based certificate generation, set the CERT_ACME_DNS, CERT_EMAIL +# CERT_ACME_DNS="acme_dns " +CERT_ACME_DNS= # Force HTTPS for handling SSL Termination MINIO_ENDPOINT_SSL=0 diff --git a/.github/workflows/build-aio-base.yml b/.github/workflows/build-aio-base.yml deleted file mode 100644 index 3fb2958f1..000000000 --- a/.github/workflows/build-aio-base.yml +++ /dev/null @@ -1,139 +0,0 @@ -name: Build AIO Base Image - -on: - workflow_dispatch: - inputs: - base_tag_name: - description: 'Base Tag Name' - required: false - default: '' - -env: - TARGET_BRANCH: ${{ github.ref_name }} - -jobs: - base_build_setup: - name: Build Preparation - runs-on: ubuntu-latest - outputs: - gh_branch_name: ${{ steps.set_env_variables.outputs.TARGET_BRANCH }} - gh_buildx_driver: ${{ steps.set_env_variables.outputs.BUILDX_DRIVER }} - gh_buildx_version: ${{ steps.set_env_variables.outputs.BUILDX_VERSION }} - gh_buildx_platforms: ${{ steps.set_env_variables.outputs.BUILDX_PLATFORMS }} - gh_buildx_endpoint: ${{ steps.set_env_variables.outputs.BUILDX_ENDPOINT }} - image_tag: ${{ steps.set_env_variables.outputs.IMAGE_TAG }} - - steps: - - id: set_env_variables - name: Set Environment Variables - run: | - echo "TARGET_BRANCH=${{ env.TARGET_BRANCH }}" >> $GITHUB_OUTPUT - - if [ "${{ github.event.inputs.base_tag_name }}" != "" ]; then - echo "IMAGE_TAG=${{ github.event.inputs.base_tag_name }}" >> $GITHUB_OUTPUT - elif [ "${{ env.TARGET_BRANCH }}" == "master" ]; then - echo "IMAGE_TAG=latest" >> $GITHUB_OUTPUT - elif [ "${{ env.TARGET_BRANCH }}" == "preview" ]; then - echo "IMAGE_TAG=preview" >> $GITHUB_OUTPUT - else - echo "IMAGE_TAG=develop" >> $GITHUB_OUTPUT - fi - - - if [ "${{ env.TARGET_BRANCH }}" == "master" ]; then - echo "BUILDX_DRIVER=cloud" >> $GITHUB_OUTPUT - echo "BUILDX_VERSION=lab:latest" >> $GITHUB_OUTPUT - echo "BUILDX_PLATFORMS=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT - echo "BUILDX_ENDPOINT=makeplane/plane-dev" >> $GITHUB_OUTPUT - else - echo "BUILDX_DRIVER=docker-container" >> $GITHUB_OUTPUT - echo "BUILDX_VERSION=latest" >> $GITHUB_OUTPUT - echo "BUILDX_PLATFORMS=linux/amd64" >> $GITHUB_OUTPUT - echo "BUILDX_ENDPOINT=" >> $GITHUB_OUTPUT - fi - - - id: checkout_files - name: Checkout Files - uses: actions/checkout@v4 - - full_base_build_push: - runs-on: ubuntu-latest - needs: [base_build_setup] - env: - BASE_IMG_TAG: makeplane/plane-aio-base:full-${{ needs.base_build_setup.outputs.image_tag }} - BUILDX_DRIVER: ${{ needs.base_build_setup.outputs.gh_buildx_driver }} - BUILDX_VERSION: ${{ needs.base_build_setup.outputs.gh_buildx_version }} - BUILDX_PLATFORMS: ${{ needs.base_build_setup.outputs.gh_buildx_platforms }} - BUILDX_ENDPOINT: ${{ needs.base_build_setup.outputs.gh_buildx_endpoint }} - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver: ${{ env.BUILDX_DRIVER }} - version: ${{ env.BUILDX_VERSION }} - endpoint: ${{ env.BUILDX_ENDPOINT }} - - - name: Build and Push to Docker Hub - uses: docker/build-push-action@v6.9.0 - with: - context: ./aio - file: ./aio/Dockerfile-base-full - platforms: ${{ env.BUILDX_PLATFORMS }} - tags: ${{ env.BASE_IMG_TAG }} - push: true - cache-from: type=gha - cache-to: type=gha,mode=max - env: - DOCKER_BUILDKIT: 1 - DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} - - slim_base_build_push: - runs-on: ubuntu-latest - needs: [base_build_setup] - env: - BASE_IMG_TAG: makeplane/plane-aio-base:slim-${{ needs.base_build_setup.outputs.image_tag }} - BUILDX_DRIVER: ${{ needs.base_build_setup.outputs.gh_buildx_driver }} - BUILDX_VERSION: ${{ needs.base_build_setup.outputs.gh_buildx_version }} - BUILDX_PLATFORMS: ${{ needs.base_build_setup.outputs.gh_buildx_platforms }} - BUILDX_ENDPOINT: ${{ needs.base_build_setup.outputs.gh_buildx_endpoint }} - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver: ${{ env.BUILDX_DRIVER }} - version: ${{ env.BUILDX_VERSION }} - endpoint: ${{ env.BUILDX_ENDPOINT }} - - - name: Build and Push to Docker Hub - uses: docker/build-push-action@v6.9.0 - with: - context: ./aio - file: ./aio/Dockerfile-base-slim - platforms: ${{ env.BUILDX_PLATFORMS }} - tags: ${{ env.BASE_IMG_TAG }} - push: true - cache-from: type=gha - cache-to: type=gha,mode=max - env: - DOCKER_BUILDKIT: 1 - DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/build-aio-branch.yml b/.github/workflows/build-aio-branch.yml deleted file mode 100644 index 3cc288354..000000000 --- a/.github/workflows/build-aio-branch.yml +++ /dev/null @@ -1,207 +0,0 @@ -name: Branch Build AIO - -on: - workflow_dispatch: - inputs: - full: - description: 'Run full build' - type: boolean - required: false - default: false - slim: - description: 'Run slim build' - type: boolean - required: false - default: false - base_tag_name: - description: 'Base Tag Name' - required: false - default: '' - release: - types: [released, prereleased] - -env: - TARGET_BRANCH: ${{ github.ref_name || github.event.release.target_commitish }} - FULL_BUILD_INPUT: ${{ github.event.inputs.full }} - SLIM_BUILD_INPUT: ${{ github.event.inputs.slim }} - -jobs: - branch_build_setup: - name: Build Setup - runs-on: ubuntu-latest - outputs: - gh_branch_name: ${{ steps.set_env_variables.outputs.TARGET_BRANCH }} - flat_branch_name: ${{ steps.set_env_variables.outputs.FLAT_BRANCH_NAME }} - gh_buildx_driver: ${{ steps.set_env_variables.outputs.BUILDX_DRIVER }} - gh_buildx_version: ${{ steps.set_env_variables.outputs.BUILDX_VERSION }} - gh_buildx_platforms: ${{ steps.set_env_variables.outputs.BUILDX_PLATFORMS }} - gh_buildx_endpoint: ${{ steps.set_env_variables.outputs.BUILDX_ENDPOINT }} - aio_base_tag: ${{ steps.set_env_variables.outputs.AIO_BASE_TAG }} - do_full_build: ${{ steps.set_env_variables.outputs.DO_FULL_BUILD }} - do_slim_build: ${{ steps.set_env_variables.outputs.DO_SLIM_BUILD }} - - steps: - - id: set_env_variables - name: Set Environment Variables - run: | - if [ "${{ env.TARGET_BRANCH }}" == "master" ] || [ "${{ github.event_name }}" == "release" ]; then - echo "BUILDX_DRIVER=cloud" >> $GITHUB_OUTPUT - echo "BUILDX_VERSION=lab:latest" >> $GITHUB_OUTPUT - echo "BUILDX_PLATFORMS=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT - echo "BUILDX_ENDPOINT=makeplane/plane-dev" >> $GITHUB_OUTPUT - - echo "AIO_BASE_TAG=latest" >> $GITHUB_OUTPUT - else - echo "BUILDX_DRIVER=docker-container" >> $GITHUB_OUTPUT - echo "BUILDX_VERSION=latest" >> $GITHUB_OUTPUT - echo "BUILDX_PLATFORMS=linux/amd64" >> $GITHUB_OUTPUT - echo "BUILDX_ENDPOINT=" >> $GITHUB_OUTPUT - - if [ "${{ github.event_name}}" == "workflow_dispatch" ] && [ "${{ github.event.inputs.base_tag_name }}" != "" ]; then - echo "AIO_BASE_TAG=${{ github.event.inputs.base_tag_name }}" >> $GITHUB_OUTPUT - elif [ "${{ env.TARGET_BRANCH }}" == "preview" ]; then - echo "AIO_BASE_TAG=preview" >> $GITHUB_OUTPUT - else - echo "AIO_BASE_TAG=develop" >> $GITHUB_OUTPUT - fi - fi - echo "TARGET_BRANCH=${{ env.TARGET_BRANCH }}" >> $GITHUB_OUTPUT - - if [ "${{ env.FULL_BUILD_INPUT }}" == "true" ] || [ "${{github.event_name}}" == "push" ] || [ "${{github.event_name}}" == "release" ]; then - echo "DO_FULL_BUILD=true" >> $GITHUB_OUTPUT - else - echo "DO_FULL_BUILD=false" >> $GITHUB_OUTPUT - fi - - if [ "${{ env.SLIM_BUILD_INPUT }}" == "true" ] || [ "${{github.event_name}}" == "push" ] || [ "${{github.event_name}}" == "release" ]; then - echo "DO_SLIM_BUILD=true" >> $GITHUB_OUTPUT - else - echo "DO_SLIM_BUILD=false" >> $GITHUB_OUTPUT - fi - - FLAT_BRANCH_NAME=$(echo "${{ env.TARGET_BRANCH }}" | sed 's/[^a-zA-Z0-9]/-/g') - echo "FLAT_BRANCH_NAME=$FLAT_BRANCH_NAME" >> $GITHUB_OUTPUT - - - id: checkout_files - name: Checkout Files - uses: actions/checkout@v4 - - full_build_push: - if: ${{ needs.branch_build_setup.outputs.do_full_build == 'true' }} - runs-on: ubuntu-22.04 - needs: [branch_build_setup] - env: - BUILD_TYPE: full - AIO_BASE_TAG: ${{ needs.branch_build_setup.outputs.aio_base_tag }} - AIO_IMAGE_TAGS: makeplane/plane-aio:full-${{ needs.branch_build_setup.outputs.flat_branch_name }} - TARGET_BRANCH: ${{ needs.branch_build_setup.outputs.gh_branch_name }} - BUILDX_DRIVER: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} - BUILDX_VERSION: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} - BUILDX_PLATFORMS: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} - BUILDX_ENDPOINT: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }} - steps: - - name: Set Docker Tag - run: | - if [ "${{ github.event_name }}" == "release" ]; then - TAG=makeplane/plane-aio:${{env.BUILD_TYPE}}-stable,makeplane/plane-aio:${{env.BUILD_TYPE}}-${{ github.event.release.tag_name }} - elif [ "${{ env.TARGET_BRANCH }}" == "master" ]; then - TAG=makeplane/plane-aio:${{env.BUILD_TYPE}}-latest - else - TAG=${{ env.AIO_IMAGE_TAGS }} - fi - echo "AIO_IMAGE_TAGS=${TAG}" >> $GITHUB_ENV - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver: ${{ env.BUILDX_DRIVER }} - version: ${{ env.BUILDX_VERSION }} - endpoint: ${{ env.BUILDX_ENDPOINT }} - - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Build and Push to Docker Hub - uses: docker/build-push-action@v6.9.0 - with: - context: . - file: ./aio/Dockerfile-app - platforms: ${{ env.BUILDX_PLATFORMS }} - tags: ${{ env.AIO_IMAGE_TAGS }} - push: true - build-args: | - BASE_TAG=${{ env.AIO_BASE_TAG }} - BUILD_TYPE=${{env.BUILD_TYPE}} - cache-from: type=gha - cache-to: type=gha,mode=max - - env: - DOCKER_BUILDKIT: 1 - DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} - - slim_build_push: - if: ${{ needs.branch_build_setup.outputs.do_slim_build == 'true' }} - runs-on: ubuntu-22.04 - needs: [branch_build_setup] - env: - BUILD_TYPE: slim - AIO_BASE_TAG: ${{ needs.branch_build_setup.outputs.aio_base_tag }} - AIO_IMAGE_TAGS: makeplane/plane-aio:slim-${{ needs.branch_build_setup.outputs.flat_branch_name }} - TARGET_BRANCH: ${{ needs.branch_build_setup.outputs.gh_branch_name }} - BUILDX_DRIVER: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} - BUILDX_VERSION: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} - BUILDX_PLATFORMS: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} - BUILDX_ENDPOINT: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }} - steps: - - name: Set Docker Tag - run: | - if [ "${{ github.event_name }}" == "release" ]; then - TAG=makeplane/plane-aio:${{env.BUILD_TYPE}}-stable,makeplane/plane-aio:${{env.BUILD_TYPE}}-${{ github.event.release.tag_name }} - elif [ "${{ env.TARGET_BRANCH }}" == "master" ]; then - TAG=makeplane/plane-aio:${{env.BUILD_TYPE}}-latest - else - TAG=${{ env.AIO_IMAGE_TAGS }} - fi - echo "AIO_IMAGE_TAGS=${TAG}" >> $GITHUB_ENV - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver: ${{ env.BUILDX_DRIVER }} - version: ${{ env.BUILDX_VERSION }} - endpoint: ${{ env.BUILDX_ENDPOINT }} - - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Build and Push to Docker Hub - uses: docker/build-push-action@v6.9.0 - with: - context: . - file: ./aio/Dockerfile-app - platforms: ${{ env.BUILDX_PLATFORMS }} - tags: ${{ env.AIO_IMAGE_TAGS }} - push: true - build-args: | - BASE_TAG=${{ env.AIO_BASE_TAG }} - BUILD_TYPE=${{env.BUILD_TYPE}} - cache-from: type=gha - cache-to: type=gha,mode=max - - env: - DOCKER_BUILDKIT: 1 - DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/build-branch.yml b/.github/workflows/build-branch.yml index 6c75af134..acd9348d2 100644 --- a/.github/workflows/build-branch.yml +++ b/.github/workflows/build-branch.yml @@ -25,6 +25,11 @@ on: required: false default: false type: boolean + aio_build: + description: "Build for AIO docker image" + required: false + default: false + type: boolean push: branches: - preview @@ -36,6 +41,7 @@ env: BUILD_TYPE: ${{ github.event.inputs.build_type }} RELEASE_VERSION: ${{ github.event.inputs.releaseVersion }} IS_PRERELEASE: ${{ github.event.inputs.isPrerelease }} + AIO_BUILD: ${{ github.event.inputs.aio_build }} jobs: branch_build_setup: @@ -54,11 +60,13 @@ jobs: dh_img_live: ${{ steps.set_env_variables.outputs.DH_IMG_LIVE }} dh_img_backend: ${{ steps.set_env_variables.outputs.DH_IMG_BACKEND }} dh_img_proxy: ${{ steps.set_env_variables.outputs.DH_IMG_PROXY }} + dh_img_aio: ${{ steps.set_env_variables.outputs.DH_IMG_AIO }} build_type: ${{steps.set_env_variables.outputs.BUILD_TYPE}} build_release: ${{ steps.set_env_variables.outputs.BUILD_RELEASE }} build_prerelease: ${{ steps.set_env_variables.outputs.BUILD_PRERELEASE }} release_version: ${{ steps.set_env_variables.outputs.RELEASE_VERSION }} + aio_build: ${{ steps.set_env_variables.outputs.AIO_BUILD }} steps: - id: set_env_variables @@ -84,12 +92,15 @@ jobs: echo "DH_IMG_LIVE=plane-live" >> $GITHUB_OUTPUT echo "DH_IMG_BACKEND=plane-backend" >> $GITHUB_OUTPUT echo "DH_IMG_PROXY=plane-proxy" >> $GITHUB_OUTPUT + echo "DH_IMG_AIO=plane-aio-community" >> $GITHUB_OUTPUT echo "BUILD_TYPE=${{env.BUILD_TYPE}}" >> $GITHUB_OUTPUT BUILD_RELEASE=false BUILD_PRERELEASE=false RELVERSION="latest" + BUILD_AIO=${{ env.AIO_BUILD }} + if [ "${{ env.BUILD_TYPE }}" == "Release" ]; then FLAT_RELEASE_VERSION=$(echo "${{ env.RELEASE_VERSION }}" | sed 's/[^a-zA-Z0-9.-]//g') echo "FLAT_RELEASE_VERSION=${FLAT_RELEASE_VERSION}" >> $GITHUB_OUTPUT @@ -108,10 +119,14 @@ jobs: if [ "${{ env.IS_PRERELEASE }}" == "true" ]; then BUILD_PRERELEASE=true fi + + BUILD_AIO=true fi + echo "BUILD_RELEASE=${BUILD_RELEASE}" >> $GITHUB_OUTPUT echo "BUILD_PRERELEASE=${BUILD_PRERELEASE}" >> $GITHUB_OUTPUT echo "RELEASE_VERSION=${RELVERSION}" >> $GITHUB_OUTPUT + echo "AIO_BUILD=${BUILD_AIO}" >> $GITHUB_OUTPUT - id: checkout_files name: Checkout Files @@ -133,7 +148,7 @@ jobs: docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_admin }} build-context: . - dockerfile-path: ./admin/Dockerfile.admin + dockerfile-path: ./apps/admin/Dockerfile.admin buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} @@ -155,7 +170,7 @@ jobs: docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_web }} build-context: . - dockerfile-path: ./web/Dockerfile.web + dockerfile-path: ./apps/web/Dockerfile.web buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} @@ -177,7 +192,7 @@ jobs: docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_space }} build-context: . - dockerfile-path: ./space/Dockerfile.space + dockerfile-path: ./apps/space/Dockerfile.space buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} @@ -199,13 +214,13 @@ jobs: docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_live }} build-context: . - dockerfile-path: ./live/Dockerfile.live + dockerfile-path: ./apps/live/Dockerfile.live buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }} - branch_build_push_apiserver: + branch_build_push_api: name: Build-Push API Server Docker Image runs-on: ubuntu-22.04 needs: [branch_build_setup] @@ -220,8 +235,8 @@ jobs: dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_backend }} - build-context: ./apiserver - dockerfile-path: ./apiserver/Dockerfile.api + build-context: ./apps/api + dockerfile-path: ./apps/api/Dockerfile.api buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} @@ -242,13 +257,102 @@ jobs: dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} docker-image-owner: makeplane docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_proxy }} - build-context: ./nginx - dockerfile-path: ./nginx/Dockerfile + build-context: ./apps/proxy + dockerfile-path: ./apps/proxy/Dockerfile.ce buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }} + branch_build_push_aio: + if: ${{ needs.branch_build_setup.outputs.aio_build == 'true' }} + name: Build-Push AIO Docker Image + runs-on: ubuntu-22.04 + needs: [ + branch_build_setup, + branch_build_push_admin, + branch_build_push_web, + branch_build_push_space, + branch_build_push_live, + branch_build_push_api, + branch_build_push_proxy + ] + steps: + - name: Checkout Files + uses: actions/checkout@v4 + + - name: Prepare AIO Assets + id: prepare_aio_assets + run: | + cd deployments/aio/community + + if [ "${{ needs.branch_build_setup.outputs.build_type }}" == "Release" ]; then + aio_version=${{ needs.branch_build_setup.outputs.release_version }} + else + aio_version=${{ needs.branch_build_setup.outputs.gh_branch_name }} + fi + bash ./build.sh --release $aio_version + echo "AIO_BUILD_VERSION=${aio_version}" >> $GITHUB_OUTPUT + + - name: Upload AIO Assets + uses: actions/upload-artifact@v4 + with: + path: ./deployments/aio/community/dist + name: aio-assets-dist + + - name: AIO Build and Push + uses: makeplane/actions/build-push@v1.1.0 + with: + build-release: ${{ needs.branch_build_setup.outputs.build_release }} + build-prerelease: ${{ needs.branch_build_setup.outputs.build_prerelease }} + release-version: ${{ needs.branch_build_setup.outputs.release_version }} + dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} + docker-image-owner: makeplane + docker-image-name: ${{ needs.branch_build_setup.outputs.dh_img_aio }} + build-context: ./deployments/aio/community + dockerfile-path: ./deployments/aio/community/Dockerfile + buildx-driver: ${{ needs.branch_build_setup.outputs.gh_buildx_driver }} + buildx-version: ${{ needs.branch_build_setup.outputs.gh_buildx_version }} + buildx-platforms: ${{ needs.branch_build_setup.outputs.gh_buildx_platforms }} + buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }} + additional-assets: aio-assets-dist + additional-assets-dir: ./deployments/aio/community/dist + build-args: | + PLANE_VERSION=${{ steps.prepare_aio_assets.outputs.AIO_BUILD_VERSION }} + + upload_build_assets: + name: Upload Build Assets + runs-on: ubuntu-22.04 + needs: [branch_build_setup, branch_build_push_admin, branch_build_push_web, branch_build_push_space, branch_build_push_live, branch_build_push_api, branch_build_push_proxy] + steps: + - name: Checkout Files + uses: actions/checkout@v4 + + - name: Update Assets + run: | + if [ "${{ needs.branch_build_setup.outputs.build_type }}" == "Release" ]; then + REL_VERSION=${{ needs.branch_build_setup.outputs.release_version }} + else + REL_VERSION=${{ needs.branch_build_setup.outputs.gh_branch_name }} + fi + + cp ./deployments/cli/community/install.sh deployments/cli/community/setup.sh + sed -i 's/${APP_RELEASE:-stable}/${APP_RELEASE:-'${REL_VERSION}'}/g' deployments/cli/community/docker-compose.yml + # sed -i 's/APP_RELEASE=stable/APP_RELEASE='${REL_VERSION}'/g' deployments/cli/community/variables.env + + - name: Upload Assets + uses: actions/upload-artifact@v4 + with: + name: community-assets + path: | + ./deployments/cli/community/setup.sh + ./deployments/cli/community/restore.sh + ./deployments/cli/community/restore-airgapped.sh + ./deployments/cli/community/docker-compose.yml + ./deployments/cli/community/variables.env + ./deployments/swarm/community/swarm.sh + publish_release: if: ${{ needs.branch_build_setup.outputs.build_type == 'Release' }} name: Build Release @@ -260,7 +364,7 @@ jobs: branch_build_push_web, branch_build_push_space, branch_build_push_live, - branch_build_push_apiserver, + branch_build_push_api, branch_build_push_proxy, ] env: @@ -271,9 +375,9 @@ jobs: - name: Update Assets run: | - cp ./deploy/selfhost/install.sh deploy/selfhost/setup.sh - sed -i 's/${APP_RELEASE:-stable}/${APP_RELEASE:-'${REL_VERSION}'}/g' deploy/selfhost/docker-compose.yml - # sed -i 's/APP_RELEASE=stable/APP_RELEASE='${REL_VERSION}'/g' deploy/selfhost/variables.env + cp ./deployments/cli/community/install.sh deployments/cli/community/setup.sh + sed -i 's/${APP_RELEASE:-stable}/${APP_RELEASE:-'${REL_VERSION}'}/g' deployments/cli/community/docker-compose.yml + # sed -i 's/APP_RELEASE=stable/APP_RELEASE='${REL_VERSION}'/g' deployments/cli/community/variables.env - name: Create Release id: create_release @@ -287,9 +391,10 @@ jobs: prerelease: ${{ env.IS_PRERELEASE }} generate_release_notes: true files: | - ${{ github.workspace }}/deploy/selfhost/setup.sh - ${{ github.workspace }}/deploy/selfhost/swarm.sh - ${{ github.workspace }}/deploy/selfhost/restore.sh - ${{ github.workspace }}/deploy/selfhost/restore-airgapped.sh - ${{ github.workspace }}/deploy/selfhost/docker-compose.yml - ${{ github.workspace }}/deploy/selfhost/variables.env + ${{ github.workspace }}/deployments/cli/community/setup.sh + ${{ github.workspace }}/deployments/cli/community/restore.sh + ${{ github.workspace }}/deployments/cli/community/restore-airgapped.sh + ${{ github.workspace }}/deployments/cli/community/docker-compose.yml + ${{ github.workspace }}/deployments/cli/community/variables.env + ${{ github.workspace }}/deployments/swarm/community/swarm.sh + diff --git a/.github/workflows/build-test-pull-request.yml b/.github/workflows/build-test-pull-request.yml index 227425c8f..acbd9d26e 100644 --- a/.github/workflows/build-test-pull-request.yml +++ b/.github/workflows/build-test-pull-request.yml @@ -6,7 +6,7 @@ on: types: ["opened", "synchronize", "ready_for_review"] jobs: - lint-apiserver: + lint-server: if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: @@ -17,10 +17,10 @@ jobs: python-version: "3.x" # Specify the Python version you need - name: Install Pylint run: python -m pip install ruff - - name: Install Apiserver Dependencies - run: cd apiserver && pip install -r requirements.txt - - name: Lint apiserver - run: ruff check --fix apiserver + - name: Install Server Dependencies + run: cd apps/server && pip install -r requirements.txt + - name: Lint apps/server + run: ruff check --fix apps/server lint-admin: if: github.event.pull_request.draft == false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a1567520..c401c3c2c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,7 @@ When opening a new issue, please use a clear and concise title that follows this - For documentation: `📘 Docs: [short description]` **Examples:** + - `🐛 Bug: API token expiry time not saving correctly` - `📘 Docs: Clarify RAM requirement for local setup` - `🚀 Feature: Allow custom time selection for token expiration` @@ -47,7 +48,7 @@ This helps us triage and manage issues more efficiently. The project is a monorepo, with backend api and frontend in a single repo. -The backend is a django project which is kept inside apiserver +The backend is a django project which is kept inside apps/api 1. Clone the repo @@ -105,11 +106,13 @@ To ensure consistency throughout the source code, please keep these rules in min - **Improve documentation** - fix incomplete or missing [docs](https://docs.plane.so/), bad wording, examples or explanations. ## Contributing to language support + This guide is designed to help contributors understand how to add or update translations in the application. ### Understanding translation structure #### File organization + Translations are organized by language in the locales directory. Each language has its own folder containing JSON files for translations. Here's how it looks: ``` @@ -122,7 +125,9 @@ packages/i18n/src/locales/ └── [language]/ └── translations.json ``` + #### Nested structure + To keep translations organized, we use a nested structure for keys. This makes it easier to manage and locate specific translations. For example: ```json @@ -137,32 +142,37 @@ To keep translations organized, we use a nested structure for keys. This makes i ``` ### Translation formatting guide + We use [IntlMessageFormat](https://formatjs.github.io/docs/intl-messageformat/) to handle dynamic content, such as variables and pluralization. Here's how to format your translations: #### Examples + - **Simple variables** - ```json - { + + ```json + { "greeting": "Hello, {name}!" - } - ``` + } + ``` - **Pluralization** - ```json - { + ```json + { "items": "{count, plural, one {Work item} other {Work items}}" - } - ``` + } + ``` ### Contributing guidelines #### Updating existing translations + 1. Locate the key in `locales//translations.json`. 2. Update the value while ensuring the key structure remains intact. 3. Preserve any existing ICU formats (e.g., variables, pluralization). #### Adding new translation keys + 1. When introducing a new key, ensure it is added to **all** language files, even if translations are not immediately available. Use English as a placeholder if needed. 2. Keep the nesting structure consistent across all languages. @@ -170,48 +180,48 @@ We use [IntlMessageFormat](https://formatjs.github.io/docs/intl-messageformat/) 3. If the new key requires dynamic content (e.g., variables or pluralization), ensure the ICU format is applied uniformly across all languages. ### Adding new languages + Adding a new language involves several steps to ensure it integrates seamlessly with the project. Follow these instructions carefully: -1. **Update type definitions** -Add the new language to the TLanguage type in the language definitions file: +1. **Update type definitions** + Add the new language to the TLanguage type in the language definitions file: - ```typescript - // types/language.ts - export type TLanguage = "en" | "fr" | "your-lang"; - ``` +```ts + // packages/i18n/src/types/language.ts + export type TLanguage = "en" | "fr" | "your-lang"; +``` -2. **Add language configuration** -Include the new language in the list of supported languages: +1. **Add language configuration** + Include the new language in the list of supported languages: +```ts + // packages/i18n/src/constants/language.ts + export const SUPPORTED_LANGUAGES: ILanguageOption[] = [ + { label: "English", value: "en" }, + { label: "Your Language", value: "your-lang" } + ]; +``` - ```typescript - // constants/language.ts - export const SUPPORTED_LANGUAGES: ILanguageOption[] = [ - { label: "English", value: "en" }, - { label: "Your Language", value: "your-lang" } - ]; - ``` - -3. **Create translation files** - 1. Create a new folder for your language under locales (e.g., `locales/your-lang/`). +2. **Create translation files** + 1. Create a new folder for your language under locales (e.g., `locales/your-lang/`). 2. Add a `translations.json` file inside the folder. 3. Copy the structure from an existing translation file and translate all keys. -4. **Update import logic** -Modify the language import logic to include your new language: - - ```typescript - private importLanguageFile(language: TLanguage): Promise { - switch (language) { - case "your-lang": - return import("../locales/your-lang/translations.json"); - // ... - } - } - ``` +3. **Update import logic** + Modify the language import logic to include your new language: +```ts + private importLanguageFile(language: TLanguage): Promise { + switch (language) { + case "your-lang": + return import("../locales/your-lang/translations.json"); + // ... + } + } +``` ### Quality checklist + Before submitting your contribution, please ensure the following: - All translation keys exist in every language file. @@ -222,6 +232,7 @@ Before submitting your contribution, please ensure the following: - There are no missing or untranslated keys. #### Pro tips + - When in doubt, refer to the English translations for context. - Verify pluralization works with different numbers. - Ensure dynamic values (e.g., `{name}`) are correctly interpolated. diff --git a/ENV_SETUP.md b/ENV_SETUP.md deleted file mode 100644 index 775d6a55f..000000000 --- a/ENV_SETUP.md +++ /dev/null @@ -1,88 +0,0 @@ -# Environment Variables - -Environment variables are distributed in various files. Please refer them carefully. - -## {PROJECT_FOLDER}/.env - -File is available in the project root folder​ - -``` -# Database Settings -POSTGRES_USER="plane" -POSTGRES_PASSWORD="plane" -POSTGRES_DB="plane" -PGDATA="/var/lib/postgresql/data" -# Redis Settings -REDIS_HOST="plane-redis" -REDIS_PORT="6379" -# AWS Settings -AWS_REGION="" -AWS_ACCESS_KEY_ID="access-key" -AWS_SECRET_ACCESS_KEY="secret-key" -AWS_S3_ENDPOINT_URL="http://plane-minio:9000" -# Changing this requires change in the nginx.conf for uploads if using minio setup -AWS_S3_BUCKET_NAME="uploads" -# Maximum file upload limit -FILE_SIZE_LIMIT=5242880 -# GPT settings -OPENAI_API_BASE="https://api.openai.com/v1" # deprecated -OPENAI_API_KEY="sk-" # deprecated -GPT_ENGINE="gpt-3.5-turbo" # deprecated -# Settings related to Docker -DOCKERIZED=1 # deprecated -# set to 1 If using the pre-configured minio setup -USE_MINIO=1 -# Nginx Configuration -NGINX_PORT=80 -``` - -## {PROJECT_FOLDER}/apiserver/.env - -``` -# Backend -# Debug value for api server use it as 0 for production use -DEBUG=0 -CORS_ALLOWED_ORIGINS="http://localhost" -# Database Settings -POSTGRES_USER="plane" -POSTGRES_PASSWORD="plane" -POSTGRES_HOST="plane-db" -POSTGRES_DB="plane" -POSTGRES_PORT=5432 -DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} -# Redis Settings -REDIS_HOST="plane-redis" -REDIS_PORT="6379" -REDIS_URL="redis://${REDIS_HOST}:6379/" -# AWS Settings -AWS_REGION="" -AWS_ACCESS_KEY_ID="access-key" -AWS_SECRET_ACCESS_KEY="secret-key" -AWS_S3_ENDPOINT_URL="http://plane-minio:9000" -# Changing this requires change in the nginx.conf for uploads if using minio setup -AWS_S3_BUCKET_NAME="uploads" -# Maximum file upload limit -FILE_SIZE_LIMIT=5242880 -# Settings related to Docker -DOCKERIZED=1 # deprecated -# set to 1 If using the pre-configured minio setup -USE_MINIO=1 -# Nginx Configuration -NGINX_PORT=80 -# Email redirections and minio domain settings -WEB_URL="http://localhost" -# Gunicorn Workers -GUNICORN_WORKERS=2 -# Base URLs -ADMIN_BASE_URL= -SPACE_BASE_URL= -APP_BASE_URL= -SECRET_KEY="gxoytl7dmnc1y37zahah820z5iq3iozu38cnfjtu3yaau9cd9z" -``` - -## Updates​ - -- The naming convention for containers and images has been updated. -- The plane-worker image will no longer be maintained, as it has been merged with plane-backend. -- The Tiptap pro-extension dependency has been removed, eliminating the need for Tiptap API keys. -- The image name for Plane deployment has been changed to plane-space. diff --git a/admin/app/email/page.tsx b/admin/app/email/page.tsx deleted file mode 100644 index 33fedc052..000000000 --- a/admin/app/email/page.tsx +++ /dev/null @@ -1,48 +0,0 @@ -"use client"; - -import { observer } from "mobx-react"; -import useSWR from "swr"; -import { Loader } from "@plane/ui"; -// hooks -import { useInstance } from "@/hooks/store"; -// components -import { InstanceEmailForm } from "./email-config-form"; - -const InstanceEmailPage = observer(() => { - // store - const { fetchInstanceConfigurations, formattedConfig } = useInstance(); - - useSWR("INSTANCE_CONFIGURATIONS", () => fetchInstanceConfigurations()); - - return ( - <> -
-
-
Secure emails from your own instance
-
- Plane can send useful emails to you and your users from your own instance without talking to the Internet. -
- Set it up below and please test your settings before you save them.  - Misconfigs can lead to email bounces and errors. -
-
-
-
- {formattedConfig ? ( - - ) : ( - - - - - - - - )} -
-
- - ); -}); - -export default InstanceEmailPage; diff --git a/admin/app/layout.tsx b/admin/app/layout.tsx deleted file mode 100644 index b10e9186c..000000000 --- a/admin/app/layout.tsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client"; - -import { ReactNode } from "react"; -import { ThemeProvider, useTheme } from "next-themes"; -import { SWRConfig } from "swr"; -// plane imports -import { ADMIN_BASE_PATH, DEFAULT_SWR_CONFIG } from "@plane/constants"; -import { Toast } from "@plane/ui"; -import { resolveGeneralTheme } from "@plane/utils"; -// lib -import { InstanceProvider } from "@/lib/instance-provider"; -import { StoreProvider } from "@/lib/store-provider"; -import { UserProvider } from "@/lib/user-provider"; -// styles -import "@/styles/globals.css"; - -const ToastWithTheme = () => { - const { resolvedTheme } = useTheme(); - return ; -}; - -export default function RootLayout({ children }: { children: ReactNode }) { - const ASSET_PREFIX = ADMIN_BASE_PATH; - return ( - - - - - - - - - - - - - - - {children} - - - - - - - ); -} diff --git a/admin/app/page.tsx b/admin/app/page.tsx deleted file mode 100644 index 1a274025a..000000000 --- a/admin/app/page.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Metadata } from "next"; -// components -import { InstanceSignInForm } from "@/components/login"; -// layouts -import { DefaultLayout } from "@/layouts/default-layout"; - -export const metadata: Metadata = { - title: "Plane | Simple, extensible, open-source project management tool.", - description: - "Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.", - openGraph: { - title: "Plane | Simple, extensible, open-source project management tool.", - description: - "Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.", - url: "https://plane.so/", - }, - keywords: - "software development, customer feedback, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration", - twitter: { - site: "@planepowers", - }, -}; - -export default async function LoginPage() { - return ( - - - - ); -} diff --git a/admin/ce/components/authentication/authentication-modes.tsx b/admin/ce/components/authentication/authentication-modes.tsx deleted file mode 100644 index 3c7ec111a..000000000 --- a/admin/ce/components/authentication/authentication-modes.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { observer } from "mobx-react"; -import Image from "next/image"; -import { useTheme } from "next-themes"; -// types -import { - TGetBaseAuthenticationModeProps, - TInstanceAuthenticationMethodKeys, - TInstanceAuthenticationModes, -} from "@plane/types"; -// components -import { AuthenticationMethodCard } from "@/components/authentication"; -// helpers -import { getBaseAuthenticationModes } from "@/lib/auth-helpers"; -// plane admin components -import { UpgradeButton } from "@/plane-admin/components/common"; -// images -import OIDCLogo from "@/public/logos/oidc-logo.svg"; -import SAMLLogo from "@/public/logos/saml-logo.svg"; - -export type TAuthenticationModeProps = { - disabled: boolean; - updateConfig: (key: TInstanceAuthenticationMethodKeys, value: string) => void; -}; - -// Authentication methods -export const getAuthenticationModes: (props: TGetBaseAuthenticationModeProps) => TInstanceAuthenticationModes[] = ({ - disabled, - updateConfig, - resolvedTheme, -}) => [ - ...getBaseAuthenticationModes({ disabled, updateConfig, resolvedTheme }), - { - key: "oidc", - name: "OIDC", - description: "Authenticate your users via the OpenID Connect protocol.", - icon: OIDC Logo, - config: , - unavailable: true, - }, - { - key: "saml", - name: "SAML", - description: "Authenticate your users via the Security Assertion Markup Language protocol.", - icon: SAML Logo, - config: , - unavailable: true, - }, -]; - -export const AuthenticationModes: React.FC = observer((props) => { - const { disabled, updateConfig } = props; - // next-themes - const { resolvedTheme } = useTheme(); - - return ( - <> - {getAuthenticationModes({ disabled, updateConfig, resolvedTheme }).map((method) => ( - - ))} - - ); -}); diff --git a/admin/core/components/admin-sidebar/index.ts b/admin/core/components/admin-sidebar/index.ts deleted file mode 100644 index e800fe3c5..000000000 --- a/admin/core/components/admin-sidebar/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./root"; -export * from "./help-section"; -export * from "./sidebar-menu"; -export * from "./sidebar-dropdown"; -export * from "./sidebar-menu-hamburger-toogle"; diff --git a/admin/core/components/admin-sidebar/sidebar-menu-hamburger-toogle.tsx b/admin/core/components/admin-sidebar/sidebar-menu-hamburger-toogle.tsx deleted file mode 100644 index 337d9baaf..000000000 --- a/admin/core/components/admin-sidebar/sidebar-menu-hamburger-toogle.tsx +++ /dev/null @@ -1,20 +0,0 @@ -"use client"; - -import { FC } from "react"; -import { observer } from "mobx-react"; -// hooks -import { Menu } from "lucide-react"; -import { useTheme } from "@/hooks/store"; -// icons - -export const SidebarHamburgerToggle: FC = observer(() => { - const { isSidebarCollapsed, toggleSidebar } = useTheme(); - return ( -
toggleSidebar(!isSidebarCollapsed)} - > - -
- ); -}); diff --git a/admin/core/components/authentication/index.ts b/admin/core/components/authentication/index.ts deleted file mode 100644 index d189a727b..000000000 --- a/admin/core/components/authentication/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from "./auth-banner"; -export * from "./email-config-switch"; -export * from "./password-config-switch"; -export * from "./authentication-method-card"; -export * from "./gitlab-config"; -export * from "./github-config"; -export * from "./google-config"; diff --git a/admin/core/components/common/index.ts b/admin/core/components/common/index.ts deleted file mode 100644 index 4d664b0a4..000000000 --- a/admin/core/components/common/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from "./breadcrumb-link"; -export * from "./confirm-discard-modal"; -export * from "./controller-input"; -export * from "./copy-field"; -export * from "./password-strength-meter"; -export * from "./banner"; -export * from "./empty-state"; -export * from "./logo-spinner"; -export * from "./page-header"; -export * from "./code-block"; diff --git a/admin/core/components/instance/index.ts b/admin/core/components/instance/index.ts deleted file mode 100644 index 56d1933f4..000000000 --- a/admin/core/components/instance/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./instance-not-ready"; -export * from "./instance-failure-view"; -export * from "./setup-form"; diff --git a/admin/core/components/login/index.ts b/admin/core/components/login/index.ts deleted file mode 100644 index bdeb387f3..000000000 --- a/admin/core/components/login/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./sign-in-form"; diff --git a/admin/core/components/login/sign-in-form.tsx b/admin/core/components/login/sign-in-form.tsx deleted file mode 100644 index 553ffe6c5..000000000 --- a/admin/core/components/login/sign-in-form.tsx +++ /dev/null @@ -1,194 +0,0 @@ -"use client"; - -import { FC, useEffect, useMemo, useState } from "react"; -import { useSearchParams } from "next/navigation"; -import { Eye, EyeOff } from "lucide-react"; -// plane internal packages -import { API_BASE_URL, EAdminAuthErrorCodes, TAdminAuthErrorInfo } from "@plane/constants"; -import { AuthService } from "@plane/services"; -import { Button, Input, Spinner } from "@plane/ui"; -// components -import { Banner } from "@/components/common"; -// helpers -import { authErrorHandler } from "@/lib/auth-helpers"; -// local components -import { AuthBanner } from "../authentication"; - -// service initialization -const authService = new AuthService(); - -// error codes -enum EErrorCodes { - INSTANCE_NOT_CONFIGURED = "INSTANCE_NOT_CONFIGURED", - REQUIRED_EMAIL_PASSWORD = "REQUIRED_EMAIL_PASSWORD", - INVALID_EMAIL = "INVALID_EMAIL", - USER_DOES_NOT_EXIST = "USER_DOES_NOT_EXIST", - AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED", -} - -type TError = { - type: EErrorCodes | undefined; - message: string | undefined; -}; - -// form data -type TFormData = { - email: string; - password: string; -}; - -const defaultFromData: TFormData = { - email: "", - password: "", -}; - -export const InstanceSignInForm: FC = (props) => { - const {} = props; - // search params - const searchParams = useSearchParams(); - const emailParam = searchParams.get("email") || undefined; - const errorCode = searchParams.get("error_code") || undefined; - const errorMessage = searchParams.get("error_message") || undefined; - // state - const [showPassword, setShowPassword] = useState(false); - const [csrfToken, setCsrfToken] = useState(undefined); - const [formData, setFormData] = useState(defaultFromData); - const [isSubmitting, setIsSubmitting] = useState(false); - const [errorInfo, setErrorInfo] = useState(undefined); - - const handleFormChange = (key: keyof TFormData, value: string | boolean) => - setFormData((prev) => ({ ...prev, [key]: value })); - - useEffect(() => { - if (csrfToken === undefined) - authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); - }, [csrfToken]); - - useEffect(() => { - if (emailParam) setFormData((prev) => ({ ...prev, email: emailParam })); - }, [emailParam]); - - // derived values - const errorData: TError = useMemo(() => { - if (errorCode && errorMessage) { - switch (errorCode) { - case EErrorCodes.INSTANCE_NOT_CONFIGURED: - return { type: EErrorCodes.INVALID_EMAIL, message: errorMessage }; - case EErrorCodes.REQUIRED_EMAIL_PASSWORD: - return { type: EErrorCodes.REQUIRED_EMAIL_PASSWORD, message: errorMessage }; - case EErrorCodes.INVALID_EMAIL: - return { type: EErrorCodes.INVALID_EMAIL, message: errorMessage }; - case EErrorCodes.USER_DOES_NOT_EXIST: - return { type: EErrorCodes.USER_DOES_NOT_EXIST, message: errorMessage }; - case EErrorCodes.AUTHENTICATION_FAILED: - return { type: EErrorCodes.AUTHENTICATION_FAILED, message: errorMessage }; - default: - return { type: undefined, message: undefined }; - } - } else return { type: undefined, message: undefined }; - }, [errorCode, errorMessage]); - - const isButtonDisabled = useMemo( - () => (!isSubmitting && formData.email && formData.password ? false : true), - [formData.email, formData.password, isSubmitting] - ); - - useEffect(() => { - if (errorCode) { - const errorDetail = authErrorHandler(errorCode?.toString() as EAdminAuthErrorCodes); - if (errorDetail) { - setErrorInfo(errorDetail); - } - } - }, [errorCode]); - - return ( -
-
-
-

- Manage your Plane instance -

-

- Configure instance-wide settings to secure your instance -

-
- - {errorData.type && errorData?.message ? ( - - ) : ( - <>{errorInfo && setErrorInfo(value)} />} - )} - -
setIsSubmitting(true)} - onError={() => setIsSubmitting(false)} - > - - -
- - handleFormChange("email", e.target.value)} - autoComplete="on" - autoFocus - /> -
- -
- -
- handleFormChange("password", e.target.value)} - autoComplete="on" - /> - {showPassword ? ( - - ) : ( - - )} -
-
-
- -
-
-
-
- ); -}; diff --git a/admin/core/components/workspace/index.ts b/admin/core/components/workspace/index.ts deleted file mode 100644 index 24950c4f2..000000000 --- a/admin/core/components/workspace/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./list-item"; diff --git a/admin/core/lib/instance-provider.tsx b/admin/core/lib/instance-provider.tsx deleted file mode 100644 index d021e3b83..000000000 --- a/admin/core/lib/instance-provider.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { FC, ReactNode } from "react"; -import { observer } from "mobx-react"; -import useSWR from "swr"; -// components -import { LogoSpinner } from "@/components/common"; -import { InstanceSetupForm, InstanceFailureView } from "@/components/instance"; -// hooks -import { useInstance } from "@/hooks/store"; -// layout -import { DefaultLayout } from "@/layouts/default-layout"; - -type InstanceProviderProps = { - children: ReactNode; -}; - -export const InstanceProvider: FC = observer((props) => { - const { children } = props; - // store hooks - const { instance, error, fetchInstanceInfo } = useInstance(); - // fetching instance details - useSWR("INSTANCE_DETAILS", () => fetchInstanceInfo(), { - revalidateOnFocus: false, - revalidateIfStale: false, - errorRetryCount: 0, - }); - - if (!instance && !error) - return ( -
- -
- ); - - if (error) { - return ( - -
- -
-
- ); - } - - if (!instance?.is_setup_done) { - return ( - -
- -
-
- ); - } - - return <>{children}; -}); diff --git a/admin/next.config.js b/admin/next.config.js deleted file mode 100644 index 421f645e8..000000000 --- a/admin/next.config.js +++ /dev/null @@ -1,27 +0,0 @@ -/** @type {import('next').NextConfig} */ - -const nextConfig = { - trailingSlash: true, - reactStrictMode: false, - swcMinify: true, - output: "standalone", - images: { - unoptimized: true, - }, - basePath: process.env.NEXT_PUBLIC_ADMIN_BASE_PATH || "", - transpilePackages: [ - "@plane/constants", - "@plane/editor", - "@plane/hooks", - "@plane/i18n", - "@plane/logger", - "@plane/propel", - "@plane/services", - "@plane/shared-state", - "@plane/types", - "@plane/ui", - "@plane/utils", - ], -}; - -module.exports = nextConfig; diff --git a/aio/Dockerfile-app b/aio/Dockerfile-app deleted file mode 100644 index 7ffe3f803..000000000 --- a/aio/Dockerfile-app +++ /dev/null @@ -1,182 +0,0 @@ -ARG BASE_TAG=develop -ARG BUILD_TYPE=full -# ***************************************************************************** -# STAGE 1: Build the project -# ***************************************************************************** -FROM node:18-alpine AS builder -RUN apk add --no-cache libc6-compat -# Set working directory -WORKDIR /app - -RUN yarn global add turbo -COPY . . - -RUN turbo prune --scope=web --scope=space --scope=admin --docker - -# ***************************************************************************** -# STAGE 2: Install dependencies & build the project -# ***************************************************************************** -# Add lockfile and package.json's of isolated subworkspace -FROM node:18-alpine AS installer - -RUN apk add --no-cache libc6-compat -WORKDIR /app - -# First install the dependencies (as they change less often) -COPY .gitignore .gitignore -COPY --from=builder /app/out/json/ . -COPY --from=builder /app/out/yarn.lock ./yarn.lock -RUN yarn install - -# # Build the project -COPY --from=builder /app/out/full/ . -COPY turbo.json turbo.json - -ARG NEXT_PUBLIC_API_BASE_URL="" -ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL - -ARG NEXT_PUBLIC_ADMIN_BASE_URL="" -ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL - -ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode" -ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH - -ARG NEXT_PUBLIC_SPACE_BASE_URL="" -ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL - -ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces" -ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH - -ARG NEXT_PUBLIC_WEB_BASE_URL="" -ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL - -ENV NEXT_TELEMETRY_DISABLED=1 -ENV TURBO_TELEMETRY_DISABLED=1 - -RUN yarn turbo run build --filter=web --filter=space --filter=admin - -# ***************************************************************************** -# STAGE 3: Copy the project and start it -# ***************************************************************************** -FROM makeplane/plane-aio-base:${BUILD_TYPE}-${BASE_TAG} AS runner - -WORKDIR /app - -SHELL [ "/bin/bash", "-c" ] - -# PYTHON APPLICATION SETUP - -ENV PYTHONDONTWRITEBYTECODE=1 -ENV PYTHONUNBUFFERED=1 -ENV PIP_DISABLE_PIP_VERSION_CHECK=1 - -COPY apiserver/requirements.txt ./api/ -COPY apiserver/requirements ./api/requirements - -RUN pip install -r ./api/requirements.txt --compile --no-cache-dir - -# Add in Django deps and generate Django's static files -COPY apiserver/manage.py ./api/manage.py -COPY apiserver/plane ./api/plane/ -COPY apiserver/templates ./api/templates/ -COPY package.json ./api/package.json - -COPY apiserver/bin ./api/bin/ - -RUN chmod +x ./api/bin/* -RUN chmod -R 777 ./api/ - -# NEXTJS BUILDS -COPY --from=installer /app/web/next.config.js ./web/ -COPY --from=installer /app/web/package.json ./web/ -COPY --from=installer /app/web/.next/standalone ./web -COPY --from=installer /app/web/.next/static ./web/web/.next/static -COPY --from=installer /app/web/public ./web/web/public - -COPY --from=installer /app/space/next.config.js ./space/ -COPY --from=installer /app/space/package.json ./space/ -COPY --from=installer /app/space/.next/standalone ./space -COPY --from=installer /app/space/.next/static ./space/space/.next/static -COPY --from=installer /app/space/public ./space/space/public - -COPY --from=installer /app/admin/next.config.js ./admin/ -COPY --from=installer /app/admin/package.json ./admin/ -COPY --from=installer /app/admin/.next/standalone ./admin -COPY --from=installer /app/admin/.next/static ./admin/admin/.next/static -COPY --from=installer /app/admin/public ./admin/admin/public - -ARG NEXT_PUBLIC_API_BASE_URL="" -ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL - -ARG NEXT_PUBLIC_ADMIN_BASE_URL="" -ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL - -ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode" -ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH - -ARG NEXT_PUBLIC_SPACE_BASE_URL="" -ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL - -ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces" -ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH - -ARG NEXT_PUBLIC_WEB_BASE_URL="" -ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL - -ENV NEXT_TELEMETRY_DISABLED=1 -ENV TURBO_TELEMETRY_DISABLED=1 - -ARG BUILD_TYPE=full -ENV BUILD_TYPE=$BUILD_TYPE - -COPY aio/supervisord-${BUILD_TYPE}-base /app/supervisord.conf -COPY aio/supervisord-app /app/supervisord-app -RUN cat /app/supervisord-app >> /app/supervisord.conf && \ - rm /app/supervisord-app - -COPY ./aio/nginx.conf /etc/nginx/nginx.conf.template - -# if build type is full, run the below copy pg-setup.sh -COPY aio/postgresql.conf /etc/postgresql/postgresql.conf -COPY aio/pg-setup.sh /app/pg-setup.sh -RUN chmod +x /app/pg-setup.sh - -# ***************************************************************************** -# APPLICATION ENVIRONMENT SETTINGS -# ***************************************************************************** -ENV APP_DOMAIN=localhost -ENV WEB_URL=http://${APP_DOMAIN} -ENV DEBUG=0 -ENV CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN},https://${APP_DOMAIN} -# Secret Key -ENV SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5 -# Gunicorn Workers -ENV GUNICORN_WORKERS=1 - -ENV POSTGRES_USER="plane" -ENV POSTGRES_PASSWORD="plane" -ENV POSTGRES_DB="plane" -ENV POSTGRES_HOST="localhost" -ENV POSTGRES_PORT="5432" -ENV DATABASE_URL="postgresql://plane:plane@localhost:5432/plane" - -ENV REDIS_HOST="localhost" -ENV REDIS_PORT="6379" -ENV REDIS_URL="redis://localhost:6379" - -ENV USE_MINIO="1" -ENV AWS_REGION="" -ENV AWS_ACCESS_KEY_ID="access-key" -ENV AWS_SECRET_ACCESS_KEY="secret-key" -ENV AWS_S3_ENDPOINT_URL="http://localhost:9000" -ENV AWS_S3_BUCKET_NAME="uploads" -ENV MINIO_ROOT_USER="access-key" -ENV MINIO_ROOT_PASSWORD="secret-key" -ENV BUCKET_NAME="uploads" -ENV FILE_SIZE_LIMIT="5242880" - -# ***************************************************************************** - -RUN /app/pg-setup.sh - -CMD ["/usr/bin/supervisord", "-c", "/app/supervisord.conf"] diff --git a/aio/Dockerfile-base-full b/aio/Dockerfile-base-full deleted file mode 100644 index 218530948..000000000 --- a/aio/Dockerfile-base-full +++ /dev/null @@ -1,73 +0,0 @@ -FROM --platform=$BUILDPLATFORM tonistiigi/binfmt AS binfmt - -FROM python:3.12-slim - -# Set environment variables to non-interactive for apt -ENV DEBIAN_FRONTEND=noninteractive -ENV BUILD_TYPE=full - -SHELL [ "/bin/bash", "-c" ] - -WORKDIR /app - -RUN mkdir -p /app/{data,logs} && \ - mkdir -p /app/data/{redis,pg,minio,nginx} && \ - mkdir -p /app/logs/{access,error} && \ - mkdir -p /etc/supervisor/conf.d - -# Update the package list and install prerequisites -RUN apt-get update && \ - apt-get install -y \ - gnupg2 curl ca-certificates lsb-release software-properties-common \ - build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \ - libsqlite3-dev wget llvm libncurses5-dev libncursesw5-dev xz-utils \ - tk-dev libffi-dev liblzma-dev supervisor nginx nano vim ncdu \ - sudo lsof net-tools libpq-dev procps gettext - -# Install Redis 7.2 -RUN echo "deb http://deb.debian.org/debian $(lsb_release -cs)-backports main" > /etc/apt/sources.list.d/backports.list && \ - curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg && \ - echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" > /etc/apt/sources.list.d/redis.list && \ - apt-get update && \ - apt-get install -y redis-server - -# Install PostgreSQL 15 -ENV POSTGRES_VERSION=15 -RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/pgdg-archive-keyring.gpg && \ - echo "deb [signed-by=/usr/share/keyrings/pgdg-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \ - apt-get update && \ - apt-get install -y postgresql-$POSTGRES_VERSION postgresql-client-$POSTGRES_VERSION && \ - mkdir -p /var/lib/postgresql/data && \ - chown -R postgres:postgres /var/lib/postgresql -COPY postgresql.conf /etc/postgresql/postgresql.conf -RUN sudo -u postgres /usr/lib/postgresql/$POSTGRES_VERSION/bin/initdb -D /var/lib/postgresql/data - -# Install MinIO -ARG TARGETARCH -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - curl -fSl https://dl.min.io/server/minio/release/linux-amd64/minio -o /usr/local/bin/minio; \ - elif [ "$TARGETARCH" = "arm64" ]; then \ - curl -fSl https://dl.min.io/server/minio/release/linux-arm64/minio -o /usr/local/bin/minio; \ - else \ - echo "Unsupported architecture: $TARGETARCH"; exit 1; \ - fi && \ - chmod +x /usr/local/bin/minio - -# Install Node.js 18 -RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ - apt-get install -y nodejs && \ - python -m pip install --upgrade pip && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Create Supervisor configuration file -COPY supervisord-full-base /app/supervisord.conf -COPY nginx.conf /etc/nginx/nginx.conf.template -COPY env.sh /app/nginx-start.sh -RUN chmod +x /app/nginx-start.sh - -# Expose ports for Redis, PostgreSQL, and MinIO -EXPOSE 6379 5432 9000 80 443 - -# Start Supervisor -CMD ["/usr/bin/supervisord", "-c", "/app/supervisord.conf"] diff --git a/aio/Dockerfile-base-slim b/aio/Dockerfile-base-slim deleted file mode 100644 index c6bc249de..000000000 --- a/aio/Dockerfile-base-slim +++ /dev/null @@ -1,45 +0,0 @@ -FROM --platform=$BUILDPLATFORM tonistiigi/binfmt AS binfmt - -FROM python:3.12-slim - -# Set environment variables to non-interactive for apt -ENV DEBIAN_FRONTEND=noninteractive -ENV BUILD_TYPE=slim - -SHELL [ "/bin/bash", "-c" ] - -WORKDIR /app - -RUN mkdir -p /app/{data,logs} && \ - mkdir -p /app/data/{nginx} && \ - mkdir -p /app/logs/{access,error} && \ - mkdir -p /etc/supervisor/conf.d - -# Update the package list and install prerequisites -RUN apt-get update && \ - apt-get install -y \ - gnupg2 curl ca-certificates lsb-release software-properties-common \ - build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \ - libsqlite3-dev wget llvm libncurses5-dev libncursesw5-dev xz-utils \ - tk-dev libffi-dev liblzma-dev supervisor nginx nano vim ncdu \ - sudo lsof net-tools libpq-dev procps gettext - -# Install Node.js 18 -RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ - apt-get install -y nodejs - -RUN python -m pip install --upgrade pip && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Create Supervisor configuration file -COPY supervisord-slim-base /app/supervisord.conf -COPY nginx.conf /etc/nginx/nginx.conf.template -COPY env.sh /app/nginx-start.sh -RUN chmod +x /app/nginx-start.sh - -# Expose ports for Redis, PostgreSQL, and MinIO -EXPOSE 80 443 - -# Start Supervisor -CMD ["/usr/bin/supervisord", "-c", "/app/supervisord.conf"] diff --git a/aio/env.sh b/aio/env.sh deleted file mode 100644 index ff5f769fd..000000000 --- a/aio/env.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -export dollar="$" -export http_upgrade="http_upgrade" -export scheme="scheme" -envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf -exec nginx -g 'daemon off;' diff --git a/aio/nginx.conf b/aio/nginx.conf deleted file mode 100644 index 78ae00d28..000000000 --- a/aio/nginx.conf +++ /dev/null @@ -1,72 +0,0 @@ -events { -} - -http { - sendfile on; - - server { - listen 80; - root /www/data/; - access_log /var/log/nginx/access.log; - - client_max_body_size ${FILE_SIZE_LIMIT}; - - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - add_header Permissions-Policy "interest-cohort=()" always; - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - add_header X-Forwarded-Proto "${dollar}scheme"; - add_header X-Forwarded-Host "${dollar}host"; - add_header X-Forwarded-For "${dollar}proxy_add_x_forwarded_for"; - add_header X-Real-IP "${dollar}remote_addr"; - - location / { - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:3001/; - } - - location /spaces/ { - rewrite ^/spaces/?$ /spaces/login break; - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:3002/spaces/; - } - - location /god-mode/ { - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:3003/god-mode/; - } - - location /api/ { - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:8000/api/; - } - - location /auth/ { - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:8000/auth/; - } - - location /${BUCKET_NAME}/ { - proxy_http_version 1.1; - proxy_set_header Upgrade ${dollar}http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host ${dollar}http_host; - proxy_pass http://localhost:9000/uploads/; - } - } -} diff --git a/aio/pg-setup.sh b/aio/pg-setup.sh deleted file mode 100644 index b830acc5e..000000000 --- a/aio/pg-setup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -if [ "$BUILD_TYPE" == "full" ]; then - - export PGHOST=localhost - - sudo -u postgres "/usr/lib/postgresql/${POSTGRES_VERSION}/bin/pg_ctl" -D /var/lib/postgresql/data start - sudo -u postgres "/usr/lib/postgresql/${POSTGRES_VERSION}/bin/psql" --command "CREATE USER $POSTGRES_USER WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" && \ - sudo -u postgres "/usr/lib/postgresql/${POSTGRES_VERSION}/bin/createdb" -O "$POSTGRES_USER" "$POSTGRES_DB" && \ - sudo -u postgres "/usr/lib/postgresql/${POSTGRES_VERSION}/bin/psql" --command "GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_USER;" && \ - sudo -u postgres "/usr/lib/postgresql/${POSTGRES_VERSION}/bin/pg_ctl" -D /var/lib/postgresql/data stop - -fi - diff --git a/aio/postgresql.conf b/aio/postgresql.conf deleted file mode 100644 index 8f3c4e8a4..000000000 --- a/aio/postgresql.conf +++ /dev/null @@ -1,815 +0,0 @@ -# ----------------------------- -# PostgreSQL configuration file -# ----------------------------- -# -# This file consists of lines of the form: -# -# name = value -# -# (The "=" is optional.) Whitespace may be used. Comments are introduced with -# "#" anywhere on a line. The complete list of parameter names and allowed -# values can be found in the PostgreSQL documentation. -# -# The commented-out settings shown in this file represent the default values. -# Re-commenting a setting is NOT sufficient to revert it to the default value; -# you need to reload the server. -# -# This file is read on server startup and when the server receives a SIGHUP -# signal. If you edit the file on a running system, you have to SIGHUP the -# server for the changes to take effect, run "pg_ctl reload", or execute -# "SELECT pg_reload_conf()". Some parameters, which are marked below, -# require a server shutdown and restart to take effect. -# -# Any parameter can also be given as a command-line option to the server, e.g., -# "postgres -c log_connections=on". Some parameters can be changed at run time -# with the "SET" SQL command. -# -# Memory units: B = bytes Time units: us = microseconds -# kB = kilobytes ms = milliseconds -# MB = megabytes s = seconds -# GB = gigabytes min = minutes -# TB = terabytes h = hours -# d = days - - -#------------------------------------------------------------------------------ -# FILE LOCATIONS -#------------------------------------------------------------------------------ - -# The default values of these variables are driven from the -D command-line -# option or PGDATA environment variable, represented here as ConfigDir. - -data_directory = '/var/lib/postgresql/data' # use data in another directory - # (change requires restart) -hba_file = '/etc/postgresql/15/main/pg_hba.conf' # host-based authentication file - # (change requires restart) -ident_file = '/etc/postgresql/15/main/pg_ident.conf' # ident configuration file - # (change requires restart) - -# If external_pid_file is not explicitly set, no extra PID file is written. -external_pid_file = '/var/run/postgresql/15-main.pid' # write an extra PID file - # (change requires restart) - - -#------------------------------------------------------------------------------ -# CONNECTIONS AND AUTHENTICATION -#------------------------------------------------------------------------------ - -# - Connection Settings - - -listen_addresses = 'localhost' # what IP address(es) to listen on; - # comma-separated list of addresses; - # defaults to 'localhost'; use '*' for all - # (change requires restart) -port = 5432 # (change requires restart) -max_connections = 200 # (change requires restart) -#superuser_reserved_connections = 3 # (change requires restart) -unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories - # (change requires restart) -#unix_socket_group = '' # (change requires restart) -#unix_socket_permissions = 0777 # begin with 0 to use octal notation - # (change requires restart) -#bonjour = off # advertise server via Bonjour - # (change requires restart) -#bonjour_name = '' # defaults to the computer name - # (change requires restart) - -# - TCP settings - -# see "man tcp" for details - -#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; - # 0 selects the system default -#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; - # 0 selects the system default -#tcp_keepalives_count = 0 # TCP_KEEPCNT; - # 0 selects the system default -#tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds; - # 0 selects the system default - -#client_connection_check_interval = 0 # time between checks for client - # disconnection while running queries; - # 0 for never - -# - Authentication - - -#authentication_timeout = 1min # 1s-600s -#password_encryption = scram-sha-256 # scram-sha-256 or md5 -#db_user_namespace = off - -# GSSAPI using Kerberos -#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab' -#krb_caseins_users = off - -# - SSL - - -ssl = on -#ssl_ca_file = '' -ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem' -#ssl_crl_file = '' -#ssl_crl_dir = '' -ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key' -#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers -#ssl_prefer_server_ciphers = on -#ssl_ecdh_curve = 'prime256v1' -#ssl_min_protocol_version = 'TLSv1.2' -#ssl_max_protocol_version = '' -#ssl_dh_params_file = '' -#ssl_passphrase_command = '' -#ssl_passphrase_command_supports_reload = off - - -#------------------------------------------------------------------------------ -# RESOURCE USAGE (except WAL) -#------------------------------------------------------------------------------ - -# - Memory - - -shared_buffers = 256MB # min 128kB - # (change requires restart) -#huge_pages = try # on, off, or try - # (change requires restart) -#huge_page_size = 0 # zero for system default - # (change requires restart) -#temp_buffers = 8MB # min 800kB -#max_prepared_transactions = 0 # zero disables the feature - # (change requires restart) -# Caution: it is not advisable to set max_prepared_transactions nonzero unless -# you actively intend to use prepared transactions. -#work_mem = 4MB # min 64kB -#hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem -#maintenance_work_mem = 64MB # min 1MB -#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem -#logical_decoding_work_mem = 64MB # min 64kB -#max_stack_depth = 2MB # min 100kB -#shared_memory_type = mmap # the default is the first option - # supported by the operating system: - # mmap - # sysv - # windows - # (change requires restart) -dynamic_shared_memory_type = posix # the default is usually the first option - # supported by the operating system: - # posix - # sysv - # windows - # mmap - # (change requires restart) -#min_dynamic_shared_memory = 0MB # (change requires restart) - -# - Disk - - -#temp_file_limit = -1 # limits per-process temp file space - # in kilobytes, or -1 for no limit - -# - Kernel Resources - - -#max_files_per_process = 1000 # min 64 - # (change requires restart) - -# - Cost-Based Vacuum Delay - - -#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) -#vacuum_cost_page_hit = 1 # 0-10000 credits -#vacuum_cost_page_miss = 2 # 0-10000 credits -#vacuum_cost_page_dirty = 20 # 0-10000 credits -#vacuum_cost_limit = 200 # 1-10000 credits - -# - Background Writer - - -#bgwriter_delay = 200ms # 10-10000ms between rounds -#bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables -#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round -#bgwriter_flush_after = 512kB # measured in pages, 0 disables - -# - Asynchronous Behavior - - -#backend_flush_after = 0 # measured in pages, 0 disables -#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching -#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching -#max_worker_processes = 8 # (change requires restart) -#max_parallel_workers_per_gather = 2 # limited by max_parallel_workers -#max_parallel_maintenance_workers = 2 # limited by max_parallel_workers -#max_parallel_workers = 8 # number of max_worker_processes that - # can be used in parallel operations -#parallel_leader_participation = on -#old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate - # (change requires restart) - - -#------------------------------------------------------------------------------ -# WRITE-AHEAD LOG -#------------------------------------------------------------------------------ - -# - Settings - - -#wal_level = replica # minimal, replica, or logical - # (change requires restart) -#fsync = on # flush data to disk for crash safety - # (turning this off can cause - # unrecoverable data corruption) -#synchronous_commit = on # synchronization level; - # off, local, remote_write, remote_apply, or on -#wal_sync_method = fsync # the default is the first option - # supported by the operating system: - # open_datasync - # fdatasync (default on Linux and FreeBSD) - # fsync - # fsync_writethrough - # open_sync -#full_page_writes = on # recover from partial page writes -#wal_log_hints = off # also do full page writes of non-critical updates - # (change requires restart) -#wal_compression = off # enables compression of full-page writes; - # off, pglz, lz4, zstd, or on -#wal_init_zero = on # zero-fill new WAL files -#wal_recycle = on # recycle WAL files -#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers - # (change requires restart) -#wal_writer_delay = 200ms # 1-10000 milliseconds -#wal_writer_flush_after = 1MB # measured in pages, 0 disables -#wal_skip_threshold = 2MB - -#commit_delay = 0 # range 0-100000, in microseconds -#commit_siblings = 5 # range 1-1000 - -# - Checkpoints - - -#checkpoint_timeout = 5min # range 30s-1d -#checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0 -#checkpoint_flush_after = 256kB # measured in pages, 0 disables -#checkpoint_warning = 30s # 0 disables -max_wal_size = 1GB -min_wal_size = 80MB - -# - Prefetching during recovery - - -#recovery_prefetch = try # prefetch pages referenced in the WAL? -#wal_decode_buffer_size = 512kB # lookahead window used for prefetching - # (change requires restart) - -# - Archiving - - -#archive_mode = off # enables archiving; off, on, or always - # (change requires restart) -#archive_library = '' # library to use to archive a logfile segment - # (empty string indicates archive_command should - # be used) -#archive_command = '' # command to use to archive a logfile segment - # placeholders: %p = path of file to archive - # %f = file name only - # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' -#archive_timeout = 0 # force a logfile segment switch after this - # number of seconds; 0 disables - -# - Archive Recovery - - -# These are only used in recovery mode. - -#restore_command = '' # command to use to restore an archived logfile segment - # placeholders: %p = path of file to restore - # %f = file name only - # e.g. 'cp /mnt/server/archivedir/%f %p' -#archive_cleanup_command = '' # command to execute at every restartpoint -#recovery_end_command = '' # command to execute at completion of recovery - -# - Recovery Target - - -# Set these only when performing a targeted recovery. - -#recovery_target = '' # 'immediate' to end recovery as soon as a - # consistent state is reached - # (change requires restart) -#recovery_target_name = '' # the named restore point to which recovery will proceed - # (change requires restart) -#recovery_target_time = '' # the time stamp up to which recovery will proceed - # (change requires restart) -#recovery_target_xid = '' # the transaction ID up to which recovery will proceed - # (change requires restart) -#recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed - # (change requires restart) -#recovery_target_inclusive = on # Specifies whether to stop: - # just after the specified recovery target (on) - # just before the recovery target (off) - # (change requires restart) -#recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID - # (change requires restart) -#recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown' - # (change requires restart) - - -#------------------------------------------------------------------------------ -# REPLICATION -#------------------------------------------------------------------------------ - -# - Sending Servers - - -# Set these on the primary and on any standby that will send replication data. - -#max_wal_senders = 10 # max number of walsender processes - # (change requires restart) -#max_replication_slots = 10 # max number of replication slots - # (change requires restart) -#wal_keep_size = 0 # in megabytes; 0 disables -#max_slot_wal_keep_size = -1 # in megabytes; -1 disables -#wal_sender_timeout = 60s # in milliseconds; 0 disables -#track_commit_timestamp = off # collect timestamp of transaction commit - # (change requires restart) - -# - Primary Server - - -# These settings are ignored on a standby server. - -#synchronous_standby_names = '' # standby servers that provide sync rep - # method to choose sync standbys, number of sync standbys, - # and comma-separated list of application_name - # from standby(s); '*' = all -#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed - -# - Standby Servers - - -# These settings are ignored on a primary server. - -#primary_conninfo = '' # connection string to sending server -#primary_slot_name = '' # replication slot on sending server -#promote_trigger_file = '' # file name whose presence ends recovery -#hot_standby = on # "off" disallows queries during recovery - # (change requires restart) -#max_standby_archive_delay = 30s # max delay before canceling queries - # when reading WAL from archive; - # -1 allows indefinite delay -#max_standby_streaming_delay = 30s # max delay before canceling queries - # when reading streaming WAL; - # -1 allows indefinite delay -#wal_receiver_create_temp_slot = off # create temp slot if primary_slot_name - # is not set -#wal_receiver_status_interval = 10s # send replies at least this often - # 0 disables -#hot_standby_feedback = off # send info from standby to prevent - # query conflicts -#wal_receiver_timeout = 60s # time that receiver waits for - # communication from primary - # in milliseconds; 0 disables -#wal_retrieve_retry_interval = 5s # time to wait before retrying to - # retrieve WAL after a failed attempt -#recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery - -# - Subscribers - - -# These settings are ignored on a publisher. - -#max_logical_replication_workers = 4 # taken from max_worker_processes - # (change requires restart) -#max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers - - -#------------------------------------------------------------------------------ -# QUERY TUNING -#------------------------------------------------------------------------------ - -# - Planner Method Configuration - - -#enable_async_append = on -#enable_bitmapscan = on -#enable_gathermerge = on -#enable_hashagg = on -#enable_hashjoin = on -#enable_incremental_sort = on -#enable_indexscan = on -#enable_indexonlyscan = on -#enable_material = on -#enable_memoize = on -#enable_mergejoin = on -#enable_nestloop = on -#enable_parallel_append = on -#enable_parallel_hash = on -#enable_partition_pruning = on -#enable_partitionwise_join = off -#enable_partitionwise_aggregate = off -#enable_seqscan = on -#enable_sort = on -#enable_tidscan = on - -# - Planner Cost Constants - - -#seq_page_cost = 1.0 # measured on an arbitrary scale -#random_page_cost = 4.0 # same scale as above -#cpu_tuple_cost = 0.01 # same scale as above -#cpu_index_tuple_cost = 0.005 # same scale as above -#cpu_operator_cost = 0.0025 # same scale as above -#parallel_setup_cost = 1000.0 # same scale as above -#parallel_tuple_cost = 0.1 # same scale as above -#min_parallel_table_scan_size = 8MB -#min_parallel_index_scan_size = 512kB -#effective_cache_size = 4GB - -#jit_above_cost = 100000 # perform JIT compilation if available - # and query more expensive than this; - # -1 disables -#jit_inline_above_cost = 500000 # inline small functions if query is - # more expensive than this; -1 disables -#jit_optimize_above_cost = 500000 # use expensive JIT optimizations if - # query is more expensive than this; - # -1 disables - -# - Genetic Query Optimizer - - -#geqo = on -#geqo_threshold = 12 -#geqo_effort = 5 # range 1-10 -#geqo_pool_size = 0 # selects default based on effort -#geqo_generations = 0 # selects default based on effort -#geqo_selection_bias = 2.0 # range 1.5-2.0 -#geqo_seed = 0.0 # range 0.0-1.0 - -# - Other Planner Options - - -#default_statistics_target = 100 # range 1-10000 -#constraint_exclusion = partition # on, off, or partition -#cursor_tuple_fraction = 0.1 # range 0.0-1.0 -#from_collapse_limit = 8 -#jit = on # allow JIT compilation -#join_collapse_limit = 8 # 1 disables collapsing of explicit - # JOIN clauses -#plan_cache_mode = auto # auto, force_generic_plan or - # force_custom_plan -#recursive_worktable_factor = 10.0 # range 0.001-1000000 - - -#------------------------------------------------------------------------------ -# REPORTING AND LOGGING -#------------------------------------------------------------------------------ - -# - Where to Log - - -#log_destination = 'stderr' # Valid values are combinations of - # stderr, csvlog, jsonlog, syslog, and - # eventlog, depending on platform. - # csvlog and jsonlog require - # logging_collector to be on. - -# This is used when logging to stderr: -#logging_collector = off # Enable capturing of stderr, jsonlog, - # and csvlog into log files. Required - # to be on for csvlogs and jsonlogs. - # (change requires restart) - -# These are only used if logging_collector is on: -#log_directory = 'log' # directory where log files are written, - # can be absolute or relative to PGDATA -#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, - # can include strftime() escapes -#log_file_mode = 0600 # creation mode for log files, - # begin with 0 to use octal notation -#log_rotation_age = 1d # Automatic rotation of logfiles will - # happen after that time. 0 disables. -#log_rotation_size = 10MB # Automatic rotation of logfiles will - # happen after that much log output. - # 0 disables. -#log_truncate_on_rotation = off # If on, an existing log file with the - # same name as the new log file will be - # truncated rather than appended to. - # But such truncation only occurs on - # time-driven rotation, not on restarts - # or size-driven rotation. Default is - # off, meaning append to existing files - # in all cases. - -# These are relevant when logging to syslog: -#syslog_facility = 'LOCAL0' -#syslog_ident = 'postgres' -#syslog_sequence_numbers = on -#syslog_split_messages = on - -# This is only relevant when logging to eventlog (Windows): -# (change requires restart) -#event_source = 'PostgreSQL' - -# - When to Log - - -#log_min_messages = warning # values in order of decreasing detail: - # debug5 - # debug4 - # debug3 - # debug2 - # debug1 - # info - # notice - # warning - # error - # log - # fatal - # panic - -#log_min_error_statement = error # values in order of decreasing detail: - # debug5 - # debug4 - # debug3 - # debug2 - # debug1 - # info - # notice - # warning - # error - # log - # fatal - # panic (effectively off) - -#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements - # and their durations, > 0 logs only - # statements running at least this number - # of milliseconds - -#log_min_duration_sample = -1 # -1 is disabled, 0 logs a sample of statements - # and their durations, > 0 logs only a sample of - # statements running at least this number - # of milliseconds; - # sample fraction is determined by log_statement_sample_rate - -#log_statement_sample_rate = 1.0 # fraction of logged statements exceeding - # log_min_duration_sample to be logged; - # 1.0 logs all such statements, 0.0 never logs - - -#log_transaction_sample_rate = 0.0 # fraction of transactions whose statements - # are logged regardless of their duration; 1.0 logs all - # statements from all transactions, 0.0 never logs - -#log_startup_progress_interval = 10s # Time between progress updates for - # long-running startup operations. - # 0 disables the feature, > 0 indicates - # the interval in milliseconds. - -# - What to Log - - -#debug_print_parse = off -#debug_print_rewritten = off -#debug_print_plan = off -#debug_pretty_print = on -#log_autovacuum_min_duration = 10min # log autovacuum activity; - # -1 disables, 0 logs all actions and - # their durations, > 0 logs only - # actions running at least this number - # of milliseconds. -#log_checkpoints = on -#log_connections = off -#log_disconnections = off -#log_duration = off -#log_error_verbosity = default # terse, default, or verbose messages -#log_hostname = off -log_line_prefix = '%m [%p] %q%u@%d ' # special values: - # %a = application name - # %u = user name - # %d = database name - # %r = remote host and port - # %h = remote host - # %b = backend type - # %p = process ID - # %P = process ID of parallel group leader - # %t = timestamp without milliseconds - # %m = timestamp with milliseconds - # %n = timestamp with milliseconds (as a Unix epoch) - # %Q = query ID (0 if none or not computed) - # %i = command tag - # %e = SQL state - # %c = session ID - # %l = session line number - # %s = session start timestamp - # %v = virtual transaction ID - # %x = transaction ID (0 if none) - # %q = stop here in non-session - # processes - # %% = '%' - # e.g. '<%u%%%d> ' -#log_lock_waits = off # log lock waits >= deadlock_timeout -#log_recovery_conflict_waits = off # log standby recovery conflict waits - # >= deadlock_timeout -#log_parameter_max_length = -1 # when logging statements, limit logged - # bind-parameter values to N bytes; - # -1 means print in full, 0 disables -#log_parameter_max_length_on_error = 0 # when logging an error, limit logged - # bind-parameter values to N bytes; - # -1 means print in full, 0 disables -#log_statement = 'none' # none, ddl, mod, all -#log_replication_commands = off -#log_temp_files = -1 # log temporary files equal or larger - # than the specified size in kilobytes; - # -1 disables, 0 logs all temp files -log_timezone = 'Etc/UTC' - - -#------------------------------------------------------------------------------ -# PROCESS TITLE -#------------------------------------------------------------------------------ - -cluster_name = '15/main' # added to process titles if nonempty - # (change requires restart) -#update_process_title = on - - -#------------------------------------------------------------------------------ -# STATISTICS -#------------------------------------------------------------------------------ - -# - Cumulative Query and Index Statistics - - -#track_activities = on -#track_activity_query_size = 1024 # (change requires restart) -#track_counts = on -#track_io_timing = off -#track_wal_io_timing = off -#track_functions = none # none, pl, all -#stats_fetch_consistency = cache - - -# - Monitoring - - -#compute_query_id = auto -#log_statement_stats = off -#log_parser_stats = off -#log_planner_stats = off -#log_executor_stats = off - - -#------------------------------------------------------------------------------ -# AUTOVACUUM -#------------------------------------------------------------------------------ - -#autovacuum = on # Enable autovacuum subprocess? 'on' - # requires track_counts to also be on. -#autovacuum_max_workers = 3 # max number of autovacuum subprocesses - # (change requires restart) -#autovacuum_naptime = 1min # time between autovacuum runs -#autovacuum_vacuum_threshold = 50 # min number of row updates before - # vacuum -#autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts - # before vacuum; -1 disables insert - # vacuums -#autovacuum_analyze_threshold = 50 # min number of row updates before - # analyze -#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum -#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table - # size before insert vacuum -#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze -#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum - # (change requires restart) -#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age - # before forced vacuum - # (change requires restart) -#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for - # autovacuum, in milliseconds; - # -1 means use vacuum_cost_delay -#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for - # autovacuum, -1 means use - # vacuum_cost_limit - - -#------------------------------------------------------------------------------ -# CLIENT CONNECTION DEFAULTS -#------------------------------------------------------------------------------ - -# - Statement Behavior - - -#client_min_messages = notice # values in order of decreasing detail: - # debug5 - # debug4 - # debug3 - # debug2 - # debug1 - # log - # notice - # warning - # error -#search_path = '"$user", public' # schema names -#row_security = on -#default_table_access_method = 'heap' -#default_tablespace = '' # a tablespace name, '' uses the default -#default_toast_compression = 'pglz' # 'pglz' or 'lz4' -#temp_tablespaces = '' # a list of tablespace names, '' uses - # only default tablespace -#check_function_bodies = on -#default_transaction_isolation = 'read committed' -#default_transaction_read_only = off -#default_transaction_deferrable = off -#session_replication_role = 'origin' -#statement_timeout = 0 # in milliseconds, 0 is disabled -#lock_timeout = 0 # in milliseconds, 0 is disabled -#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled -#idle_session_timeout = 0 # in milliseconds, 0 is disabled -#vacuum_freeze_table_age = 150000000 -#vacuum_freeze_min_age = 50000000 -#vacuum_failsafe_age = 1600000000 -#vacuum_multixact_freeze_table_age = 150000000 -#vacuum_multixact_freeze_min_age = 5000000 -#vacuum_multixact_failsafe_age = 1600000000 -#bytea_output = 'hex' # hex, escape -#xmlbinary = 'base64' -#xmloption = 'content' -#gin_pending_list_limit = 4MB - -# - Locale and Formatting - - -datestyle = 'iso, mdy' -#intervalstyle = 'postgres' -timezone = 'Etc/UTC' -#timezone_abbreviations = 'Default' # Select the set of available time zone - # abbreviations. Currently, there are - # Default - # Australia (historical usage) - # India - # You can create your own file in - # share/timezonesets/. -#extra_float_digits = 1 # min -15, max 3; any value >0 actually - # selects precise output mode -#client_encoding = sql_ascii # actually, defaults to database - # encoding - -# These settings are initialized by initdb, but they can be changed. -lc_messages = 'C.UTF-8' # locale for system error message - # strings -lc_monetary = 'C.UTF-8' # locale for monetary formatting -lc_numeric = 'C.UTF-8' # locale for number formatting -lc_time = 'C.UTF-8' # locale for time formatting - -# default configuration for text search -default_text_search_config = 'pg_catalog.english' - -# - Shared Library Preloading - - -#local_preload_libraries = '' -#session_preload_libraries = '' -#shared_preload_libraries = '' # (change requires restart) -#jit_provider = 'llvmjit' # JIT library to use - -# - Other Defaults - - -#dynamic_library_path = '$libdir' -#extension_destdir = '' # prepend path when loading extensions - # and shared objects (added by Debian) -#gin_fuzzy_search_limit = 0 - - -#------------------------------------------------------------------------------ -# LOCK MANAGEMENT -#------------------------------------------------------------------------------ - -#deadlock_timeout = 1s -#max_locks_per_transaction = 64 # min 10 - # (change requires restart) -#max_pred_locks_per_transaction = 64 # min 10 - # (change requires restart) -#max_pred_locks_per_relation = -2 # negative values mean - # (max_pred_locks_per_transaction - # / -max_pred_locks_per_relation) - 1 -#max_pred_locks_per_page = 2 # min 0 - - -#------------------------------------------------------------------------------ -# VERSION AND PLATFORM COMPATIBILITY -#------------------------------------------------------------------------------ - -# - Previous PostgreSQL Versions - - -#array_nulls = on -#backslash_quote = safe_encoding # on, off, or safe_encoding -#escape_string_warning = on -#lo_compat_privileges = off -#quote_all_identifiers = off -#standard_conforming_strings = on -#synchronize_seqscans = on - -# - Other Platforms and Clients - - -#transform_null_equals = off - - -#------------------------------------------------------------------------------ -# ERROR HANDLING -#------------------------------------------------------------------------------ - -#exit_on_error = off # terminate session on any error? -#restart_after_crash = on # reinitialize after backend crash? -#data_sync_retry = off # retry or panic on failure to fsync - # data? - # (change requires restart) -#recovery_init_sync_method = fsync # fsync, syncfs (Linux 5.8+) - - -#------------------------------------------------------------------------------ -# CONFIG FILE INCLUDES -#------------------------------------------------------------------------------ - -# These options allow settings to be loaded from files other than the -# default postgresql.conf. Note that these are directives, not variable -# assignments, so they can usefully be given more than once. - -# include_dir = 'conf.d' # include files ending in '.conf' from - # a directory, e.g., 'conf.d' -#include_if_exists = '...' # include file only if it exists -#include = '...' # include file - - -#------------------------------------------------------------------------------ -# CUSTOMIZED OPTIONS -#------------------------------------------------------------------------------ - -# Add settings for extensions here diff --git a/aio/supervisord-app b/aio/supervisord-app deleted file mode 100644 index e2cf1f047..000000000 --- a/aio/supervisord-app +++ /dev/null @@ -1,71 +0,0 @@ - -[program:web] -command=node /app/web/web/server.js -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 -environment=PORT=3001,HOSTNAME=0.0.0.0 - -[program:space] -command=node /app/space/space/server.js -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 -environment=PORT=3002,HOSTNAME=0.0.0.0 - -[program:admin] -command=node /app/admin/admin/server.js -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 -environment=PORT=3003,HOSTNAME=0.0.0.0 - -[program:migrator] -directory=/app/api -command=sh -c "./bin/docker-entrypoint-migrator.sh" -autostart=true -autorestart=false -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 - -[program:api] -directory=/app/api -command=sh -c "./bin/docker-entrypoint-api.sh" -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 - -[program:worker] -directory=/app/api -command=sh -c "./bin/docker-entrypoint-worker.sh" -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 - -[program:beat] -directory=/app/api -command=sh -c "./bin/docker-entrypoint-beat.sh" -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stdout -stderr_logfile_maxbytes=0 - diff --git a/aio/supervisord-full-base b/aio/supervisord-full-base deleted file mode 100644 index 0a6c27e13..000000000 --- a/aio/supervisord-full-base +++ /dev/null @@ -1,38 +0,0 @@ -[supervisord] -user=root -nodaemon=true -stderr_logfile=/app/logs/error/supervisor.err.log -stdout_logfile=/app/logs/access/supervisor.log - -[program:redis] -directory=/app/data/redis -command=redis-server -autostart=true -autorestart=true -stderr_logfile=/app/logs/error/redis.err.log -stdout_logfile=/app/logs/access/redis.log - -[program:postgresql] -user=postgres -command=/usr/lib/postgresql/15/bin/postgres --config-file=/etc/postgresql/postgresql.conf -autostart=true -autorestart=true -stderr_logfile=/app/logs/error/postgresql.err.log -stdout_logfile=/app/logs/access/postgresql.log - -[program:minio] -directory=/app/data/minio -command=minio server /app/data/minio -autostart=true -autorestart=true -stderr_logfile=/app/logs/error/minio.err.log -stdout_logfile=/app/logs/access/minio.log - -[program:nginx] -directory=/app/data/nginx -command=/app/nginx-start.sh -autostart=true -autorestart=true -stderr_logfile=/app/logs/error/nginx.err.log -stdout_logfile=/app/logs/access/nginx.log - diff --git a/aio/supervisord-slim-base b/aio/supervisord-slim-base deleted file mode 100644 index 24509216e..000000000 --- a/aio/supervisord-slim-base +++ /dev/null @@ -1,14 +0,0 @@ -[supervisord] -user=root -nodaemon=true -stderr_logfile=/app/logs/error/supervisor.err.log -stdout_logfile=/app/logs/access/supervisor.log - -[program:nginx] -directory=/app/data/nginx -command=/app/nginx-start.sh -autostart=true -autorestart=true -stderr_logfile=/app/logs/error/nginx.err.log -stdout_logfile=/app/logs/access/nginx.log - diff --git a/apiserver/Procfile b/apiserver/Procfile deleted file mode 100644 index 63736e8e8..000000000 --- a/apiserver/Procfile +++ /dev/null @@ -1,3 +0,0 @@ -web: gunicorn -w 4 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:$PORT --max-requests 10000 --max-requests-jitter 1000 --access-logfile - -worker: celery -A plane worker -l info -beat: celery -A plane beat -l INFO \ No newline at end of file diff --git a/apiserver/back_migration.py b/apiserver/back_migration.py deleted file mode 100644 index 69eb2f1df..000000000 --- a/apiserver/back_migration.py +++ /dev/null @@ -1,224 +0,0 @@ -# All the python scripts that are used for back migrations -import uuid -import random -from django.contrib.auth.hashers import make_password -from plane.db.models import ProjectIdentifier -from plane.db.models import ( - Issue, - IssueComment, - User, - Project, - ProjectMember, - Label, - Integration, -) - - -# Update description and description html values for old descriptions -def update_description(): - try: - issues = Issue.objects.all() - updated_issues = [] - - for issue in issues: - issue.description_html = f"

{issue.description}

" - issue.description_stripped = issue.description - updated_issues.append(issue) - - Issue.objects.bulk_update( - updated_issues, ["description_html", "description_stripped"], batch_size=100 - ) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_comments(): - try: - issue_comments = IssueComment.objects.all() - updated_issue_comments = [] - - for issue_comment in issue_comments: - issue_comment.comment_html = f"

{issue_comment.comment_stripped}

" - updated_issue_comments.append(issue_comment) - - IssueComment.objects.bulk_update( - updated_issue_comments, ["comment_html"], batch_size=100 - ) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_project_identifiers(): - try: - project_identifiers = ProjectIdentifier.objects.filter( - workspace_id=None - ).select_related("project", "project__workspace") - updated_identifiers = [] - - for identifier in project_identifiers: - identifier.workspace_id = identifier.project.workspace_id - updated_identifiers.append(identifier) - - ProjectIdentifier.objects.bulk_update( - updated_identifiers, ["workspace_id"], batch_size=50 - ) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_user_empty_password(): - try: - users = User.objects.filter(password="") - updated_users = [] - - for user in users: - user.password = make_password(uuid.uuid4().hex) - user.is_password_autoset = True - updated_users.append(user) - - User.objects.bulk_update(updated_users, ["password"], batch_size=50) - print("Success") - - except Exception as e: - print(e) - print("Failed") - - -def updated_issue_sort_order(): - try: - issues = Issue.objects.all() - updated_issues = [] - - for issue in issues: - issue.sort_order = issue.sequence_id * random.randint(100, 500) - updated_issues.append(issue) - - Issue.objects.bulk_update(updated_issues, ["sort_order"], batch_size=100) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_project_cover_images(): - try: - project_cover_images = [ - "https://images.unsplash.com/photo-1677432658720-3d84f9d657b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1661107564401-57497d8fe86f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80", - "https://images.unsplash.com/photo-1677352241429-dc90cfc7a623?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80", - "https://images.unsplash.com/photo-1677196728306-eeafea692454?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1331&q=80", - "https://images.unsplash.com/photo-1660902179734-c94c944f7830?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1255&q=80", - "https://images.unsplash.com/photo-1672243775941-10d763d9adef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1677040628614-53936ff66632?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1676920410907-8d5f8dd4b5ba?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80", - "https://images.unsplash.com/photo-1676846328604-ce831c481346?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1155&q=80", - "https://images.unsplash.com/photo-1676744843212-09b7e64c3a05?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1676798531090-1608bedeac7b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1597088758740-56fd7ec8a3f0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1169&q=80", - "https://images.unsplash.com/photo-1676638392418-80aad7c87b96?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80", - "https://images.unsplash.com/photo-1649639194967-2fec0b4ea7bc?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1675883086902-b453b3f8146e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80", - "https://images.unsplash.com/photo-1675887057159-40fca28fdc5d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1173&q=80", - "https://images.unsplash.com/photo-1675373980203-f84c5a672aa5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1675191475318-d2bf6bad1200?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80", - "https://images.unsplash.com/photo-1675456230532-2194d0c4bcc0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", - "https://images.unsplash.com/photo-1675371788315-60fa0ef48267?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80", - ] - - projects = Project.objects.all() - updated_projects = [] - for project in projects: - project.cover_image = project_cover_images[random.randint(0, 19)] - updated_projects.append(project) - - Project.objects.bulk_update(updated_projects, ["cover_image"], batch_size=100) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_user_view_property(): - try: - project_members = ProjectMember.objects.all() - updated_project_members = [] - for project_member in project_members: - project_member.default_props = { - "filters": {"type": None}, - "orderBy": "-created_at", - "collapsed": True, - "issueView": "list", - "filterIssue": None, - "groupByProperty": None, - "showEmptyGroups": True, - } - updated_project_members.append(project_member) - - ProjectMember.objects.bulk_update( - updated_project_members, ["default_props"], batch_size=100 - ) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_label_color(): - try: - labels = Label.objects.filter(color="") - updated_labels = [] - for label in labels: - label.color = f"#{random.randint(0, 0xFFFFFF+1):06X}" - updated_labels.append(label) - - Label.objects.bulk_update(updated_labels, ["color"], batch_size=100) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def create_slack_integration(): - try: - _ = Integration.objects.create(provider="slack", network=2, title="Slack") - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_integration_verified(): - try: - integrations = Integration.objects.all() - updated_integrations = [] - for integration in integrations: - integration.verified = True - updated_integrations.append(integration) - - Integration.objects.bulk_update( - updated_integrations, ["verified"], batch_size=10 - ) - print("Success") - except Exception as e: - print(e) - print("Failed") - - -def update_start_date(): - try: - issues = Issue.objects.filter(state__group__in=["started", "completed"]) - updated_issues = [] - for issue in issues: - issue.start_date = issue.created_at.date() - updated_issues.append(issue) - Issue.objects.bulk_update(updated_issues, ["start_date"], batch_size=500) - print("Success") - except Exception as e: - print(e) - print("Failed") diff --git a/apiserver/plane/tests/contract/app/__init__.py b/apiserver/plane/tests/contract/app/__init__.py deleted file mode 100644 index 0519ecba6..000000000 --- a/apiserver/plane/tests/contract/app/__init__.py +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apiserver/runtime.txt b/apiserver/runtime.txt deleted file mode 100644 index 4937ae149..000000000 --- a/apiserver/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.12.6 \ No newline at end of file diff --git a/app.json b/app.json deleted file mode 100644 index 6b1ab7528..000000000 --- a/app.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "Plane", - "description": "Plane helps you track your issues, epics, and product roadmaps.", - "repository": "http://github.com/makeplane/plane", - "logo": "https://avatars.githubusercontent.com/u/115727700?s=200&v=4", - "website": "https://plane.so/", - "success_url": "/", - "stack": "heroku-22", - "keywords": ["plane", "project management", "django", "next"], - "addons": ["heroku-postgresql:mini", "heroku-redis:mini"], - "buildpacks": [ - { - "url": "https://github.com/heroku/heroku-buildpack-python.git" - }, - { - "url": "https://github.com/heroku/heroku-buildpack-nodejs#v176" - } - ], - "env": { - "EMAIL_HOST": { - "description": "Email host to send emails from", - "value": "" - }, - "EMAIL_HOST_USER": { - "description": "Email host to send emails from", - "value": "" - }, - "EMAIL_HOST_PASSWORD": { - "description": "Email host to send emails from", - "value": "" - }, - "EMAIL_FROM": { - "description": "Email Sender", - "value": "" - }, - "EMAIL_PORT": { - "description": "The default Email PORT to use", - "value": "587" - }, - "AWS_REGION": { - "description": "AWS Region to use for S3", - "value": "false" - }, - "AWS_ACCESS_KEY_ID": { - "description": "AWS Access Key ID to use for S3", - "value": "" - }, - "AWS_SECRET_ACCESS_KEY": { - "description": "AWS Secret Access Key to use for S3", - "value": "" - }, - "AWS_S3_BUCKET_NAME": { - "description": "AWS Bucket Name to use for S3", - "value": "" - }, - "WEB_URL": { - "description": "Web URL for Plane this will be used for redirections in the emails", - "value": "" - }, - "GITHUB_CLIENT_SECRET": { - "description": "GitHub Client Secret", - "value": "" - }, - "NEXT_PUBLIC_API_BASE_URL": { - "description": "Next Public API Base URL", - "value": "" - }, - "SECRET_KEY": { - "description": "Django Secret Key", - "value": "" - } - } -} diff --git a/admin/.env.example b/apps/admin/.env.example similarity index 100% rename from admin/.env.example rename to apps/admin/.env.example diff --git a/admin/.eslintrc.js b/apps/admin/.eslintrc.js similarity index 100% rename from admin/.eslintrc.js rename to apps/admin/.eslintrc.js diff --git a/admin/.prettierignore b/apps/admin/.prettierignore similarity index 100% rename from admin/.prettierignore rename to apps/admin/.prettierignore diff --git a/admin/.prettierrc b/apps/admin/.prettierrc similarity index 100% rename from admin/.prettierrc rename to apps/admin/.prettierrc diff --git a/admin/Dockerfile.admin b/apps/admin/Dockerfile.admin similarity index 77% rename from admin/Dockerfile.admin rename to apps/admin/Dockerfile.admin index 8046bf329..01884206e 100644 --- a/admin/Dockerfile.admin +++ b/apps/admin/Dockerfile.admin @@ -1,4 +1,4 @@ -FROM node:20-alpine as base +FROM node:22-alpine AS base # ***************************************************************************** # STAGE 1: Build the project @@ -46,8 +46,8 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL -ENV NEXT_TELEMETRY_DISABLED 1 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 RUN yarn turbo run build --filter=admin @@ -57,12 +57,16 @@ RUN yarn turbo run build --filter=admin FROM base AS runner WORKDIR /app -COPY --from=installer /app/admin/next.config.js . -COPY --from=installer /app/admin/package.json . +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs +USER nextjs -COPY --from=installer /app/admin/.next/standalone ./ -COPY --from=installer /app/admin/.next/static ./admin/.next/static -COPY --from=installer /app/admin/public ./admin/public +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=installer /app/apps/admin/.next/standalone ./ +COPY --from=installer /app/apps/admin/.next/static ./apps/admin/.next/static +COPY --from=installer /app/apps/admin/public ./apps/admin/public ARG NEXT_PUBLIC_API_BASE_URL="" ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL @@ -82,7 +86,9 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL -ENV NEXT_TELEMETRY_DISABLED 1 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 -EXPOSE 3000 \ No newline at end of file +EXPOSE 3000 + +CMD ["node", "apps/admin/server.js"] \ No newline at end of file diff --git a/admin/Dockerfile.dev b/apps/admin/Dockerfile.dev similarity index 93% rename from admin/Dockerfile.dev rename to apps/admin/Dockerfile.dev index 3bdc71c16..edf82d227 100644 --- a/admin/Dockerfile.dev +++ b/apps/admin/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM node:20-alpine +FROM node:22-alpine RUN apk add --no-cache libc6-compat # Set working directory WORKDIR /app diff --git a/admin/app/ai/form.tsx b/apps/admin/app/(all)/(dashboard)/ai/form.tsx similarity index 99% rename from admin/app/ai/form.tsx rename to apps/admin/app/(all)/(dashboard)/ai/form.tsx index 47ab9480e..8b7d036ad 100644 --- a/admin/app/ai/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/ai/form.tsx @@ -5,7 +5,7 @@ import { Lightbulb } from "lucide-react"; import { IFormattedInstanceConfiguration, TInstanceAIConfigurationKeys } from "@plane/types"; import { Button, TOAST_TYPE, setToast } from "@plane/ui"; // components -import { ControllerInput, TControllerInputFormField } from "@/components/common"; +import { ControllerInput, TControllerInputFormField } from "@/components/common/controller-input"; // hooks import { useInstance } from "@/hooks/store"; diff --git a/admin/app/ai/layout.tsx b/apps/admin/app/(all)/(dashboard)/ai/layout.tsx similarity index 53% rename from admin/app/ai/layout.tsx rename to apps/admin/app/(all)/(dashboard)/ai/layout.tsx index d461a626a..42f379649 100644 --- a/admin/app/ai/layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/ai/layout.tsx @@ -1,11 +1,10 @@ import { ReactNode } from "react"; import { Metadata } from "next"; -import { AdminLayout } from "@/layouts/admin-layout"; export const metadata: Metadata = { - title: "Artificial Intelligence Settings - Plane Web", + title: "Artificial Intelligence Settings - God Mode", }; export default function AILayout({ children }: { children: ReactNode }) { - return {children}; + return <>{children}; } diff --git a/admin/app/ai/page.tsx b/apps/admin/app/(all)/(dashboard)/ai/page.tsx similarity index 100% rename from admin/app/ai/page.tsx rename to apps/admin/app/(all)/(dashboard)/ai/page.tsx diff --git a/admin/app/authentication/github/form.tsx b/apps/admin/app/(all)/(dashboard)/authentication/github/form.tsx similarity index 95% rename from admin/app/authentication/github/form.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/github/form.tsx index 0c6d81ae6..6e5f2a903 100644 --- a/admin/app/authentication/github/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/github/form.tsx @@ -10,14 +10,10 @@ import { IFormattedInstanceConfiguration, TInstanceGithubAuthenticationConfigura import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; import { cn } from "@plane/utils"; // components -import { - CodeBlock, - ConfirmDiscardModal, - ControllerInput, - CopyField, - TControllerInputFormField, - TCopyField, -} from "@/components/common"; +import { CodeBlock } from "@/components/common/code-block"; +import { ConfirmDiscardModal } from "@/components/common/confirm-discard-modal"; +import { ControllerInput, TControllerInputFormField } from "@/components/common/controller-input"; +import { CopyField, TCopyField } from "@/components/common/copy-field"; // hooks import { useInstance } from "@/hooks/store"; diff --git a/apps/admin/app/(all)/(dashboard)/authentication/github/layout.tsx b/apps/admin/app/(all)/(dashboard)/authentication/github/layout.tsx new file mode 100644 index 000000000..373f9340a --- /dev/null +++ b/apps/admin/app/(all)/(dashboard)/authentication/github/layout.tsx @@ -0,0 +1,10 @@ +import { ReactNode } from "react"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "GitHub Authentication - God Mode", +}; + +export default function GitHubAuthenticationLayout({ children }: { children: ReactNode }) { + return <>{children}; +} diff --git a/admin/app/authentication/github/page.tsx b/apps/admin/app/(all)/(dashboard)/authentication/github/page.tsx similarity index 90% rename from admin/app/authentication/github/page.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/github/page.tsx index 986a5ebd2..75cb84e4a 100644 --- a/admin/app/authentication/github/page.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/github/page.tsx @@ -9,8 +9,7 @@ import useSWR from "swr"; import { Loader, ToggleSwitch, setPromiseToast } from "@plane/ui"; import { resolveGeneralTheme } from "@plane/utils"; // components -import { AuthenticationMethodCard } from "@/components/authentication"; -import { PageHeader } from "@/components/common"; +import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card"; // hooks import { useInstance } from "@/hooks/store"; // icons @@ -61,9 +60,11 @@ const InstanceGithubAuthenticationPage = observer(() => { setIsSubmitting(false); }); }; + + const isGithubEnabled = enableGithubConfig === "1"; + return ( <> -
{ } config={ { - Boolean(parseInt(enableGithubConfig)) === true - ? updateConfig("IS_GITHUB_ENABLED", "0") - : updateConfig("IS_GITHUB_ENABLED", "1"); + updateConfig("IS_GITHUB_ENABLED", isGithubEnabled ? "0" : "1"); }} size="sm" disabled={isSubmitting || !formattedConfig} diff --git a/admin/app/authentication/gitlab/form.tsx b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/form.tsx similarity index 95% rename from admin/app/authentication/gitlab/form.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/gitlab/form.tsx index f64158744..888b2533c 100644 --- a/admin/app/authentication/gitlab/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/form.tsx @@ -8,14 +8,10 @@ import { IFormattedInstanceConfiguration, TInstanceGitlabAuthenticationConfigura import { Button, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; import { cn } from "@plane/utils"; // components -import { - CodeBlock, - ConfirmDiscardModal, - ControllerInput, - CopyField, - TControllerInputFormField, - TCopyField, -} from "@/components/common"; +import { CodeBlock } from "@/components/common/code-block"; +import { ConfirmDiscardModal } from "@/components/common/confirm-discard-modal"; +import { ControllerInput, TControllerInputFormField } from "@/components/common/controller-input"; +import { CopyField, TCopyField } from "@/components/common/copy-field"; // hooks import { useInstance } from "@/hooks/store"; diff --git a/apps/admin/app/(all)/(dashboard)/authentication/gitlab/layout.tsx b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/layout.tsx new file mode 100644 index 000000000..fc89e9752 --- /dev/null +++ b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/layout.tsx @@ -0,0 +1,10 @@ +import { ReactNode } from "react"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "GitLab Authentication - God Mode", +}; + +export default function GitlabAuthenticationLayout({ children }: { children: ReactNode }) { + return <>{children}; +} diff --git a/admin/app/authentication/gitlab/page.tsx b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/page.tsx similarity index 96% rename from admin/app/authentication/gitlab/page.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/gitlab/page.tsx index 7a4d8248e..cdcfcd61b 100644 --- a/admin/app/authentication/gitlab/page.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/gitlab/page.tsx @@ -6,8 +6,7 @@ import Image from "next/image"; import useSWR from "swr"; import { Loader, ToggleSwitch, setPromiseToast } from "@plane/ui"; // components -import { AuthenticationMethodCard } from "@/components/authentication"; -import { PageHeader } from "@/components/common"; +import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card"; // hooks import { useInstance } from "@/hooks/store"; // icons @@ -57,7 +56,6 @@ const InstanceGitlabAuthenticationPage = observer(() => { }; return ( <> -
{children}; +} diff --git a/admin/app/authentication/google/page.tsx b/apps/admin/app/(all)/(dashboard)/authentication/google/page.tsx similarity index 96% rename from admin/app/authentication/google/page.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/google/page.tsx index 992c7a8a7..6ac4ea09b 100644 --- a/admin/app/authentication/google/page.tsx +++ b/apps/admin/app/(all)/(dashboard)/authentication/google/page.tsx @@ -6,8 +6,7 @@ import Image from "next/image"; import useSWR from "swr"; import { Loader, ToggleSwitch, setPromiseToast } from "@plane/ui"; // components -import { AuthenticationMethodCard } from "@/components/authentication"; -import { PageHeader } from "@/components/common"; +import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card"; // hooks import { useInstance } from "@/hooks/store"; // icons @@ -57,7 +56,6 @@ const InstanceGoogleAuthenticationPage = observer(() => { }; return ( <> -
{children}; + return <>{children}; } diff --git a/admin/app/authentication/page.tsx b/apps/admin/app/(all)/(dashboard)/authentication/page.tsx similarity index 100% rename from admin/app/authentication/page.tsx rename to apps/admin/app/(all)/(dashboard)/authentication/page.tsx diff --git a/admin/app/email/email-config-form.tsx b/apps/admin/app/(all)/(dashboard)/email/email-config-form.tsx similarity index 97% rename from admin/app/email/email-config-form.tsx rename to apps/admin/app/(all)/(dashboard)/email/email-config-form.tsx index 73a1af174..2bfcc4287 100644 --- a/admin/app/email/email-config-form.tsx +++ b/apps/admin/app/(all)/(dashboard)/email/email-config-form.tsx @@ -7,7 +7,7 @@ import { IFormattedInstanceConfiguration, TInstanceEmailConfigurationKeys } from // ui import { Button, CustomSelect, TOAST_TYPE, setToast } from "@plane/ui"; // components -import { ControllerInput, TControllerInputFormField } from "@/components/common"; +import { ControllerInput, TControllerInputFormField } from "@/components/common/controller-input"; // hooks import { useInstance } from "@/hooks/store"; // local components @@ -49,9 +49,9 @@ export const InstanceEmailForm: FC = (props) => { EMAIL_USE_TLS: config["EMAIL_USE_TLS"], EMAIL_USE_SSL: config["EMAIL_USE_SSL"], EMAIL_FROM: config["EMAIL_FROM"], + ENABLE_SMTP: config["ENABLE_SMTP"], }, }); - const emailFormFields: TControllerInputFormField[] = [ { key: "EMAIL_HOST", @@ -101,7 +101,7 @@ export const InstanceEmailForm: FC = (props) => { ]; const onSubmit = async (formData: EmailFormValues) => { - const payload: Partial = { ...formData }; + const payload: Partial = { ...formData, ENABLE_SMTP: "1" }; await updateInstanceConfigurations(payload) .then(() => diff --git a/admin/app/email/layout.tsx b/apps/admin/app/(all)/(dashboard)/email/layout.tsx similarity index 62% rename from admin/app/email/layout.tsx rename to apps/admin/app/(all)/(dashboard)/email/layout.tsx index 2084af1ea..cb3212951 100644 --- a/admin/app/email/layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/email/layout.tsx @@ -1,15 +1,14 @@ import { ReactNode } from "react"; import { Metadata } from "next"; -import { AdminLayout } from "@/layouts/admin-layout"; interface EmailLayoutProps { children: ReactNode; } export const metadata: Metadata = { - title: "Email Settings - Plane Web", + title: "Email Settings - God Mode", }; export default function EmailLayout({ children }: EmailLayoutProps) { - return {children}; + return <>{children}; } diff --git a/apps/admin/app/(all)/(dashboard)/email/page.tsx b/apps/admin/app/(all)/(dashboard)/email/page.tsx new file mode 100644 index 000000000..445ff2ec7 --- /dev/null +++ b/apps/admin/app/(all)/(dashboard)/email/page.tsx @@ -0,0 +1,93 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { observer } from "mobx-react"; +import useSWR from "swr"; +import { Loader, setToast, TOAST_TYPE, ToggleSwitch } from "@plane/ui"; +// hooks +import { useInstance } from "@/hooks/store"; +// components +import { InstanceEmailForm } from "./email-config-form"; + +const InstanceEmailPage = observer(() => { + // store + const { fetchInstanceConfigurations, formattedConfig, disableEmail } = useInstance(); + + const { isLoading } = useSWR("INSTANCE_CONFIGURATIONS", () => fetchInstanceConfigurations()); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [isSMTPEnabled, setIsSMTPEnabled] = useState(false); + + const handleToggle = async () => { + if (isSMTPEnabled) { + setIsSubmitting(true); + try { + await disableEmail(); + setIsSMTPEnabled(false); + setToast({ + title: "Email feature disabled", + message: "Email feature has been disabled", + type: TOAST_TYPE.SUCCESS, + }); + } catch (error) { + setToast({ + title: "Error disabling email", + message: "Failed to disable email feature. Please try again.", + type: TOAST_TYPE.ERROR, + }); + } finally { + setIsSubmitting(false); + } + return; + } + setIsSMTPEnabled(true); + }; + useEffect(() => { + if (formattedConfig) { + setIsSMTPEnabled(formattedConfig.ENABLE_SMTP === "1"); + } + }, [formattedConfig]); + + return ( + <> +
+
+
+
Secure emails from your own instance
+
+ Plane can send useful emails to you and your users from your own instance without talking to the Internet. +
+ Set it up below and please test your settings before you save them.  + Misconfigs can lead to email bounces and errors. +
+
+
+ {isLoading ? ( + + + + ) : ( + + )} +
+ {isSMTPEnabled && !isLoading && ( +
+ {formattedConfig ? ( + + ) : ( + + + + + + + + )} +
+ )} +
+ + ); +}); + +export default InstanceEmailPage; diff --git a/admin/app/email/test-email-modal.tsx b/apps/admin/app/(all)/(dashboard)/email/test-email-modal.tsx similarity index 100% rename from admin/app/email/test-email-modal.tsx rename to apps/admin/app/(all)/(dashboard)/email/test-email-modal.tsx diff --git a/admin/app/general/form.tsx b/apps/admin/app/(all)/(dashboard)/general/form.tsx similarity index 98% rename from admin/app/general/form.tsx rename to apps/admin/app/(all)/(dashboard)/general/form.tsx index 4fbd70535..0700c4d0d 100644 --- a/admin/app/general/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/general/form.tsx @@ -8,7 +8,7 @@ import { IInstance, IInstanceAdmin } from "@plane/types"; // ui import { Button, Input, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui"; // components -import { ControllerInput } from "@/components/common"; +import { ControllerInput } from "@/components/common/controller-input"; import { useInstance } from "@/hooks/store"; import { IntercomConfig } from "./intercom"; // hooks diff --git a/admin/app/general/intercom.tsx b/apps/admin/app/(all)/(dashboard)/general/intercom.tsx similarity index 100% rename from admin/app/general/intercom.tsx rename to apps/admin/app/(all)/(dashboard)/general/intercom.tsx diff --git a/admin/app/general/layout.tsx b/apps/admin/app/(all)/(dashboard)/general/layout.tsx similarity index 57% rename from admin/app/general/layout.tsx rename to apps/admin/app/(all)/(dashboard)/general/layout.tsx index 374257daa..af3000510 100644 --- a/admin/app/general/layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/general/layout.tsx @@ -1,11 +1,10 @@ import { ReactNode } from "react"; import { Metadata } from "next"; -import { AdminLayout } from "@/layouts/admin-layout"; export const metadata: Metadata = { - title: "General Settings - Plane Web", + title: "General Settings - God Mode", }; export default function GeneralLayout({ children }: { children: ReactNode }) { - return {children}; + return <>{children}; } diff --git a/admin/app/general/page.tsx b/apps/admin/app/(all)/(dashboard)/general/page.tsx similarity index 100% rename from admin/app/general/page.tsx rename to apps/admin/app/(all)/(dashboard)/general/page.tsx diff --git a/admin/core/components/auth-header.tsx b/apps/admin/app/(all)/(dashboard)/header.tsx similarity index 71% rename from admin/core/components/auth-header.tsx rename to apps/admin/app/(all)/(dashboard)/header.tsx index b97dd7c9e..af7161c2d 100644 --- a/admin/core/components/auth-header.tsx +++ b/apps/admin/app/(all)/(dashboard)/header.tsx @@ -3,16 +3,27 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; -// mobx -// ui -import { Settings } from "lucide-react"; +import { Menu, Settings } from "lucide-react"; // icons import { Breadcrumbs } from "@plane/ui"; // components -import { SidebarHamburgerToggle } from "@/components/admin-sidebar"; -import { BreadcrumbLink } from "@/components/common"; +import { BreadcrumbLink } from "@/components/common/breadcrumb-link"; +// hooks +import { useTheme } from "@/hooks/store"; -export const InstanceHeader: FC = observer(() => { +export const HamburgerToggle: FC = observer(() => { + const { isSidebarCollapsed, toggleSidebar } = useTheme(); + return ( +
toggleSidebar(!isSidebarCollapsed)} + > + +
+ ); +}); + +export const AdminHeader: FC = observer(() => { const pathName = usePathname(); const getHeaderTitle = (pathName: string) => { @@ -61,9 +72,9 @@ export const InstanceHeader: FC = observer(() => { const breadcrumbItems = generateBreadcrumbItems(pathName); return ( -
+
- + {breadcrumbItems.length >= 0 && (
diff --git a/admin/app/image/form.tsx b/apps/admin/app/(all)/(dashboard)/image/form.tsx similarity index 97% rename from admin/app/image/form.tsx rename to apps/admin/app/(all)/(dashboard)/image/form.tsx index 61d2875ed..be77983ec 100644 --- a/admin/app/image/form.tsx +++ b/apps/admin/app/(all)/(dashboard)/image/form.tsx @@ -4,7 +4,7 @@ import { useForm } from "react-hook-form"; import { IFormattedInstanceConfiguration, TInstanceImageConfigurationKeys } from "@plane/types"; import { Button, TOAST_TYPE, setToast } from "@plane/ui"; // components -import { ControllerInput } from "@/components/common"; +import { ControllerInput } from "@/components/common/controller-input"; // hooks import { useInstance } from "@/hooks/store"; diff --git a/admin/app/image/layout.tsx b/apps/admin/app/(all)/(dashboard)/image/layout.tsx similarity index 62% rename from admin/app/image/layout.tsx rename to apps/admin/app/(all)/(dashboard)/image/layout.tsx index 32233e078..7ec0ff54b 100644 --- a/admin/app/image/layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/image/layout.tsx @@ -1,15 +1,14 @@ import { ReactNode } from "react"; import { Metadata } from "next"; -import { AdminLayout } from "@/layouts/admin-layout"; interface ImageLayoutProps { children: ReactNode; } export const metadata: Metadata = { - title: "Images Settings - Plane Web", + title: "Images Settings - God Mode", }; export default function ImageLayout({ children }: ImageLayoutProps) { - return {children}; + return <>{children}; } diff --git a/admin/app/image/page.tsx b/apps/admin/app/(all)/(dashboard)/image/page.tsx similarity index 100% rename from admin/app/image/page.tsx rename to apps/admin/app/(all)/(dashboard)/image/page.tsx diff --git a/admin/core/layouts/admin-layout.tsx b/apps/admin/app/(all)/(dashboard)/layout.tsx similarity index 52% rename from admin/core/layouts/admin-layout.tsx rename to apps/admin/app/(all)/(dashboard)/layout.tsx index 88f71aa3c..179623783 100644 --- a/admin/core/layouts/admin-layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/layout.tsx @@ -1,20 +1,22 @@ "use client"; + import { FC, ReactNode, useEffect } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/navigation"; // components -import { InstanceSidebar } from "@/components/admin-sidebar"; -import { InstanceHeader } from "@/components/auth-header"; -import { LogoSpinner } from "@/components/common"; +import { LogoSpinner } from "@/components/common/logo-spinner"; import { NewUserPopup } from "@/components/new-user-popup"; // hooks import { useUser } from "@/hooks/store"; +// local components +import { AdminHeader } from "./header"; +import { AdminSidebar } from "./sidebar"; type TAdminLayout = { children: ReactNode; }; -export const AdminLayout: FC = observer((props) => { +const AdminLayout: FC = (props) => { const { children } = props; // router const router = useRouter(); @@ -35,14 +37,20 @@ export const AdminLayout: FC = observer((props) => { ); } - return ( -
- -
- -
{children}
-
- -
- ); -}); + if (isUserLoggedIn) { + return ( +
+ +
+ +
{children}
+
+ +
+ ); + } + + return <>; +}; + +export default observer(AdminLayout); diff --git a/admin/core/components/admin-sidebar/sidebar-dropdown.tsx b/apps/admin/app/(all)/(dashboard)/sidebar-dropdown.tsx similarity index 96% rename from admin/core/components/admin-sidebar/sidebar-dropdown.tsx rename to apps/admin/app/(all)/(dashboard)/sidebar-dropdown.tsx index 0cde7f551..5554947be 100644 --- a/admin/core/components/admin-sidebar/sidebar-dropdown.tsx +++ b/apps/admin/app/(all)/(dashboard)/sidebar-dropdown.tsx @@ -16,7 +16,7 @@ import { useTheme, useUser } from "@/hooks/store"; // service initialization const authService = new AuthService(); -export const SidebarDropdown = observer(() => { +export const AdminSidebarDropdown = observer(() => { // store hooks const { isSidebarCollapsed } = useTheme(); const { currentUser, signOut } = useUser(); @@ -77,7 +77,7 @@ export const SidebarDropdown = observer(() => { }, [csrfToken]); return ( -
+
{ +export const AdminSidebarHelpSection: FC = observer(() => { // states const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); // store diff --git a/admin/core/components/admin-sidebar/sidebar-menu.tsx b/apps/admin/app/(all)/(dashboard)/sidebar-menu.tsx similarity index 98% rename from admin/core/components/admin-sidebar/sidebar-menu.tsx rename to apps/admin/app/(all)/(dashboard)/sidebar-menu.tsx index 618551ae6..e536a5145 100644 --- a/admin/core/components/admin-sidebar/sidebar-menu.tsx +++ b/apps/admin/app/(all)/(dashboard)/sidebar-menu.tsx @@ -49,7 +49,7 @@ const INSTANCE_ADMIN_LINKS = [ }, ]; -export const SidebarMenu = observer(() => { +export const AdminSidebarMenu = observer(() => { // store hooks const { isSidebarCollapsed, toggleSidebar } = useTheme(); // router diff --git a/admin/core/components/admin-sidebar/root.tsx b/apps/admin/app/(all)/(dashboard)/sidebar.tsx similarity index 81% rename from admin/core/components/admin-sidebar/root.tsx rename to apps/admin/app/(all)/(dashboard)/sidebar.tsx index 05dde0d8a..09dab86ee 100644 --- a/admin/core/components/admin-sidebar/root.tsx +++ b/apps/admin/app/(all)/(dashboard)/sidebar.tsx @@ -4,12 +4,14 @@ import { FC, useEffect, useRef } from "react"; import { observer } from "mobx-react"; // plane helpers import { useOutsideClickDetector } from "@plane/hooks"; -// components -import { HelpSection, SidebarMenu, SidebarDropdown } from "@/components/admin-sidebar"; // hooks import { useTheme } from "@/hooks/store"; +// components +import { AdminSidebarDropdown } from "./sidebar-dropdown"; +import { AdminSidebarHelpSection } from "./sidebar-help-section"; +import { AdminSidebarMenu } from "./sidebar-menu"; -export const InstanceSidebar: FC = observer(() => { +export const AdminSidebar: FC = observer(() => { // store const { isSidebarCollapsed, toggleSidebar } = useTheme(); @@ -47,9 +49,9 @@ export const InstanceSidebar: FC = observer(() => { `} >
- - - + + +
); diff --git a/admin/app/workspace/create/form.tsx b/apps/admin/app/(all)/(dashboard)/workspace/create/form.tsx similarity index 100% rename from admin/app/workspace/create/form.tsx rename to apps/admin/app/(all)/(dashboard)/workspace/create/form.tsx diff --git a/admin/app/workspace/create/page.tsx b/apps/admin/app/(all)/(dashboard)/workspace/create/page.tsx similarity index 100% rename from admin/app/workspace/create/page.tsx rename to apps/admin/app/(all)/(dashboard)/workspace/create/page.tsx diff --git a/admin/app/workspace/layout.tsx b/apps/admin/app/(all)/(dashboard)/workspace/layout.tsx similarity index 56% rename from admin/app/workspace/layout.tsx rename to apps/admin/app/(all)/(dashboard)/workspace/layout.tsx index 9f2a63c67..78b0f3c40 100644 --- a/admin/app/workspace/layout.tsx +++ b/apps/admin/app/(all)/(dashboard)/workspace/layout.tsx @@ -1,12 +1,10 @@ import { ReactNode } from "react"; import { Metadata } from "next"; -// layouts -import { AdminLayout } from "@/layouts/admin-layout"; export const metadata: Metadata = { - title: "Workspace Management - Plane Web", + title: "Workspace Management - God Mode", }; export default function WorkspaceManagementLayout({ children }: { children: ReactNode }) { - return {children}; + return <>{children}; } diff --git a/admin/app/workspace/page.tsx b/apps/admin/app/(all)/(dashboard)/workspace/page.tsx similarity index 98% rename from admin/app/workspace/page.tsx rename to apps/admin/app/(all)/(dashboard)/workspace/page.tsx index 3ca34b69e..b8f79db04 100644 --- a/admin/app/workspace/page.tsx +++ b/apps/admin/app/(all)/(dashboard)/workspace/page.tsx @@ -10,7 +10,7 @@ import { TInstanceConfigurationKeys } from "@plane/types"; import { Button, getButtonStyling, Loader, setPromiseToast, ToggleSwitch } from "@plane/ui"; import { cn } from "@plane/utils"; // components -import { WorkspaceListItem } from "@/components/workspace"; +import { WorkspaceListItem } from "@/components/workspace/list-item"; // hooks import { useInstance, useWorkspace } from "@/hooks/store"; diff --git a/admin/core/components/authentication/auth-banner.tsx b/apps/admin/app/(all)/(home)/auth-banner.tsx similarity index 100% rename from admin/core/components/authentication/auth-banner.tsx rename to apps/admin/app/(all)/(home)/auth-banner.tsx diff --git a/admin/core/lib/auth-helpers.tsx b/apps/admin/app/(all)/(home)/auth-helpers.tsx similarity index 93% rename from admin/core/lib/auth-helpers.tsx rename to apps/admin/app/(all)/(home)/auth-helpers.tsx index f9882b5e5..7613548b9 100644 --- a/admin/core/lib/auth-helpers.tsx +++ b/apps/admin/app/(all)/(home)/auth-helpers.tsx @@ -7,13 +7,11 @@ import { SUPPORT_EMAIL, EAdminAuthErrorCodes, TAdminAuthErrorInfo } from "@plane import { TGetBaseAuthenticationModeProps, TInstanceAuthenticationModes } from "@plane/types"; import { resolveGeneralTheme } from "@plane/utils"; // components -import { - EmailCodesConfiguration, - GithubConfiguration, - GitlabConfiguration, - GoogleConfiguration, - PasswordLoginConfiguration, -} from "@/components/authentication"; +import { EmailCodesConfiguration } from "@/components/authentication/email-config-switch"; +import { GithubConfiguration } from "@/components/authentication/github-config"; +import { GitlabConfiguration } from "@/components/authentication/gitlab-config"; +import { GoogleConfiguration } from "@/components/authentication/google-config"; +import { PasswordLoginConfiguration } from "@/components/authentication/password-config-switch"; // images import githubLightModeImage from "@/public/logos/github-black.png"; import githubDarkModeImage from "@/public/logos/github-white.png"; diff --git a/admin/core/layouts/default-layout.tsx b/apps/admin/app/(all)/(home)/layout.tsx similarity index 65% rename from admin/core/layouts/default-layout.tsx rename to apps/admin/app/(all)/(home)/layout.tsx index 1be40ea12..19cab04cb 100644 --- a/admin/core/layouts/default-layout.tsx +++ b/apps/admin/app/(all)/(home)/layout.tsx @@ -1,26 +1,18 @@ "use client"; -import { FC, ReactNode } from "react"; import Image from "next/image"; import Link from "next/link"; import { useTheme } from "next-themes"; -// logo/ images +// logo assets import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg"; import PlaneBackgroundPattern from "public/auth/background-pattern.svg"; import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png"; import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png"; -type TDefaultLayout = { - children: ReactNode; - withoutBackground?: boolean; -}; - -export const DefaultLayout: FC = (props) => { - const { children, withoutBackground = false } = props; - // hooks +export default function RootLayout({ children }: { children: React.ReactNode }) { const { resolvedTheme } = useTheme(); - const patternBackground = resolvedTheme === "dark" ? PlaneBackgroundPatternDark : PlaneBackgroundPattern; + const patternBackground = resolvedTheme === "light" ? PlaneBackgroundPattern : PlaneBackgroundPatternDark; const logo = resolvedTheme === "light" ? BlackHorizontalLogo : WhiteHorizontalLogo; return ( @@ -33,13 +25,11 @@ export const DefaultLayout: FC = (props) => {
- {!withoutBackground && ( -
- Plane background pattern -
- )} +
+ Plane background pattern +
{children}
); -}; +} diff --git a/apps/admin/app/(all)/(home)/page.tsx b/apps/admin/app/(all)/(home)/page.tsx new file mode 100644 index 000000000..80ea40ee6 --- /dev/null +++ b/apps/admin/app/(all)/(home)/page.tsx @@ -0,0 +1,62 @@ +"use client"; + +import { observer } from "mobx-react"; +// components +import { InstanceFailureView } from "@/components/instance/failure"; +import { InstanceLoading } from "@/components/instance/loading"; +import { InstanceSetupForm } from "@/components/instance/setup-form"; +// hooks +import { useInstance } from "@/hooks/store"; +// components +import { InstanceSignInForm } from "./sign-in-form"; + +const HomePage = () => { + // store hooks + const { instance, error } = useInstance(); + + // if instance is not fetched, show loading + if (!instance && !error) { + return ( +
+ +
+ ); + } + + // if instance fetch fails, show failure view + if (error) { + return ( +
+ +
+ ); + } + + // if instance is fetched and setup is not done, show setup form + if (instance && !instance?.is_setup_done) { + return ( +
+ +
+ ); + } + + // if instance is fetched and setup is done, show sign in form + return ( +
+
+
+

+ Manage your Plane instance +

+

+ Configure instance-wide settings to secure your instance +

+
+ +
+
+ ); +}; + +export default observer(HomePage); diff --git a/apps/admin/app/(all)/(home)/sign-in-form.tsx b/apps/admin/app/(all)/(home)/sign-in-form.tsx new file mode 100644 index 000000000..12b250a93 --- /dev/null +++ b/apps/admin/app/(all)/(home)/sign-in-form.tsx @@ -0,0 +1,178 @@ +"use client"; + +import { FC, useEffect, useMemo, useState } from "react"; +import { useSearchParams } from "next/navigation"; +import { Eye, EyeOff } from "lucide-react"; +// plane internal packages +import { API_BASE_URL, EAdminAuthErrorCodes, TAdminAuthErrorInfo } from "@plane/constants"; +import { AuthService } from "@plane/services"; +import { Button, Input, Spinner } from "@plane/ui"; +// components +import { Banner } from "@/components/common/banner"; +// local components +import { AuthBanner } from "./auth-banner"; +import { authErrorHandler } from "./auth-helpers"; + +// service initialization +const authService = new AuthService(); + +// error codes +enum EErrorCodes { + INSTANCE_NOT_CONFIGURED = "INSTANCE_NOT_CONFIGURED", + REQUIRED_EMAIL_PASSWORD = "REQUIRED_EMAIL_PASSWORD", + INVALID_EMAIL = "INVALID_EMAIL", + USER_DOES_NOT_EXIST = "USER_DOES_NOT_EXIST", + AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED", +} + +type TError = { + type: EErrorCodes | undefined; + message: string | undefined; +}; + +// form data +type TFormData = { + email: string; + password: string; +}; + +const defaultFromData: TFormData = { + email: "", + password: "", +}; + +export const InstanceSignInForm: FC = () => { + // search params + const searchParams = useSearchParams(); + const emailParam = searchParams.get("email") || undefined; + const errorCode = searchParams.get("error_code") || undefined; + const errorMessage = searchParams.get("error_message") || undefined; + // state + const [showPassword, setShowPassword] = useState(false); + const [csrfToken, setCsrfToken] = useState(undefined); + const [formData, setFormData] = useState(defaultFromData); + const [isSubmitting, setIsSubmitting] = useState(false); + const [errorInfo, setErrorInfo] = useState(undefined); + + const handleFormChange = (key: keyof TFormData, value: string | boolean) => + setFormData((prev) => ({ ...prev, [key]: value })); + + useEffect(() => { + if (csrfToken === undefined) + authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); + }, [csrfToken]); + + useEffect(() => { + if (emailParam) setFormData((prev) => ({ ...prev, email: emailParam })); + }, [emailParam]); + + // derived values + const errorData: TError = useMemo(() => { + if (errorCode && errorMessage) { + switch (errorCode) { + case EErrorCodes.INSTANCE_NOT_CONFIGURED: + return { type: EErrorCodes.INSTANCE_NOT_CONFIGURED, message: errorMessage }; + case EErrorCodes.REQUIRED_EMAIL_PASSWORD: + return { type: EErrorCodes.REQUIRED_EMAIL_PASSWORD, message: errorMessage }; + case EErrorCodes.INVALID_EMAIL: + return { type: EErrorCodes.INVALID_EMAIL, message: errorMessage }; + case EErrorCodes.USER_DOES_NOT_EXIST: + return { type: EErrorCodes.USER_DOES_NOT_EXIST, message: errorMessage }; + case EErrorCodes.AUTHENTICATION_FAILED: + return { type: EErrorCodes.AUTHENTICATION_FAILED, message: errorMessage }; + default: + return { type: undefined, message: undefined }; + } + } else return { type: undefined, message: undefined }; + }, [errorCode, errorMessage]); + + const isButtonDisabled = useMemo( + () => (!isSubmitting && formData.email && formData.password ? false : true), + [formData.email, formData.password, isSubmitting] + ); + + useEffect(() => { + if (errorCode) { + const errorDetail = authErrorHandler(errorCode?.toString() as EAdminAuthErrorCodes); + if (errorDetail) { + setErrorInfo(errorDetail); + } + } + }, [errorCode]); + + return ( +
setIsSubmitting(true)} + onError={() => setIsSubmitting(false)} + > + {errorData.type && errorData?.message ? ( + + ) : ( + <>{errorInfo && setErrorInfo(value)} />} + )} + + +
+ + handleFormChange("email", e.target.value)} + autoComplete="on" + autoFocus + /> +
+ +
+ +
+ handleFormChange("password", e.target.value)} + autoComplete="on" + /> + {showPassword ? ( + + ) : ( + + )} +
+
+
+ +
+ + ); +}; diff --git a/apps/admin/app/(all)/instance.provider.tsx b/apps/admin/app/(all)/instance.provider.tsx new file mode 100644 index 000000000..ac8fa74e8 --- /dev/null +++ b/apps/admin/app/(all)/instance.provider.tsx @@ -0,0 +1,23 @@ +import { FC, ReactNode } from "react"; +import { observer } from "mobx-react"; +import useSWR from "swr"; +// hooks +import { useInstance } from "@/hooks/store"; + +type InstanceProviderProps = { + children: ReactNode; +}; + +export const InstanceProvider: FC = observer((props) => { + const { children } = props; + // store hooks + const { fetchInstanceInfo } = useInstance(); + // fetching instance details + useSWR("INSTANCE_DETAILS", () => fetchInstanceInfo(), { + revalidateOnFocus: false, + revalidateIfStale: false, + errorRetryCount: 0, + }); + + return <>{children}; +}); diff --git a/apps/admin/app/(all)/layout.tsx b/apps/admin/app/(all)/layout.tsx new file mode 100644 index 000000000..ddfba732a --- /dev/null +++ b/apps/admin/app/(all)/layout.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { ThemeProvider } from "next-themes"; +import { SWRConfig } from "swr"; +// providers +import { InstanceProvider } from "./instance.provider"; +import { StoreProvider } from "./store.provider"; +import { ToastWithTheme } from "./toast"; +import { UserProvider } from "./user.provider"; + +const DEFAULT_SWR_CONFIG = { + refreshWhenHidden: false, + revalidateIfStale: false, + revalidateOnFocus: false, + revalidateOnMount: true, + refreshInterval: 600000, + errorRetryCount: 3, +}; + +export default function InstanceLayout({ children }: { children: React.ReactNode }) { + return ( + + + + + + {children} + + + + + ); +} diff --git a/admin/core/lib/store-provider.tsx b/apps/admin/app/(all)/store.provider.tsx similarity index 100% rename from admin/core/lib/store-provider.tsx rename to apps/admin/app/(all)/store.provider.tsx diff --git a/apps/admin/app/(all)/toast.tsx b/apps/admin/app/(all)/toast.tsx new file mode 100644 index 000000000..7d7938a9b --- /dev/null +++ b/apps/admin/app/(all)/toast.tsx @@ -0,0 +1,10 @@ +"use client"; + +import { useTheme } from "next-themes"; +import { Toast } from "@plane/ui"; +import { resolveGeneralTheme } from "@plane/utils"; + +export const ToastWithTheme = () => { + const { resolvedTheme } = useTheme(); + return ; +}; diff --git a/admin/core/lib/user-provider.tsx b/apps/admin/app/(all)/user.provider.tsx similarity index 99% rename from admin/core/lib/user-provider.tsx rename to apps/admin/app/(all)/user.provider.tsx index 17d702627..3a50823dc 100644 --- a/admin/core/lib/user-provider.tsx +++ b/apps/admin/app/(all)/user.provider.tsx @@ -19,6 +19,7 @@ export const UserProvider: FC = observer(({ children }) => { useSWR("CURRENT_USER", () => fetchCurrentUser(), { shouldRetryOnError: false, }); + useSWR("INSTANCE_ADMINS", () => fetchInstanceAdmins()); useEffect(() => { diff --git a/admin/app/error.tsx b/apps/admin/app/error.tsx similarity index 100% rename from admin/app/error.tsx rename to apps/admin/app/error.tsx diff --git a/apps/admin/app/layout.tsx b/apps/admin/app/layout.tsx new file mode 100644 index 000000000..e73572369 --- /dev/null +++ b/apps/admin/app/layout.tsx @@ -0,0 +1,39 @@ +import { ReactNode } from "react"; +import { Metadata } from "next"; +// plane imports +import { ADMIN_BASE_PATH } from "@plane/constants"; +// styles +import "@/styles/globals.css"; + +export const metadata: Metadata = { + title: "Plane | Simple, extensible, open-source project management tool.", + description: + "Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.", + openGraph: { + title: "Plane | Simple, extensible, open-source project management tool.", + description: + "Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.", + url: "https://plane.so/", + }, + keywords: + "software development, customer feedback, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration", + twitter: { + site: "@planepowers", + }, +}; + +export default function RootLayout({ children }: { children: ReactNode }) { + const ASSET_PREFIX = ADMIN_BASE_PATH; + return ( + + + + + + + + + {children} + + ); +} diff --git a/apps/admin/ce/components/authentication/authentication-modes.tsx b/apps/admin/ce/components/authentication/authentication-modes.tsx new file mode 100644 index 000000000..c90016702 --- /dev/null +++ b/apps/admin/ce/components/authentication/authentication-modes.tsx @@ -0,0 +1,121 @@ +import { observer } from "mobx-react"; +import Image from "next/image"; +import { useTheme } from "next-themes"; +import { KeyRound, Mails } from "lucide-react"; +// types +import { + TGetBaseAuthenticationModeProps, + TInstanceAuthenticationMethodKeys, + TInstanceAuthenticationModes, +} from "@plane/types"; +import { resolveGeneralTheme } from "@plane/utils"; +// components +import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card"; +import { EmailCodesConfiguration } from "@/components/authentication/email-config-switch"; +import { GithubConfiguration } from "@/components/authentication/github-config"; +import { GitlabConfiguration } from "@/components/authentication/gitlab-config"; +import { GoogleConfiguration } from "@/components/authentication/google-config"; +import { PasswordLoginConfiguration } from "@/components/authentication/password-config-switch"; +// plane admin components +import { UpgradeButton } from "@/plane-admin/components/common"; +// assets +import githubLightModeImage from "@/public/logos/github-black.png"; +import githubDarkModeImage from "@/public/logos/github-white.png"; +import GitlabLogo from "@/public/logos/gitlab-logo.svg"; +import GoogleLogo from "@/public/logos/google-logo.svg"; +import OIDCLogo from "@/public/logos/oidc-logo.svg"; +import SAMLLogo from "@/public/logos/saml-logo.svg"; + +export type TAuthenticationModeProps = { + disabled: boolean; + updateConfig: (key: TInstanceAuthenticationMethodKeys, value: string) => void; +}; + +// Authentication methods +export const getAuthenticationModes: (props: TGetBaseAuthenticationModeProps) => TInstanceAuthenticationModes[] = ({ + disabled, + updateConfig, + resolvedTheme, +}) => [ + { + key: "unique-codes", + name: "Unique codes", + description: + "Log in or sign up for Plane using codes sent via email. You need to have set up SMTP to use this method.", + icon: , + config: , + }, + { + key: "passwords-login", + name: "Passwords", + description: "Allow members to create accounts with passwords and use it with their email addresses to sign in.", + icon: , + config: , + }, + { + key: "google", + name: "Google", + description: "Allow members to log in or sign up for Plane with their Google accounts.", + icon: Google Logo, + config: , + }, + { + key: "github", + name: "GitHub", + description: "Allow members to log in or sign up for Plane with their GitHub accounts.", + icon: ( + GitHub Logo + ), + config: , + }, + { + key: "gitlab", + name: "GitLab", + description: "Allow members to log in or sign up to plane with their GitLab accounts.", + icon: GitLab Logo, + config: , + }, + { + key: "oidc", + name: "OIDC", + description: "Authenticate your users via the OpenID Connect protocol.", + icon: OIDC Logo, + config: , + unavailable: true, + }, + { + key: "saml", + name: "SAML", + description: "Authenticate your users via the Security Assertion Markup Language protocol.", + icon: SAML Logo, + config: , + unavailable: true, + }, +]; + +export const AuthenticationModes: React.FC = observer((props) => { + const { disabled, updateConfig } = props; + // next-themes + const { resolvedTheme } = useTheme(); + + return ( + <> + {getAuthenticationModes({ disabled, updateConfig, resolvedTheme }).map((method) => ( + + ))} + + ); +}); diff --git a/admin/ce/components/authentication/index.ts b/apps/admin/ce/components/authentication/index.ts similarity index 100% rename from admin/ce/components/authentication/index.ts rename to apps/admin/ce/components/authentication/index.ts diff --git a/admin/ce/components/common/index.ts b/apps/admin/ce/components/common/index.ts similarity index 100% rename from admin/ce/components/common/index.ts rename to apps/admin/ce/components/common/index.ts diff --git a/admin/ce/components/common/upgrade-button.tsx b/apps/admin/ce/components/common/upgrade-button.tsx similarity index 100% rename from admin/ce/components/common/upgrade-button.tsx rename to apps/admin/ce/components/common/upgrade-button.tsx diff --git a/admin/ce/store/root.store.ts b/apps/admin/ce/store/root.store.ts similarity index 100% rename from admin/ce/store/root.store.ts rename to apps/admin/ce/store/root.store.ts diff --git a/admin/core/components/authentication/authentication-method-card.tsx b/apps/admin/core/components/authentication/authentication-method-card.tsx similarity index 100% rename from admin/core/components/authentication/authentication-method-card.tsx rename to apps/admin/core/components/authentication/authentication-method-card.tsx diff --git a/admin/core/components/authentication/email-config-switch.tsx b/apps/admin/core/components/authentication/email-config-switch.tsx similarity index 100% rename from admin/core/components/authentication/email-config-switch.tsx rename to apps/admin/core/components/authentication/email-config-switch.tsx diff --git a/admin/core/components/authentication/github-config.tsx b/apps/admin/core/components/authentication/github-config.tsx similarity index 100% rename from admin/core/components/authentication/github-config.tsx rename to apps/admin/core/components/authentication/github-config.tsx diff --git a/admin/core/components/authentication/gitlab-config.tsx b/apps/admin/core/components/authentication/gitlab-config.tsx similarity index 100% rename from admin/core/components/authentication/gitlab-config.tsx rename to apps/admin/core/components/authentication/gitlab-config.tsx diff --git a/admin/core/components/authentication/google-config.tsx b/apps/admin/core/components/authentication/google-config.tsx similarity index 100% rename from admin/core/components/authentication/google-config.tsx rename to apps/admin/core/components/authentication/google-config.tsx diff --git a/admin/core/components/authentication/password-config-switch.tsx b/apps/admin/core/components/authentication/password-config-switch.tsx similarity index 100% rename from admin/core/components/authentication/password-config-switch.tsx rename to apps/admin/core/components/authentication/password-config-switch.tsx diff --git a/admin/core/components/common/banner.tsx b/apps/admin/core/components/common/banner.tsx similarity index 100% rename from admin/core/components/common/banner.tsx rename to apps/admin/core/components/common/banner.tsx diff --git a/admin/core/components/common/breadcrumb-link.tsx b/apps/admin/core/components/common/breadcrumb-link.tsx similarity index 100% rename from admin/core/components/common/breadcrumb-link.tsx rename to apps/admin/core/components/common/breadcrumb-link.tsx diff --git a/admin/core/components/common/code-block.tsx b/apps/admin/core/components/common/code-block.tsx similarity index 100% rename from admin/core/components/common/code-block.tsx rename to apps/admin/core/components/common/code-block.tsx diff --git a/admin/core/components/common/confirm-discard-modal.tsx b/apps/admin/core/components/common/confirm-discard-modal.tsx similarity index 100% rename from admin/core/components/common/confirm-discard-modal.tsx rename to apps/admin/core/components/common/confirm-discard-modal.tsx diff --git a/admin/core/components/common/controller-input.tsx b/apps/admin/core/components/common/controller-input.tsx similarity index 100% rename from admin/core/components/common/controller-input.tsx rename to apps/admin/core/components/common/controller-input.tsx diff --git a/admin/core/components/common/copy-field.tsx b/apps/admin/core/components/common/copy-field.tsx similarity index 100% rename from admin/core/components/common/copy-field.tsx rename to apps/admin/core/components/common/copy-field.tsx diff --git a/admin/core/components/common/empty-state.tsx b/apps/admin/core/components/common/empty-state.tsx similarity index 100% rename from admin/core/components/common/empty-state.tsx rename to apps/admin/core/components/common/empty-state.tsx diff --git a/admin/core/components/common/logo-spinner.tsx b/apps/admin/core/components/common/logo-spinner.tsx similarity index 100% rename from admin/core/components/common/logo-spinner.tsx rename to apps/admin/core/components/common/logo-spinner.tsx diff --git a/admin/core/components/common/page-header.tsx b/apps/admin/core/components/common/page-header.tsx similarity index 100% rename from admin/core/components/common/page-header.tsx rename to apps/admin/core/components/common/page-header.tsx diff --git a/admin/core/components/common/password-strength-meter.tsx b/apps/admin/core/components/common/password-strength-meter.tsx similarity index 100% rename from admin/core/components/common/password-strength-meter.tsx rename to apps/admin/core/components/common/password-strength-meter.tsx diff --git a/admin/core/components/instance/instance-failure-view.tsx b/apps/admin/core/components/instance/failure.tsx similarity index 100% rename from admin/core/components/instance/instance-failure-view.tsx rename to apps/admin/core/components/instance/failure.tsx diff --git a/admin/core/components/instance/instance-not-ready.tsx b/apps/admin/core/components/instance/instance-not-ready.tsx similarity index 100% rename from admin/core/components/instance/instance-not-ready.tsx rename to apps/admin/core/components/instance/instance-not-ready.tsx diff --git a/apps/admin/core/components/instance/loading.tsx b/apps/admin/core/components/instance/loading.tsx new file mode 100644 index 000000000..a21319d9e --- /dev/null +++ b/apps/admin/core/components/instance/loading.tsx @@ -0,0 +1,21 @@ +import Image from "next/image"; +import { useTheme } from "next-themes"; +// assets +import LogoSpinnerDark from "@/public/images/logo-spinner-dark.gif"; +import LogoSpinnerLight from "@/public/images/logo-spinner-light.gif"; + +export const InstanceLoading = () => { + const { resolvedTheme } = useTheme(); + const logoSrc = resolvedTheme === "dark" ? LogoSpinnerDark : LogoSpinnerLight; + + return ( +
+
+
+ logo +

Fetching instance details...

+
+
+
+ ); +}; diff --git a/admin/core/components/instance/setup-form.tsx b/apps/admin/core/components/instance/setup-form.tsx similarity index 99% rename from admin/core/components/instance/setup-form.tsx rename to apps/admin/core/components/instance/setup-form.tsx index fcc5c6c83..4e771e91b 100644 --- a/admin/core/components/instance/setup-form.tsx +++ b/apps/admin/core/components/instance/setup-form.tsx @@ -10,7 +10,8 @@ import { AuthService } from "@plane/services"; import { Button, Checkbox, Input, Spinner } from "@plane/ui"; import { getPasswordStrength } from "@plane/utils"; // components -import { Banner, PasswordStrengthMeter } from "@/components/common"; +import { Banner } from "@/components/common/banner"; +import { PasswordStrengthMeter } from "@/components/common/password-strength-meter"; // service initialization const authService = new AuthService(); diff --git a/admin/core/components/new-user-popup.tsx b/apps/admin/core/components/new-user-popup.tsx similarity index 100% rename from admin/core/components/new-user-popup.tsx rename to apps/admin/core/components/new-user-popup.tsx diff --git a/admin/core/components/workspace/list-item.tsx b/apps/admin/core/components/workspace/list-item.tsx similarity index 100% rename from admin/core/components/workspace/list-item.tsx rename to apps/admin/core/components/workspace/list-item.tsx diff --git a/admin/core/hooks/store/index.ts b/apps/admin/core/hooks/store/index.ts similarity index 100% rename from admin/core/hooks/store/index.ts rename to apps/admin/core/hooks/store/index.ts diff --git a/admin/core/hooks/store/use-instance.tsx b/apps/admin/core/hooks/store/use-instance.tsx similarity index 84% rename from admin/core/hooks/store/use-instance.tsx rename to apps/admin/core/hooks/store/use-instance.tsx index cf2edc39f..67ac3bca8 100644 --- a/admin/core/hooks/store/use-instance.tsx +++ b/apps/admin/core/hooks/store/use-instance.tsx @@ -1,6 +1,6 @@ import { useContext } from "react"; // store -import { StoreContext } from "@/lib/store-provider"; +import { StoreContext } from "@/app/(all)/store.provider"; import { IInstanceStore } from "@/store/instance.store"; export const useInstance = (): IInstanceStore => { diff --git a/admin/core/hooks/store/use-theme.tsx b/apps/admin/core/hooks/store/use-theme.tsx similarity index 83% rename from admin/core/hooks/store/use-theme.tsx rename to apps/admin/core/hooks/store/use-theme.tsx index bad89cfee..0f07149b1 100644 --- a/admin/core/hooks/store/use-theme.tsx +++ b/apps/admin/core/hooks/store/use-theme.tsx @@ -1,6 +1,6 @@ import { useContext } from "react"; // store -import { StoreContext } from "@/lib/store-provider"; +import { StoreContext } from "@/app/(all)/store.provider"; import { IThemeStore } from "@/store/theme.store"; export const useTheme = (): IThemeStore => { diff --git a/admin/core/hooks/store/use-user.tsx b/apps/admin/core/hooks/store/use-user.tsx similarity index 83% rename from admin/core/hooks/store/use-user.tsx rename to apps/admin/core/hooks/store/use-user.tsx index 823003144..eaf02862e 100644 --- a/admin/core/hooks/store/use-user.tsx +++ b/apps/admin/core/hooks/store/use-user.tsx @@ -1,6 +1,6 @@ import { useContext } from "react"; // store -import { StoreContext } from "@/lib/store-provider"; +import { StoreContext } from "@/app/(all)/store.provider"; import { IUserStore } from "@/store/user.store"; export const useUser = (): IUserStore => { diff --git a/admin/core/hooks/store/use-workspace.tsx b/apps/admin/core/hooks/store/use-workspace.tsx similarity index 84% rename from admin/core/hooks/store/use-workspace.tsx rename to apps/admin/core/hooks/store/use-workspace.tsx index e3bde92d5..2203ec948 100644 --- a/admin/core/hooks/store/use-workspace.tsx +++ b/apps/admin/core/hooks/store/use-workspace.tsx @@ -1,6 +1,6 @@ import { useContext } from "react"; // store -import { StoreContext } from "@/lib/store-provider"; +import { StoreContext } from "@/app/(all)/store.provider"; import { IWorkspaceStore } from "@/store/workspace.store"; export const useWorkspace = (): IWorkspaceStore => { diff --git a/admin/core/store/instance.store.ts b/apps/admin/core/store/instance.store.ts similarity index 87% rename from admin/core/store/instance.store.ts rename to apps/admin/core/store/instance.store.ts index 33954fe73..1179f04d6 100644 --- a/admin/core/store/instance.store.ts +++ b/apps/admin/core/store/instance.store.ts @@ -32,6 +32,7 @@ export interface IInstanceStore { fetchInstanceAdmins: () => Promise; fetchInstanceConfigurations: () => Promise; updateInstanceConfigurations: (data: Partial) => Promise; + disableEmail: () => Promise; } export class InstanceStore implements IInstanceStore { @@ -100,7 +101,7 @@ export class InstanceStore implements IInstanceStore { if (this.instance === undefined && !instanceInfo?.instance?.workspaces_exist) this.store.theme.toggleNewUserPopup(); runInAction(() => { - console.log("instanceInfo: ", instanceInfo); + // console.log("instanceInfo: ", instanceInfo); this.isLoading = false; this.instance = instanceInfo.instance; this.config = instanceInfo.config; @@ -187,4 +188,30 @@ export class InstanceStore implements IInstanceStore { throw error; } }; + + disableEmail = async () => { + const instanceConfigurations = this.instanceConfigurations; + try { + runInAction(() => { + this.instanceConfigurations = this.instanceConfigurations?.map((config) => { + if ( + [ + "EMAIL_HOST", + "EMAIL_PORT", + "EMAIL_HOST_USER", + "EMAIL_HOST_PASSWORD", + "EMAIL_FROM", + "ENABLE_SMTP", + ].includes(config.key) + ) + return { ...config, value: "" }; + return config; + }); + }); + await this.instanceService.disableEmail(); + } catch (error) { + console.error("Error disabling the email"); + this.instanceConfigurations = instanceConfigurations; + } + }; } diff --git a/admin/core/store/root.store.ts b/apps/admin/core/store/root.store.ts similarity index 100% rename from admin/core/store/root.store.ts rename to apps/admin/core/store/root.store.ts diff --git a/admin/core/store/theme.store.ts b/apps/admin/core/store/theme.store.ts similarity index 100% rename from admin/core/store/theme.store.ts rename to apps/admin/core/store/theme.store.ts diff --git a/admin/core/store/user.store.ts b/apps/admin/core/store/user.store.ts similarity index 100% rename from admin/core/store/user.store.ts rename to apps/admin/core/store/user.store.ts diff --git a/admin/core/store/workspace.store.ts b/apps/admin/core/store/workspace.store.ts similarity index 100% rename from admin/core/store/workspace.store.ts rename to apps/admin/core/store/workspace.store.ts diff --git a/admin/ee/components/authentication/authentication-modes.tsx b/apps/admin/ee/components/authentication/authentication-modes.tsx similarity index 100% rename from admin/ee/components/authentication/authentication-modes.tsx rename to apps/admin/ee/components/authentication/authentication-modes.tsx diff --git a/admin/ee/components/authentication/index.ts b/apps/admin/ee/components/authentication/index.ts similarity index 100% rename from admin/ee/components/authentication/index.ts rename to apps/admin/ee/components/authentication/index.ts diff --git a/admin/ee/components/common/index.ts b/apps/admin/ee/components/common/index.ts similarity index 100% rename from admin/ee/components/common/index.ts rename to apps/admin/ee/components/common/index.ts diff --git a/admin/ee/store/root.store.ts b/apps/admin/ee/store/root.store.ts similarity index 100% rename from admin/ee/store/root.store.ts rename to apps/admin/ee/store/root.store.ts diff --git a/admin/next-env.d.ts b/apps/admin/next-env.d.ts similarity index 100% rename from admin/next-env.d.ts rename to apps/admin/next-env.d.ts diff --git a/apps/admin/next.config.js b/apps/admin/next.config.js new file mode 100644 index 000000000..c848e0b92 --- /dev/null +++ b/apps/admin/next.config.js @@ -0,0 +1,29 @@ +/** @type {import('next').NextConfig} */ + +const nextConfig = { + trailingSlash: true, + reactStrictMode: false, + swcMinify: true, + output: "standalone", + images: { + unoptimized: true, + }, + basePath: process.env.NEXT_PUBLIC_ADMIN_BASE_PATH || "", + experimental: { + optimizePackageImports: [ + "@plane/constants", + "@plane/editor", + "@plane/hooks", + "@plane/i18n", + "@plane/logger", + "@plane/propel", + "@plane/services", + "@plane/shared-state", + "@plane/types", + "@plane/ui", + "@plane/utils", + ], + }, +}; + +module.exports = nextConfig; diff --git a/admin/package.json b/apps/admin/package.json similarity index 72% rename from admin/package.json rename to apps/admin/package.json index 6220dc876..556c29a58 100644 --- a/admin/package.json +++ b/apps/admin/package.json @@ -1,18 +1,20 @@ { "name": "admin", "description": "Admin UI for Plane", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "private": true, "scripts": { - "dev": "turbo run develop", - "develop": "next dev --port 3001", + "dev": "next dev --port 3001", "build": "next build", "preview": "next build && next start", "start": "next start", - "format": "prettier --write .", - "lint": "eslint . --ext .ts,.tsx", - "lint:errors": "eslint . --ext .ts,.tsx --quiet" + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"" }, "dependencies": { "@headlessui/react": "^1.7.19", @@ -26,14 +28,14 @@ "@tailwindcss/typography": "^0.5.9", "@types/lodash": "^4.17.0", "autoprefixer": "10.4.14", - "axios": "^1.8.3", + "axios": "1.11.0", "lodash": "^4.17.21", "lucide-react": "^0.469.0", "mobx": "^6.12.0", "mobx-react": "^9.1.1", "next": "14.2.30", "next-themes": "^0.2.1", - "postcss": "^8.4.38", + "postcss": "^8.4.49", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "7.51.5", diff --git a/admin/postcss.config.js b/apps/admin/postcss.config.js similarity index 100% rename from admin/postcss.config.js rename to apps/admin/postcss.config.js diff --git a/admin/public/auth/background-pattern-dark.svg b/apps/admin/public/auth/background-pattern-dark.svg similarity index 100% rename from admin/public/auth/background-pattern-dark.svg rename to apps/admin/public/auth/background-pattern-dark.svg diff --git a/admin/public/auth/background-pattern.svg b/apps/admin/public/auth/background-pattern.svg similarity index 100% rename from admin/public/auth/background-pattern.svg rename to apps/admin/public/auth/background-pattern.svg diff --git a/admin/public/favicon/android-chrome-192x192.png b/apps/admin/public/favicon/android-chrome-192x192.png similarity index 100% rename from admin/public/favicon/android-chrome-192x192.png rename to apps/admin/public/favicon/android-chrome-192x192.png diff --git a/admin/public/favicon/android-chrome-512x512.png b/apps/admin/public/favicon/android-chrome-512x512.png similarity index 100% rename from admin/public/favicon/android-chrome-512x512.png rename to apps/admin/public/favicon/android-chrome-512x512.png diff --git a/admin/public/favicon/apple-touch-icon.png b/apps/admin/public/favicon/apple-touch-icon.png similarity index 100% rename from admin/public/favicon/apple-touch-icon.png rename to apps/admin/public/favicon/apple-touch-icon.png diff --git a/admin/public/favicon/favicon-16x16.png b/apps/admin/public/favicon/favicon-16x16.png similarity index 100% rename from admin/public/favicon/favicon-16x16.png rename to apps/admin/public/favicon/favicon-16x16.png diff --git a/admin/public/favicon/favicon-32x32.png b/apps/admin/public/favicon/favicon-32x32.png similarity index 100% rename from admin/public/favicon/favicon-32x32.png rename to apps/admin/public/favicon/favicon-32x32.png diff --git a/admin/public/favicon/favicon.ico b/apps/admin/public/favicon/favicon.ico similarity index 100% rename from admin/public/favicon/favicon.ico rename to apps/admin/public/favicon/favicon.ico diff --git a/admin/public/favicon/site.webmanifest b/apps/admin/public/favicon/site.webmanifest similarity index 100% rename from admin/public/favicon/site.webmanifest rename to apps/admin/public/favicon/site.webmanifest diff --git a/admin/public/images/logo-spinner-dark.gif b/apps/admin/public/images/logo-spinner-dark.gif similarity index 100% rename from admin/public/images/logo-spinner-dark.gif rename to apps/admin/public/images/logo-spinner-dark.gif diff --git a/admin/public/images/logo-spinner-light.gif b/apps/admin/public/images/logo-spinner-light.gif similarity index 100% rename from admin/public/images/logo-spinner-light.gif rename to apps/admin/public/images/logo-spinner-light.gif diff --git a/admin/public/images/plane-takeoff.png b/apps/admin/public/images/plane-takeoff.png similarity index 100% rename from admin/public/images/plane-takeoff.png rename to apps/admin/public/images/plane-takeoff.png diff --git a/admin/public/instance/instance-failure-dark.svg b/apps/admin/public/instance/instance-failure-dark.svg similarity index 100% rename from admin/public/instance/instance-failure-dark.svg rename to apps/admin/public/instance/instance-failure-dark.svg diff --git a/admin/public/instance/instance-failure.svg b/apps/admin/public/instance/instance-failure.svg similarity index 100% rename from admin/public/instance/instance-failure.svg rename to apps/admin/public/instance/instance-failure.svg diff --git a/admin/public/instance/plane-takeoff.png b/apps/admin/public/instance/plane-takeoff.png similarity index 100% rename from admin/public/instance/plane-takeoff.png rename to apps/admin/public/instance/plane-takeoff.png diff --git a/admin/public/logos/github-black.png b/apps/admin/public/logos/github-black.png similarity index 100% rename from admin/public/logos/github-black.png rename to apps/admin/public/logos/github-black.png diff --git a/admin/public/logos/github-white.png b/apps/admin/public/logos/github-white.png similarity index 100% rename from admin/public/logos/github-white.png rename to apps/admin/public/logos/github-white.png diff --git a/admin/public/logos/gitlab-logo.svg b/apps/admin/public/logos/gitlab-logo.svg similarity index 100% rename from admin/public/logos/gitlab-logo.svg rename to apps/admin/public/logos/gitlab-logo.svg diff --git a/admin/public/logos/google-logo.svg b/apps/admin/public/logos/google-logo.svg similarity index 100% rename from admin/public/logos/google-logo.svg rename to apps/admin/public/logos/google-logo.svg diff --git a/admin/public/logos/oidc-logo.svg b/apps/admin/public/logos/oidc-logo.svg similarity index 100% rename from admin/public/logos/oidc-logo.svg rename to apps/admin/public/logos/oidc-logo.svg diff --git a/admin/public/logos/saml-logo.svg b/apps/admin/public/logos/saml-logo.svg similarity index 100% rename from admin/public/logos/saml-logo.svg rename to apps/admin/public/logos/saml-logo.svg diff --git a/admin/public/logos/takeoff-icon-dark.svg b/apps/admin/public/logos/takeoff-icon-dark.svg similarity index 100% rename from admin/public/logos/takeoff-icon-dark.svg rename to apps/admin/public/logos/takeoff-icon-dark.svg diff --git a/admin/public/logos/takeoff-icon-light.svg b/apps/admin/public/logos/takeoff-icon-light.svg similarity index 100% rename from admin/public/logos/takeoff-icon-light.svg rename to apps/admin/public/logos/takeoff-icon-light.svg diff --git a/admin/public/plane-logos/black-horizontal-with-blue-logo.png b/apps/admin/public/plane-logos/black-horizontal-with-blue-logo.png similarity index 100% rename from admin/public/plane-logos/black-horizontal-with-blue-logo.png rename to apps/admin/public/plane-logos/black-horizontal-with-blue-logo.png diff --git a/admin/public/plane-logos/blue-without-text.png b/apps/admin/public/plane-logos/blue-without-text.png similarity index 100% rename from admin/public/plane-logos/blue-without-text.png rename to apps/admin/public/plane-logos/blue-without-text.png diff --git a/admin/public/plane-logos/white-horizontal-with-blue-logo.png b/apps/admin/public/plane-logos/white-horizontal-with-blue-logo.png similarity index 100% rename from admin/public/plane-logos/white-horizontal-with-blue-logo.png rename to apps/admin/public/plane-logos/white-horizontal-with-blue-logo.png diff --git a/admin/public/site.webmanifest.json b/apps/admin/public/site.webmanifest.json similarity index 100% rename from admin/public/site.webmanifest.json rename to apps/admin/public/site.webmanifest.json diff --git a/admin/styles/globals.css b/apps/admin/styles/globals.css similarity index 100% rename from admin/styles/globals.css rename to apps/admin/styles/globals.css diff --git a/admin/tailwind.config.js b/apps/admin/tailwind.config.js similarity index 100% rename from admin/tailwind.config.js rename to apps/admin/tailwind.config.js diff --git a/admin/tsconfig.json b/apps/admin/tsconfig.json similarity index 94% rename from admin/tsconfig.json rename to apps/admin/tsconfig.json index df72d07b4..d85abf2cc 100644 --- a/admin/tsconfig.json +++ b/apps/admin/tsconfig.json @@ -8,6 +8,7 @@ ], "baseUrl": ".", "paths": { + "@/app/*": ["app/*"], "@/*": ["core/*"], "@/public/*": ["public/*"], "@/plane-admin/*": ["ce/*"], diff --git a/apiserver/.coveragerc b/apps/api/.coveragerc similarity index 100% rename from apiserver/.coveragerc rename to apps/api/.coveragerc diff --git a/apiserver/.env.example b/apps/api/.env.example similarity index 93% rename from apiserver/.env.example rename to apps/api/.env.example index 7fdffd179..f158e3d7c 100644 --- a/apiserver/.env.example +++ b/apps/api/.env.example @@ -28,7 +28,7 @@ AWS_REGION="" AWS_ACCESS_KEY_ID="access-key" AWS_SECRET_ACCESS_KEY="secret-key" AWS_S3_ENDPOINT_URL="http://localhost:9000" -# Changing this requires change in the nginx.conf for uploads if using minio setup +# Changing this requires change in the proxy config for uploads if using minio setup AWS_S3_BUCKET_NAME="uploads" # Maximum file upload limit FILE_SIZE_LIMIT=5242880 @@ -39,8 +39,7 @@ DOCKERIZED=1 # deprecated # set to 1 If using the pre-configured minio setup USE_MINIO=0 -# Nginx Configuration -NGINX_PORT=80 + # Email redirections and minio domain settings WEB_URL="http://localhost:8000" diff --git a/apiserver/Dockerfile.api b/apps/api/Dockerfile.api similarity index 68% rename from apiserver/Dockerfile.api rename to apps/api/Dockerfile.api index b0fa44788..132514811 100644 --- a/apiserver/Dockerfile.api +++ b/apps/api/Dockerfile.api @@ -1,18 +1,22 @@ -FROM python:3.12.5-alpine AS backend +FROM python:3.12.10-alpine # set environment variables -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 ENV PIP_DISABLE_PIP_VERSION_CHECK=1 -ENV INSTANCE_CHANGELOG_URL https://sites.plane.so/pages/691ef037bcfe416a902e48cb55f59891/ +ENV INSTANCE_CHANGELOG_URL=https://sites.plane.so/pages/691ef037bcfe416a902e48cb55f59891/ + +# Update system packages for security +RUN apk update && apk upgrade WORKDIR /code -RUN apk add --no-cache \ +RUN apk add --no-cache --upgrade \ "libpq" \ "libxslt" \ - "nodejs-current" \ - "xmlsec" + "xmlsec" \ + "ca-certificates" \ + "openssl" COPY requirements.txt ./ COPY requirements ./requirements @@ -30,7 +34,9 @@ RUN apk add --no-cache --virtual .build-deps \ && \ pip install -r requirements.txt --compile --no-cache-dir \ && \ - apk del .build-deps + apk del .build-deps \ + && \ + rm -rf /var/cache/apk/* # Add in Django deps and generate Django's static files @@ -49,4 +55,4 @@ RUN chmod -R 777 /code # Expose container port and run entry point script EXPOSE 8000 - +CMD ["./bin/docker-entrypoint-api.sh"] \ No newline at end of file diff --git a/apiserver/Dockerfile.dev b/apps/api/Dockerfile.dev similarity index 100% rename from apiserver/Dockerfile.dev rename to apps/api/Dockerfile.dev diff --git a/apiserver/bin/docker-entrypoint-api-local.sh b/apps/api/bin/docker-entrypoint-api-local.sh similarity index 100% rename from apiserver/bin/docker-entrypoint-api-local.sh rename to apps/api/bin/docker-entrypoint-api-local.sh diff --git a/apiserver/bin/docker-entrypoint-api.sh b/apps/api/bin/docker-entrypoint-api.sh similarity index 100% rename from apiserver/bin/docker-entrypoint-api.sh rename to apps/api/bin/docker-entrypoint-api.sh diff --git a/apiserver/bin/docker-entrypoint-beat.sh b/apps/api/bin/docker-entrypoint-beat.sh similarity index 100% rename from apiserver/bin/docker-entrypoint-beat.sh rename to apps/api/bin/docker-entrypoint-beat.sh diff --git a/apiserver/bin/docker-entrypoint-migrator.sh b/apps/api/bin/docker-entrypoint-migrator.sh similarity index 100% rename from apiserver/bin/docker-entrypoint-migrator.sh rename to apps/api/bin/docker-entrypoint-migrator.sh diff --git a/apiserver/bin/docker-entrypoint-worker.sh b/apps/api/bin/docker-entrypoint-worker.sh similarity index 100% rename from apiserver/bin/docker-entrypoint-worker.sh rename to apps/api/bin/docker-entrypoint-worker.sh diff --git a/apiserver/manage.py b/apps/api/manage.py similarity index 100% rename from apiserver/manage.py rename to apps/api/manage.py diff --git a/apiserver/package.json b/apps/api/package.json similarity index 84% rename from apiserver/package.json rename to apps/api/package.json index 46d5fc5e6..6b374e611 100644 --- a/apiserver/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "plane-api", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "private": true, "description": "API server powering Plane's backend" diff --git a/apiserver/plane/__init__.py b/apps/api/plane/__init__.py similarity index 100% rename from apiserver/plane/__init__.py rename to apps/api/plane/__init__.py diff --git a/apiserver/plane/analytics/__init__.py b/apps/api/plane/analytics/__init__.py similarity index 100% rename from apiserver/plane/analytics/__init__.py rename to apps/api/plane/analytics/__init__.py diff --git a/apiserver/plane/analytics/apps.py b/apps/api/plane/analytics/apps.py similarity index 100% rename from apiserver/plane/analytics/apps.py rename to apps/api/plane/analytics/apps.py diff --git a/apiserver/plane/api/__init__.py b/apps/api/plane/api/__init__.py similarity index 100% rename from apiserver/plane/api/__init__.py rename to apps/api/plane/api/__init__.py diff --git a/apiserver/plane/api/apps.py b/apps/api/plane/api/apps.py similarity index 100% rename from apiserver/plane/api/apps.py rename to apps/api/plane/api/apps.py diff --git a/apiserver/plane/api/middleware/__init__.py b/apps/api/plane/api/middleware/__init__.py similarity index 100% rename from apiserver/plane/api/middleware/__init__.py rename to apps/api/plane/api/middleware/__init__.py diff --git a/apiserver/plane/api/middleware/api_authentication.py b/apps/api/plane/api/middleware/api_authentication.py similarity index 100% rename from apiserver/plane/api/middleware/api_authentication.py rename to apps/api/plane/api/middleware/api_authentication.py diff --git a/apiserver/plane/api/rate_limit.py b/apps/api/plane/api/rate_limit.py similarity index 100% rename from apiserver/plane/api/rate_limit.py rename to apps/api/plane/api/rate_limit.py diff --git a/apiserver/plane/api/serializers/__init__.py b/apps/api/plane/api/serializers/__init__.py similarity index 100% rename from apiserver/plane/api/serializers/__init__.py rename to apps/api/plane/api/serializers/__init__.py diff --git a/apiserver/plane/api/serializers/base.py b/apps/api/plane/api/serializers/base.py similarity index 100% rename from apiserver/plane/api/serializers/base.py rename to apps/api/plane/api/serializers/base.py diff --git a/apiserver/plane/api/serializers/cycle.py b/apps/api/plane/api/serializers/cycle.py similarity index 100% rename from apiserver/plane/api/serializers/cycle.py rename to apps/api/plane/api/serializers/cycle.py diff --git a/apiserver/plane/api/serializers/estimate.py b/apps/api/plane/api/serializers/estimate.py similarity index 100% rename from apiserver/plane/api/serializers/estimate.py rename to apps/api/plane/api/serializers/estimate.py diff --git a/apiserver/plane/api/serializers/intake.py b/apps/api/plane/api/serializers/intake.py similarity index 100% rename from apiserver/plane/api/serializers/intake.py rename to apps/api/plane/api/serializers/intake.py diff --git a/apiserver/plane/api/serializers/issue.py b/apps/api/plane/api/serializers/issue.py similarity index 86% rename from apiserver/plane/api/serializers/issue.py rename to apps/api/plane/api/serializers/issue.py index 10738b97f..20f967e3b 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apps/api/plane/api/serializers/issue.py @@ -20,6 +20,12 @@ from plane.db.models import ( ProjectMember, State, User, + EstimatePoint, +) +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, ) from .base import BaseSerializer @@ -75,6 +81,22 @@ class IssueSerializer(BaseSerializer): except Exception: raise serializers.ValidationError("Invalid HTML passed") + # Validate description content for security + if data.get("description"): + is_valid, error_msg = validate_json_content(data["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if data.get("description_html"): + is_valid, error_msg = validate_html_content(data["description_html"]) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + if data.get("description_binary"): + is_valid, error_msg = validate_binary_data(data["description_binary"]) + if not is_valid: + raise serializers.ValidationError({"description_binary": error_msg}) + # Validate assignees are from project if data.get("assignees", []): data["assignees"] = ProjectMember.objects.filter( @@ -105,13 +127,27 @@ class IssueSerializer(BaseSerializer): if ( data.get("parent") and not Issue.objects.filter( - workspace_id=self.context.get("workspace_id"), pk=data.get("parent").id + workspace_id=self.context.get("workspace_id"), + project_id=self.context.get("project_id"), + pk=data.get("parent").id, ).exists() ): raise serializers.ValidationError( "Parent is not valid issue_id please pass a valid issue_id" ) + if ( + data.get("estimate_point") + and not EstimatePoint.objects.filter( + workspace_id=self.context.get("workspace_id"), + project_id=self.context.get("project_id"), + pk=data.get("estimate_point").id, + ).exists() + ): + raise serializers.ValidationError( + "Estimate point is not valid please pass a valid estimate_point_id" + ) + return data def create(self, validated_data): @@ -448,10 +484,30 @@ class LabelLiteSerializer(BaseSerializer): class IssueExpandSerializer(BaseSerializer): cycle = CycleLiteSerializer(source="issue_cycle.cycle", read_only=True) module = ModuleLiteSerializer(source="issue_module.module", read_only=True) - labels = LabelLiteSerializer(read_only=True, many=True) - assignees = UserLiteSerializer(read_only=True, many=True) + + labels = serializers.SerializerMethodField() + assignees = serializers.SerializerMethodField() state = StateLiteSerializer(read_only=True) + + def get_labels(self, obj): + expand = self.context.get("expand", []) + if "labels" in expand: + # Use prefetched data + return LabelLiteSerializer( + [il.label for il in obj.label_issue.all()], many=True + ).data + return [il.label_id for il in obj.label_issue.all()] + + def get_assignees(self, obj): + expand = self.context.get("expand", []) + if "assignees" in expand: + return UserLiteSerializer( + [ia.assignee for ia in obj.issue_assignee.all()], many=True + ).data + return [ia.assignee_id for ia in obj.issue_assignee.all()] + + class Meta: model = Issue fields = "__all__" diff --git a/apiserver/plane/api/serializers/module.py b/apps/api/plane/api/serializers/module.py similarity index 100% rename from apiserver/plane/api/serializers/module.py rename to apps/api/plane/api/serializers/module.py diff --git a/apiserver/plane/api/serializers/project.py b/apps/api/plane/api/serializers/project.py similarity index 71% rename from apiserver/plane/api/serializers/project.py rename to apps/api/plane/api/serializers/project.py index c76652e1e..10ae7f4de 100644 --- a/apiserver/plane/api/serializers/project.py +++ b/apps/api/plane/api/serializers/project.py @@ -3,6 +3,11 @@ from rest_framework import serializers # Module imports from plane.db.models import Project, ProjectIdentifier, WorkspaceMember +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, +) from .base import BaseSerializer @@ -57,6 +62,29 @@ class ProjectSerializer(BaseSerializer): "Default assignee should be a user in the workspace" ) + # Validate description content for security + if "description" in data and data["description"]: + # For Project, description might be text field, not JSON + if isinstance(data["description"], dict): + is_valid, error_msg = validate_json_content(data["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_text" in data and data["description_text"]: + is_valid, error_msg = validate_json_content(data["description_text"]) + if not is_valid: + raise serializers.ValidationError({"description_text": error_msg}) + + if "description_html" in data and data["description_html"]: + if isinstance(data["description_html"], dict): + is_valid, error_msg = validate_json_content(data["description_html"]) + else: + is_valid, error_msg = validate_html_content( + str(data["description_html"]) + ) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + return data def create(self, validated_data): diff --git a/apiserver/plane/api/serializers/state.py b/apps/api/plane/api/serializers/state.py similarity index 100% rename from apiserver/plane/api/serializers/state.py rename to apps/api/plane/api/serializers/state.py diff --git a/apiserver/plane/api/serializers/user.py b/apps/api/plane/api/serializers/user.py similarity index 100% rename from apiserver/plane/api/serializers/user.py rename to apps/api/plane/api/serializers/user.py diff --git a/apiserver/plane/api/serializers/workspace.py b/apps/api/plane/api/serializers/workspace.py similarity index 100% rename from apiserver/plane/api/serializers/workspace.py rename to apps/api/plane/api/serializers/workspace.py diff --git a/apiserver/plane/api/urls/__init__.py b/apps/api/plane/api/urls/__init__.py similarity index 100% rename from apiserver/plane/api/urls/__init__.py rename to apps/api/plane/api/urls/__init__.py diff --git a/apiserver/plane/api/urls/cycle.py b/apps/api/plane/api/urls/cycle.py similarity index 100% rename from apiserver/plane/api/urls/cycle.py rename to apps/api/plane/api/urls/cycle.py diff --git a/apiserver/plane/api/urls/intake.py b/apps/api/plane/api/urls/intake.py similarity index 100% rename from apiserver/plane/api/urls/intake.py rename to apps/api/plane/api/urls/intake.py diff --git a/apiserver/plane/api/urls/issue.py b/apps/api/plane/api/urls/issue.py similarity index 100% rename from apiserver/plane/api/urls/issue.py rename to apps/api/plane/api/urls/issue.py diff --git a/apiserver/plane/api/urls/member.py b/apps/api/plane/api/urls/member.py similarity index 100% rename from apiserver/plane/api/urls/member.py rename to apps/api/plane/api/urls/member.py diff --git a/apiserver/plane/api/urls/module.py b/apps/api/plane/api/urls/module.py similarity index 100% rename from apiserver/plane/api/urls/module.py rename to apps/api/plane/api/urls/module.py diff --git a/apiserver/plane/api/urls/project.py b/apps/api/plane/api/urls/project.py similarity index 100% rename from apiserver/plane/api/urls/project.py rename to apps/api/plane/api/urls/project.py diff --git a/apiserver/plane/api/urls/state.py b/apps/api/plane/api/urls/state.py similarity index 100% rename from apiserver/plane/api/urls/state.py rename to apps/api/plane/api/urls/state.py diff --git a/apiserver/plane/api/views/__init__.py b/apps/api/plane/api/views/__init__.py similarity index 100% rename from apiserver/plane/api/views/__init__.py rename to apps/api/plane/api/views/__init__.py diff --git a/apiserver/plane/api/views/base.py b/apps/api/plane/api/views/base.py similarity index 100% rename from apiserver/plane/api/views/base.py rename to apps/api/plane/api/views/base.py diff --git a/apiserver/plane/api/views/cycle.py b/apps/api/plane/api/views/cycle.py similarity index 99% rename from apiserver/plane/api/views/cycle.py rename to apps/api/plane/api/views/cycle.py index 9005821f3..457671b93 100644 --- a/apiserver/plane/api/views/cycle.py +++ b/apps/api/plane/api/views/cycle.py @@ -25,7 +25,7 @@ from rest_framework import status from rest_framework.response import Response # Module imports -from plane.api.serializers import CycleIssueSerializer, CycleSerializer +from plane.api.serializers import CycleIssueSerializer, CycleSerializer, IssueSerializer from plane.app.permissions import ProjectEntityPermission from plane.bgtasks.issue_activities_task import issue_activity from plane.db.models import ( @@ -639,7 +639,7 @@ class CycleIssueAPIEndpoint(BaseAPIView): return self.paginate( request=request, queryset=(issues), - on_results=lambda issues: CycleSerializer( + on_results=lambda issues: IssueSerializer( issues, many=True, fields=self.fields, expand=self.expand ).data, ) diff --git a/apiserver/plane/api/views/intake.py b/apps/api/plane/api/views/intake.py similarity index 100% rename from apiserver/plane/api/views/intake.py rename to apps/api/plane/api/views/intake.py diff --git a/apiserver/plane/api/views/issue.py b/apps/api/plane/api/views/issue.py similarity index 99% rename from apiserver/plane/api/views/issue.py rename to apps/api/plane/api/views/issue.py index 7ba8cb253..6a5016bec 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apps/api/plane/api/views/issue.py @@ -60,6 +60,7 @@ from plane.utils.host import base_host from plane.bgtasks.webhook_task import model_activity from plane.bgtasks.work_item_link_task import crawl_work_item_link_title + class WorkspaceIssueAPIEndpoint(BaseAPIView): """ This viewset provides `retrieveByIssueId` on workspace level diff --git a/apiserver/plane/api/views/member.py b/apps/api/plane/api/views/member.py similarity index 100% rename from apiserver/plane/api/views/member.py rename to apps/api/plane/api/views/member.py diff --git a/apiserver/plane/api/views/module.py b/apps/api/plane/api/views/module.py similarity index 100% rename from apiserver/plane/api/views/module.py rename to apps/api/plane/api/views/module.py diff --git a/apiserver/plane/api/views/project.py b/apps/api/plane/api/views/project.py similarity index 100% rename from apiserver/plane/api/views/project.py rename to apps/api/plane/api/views/project.py diff --git a/apiserver/plane/api/views/state.py b/apps/api/plane/api/views/state.py similarity index 100% rename from apiserver/plane/api/views/state.py rename to apps/api/plane/api/views/state.py diff --git a/apiserver/plane/app/__init__.py b/apps/api/plane/app/__init__.py similarity index 100% rename from apiserver/plane/app/__init__.py rename to apps/api/plane/app/__init__.py diff --git a/apiserver/plane/app/apps.py b/apps/api/plane/app/apps.py similarity index 100% rename from apiserver/plane/app/apps.py rename to apps/api/plane/app/apps.py diff --git a/apiserver/plane/app/middleware/__init__.py b/apps/api/plane/app/middleware/__init__.py similarity index 100% rename from apiserver/plane/app/middleware/__init__.py rename to apps/api/plane/app/middleware/__init__.py diff --git a/apiserver/plane/app/middleware/api_authentication.py b/apps/api/plane/app/middleware/api_authentication.py similarity index 100% rename from apiserver/plane/app/middleware/api_authentication.py rename to apps/api/plane/app/middleware/api_authentication.py diff --git a/apiserver/plane/app/permissions/__init__.py b/apps/api/plane/app/permissions/__init__.py similarity index 100% rename from apiserver/plane/app/permissions/__init__.py rename to apps/api/plane/app/permissions/__init__.py diff --git a/apiserver/plane/app/permissions/base.py b/apps/api/plane/app/permissions/base.py similarity index 100% rename from apiserver/plane/app/permissions/base.py rename to apps/api/plane/app/permissions/base.py diff --git a/apiserver/plane/app/permissions/project.py b/apps/api/plane/app/permissions/project.py similarity index 100% rename from apiserver/plane/app/permissions/project.py rename to apps/api/plane/app/permissions/project.py diff --git a/apiserver/plane/app/permissions/workspace.py b/apps/api/plane/app/permissions/workspace.py similarity index 100% rename from apiserver/plane/app/permissions/workspace.py rename to apps/api/plane/app/permissions/workspace.py diff --git a/apiserver/plane/app/serializers/__init__.py b/apps/api/plane/app/serializers/__init__.py similarity index 99% rename from apiserver/plane/app/serializers/__init__.py rename to apps/api/plane/app/serializers/__init__.py index f0d98886e..0116b2061 100644 --- a/apiserver/plane/app/serializers/__init__.py +++ b/apps/api/plane/app/serializers/__init__.py @@ -96,6 +96,7 @@ from .page import ( SubPageSerializer, PageDetailSerializer, PageVersionSerializer, + PageBinaryUpdateSerializer, PageVersionDetailSerializer, ) diff --git a/apiserver/plane/app/serializers/analytic.py b/apps/api/plane/app/serializers/analytic.py similarity index 100% rename from apiserver/plane/app/serializers/analytic.py rename to apps/api/plane/app/serializers/analytic.py diff --git a/apiserver/plane/app/serializers/api.py b/apps/api/plane/app/serializers/api.py similarity index 100% rename from apiserver/plane/app/serializers/api.py rename to apps/api/plane/app/serializers/api.py diff --git a/apiserver/plane/app/serializers/asset.py b/apps/api/plane/app/serializers/asset.py similarity index 100% rename from apiserver/plane/app/serializers/asset.py rename to apps/api/plane/app/serializers/asset.py diff --git a/apiserver/plane/app/serializers/base.py b/apps/api/plane/app/serializers/base.py similarity index 100% rename from apiserver/plane/app/serializers/base.py rename to apps/api/plane/app/serializers/base.py diff --git a/apiserver/plane/app/serializers/cycle.py b/apps/api/plane/app/serializers/cycle.py similarity index 97% rename from apiserver/plane/app/serializers/cycle.py rename to apps/api/plane/app/serializers/cycle.py index b3b69e375..2aa2ac7b7 100644 --- a/apiserver/plane/app/serializers/cycle.py +++ b/apps/api/plane/app/serializers/cycle.py @@ -102,4 +102,4 @@ class CycleUserPropertiesSerializer(BaseSerializer): class Meta: model = CycleUserProperties fields = "__all__" - read_only_fields = ["workspace", "project", "cycle" "user"] + read_only_fields = ["workspace", "project", "cycle", "user"] diff --git a/apiserver/plane/app/serializers/draft.py b/apps/api/plane/app/serializers/draft.py similarity index 70% rename from apiserver/plane/app/serializers/draft.py rename to apps/api/plane/app/serializers/draft.py index f30835263..57600bff9 100644 --- a/apiserver/plane/app/serializers/draft.py +++ b/apps/api/plane/app/serializers/draft.py @@ -16,7 +16,15 @@ from plane.db.models import ( DraftIssueLabel, DraftIssueCycle, DraftIssueModule, + ProjectMember, + EstimatePoint, ) +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, +) +from plane.app.permissions import ROLE class DraftIssueCreateSerializer(BaseSerializer): @@ -57,14 +65,84 @@ class DraftIssueCreateSerializer(BaseSerializer): data["label_ids"] = label_ids if label_ids else [] return data - def validate(self, data): + def validate(self, attrs): if ( - data.get("start_date", None) is not None - and data.get("target_date", None) is not None - and data.get("start_date", None) > data.get("target_date", None) + attrs.get("start_date", None) is not None + and attrs.get("target_date", None) is not None + and attrs.get("start_date", None) > attrs.get("target_date", None) ): raise serializers.ValidationError("Start date cannot exceed target date") - return data + + # Validate description content for security + if "description" in attrs and attrs["description"]: + is_valid, error_msg = validate_json_content(attrs["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_html" in attrs and attrs["description_html"]: + is_valid, error_msg = validate_html_content(attrs["description_html"]) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + if "description_binary" in attrs and attrs["description_binary"]: + is_valid, error_msg = validate_binary_data(attrs["description_binary"]) + if not is_valid: + raise serializers.ValidationError({"description_binary": error_msg}) + + # Validate assignees are from project + if attrs.get("assignee_ids", []): + attrs["assignee_ids"] = ProjectMember.objects.filter( + project_id=self.context["project_id"], + role__gte=ROLE.MEMBER.value, + is_active=True, + member_id__in=attrs["assignee_ids"], + ).values_list("member_id", flat=True) + + # Validate labels are from project + if attrs.get("label_ids"): + label_ids = [label.id for label in attrs["label_ids"]] + attrs["label_ids"] = list( + Label.objects.filter( + project_id=self.context.get("project_id"), id__in=label_ids + ).values_list("id", flat=True) + ) + + # # Check state is from the project only else raise validation error + if ( + attrs.get("state") + and not State.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("state").id, + ).exists() + ): + raise serializers.ValidationError( + "State is not valid please pass a valid state_id" + ) + + # # Check parent issue is from workspace as it can be cross workspace + if ( + attrs.get("parent") + and not Issue.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("parent").id, + ).exists() + ): + raise serializers.ValidationError( + "Parent is not valid issue_id please pass a valid issue_id" + ) + + if ( + attrs.get("estimate_point") + and not EstimatePoint.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("estimate_point").id, + ).exists() + ): + raise serializers.ValidationError( + "Estimate point is not valid please pass a valid estimate_point_id" + ) + + return attrs def create(self, validated_data): assignees = validated_data.pop("assignee_ids", None) @@ -89,14 +167,14 @@ class DraftIssueCreateSerializer(BaseSerializer): DraftIssueAssignee.objects.bulk_create( [ DraftIssueAssignee( - assignee=user, + assignee_id=assignee_id, draft_issue=issue, workspace_id=workspace_id, project_id=project_id, created_by_id=created_by_id, updated_by_id=updated_by_id, ) - for user in assignees + for assignee_id in assignees ], batch_size=10, ) @@ -105,14 +183,14 @@ class DraftIssueCreateSerializer(BaseSerializer): DraftIssueLabel.objects.bulk_create( [ DraftIssueLabel( - label=label, + label_id=label_id, draft_issue=issue, project_id=project_id, workspace_id=workspace_id, created_by_id=created_by_id, updated_by_id=updated_by_id, ) - for label in labels + for label_id in labels ], batch_size=10, ) @@ -163,14 +241,14 @@ class DraftIssueCreateSerializer(BaseSerializer): DraftIssueAssignee.objects.bulk_create( [ DraftIssueAssignee( - assignee=user, + assignee_id=assignee_id, draft_issue=instance, workspace_id=workspace_id, project_id=project_id, created_by_id=created_by_id, updated_by_id=updated_by_id, ) - for user in assignees + for assignee_id in assignees ], batch_size=10, ) diff --git a/apiserver/plane/app/serializers/estimate.py b/apps/api/plane/app/serializers/estimate.py similarity index 100% rename from apiserver/plane/app/serializers/estimate.py rename to apps/api/plane/app/serializers/estimate.py diff --git a/apiserver/plane/app/serializers/exporter.py b/apps/api/plane/app/serializers/exporter.py similarity index 100% rename from apiserver/plane/app/serializers/exporter.py rename to apps/api/plane/app/serializers/exporter.py diff --git a/apiserver/plane/app/serializers/favorite.py b/apps/api/plane/app/serializers/favorite.py similarity index 100% rename from apiserver/plane/app/serializers/favorite.py rename to apps/api/plane/app/serializers/favorite.py diff --git a/apiserver/plane/app/serializers/importer.py b/apps/api/plane/app/serializers/importer.py similarity index 100% rename from apiserver/plane/app/serializers/importer.py rename to apps/api/plane/app/serializers/importer.py diff --git a/apiserver/plane/app/serializers/intake.py b/apps/api/plane/app/serializers/intake.py similarity index 100% rename from apiserver/plane/app/serializers/intake.py rename to apps/api/plane/app/serializers/intake.py diff --git a/apiserver/plane/app/serializers/issue.py b/apps/api/plane/app/serializers/issue.py similarity index 91% rename from apiserver/plane/app/serializers/issue.py rename to apps/api/plane/app/serializers/issue.py index c2aca4f81..897326431 100644 --- a/apiserver/plane/app/serializers/issue.py +++ b/apps/api/plane/app/serializers/issue.py @@ -37,6 +37,12 @@ from plane.db.models import ( IssueVersion, IssueDescriptionVersion, ProjectMember, + EstimatePoint, +) +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, ) @@ -119,6 +125,23 @@ class IssueCreateSerializer(BaseSerializer): ): raise serializers.ValidationError("Start date cannot exceed target date") + # Validate description content for security + if "description" in attrs and attrs["description"]: + is_valid, error_msg = validate_json_content(attrs["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_html" in attrs and attrs["description_html"]: + is_valid, error_msg = validate_html_content(attrs["description_html"]) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + if "description_binary" in attrs and attrs["description_binary"]: + is_valid, error_msg = validate_binary_data(attrs["description_binary"]) + if not is_valid: + raise serializers.ValidationError({"description_binary": error_msg}) + + # Validate assignees are from project if attrs.get("assignee_ids", []): attrs["assignee_ids"] = ProjectMember.objects.filter( project_id=self.context["project_id"], @@ -127,6 +150,51 @@ class IssueCreateSerializer(BaseSerializer): member_id__in=attrs["assignee_ids"], ).values_list("member_id", flat=True) + # Validate labels are from project + if attrs.get("label_ids"): + label_ids = [label.id for label in attrs["label_ids"]] + attrs["label_ids"] = list( + Label.objects.filter( + project_id=self.context.get("project_id"), + id__in=label_ids, + ).values_list("id", flat=True) + ) + + # Check state is from the project only else raise validation error + if ( + attrs.get("state") + and not State.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("state").id, + ).exists() + ): + raise serializers.ValidationError( + "State is not valid please pass a valid state_id" + ) + + # Check parent issue is from workspace as it can be cross workspace + if ( + attrs.get("parent") + and not Issue.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("parent").id, + ).exists() + ): + raise serializers.ValidationError( + "Parent is not valid issue_id please pass a valid issue_id" + ) + + if ( + attrs.get("estimate_point") + and not EstimatePoint.objects.filter( + project_id=self.context.get("project_id"), + pk=attrs.get("estimate_point").id, + ).exists() + ): + raise serializers.ValidationError( + "Estimate point is not valid please pass a valid estimate_point_id" + ) + return attrs def create(self, validated_data): @@ -190,14 +258,14 @@ class IssueCreateSerializer(BaseSerializer): IssueLabel.objects.bulk_create( [ IssueLabel( - label=label, + label_id=label_id, issue=issue, project_id=project_id, workspace_id=workspace_id, created_by_id=created_by_id, updated_by_id=updated_by_id, ) - for label in labels + for label_id in labels ], batch_size=10, ) @@ -243,14 +311,14 @@ class IssueCreateSerializer(BaseSerializer): IssueLabel.objects.bulk_create( [ IssueLabel( - label=label, + label_id=label_id, issue=instance, project_id=project_id, workspace_id=workspace_id, created_by_id=created_by_id, updated_by_id=updated_by_id, ) - for label in labels + for label_id in labels ], batch_size=10, ignore_conflicts=True, @@ -726,7 +794,6 @@ class IssueSerializer(DynamicBaseSerializer): class IssueListDetailSerializer(serializers.Serializer): - def __init__(self, *args, **kwargs): # Extract expand parameter and store it as instance variable self.expand = kwargs.pop("expand", []) or [] diff --git a/apiserver/plane/app/serializers/module.py b/apps/api/plane/app/serializers/module.py similarity index 100% rename from apiserver/plane/app/serializers/module.py rename to apps/api/plane/app/serializers/module.py diff --git a/apiserver/plane/app/serializers/notification.py b/apps/api/plane/app/serializers/notification.py similarity index 100% rename from apiserver/plane/app/serializers/notification.py rename to apps/api/plane/app/serializers/notification.py diff --git a/apiserver/plane/app/serializers/page.py b/apps/api/plane/app/serializers/page.py similarity index 68% rename from apiserver/plane/app/serializers/page.py rename to apps/api/plane/app/serializers/page.py index 1fd2f4d3c..78762e4b4 100644 --- a/apiserver/plane/app/serializers/page.py +++ b/apps/api/plane/app/serializers/page.py @@ -1,8 +1,14 @@ # Third party imports from rest_framework import serializers +import base64 # Module imports from .base import BaseSerializer +from plane.utils.content_validator import ( + validate_binary_data, + validate_html_content, + validate_json_content, +) from plane.db.models import ( Page, PageLog, @@ -186,3 +192,71 @@ class PageVersionDetailSerializer(BaseSerializer): "updated_by", ] read_only_fields = ["workspace", "page"] + + +class PageBinaryUpdateSerializer(serializers.Serializer): + """Serializer for updating page binary description with validation""" + + description_binary = serializers.CharField(required=False, allow_blank=True) + description_html = serializers.CharField(required=False, allow_blank=True) + description = serializers.JSONField(required=False, allow_null=True) + + def validate_description_binary(self, value): + """Validate the base64-encoded binary data""" + if not value: + return value + + try: + # Decode the base64 data + binary_data = base64.b64decode(value) + + # Validate the binary data + is_valid, error_message = validate_binary_data(binary_data) + if not is_valid: + raise serializers.ValidationError( + f"Invalid binary data: {error_message}" + ) + + return binary_data + except Exception as e: + if isinstance(e, serializers.ValidationError): + raise + raise serializers.ValidationError("Failed to decode base64 data") + + def validate_description_html(self, value): + """Validate the HTML content""" + if not value: + return value + + # Use the validation function from utils + is_valid, error_message = validate_html_content(value) + if not is_valid: + raise serializers.ValidationError(error_message) + + return value + + def validate_description(self, value): + """Validate the JSON description""" + if not value: + return value + + # Use the validation function from utils + is_valid, error_message = validate_json_content(value) + if not is_valid: + raise serializers.ValidationError(error_message) + + return value + + def update(self, instance, validated_data): + """Update the page instance with validated data""" + if "description_binary" in validated_data: + instance.description_binary = validated_data.get("description_binary") + + if "description_html" in validated_data: + instance.description_html = validated_data.get("description_html") + + if "description" in validated_data: + instance.description = validated_data.get("description") + + instance.save() + return instance diff --git a/apiserver/plane/app/serializers/project.py b/apps/api/plane/app/serializers/project.py similarity index 62% rename from apiserver/plane/app/serializers/project.py rename to apps/api/plane/app/serializers/project.py index 8d521e8e8..dfa541d9f 100644 --- a/apiserver/plane/app/serializers/project.py +++ b/apps/api/plane/app/serializers/project.py @@ -13,6 +13,11 @@ from plane.db.models import ( DeployBoard, ProjectPublicMember, ) +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, +) class ProjectSerializer(BaseSerializer): @@ -24,55 +29,77 @@ class ProjectSerializer(BaseSerializer): fields = "__all__" read_only_fields = ["workspace", "deleted_at"] + def validate_name(self, name): + project_id = self.instance.id if self.instance else None + workspace_id = self.context["workspace_id"] + + project = Project.objects.filter(name=name, workspace_id=workspace_id) + + if project_id: + project = project.exclude(id=project_id) + + if project.exists(): + raise serializers.ValidationError( + detail="PROJECT_NAME_ALREADY_EXIST", + ) + + return name + + def validate_identifier(self, identifier): + project_id = self.instance.id if self.instance else None + workspace_id = self.context["workspace_id"] + + project = Project.objects.filter( + identifier=identifier, workspace_id=workspace_id + ) + + if project_id: + project = project.exclude(id=project_id) + + if project.exists(): + raise serializers.ValidationError( + detail="PROJECT_IDENTIFIER_ALREADY_EXIST", + ) + + return identifier + + def validate(self, data): + # Validate description content for security + if "description" in data and data["description"]: + # For Project, description might be text field, not JSON + if isinstance(data["description"], dict): + is_valid, error_msg = validate_json_content(data["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_text" in data and data["description_text"]: + is_valid, error_msg = validate_json_content(data["description_text"]) + if not is_valid: + raise serializers.ValidationError({"description_text": error_msg}) + + if "description_html" in data and data["description_html"]: + if isinstance(data["description_html"], dict): + is_valid, error_msg = validate_json_content(data["description_html"]) + else: + is_valid, error_msg = validate_html_content( + str(data["description_html"]) + ) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + return data + def create(self, validated_data): - identifier = validated_data.get("identifier", "").strip().upper() - if identifier == "": - raise serializers.ValidationError(detail="Project Identifier is required") + workspace_id = self.context["workspace_id"] - if ProjectIdentifier.objects.filter( - name=identifier, workspace_id=self.context["workspace_id"] - ).exists(): - raise serializers.ValidationError(detail="Project Identifier is taken") - project = Project.objects.create( - **validated_data, workspace_id=self.context["workspace_id"] - ) - _ = ProjectIdentifier.objects.create( - name=project.identifier, - project=project, - workspace_id=self.context["workspace_id"], + project = Project.objects.create(**validated_data, workspace_id=workspace_id) + + ProjectIdentifier.objects.create( + name=project.identifier, project=project, workspace_id=workspace_id ) + return project - def update(self, instance, validated_data): - identifier = validated_data.get("identifier", "").strip().upper() - - # If identifier is not passed update the project and return - if identifier == "": - project = super().update(instance, validated_data) - return project - - # If no Project Identifier is found create it - project_identifier = ProjectIdentifier.objects.filter( - name=identifier, workspace_id=instance.workspace_id - ).first() - if project_identifier is None: - project = super().update(instance, validated_data) - project_identifier = ProjectIdentifier.objects.filter( - project=project - ).first() - if project_identifier is not None: - project_identifier.name = identifier - project_identifier.save() - return project - # If found check if the project_id to be updated and identifier project id is same - if project_identifier.project_id == instance.id: - # If same pass update - project = super().update(instance, validated_data) - return project - - # If not same fail update - raise serializers.ValidationError(detail="Project Identifier is already taken") - class ProjectLiteSerializer(BaseSerializer): class Meta: @@ -148,8 +175,8 @@ class ProjectMemberAdminSerializer(BaseSerializer): fields = "__all__" -class ProjectMemberRoleSerializer(DynamicBaseSerializer): - original_role = serializers.IntegerField(source='role', read_only=True) +class ProjectMemberRoleSerializer(DynamicBaseSerializer): + original_role = serializers.IntegerField(source="role", read_only=True) class Meta: model = ProjectMember diff --git a/apiserver/plane/app/serializers/state.py b/apps/api/plane/app/serializers/state.py similarity index 100% rename from apiserver/plane/app/serializers/state.py rename to apps/api/plane/app/serializers/state.py diff --git a/apiserver/plane/app/serializers/user.py b/apps/api/plane/app/serializers/user.py similarity index 97% rename from apiserver/plane/app/serializers/user.py rename to apps/api/plane/app/serializers/user.py index c5a3d35df..7b5453568 100644 --- a/apiserver/plane/app/serializers/user.py +++ b/apps/api/plane/app/serializers/user.py @@ -110,7 +110,11 @@ class UserMeSettingsSerializer(BaseSerializer): workspace_member__member=obj.id, workspace_member__is_active=True, ).first() - logo_asset_url = workspace.logo_asset.asset_url if workspace.logo_asset is not None else "" + logo_asset_url = ( + workspace.logo_asset.asset_url + if workspace.logo_asset is not None + else "" + ) return { "last_workspace_id": profile.last_workspace_id, "last_workspace_slug": ( diff --git a/apiserver/plane/app/serializers/view.py b/apps/api/plane/app/serializers/view.py similarity index 99% rename from apiserver/plane/app/serializers/view.py rename to apps/api/plane/app/serializers/view.py index 94ff68de3..bf7ff9727 100644 --- a/apiserver/plane/app/serializers/view.py +++ b/apps/api/plane/app/serializers/view.py @@ -8,7 +8,6 @@ from plane.utils.issue_filters import issue_filters class ViewIssueListSerializer(serializers.Serializer): - def get_assignee_ids(self, instance): return [assignee.assignee_id for assignee in instance.issue_assignee.all()] diff --git a/apiserver/plane/app/serializers/webhook.py b/apps/api/plane/app/serializers/webhook.py similarity index 100% rename from apiserver/plane/app/serializers/webhook.py rename to apps/api/plane/app/serializers/webhook.py diff --git a/apiserver/plane/app/serializers/workspace.py b/apps/api/plane/app/serializers/workspace.py similarity index 90% rename from apiserver/plane/app/serializers/workspace.py rename to apps/api/plane/app/serializers/workspace.py index b4e75a506..ec4c4bf63 100644 --- a/apiserver/plane/app/serializers/workspace.py +++ b/apps/api/plane/app/serializers/workspace.py @@ -24,6 +24,11 @@ from plane.db.models import ( ) from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS from plane.utils.url import contains_url +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, +) # Django imports from django.core.validators import URLValidator @@ -76,7 +81,6 @@ class WorkspaceLiteSerializer(BaseSerializer): class WorkSpaceMemberSerializer(DynamicBaseSerializer): member = UserLiteSerializer(read_only=True) - workspace = WorkspaceLiteSerializer(read_only=True) class Meta: model = WorkspaceMember @@ -93,7 +97,6 @@ class WorkspaceMemberMeSerializer(BaseSerializer): class WorkspaceMemberAdminSerializer(DynamicBaseSerializer): member = UserAdminLiteSerializer(read_only=True) - workspace = WorkspaceLiteSerializer(read_only=True) class Meta: model = WorkspaceMember @@ -314,6 +317,25 @@ class StickySerializer(BaseSerializer): read_only_fields = ["workspace", "owner"] extra_kwargs = {"name": {"required": False}} + def validate(self, data): + # Validate description content for security + if "description" in data and data["description"]: + is_valid, error_msg = validate_json_content(data["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_html" in data and data["description_html"]: + is_valid, error_msg = validate_html_content(data["description_html"]) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + if "description_binary" in data and data["description_binary"]: + is_valid, error_msg = validate_binary_data(data["description_binary"]) + if not is_valid: + raise serializers.ValidationError({"description_binary": error_msg}) + + return data + class WorkspaceUserPreferenceSerializer(BaseSerializer): class Meta: diff --git a/apiserver/plane/app/urls/__init__.py b/apps/api/plane/app/urls/__init__.py similarity index 100% rename from apiserver/plane/app/urls/__init__.py rename to apps/api/plane/app/urls/__init__.py diff --git a/apiserver/plane/app/urls/analytic.py b/apps/api/plane/app/urls/analytic.py similarity index 100% rename from apiserver/plane/app/urls/analytic.py rename to apps/api/plane/app/urls/analytic.py diff --git a/apiserver/plane/app/urls/api.py b/apps/api/plane/app/urls/api.py similarity index 100% rename from apiserver/plane/app/urls/api.py rename to apps/api/plane/app/urls/api.py diff --git a/apiserver/plane/app/urls/asset.py b/apps/api/plane/app/urls/asset.py similarity index 100% rename from apiserver/plane/app/urls/asset.py rename to apps/api/plane/app/urls/asset.py diff --git a/apiserver/plane/app/urls/cycle.py b/apps/api/plane/app/urls/cycle.py similarity index 100% rename from apiserver/plane/app/urls/cycle.py rename to apps/api/plane/app/urls/cycle.py diff --git a/apiserver/plane/app/urls/estimate.py b/apps/api/plane/app/urls/estimate.py similarity index 100% rename from apiserver/plane/app/urls/estimate.py rename to apps/api/plane/app/urls/estimate.py diff --git a/apiserver/plane/app/urls/external.py b/apps/api/plane/app/urls/external.py similarity index 100% rename from apiserver/plane/app/urls/external.py rename to apps/api/plane/app/urls/external.py diff --git a/apiserver/plane/app/urls/intake.py b/apps/api/plane/app/urls/intake.py similarity index 100% rename from apiserver/plane/app/urls/intake.py rename to apps/api/plane/app/urls/intake.py diff --git a/apiserver/plane/app/urls/issue.py b/apps/api/plane/app/urls/issue.py similarity index 100% rename from apiserver/plane/app/urls/issue.py rename to apps/api/plane/app/urls/issue.py diff --git a/apiserver/plane/app/urls/module.py b/apps/api/plane/app/urls/module.py similarity index 100% rename from apiserver/plane/app/urls/module.py rename to apps/api/plane/app/urls/module.py diff --git a/apiserver/plane/app/urls/notification.py b/apps/api/plane/app/urls/notification.py similarity index 100% rename from apiserver/plane/app/urls/notification.py rename to apps/api/plane/app/urls/notification.py diff --git a/apiserver/plane/app/urls/page.py b/apps/api/plane/app/urls/page.py similarity index 100% rename from apiserver/plane/app/urls/page.py rename to apps/api/plane/app/urls/page.py diff --git a/apiserver/plane/app/urls/project.py b/apps/api/plane/app/urls/project.py similarity index 100% rename from apiserver/plane/app/urls/project.py rename to apps/api/plane/app/urls/project.py diff --git a/apiserver/plane/app/urls/search.py b/apps/api/plane/app/urls/search.py similarity index 100% rename from apiserver/plane/app/urls/search.py rename to apps/api/plane/app/urls/search.py diff --git a/apiserver/plane/app/urls/state.py b/apps/api/plane/app/urls/state.py similarity index 100% rename from apiserver/plane/app/urls/state.py rename to apps/api/plane/app/urls/state.py diff --git a/apiserver/plane/app/urls/timezone.py b/apps/api/plane/app/urls/timezone.py similarity index 100% rename from apiserver/plane/app/urls/timezone.py rename to apps/api/plane/app/urls/timezone.py diff --git a/apiserver/plane/app/urls/user.py b/apps/api/plane/app/urls/user.py similarity index 100% rename from apiserver/plane/app/urls/user.py rename to apps/api/plane/app/urls/user.py diff --git a/apiserver/plane/app/urls/views.py b/apps/api/plane/app/urls/views.py similarity index 100% rename from apiserver/plane/app/urls/views.py rename to apps/api/plane/app/urls/views.py diff --git a/apiserver/plane/app/urls/webhook.py b/apps/api/plane/app/urls/webhook.py similarity index 100% rename from apiserver/plane/app/urls/webhook.py rename to apps/api/plane/app/urls/webhook.py diff --git a/apiserver/plane/app/urls/workspace.py b/apps/api/plane/app/urls/workspace.py similarity index 100% rename from apiserver/plane/app/urls/workspace.py rename to apps/api/plane/app/urls/workspace.py diff --git a/apiserver/plane/app/views/__init__.py b/apps/api/plane/app/views/__init__.py similarity index 100% rename from apiserver/plane/app/views/__init__.py rename to apps/api/plane/app/views/__init__.py diff --git a/apiserver/plane/app/views/analytic/advance.py b/apps/api/plane/app/views/analytic/advance.py similarity index 98% rename from apiserver/plane/app/views/analytic/advance.py rename to apps/api/plane/app/views/analytic/advance.py index 8a2aea90b..c690fbe7d 100644 --- a/apiserver/plane/app/views/analytic/advance.py +++ b/apps/api/plane/app/views/analytic/advance.py @@ -160,7 +160,8 @@ class AdvanceAnalyticsStatsEndpoint(AdvanceAnalyticsBaseView): ) return ( - base_queryset.values("project_id", "project__name").annotate( + base_queryset.values("project_id", "project__name") + .annotate( cancelled_work_items=Count("id", filter=Q(state__group="cancelled")), completed_work_items=Count("id", filter=Q(state__group="completed")), backlog_work_items=Count("id", filter=Q(state__group="backlog")), @@ -173,8 +174,7 @@ class AdvanceAnalyticsStatsEndpoint(AdvanceAnalyticsBaseView): def get_work_items_stats(self) -> Dict[str, Dict[str, int]]: base_queryset = Issue.issue_objects.filter(**self.filters["base_filters"]) return ( - base_queryset - .values("project_id", "project__name") + base_queryset.values("project_id", "project__name") .annotate( cancelled_work_items=Count("id", filter=Q(state__group="cancelled")), completed_work_items=Count("id", filter=Q(state__group="completed")), diff --git a/apiserver/plane/app/views/analytic/base.py b/apps/api/plane/app/views/analytic/base.py similarity index 100% rename from apiserver/plane/app/views/analytic/base.py rename to apps/api/plane/app/views/analytic/base.py diff --git a/apiserver/plane/app/views/analytic/project_analytics.py b/apps/api/plane/app/views/analytic/project_analytics.py similarity index 100% rename from apiserver/plane/app/views/analytic/project_analytics.py rename to apps/api/plane/app/views/analytic/project_analytics.py diff --git a/apiserver/plane/app/views/api.py b/apps/api/plane/app/views/api.py similarity index 100% rename from apiserver/plane/app/views/api.py rename to apps/api/plane/app/views/api.py diff --git a/apiserver/plane/app/views/asset/base.py b/apps/api/plane/app/views/asset/base.py similarity index 100% rename from apiserver/plane/app/views/asset/base.py rename to apps/api/plane/app/views/asset/base.py diff --git a/apiserver/plane/app/views/asset/v2.py b/apps/api/plane/app/views/asset/v2.py similarity index 99% rename from apiserver/plane/app/views/asset/v2.py rename to apps/api/plane/app/views/asset/v2.py index 5994ffd8c..7e0c14fdd 100644 --- a/apiserver/plane/app/views/asset/v2.py +++ b/apps/api/plane/app/views/asset/v2.py @@ -740,7 +740,8 @@ class WorkspaceAssetDownloadEndpoint(BaseAPIView): storage = S3Storage(request=request) signed_url = storage.generate_presigned_url( object_name=asset.asset.name, - disposition=f"attachment; filename={asset.asset.name}", + disposition="attachment", + filename=asset.attributes.get("name", uuid.uuid4().hex), ) return HttpResponseRedirect(signed_url) @@ -767,7 +768,8 @@ class ProjectAssetDownloadEndpoint(BaseAPIView): storage = S3Storage(request=request) signed_url = storage.generate_presigned_url( object_name=asset.asset.name, - disposition=f"attachment; filename={asset.asset.name}", + disposition="attachment", + filename=asset.attributes.get("name", uuid.uuid4().hex), ) return HttpResponseRedirect(signed_url) diff --git a/apiserver/plane/app/views/base.py b/apps/api/plane/app/views/base.py similarity index 100% rename from apiserver/plane/app/views/base.py rename to apps/api/plane/app/views/base.py diff --git a/apiserver/plane/app/views/cycle/archive.py b/apps/api/plane/app/views/cycle/archive.py similarity index 100% rename from apiserver/plane/app/views/cycle/archive.py rename to apps/api/plane/app/views/cycle/archive.py diff --git a/apiserver/plane/app/views/cycle/base.py b/apps/api/plane/app/views/cycle/base.py similarity index 100% rename from apiserver/plane/app/views/cycle/base.py rename to apps/api/plane/app/views/cycle/base.py diff --git a/apiserver/plane/app/views/cycle/issue.py b/apps/api/plane/app/views/cycle/issue.py similarity index 100% rename from apiserver/plane/app/views/cycle/issue.py rename to apps/api/plane/app/views/cycle/issue.py diff --git a/apiserver/plane/app/views/error_404.py b/apps/api/plane/app/views/error_404.py similarity index 100% rename from apiserver/plane/app/views/error_404.py rename to apps/api/plane/app/views/error_404.py diff --git a/apiserver/plane/app/views/estimate/base.py b/apps/api/plane/app/views/estimate/base.py similarity index 100% rename from apiserver/plane/app/views/estimate/base.py rename to apps/api/plane/app/views/estimate/base.py diff --git a/apiserver/plane/app/views/exporter/base.py b/apps/api/plane/app/views/exporter/base.py similarity index 100% rename from apiserver/plane/app/views/exporter/base.py rename to apps/api/plane/app/views/exporter/base.py diff --git a/apiserver/plane/app/views/external/base.py b/apps/api/plane/app/views/external/base.py similarity index 100% rename from apiserver/plane/app/views/external/base.py rename to apps/api/plane/app/views/external/base.py diff --git a/apiserver/plane/app/views/intake/base.py b/apps/api/plane/app/views/intake/base.py similarity index 100% rename from apiserver/plane/app/views/intake/base.py rename to apps/api/plane/app/views/intake/base.py diff --git a/apiserver/plane/app/views/issue/activity.py b/apps/api/plane/app/views/issue/activity.py similarity index 100% rename from apiserver/plane/app/views/issue/activity.py rename to apps/api/plane/app/views/issue/activity.py diff --git a/apiserver/plane/app/views/issue/archive.py b/apps/api/plane/app/views/issue/archive.py similarity index 100% rename from apiserver/plane/app/views/issue/archive.py rename to apps/api/plane/app/views/issue/archive.py diff --git a/apiserver/plane/app/views/issue/attachment.py b/apps/api/plane/app/views/issue/attachment.py similarity index 100% rename from apiserver/plane/app/views/issue/attachment.py rename to apps/api/plane/app/views/issue/attachment.py diff --git a/apiserver/plane/app/views/issue/base.py b/apps/api/plane/app/views/issue/base.py similarity index 100% rename from apiserver/plane/app/views/issue/base.py rename to apps/api/plane/app/views/issue/base.py diff --git a/apiserver/plane/app/views/issue/comment.py b/apps/api/plane/app/views/issue/comment.py similarity index 100% rename from apiserver/plane/app/views/issue/comment.py rename to apps/api/plane/app/views/issue/comment.py diff --git a/apiserver/plane/app/views/issue/label.py b/apps/api/plane/app/views/issue/label.py similarity index 100% rename from apiserver/plane/app/views/issue/label.py rename to apps/api/plane/app/views/issue/label.py diff --git a/apiserver/plane/app/views/issue/link.py b/apps/api/plane/app/views/issue/link.py similarity index 100% rename from apiserver/plane/app/views/issue/link.py rename to apps/api/plane/app/views/issue/link.py diff --git a/apiserver/plane/app/views/issue/reaction.py b/apps/api/plane/app/views/issue/reaction.py similarity index 100% rename from apiserver/plane/app/views/issue/reaction.py rename to apps/api/plane/app/views/issue/reaction.py diff --git a/apiserver/plane/app/views/issue/relation.py b/apps/api/plane/app/views/issue/relation.py similarity index 100% rename from apiserver/plane/app/views/issue/relation.py rename to apps/api/plane/app/views/issue/relation.py diff --git a/apiserver/plane/app/views/issue/sub_issue.py b/apps/api/plane/app/views/issue/sub_issue.py similarity index 100% rename from apiserver/plane/app/views/issue/sub_issue.py rename to apps/api/plane/app/views/issue/sub_issue.py diff --git a/apiserver/plane/app/views/issue/subscriber.py b/apps/api/plane/app/views/issue/subscriber.py similarity index 100% rename from apiserver/plane/app/views/issue/subscriber.py rename to apps/api/plane/app/views/issue/subscriber.py diff --git a/apiserver/plane/app/views/issue/version.py b/apps/api/plane/app/views/issue/version.py similarity index 100% rename from apiserver/plane/app/views/issue/version.py rename to apps/api/plane/app/views/issue/version.py diff --git a/apiserver/plane/app/views/module/archive.py b/apps/api/plane/app/views/module/archive.py similarity index 100% rename from apiserver/plane/app/views/module/archive.py rename to apps/api/plane/app/views/module/archive.py diff --git a/apiserver/plane/app/views/module/base.py b/apps/api/plane/app/views/module/base.py similarity index 100% rename from apiserver/plane/app/views/module/base.py rename to apps/api/plane/app/views/module/base.py diff --git a/apiserver/plane/app/views/module/issue.py b/apps/api/plane/app/views/module/issue.py similarity index 100% rename from apiserver/plane/app/views/module/issue.py rename to apps/api/plane/app/views/module/issue.py diff --git a/apiserver/plane/app/views/notification/base.py b/apps/api/plane/app/views/notification/base.py similarity index 99% rename from apiserver/plane/app/views/notification/base.py rename to apps/api/plane/app/views/notification/base.py index d2aa1a02d..e84cf4d29 100644 --- a/apiserver/plane/app/views/notification/base.py +++ b/apps/api/plane/app/views/notification/base.py @@ -37,7 +37,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator): workspace__slug=self.kwargs.get("slug"), receiver_id=self.request.user.id, ) - .select_related("workspace", "project," "triggered_by", "receiver") + .select_related("workspace", "project", "triggered_by", "receiver") ) @allow_permission( diff --git a/apiserver/plane/app/views/page/base.py b/apps/api/plane/app/views/page/base.py similarity index 96% rename from apiserver/plane/app/views/page/base.py rename to apps/api/plane/app/views/page/base.py index 26e9223b8..96de81abf 100644 --- a/apiserver/plane/app/views/page/base.py +++ b/apps/api/plane/app/views/page/base.py @@ -25,6 +25,7 @@ from plane.app.serializers import ( PageSerializer, SubPageSerializer, PageDetailSerializer, + PageBinaryUpdateSerializer, ) from plane.db.models import ( Page, @@ -40,7 +41,7 @@ from ..base import BaseAPIView, BaseViewSet from plane.bgtasks.page_transaction_task import page_transaction from plane.bgtasks.page_version_task import page_version from plane.bgtasks.recent_visited_task import recent_visited_task -from plane.bgtasks.copy_s3_object import copy_s3_objects +from plane.bgtasks.copy_s3_object import copy_s3_objects_of_description_and_assets def unarchive_archive_page_and_descendants(page_id, archived_at): @@ -538,32 +539,27 @@ class PagesDescriptionViewSet(BaseViewSet): {"description_html": page.description_html}, cls=DjangoJSONEncoder ) - # Get the base64 data from the request - base64_data = request.data.get("description_binary") - - # If base64 data is provided - if base64_data: - # Decode the base64 data to bytes - new_binary_data = base64.b64decode(base64_data) - # capture the page transaction + # Use serializer for validation and update + serializer = PageBinaryUpdateSerializer(page, data=request.data, partial=True) + if serializer.is_valid(): + # Capture the page transaction if request.data.get("description_html"): page_transaction.delay( new_value=request.data, old_value=existing_instance, page_id=pk ) - # Store the updated binary data - page.description_binary = new_binary_data - page.description_html = request.data.get("description_html") - page.description = request.data.get("description") - page.save() - # Return a success response + + # Update the page using serializer + updated_page = serializer.save() + + # Run background tasks page_version.delay( - page_id=page.id, + page_id=updated_page.id, existing_instance=existing_instance, user_id=request.user.id, ) return Response({"message": "Updated successfully"}) else: - return Response({"error": "No binary data provided"}) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class PageDuplicateEndpoint(BaseAPIView): @@ -606,7 +602,7 @@ class PageDuplicateEndpoint(BaseAPIView): ) # Copy the s3 objects uploaded in the page - copy_s3_objects.delay( + copy_s3_objects_of_description_and_assets.delay( entity_name="PAGE", entity_identifier=page.id, project_id=project_id, diff --git a/apiserver/plane/app/views/page/version.py b/apps/api/plane/app/views/page/version.py similarity index 100% rename from apiserver/plane/app/views/page/version.py rename to apps/api/plane/app/views/page/version.py diff --git a/apiserver/plane/app/views/project/base.py b/apps/api/plane/app/views/project/base.py similarity index 70% rename from apiserver/plane/app/views/project/base.py rename to apps/api/plane/app/views/project/base.py index 2728bf4de..1da2aa84b 100644 --- a/apiserver/plane/app/views/project/base.py +++ b/apps/api/plane/app/views/project/base.py @@ -239,205 +239,165 @@ class ProjectViewSet(BaseViewSet): @allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE") def create(self, request, slug): - try: - workspace = Workspace.objects.get(slug=slug) + workspace = Workspace.objects.get(slug=slug) - serializer = ProjectSerializer( - data={**request.data}, context={"workspace_id": workspace.id} + serializer = ProjectSerializer( + data={**request.data}, context={"workspace_id": workspace.id} + ) + if serializer.is_valid(): + serializer.save() + + # Add the user as Administrator to the project + _ = ProjectMember.objects.create( + project_id=serializer.data["id"], member=request.user, role=20 + ) + # Also create the issue property for the user + _ = IssueUserProperty.objects.create( + project_id=serializer.data["id"], user=request.user ) - if serializer.is_valid(): - serializer.save() - # Add the user as Administrator to the project - _ = ProjectMember.objects.create( - project_id=serializer.data["id"], member=request.user, role=20 + if serializer.data["project_lead"] is not None and str( + serializer.data["project_lead"] + ) != str(request.user.id): + ProjectMember.objects.create( + project_id=serializer.data["id"], + member_id=serializer.data["project_lead"], + role=20, ) # Also create the issue property for the user - _ = IssueUserProperty.objects.create( - project_id=serializer.data["id"], user=request.user + IssueUserProperty.objects.create( + project_id=serializer.data["id"], + user_id=serializer.data["project_lead"], ) - if serializer.data["project_lead"] is not None and str( - serializer.data["project_lead"] - ) != str(request.user.id): - ProjectMember.objects.create( - project_id=serializer.data["id"], - member_id=serializer.data["project_lead"], - role=20, - ) - # Also create the issue property for the user - IssueUserProperty.objects.create( - project_id=serializer.data["id"], - user_id=serializer.data["project_lead"], - ) - - # Default states - states = [ - { - "name": "Backlog", - "color": "#60646C", - "sequence": 15000, - "group": "backlog", - "default": True, - }, - { - "name": "Todo", - "color": "#60646C", - "sequence": 25000, - "group": "unstarted", - }, - { - "name": "In Progress", - "color": "#F59E0B", - "sequence": 35000, - "group": "started", - }, - { - "name": "Done", - "color": "#46A758", - "sequence": 45000, - "group": "completed", - }, - { - "name": "Cancelled", - "color": "#9AA4BC", - "sequence": 55000, - "group": "cancelled", - }, - ] - - State.objects.bulk_create( - [ - State( - name=state["name"], - color=state["color"], - project=serializer.instance, - sequence=state["sequence"], - workspace=serializer.instance.workspace, - group=state["group"], - default=state.get("default", False), - created_by=request.user, - ) - for state in states - ] - ) - - project = self.get_queryset().filter(pk=serializer.data["id"]).first() - - # Create the model activity - model_activity.delay( - model_name="project", - model_id=str(project.id), - requested_data=request.data, - current_instance=None, - actor_id=request.user.id, - slug=slug, - origin=base_host(request=request, is_app=True), - ) - - serializer = ProjectListSerializer(project) - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - except IntegrityError as e: - if "already exists" in str(e): - return Response( - { - "name": "The project name is already taken", - "code": "PROJECT_NAME_ALREADY_EXIST", - }, - status=status.HTTP_409_CONFLICT, - ) - except Workspace.DoesNotExist: - return Response( - {"error": "Workspace does not exist"}, status=status.HTTP_404_NOT_FOUND - ) - except serializers.ValidationError: - return Response( + # Default states + states = [ { - "identifier": "The project identifier is already taken", - "code": "PROJECT_IDENTIFIER_ALREADY_EXIST", + "name": "Backlog", + "color": "#60646C", + "sequence": 15000, + "group": "backlog", + "default": True, }, - status=status.HTTP_409_CONFLICT, + { + "name": "Todo", + "color": "#60646C", + "sequence": 25000, + "group": "unstarted", + }, + { + "name": "In Progress", + "color": "#F59E0B", + "sequence": 35000, + "group": "started", + }, + { + "name": "Done", + "color": "#46A758", + "sequence": 45000, + "group": "completed", + }, + { + "name": "Cancelled", + "color": "#9AA4BC", + "sequence": 55000, + "group": "cancelled", + }, + ] + + State.objects.bulk_create( + [ + State( + name=state["name"], + color=state["color"], + project=serializer.instance, + sequence=state["sequence"], + workspace=serializer.instance.workspace, + group=state["group"], + default=state.get("default", False), + created_by=request.user, + ) + for state in states + ] ) + project = self.get_queryset().filter(pk=serializer.data["id"]).first() + + # Create the model activity + model_activity.delay( + model_name="project", + model_id=str(project.id), + requested_data=request.data, + current_instance=None, + actor_id=request.user.id, + slug=slug, + origin=base_host(request=request, is_app=True), + ) + + serializer = ProjectListSerializer(project) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + def partial_update(self, request, slug, pk=None): - try: - if not ProjectMember.objects.filter( - member=request.user, - workspace__slug=slug, - project_id=pk, - role=20, - is_active=True, - ).exists(): - return Response( - {"error": "You don't have the required permissions."}, - status=status.HTTP_403_FORBIDDEN, - ) - - workspace = Workspace.objects.get(slug=slug) - - project = Project.objects.get(pk=pk) - intake_view = request.data.get("inbox_view", project.intake_view) - current_instance = json.dumps( - ProjectSerializer(project).data, cls=DjangoJSONEncoder - ) - if project.archived_at: - return Response( - {"error": "Archived projects cannot be updated"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - serializer = ProjectSerializer( - project, - data={**request.data, "intake_view": intake_view}, - context={"workspace_id": workspace.id}, - partial=True, - ) - - if serializer.is_valid(): - serializer.save() - if intake_view: - intake = Intake.objects.filter( - project=project, is_default=True - ).first() - if not intake: - Intake.objects.create( - name=f"{project.name} Intake", - project=project, - is_default=True, - ) - - project = self.get_queryset().filter(pk=serializer.data["id"]).first() - - model_activity.delay( - model_name="project", - model_id=str(project.id), - requested_data=request.data, - current_instance=current_instance, - actor_id=request.user.id, - slug=slug, - origin=base_host(request=request, is_app=True), - ) - serializer = ProjectListSerializer(project) - return Response(serializer.data, status=status.HTTP_200_OK) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - - except IntegrityError as e: - if "already exists" in str(e): - return Response( - {"name": "The project name is already taken"}, - status=status.HTTP_409_CONFLICT, - ) - except (Project.DoesNotExist, Workspace.DoesNotExist): + # try: + if not ProjectMember.objects.filter( + member=request.user, + workspace__slug=slug, + project_id=pk, + role=20, + is_active=True, + ).exists(): return Response( - {"error": "Project does not exist"}, status=status.HTTP_404_NOT_FOUND + {"error": "You don't have the required permissions."}, + status=status.HTTP_403_FORBIDDEN, ) - except serializers.ValidationError: + + workspace = Workspace.objects.get(slug=slug) + + project = Project.objects.get(pk=pk) + intake_view = request.data.get("inbox_view", project.intake_view) + current_instance = json.dumps( + ProjectSerializer(project).data, cls=DjangoJSONEncoder + ) + if project.archived_at: return Response( - {"identifier": "The project identifier is already taken"}, - status=status.HTTP_409_CONFLICT, + {"error": "Archived projects cannot be updated"}, + status=status.HTTP_400_BAD_REQUEST, ) + serializer = ProjectSerializer( + project, + data={**request.data, "intake_view": intake_view}, + context={"workspace_id": workspace.id}, + partial=True, + ) + + if serializer.is_valid(): + serializer.save() + if intake_view: + intake = Intake.objects.filter(project=project, is_default=True).first() + if not intake: + Intake.objects.create( + name=f"{project.name} Intake", + project=project, + is_default=True, + ) + + project = self.get_queryset().filter(pk=serializer.data["id"]).first() + + model_activity.delay( + model_name="project", + model_id=str(project.id), + requested_data=request.data, + current_instance=current_instance, + actor_id=request.user.id, + slug=slug, + origin=base_host(request=request, is_app=True), + ) + serializer = ProjectListSerializer(project) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + def destroy(self, request, slug, pk): if ( WorkspaceMember.objects.filter( diff --git a/apiserver/plane/app/views/project/invite.py b/apps/api/plane/app/views/project/invite.py similarity index 100% rename from apiserver/plane/app/views/project/invite.py rename to apps/api/plane/app/views/project/invite.py diff --git a/apiserver/plane/app/views/project/member.py b/apps/api/plane/app/views/project/member.py similarity index 100% rename from apiserver/plane/app/views/project/member.py rename to apps/api/plane/app/views/project/member.py diff --git a/apiserver/plane/app/views/search/base.py b/apps/api/plane/app/views/search/base.py similarity index 100% rename from apiserver/plane/app/views/search/base.py rename to apps/api/plane/app/views/search/base.py diff --git a/apiserver/plane/app/views/search/issue.py b/apps/api/plane/app/views/search/issue.py similarity index 100% rename from apiserver/plane/app/views/search/issue.py rename to apps/api/plane/app/views/search/issue.py diff --git a/apiserver/plane/app/views/state/base.py b/apps/api/plane/app/views/state/base.py similarity index 100% rename from apiserver/plane/app/views/state/base.py rename to apps/api/plane/app/views/state/base.py diff --git a/apiserver/plane/app/views/timezone/base.py b/apps/api/plane/app/views/timezone/base.py similarity index 99% rename from apiserver/plane/app/views/timezone/base.py rename to apps/api/plane/app/views/timezone/base.py index 21d1d3560..bb3f10c0b 100644 --- a/apiserver/plane/app/views/timezone/base.py +++ b/apps/api/plane/app/views/timezone/base.py @@ -116,6 +116,7 @@ class TimezoneEndpoint(APIView): ("Astrakhan", "Europe/Astrakhan"), # UTC+04:00 ("Tbilisi", "Asia/Tbilisi"), # UTC+04:00 ("Mauritius", "Indian/Mauritius"), # UTC+04:00 + ("Kabul", "Asia/Kabul"), # UTC+04:30 ("Islamabad", "Asia/Karachi"), # UTC+05:00 ("Karachi", "Asia/Karachi"), # UTC+05:00 ("Tashkent", "Asia/Tashkent"), # UTC+05:00 diff --git a/apiserver/plane/app/views/user/base.py b/apps/api/plane/app/views/user/base.py similarity index 100% rename from apiserver/plane/app/views/user/base.py rename to apps/api/plane/app/views/user/base.py diff --git a/apiserver/plane/app/views/view/base.py b/apps/api/plane/app/views/view/base.py similarity index 100% rename from apiserver/plane/app/views/view/base.py rename to apps/api/plane/app/views/view/base.py diff --git a/apiserver/plane/app/views/webhook/base.py b/apps/api/plane/app/views/webhook/base.py similarity index 100% rename from apiserver/plane/app/views/webhook/base.py rename to apps/api/plane/app/views/webhook/base.py diff --git a/apiserver/plane/app/views/workspace/base.py b/apps/api/plane/app/views/workspace/base.py similarity index 100% rename from apiserver/plane/app/views/workspace/base.py rename to apps/api/plane/app/views/workspace/base.py diff --git a/apiserver/plane/app/views/workspace/cycle.py b/apps/api/plane/app/views/workspace/cycle.py similarity index 100% rename from apiserver/plane/app/views/workspace/cycle.py rename to apps/api/plane/app/views/workspace/cycle.py diff --git a/apiserver/plane/app/views/workspace/draft.py b/apps/api/plane/app/views/workspace/draft.py similarity index 100% rename from apiserver/plane/app/views/workspace/draft.py rename to apps/api/plane/app/views/workspace/draft.py diff --git a/apiserver/plane/app/views/workspace/estimate.py b/apps/api/plane/app/views/workspace/estimate.py similarity index 100% rename from apiserver/plane/app/views/workspace/estimate.py rename to apps/api/plane/app/views/workspace/estimate.py diff --git a/apiserver/plane/app/views/workspace/favorite.py b/apps/api/plane/app/views/workspace/favorite.py similarity index 100% rename from apiserver/plane/app/views/workspace/favorite.py rename to apps/api/plane/app/views/workspace/favorite.py diff --git a/apiserver/plane/app/views/workspace/home.py b/apps/api/plane/app/views/workspace/home.py similarity index 100% rename from apiserver/plane/app/views/workspace/home.py rename to apps/api/plane/app/views/workspace/home.py diff --git a/apiserver/plane/app/views/workspace/invite.py b/apps/api/plane/app/views/workspace/invite.py similarity index 99% rename from apiserver/plane/app/views/workspace/invite.py rename to apps/api/plane/app/views/workspace/invite.py index a60dd3fc9..84ef7c361 100644 --- a/apiserver/plane/app/views/workspace/invite.py +++ b/apps/api/plane/app/views/workspace/invite.py @@ -80,7 +80,7 @@ class WorkspaceInvitationsViewset(BaseViewSet): workspace_id=workspace.id, member__email__in=[email.get("email") for email in emails], is_active=True, - ).select_related("member", "workspace", "workspace__owner") + ).select_related("member", "member__avatar_asset") if workspace_members: return Response( diff --git a/apiserver/plane/app/views/workspace/label.py b/apps/api/plane/app/views/workspace/label.py similarity index 100% rename from apiserver/plane/app/views/workspace/label.py rename to apps/api/plane/app/views/workspace/label.py diff --git a/apiserver/plane/app/views/workspace/member.py b/apps/api/plane/app/views/workspace/member.py similarity index 98% rename from apiserver/plane/app/views/workspace/member.py rename to apps/api/plane/app/views/workspace/member.py index eda7c34fd..7743ff4cd 100644 --- a/apiserver/plane/app/views/workspace/member.py +++ b/apps/api/plane/app/views/workspace/member.py @@ -33,9 +33,8 @@ class WorkSpaceMemberViewSet(BaseViewSet): return self.filter_queryset( super() .get_queryset() - .filter(workspace__slug=self.kwargs.get("slug"), is_active=True) - .select_related("workspace", "workspace__owner") - .select_related("member") + .filter(workspace__slug=self.kwargs.get("slug")) + .select_related("member", "member__avatar_asset") ) @allow_permission( diff --git a/apiserver/plane/app/views/workspace/module.py b/apps/api/plane/app/views/workspace/module.py similarity index 100% rename from apiserver/plane/app/views/workspace/module.py rename to apps/api/plane/app/views/workspace/module.py diff --git a/apiserver/plane/app/views/workspace/quick_link.py b/apps/api/plane/app/views/workspace/quick_link.py similarity index 100% rename from apiserver/plane/app/views/workspace/quick_link.py rename to apps/api/plane/app/views/workspace/quick_link.py diff --git a/apiserver/plane/app/views/workspace/recent_visit.py b/apps/api/plane/app/views/workspace/recent_visit.py similarity index 100% rename from apiserver/plane/app/views/workspace/recent_visit.py rename to apps/api/plane/app/views/workspace/recent_visit.py diff --git a/apiserver/plane/app/views/workspace/state.py b/apps/api/plane/app/views/workspace/state.py similarity index 100% rename from apiserver/plane/app/views/workspace/state.py rename to apps/api/plane/app/views/workspace/state.py diff --git a/apiserver/plane/app/views/workspace/sticky.py b/apps/api/plane/app/views/workspace/sticky.py similarity index 100% rename from apiserver/plane/app/views/workspace/sticky.py rename to apps/api/plane/app/views/workspace/sticky.py diff --git a/apiserver/plane/app/views/workspace/user.py b/apps/api/plane/app/views/workspace/user.py similarity index 100% rename from apiserver/plane/app/views/workspace/user.py rename to apps/api/plane/app/views/workspace/user.py diff --git a/apiserver/plane/app/views/workspace/user_preference.py b/apps/api/plane/app/views/workspace/user_preference.py similarity index 100% rename from apiserver/plane/app/views/workspace/user_preference.py rename to apps/api/plane/app/views/workspace/user_preference.py diff --git a/apiserver/plane/asgi.py b/apps/api/plane/asgi.py similarity index 100% rename from apiserver/plane/asgi.py rename to apps/api/plane/asgi.py diff --git a/apiserver/plane/authentication/__init__.py b/apps/api/plane/authentication/__init__.py similarity index 100% rename from apiserver/plane/authentication/__init__.py rename to apps/api/plane/authentication/__init__.py diff --git a/apiserver/plane/authentication/adapter/__init__.py b/apps/api/plane/authentication/adapter/__init__.py similarity index 100% rename from apiserver/plane/authentication/adapter/__init__.py rename to apps/api/plane/authentication/adapter/__init__.py diff --git a/apiserver/plane/authentication/adapter/base.py b/apps/api/plane/authentication/adapter/base.py similarity index 100% rename from apiserver/plane/authentication/adapter/base.py rename to apps/api/plane/authentication/adapter/base.py diff --git a/apiserver/plane/authentication/adapter/credential.py b/apps/api/plane/authentication/adapter/credential.py similarity index 100% rename from apiserver/plane/authentication/adapter/credential.py rename to apps/api/plane/authentication/adapter/credential.py diff --git a/apiserver/plane/authentication/adapter/error.py b/apps/api/plane/authentication/adapter/error.py similarity index 100% rename from apiserver/plane/authentication/adapter/error.py rename to apps/api/plane/authentication/adapter/error.py diff --git a/apiserver/plane/authentication/adapter/exception.py b/apps/api/plane/authentication/adapter/exception.py similarity index 100% rename from apiserver/plane/authentication/adapter/exception.py rename to apps/api/plane/authentication/adapter/exception.py diff --git a/apiserver/plane/authentication/adapter/oauth.py b/apps/api/plane/authentication/adapter/oauth.py similarity index 100% rename from apiserver/plane/authentication/adapter/oauth.py rename to apps/api/plane/authentication/adapter/oauth.py diff --git a/apiserver/plane/authentication/apps.py b/apps/api/plane/authentication/apps.py similarity index 100% rename from apiserver/plane/authentication/apps.py rename to apps/api/plane/authentication/apps.py diff --git a/apiserver/plane/authentication/middleware/__init__.py b/apps/api/plane/authentication/middleware/__init__.py similarity index 100% rename from apiserver/plane/authentication/middleware/__init__.py rename to apps/api/plane/authentication/middleware/__init__.py diff --git a/apiserver/plane/authentication/middleware/session.py b/apps/api/plane/authentication/middleware/session.py similarity index 100% rename from apiserver/plane/authentication/middleware/session.py rename to apps/api/plane/authentication/middleware/session.py diff --git a/apiserver/plane/authentication/provider/__init__.py b/apps/api/plane/authentication/provider/__init__.py similarity index 100% rename from apiserver/plane/authentication/provider/__init__.py rename to apps/api/plane/authentication/provider/__init__.py diff --git a/apiserver/plane/authentication/provider/credentials/__init__.py b/apps/api/plane/authentication/provider/credentials/__init__.py similarity index 100% rename from apiserver/plane/authentication/provider/credentials/__init__.py rename to apps/api/plane/authentication/provider/credentials/__init__.py diff --git a/apiserver/plane/authentication/provider/credentials/email.py b/apps/api/plane/authentication/provider/credentials/email.py similarity index 100% rename from apiserver/plane/authentication/provider/credentials/email.py rename to apps/api/plane/authentication/provider/credentials/email.py diff --git a/apiserver/plane/authentication/provider/credentials/magic_code.py b/apps/api/plane/authentication/provider/credentials/magic_code.py similarity index 100% rename from apiserver/plane/authentication/provider/credentials/magic_code.py rename to apps/api/plane/authentication/provider/credentials/magic_code.py diff --git a/apiserver/plane/authentication/provider/oauth/__init__.py b/apps/api/plane/authentication/provider/oauth/__init__.py similarity index 100% rename from apiserver/plane/authentication/provider/oauth/__init__.py rename to apps/api/plane/authentication/provider/oauth/__init__.py diff --git a/apiserver/plane/authentication/provider/oauth/github.py b/apps/api/plane/authentication/provider/oauth/github.py similarity index 100% rename from apiserver/plane/authentication/provider/oauth/github.py rename to apps/api/plane/authentication/provider/oauth/github.py diff --git a/apiserver/plane/authentication/provider/oauth/gitlab.py b/apps/api/plane/authentication/provider/oauth/gitlab.py similarity index 100% rename from apiserver/plane/authentication/provider/oauth/gitlab.py rename to apps/api/plane/authentication/provider/oauth/gitlab.py diff --git a/apiserver/plane/authentication/provider/oauth/google.py b/apps/api/plane/authentication/provider/oauth/google.py similarity index 100% rename from apiserver/plane/authentication/provider/oauth/google.py rename to apps/api/plane/authentication/provider/oauth/google.py diff --git a/apiserver/plane/authentication/rate_limit.py b/apps/api/plane/authentication/rate_limit.py similarity index 100% rename from apiserver/plane/authentication/rate_limit.py rename to apps/api/plane/authentication/rate_limit.py diff --git a/apiserver/plane/authentication/session.py b/apps/api/plane/authentication/session.py similarity index 100% rename from apiserver/plane/authentication/session.py rename to apps/api/plane/authentication/session.py diff --git a/apiserver/plane/authentication/urls.py b/apps/api/plane/authentication/urls.py similarity index 100% rename from apiserver/plane/authentication/urls.py rename to apps/api/plane/authentication/urls.py diff --git a/apiserver/plane/authentication/utils/host.py b/apps/api/plane/authentication/utils/host.py similarity index 100% rename from apiserver/plane/authentication/utils/host.py rename to apps/api/plane/authentication/utils/host.py diff --git a/apiserver/plane/authentication/utils/login.py b/apps/api/plane/authentication/utils/login.py similarity index 100% rename from apiserver/plane/authentication/utils/login.py rename to apps/api/plane/authentication/utils/login.py diff --git a/apiserver/plane/authentication/utils/redirection_path.py b/apps/api/plane/authentication/utils/redirection_path.py similarity index 100% rename from apiserver/plane/authentication/utils/redirection_path.py rename to apps/api/plane/authentication/utils/redirection_path.py diff --git a/apiserver/plane/authentication/utils/user_auth_workflow.py b/apps/api/plane/authentication/utils/user_auth_workflow.py similarity index 100% rename from apiserver/plane/authentication/utils/user_auth_workflow.py rename to apps/api/plane/authentication/utils/user_auth_workflow.py diff --git a/apiserver/plane/authentication/utils/workspace_project_join.py b/apps/api/plane/authentication/utils/workspace_project_join.py similarity index 100% rename from apiserver/plane/authentication/utils/workspace_project_join.py rename to apps/api/plane/authentication/utils/workspace_project_join.py diff --git a/apiserver/plane/authentication/views/__init__.py b/apps/api/plane/authentication/views/__init__.py similarity index 100% rename from apiserver/plane/authentication/views/__init__.py rename to apps/api/plane/authentication/views/__init__.py diff --git a/apiserver/plane/authentication/views/app/check.py b/apps/api/plane/authentication/views/app/check.py similarity index 100% rename from apiserver/plane/authentication/views/app/check.py rename to apps/api/plane/authentication/views/app/check.py diff --git a/apiserver/plane/authentication/views/app/email.py b/apps/api/plane/authentication/views/app/email.py similarity index 100% rename from apiserver/plane/authentication/views/app/email.py rename to apps/api/plane/authentication/views/app/email.py diff --git a/apiserver/plane/authentication/views/app/github.py b/apps/api/plane/authentication/views/app/github.py similarity index 100% rename from apiserver/plane/authentication/views/app/github.py rename to apps/api/plane/authentication/views/app/github.py diff --git a/apiserver/plane/authentication/views/app/gitlab.py b/apps/api/plane/authentication/views/app/gitlab.py similarity index 100% rename from apiserver/plane/authentication/views/app/gitlab.py rename to apps/api/plane/authentication/views/app/gitlab.py diff --git a/apiserver/plane/authentication/views/app/google.py b/apps/api/plane/authentication/views/app/google.py similarity index 100% rename from apiserver/plane/authentication/views/app/google.py rename to apps/api/plane/authentication/views/app/google.py diff --git a/apiserver/plane/authentication/views/app/magic.py b/apps/api/plane/authentication/views/app/magic.py similarity index 100% rename from apiserver/plane/authentication/views/app/magic.py rename to apps/api/plane/authentication/views/app/magic.py diff --git a/apiserver/plane/authentication/views/app/password_management.py b/apps/api/plane/authentication/views/app/password_management.py similarity index 100% rename from apiserver/plane/authentication/views/app/password_management.py rename to apps/api/plane/authentication/views/app/password_management.py diff --git a/apiserver/plane/authentication/views/app/signout.py b/apps/api/plane/authentication/views/app/signout.py similarity index 100% rename from apiserver/plane/authentication/views/app/signout.py rename to apps/api/plane/authentication/views/app/signout.py diff --git a/apiserver/plane/authentication/views/common.py b/apps/api/plane/authentication/views/common.py similarity index 100% rename from apiserver/plane/authentication/views/common.py rename to apps/api/plane/authentication/views/common.py diff --git a/apiserver/plane/authentication/views/space/check.py b/apps/api/plane/authentication/views/space/check.py similarity index 100% rename from apiserver/plane/authentication/views/space/check.py rename to apps/api/plane/authentication/views/space/check.py diff --git a/apiserver/plane/authentication/views/space/email.py b/apps/api/plane/authentication/views/space/email.py similarity index 100% rename from apiserver/plane/authentication/views/space/email.py rename to apps/api/plane/authentication/views/space/email.py diff --git a/apiserver/plane/authentication/views/space/github.py b/apps/api/plane/authentication/views/space/github.py similarity index 100% rename from apiserver/plane/authentication/views/space/github.py rename to apps/api/plane/authentication/views/space/github.py diff --git a/apiserver/plane/authentication/views/space/gitlab.py b/apps/api/plane/authentication/views/space/gitlab.py similarity index 100% rename from apiserver/plane/authentication/views/space/gitlab.py rename to apps/api/plane/authentication/views/space/gitlab.py diff --git a/apiserver/plane/authentication/views/space/google.py b/apps/api/plane/authentication/views/space/google.py similarity index 100% rename from apiserver/plane/authentication/views/space/google.py rename to apps/api/plane/authentication/views/space/google.py diff --git a/apiserver/plane/authentication/views/space/magic.py b/apps/api/plane/authentication/views/space/magic.py similarity index 100% rename from apiserver/plane/authentication/views/space/magic.py rename to apps/api/plane/authentication/views/space/magic.py diff --git a/apiserver/plane/authentication/views/space/password_management.py b/apps/api/plane/authentication/views/space/password_management.py similarity index 100% rename from apiserver/plane/authentication/views/space/password_management.py rename to apps/api/plane/authentication/views/space/password_management.py diff --git a/apiserver/plane/authentication/views/space/signout.py b/apps/api/plane/authentication/views/space/signout.py similarity index 100% rename from apiserver/plane/authentication/views/space/signout.py rename to apps/api/plane/authentication/views/space/signout.py diff --git a/apiserver/plane/bgtasks/__init__.py b/apps/api/plane/bgtasks/__init__.py similarity index 100% rename from apiserver/plane/bgtasks/__init__.py rename to apps/api/plane/bgtasks/__init__.py diff --git a/apiserver/plane/bgtasks/analytic_plot_export.py b/apps/api/plane/bgtasks/analytic_plot_export.py similarity index 100% rename from apiserver/plane/bgtasks/analytic_plot_export.py rename to apps/api/plane/bgtasks/analytic_plot_export.py diff --git a/apiserver/plane/bgtasks/api_logs_task.py b/apps/api/plane/bgtasks/api_logs_task.py similarity index 100% rename from apiserver/plane/bgtasks/api_logs_task.py rename to apps/api/plane/bgtasks/api_logs_task.py diff --git a/apiserver/plane/bgtasks/apps.py b/apps/api/plane/bgtasks/apps.py similarity index 100% rename from apiserver/plane/bgtasks/apps.py rename to apps/api/plane/bgtasks/apps.py diff --git a/apiserver/plane/bgtasks/copy_s3_object.py b/apps/api/plane/bgtasks/copy_s3_object.py similarity index 62% rename from apiserver/plane/bgtasks/copy_s3_object.py rename to apps/api/plane/bgtasks/copy_s3_object.py index a92d7fe4e..c8d9fc480 100644 --- a/apiserver/plane/bgtasks/copy_s3_object.py +++ b/apps/api/plane/bgtasks/copy_s3_object.py @@ -83,8 +83,52 @@ def sync_with_external_service(entity_name, description_html): return {} +def copy_assets(entity, entity_identifier, project_id, asset_ids, user_id): + duplicated_assets = [] + workspace = entity.workspace + storage = S3Storage() + original_assets = FileAsset.objects.filter( + workspace=workspace, project_id=project_id, id__in=asset_ids + ) + + for original_asset in original_assets: + destination_key = ( + f"{workspace.id}/{uuid.uuid4().hex}-{original_asset.attributes.get('name')}" + ) + duplicated_asset = FileAsset.objects.create( + attributes={ + "name": original_asset.attributes.get("name"), + "type": original_asset.attributes.get("type"), + "size": original_asset.attributes.get("size"), + }, + asset=destination_key, + size=original_asset.size, + workspace=workspace, + created_by_id=user_id, + entity_type=original_asset.entity_type, + project_id=project_id, + storage_metadata=original_asset.storage_metadata, + **get_entity_id_field(original_asset.entity_type, entity_identifier), + ) + storage.copy_object(original_asset.asset, destination_key) + duplicated_assets.append( + { + "new_asset_id": str(duplicated_asset.id), + "old_asset_id": str(original_asset.id), + } + ) + if duplicated_assets: + FileAsset.objects.filter( + pk__in=[item["new_asset_id"] for item in duplicated_assets] + ).update(is_uploaded=True) + + return duplicated_assets + + @shared_task -def copy_s3_objects(entity_name, entity_identifier, project_id, slug, user_id): +def copy_s3_objects_of_description_and_assets( + entity_name, entity_identifier, project_id, slug, user_id +): """ Step 1: Extract asset ids from the description_html of the entity Step 2: Duplicate the assets @@ -100,53 +144,20 @@ def copy_s3_objects(entity_name, entity_identifier, project_id, slug, user_id): entity = model_class.objects.get(id=entity_identifier) asset_ids = extract_asset_ids(entity.description_html, "image-component") - duplicated_assets = [] - workspace = entity.workspace - storage = S3Storage() - original_assets = FileAsset.objects.filter( - workspace=workspace, project_id=project_id, id__in=asset_ids + duplicated_assets = copy_assets( + entity, entity_identifier, project_id, asset_ids, user_id ) - for original_asset in original_assets: - destination_key = f"{workspace.id}/{uuid.uuid4().hex}-{original_asset.attributes.get('name')}" - duplicated_asset = FileAsset.objects.create( - attributes={ - "name": original_asset.attributes.get("name"), - "type": original_asset.attributes.get("type"), - "size": original_asset.attributes.get("size"), - }, - asset=destination_key, - size=original_asset.size, - workspace=workspace, - created_by_id=user_id, - entity_type=original_asset.entity_type, - project_id=project_id, - storage_metadata=original_asset.storage_metadata, - **get_entity_id_field(original_asset.entity_type, entity_identifier), - ) - storage.copy_object(original_asset.asset, destination_key) - duplicated_assets.append( - { - "new_asset_id": str(duplicated_asset.id), - "old_asset_id": str(original_asset.id), - } - ) + updated_html = update_description(entity, duplicated_assets, "image-component") - if duplicated_assets: - FileAsset.objects.filter( - pk__in=[item["new_asset_id"] for item in duplicated_assets] - ).update(is_uploaded=True) - updated_html = update_description( - entity, duplicated_assets, "image-component" - ) - external_data = sync_with_external_service(entity_name, updated_html) + external_data = sync_with_external_service(entity_name, updated_html) - if external_data: - entity.description = external_data.get("description") - entity.description_binary = base64.b64decode( - external_data.get("description_binary") - ) - entity.save() + if external_data: + entity.description = external_data.get("description") + entity.description_binary = base64.b64decode( + external_data.get("description_binary") + ) + entity.save() return except Exception as e: diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apps/api/plane/bgtasks/deletion_task.py similarity index 100% rename from apiserver/plane/bgtasks/deletion_task.py rename to apps/api/plane/bgtasks/deletion_task.py diff --git a/apiserver/plane/bgtasks/dummy_data_task.py b/apps/api/plane/bgtasks/dummy_data_task.py similarity index 100% rename from apiserver/plane/bgtasks/dummy_data_task.py rename to apps/api/plane/bgtasks/dummy_data_task.py diff --git a/apiserver/plane/bgtasks/email_notification_task.py b/apps/api/plane/bgtasks/email_notification_task.py similarity index 98% rename from apiserver/plane/bgtasks/email_notification_task.py rename to apps/api/plane/bgtasks/email_notification_task.py index dcc37796d..5a601dcb8 100644 --- a/apiserver/plane/bgtasks/email_notification_task.py +++ b/apps/api/plane/bgtasks/email_notification_task.py @@ -21,8 +21,8 @@ from plane.utils.exception_logger import log_exception def remove_unwanted_characters(input_text): - # Keep only alphanumeric characters, spaces, and dashes. - processed_text = re.sub(r"[^a-zA-Z0-9 \-]", "", input_text) + # Remove only control characters and potentially problematic characters for email subjects + processed_text = re.sub(r"[\x00-\x1F\x7F-\x9F]", "", input_text) return processed_text diff --git a/apiserver/plane/bgtasks/event_tracking_task.py b/apps/api/plane/bgtasks/event_tracking_task.py similarity index 100% rename from apiserver/plane/bgtasks/event_tracking_task.py rename to apps/api/plane/bgtasks/event_tracking_task.py diff --git a/apiserver/plane/bgtasks/export_task.py b/apps/api/plane/bgtasks/export_task.py similarity index 100% rename from apiserver/plane/bgtasks/export_task.py rename to apps/api/plane/bgtasks/export_task.py diff --git a/apiserver/plane/bgtasks/exporter_expired_task.py b/apps/api/plane/bgtasks/exporter_expired_task.py similarity index 100% rename from apiserver/plane/bgtasks/exporter_expired_task.py rename to apps/api/plane/bgtasks/exporter_expired_task.py diff --git a/apiserver/plane/bgtasks/file_asset_task.py b/apps/api/plane/bgtasks/file_asset_task.py similarity index 100% rename from apiserver/plane/bgtasks/file_asset_task.py rename to apps/api/plane/bgtasks/file_asset_task.py diff --git a/apiserver/plane/bgtasks/forgot_password_task.py b/apps/api/plane/bgtasks/forgot_password_task.py similarity index 100% rename from apiserver/plane/bgtasks/forgot_password_task.py rename to apps/api/plane/bgtasks/forgot_password_task.py diff --git a/apiserver/plane/bgtasks/issue_activities_task.py b/apps/api/plane/bgtasks/issue_activities_task.py similarity index 100% rename from apiserver/plane/bgtasks/issue_activities_task.py rename to apps/api/plane/bgtasks/issue_activities_task.py diff --git a/apiserver/plane/bgtasks/issue_automation_task.py b/apps/api/plane/bgtasks/issue_automation_task.py similarity index 100% rename from apiserver/plane/bgtasks/issue_automation_task.py rename to apps/api/plane/bgtasks/issue_automation_task.py diff --git a/apiserver/plane/bgtasks/issue_description_version_sync.py b/apps/api/plane/bgtasks/issue_description_version_sync.py similarity index 100% rename from apiserver/plane/bgtasks/issue_description_version_sync.py rename to apps/api/plane/bgtasks/issue_description_version_sync.py diff --git a/apiserver/plane/bgtasks/issue_description_version_task.py b/apps/api/plane/bgtasks/issue_description_version_task.py similarity index 100% rename from apiserver/plane/bgtasks/issue_description_version_task.py rename to apps/api/plane/bgtasks/issue_description_version_task.py diff --git a/apiserver/plane/bgtasks/issue_version_sync.py b/apps/api/plane/bgtasks/issue_version_sync.py similarity index 100% rename from apiserver/plane/bgtasks/issue_version_sync.py rename to apps/api/plane/bgtasks/issue_version_sync.py diff --git a/apiserver/plane/bgtasks/magic_link_code_task.py b/apps/api/plane/bgtasks/magic_link_code_task.py similarity index 100% rename from apiserver/plane/bgtasks/magic_link_code_task.py rename to apps/api/plane/bgtasks/magic_link_code_task.py diff --git a/apiserver/plane/bgtasks/notification_task.py b/apps/api/plane/bgtasks/notification_task.py similarity index 100% rename from apiserver/plane/bgtasks/notification_task.py rename to apps/api/plane/bgtasks/notification_task.py diff --git a/apiserver/plane/bgtasks/page_transaction_task.py b/apps/api/plane/bgtasks/page_transaction_task.py similarity index 100% rename from apiserver/plane/bgtasks/page_transaction_task.py rename to apps/api/plane/bgtasks/page_transaction_task.py diff --git a/apiserver/plane/bgtasks/page_version_task.py b/apps/api/plane/bgtasks/page_version_task.py similarity index 100% rename from apiserver/plane/bgtasks/page_version_task.py rename to apps/api/plane/bgtasks/page_version_task.py diff --git a/apiserver/plane/bgtasks/project_add_user_email_task.py b/apps/api/plane/bgtasks/project_add_user_email_task.py similarity index 100% rename from apiserver/plane/bgtasks/project_add_user_email_task.py rename to apps/api/plane/bgtasks/project_add_user_email_task.py diff --git a/apiserver/plane/bgtasks/project_invitation_task.py b/apps/api/plane/bgtasks/project_invitation_task.py similarity index 100% rename from apiserver/plane/bgtasks/project_invitation_task.py rename to apps/api/plane/bgtasks/project_invitation_task.py diff --git a/apiserver/plane/bgtasks/recent_visited_task.py b/apps/api/plane/bgtasks/recent_visited_task.py similarity index 100% rename from apiserver/plane/bgtasks/recent_visited_task.py rename to apps/api/plane/bgtasks/recent_visited_task.py diff --git a/apiserver/plane/bgtasks/storage_metadata_task.py b/apps/api/plane/bgtasks/storage_metadata_task.py similarity index 100% rename from apiserver/plane/bgtasks/storage_metadata_task.py rename to apps/api/plane/bgtasks/storage_metadata_task.py diff --git a/apiserver/plane/bgtasks/user_activation_email_task.py b/apps/api/plane/bgtasks/user_activation_email_task.py similarity index 100% rename from apiserver/plane/bgtasks/user_activation_email_task.py rename to apps/api/plane/bgtasks/user_activation_email_task.py diff --git a/apiserver/plane/bgtasks/user_deactivation_email_task.py b/apps/api/plane/bgtasks/user_deactivation_email_task.py similarity index 100% rename from apiserver/plane/bgtasks/user_deactivation_email_task.py rename to apps/api/plane/bgtasks/user_deactivation_email_task.py diff --git a/apiserver/plane/bgtasks/webhook_task.py b/apps/api/plane/bgtasks/webhook_task.py similarity index 93% rename from apiserver/plane/bgtasks/webhook_task.py rename to apps/api/plane/bgtasks/webhook_task.py index 0bcfd2693..ae7c30ac9 100644 --- a/apiserver/plane/bgtasks/webhook_task.py +++ b/apps/api/plane/bgtasks/webhook_task.py @@ -12,6 +12,7 @@ from celery import shared_task # Django imports from django.conf import settings +from django.db.models import Prefetch from django.core.mail import EmailMultiAlternatives, get_connection from django.core.serializers.json import DjangoJSONEncoder from django.template.loader import render_to_string @@ -42,6 +43,8 @@ from plane.db.models import ( Webhook, WebhookLog, IntakeIssue, + IssueLabel, + IssueAssignee, ) from plane.license.utils.instance_value import get_email_configuration from plane.utils.exception_logger import log_exception @@ -74,6 +77,15 @@ MODEL_MAPPER = { logger = logging.getLogger("plane.worker") +def get_issue_prefetches(): + return [ + Prefetch("label_issue", queryset=IssueLabel.objects.select_related("label")), + Prefetch( + "issue_assignee", queryset=IssueAssignee.objects.select_related("assignee") + ), + ] + + def get_model_data( event: str, event_id: Union[str, List[str]], many: bool = False ) -> Dict[str, Any]: @@ -103,10 +115,27 @@ def get_model_data( queryset = model.objects.get(pk=event_id) serializer = SERIALIZER_MAPPER.get(event) + if serializer is None: raise ValueError(f"Serializer not found for event: {event}") - return serializer(queryset, many=many).data + issue_prefetches = get_issue_prefetches() + if event == "issue": + if many: + queryset = queryset.prefetch_related(*issue_prefetches) + else: + issue_id = queryset.id + queryset = ( + model.objects.filter(pk=issue_id) + .prefetch_related(*issue_prefetches) + .first() + ) + + return serializer( + queryset, many=many, context={"expand": ["labels", "assignees"]} + ).data + else: + return serializer(queryset, many=many).data except ObjectDoesNotExist: raise ObjectDoesNotExist(f"No {event} found with id: {event_id}") diff --git a/apiserver/plane/bgtasks/work_item_link_task.py b/apps/api/plane/bgtasks/work_item_link_task.py similarity index 99% rename from apiserver/plane/bgtasks/work_item_link_task.py rename to apps/api/plane/bgtasks/work_item_link_task.py index 1ba48caf9..721231be1 100644 --- a/apiserver/plane/bgtasks/work_item_link_task.py +++ b/apps/api/plane/bgtasks/work_item_link_task.py @@ -19,6 +19,7 @@ logger = logging.getLogger("plane.worker") DEFAULT_FAVICON = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWxpbmstaWNvbiBsdWNpZGUtbGluayI+PHBhdGggZD0iTTEwIDEzYTUgNSAwIDAgMCA3LjU0LjU0bDMtM2E1IDUgMCAwIDAtNy4wNy03LjA3bC0xLjcyIDEuNzEiLz48cGF0aCBkPSJNMTQgMTFhNSA1IDAgMCAwLTcuNTQtLjU0bC0zIDNhNSA1IDAgMCAwIDcuMDcgNy4wN2wxLjcxLTEuNzEiLz48L3N2Zz4=" # noqa: E501 + def crawl_work_item_link_title_and_favicon(url: str) -> Dict[str, Any]: """ Crawls a URL to extract the title and favicon. @@ -118,7 +119,7 @@ def find_favicon_url(soup: Optional[BeautifulSoup], base_url: str) -> Optional[s if response.status_code == 200: return fallback_url except requests.RequestException as e: - log_exception(e) + log_exception(e, warning=True) return None return None diff --git a/apiserver/plane/bgtasks/workspace_invitation_task.py b/apps/api/plane/bgtasks/workspace_invitation_task.py similarity index 100% rename from apiserver/plane/bgtasks/workspace_invitation_task.py rename to apps/api/plane/bgtasks/workspace_invitation_task.py diff --git a/apiserver/plane/bgtasks/workspace_seed_task.py b/apps/api/plane/bgtasks/workspace_seed_task.py similarity index 100% rename from apiserver/plane/bgtasks/workspace_seed_task.py rename to apps/api/plane/bgtasks/workspace_seed_task.py diff --git a/apiserver/plane/celery.py b/apps/api/plane/celery.py similarity index 100% rename from apiserver/plane/celery.py rename to apps/api/plane/celery.py diff --git a/apiserver/plane/db/__init__.py b/apps/api/plane/db/__init__.py similarity index 100% rename from apiserver/plane/db/__init__.py rename to apps/api/plane/db/__init__.py diff --git a/apiserver/plane/db/apps.py b/apps/api/plane/db/apps.py similarity index 100% rename from apiserver/plane/db/apps.py rename to apps/api/plane/db/apps.py diff --git a/apiserver/plane/db/management/__init__.py b/apps/api/plane/db/management/__init__.py similarity index 100% rename from apiserver/plane/db/management/__init__.py rename to apps/api/plane/db/management/__init__.py diff --git a/apiserver/plane/db/management/commands/__init__.py b/apps/api/plane/db/management/commands/__init__.py similarity index 100% rename from apiserver/plane/db/management/commands/__init__.py rename to apps/api/plane/db/management/commands/__init__.py diff --git a/apiserver/plane/db/management/commands/activate_user.py b/apps/api/plane/db/management/commands/activate_user.py similarity index 100% rename from apiserver/plane/db/management/commands/activate_user.py rename to apps/api/plane/db/management/commands/activate_user.py diff --git a/apiserver/plane/db/management/commands/clear_cache.py b/apps/api/plane/db/management/commands/clear_cache.py similarity index 100% rename from apiserver/plane/db/management/commands/clear_cache.py rename to apps/api/plane/db/management/commands/clear_cache.py diff --git a/apiserver/plane/db/management/commands/create_bucket.py b/apps/api/plane/db/management/commands/create_bucket.py similarity index 100% rename from apiserver/plane/db/management/commands/create_bucket.py rename to apps/api/plane/db/management/commands/create_bucket.py diff --git a/apiserver/plane/db/management/commands/create_dummy_data.py b/apps/api/plane/db/management/commands/create_dummy_data.py similarity index 99% rename from apiserver/plane/db/management/commands/create_dummy_data.py rename to apps/api/plane/db/management/commands/create_dummy_data.py index 3eedc390c..0915cd9d8 100644 --- a/apiserver/plane/db/management/commands/create_dummy_data.py +++ b/apps/api/plane/db/management/commands/create_dummy_data.py @@ -50,7 +50,7 @@ class Command(BaseCommand): project_count = int(input("Number of projects to be created: ")) for i in range(project_count): - print(f"Please provide the following details for project {i+1}:") + print(f"Please provide the following details for project {i + 1}:") issue_count = int(input("Number of issues to be created: ")) cycle_count = int(input("Number of cycles to be created: ")) module_count = int(input("Number of modules to be created: ")) diff --git a/apiserver/plane/db/management/commands/create_instance_admin.py b/apps/api/plane/db/management/commands/create_instance_admin.py similarity index 100% rename from apiserver/plane/db/management/commands/create_instance_admin.py rename to apps/api/plane/db/management/commands/create_instance_admin.py diff --git a/apiserver/plane/db/management/commands/create_project_member.py b/apps/api/plane/db/management/commands/create_project_member.py similarity index 100% rename from apiserver/plane/db/management/commands/create_project_member.py rename to apps/api/plane/db/management/commands/create_project_member.py diff --git a/apiserver/plane/db/management/commands/fix_duplicate_sequences.py b/apps/api/plane/db/management/commands/fix_duplicate_sequences.py similarity index 100% rename from apiserver/plane/db/management/commands/fix_duplicate_sequences.py rename to apps/api/plane/db/management/commands/fix_duplicate_sequences.py diff --git a/apiserver/plane/db/management/commands/reset_password.py b/apps/api/plane/db/management/commands/reset_password.py similarity index 100% rename from apiserver/plane/db/management/commands/reset_password.py rename to apps/api/plane/db/management/commands/reset_password.py diff --git a/apiserver/plane/db/management/commands/sync_issue_description_version.py b/apps/api/plane/db/management/commands/sync_issue_description_version.py similarity index 100% rename from apiserver/plane/db/management/commands/sync_issue_description_version.py rename to apps/api/plane/db/management/commands/sync_issue_description_version.py diff --git a/apiserver/plane/db/management/commands/sync_issue_version.py b/apps/api/plane/db/management/commands/sync_issue_version.py similarity index 100% rename from apiserver/plane/db/management/commands/sync_issue_version.py rename to apps/api/plane/db/management/commands/sync_issue_version.py diff --git a/apiserver/plane/db/management/commands/test_email.py b/apps/api/plane/db/management/commands/test_email.py similarity index 100% rename from apiserver/plane/db/management/commands/test_email.py rename to apps/api/plane/db/management/commands/test_email.py diff --git a/apiserver/plane/db/management/commands/update_bucket.py b/apps/api/plane/db/management/commands/update_bucket.py similarity index 100% rename from apiserver/plane/db/management/commands/update_bucket.py rename to apps/api/plane/db/management/commands/update_bucket.py diff --git a/apiserver/plane/db/management/commands/update_deleted_workspace_slug.py b/apps/api/plane/db/management/commands/update_deleted_workspace_slug.py similarity index 100% rename from apiserver/plane/db/management/commands/update_deleted_workspace_slug.py rename to apps/api/plane/db/management/commands/update_deleted_workspace_slug.py diff --git a/apiserver/plane/db/management/commands/wait_for_db.py b/apps/api/plane/db/management/commands/wait_for_db.py similarity index 100% rename from apiserver/plane/db/management/commands/wait_for_db.py rename to apps/api/plane/db/management/commands/wait_for_db.py diff --git a/apiserver/plane/db/management/commands/wait_for_migrations.py b/apps/api/plane/db/management/commands/wait_for_migrations.py similarity index 100% rename from apiserver/plane/db/management/commands/wait_for_migrations.py rename to apps/api/plane/db/management/commands/wait_for_migrations.py diff --git a/apiserver/plane/db/migrations/0001_initial.py b/apps/api/plane/db/migrations/0001_initial.py similarity index 100% rename from apiserver/plane/db/migrations/0001_initial.py rename to apps/api/plane/db/migrations/0001_initial.py diff --git a/apiserver/plane/db/migrations/0002_auto_20221104_2239.py b/apps/api/plane/db/migrations/0002_auto_20221104_2239.py similarity index 100% rename from apiserver/plane/db/migrations/0002_auto_20221104_2239.py rename to apps/api/plane/db/migrations/0002_auto_20221104_2239.py diff --git a/apiserver/plane/db/migrations/0003_auto_20221109_2320.py b/apps/api/plane/db/migrations/0003_auto_20221109_2320.py similarity index 100% rename from apiserver/plane/db/migrations/0003_auto_20221109_2320.py rename to apps/api/plane/db/migrations/0003_auto_20221109_2320.py diff --git a/apiserver/plane/db/migrations/0004_alter_state_sequence.py b/apps/api/plane/db/migrations/0004_alter_state_sequence.py similarity index 100% rename from apiserver/plane/db/migrations/0004_alter_state_sequence.py rename to apps/api/plane/db/migrations/0004_alter_state_sequence.py diff --git a/apiserver/plane/db/migrations/0005_auto_20221114_2127.py b/apps/api/plane/db/migrations/0005_auto_20221114_2127.py similarity index 100% rename from apiserver/plane/db/migrations/0005_auto_20221114_2127.py rename to apps/api/plane/db/migrations/0005_auto_20221114_2127.py diff --git a/apiserver/plane/db/migrations/0006_alter_cycle_status.py b/apps/api/plane/db/migrations/0006_alter_cycle_status.py similarity index 100% rename from apiserver/plane/db/migrations/0006_alter_cycle_status.py rename to apps/api/plane/db/migrations/0006_alter_cycle_status.py diff --git a/apiserver/plane/db/migrations/0007_label_parent.py b/apps/api/plane/db/migrations/0007_label_parent.py similarity index 100% rename from apiserver/plane/db/migrations/0007_label_parent.py rename to apps/api/plane/db/migrations/0007_label_parent.py diff --git a/apiserver/plane/db/migrations/0008_label_colour.py b/apps/api/plane/db/migrations/0008_label_colour.py similarity index 100% rename from apiserver/plane/db/migrations/0008_label_colour.py rename to apps/api/plane/db/migrations/0008_label_colour.py diff --git a/apiserver/plane/db/migrations/0009_auto_20221208_0310.py b/apps/api/plane/db/migrations/0009_auto_20221208_0310.py similarity index 100% rename from apiserver/plane/db/migrations/0009_auto_20221208_0310.py rename to apps/api/plane/db/migrations/0009_auto_20221208_0310.py diff --git a/apiserver/plane/db/migrations/0010_auto_20221213_0037.py b/apps/api/plane/db/migrations/0010_auto_20221213_0037.py similarity index 100% rename from apiserver/plane/db/migrations/0010_auto_20221213_0037.py rename to apps/api/plane/db/migrations/0010_auto_20221213_0037.py diff --git a/apiserver/plane/db/migrations/0011_auto_20221222_2357.py b/apps/api/plane/db/migrations/0011_auto_20221222_2357.py similarity index 100% rename from apiserver/plane/db/migrations/0011_auto_20221222_2357.py rename to apps/api/plane/db/migrations/0011_auto_20221222_2357.py diff --git a/apiserver/plane/db/migrations/0012_auto_20230104_0117.py b/apps/api/plane/db/migrations/0012_auto_20230104_0117.py similarity index 100% rename from apiserver/plane/db/migrations/0012_auto_20230104_0117.py rename to apps/api/plane/db/migrations/0012_auto_20230104_0117.py diff --git a/apiserver/plane/db/migrations/0013_auto_20230107_0041.py b/apps/api/plane/db/migrations/0013_auto_20230107_0041.py similarity index 100% rename from apiserver/plane/db/migrations/0013_auto_20230107_0041.py rename to apps/api/plane/db/migrations/0013_auto_20230107_0041.py diff --git a/apiserver/plane/db/migrations/0014_alter_workspacememberinvite_unique_together.py b/apps/api/plane/db/migrations/0014_alter_workspacememberinvite_unique_together.py similarity index 100% rename from apiserver/plane/db/migrations/0014_alter_workspacememberinvite_unique_together.py rename to apps/api/plane/db/migrations/0014_alter_workspacememberinvite_unique_together.py diff --git a/apiserver/plane/db/migrations/0015_auto_20230107_1636.py b/apps/api/plane/db/migrations/0015_auto_20230107_1636.py similarity index 100% rename from apiserver/plane/db/migrations/0015_auto_20230107_1636.py rename to apps/api/plane/db/migrations/0015_auto_20230107_1636.py diff --git a/apiserver/plane/db/migrations/0016_auto_20230107_1735.py b/apps/api/plane/db/migrations/0016_auto_20230107_1735.py similarity index 100% rename from apiserver/plane/db/migrations/0016_auto_20230107_1735.py rename to apps/api/plane/db/migrations/0016_auto_20230107_1735.py diff --git a/apiserver/plane/db/migrations/0017_alter_workspace_unique_together.py b/apps/api/plane/db/migrations/0017_alter_workspace_unique_together.py similarity index 100% rename from apiserver/plane/db/migrations/0017_alter_workspace_unique_together.py rename to apps/api/plane/db/migrations/0017_alter_workspace_unique_together.py diff --git a/apiserver/plane/db/migrations/0018_auto_20230130_0119.py b/apps/api/plane/db/migrations/0018_auto_20230130_0119.py similarity index 100% rename from apiserver/plane/db/migrations/0018_auto_20230130_0119.py rename to apps/api/plane/db/migrations/0018_auto_20230130_0119.py diff --git a/apiserver/plane/db/migrations/0019_auto_20230131_0049.py b/apps/api/plane/db/migrations/0019_auto_20230131_0049.py similarity index 100% rename from apiserver/plane/db/migrations/0019_auto_20230131_0049.py rename to apps/api/plane/db/migrations/0019_auto_20230131_0049.py diff --git a/apiserver/plane/db/migrations/0020_auto_20230214_0118.py b/apps/api/plane/db/migrations/0020_auto_20230214_0118.py similarity index 100% rename from apiserver/plane/db/migrations/0020_auto_20230214_0118.py rename to apps/api/plane/db/migrations/0020_auto_20230214_0118.py diff --git a/apiserver/plane/db/migrations/0021_auto_20230223_0104.py b/apps/api/plane/db/migrations/0021_auto_20230223_0104.py similarity index 100% rename from apiserver/plane/db/migrations/0021_auto_20230223_0104.py rename to apps/api/plane/db/migrations/0021_auto_20230223_0104.py diff --git a/apiserver/plane/db/migrations/0022_auto_20230307_0304.py b/apps/api/plane/db/migrations/0022_auto_20230307_0304.py similarity index 100% rename from apiserver/plane/db/migrations/0022_auto_20230307_0304.py rename to apps/api/plane/db/migrations/0022_auto_20230307_0304.py diff --git a/apiserver/plane/db/migrations/0023_auto_20230316_0040.py b/apps/api/plane/db/migrations/0023_auto_20230316_0040.py similarity index 100% rename from apiserver/plane/db/migrations/0023_auto_20230316_0040.py rename to apps/api/plane/db/migrations/0023_auto_20230316_0040.py diff --git a/apiserver/plane/db/migrations/0024_auto_20230322_0138.py b/apps/api/plane/db/migrations/0024_auto_20230322_0138.py similarity index 100% rename from apiserver/plane/db/migrations/0024_auto_20230322_0138.py rename to apps/api/plane/db/migrations/0024_auto_20230322_0138.py diff --git a/apiserver/plane/db/migrations/0025_auto_20230331_0203.py b/apps/api/plane/db/migrations/0025_auto_20230331_0203.py similarity index 100% rename from apiserver/plane/db/migrations/0025_auto_20230331_0203.py rename to apps/api/plane/db/migrations/0025_auto_20230331_0203.py diff --git a/apiserver/plane/db/migrations/0026_alter_projectmember_view_props.py b/apps/api/plane/db/migrations/0026_alter_projectmember_view_props.py similarity index 100% rename from apiserver/plane/db/migrations/0026_alter_projectmember_view_props.py rename to apps/api/plane/db/migrations/0026_alter_projectmember_view_props.py diff --git a/apiserver/plane/db/migrations/0027_auto_20230409_0312.py b/apps/api/plane/db/migrations/0027_auto_20230409_0312.py similarity index 100% rename from apiserver/plane/db/migrations/0027_auto_20230409_0312.py rename to apps/api/plane/db/migrations/0027_auto_20230409_0312.py diff --git a/apiserver/plane/db/migrations/0028_auto_20230414_1703.py b/apps/api/plane/db/migrations/0028_auto_20230414_1703.py similarity index 100% rename from apiserver/plane/db/migrations/0028_auto_20230414_1703.py rename to apps/api/plane/db/migrations/0028_auto_20230414_1703.py diff --git a/apiserver/plane/db/migrations/0029_auto_20230502_0126.py b/apps/api/plane/db/migrations/0029_auto_20230502_0126.py similarity index 100% rename from apiserver/plane/db/migrations/0029_auto_20230502_0126.py rename to apps/api/plane/db/migrations/0029_auto_20230502_0126.py diff --git a/apiserver/plane/db/migrations/0030_alter_estimatepoint_unique_together.py b/apps/api/plane/db/migrations/0030_alter_estimatepoint_unique_together.py similarity index 100% rename from apiserver/plane/db/migrations/0030_alter_estimatepoint_unique_together.py rename to apps/api/plane/db/migrations/0030_alter_estimatepoint_unique_together.py diff --git a/apiserver/plane/db/migrations/0031_analyticview.py b/apps/api/plane/db/migrations/0031_analyticview.py similarity index 100% rename from apiserver/plane/db/migrations/0031_analyticview.py rename to apps/api/plane/db/migrations/0031_analyticview.py diff --git a/apiserver/plane/db/migrations/0032_auto_20230520_2015.py b/apps/api/plane/db/migrations/0032_auto_20230520_2015.py similarity index 100% rename from apiserver/plane/db/migrations/0032_auto_20230520_2015.py rename to apps/api/plane/db/migrations/0032_auto_20230520_2015.py diff --git a/apiserver/plane/db/migrations/0033_auto_20230618_2125.py b/apps/api/plane/db/migrations/0033_auto_20230618_2125.py similarity index 100% rename from apiserver/plane/db/migrations/0033_auto_20230618_2125.py rename to apps/api/plane/db/migrations/0033_auto_20230618_2125.py diff --git a/apiserver/plane/db/migrations/0034_auto_20230628_1046.py b/apps/api/plane/db/migrations/0034_auto_20230628_1046.py similarity index 100% rename from apiserver/plane/db/migrations/0034_auto_20230628_1046.py rename to apps/api/plane/db/migrations/0034_auto_20230628_1046.py diff --git a/apiserver/plane/db/migrations/0035_auto_20230704_2225.py b/apps/api/plane/db/migrations/0035_auto_20230704_2225.py similarity index 100% rename from apiserver/plane/db/migrations/0035_auto_20230704_2225.py rename to apps/api/plane/db/migrations/0035_auto_20230704_2225.py diff --git a/apiserver/plane/db/migrations/0036_alter_workspace_organization_size.py b/apps/api/plane/db/migrations/0036_alter_workspace_organization_size.py similarity index 100% rename from apiserver/plane/db/migrations/0036_alter_workspace_organization_size.py rename to apps/api/plane/db/migrations/0036_alter_workspace_organization_size.py diff --git a/apiserver/plane/db/migrations/0037_issue_archived_at_project_archive_in_and_more.py b/apps/api/plane/db/migrations/0037_issue_archived_at_project_archive_in_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0037_issue_archived_at_project_archive_in_and_more.py rename to apps/api/plane/db/migrations/0037_issue_archived_at_project_archive_in_and_more.py diff --git a/apiserver/plane/db/migrations/0038_auto_20230720_1505.py b/apps/api/plane/db/migrations/0038_auto_20230720_1505.py similarity index 100% rename from apiserver/plane/db/migrations/0038_auto_20230720_1505.py rename to apps/api/plane/db/migrations/0038_auto_20230720_1505.py diff --git a/apiserver/plane/db/migrations/0039_auto_20230723_2203.py b/apps/api/plane/db/migrations/0039_auto_20230723_2203.py similarity index 100% rename from apiserver/plane/db/migrations/0039_auto_20230723_2203.py rename to apps/api/plane/db/migrations/0039_auto_20230723_2203.py diff --git a/apiserver/plane/db/migrations/0040_projectmember_preferences_user_cover_image_and_more.py b/apps/api/plane/db/migrations/0040_projectmember_preferences_user_cover_image_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0040_projectmember_preferences_user_cover_image_and_more.py rename to apps/api/plane/db/migrations/0040_projectmember_preferences_user_cover_image_and_more.py diff --git a/apiserver/plane/db/migrations/0041_cycle_sort_order_issuecomment_access_and_more.py b/apps/api/plane/db/migrations/0041_cycle_sort_order_issuecomment_access_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0041_cycle_sort_order_issuecomment_access_and_more.py rename to apps/api/plane/db/migrations/0041_cycle_sort_order_issuecomment_access_and_more.py diff --git a/apiserver/plane/db/migrations/0042_alter_analyticview_created_by_and_more.py b/apps/api/plane/db/migrations/0042_alter_analyticview_created_by_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0042_alter_analyticview_created_by_and_more.py rename to apps/api/plane/db/migrations/0042_alter_analyticview_created_by_and_more.py diff --git a/apiserver/plane/db/migrations/0043_alter_analyticview_created_by_and_more.py b/apps/api/plane/db/migrations/0043_alter_analyticview_created_by_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0043_alter_analyticview_created_by_and_more.py rename to apps/api/plane/db/migrations/0043_alter_analyticview_created_by_and_more.py diff --git a/apiserver/plane/db/migrations/0044_auto_20230913_0709.py b/apps/api/plane/db/migrations/0044_auto_20230913_0709.py similarity index 100% rename from apiserver/plane/db/migrations/0044_auto_20230913_0709.py rename to apps/api/plane/db/migrations/0044_auto_20230913_0709.py diff --git a/apiserver/plane/db/migrations/0045_issueactivity_epoch_workspacemember_issue_props_and_more.py b/apps/api/plane/db/migrations/0045_issueactivity_epoch_workspacemember_issue_props_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0045_issueactivity_epoch_workspacemember_issue_props_and_more.py rename to apps/api/plane/db/migrations/0045_issueactivity_epoch_workspacemember_issue_props_and_more.py diff --git a/apiserver/plane/db/migrations/0046_label_sort_order_alter_analyticview_created_by_and_more.py b/apps/api/plane/db/migrations/0046_label_sort_order_alter_analyticview_created_by_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0046_label_sort_order_alter_analyticview_created_by_and_more.py rename to apps/api/plane/db/migrations/0046_label_sort_order_alter_analyticview_created_by_and_more.py diff --git a/apiserver/plane/db/migrations/0047_webhook_apitoken_description_apitoken_expired_at_and_more.py b/apps/api/plane/db/migrations/0047_webhook_apitoken_description_apitoken_expired_at_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0047_webhook_apitoken_description_apitoken_expired_at_and_more.py rename to apps/api/plane/db/migrations/0047_webhook_apitoken_description_apitoken_expired_at_and_more.py diff --git a/apiserver/plane/db/migrations/0048_auto_20231116_0713.py b/apps/api/plane/db/migrations/0048_auto_20231116_0713.py similarity index 100% rename from apiserver/plane/db/migrations/0048_auto_20231116_0713.py rename to apps/api/plane/db/migrations/0048_auto_20231116_0713.py diff --git a/apiserver/plane/db/migrations/0049_auto_20231116_0713.py b/apps/api/plane/db/migrations/0049_auto_20231116_0713.py similarity index 100% rename from apiserver/plane/db/migrations/0049_auto_20231116_0713.py rename to apps/api/plane/db/migrations/0049_auto_20231116_0713.py diff --git a/apiserver/plane/db/migrations/0050_user_use_case_alter_workspace_organization_size.py b/apps/api/plane/db/migrations/0050_user_use_case_alter_workspace_organization_size.py similarity index 100% rename from apiserver/plane/db/migrations/0050_user_use_case_alter_workspace_organization_size.py rename to apps/api/plane/db/migrations/0050_user_use_case_alter_workspace_organization_size.py diff --git a/apiserver/plane/db/migrations/0051_cycle_external_id_cycle_external_source_and_more.py b/apps/api/plane/db/migrations/0051_cycle_external_id_cycle_external_source_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0051_cycle_external_id_cycle_external_source_and_more.py rename to apps/api/plane/db/migrations/0051_cycle_external_id_cycle_external_source_and_more.py diff --git a/apiserver/plane/db/migrations/0052_auto_20231220_1141.py b/apps/api/plane/db/migrations/0052_auto_20231220_1141.py similarity index 100% rename from apiserver/plane/db/migrations/0052_auto_20231220_1141.py rename to apps/api/plane/db/migrations/0052_auto_20231220_1141.py diff --git a/apiserver/plane/db/migrations/0053_auto_20240102_1315.py b/apps/api/plane/db/migrations/0053_auto_20240102_1315.py similarity index 100% rename from apiserver/plane/db/migrations/0053_auto_20240102_1315.py rename to apps/api/plane/db/migrations/0053_auto_20240102_1315.py diff --git a/apiserver/plane/db/migrations/0054_dashboard_widget_dashboardwidget.py b/apps/api/plane/db/migrations/0054_dashboard_widget_dashboardwidget.py similarity index 100% rename from apiserver/plane/db/migrations/0054_dashboard_widget_dashboardwidget.py rename to apps/api/plane/db/migrations/0054_dashboard_widget_dashboardwidget.py diff --git a/apiserver/plane/db/migrations/0055_auto_20240108_0648.py b/apps/api/plane/db/migrations/0055_auto_20240108_0648.py similarity index 100% rename from apiserver/plane/db/migrations/0055_auto_20240108_0648.py rename to apps/api/plane/db/migrations/0055_auto_20240108_0648.py diff --git a/apiserver/plane/db/migrations/0056_usernotificationpreference_emailnotificationlog.py b/apps/api/plane/db/migrations/0056_usernotificationpreference_emailnotificationlog.py similarity index 100% rename from apiserver/plane/db/migrations/0056_usernotificationpreference_emailnotificationlog.py rename to apps/api/plane/db/migrations/0056_usernotificationpreference_emailnotificationlog.py diff --git a/apiserver/plane/db/migrations/0057_auto_20240122_0901.py b/apps/api/plane/db/migrations/0057_auto_20240122_0901.py similarity index 100% rename from apiserver/plane/db/migrations/0057_auto_20240122_0901.py rename to apps/api/plane/db/migrations/0057_auto_20240122_0901.py diff --git a/apiserver/plane/db/migrations/0058_alter_moduleissue_issue_and_more.py b/apps/api/plane/db/migrations/0058_alter_moduleissue_issue_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0058_alter_moduleissue_issue_and_more.py rename to apps/api/plane/db/migrations/0058_alter_moduleissue_issue_and_more.py diff --git a/apiserver/plane/db/migrations/0059_auto_20240208_0957.py b/apps/api/plane/db/migrations/0059_auto_20240208_0957.py similarity index 100% rename from apiserver/plane/db/migrations/0059_auto_20240208_0957.py rename to apps/api/plane/db/migrations/0059_auto_20240208_0957.py diff --git a/apiserver/plane/db/migrations/0060_cycle_progress_snapshot.py b/apps/api/plane/db/migrations/0060_cycle_progress_snapshot.py similarity index 100% rename from apiserver/plane/db/migrations/0060_cycle_progress_snapshot.py rename to apps/api/plane/db/migrations/0060_cycle_progress_snapshot.py diff --git a/apiserver/plane/db/migrations/0061_project_logo_props.py b/apps/api/plane/db/migrations/0061_project_logo_props.py similarity index 100% rename from apiserver/plane/db/migrations/0061_project_logo_props.py rename to apps/api/plane/db/migrations/0061_project_logo_props.py diff --git a/apiserver/plane/db/migrations/0062_cycle_archived_at_module_archived_at_and_more.py b/apps/api/plane/db/migrations/0062_cycle_archived_at_module_archived_at_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0062_cycle_archived_at_module_archived_at_and_more.py rename to apps/api/plane/db/migrations/0062_cycle_archived_at_module_archived_at_and_more.py diff --git a/apiserver/plane/db/migrations/0063_state_is_triage_alter_state_group.py b/apps/api/plane/db/migrations/0063_state_is_triage_alter_state_group.py similarity index 100% rename from apiserver/plane/db/migrations/0063_state_is_triage_alter_state_group.py rename to apps/api/plane/db/migrations/0063_state_is_triage_alter_state_group.py diff --git a/apiserver/plane/db/migrations/0064_auto_20240409_1134.py b/apps/api/plane/db/migrations/0064_auto_20240409_1134.py similarity index 100% rename from apiserver/plane/db/migrations/0064_auto_20240409_1134.py rename to apps/api/plane/db/migrations/0064_auto_20240409_1134.py diff --git a/apiserver/plane/db/migrations/0065_auto_20240415_0937.py b/apps/api/plane/db/migrations/0065_auto_20240415_0937.py similarity index 100% rename from apiserver/plane/db/migrations/0065_auto_20240415_0937.py rename to apps/api/plane/db/migrations/0065_auto_20240415_0937.py diff --git a/apiserver/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py b/apps/api/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py similarity index 100% rename from apiserver/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py rename to apps/api/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py diff --git a/apiserver/plane/db/migrations/0067_issue_estimate.py b/apps/api/plane/db/migrations/0067_issue_estimate.py similarity index 100% rename from apiserver/plane/db/migrations/0067_issue_estimate.py rename to apps/api/plane/db/migrations/0067_issue_estimate.py diff --git a/apiserver/plane/db/migrations/0068_remove_pagelabel_project_remove_pagelog_project_and_more.py b/apps/api/plane/db/migrations/0068_remove_pagelabel_project_remove_pagelog_project_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0068_remove_pagelabel_project_remove_pagelog_project_and_more.py rename to apps/api/plane/db/migrations/0068_remove_pagelabel_project_remove_pagelog_project_and_more.py diff --git a/apiserver/plane/db/migrations/0069_alter_account_provider_and_more.py b/apps/api/plane/db/migrations/0069_alter_account_provider_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0069_alter_account_provider_and_more.py rename to apps/api/plane/db/migrations/0069_alter_account_provider_and_more.py diff --git a/apiserver/plane/db/migrations/0070_apitoken_is_service_exporterhistory_filters_and_more.py b/apps/api/plane/db/migrations/0070_apitoken_is_service_exporterhistory_filters_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0070_apitoken_is_service_exporterhistory_filters_and_more.py rename to apps/api/plane/db/migrations/0070_apitoken_is_service_exporterhistory_filters_and_more.py diff --git a/apiserver/plane/db/migrations/0071_rename_issueproperty_issueuserproperty_and_more.py b/apps/api/plane/db/migrations/0071_rename_issueproperty_issueuserproperty_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0071_rename_issueproperty_issueuserproperty_and_more.py rename to apps/api/plane/db/migrations/0071_rename_issueproperty_issueuserproperty_and_more.py diff --git a/apiserver/plane/db/migrations/0072_issueattachment_external_id_and_more.py b/apps/api/plane/db/migrations/0072_issueattachment_external_id_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0072_issueattachment_external_id_and_more.py rename to apps/api/plane/db/migrations/0072_issueattachment_external_id_and_more.py diff --git a/apiserver/plane/db/migrations/0073_alter_commentreaction_unique_together_and_more.py b/apps/api/plane/db/migrations/0073_alter_commentreaction_unique_together_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0073_alter_commentreaction_unique_together_and_more.py rename to apps/api/plane/db/migrations/0073_alter_commentreaction_unique_together_and_more.py diff --git a/apiserver/plane/db/migrations/0074_deploy_board_and_project_issues.py b/apps/api/plane/db/migrations/0074_deploy_board_and_project_issues.py similarity index 100% rename from apiserver/plane/db/migrations/0074_deploy_board_and_project_issues.py rename to apps/api/plane/db/migrations/0074_deploy_board_and_project_issues.py diff --git a/apiserver/plane/db/migrations/0075_alter_fileasset_asset.py b/apps/api/plane/db/migrations/0075_alter_fileasset_asset.py similarity index 100% rename from apiserver/plane/db/migrations/0075_alter_fileasset_asset.py rename to apps/api/plane/db/migrations/0075_alter_fileasset_asset.py diff --git a/apiserver/plane/db/migrations/0076_alter_projectmember_role_and_more.py b/apps/api/plane/db/migrations/0076_alter_projectmember_role_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0076_alter_projectmember_role_and_more.py rename to apps/api/plane/db/migrations/0076_alter_projectmember_role_and_more.py diff --git a/apiserver/plane/db/migrations/0077_draftissue_cycle_user_timezone_project_user_timezone_and_more.py b/apps/api/plane/db/migrations/0077_draftissue_cycle_user_timezone_project_user_timezone_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0077_draftissue_cycle_user_timezone_project_user_timezone_and_more.py rename to apps/api/plane/db/migrations/0077_draftissue_cycle_user_timezone_project_user_timezone_and_more.py diff --git a/apiserver/plane/db/migrations/0078_fileasset_comment_fileasset_entity_type_and_more.py b/apps/api/plane/db/migrations/0078_fileasset_comment_fileasset_entity_type_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0078_fileasset_comment_fileasset_entity_type_and_more.py rename to apps/api/plane/db/migrations/0078_fileasset_comment_fileasset_entity_type_and_more.py diff --git a/apiserver/plane/db/migrations/0079_auto_20241009_0619.py b/apps/api/plane/db/migrations/0079_auto_20241009_0619.py similarity index 100% rename from apiserver/plane/db/migrations/0079_auto_20241009_0619.py rename to apps/api/plane/db/migrations/0079_auto_20241009_0619.py diff --git a/apiserver/plane/db/migrations/0080_fileasset_draft_issue_alter_fileasset_entity_type.py b/apps/api/plane/db/migrations/0080_fileasset_draft_issue_alter_fileasset_entity_type.py similarity index 100% rename from apiserver/plane/db/migrations/0080_fileasset_draft_issue_alter_fileasset_entity_type.py rename to apps/api/plane/db/migrations/0080_fileasset_draft_issue_alter_fileasset_entity_type.py diff --git a/apiserver/plane/db/migrations/0081_remove_globalview_created_by_and_more.py b/apps/api/plane/db/migrations/0081_remove_globalview_created_by_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0081_remove_globalview_created_by_and_more.py rename to apps/api/plane/db/migrations/0081_remove_globalview_created_by_and_more.py diff --git a/apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py b/apps/api/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py rename to apps/api/plane/db/migrations/0082_alter_issue_managers_alter_cycleissue_issue_and_more.py diff --git a/apiserver/plane/db/migrations/0083_device_workspace_timezone_and_more.py b/apps/api/plane/db/migrations/0083_device_workspace_timezone_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0083_device_workspace_timezone_and_more.py rename to apps/api/plane/db/migrations/0083_device_workspace_timezone_and_more.py diff --git a/apiserver/plane/db/migrations/0084_remove_label_label_unique_name_project_when_deleted_at_null_and_more.py b/apps/api/plane/db/migrations/0084_remove_label_label_unique_name_project_when_deleted_at_null_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0084_remove_label_label_unique_name_project_when_deleted_at_null_and_more.py rename to apps/api/plane/db/migrations/0084_remove_label_label_unique_name_project_when_deleted_at_null_and_more.py diff --git a/apiserver/plane/db/migrations/0085_intake_intakeissue_remove_inboxissue_created_by_and_more.py b/apps/api/plane/db/migrations/0085_intake_intakeissue_remove_inboxissue_created_by_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0085_intake_intakeissue_remove_inboxissue_created_by_and_more.py rename to apps/api/plane/db/migrations/0085_intake_intakeissue_remove_inboxissue_created_by_and_more.py diff --git a/apiserver/plane/db/migrations/0086_issueversion_alter_teampage_unique_together_and_more.py b/apps/api/plane/db/migrations/0086_issueversion_alter_teampage_unique_together_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0086_issueversion_alter_teampage_unique_together_and_more.py rename to apps/api/plane/db/migrations/0086_issueversion_alter_teampage_unique_together_and_more.py diff --git a/apiserver/plane/db/migrations/0087_remove_issueversion_description_and_more.py b/apps/api/plane/db/migrations/0087_remove_issueversion_description_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0087_remove_issueversion_description_and_more.py rename to apps/api/plane/db/migrations/0087_remove_issueversion_description_and_more.py diff --git a/apiserver/plane/db/migrations/0088_sticky_sort_order_workspaceuserlink.py b/apps/api/plane/db/migrations/0088_sticky_sort_order_workspaceuserlink.py similarity index 100% rename from apiserver/plane/db/migrations/0088_sticky_sort_order_workspaceuserlink.py rename to apps/api/plane/db/migrations/0088_sticky_sort_order_workspaceuserlink.py diff --git a/apiserver/plane/db/migrations/0089_workspacehomepreference_and_more.py b/apps/api/plane/db/migrations/0089_workspacehomepreference_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0089_workspacehomepreference_and_more.py rename to apps/api/plane/db/migrations/0089_workspacehomepreference_and_more.py diff --git a/apiserver/plane/db/migrations/0090_rename_dashboard_deprecateddashboard_and_more.py b/apps/api/plane/db/migrations/0090_rename_dashboard_deprecateddashboard_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0090_rename_dashboard_deprecateddashboard_and_more.py rename to apps/api/plane/db/migrations/0090_rename_dashboard_deprecateddashboard_and_more.py diff --git a/apiserver/plane/db/migrations/0091_issuecomment_edited_at_and_more.py b/apps/api/plane/db/migrations/0091_issuecomment_edited_at_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0091_issuecomment_edited_at_and_more.py rename to apps/api/plane/db/migrations/0091_issuecomment_edited_at_and_more.py diff --git a/apiserver/plane/db/migrations/0092_alter_deprecateddashboardwidget_unique_together_and_more.py b/apps/api/plane/db/migrations/0092_alter_deprecateddashboardwidget_unique_together_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0092_alter_deprecateddashboardwidget_unique_together_and_more.py rename to apps/api/plane/db/migrations/0092_alter_deprecateddashboardwidget_unique_together_and_more.py diff --git a/apiserver/plane/db/migrations/0093_page_moved_to_page_page_moved_to_project_and_more.py b/apps/api/plane/db/migrations/0093_page_moved_to_page_page_moved_to_project_and_more.py similarity index 100% rename from apiserver/plane/db/migrations/0093_page_moved_to_page_page_moved_to_project_and_more.py rename to apps/api/plane/db/migrations/0093_page_moved_to_page_page_moved_to_project_and_more.py diff --git a/apiserver/plane/db/migrations/0094_auto_20250425_0902.py b/apps/api/plane/db/migrations/0094_auto_20250425_0902.py similarity index 100% rename from apiserver/plane/db/migrations/0094_auto_20250425_0902.py rename to apps/api/plane/db/migrations/0094_auto_20250425_0902.py diff --git a/apiserver/plane/db/migrations/0095_page_external_id_page_external_source.py b/apps/api/plane/db/migrations/0095_page_external_id_page_external_source.py similarity index 100% rename from apiserver/plane/db/migrations/0095_page_external_id_page_external_source.py rename to apps/api/plane/db/migrations/0095_page_external_id_page_external_source.py diff --git a/apiserver/plane/db/migrations/0096_user_is_email_valid_user_masked_at.py b/apps/api/plane/db/migrations/0096_user_is_email_valid_user_masked_at.py similarity index 100% rename from apiserver/plane/db/migrations/0096_user_is_email_valid_user_masked_at.py rename to apps/api/plane/db/migrations/0096_user_is_email_valid_user_masked_at.py diff --git a/apiserver/plane/db/migrations/0097_project_external_id_project_external_source.py b/apps/api/plane/db/migrations/0097_project_external_id_project_external_source.py similarity index 100% rename from apiserver/plane/db/migrations/0097_project_external_id_project_external_source.py rename to apps/api/plane/db/migrations/0097_project_external_id_project_external_source.py diff --git a/apps/api/plane/db/migrations/0098_profile_is_app_rail_docked_and_more.py b/apps/api/plane/db/migrations/0098_profile_is_app_rail_docked_and_more.py new file mode 100644 index 000000000..db648ad56 --- /dev/null +++ b/apps/api/plane/db/migrations/0098_profile_is_app_rail_docked_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.21 on 2025-07-14 10:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0097_project_external_id_project_external_source'), + ] + + operations = [ + migrations.AddField( + model_name='profile', + name='is_app_rail_docked', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='commentreaction', + name='reaction', + field=models.TextField(), + ), + migrations.AlterField( + model_name='issuereaction', + name='reaction', + field=models.TextField(), + ), + ] diff --git a/apiserver/plane/db/migrations/__init__.py b/apps/api/plane/db/migrations/__init__.py similarity index 100% rename from apiserver/plane/db/migrations/__init__.py rename to apps/api/plane/db/migrations/__init__.py diff --git a/apiserver/plane/db/mixins.py b/apps/api/plane/db/mixins.py similarity index 100% rename from apiserver/plane/db/mixins.py rename to apps/api/plane/db/mixins.py diff --git a/apiserver/plane/db/models/__init__.py b/apps/api/plane/db/models/__init__.py similarity index 100% rename from apiserver/plane/db/models/__init__.py rename to apps/api/plane/db/models/__init__.py diff --git a/apiserver/plane/db/models/analytic.py b/apps/api/plane/db/models/analytic.py similarity index 100% rename from apiserver/plane/db/models/analytic.py rename to apps/api/plane/db/models/analytic.py diff --git a/apiserver/plane/db/models/api.py b/apps/api/plane/db/models/api.py similarity index 100% rename from apiserver/plane/db/models/api.py rename to apps/api/plane/db/models/api.py diff --git a/apiserver/plane/db/models/asset.py b/apps/api/plane/db/models/asset.py similarity index 100% rename from apiserver/plane/db/models/asset.py rename to apps/api/plane/db/models/asset.py diff --git a/apiserver/plane/db/models/base.py b/apps/api/plane/db/models/base.py similarity index 100% rename from apiserver/plane/db/models/base.py rename to apps/api/plane/db/models/base.py diff --git a/apiserver/plane/db/models/cycle.py b/apps/api/plane/db/models/cycle.py similarity index 100% rename from apiserver/plane/db/models/cycle.py rename to apps/api/plane/db/models/cycle.py diff --git a/apiserver/plane/db/models/deploy_board.py b/apps/api/plane/db/models/deploy_board.py similarity index 100% rename from apiserver/plane/db/models/deploy_board.py rename to apps/api/plane/db/models/deploy_board.py diff --git a/apiserver/plane/db/models/device.py b/apps/api/plane/db/models/device.py similarity index 100% rename from apiserver/plane/db/models/device.py rename to apps/api/plane/db/models/device.py diff --git a/apiserver/plane/db/models/draft.py b/apps/api/plane/db/models/draft.py similarity index 100% rename from apiserver/plane/db/models/draft.py rename to apps/api/plane/db/models/draft.py diff --git a/apiserver/plane/db/models/estimate.py b/apps/api/plane/db/models/estimate.py similarity index 100% rename from apiserver/plane/db/models/estimate.py rename to apps/api/plane/db/models/estimate.py diff --git a/apiserver/plane/db/models/exporter.py b/apps/api/plane/db/models/exporter.py similarity index 100% rename from apiserver/plane/db/models/exporter.py rename to apps/api/plane/db/models/exporter.py diff --git a/apiserver/plane/db/models/favorite.py b/apps/api/plane/db/models/favorite.py similarity index 100% rename from apiserver/plane/db/models/favorite.py rename to apps/api/plane/db/models/favorite.py diff --git a/apiserver/plane/db/models/importer.py b/apps/api/plane/db/models/importer.py similarity index 100% rename from apiserver/plane/db/models/importer.py rename to apps/api/plane/db/models/importer.py diff --git a/apiserver/plane/db/models/intake.py b/apps/api/plane/db/models/intake.py similarity index 100% rename from apiserver/plane/db/models/intake.py rename to apps/api/plane/db/models/intake.py diff --git a/apiserver/plane/db/models/integration/__init__.py b/apps/api/plane/db/models/integration/__init__.py similarity index 100% rename from apiserver/plane/db/models/integration/__init__.py rename to apps/api/plane/db/models/integration/__init__.py diff --git a/apiserver/plane/db/models/integration/base.py b/apps/api/plane/db/models/integration/base.py similarity index 100% rename from apiserver/plane/db/models/integration/base.py rename to apps/api/plane/db/models/integration/base.py diff --git a/apiserver/plane/db/models/integration/github.py b/apps/api/plane/db/models/integration/github.py similarity index 100% rename from apiserver/plane/db/models/integration/github.py rename to apps/api/plane/db/models/integration/github.py diff --git a/apiserver/plane/db/models/integration/slack.py b/apps/api/plane/db/models/integration/slack.py similarity index 100% rename from apiserver/plane/db/models/integration/slack.py rename to apps/api/plane/db/models/integration/slack.py diff --git a/apiserver/plane/db/models/issue.py b/apps/api/plane/db/models/issue.py similarity index 93% rename from apiserver/plane/db/models/issue.py rename to apps/api/plane/db/models/issue.py index dad7aab3f..a3994d79e 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apps/api/plane/db/models/issue.py @@ -215,30 +215,37 @@ class Issue(ProjectBaseModel): with connection.cursor() as cursor: # Get an exclusive lock using the project ID as the lock key - cursor.execute("SELECT pg_advisory_xact_lock(%s)", [lock_key]) + cursor.execute("SELECT pg_advisory_lock(%s)", [lock_key]) - # Get the last sequence for the project - last_sequence = IssueSequence.objects.filter( - project=self.project - ).aggregate(largest=models.Max("sequence"))["largest"] - self.sequence_id = last_sequence + 1 if last_sequence else 1 - # Strip the html tags using html parser - self.description_stripped = ( - None - if (self.description_html == "" or self.description_html is None) - else strip_tags(self.description_html) - ) - largest_sort_order = Issue.objects.filter( - project=self.project, state=self.state - ).aggregate(largest=models.Max("sort_order"))["largest"] - if largest_sort_order is not None: - self.sort_order = largest_sort_order + 10000 + try: + # Get the last sequence for the project + last_sequence = IssueSequence.objects.filter( + project=self.project + ).aggregate(largest=models.Max("sequence"))["largest"] + self.sequence_id = last_sequence + 1 if last_sequence else 1 + # Strip the html tags using html parser + self.description_stripped = ( + None + if ( + self.description_html == "" or self.description_html is None + ) + else strip_tags(self.description_html) + ) + largest_sort_order = Issue.objects.filter( + project=self.project, state=self.state + ).aggregate(largest=models.Max("sort_order"))["largest"] + if largest_sort_order is not None: + self.sort_order = largest_sort_order + 10000 - super(Issue, self).save(*args, **kwargs) + super(Issue, self).save(*args, **kwargs) - IssueSequence.objects.create( - issue=self, sequence=self.sequence_id, project=self.project - ) + IssueSequence.objects.create( + issue=self, sequence=self.sequence_id, project=self.project + ) + finally: + # Release the lock + with connection.cursor() as cursor: + cursor.execute("SELECT pg_advisory_unlock(%s)", [lock_key]) else: # Strip the html tags using html parser self.description_stripped = ( @@ -271,15 +278,15 @@ class IssueBlocker(ProjectBaseModel): return f"{self.block.name} {self.blocked_by.name}" -class IssueRelation(ProjectBaseModel): - RELATION_CHOICES = ( - ("duplicate", "Duplicate"), - ("relates_to", "Relates To"), - ("blocked_by", "Blocked By"), - ("start_before", "Start Before"), - ("finish_before", "Finish Before"), - ) +class IssueRelationChoices(models.TextChoices): + DUPLICATE = "duplicate", "Duplicate" + RELATES_TO = "relates_to", "Relates To" + BLOCKED_BY = "blocked_by", "Blocked By" + START_BEFORE = "start_before", "Start Before" + FINISH_BEFORE = "finish_before", "Finish Before" + +class IssueRelation(ProjectBaseModel): issue = models.ForeignKey( Issue, related_name="issue_relation", on_delete=models.CASCADE ) @@ -288,9 +295,9 @@ class IssueRelation(ProjectBaseModel): ) relation_type = models.CharField( max_length=20, - choices=RELATION_CHOICES, + choices=IssueRelationChoices.choices, verbose_name="Issue Relation Type", - default="blocked_by", + default=IssueRelationChoices.BLOCKED_BY, ) class Meta: @@ -594,7 +601,7 @@ class IssueReaction(ProjectBaseModel): issue = models.ForeignKey( Issue, on_delete=models.CASCADE, related_name="issue_reactions" ) - reaction = models.CharField(max_length=20) + reaction = models.TextField() class Meta: unique_together = ["issue", "actor", "reaction", "deleted_at"] @@ -623,7 +630,7 @@ class CommentReaction(ProjectBaseModel): comment = models.ForeignKey( IssueComment, on_delete=models.CASCADE, related_name="comment_reactions" ) - reaction = models.CharField(max_length=20) + reaction = models.TextField() class Meta: unique_together = ["comment", "actor", "reaction", "deleted_at"] diff --git a/apiserver/plane/db/models/issue_type.py b/apps/api/plane/db/models/issue_type.py similarity index 100% rename from apiserver/plane/db/models/issue_type.py rename to apps/api/plane/db/models/issue_type.py diff --git a/apiserver/plane/db/models/label.py b/apps/api/plane/db/models/label.py similarity index 100% rename from apiserver/plane/db/models/label.py rename to apps/api/plane/db/models/label.py diff --git a/apiserver/plane/db/models/module.py b/apps/api/plane/db/models/module.py similarity index 100% rename from apiserver/plane/db/models/module.py rename to apps/api/plane/db/models/module.py diff --git a/apiserver/plane/db/models/notification.py b/apps/api/plane/db/models/notification.py similarity index 100% rename from apiserver/plane/db/models/notification.py rename to apps/api/plane/db/models/notification.py diff --git a/apiserver/plane/db/models/page.py b/apps/api/plane/db/models/page.py similarity index 100% rename from apiserver/plane/db/models/page.py rename to apps/api/plane/db/models/page.py diff --git a/apiserver/plane/db/models/project.py b/apps/api/plane/db/models/project.py similarity index 100% rename from apiserver/plane/db/models/project.py rename to apps/api/plane/db/models/project.py diff --git a/apiserver/plane/db/models/recent_visit.py b/apps/api/plane/db/models/recent_visit.py similarity index 100% rename from apiserver/plane/db/models/recent_visit.py rename to apps/api/plane/db/models/recent_visit.py diff --git a/apiserver/plane/db/models/session.py b/apps/api/plane/db/models/session.py similarity index 100% rename from apiserver/plane/db/models/session.py rename to apps/api/plane/db/models/session.py diff --git a/apiserver/plane/db/models/social_connection.py b/apps/api/plane/db/models/social_connection.py similarity index 100% rename from apiserver/plane/db/models/social_connection.py rename to apps/api/plane/db/models/social_connection.py diff --git a/apiserver/plane/db/models/state.py b/apps/api/plane/db/models/state.py similarity index 100% rename from apiserver/plane/db/models/state.py rename to apps/api/plane/db/models/state.py diff --git a/apiserver/plane/db/models/sticky.py b/apps/api/plane/db/models/sticky.py similarity index 100% rename from apiserver/plane/db/models/sticky.py rename to apps/api/plane/db/models/sticky.py diff --git a/apiserver/plane/db/models/user.py b/apps/api/plane/db/models/user.py similarity index 99% rename from apiserver/plane/db/models/user.py rename to apps/api/plane/db/models/user.py index ad6e858ad..b2613a427 100644 --- a/apiserver/plane/db/models/user.py +++ b/apps/api/plane/db/models/user.py @@ -197,6 +197,7 @@ class Profile(TimeAuditModel): ) # General theme = models.JSONField(default=dict) + is_app_rail_docked = models.BooleanField(default=True) # Onboarding is_tour_completed = models.BooleanField(default=False) onboarding_step = models.JSONField(default=get_default_onboarding) diff --git a/apiserver/plane/db/models/view.py b/apps/api/plane/db/models/view.py similarity index 100% rename from apiserver/plane/db/models/view.py rename to apps/api/plane/db/models/view.py diff --git a/apiserver/plane/db/models/webhook.py b/apps/api/plane/db/models/webhook.py similarity index 100% rename from apiserver/plane/db/models/webhook.py rename to apps/api/plane/db/models/webhook.py diff --git a/apiserver/plane/db/models/workspace.py b/apps/api/plane/db/models/workspace.py similarity index 100% rename from apiserver/plane/db/models/workspace.py rename to apps/api/plane/db/models/workspace.py diff --git a/apiserver/plane/license/__init__.py b/apps/api/plane/license/__init__.py similarity index 100% rename from apiserver/plane/license/__init__.py rename to apps/api/plane/license/__init__.py diff --git a/apiserver/plane/license/api/__init__.py b/apps/api/plane/license/api/__init__.py similarity index 100% rename from apiserver/plane/license/api/__init__.py rename to apps/api/plane/license/api/__init__.py diff --git a/apiserver/plane/license/api/permissions/__init__.py b/apps/api/plane/license/api/permissions/__init__.py similarity index 100% rename from apiserver/plane/license/api/permissions/__init__.py rename to apps/api/plane/license/api/permissions/__init__.py diff --git a/apiserver/plane/license/api/permissions/instance.py b/apps/api/plane/license/api/permissions/instance.py similarity index 100% rename from apiserver/plane/license/api/permissions/instance.py rename to apps/api/plane/license/api/permissions/instance.py diff --git a/apiserver/plane/license/api/serializers/__init__.py b/apps/api/plane/license/api/serializers/__init__.py similarity index 100% rename from apiserver/plane/license/api/serializers/__init__.py rename to apps/api/plane/license/api/serializers/__init__.py diff --git a/apiserver/plane/license/api/serializers/admin.py b/apps/api/plane/license/api/serializers/admin.py similarity index 100% rename from apiserver/plane/license/api/serializers/admin.py rename to apps/api/plane/license/api/serializers/admin.py diff --git a/apiserver/plane/license/api/serializers/base.py b/apps/api/plane/license/api/serializers/base.py similarity index 100% rename from apiserver/plane/license/api/serializers/base.py rename to apps/api/plane/license/api/serializers/base.py diff --git a/apiserver/plane/license/api/serializers/configuration.py b/apps/api/plane/license/api/serializers/configuration.py similarity index 100% rename from apiserver/plane/license/api/serializers/configuration.py rename to apps/api/plane/license/api/serializers/configuration.py diff --git a/apiserver/plane/license/api/serializers/instance.py b/apps/api/plane/license/api/serializers/instance.py similarity index 100% rename from apiserver/plane/license/api/serializers/instance.py rename to apps/api/plane/license/api/serializers/instance.py diff --git a/apiserver/plane/license/api/serializers/user.py b/apps/api/plane/license/api/serializers/user.py similarity index 100% rename from apiserver/plane/license/api/serializers/user.py rename to apps/api/plane/license/api/serializers/user.py diff --git a/apiserver/plane/license/api/serializers/workspace.py b/apps/api/plane/license/api/serializers/workspace.py similarity index 100% rename from apiserver/plane/license/api/serializers/workspace.py rename to apps/api/plane/license/api/serializers/workspace.py diff --git a/apiserver/plane/license/api/views/__init__.py b/apps/api/plane/license/api/views/__init__.py similarity index 75% rename from apiserver/plane/license/api/views/__init__.py rename to apps/api/plane/license/api/views/__init__.py index a2ef90fac..7f30d53fe 100644 --- a/apiserver/plane/license/api/views/__init__.py +++ b/apps/api/plane/license/api/views/__init__.py @@ -1,7 +1,11 @@ from .instance import InstanceEndpoint, SignUpScreenVisitedEndpoint -from .configuration import EmailCredentialCheckEndpoint, InstanceConfigurationEndpoint +from .configuration import ( + EmailCredentialCheckEndpoint, + InstanceConfigurationEndpoint, + DisableEmailFeatureEndpoint, +) from .admin import ( diff --git a/apiserver/plane/license/api/views/admin.py b/apps/api/plane/license/api/views/admin.py similarity index 100% rename from apiserver/plane/license/api/views/admin.py rename to apps/api/plane/license/api/views/admin.py diff --git a/apiserver/plane/license/api/views/base.py b/apps/api/plane/license/api/views/base.py similarity index 100% rename from apiserver/plane/license/api/views/base.py rename to apps/api/plane/license/api/views/base.py diff --git a/apiserver/plane/license/api/views/configuration.py b/apps/api/plane/license/api/views/configuration.py similarity index 84% rename from apiserver/plane/license/api/views/configuration.py rename to apps/api/plane/license/api/views/configuration.py index 594a899eb..3bf996db9 100644 --- a/apiserver/plane/license/api/views/configuration.py +++ b/apps/api/plane/license/api/views/configuration.py @@ -9,6 +9,7 @@ from smtplib import ( # Django imports from django.core.mail import BadHeaderError, EmailMultiAlternatives, get_connection +from django.db.models import Q, Case, When, Value # Third party imports from rest_framework import status @@ -57,6 +58,34 @@ class InstanceConfigurationEndpoint(BaseAPIView): return Response(serializer.data, status=status.HTTP_200_OK) +class DisableEmailFeatureEndpoint(BaseAPIView): + permission_classes = [InstanceAdminPermission] + + @invalidate_cache(path="/api/instances/", user=False) + def delete(self, request): + try: + InstanceConfiguration.objects.filter( + Q( + key__in=[ + "EMAIL_HOST", + "EMAIL_HOST_USER", + "EMAIL_HOST_PASSWORD", + "ENABLE_SMTP", + "EMAIL_PORT", + "EMAIL_FROM", + ] + ) + ).update( + value=Case(When(key="ENABLE_SMTP", then=Value("0")), default=Value("")) + ) + return Response(status=status.HTTP_200_OK) + except Exception: + return Response( + {"error": "Failed to disable email configuration"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + class EmailCredentialCheckEndpoint(BaseAPIView): def post(self, request): receiver_email = request.data.get("receiver_email", False) diff --git a/apiserver/plane/license/api/views/instance.py b/apps/api/plane/license/api/views/instance.py similarity index 100% rename from apiserver/plane/license/api/views/instance.py rename to apps/api/plane/license/api/views/instance.py diff --git a/apiserver/plane/license/api/views/workspace.py b/apps/api/plane/license/api/views/workspace.py similarity index 100% rename from apiserver/plane/license/api/views/workspace.py rename to apps/api/plane/license/api/views/workspace.py diff --git a/apiserver/plane/license/apps.py b/apps/api/plane/license/apps.py similarity index 100% rename from apiserver/plane/license/apps.py rename to apps/api/plane/license/apps.py diff --git a/apiserver/plane/license/bgtasks/__init__.py b/apps/api/plane/license/bgtasks/__init__.py similarity index 100% rename from apiserver/plane/license/bgtasks/__init__.py rename to apps/api/plane/license/bgtasks/__init__.py diff --git a/apiserver/plane/license/bgtasks/tracer.py b/apps/api/plane/license/bgtasks/tracer.py similarity index 100% rename from apiserver/plane/license/bgtasks/tracer.py rename to apps/api/plane/license/bgtasks/tracer.py diff --git a/apiserver/plane/license/management/__init__.py b/apps/api/plane/license/management/__init__.py similarity index 100% rename from apiserver/plane/license/management/__init__.py rename to apps/api/plane/license/management/__init__.py diff --git a/apiserver/plane/license/management/commands/__init__.py b/apps/api/plane/license/management/commands/__init__.py similarity index 100% rename from apiserver/plane/license/management/commands/__init__.py rename to apps/api/plane/license/management/commands/__init__.py diff --git a/apiserver/plane/license/management/commands/configure_instance.py b/apps/api/plane/license/management/commands/configure_instance.py similarity index 98% rename from apiserver/plane/license/management/commands/configure_instance.py rename to apps/api/plane/license/management/commands/configure_instance.py index 2e1b6a123..1414c970c 100644 --- a/apiserver/plane/license/management/commands/configure_instance.py +++ b/apps/api/plane/license/management/commands/configure_instance.py @@ -89,6 +89,12 @@ class Command(BaseCommand): "category": "GITLAB", "is_encrypted": False, }, + { + "key": "ENABLE_SMTP", + "value": os.environ.get("ENABLE_SMTP", "0"), + "category": "SMTP", + "is_encrypted": False, + }, { "key": "GITLAB_CLIENT_SECRET", "value": os.environ.get("GITLAB_CLIENT_SECRET"), diff --git a/apiserver/plane/license/management/commands/register_instance.py b/apps/api/plane/license/management/commands/register_instance.py similarity index 100% rename from apiserver/plane/license/management/commands/register_instance.py rename to apps/api/plane/license/management/commands/register_instance.py diff --git a/apiserver/plane/license/migrations/0001_initial.py b/apps/api/plane/license/migrations/0001_initial.py similarity index 100% rename from apiserver/plane/license/migrations/0001_initial.py rename to apps/api/plane/license/migrations/0001_initial.py diff --git a/apiserver/plane/license/migrations/0002_rename_version_instance_current_version_and_more.py b/apps/api/plane/license/migrations/0002_rename_version_instance_current_version_and_more.py similarity index 100% rename from apiserver/plane/license/migrations/0002_rename_version_instance_current_version_and_more.py rename to apps/api/plane/license/migrations/0002_rename_version_instance_current_version_and_more.py diff --git a/apiserver/plane/license/migrations/0003_alter_changelog_title_alter_changelog_version_and_more.py b/apps/api/plane/license/migrations/0003_alter_changelog_title_alter_changelog_version_and_more.py similarity index 100% rename from apiserver/plane/license/migrations/0003_alter_changelog_title_alter_changelog_version_and_more.py rename to apps/api/plane/license/migrations/0003_alter_changelog_title_alter_changelog_version_and_more.py diff --git a/apiserver/plane/license/migrations/0004_changelog_deleted_at_instance_deleted_at_and_more.py b/apps/api/plane/license/migrations/0004_changelog_deleted_at_instance_deleted_at_and_more.py similarity index 100% rename from apiserver/plane/license/migrations/0004_changelog_deleted_at_instance_deleted_at_and_more.py rename to apps/api/plane/license/migrations/0004_changelog_deleted_at_instance_deleted_at_and_more.py diff --git a/apiserver/plane/license/migrations/0005_rename_product_instance_edition_and_more.py b/apps/api/plane/license/migrations/0005_rename_product_instance_edition_and_more.py similarity index 100% rename from apiserver/plane/license/migrations/0005_rename_product_instance_edition_and_more.py rename to apps/api/plane/license/migrations/0005_rename_product_instance_edition_and_more.py diff --git a/apiserver/plane/license/migrations/__init__.py b/apps/api/plane/license/migrations/__init__.py similarity index 100% rename from apiserver/plane/license/migrations/__init__.py rename to apps/api/plane/license/migrations/__init__.py diff --git a/apiserver/plane/license/models/__init__.py b/apps/api/plane/license/models/__init__.py similarity index 100% rename from apiserver/plane/license/models/__init__.py rename to apps/api/plane/license/models/__init__.py diff --git a/apiserver/plane/license/models/instance.py b/apps/api/plane/license/models/instance.py similarity index 100% rename from apiserver/plane/license/models/instance.py rename to apps/api/plane/license/models/instance.py diff --git a/apiserver/plane/license/urls.py b/apps/api/plane/license/urls.py similarity index 91% rename from apiserver/plane/license/urls.py rename to apps/api/plane/license/urls.py index 9c3adbf98..4d306924e 100644 --- a/apiserver/plane/license/urls.py +++ b/apps/api/plane/license/urls.py @@ -6,6 +6,7 @@ from plane.license.api.views import ( InstanceAdminSignInEndpoint, InstanceAdminSignUpEndpoint, InstanceConfigurationEndpoint, + DisableEmailFeatureEndpoint, InstanceEndpoint, SignUpScreenVisitedEndpoint, InstanceAdminUserMeEndpoint, @@ -35,6 +36,11 @@ urlpatterns = [ InstanceConfigurationEndpoint.as_view(), name="instance-configuration", ), + path( + "configurations/disable-email-feature/", + DisableEmailFeatureEndpoint.as_view(), + name="disable-email-configuration", + ), path( "admins/sign-in/", InstanceAdminSignInEndpoint.as_view(), diff --git a/apiserver/plane/license/utils/__init__.py b/apps/api/plane/license/utils/__init__.py similarity index 100% rename from apiserver/plane/license/utils/__init__.py rename to apps/api/plane/license/utils/__init__.py diff --git a/apiserver/plane/license/utils/encryption.py b/apps/api/plane/license/utils/encryption.py similarity index 100% rename from apiserver/plane/license/utils/encryption.py rename to apps/api/plane/license/utils/encryption.py diff --git a/apiserver/plane/license/utils/instance_value.py b/apps/api/plane/license/utils/instance_value.py similarity index 100% rename from apiserver/plane/license/utils/instance_value.py rename to apps/api/plane/license/utils/instance_value.py diff --git a/apiserver/plane/middleware/__init__.py b/apps/api/plane/middleware/__init__.py similarity index 100% rename from apiserver/plane/middleware/__init__.py rename to apps/api/plane/middleware/__init__.py diff --git a/apiserver/plane/middleware/apps.py b/apps/api/plane/middleware/apps.py similarity index 100% rename from apiserver/plane/middleware/apps.py rename to apps/api/plane/middleware/apps.py diff --git a/apiserver/plane/middleware/logger.py b/apps/api/plane/middleware/logger.py similarity index 100% rename from apiserver/plane/middleware/logger.py rename to apps/api/plane/middleware/logger.py diff --git a/apiserver/plane/seeds/data/issues.json b/apps/api/plane/seeds/data/issues.json similarity index 100% rename from apiserver/plane/seeds/data/issues.json rename to apps/api/plane/seeds/data/issues.json diff --git a/apiserver/plane/seeds/data/labels.json b/apps/api/plane/seeds/data/labels.json similarity index 100% rename from apiserver/plane/seeds/data/labels.json rename to apps/api/plane/seeds/data/labels.json diff --git a/apiserver/plane/seeds/data/projects.json b/apps/api/plane/seeds/data/projects.json similarity index 100% rename from apiserver/plane/seeds/data/projects.json rename to apps/api/plane/seeds/data/projects.json diff --git a/apiserver/plane/seeds/data/states.json b/apps/api/plane/seeds/data/states.json similarity index 100% rename from apiserver/plane/seeds/data/states.json rename to apps/api/plane/seeds/data/states.json diff --git a/apiserver/plane/settings/__init__.py b/apps/api/plane/settings/__init__.py similarity index 100% rename from apiserver/plane/settings/__init__.py rename to apps/api/plane/settings/__init__.py diff --git a/apiserver/plane/settings/common.py b/apps/api/plane/settings/common.py similarity index 100% rename from apiserver/plane/settings/common.py rename to apps/api/plane/settings/common.py diff --git a/apiserver/plane/settings/local.py b/apps/api/plane/settings/local.py similarity index 100% rename from apiserver/plane/settings/local.py rename to apps/api/plane/settings/local.py diff --git a/apiserver/plane/settings/production.py b/apps/api/plane/settings/production.py similarity index 100% rename from apiserver/plane/settings/production.py rename to apps/api/plane/settings/production.py diff --git a/apiserver/plane/settings/redis.py b/apps/api/plane/settings/redis.py similarity index 100% rename from apiserver/plane/settings/redis.py rename to apps/api/plane/settings/redis.py diff --git a/apiserver/plane/settings/storage.py b/apps/api/plane/settings/storage.py similarity index 98% rename from apiserver/plane/settings/storage.py rename to apps/api/plane/settings/storage.py index f2be261ad..71709ebe0 100644 --- a/apiserver/plane/settings/storage.py +++ b/apps/api/plane/settings/storage.py @@ -1,5 +1,6 @@ # Python imports import os +import uuid # Third party imports import boto3 @@ -101,6 +102,9 @@ class S3Storage(S3Boto3Storage): def _get_content_disposition(self, disposition, filename=None): """Helper method to generate Content-Disposition header value""" + if filename is None: + filename = uuid.uuid4().hex + if filename: # Encode the filename to handle special characters encoded_filename = quote(filename) diff --git a/apiserver/plane/settings/test.py b/apps/api/plane/settings/test.py similarity index 100% rename from apiserver/plane/settings/test.py rename to apps/api/plane/settings/test.py diff --git a/apiserver/plane/space/__init__.py b/apps/api/plane/space/__init__.py similarity index 100% rename from apiserver/plane/space/__init__.py rename to apps/api/plane/space/__init__.py diff --git a/apiserver/plane/space/apps.py b/apps/api/plane/space/apps.py similarity index 100% rename from apiserver/plane/space/apps.py rename to apps/api/plane/space/apps.py diff --git a/apiserver/plane/space/serializer/__init__.py b/apps/api/plane/space/serializer/__init__.py similarity index 100% rename from apiserver/plane/space/serializer/__init__.py rename to apps/api/plane/space/serializer/__init__.py diff --git a/apiserver/plane/space/serializer/base.py b/apps/api/plane/space/serializer/base.py similarity index 100% rename from apiserver/plane/space/serializer/base.py rename to apps/api/plane/space/serializer/base.py diff --git a/apiserver/plane/space/serializer/cycle.py b/apps/api/plane/space/serializer/cycle.py similarity index 100% rename from apiserver/plane/space/serializer/cycle.py rename to apps/api/plane/space/serializer/cycle.py diff --git a/apiserver/plane/space/serializer/intake.py b/apps/api/plane/space/serializer/intake.py similarity index 100% rename from apiserver/plane/space/serializer/intake.py rename to apps/api/plane/space/serializer/intake.py diff --git a/apiserver/plane/space/serializer/issue.py b/apps/api/plane/space/serializer/issue.py similarity index 93% rename from apiserver/plane/space/serializer/issue.py rename to apps/api/plane/space/serializer/issue.py index e1445b4e6..3549e7626 100644 --- a/apiserver/plane/space/serializer/issue.py +++ b/apps/api/plane/space/serializer/issue.py @@ -28,6 +28,11 @@ from plane.db.models import ( IssueVote, IssueRelation, ) +from plane.utils.content_validator import ( + validate_html_content, + validate_json_content, + validate_binary_data, +) class IssueStateFlatSerializer(BaseSerializer): @@ -283,6 +288,23 @@ class IssueCreateSerializer(BaseSerializer): and data.get("start_date", None) > data.get("target_date", None) ): raise serializers.ValidationError("Start date cannot exceed target date") + + # Validate description content for security + if "description" in data and data["description"]: + is_valid, error_msg = validate_json_content(data["description"]) + if not is_valid: + raise serializers.ValidationError({"description": error_msg}) + + if "description_html" in data and data["description_html"]: + is_valid, error_msg = validate_html_content(data["description_html"]) + if not is_valid: + raise serializers.ValidationError({"description_html": error_msg}) + + if "description_binary" in data and data["description_binary"]: + is_valid, error_msg = validate_binary_data(data["description_binary"]) + if not is_valid: + raise serializers.ValidationError({"description_binary": error_msg}) + return data def create(self, validated_data): diff --git a/apiserver/plane/space/serializer/module.py b/apps/api/plane/space/serializer/module.py similarity index 100% rename from apiserver/plane/space/serializer/module.py rename to apps/api/plane/space/serializer/module.py diff --git a/apiserver/plane/space/serializer/project.py b/apps/api/plane/space/serializer/project.py similarity index 100% rename from apiserver/plane/space/serializer/project.py rename to apps/api/plane/space/serializer/project.py diff --git a/apiserver/plane/space/serializer/state.py b/apps/api/plane/space/serializer/state.py similarity index 100% rename from apiserver/plane/space/serializer/state.py rename to apps/api/plane/space/serializer/state.py diff --git a/apiserver/plane/space/serializer/user.py b/apps/api/plane/space/serializer/user.py similarity index 100% rename from apiserver/plane/space/serializer/user.py rename to apps/api/plane/space/serializer/user.py diff --git a/apiserver/plane/space/serializer/workspace.py b/apps/api/plane/space/serializer/workspace.py similarity index 100% rename from apiserver/plane/space/serializer/workspace.py rename to apps/api/plane/space/serializer/workspace.py diff --git a/apiserver/plane/space/urls/__init__.py b/apps/api/plane/space/urls/__init__.py similarity index 100% rename from apiserver/plane/space/urls/__init__.py rename to apps/api/plane/space/urls/__init__.py diff --git a/apiserver/plane/space/urls/asset.py b/apps/api/plane/space/urls/asset.py similarity index 100% rename from apiserver/plane/space/urls/asset.py rename to apps/api/plane/space/urls/asset.py diff --git a/apiserver/plane/space/urls/intake.py b/apps/api/plane/space/urls/intake.py similarity index 100% rename from apiserver/plane/space/urls/intake.py rename to apps/api/plane/space/urls/intake.py diff --git a/apiserver/plane/space/urls/issue.py b/apps/api/plane/space/urls/issue.py similarity index 100% rename from apiserver/plane/space/urls/issue.py rename to apps/api/plane/space/urls/issue.py diff --git a/apiserver/plane/space/urls/project.py b/apps/api/plane/space/urls/project.py similarity index 100% rename from apiserver/plane/space/urls/project.py rename to apps/api/plane/space/urls/project.py diff --git a/apiserver/plane/space/utils/grouper.py b/apps/api/plane/space/utils/grouper.py similarity index 100% rename from apiserver/plane/space/utils/grouper.py rename to apps/api/plane/space/utils/grouper.py diff --git a/apiserver/plane/space/views/__init__.py b/apps/api/plane/space/views/__init__.py similarity index 100% rename from apiserver/plane/space/views/__init__.py rename to apps/api/plane/space/views/__init__.py diff --git a/apiserver/plane/space/views/asset.py b/apps/api/plane/space/views/asset.py similarity index 100% rename from apiserver/plane/space/views/asset.py rename to apps/api/plane/space/views/asset.py diff --git a/apiserver/plane/space/views/base.py b/apps/api/plane/space/views/base.py similarity index 100% rename from apiserver/plane/space/views/base.py rename to apps/api/plane/space/views/base.py diff --git a/apiserver/plane/space/views/cycle.py b/apps/api/plane/space/views/cycle.py similarity index 100% rename from apiserver/plane/space/views/cycle.py rename to apps/api/plane/space/views/cycle.py diff --git a/apiserver/plane/space/views/intake.py b/apps/api/plane/space/views/intake.py similarity index 100% rename from apiserver/plane/space/views/intake.py rename to apps/api/plane/space/views/intake.py diff --git a/apiserver/plane/space/views/issue.py b/apps/api/plane/space/views/issue.py similarity index 100% rename from apiserver/plane/space/views/issue.py rename to apps/api/plane/space/views/issue.py diff --git a/apiserver/plane/space/views/label.py b/apps/api/plane/space/views/label.py similarity index 100% rename from apiserver/plane/space/views/label.py rename to apps/api/plane/space/views/label.py diff --git a/apiserver/plane/space/views/meta.py b/apps/api/plane/space/views/meta.py similarity index 100% rename from apiserver/plane/space/views/meta.py rename to apps/api/plane/space/views/meta.py diff --git a/apiserver/plane/space/views/module.py b/apps/api/plane/space/views/module.py similarity index 100% rename from apiserver/plane/space/views/module.py rename to apps/api/plane/space/views/module.py diff --git a/apiserver/plane/space/views/project.py b/apps/api/plane/space/views/project.py similarity index 100% rename from apiserver/plane/space/views/project.py rename to apps/api/plane/space/views/project.py diff --git a/apiserver/plane/space/views/state.py b/apps/api/plane/space/views/state.py similarity index 100% rename from apiserver/plane/space/views/state.py rename to apps/api/plane/space/views/state.py diff --git a/apiserver/plane/static/css/style.css b/apps/api/plane/static/css/style.css similarity index 100% rename from apiserver/plane/static/css/style.css rename to apps/api/plane/static/css/style.css diff --git a/apiserver/plane/static/humans.txt b/apps/api/plane/static/humans.txt similarity index 100% rename from apiserver/plane/static/humans.txt rename to apps/api/plane/static/humans.txt diff --git a/apiserver/plane/static/js/script.js b/apps/api/plane/static/js/script.js similarity index 100% rename from apiserver/plane/static/js/script.js rename to apps/api/plane/static/js/script.js diff --git a/apiserver/plane/tests/README.md b/apps/api/plane/tests/README.md similarity index 100% rename from apiserver/plane/tests/README.md rename to apps/api/plane/tests/README.md diff --git a/apiserver/plane/tests/TESTING_GUIDE.md b/apps/api/plane/tests/TESTING_GUIDE.md similarity index 100% rename from apiserver/plane/tests/TESTING_GUIDE.md rename to apps/api/plane/tests/TESTING_GUIDE.md diff --git a/apiserver/plane/tests/__init__.py b/apps/api/plane/tests/__init__.py similarity index 100% rename from apiserver/plane/tests/__init__.py rename to apps/api/plane/tests/__init__.py diff --git a/apiserver/plane/tests/apps.py b/apps/api/plane/tests/apps.py similarity index 100% rename from apiserver/plane/tests/apps.py rename to apps/api/plane/tests/apps.py diff --git a/apiserver/plane/tests/conftest.py b/apps/api/plane/tests/conftest.py similarity index 84% rename from apiserver/plane/tests/conftest.py rename to apps/api/plane/tests/conftest.py index 832558810..b70c9352a 100644 --- a/apiserver/plane/tests/conftest.py +++ b/apps/api/plane/tests/conftest.py @@ -4,7 +4,7 @@ from rest_framework.test import APIClient from pytest_django.fixtures import django_db_setup from unittest.mock import patch, MagicMock -from plane.db.models import User +from plane.db.models import User, Workspace, WorkspaceMember from plane.db.models.api import APIToken @@ -118,3 +118,23 @@ def plane_server(live_server): Returns a live Django server for testing HTTP requests. """ return live_server + + +@pytest.fixture +def workspace(create_user): + """ + Create a new workspace and return the + corresponding Workspace model instance. + """ + # Create the workspace using the model + created_workspace = Workspace.objects.create( + name="Test Workspace", + owner=create_user, + slug="test-workspace", + ) + + WorkspaceMember.objects.create( + workspace=created_workspace, member=create_user, role=20 + ) + + return created_workspace diff --git a/apiserver/plane/tests/conftest_external.py b/apps/api/plane/tests/conftest_external.py similarity index 81% rename from apiserver/plane/tests/conftest_external.py rename to apps/api/plane/tests/conftest_external.py index d2d6a2df5..50022b490 100644 --- a/apiserver/plane/tests/conftest_external.py +++ b/apps/api/plane/tests/conftest_external.py @@ -21,7 +21,7 @@ def mock_redis(): mock_redis_client.ttl.return_value = -1 # Start the patch - with patch('plane.settings.redis.redis_instance', return_value=mock_redis_client): + with patch("plane.settings.redis.redis_instance", return_value=mock_redis_client): yield mock_redis_client @@ -44,7 +44,7 @@ def mock_elasticsearch(): mock_es_client.delete.return_value = {"_id": "test_id", "result": "deleted"} # Start the patch - with patch('elasticsearch.Elasticsearch', return_value=mock_es_client): + with patch("elasticsearch.Elasticsearch", return_value=mock_es_client): yield mock_es_client @@ -68,39 +68,30 @@ def mock_mongodb(): # Configure common MongoDB collection operations mock_mongo_collection.find_one.return_value = None mock_mongo_collection.find.return_value = MagicMock( - __iter__=lambda x: iter([]), - count=lambda: 0 + __iter__=lambda x: iter([]), count=lambda: 0 ) mock_mongo_collection.insert_one.return_value = MagicMock( - inserted_id="mock_id_123", - acknowledged=True + inserted_id="mock_id_123", acknowledged=True ) mock_mongo_collection.insert_many.return_value = MagicMock( - inserted_ids=["mock_id_123", "mock_id_456"], - acknowledged=True + inserted_ids=["mock_id_123", "mock_id_456"], acknowledged=True ) mock_mongo_collection.update_one.return_value = MagicMock( - modified_count=1, - matched_count=1, - acknowledged=True + modified_count=1, matched_count=1, acknowledged=True ) mock_mongo_collection.update_many.return_value = MagicMock( - modified_count=2, - matched_count=2, - acknowledged=True + modified_count=2, matched_count=2, acknowledged=True ) mock_mongo_collection.delete_one.return_value = MagicMock( - deleted_count=1, - acknowledged=True + deleted_count=1, acknowledged=True ) mock_mongo_collection.delete_many.return_value = MagicMock( - deleted_count=2, - acknowledged=True + deleted_count=2, acknowledged=True ) mock_mongo_collection.count_documents.return_value = 0 # Start the patch - with patch('pymongo.MongoClient', return_value=mock_mongo_client): + with patch("pymongo.MongoClient", return_value=mock_mongo_client): yield mock_mongo_client @@ -112,6 +103,6 @@ def mock_celery(): This fixture patches Celery's task.delay() to prevent actual task execution. """ # Start the patch - with patch('celery.app.task.Task.delay') as mock_delay: + with patch("celery.app.task.Task.delay") as mock_delay: mock_delay.return_value = MagicMock(id="mock-task-id") - yield mock_delay \ No newline at end of file + yield mock_delay diff --git a/apiserver/plane/tests/contract/__init__.py b/apps/api/plane/tests/contract/__init__.py similarity index 100% rename from apiserver/plane/tests/contract/__init__.py rename to apps/api/plane/tests/contract/__init__.py diff --git a/apiserver/plane/tests/contract/api/__init__.py b/apps/api/plane/tests/contract/api/__init__.py similarity index 100% rename from apiserver/plane/tests/contract/api/__init__.py rename to apps/api/plane/tests/contract/api/__init__.py diff --git a/apiserver/plane/tests/smoke/__init__.py b/apps/api/plane/tests/contract/app/__init__.py similarity index 100% rename from apiserver/plane/tests/smoke/__init__.py rename to apps/api/plane/tests/contract/app/__init__.py diff --git a/apiserver/plane/tests/contract/app/test_api_token.py b/apps/api/plane/tests/contract/app/test_api_token.py similarity index 100% rename from apiserver/plane/tests/contract/app/test_api_token.py rename to apps/api/plane/tests/contract/app/test_api_token.py diff --git a/apiserver/plane/tests/contract/app/test_authentication.py b/apps/api/plane/tests/contract/app/test_authentication.py similarity index 88% rename from apiserver/plane/tests/contract/app/test_authentication.py rename to apps/api/plane/tests/contract/app/test_authentication.py index 0dc548710..a52882b9d 100644 --- a/apiserver/plane/tests/contract/app/test_authentication.py +++ b/apps/api/plane/tests/contract/app/test_authentication.py @@ -16,7 +16,9 @@ from plane.license.models import Instance @pytest.fixture def setup_instance(db): """Create and configure an instance for authentication tests""" - instance_id = uuid.uuid4() if not Instance.objects.exists() else Instance.objects.first().id + instance_id = ( + uuid.uuid4() if not Instance.objects.exists() else Instance.objects.first().id + ) # Create or update instance with all required fields instance, _ = Instance.objects.update_or_create( @@ -28,7 +30,7 @@ def setup_instance(db): "domain": "http://localhost:8000", "last_checked_at": timezone.now(), "is_setup_done": True, - } + }, ) return instance @@ -36,7 +38,9 @@ def setup_instance(db): @pytest.fixture def django_client(): """Return a Django test client with User-Agent header for handling redirects""" - client = Client(HTTP_USER_AGENT="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1") + client = Client( + HTTP_USER_AGENT="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1" + ) return client @@ -79,7 +83,9 @@ class TestMagicLinkGenerate: @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_magic_generate(self, mock_magic_link, api_client, setup_user, setup_instance): + def test_magic_generate( + self, mock_magic_link, api_client, setup_user, setup_instance + ): """Test successful magic link generation""" url = reverse("magic-generate") @@ -97,7 +103,9 @@ class TestMagicLinkGenerate: @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_max_generate_attempt(self, mock_magic_link, api_client, setup_user, setup_instance): + def test_max_generate_attempt( + self, mock_magic_link, api_client, setup_user, setup_instance + ): """Test exceeding maximum magic link generation attempts""" url = reverse("magic-generate") @@ -163,10 +171,9 @@ class TestSignInEndpoint: url, {"email": "user@plane.so", "password": "user123"}, follow=True ) - # Check for the specific authentication error in the URL redirect_urls = [url for url, _ in response.redirect_chain] - redirect_contents = ' '.join(redirect_urls) + redirect_contents = " ".join(redirect_urls) # The actual error code for invalid password is AUTHENTICATION_FAILED_SIGN_IN assert "AUTHENTICATION_FAILED_SIGN_IN" in redirect_contents @@ -201,14 +208,13 @@ class TestSignInEndpoint: response = django_client.post( url, {"email": "user@plane.so", "password": "user@123", "next_path": next_path}, - follow=False + follow=False, ) # Check that the initial response is a redirect (302) without error code assert response.status_code == 302 assert "error_code" not in response.url - # In a real browser, the next_path would be used to build the absolute URL # Since we're just testing the authentication logic, we won't check for the exact URL structure # Instead, just verify that we're authenticated @@ -237,16 +243,16 @@ class TestMagicSignIn: assert "MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED" in response.redirect_chain[-1][0] @pytest.mark.django_db - def test_expired_invalid_magic_link(self, django_client, setup_user, setup_instance): + def test_expired_invalid_magic_link( + self, django_client, setup_user, setup_instance + ): """Test magic link sign-in with expired/invalid link""" ri = redis_instance() ri.delete("magic_user@plane.so") url = reverse("magic-sign-in") response = django_client.post( - url, - {"email": "user@plane.so", "code": "xxxx-xxxxx-xxxx"}, - follow=False + url, {"email": "user@plane.so", "code": "xxxx-xxxxx-xxxx"}, follow=False ) # Check that we get a redirect @@ -254,7 +260,10 @@ class TestMagicSignIn: # The actual error code is EXPIRED_MAGIC_CODE_SIGN_IN (when key doesn't exist) # or INVALID_MAGIC_CODE_SIGN_IN (when key exists but code doesn't match) - assert "EXPIRED_MAGIC_CODE_SIGN_IN" in response.url or "INVALID_MAGIC_CODE_SIGN_IN" in response.url + assert ( + "EXPIRED_MAGIC_CODE_SIGN_IN" in response.url + or "INVALID_MAGIC_CODE_SIGN_IN" in response.url + ) @pytest.mark.django_db def test_user_does_not_exist(self, django_client, setup_instance): @@ -263,7 +272,7 @@ class TestMagicSignIn: response = django_client.post( url, {"email": "nonexistent@plane.so", "code": "xxxx-xxxxx-xxxx"}, - follow=True + follow=True, ) # Check redirect contains error code @@ -271,7 +280,9 @@ class TestMagicSignIn: @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_magic_code_sign_in(self, mock_magic_link, django_client, api_client, setup_user, setup_instance): + def test_magic_code_sign_in( + self, mock_magic_link, django_client, api_client, setup_user, setup_instance + ): """Test successful magic link sign-in process""" # First generate a magic link token gen_url = reverse("magic-generate") @@ -288,9 +299,7 @@ class TestMagicSignIn: # Use Django client to test the redirect flow without following redirects url = reverse("magic-sign-in") response = django_client.post( - url, - {"email": "user@plane.so", "code": token}, - follow=False + url, {"email": "user@plane.so", "code": token}, follow=False ) # Check that the initial response is a redirect without error code @@ -302,7 +311,9 @@ class TestMagicSignIn: @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_magic_sign_in_with_next_path(self, mock_magic_link, django_client, api_client, setup_user, setup_instance): + def test_magic_sign_in_with_next_path( + self, mock_magic_link, django_client, api_client, setup_user, setup_instance + ): """Test magic sign-in with next_path parameter""" # First generate a magic link token gen_url = reverse("magic-generate") @@ -322,7 +333,7 @@ class TestMagicSignIn: response = django_client.post( url, {"email": "user@plane.so", "code": token, "next_path": next_path}, - follow=False + follow=False, ) # Check that the initial response is a redirect without error code @@ -357,9 +368,7 @@ class TestMagicSignUp: url = reverse("magic-sign-up") response = django_client.post( - url, - {"email": "existing@plane.so", "code": "xxxx-xxxxx-xxxx"}, - follow=True + url, {"email": "existing@plane.so", "code": "xxxx-xxxxx-xxxx"}, follow=True ) # Check redirect contains error code @@ -370,9 +379,7 @@ class TestMagicSignUp: """Test magic link sign-up with expired/invalid link""" url = reverse("magic-sign-up") response = django_client.post( - url, - {"email": "new@plane.so", "code": "xxxx-xxxxx-xxxx"}, - follow=False + url, {"email": "new@plane.so", "code": "xxxx-xxxxx-xxxx"}, follow=False ) # Check that we get a redirect @@ -380,11 +387,16 @@ class TestMagicSignUp: # The actual error code is EXPIRED_MAGIC_CODE_SIGN_UP (when key doesn't exist) # or INVALID_MAGIC_CODE_SIGN_UP (when key exists but code doesn't match) - assert "EXPIRED_MAGIC_CODE_SIGN_UP" in response.url or "INVALID_MAGIC_CODE_SIGN_UP" in response.url + assert ( + "EXPIRED_MAGIC_CODE_SIGN_UP" in response.url + or "INVALID_MAGIC_CODE_SIGN_UP" in response.url + ) @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_magic_code_sign_up(self, mock_magic_link, django_client, api_client, setup_instance): + def test_magic_code_sign_up( + self, mock_magic_link, django_client, api_client, setup_instance + ): """Test successful magic link sign-up process""" email = "newuser@plane.so" @@ -403,9 +415,7 @@ class TestMagicSignUp: # Use Django client to test the redirect flow without following redirects url = reverse("magic-sign-up") response = django_client.post( - url, - {"email": email, "code": token}, - follow=False + url, {"email": email, "code": token}, follow=False ) # Check that the initial response is a redirect without error code @@ -420,7 +430,9 @@ class TestMagicSignUp: @pytest.mark.django_db @patch("plane.bgtasks.magic_link_code_task.magic_link.delay") - def test_magic_sign_up_with_next_path(self, mock_magic_link, django_client, api_client, setup_instance): + def test_magic_sign_up_with_next_path( + self, mock_magic_link, django_client, api_client, setup_instance + ): """Test magic sign-up with next_path parameter""" email = "newuser2@plane.so" @@ -440,9 +452,7 @@ class TestMagicSignUp: url = reverse("magic-sign-up") next_path = "onboarding" response = django_client.post( - url, - {"email": email, "code": token, "next_path": next_path}, - follow=False + url, {"email": email, "code": token, "next_path": next_path}, follow=False ) # Check that the initial response is a redirect without error code @@ -456,4 +466,4 @@ class TestMagicSignUp: assert User.objects.filter(email=email).exists() # Check if user is authenticated - assert "_auth_user_id" in django_client.session \ No newline at end of file + assert "_auth_user_id" in django_client.session diff --git a/apps/api/plane/tests/contract/app/test_project_app.py b/apps/api/plane/tests/contract/app/test_project_app.py new file mode 100644 index 000000000..78bcd7aea --- /dev/null +++ b/apps/api/plane/tests/contract/app/test_project_app.py @@ -0,0 +1,618 @@ +import pytest +from rest_framework import status +import uuid +from django.utils import timezone + +from plane.db.models import ( + Project, + ProjectMember, + IssueUserProperty, + State, + WorkspaceMember, + User, +) + + +class TestProjectBase: + def get_project_url( + self, workspace_slug: str, pk: uuid.UUID = None, details: bool = False + ) -> str: + """ + Constructs the project endpoint URL for the given workspace as reverse() is + unreliable due to duplicate 'name' values in URL patterns ('api' and 'app'). + + Args: + workspace_slug (str): The slug of the workspace. + pk (uuid.UUID, optional): The primary key of a specific project. + details (bool, optional): If True, constructs the URL for the + project details endpoint. Defaults to False. + """ + # Establish the common base URL for all project-related endpoints. + base_url = f"/api/workspaces/{workspace_slug}/projects/" + + # Specific project instance URL. + if pk: + return f"{base_url}{pk}/" + + # Append 'details/' to the base URL. + if details: + return f"{base_url}details/" + + # Return the base project list URL. + return base_url + + +@pytest.mark.contract +class TestProjectAPIPost(TestProjectBase): + """Test project POST operations""" + + @pytest.mark.django_db + def test_create_project_empty_data(self, session_client, workspace): + """Test creating a project with empty data""" + + url = self.get_project_url(workspace.slug) + + # Test with empty data + response = session_client.post(url, {}, format="json") + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_create_project_valid_data(self, session_client, workspace, create_user): + url = self.get_project_url(workspace.slug) + + project_data = { + "name": "New Project Test", + "identifier": "NPT", + } + + user = create_user + + # Make the request + response = session_client.post(url, project_data, format="json") + + # Check response status + assert response.status_code == status.HTTP_201_CREATED + + # Verify project was created + assert Project.objects.count() == 1 + project = Project.objects.get(name=project_data["name"]) + assert project.workspace == workspace + + # Check if the member is created with the correct role + assert ProjectMember.objects.count() == 1 + project_member = ProjectMember.objects.filter( + project=project, member=user + ).first() + assert project_member.role == 20 # Administrator + assert project_member.is_active is True + + # Verify IssueUserProperty was created + assert IssueUserProperty.objects.filter(project=project, user=user).exists() + + # Verify default states were created + states = State.objects.filter(project=project) + assert states.count() == 5 + expected_states = ["Backlog", "Todo", "In Progress", "Done", "Cancelled"] + state_names = list(states.values_list("name", flat=True)) + assert set(state_names) == set(expected_states) + + @pytest.mark.django_db + def test_create_project_with_project_lead( + self, session_client, workspace, create_user + ): + """Test creating project with a different project lead""" + # Create another user to be project lead + project_lead = User.objects.create_user( + email="lead@example.com", username="projectlead" + ) + + # Add project lead to workspace + WorkspaceMember.objects.create( + workspace=workspace, member=project_lead, role=15 + ) + + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Project with Lead", + "identifier": "PWL", + "project_lead": project_lead.id, + } + + response = session_client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_201_CREATED + + # Verify both creator and project lead are administrators + project = Project.objects.get(name=project_data["name"]) + assert ProjectMember.objects.filter(project=project, role=20).count() == 2 + + # Verify both have IssueUserProperty + assert IssueUserProperty.objects.filter(project=project).count() == 2 + + @pytest.mark.django_db + def test_create_project_guest_forbidden(self, session_client, workspace): + """Test that guests cannot create projects""" + guest_user = User.objects.create_user( + email="guest@example.com", username="guest" + ) + WorkspaceMember.objects.create(workspace=workspace, member=guest_user, role=5) + + session_client.force_authenticate(user=guest_user) + + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Guest Project", + "identifier": "GP", + } + + response = session_client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_403_FORBIDDEN + assert Project.objects.count() == 0 + + @pytest.mark.django_db + def test_create_project_unauthenticated(self, client, workspace): + """Test unauthenticated access""" + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Unauth Project", + "identifier": "UP", + } + + response = client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_401_UNAUTHORIZED + + @pytest.mark.django_db + def test_create_project_duplicate_name( + self, session_client, workspace, create_user + ): + """Test creating project with duplicate name""" + # Create first project + Project.objects.create( + name="Duplicate Name", identifier="DN1", workspace=workspace + ) + + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Duplicate Name", + "identifier": "DN2", + } + + response = session_client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_create_project_duplicate_identifier( + self, session_client, workspace, create_user + ): + """Test creating project with duplicate identifier""" + Project.objects.create( + name="First Project", identifier="DUP", workspace=workspace + ) + + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Second Project", + "identifier": "DUP", + } + + response = session_client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_create_project_missing_required_fields( + self, session_client, workspace, create_user + ): + """Test validation with missing required fields""" + url = self.get_project_url(workspace.slug) + + # Test missing name + response = session_client.post(url, {"identifier": "MN"}, format="json") + assert response.status_code == status.HTTP_400_BAD_REQUEST + + # Test missing identifier + response = session_client.post( + url, {"name": "Missing Identifier"}, format="json" + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_create_project_with_all_optional_fields( + self, session_client, workspace, create_user + ): + """Test creating project with all optional fields""" + url = self.get_project_url(workspace.slug) + project_data = { + "name": "Full Project", + "identifier": "FP", + "description": "A comprehensive test project", + "network": 2, + "cycle_view": True, + "issue_views_view": False, + "module_view": True, + "page_view": False, + "inbox_view": True, + "guest_view_all_features": True, + "logo_props": { + "in_use": "emoji", + "emoji": {"value": "🚀", "unicode": "1f680"}, + }, + } + + response = session_client.post(url, project_data, format="json") + + assert response.status_code == status.HTTP_201_CREATED + + response_data = response.json() + assert response_data["description"] == project_data["description"] + assert response_data["network"] == project_data["network"] + + +@pytest.mark.contract +class TestProjectAPIGet(TestProjectBase): + """Test project GET operations""" + + @pytest.mark.django_db + def test_list_projects_authenticated_admin( + self, session_client, workspace, create_user + ): + """Test listing projects as workspace admin""" + # Create a project + project = Project.objects.create( + name="Test Project", identifier="TP", workspace=workspace + ) + + # Add user as project member + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug) + response = session_client.get(url) + + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert len(data) == 1 + assert data[0]["name"] == "Test Project" + assert data[0]["identifier"] == "TP" + + @pytest.mark.django_db + def test_list_projects_authenticated_guest(self, session_client, workspace): + """Test listing projects as workspace guest""" + # Create a guest user + guest_user = User.objects.create_user( + email="guest@example.com", username="guest" + ) + WorkspaceMember.objects.create( + workspace=workspace, member=guest_user, role=5, is_active=True + ) + + # Create projects + project1 = Project.objects.create( + name="Project 1", identifier="P1", workspace=workspace + ) + + Project.objects.create(name="Project 2", identifier="P2", workspace=workspace) + + # Add guest to only one project + ProjectMember.objects.create( + project=project1, member=guest_user, role=10, is_active=True + ) + + session_client.force_authenticate(user=guest_user) + + url = self.get_project_url(workspace.slug) + response = session_client.get(url) + + assert response.status_code == status.HTTP_200_OK + data = response.json() + # Guest should only see projects they're members of + assert len(data) == 1 + assert data[0]["name"] == "Project 1" + + @pytest.mark.django_db + def test_list_projects_unauthenticated(self, client, workspace): + """Test listing projects without authentication""" + url = self.get_project_url(workspace.slug) + response = client.get(url) + + assert response.status_code == status.HTTP_401_UNAUTHORIZED + + @pytest.mark.django_db + def test_list_detail_projects(self, session_client, workspace, create_user): + """Test listing projects with detailed information""" + # Create a project + project = Project.objects.create( + name="Detailed Project", + identifier="DP", + workspace=workspace, + description="A detailed test project", + ) + + # Add user as project member + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, details=True) + response = session_client.get(url) + + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert len(data) == 1 + assert data[0]["name"] == "Detailed Project" + assert data[0]["description"] == "A detailed test project" + + @pytest.mark.django_db + def test_retrieve_project_success(self, session_client, workspace, create_user): + """Test retrieving a specific project""" + # Create a project + project = Project.objects.create( + name="Retrieve Test Project", + identifier="RTP", + workspace=workspace, + description="Test project for retrieval", + ) + + # Add user as project member + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = session_client.get(url) + + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data["name"] == "Retrieve Test Project" + assert data["identifier"] == "RTP" + assert data["description"] == "Test project for retrieval" + + @pytest.mark.django_db + def test_retrieve_project_not_found(self, session_client, workspace, create_user): + """Test retrieving a non-existent project""" + fake_uuid = uuid.uuid4() + url = self.get_project_url(workspace.slug, pk=fake_uuid) + response = session_client.get(url) + + assert response.status_code == status.HTTP_404_NOT_FOUND + + @pytest.mark.django_db + def test_retrieve_archived_project(self, session_client, workspace, create_user): + """Test retrieving an archived project""" + # Create an archived project + project = Project.objects.create( + name="Archived Project", + identifier="AP", + workspace=workspace, + archived_at=timezone.now(), + ) + + # Add user as project member + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = session_client.get(url) + + assert response.status_code == status.HTTP_404_NOT_FOUND + + +@pytest.mark.contract +class TestProjectAPIPatchDelete(TestProjectBase): + """Test project PATCH, and DELETE operations""" + + @pytest.mark.django_db + def test_partial_update_project_success( + self, session_client, workspace, create_user + ): + """Test successful partial update of project""" + # Create a project + project = Project.objects.create( + name="Original Project", + identifier="OP", + workspace=workspace, + description="Original description", + ) + + # Add user as project administrator + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + update_data = { + "name": "Updated Project", + "description": "Updated description", + "cycle_view": True, + "module_view": False, + } + + response = session_client.patch(url, update_data, format="json") + + assert response.status_code == status.HTTP_200_OK + + # Verify project was updated + project.refresh_from_db() + assert project.name == "Updated Project" + assert project.description == "Updated description" + assert project.cycle_view is True + assert project.module_view is False + + @pytest.mark.django_db + def test_partial_update_project_forbidden_non_admin( + self, session_client, workspace + ): + """Test that non-admin project members cannot update project""" + # Create a project + project = Project.objects.create( + name="Protected Project", identifier="PP", workspace=workspace + ) + + # Create a member user (not admin) + member_user = User.objects.create_user( + email="member@example.com", username="member" + ) + WorkspaceMember.objects.create( + workspace=workspace, member=member_user, role=15, is_active=True + ) + ProjectMember.objects.create( + project=project, member=member_user, role=15, is_active=True + ) + + session_client.force_authenticate(user=member_user) + + url = self.get_project_url(workspace.slug, pk=project.id) + update_data = {"name": "Hacked Project"} + + response = session_client.patch(url, update_data, format="json") + + assert response.status_code == status.HTTP_403_FORBIDDEN + + @pytest.mark.django_db + def test_partial_update_duplicate_name_conflict( + self, session_client, workspace, create_user + ): + """Test updating project with duplicate name returns conflict""" + # Create two projects + Project.objects.create(name="Project One", identifier="P1", workspace=workspace) + project2 = Project.objects.create( + name="Project Two", identifier="P2", workspace=workspace + ) + + ProjectMember.objects.create( + project=project2, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project2.id) + update_data = {"name": "Project One"} # Duplicate name + + response = session_client.patch(url, update_data, format="json") + + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_partial_update_duplicate_identifier_conflict( + self, session_client, workspace, create_user + ): + """Test updating project with duplicate identifier returns conflict""" + # Create two projects + Project.objects.create(name="Project One", identifier="P1", workspace=workspace) + project2 = Project.objects.create( + name="Project Two", identifier="P2", workspace=workspace + ) + + ProjectMember.objects.create( + project=project2, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project2.id) + update_data = {"identifier": "P1"} # Duplicate identifier + + response = session_client.patch(url, update_data, format="json") + + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_partial_update_invalid_data(self, session_client, workspace, create_user): + """Test partial update with invalid data""" + project = Project.objects.create( + name="Valid Project", identifier="VP", workspace=workspace + ) + + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + update_data = {"name": ""} + + response = session_client.patch(url, update_data, format="json") + + assert response.status_code == status.HTTP_400_BAD_REQUEST + + @pytest.mark.django_db + def test_delete_project_success_project_admin( + self, session_client, workspace, create_user + ): + """Test successful project deletion by project admin""" + project = Project.objects.create( + name="Delete Me", identifier="DM", workspace=workspace + ) + + ProjectMember.objects.create( + project=project, member=create_user, role=20, is_active=True + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = session_client.delete(url) + + assert response.status_code == status.HTTP_204_NO_CONTENT + assert not Project.objects.filter(id=project.id).exists() + + @pytest.mark.django_db + def test_delete_project_success_workspace_admin(self, session_client, workspace): + """Test successful project deletion by workspace admin""" + # Create workspace admin user + workspace_admin = User.objects.create_user( + email="admin@example.com", username="admin" + ) + WorkspaceMember.objects.create( + workspace=workspace, member=workspace_admin, role=20, is_active=True + ) + + project = Project.objects.create( + name="Delete Me", identifier="DM", workspace=workspace + ) + + session_client.force_authenticate(user=workspace_admin) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = session_client.delete(url) + + assert response.status_code == status.HTTP_204_NO_CONTENT + assert not Project.objects.filter(id=project.id).exists() + + @pytest.mark.django_db + def test_delete_project_forbidden_non_admin(self, session_client, workspace): + """Test that non-admin users cannot delete projects""" + # Create a member user (not admin) + member_user = User.objects.create_user( + email="member@example.com", username="member" + ) + WorkspaceMember.objects.create( + workspace=workspace, member=member_user, role=15, is_active=True + ) + + project = Project.objects.create( + name="Protected Project", identifier="PP", workspace=workspace + ) + + ProjectMember.objects.create( + project=project, member=member_user, role=15, is_active=True + ) + + session_client.force_authenticate(user=member_user) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = session_client.delete(url) + + assert response.status_code == status.HTTP_403_FORBIDDEN + assert Project.objects.filter(id=project.id).exists() + + @pytest.mark.django_db + def test_delete_project_unauthenticated(self, client, workspace): + """Test unauthenticated project deletion""" + project = Project.objects.create( + name="Protected Project", identifier="PP", workspace=workspace + ) + + url = self.get_project_url(workspace.slug, pk=project.id) + response = client.delete(url) + + assert response.status_code == status.HTTP_401_UNAUTHORIZED + assert Project.objects.filter(id=project.id).exists() diff --git a/apiserver/plane/tests/contract/app/test_workspace_app.py b/apps/api/plane/tests/contract/app/test_workspace_app.py similarity index 87% rename from apiserver/plane/tests/contract/app/test_workspace_app.py rename to apps/api/plane/tests/contract/app/test_workspace_app.py index 71ad1d412..9d4c560e5 100644 --- a/apiserver/plane/tests/contract/app/test_workspace_app.py +++ b/apps/api/plane/tests/contract/app/test_workspace_app.py @@ -21,7 +21,9 @@ class TestWorkspaceAPI: @pytest.mark.django_db @patch("plane.bgtasks.workspace_seed_task.workspace_seed.delay") - def test_create_workspace_valid_data(self, mock_workspace_seed, session_client, create_user): + def test_create_workspace_valid_data( + self, mock_workspace_seed, session_client, create_user + ): """Test creating a workspace with valid data""" url = reverse("workspace") user = create_user # Use the create_user fixture directly as it returns a user object @@ -30,7 +32,7 @@ class TestWorkspaceAPI: workspace_data = { "name": "Plane", "slug": "pla-ne-test", - "company_name": "Plane Inc." + "company_name": "Plane Inc.", } # Make the request @@ -57,15 +59,13 @@ class TestWorkspaceAPI: mock_workspace_seed.assert_called_once_with(response.data["id"]) @pytest.mark.django_db - @patch('plane.bgtasks.workspace_seed_task.workspace_seed.delay') + @patch("plane.bgtasks.workspace_seed_task.workspace_seed.delay") def test_create_duplicate_workspace(self, mock_workspace_seed, session_client): """Test creating a duplicate workspace""" url = reverse("workspace") # Create first workspace - session_client.post( - url, {"name": "Plane", "slug": "pla-ne"}, format="json" - ) + session_client.post(url, {"name": "Plane", "slug": "pla-ne"}, format="json") # Try to create a workspace with the same slug response = session_client.post( @@ -76,4 +76,4 @@ class TestWorkspaceAPI: assert response.status_code == status.HTTP_400_BAD_REQUEST # Optionally check the error message to confirm it's related to the duplicate slug - assert "slug" in response.data \ No newline at end of file + assert "slug" in response.data diff --git a/apiserver/plane/tests/factories.py b/apps/api/plane/tests/factories.py similarity index 69% rename from apiserver/plane/tests/factories.py rename to apps/api/plane/tests/factories.py index 8d95773de..b8cd78361 100644 --- a/apiserver/plane/tests/factories.py +++ b/apps/api/plane/tests/factories.py @@ -2,26 +2,21 @@ import factory from uuid import uuid4 from django.utils import timezone -from plane.db.models import ( - User, - Workspace, - WorkspaceMember, - Project, - ProjectMember -) +from plane.db.models import User, Workspace, WorkspaceMember, Project, ProjectMember class UserFactory(factory.django.DjangoModelFactory): """Factory for creating User instances""" + class Meta: model = User - django_get_or_create = ('email',) + django_get_or_create = ("email",) id = factory.LazyFunction(uuid4) - email = factory.Sequence(lambda n: f'user{n}@plane.so') - password = factory.PostGenerationMethodCall('set_password', 'password') - first_name = factory.Sequence(lambda n: f'First{n}') - last_name = factory.Sequence(lambda n: f'Last{n}') + email = factory.Sequence(lambda n: f"user{n}@plane.so") + password = factory.PostGenerationMethodCall("set_password", "password") + first_name = factory.Sequence(lambda n: f"First{n}") + last_name = factory.Sequence(lambda n: f"Last{n}") is_active = True is_superuser = False is_staff = False @@ -29,13 +24,14 @@ class UserFactory(factory.django.DjangoModelFactory): class WorkspaceFactory(factory.django.DjangoModelFactory): """Factory for creating Workspace instances""" + class Meta: model = Workspace - django_get_or_create = ('slug',) + django_get_or_create = ("slug",) id = factory.LazyFunction(uuid4) - name = factory.Sequence(lambda n: f'Workspace {n}') - slug = factory.Sequence(lambda n: f'workspace-{n}') + name = factory.Sequence(lambda n: f"Workspace {n}") + slug = factory.Sequence(lambda n: f"workspace-{n}") owner = factory.SubFactory(UserFactory) created_at = factory.LazyFunction(timezone.now) updated_at = factory.LazyFunction(timezone.now) @@ -43,6 +39,7 @@ class WorkspaceFactory(factory.django.DjangoModelFactory): class WorkspaceMemberFactory(factory.django.DjangoModelFactory): """Factory for creating WorkspaceMember instances""" + class Meta: model = WorkspaceMember @@ -56,21 +53,23 @@ class WorkspaceMemberFactory(factory.django.DjangoModelFactory): class ProjectFactory(factory.django.DjangoModelFactory): """Factory for creating Project instances""" + class Meta: model = Project - django_get_or_create = ('name', 'workspace') + django_get_or_create = ("name", "workspace") id = factory.LazyFunction(uuid4) - name = factory.Sequence(lambda n: f'Project {n}') + name = factory.Sequence(lambda n: f"Project {n}") workspace = factory.SubFactory(WorkspaceFactory) - created_by = factory.SelfAttribute('workspace.owner') - updated_by = factory.SelfAttribute('workspace.owner') + created_by = factory.SelfAttribute("workspace.owner") + updated_by = factory.SelfAttribute("workspace.owner") created_at = factory.LazyFunction(timezone.now) updated_at = factory.LazyFunction(timezone.now) class ProjectMemberFactory(factory.django.DjangoModelFactory): """Factory for creating ProjectMember instances""" + class Meta: model = ProjectMember @@ -79,4 +78,4 @@ class ProjectMemberFactory(factory.django.DjangoModelFactory): member = factory.SubFactory(UserFactory) role = 20 # Admin role by default created_at = factory.LazyFunction(timezone.now) - updated_at = factory.LazyFunction(timezone.now) \ No newline at end of file + updated_at = factory.LazyFunction(timezone.now) diff --git a/apiserver/plane/tests/unit/__init__.py b/apps/api/plane/tests/smoke/__init__.py similarity index 100% rename from apiserver/plane/tests/unit/__init__.py rename to apps/api/plane/tests/smoke/__init__.py diff --git a/apiserver/plane/tests/smoke/test_auth_smoke.py b/apps/api/plane/tests/smoke/test_auth_smoke.py similarity index 65% rename from apiserver/plane/tests/smoke/test_auth_smoke.py rename to apps/api/plane/tests/smoke/test_auth_smoke.py index 4d6de6c35..85ca476b4 100644 --- a/apiserver/plane/tests/smoke/test_auth_smoke.py +++ b/apps/api/plane/tests/smoke/test_auth_smoke.py @@ -16,72 +16,79 @@ class TestAuthSmoke: # 1. Test bad login - test with wrong password response = requests.post( - url, - data={ - "email": user_data["email"], - "password": "wrong-password" - } + url, data={"email": user_data["email"], "password": "wrong-password"} ) # For bad credentials, any of these status codes would be valid # The test shouldn't be brittle to minor implementation changes - assert response.status_code != 500, "Authentication should not cause server errors" + assert response.status_code != 500, ( + "Authentication should not cause server errors" + ) assert response.status_code != 404, "Authentication endpoint should exist" if response.status_code == 200: # If API returns 200 for failures, check the response body for error indication - if hasattr(response, 'json'): + if hasattr(response, "json"): try: data = response.json() # JSON response might indicate error in its structure - assert "error" in data or "error_code" in data or "detail" in data or response.url.endswith("sign-in"), \ - "Error response should contain error details" + assert ( + "error" in data + or "error_code" in data + or "detail" in data + or response.url.endswith("sign-in") + ), "Error response should contain error details" except ValueError: # It's ok if response isn't JSON format pass elif response.status_code in [302, 303]: # If it's a redirect, it should redirect to a login page or error page - redirect_url = response.headers.get('Location', '') - assert "error" in redirect_url or "sign-in" in redirect_url, \ + redirect_url = response.headers.get("Location", "") + assert "error" in redirect_url or "sign-in" in redirect_url, ( "Failed login should redirect to login page or error page" + ) # 2. Test good login with correct credentials response = requests.post( url, - data={ - "email": user_data["email"], - "password": user_data["password"] - }, - allow_redirects=False # Don't follow redirects + data={"email": user_data["email"], "password": user_data["password"]}, + allow_redirects=False, # Don't follow redirects ) # Successful auth should not be a client error or server error - assert response.status_code not in range(400, 600), \ + assert response.status_code not in range(400, 600), ( f"Authentication with valid credentials failed with status {response.status_code}" + ) # Specific validation based on response type if response.status_code in [302, 303]: # Redirect-based auth: check that redirect URL doesn't contain error - redirect_url = response.headers.get('Location', '') - assert "error" not in redirect_url and "error_code" not in redirect_url, \ + redirect_url = response.headers.get("Location", "") + assert "error" not in redirect_url and "error_code" not in redirect_url, ( "Successful login redirect should not contain error parameters" + ) elif response.status_code == 200: # API token-based auth: check for tokens or user session - if hasattr(response, 'json'): + if hasattr(response, "json"): try: data = response.json() # If it's a token response if "access_token" in data: - assert "refresh_token" in data, "JWT auth should return both access and refresh tokens" + assert "refresh_token" in data, ( + "JWT auth should return both access and refresh tokens" + ) # If it's a user session response elif "user" in data: - assert "is_authenticated" in data and data["is_authenticated"], \ - "User session response should indicate authentication" + assert ( + "is_authenticated" in data and data["is_authenticated"] + ), "User session response should indicate authentication" # Otherwise it should at least indicate success else: - assert not any(error_key in data for error_key in ["error", "error_code", "detail"]), \ - "Success response should not contain error keys" + assert not any( + error_key in data + for error_key in ["error", "error_code", "detail"] + ), "Success response should not contain error keys" except ValueError: # Non-JSON is acceptable if it's a redirect or HTML response pass @@ -97,4 +104,4 @@ class TestHealthCheckSmoke: response = requests.get(f"{plane_server.url}/") # Should be OK - assert response.status_code == 200, "Health check endpoint should return 200 OK" \ No newline at end of file + assert response.status_code == 200, "Health check endpoint should return 200 OK" diff --git a/apiserver/plane/tests/unit/models/__init__.py b/apps/api/plane/tests/unit/__init__.py similarity index 100% rename from apiserver/plane/tests/unit/models/__init__.py rename to apps/api/plane/tests/unit/__init__.py diff --git a/apps/api/plane/tests/unit/bg_tasks/test_copy_s3_objects.py b/apps/api/plane/tests/unit/bg_tasks/test_copy_s3_objects.py new file mode 100644 index 000000000..bbb98e6b1 --- /dev/null +++ b/apps/api/plane/tests/unit/bg_tasks/test_copy_s3_objects.py @@ -0,0 +1,182 @@ +import pytest +from plane.db.models import Project, ProjectMember, Issue, FileAsset +from unittest.mock import patch, MagicMock +from plane.bgtasks.copy_s3_object import ( + copy_s3_objects_of_description_and_assets, + copy_assets, +) +import base64 + + +@pytest.mark.unit +class TestCopyS3Objects: + """Test the copy_s3_objects_of_description_and_assets function""" + + @pytest.fixture + def project(self, create_user, workspace): + project = Project.objects.create( + name="Test Project", identifier="test-project", workspace=workspace + ) + + ProjectMember.objects.create(project=project, member=create_user) + return project + + @pytest.fixture + def issue(self, workspace, project): + return Issue.objects.create( + name="Test Issue", + workspace=workspace, + project_id=project.id, + description_html=f'
', + ) + + @pytest.fixture + def file_asset(self, workspace, project, issue): + return FileAsset.objects.create( + issue=issue, + workspace=workspace, + project=project, + asset="workspace1/test-asset-1.jpg", + attributes={ + "name": "test-asset-1.jpg", + "size": 100, + "type": "image/jpeg", + }, + id="35e8b958-6ee5-43ce-ae56-fb0e776f421e", + entity_type="ISSUE_DESCRIPTION", + ) + + @pytest.mark.django_db + @patch("plane.bgtasks.copy_s3_object.S3Storage") + def test_copy_s3_objects_of_description_and_assets( + self, mock_s3_storage, create_user, workspace, project, issue, file_asset + ): + FileAsset.objects.create( + issue=issue, + workspace=workspace, + project=project, + asset="workspace1/test-asset-2.pdf", + attributes={ + "name": "test-asset-2.pdf", + "size": 100, + "type": "application/pdf", + }, + id="97988198-274f-4dfe-aa7a-4c0ffc684214", + entity_type="ISSUE_DESCRIPTION", + ) + + issue.save() + + # Set up mock S3 storage + mock_storage_instance = MagicMock() + mock_s3_storage.return_value = mock_storage_instance + + # Mock the external service call to avoid actual HTTP requests + with patch( + "plane.bgtasks.copy_s3_object.sync_with_external_service" + ) as mock_sync: + mock_sync.return_value = { + "description": "test description", + "description_binary": base64.b64encode(b"test binary").decode(), + } + + # Call the actual function (not .delay()) + copy_s3_objects_of_description_and_assets( + "ISSUE", issue.id, project.id, "test-workspace", create_user.id + ) + + # Assert that copy_object was called for each asset + assert mock_storage_instance.copy_object.call_count == 2 + + # Get the updated issue and its new assets + updated_issue = Issue.objects.get(id=issue.id) + new_assets = FileAsset.objects.filter( + issue=updated_issue, + entity_type="ISSUE_DESCRIPTION", + ) + + # Verify new assets were created + assert new_assets.count() == 4 # 2 original + 2 copied + + @pytest.mark.django_db + @patch("plane.bgtasks.copy_s3_object.S3Storage") + def test_copy_assets_successful( + self, mock_s3_storage, workspace, project, issue, file_asset + ): + """Test successful copying of assets""" + # Arrange + mock_storage_instance = MagicMock() + mock_s3_storage.return_value = mock_storage_instance + + # Act + result = copy_assets( + entity=issue, + entity_identifier=issue.id, + project_id=project.id, + asset_ids=[file_asset.id], + user_id=issue.created_by_id, + ) + + # Assert + # Verify S3 copy was called + mock_storage_instance.copy_object.assert_called_once() + + # Verify new asset was created + assert len(result) == 1 + new_asset_id = result[0]["new_asset_id"] + new_asset = FileAsset.objects.get(id=new_asset_id) + + # Verify asset properties were copied correctly + assert new_asset.workspace == workspace + assert new_asset.project_id == project.id + assert new_asset.entity_type == file_asset.entity_type + assert new_asset.attributes == file_asset.attributes + assert new_asset.size == file_asset.size + assert new_asset.is_uploaded is True + + @pytest.mark.django_db + @patch("plane.bgtasks.copy_s3_object.S3Storage") + def test_copy_assets_empty_asset_ids( + self, mock_s3_storage, workspace, project, issue + ): + """Test copying with empty asset_ids list""" + # Arrange + mock_storage_instance = MagicMock() + mock_s3_storage.return_value = mock_storage_instance + + # Act + result = copy_assets( + entity=issue, + entity_identifier=issue.id, + project_id=project.id, + asset_ids=[], + user_id=issue.created_by_id, + ) + + # Assert + assert result == [] + mock_storage_instance.copy_object.assert_not_called() + + @pytest.mark.django_db + @patch("plane.bgtasks.copy_s3_object.S3Storage") + def test_copy_assets_nonexistent_asset( + self, mock_s3_storage, workspace, project, issue + ): + """Test copying with non-existent asset ID""" + # Arrange + mock_storage_instance = MagicMock() + mock_s3_storage.return_value = mock_storage_instance + non_existent_id = "00000000-0000-0000-0000-000000000000" + + # Act + result = copy_assets( + entity=issue, + entity_identifier=issue.id, + project_id=project.id, + asset_ids=[non_existent_id], + user_id=issue.created_by_id, + ) + + # Assert + assert result == [] + mock_storage_instance.copy_object.assert_not_called() diff --git a/apiserver/plane/tests/unit/serializers/__init__.py b/apps/api/plane/tests/unit/models/__init__.py similarity index 100% rename from apiserver/plane/tests/unit/serializers/__init__.py rename to apps/api/plane/tests/unit/models/__init__.py diff --git a/apiserver/plane/tests/unit/models/test_workspace_model.py b/apps/api/plane/tests/unit/models/test_workspace_model.py similarity index 78% rename from apiserver/plane/tests/unit/models/test_workspace_model.py rename to apps/api/plane/tests/unit/models/test_workspace_model.py index 40380fa0f..aa3c15645 100644 --- a/apiserver/plane/tests/unit/models/test_workspace_model.py +++ b/apps/api/plane/tests/unit/models/test_workspace_model.py @@ -13,10 +13,7 @@ class TestWorkspaceModel: """Test creating a workspace""" # Create a workspace workspace = Workspace.objects.create( - name="Test Workspace", - slug="test-workspace", - id=uuid4(), - owner=create_user + name="Test Workspace", slug="test-workspace", id=uuid4(), owner=create_user ) # Verify it was created @@ -30,21 +27,18 @@ class TestWorkspaceModel: """Test creating a workspace member""" # Create a workspace workspace = Workspace.objects.create( - name="Test Workspace", - slug="test-workspace", - id=uuid4(), - owner=create_user + name="Test Workspace", slug="test-workspace", id=uuid4(), owner=create_user ) # Create a workspace member workspace_member = WorkspaceMember.objects.create( workspace=workspace, member=create_user, - role=20 # Admin role + role=20, # Admin role ) # Verify it was created assert workspace_member.id is not None assert workspace_member.workspace == workspace assert workspace_member.member == create_user - assert workspace_member.role == 20 \ No newline at end of file + assert workspace_member.role == 20 diff --git a/apiserver/plane/tests/unit/utils/__init__.py b/apps/api/plane/tests/unit/serializers/__init__.py similarity index 100% rename from apiserver/plane/tests/unit/utils/__init__.py rename to apps/api/plane/tests/unit/serializers/__init__.py diff --git a/apiserver/plane/tests/unit/serializers/test_issue_recent_visit.py b/apps/api/plane/tests/unit/serializers/test_issue_recent_visit.py similarity index 100% rename from apiserver/plane/tests/unit/serializers/test_issue_recent_visit.py rename to apps/api/plane/tests/unit/serializers/test_issue_recent_visit.py diff --git a/apiserver/plane/tests/unit/serializers/test_workspace.py b/apps/api/plane/tests/unit/serializers/test_workspace.py similarity index 74% rename from apiserver/plane/tests/unit/serializers/test_workspace.py rename to apps/api/plane/tests/unit/serializers/test_workspace.py index 19767a7c6..28e6c8d75 100644 --- a/apiserver/plane/tests/unit/serializers/test_workspace.py +++ b/apps/api/plane/tests/unit/serializers/test_workspace.py @@ -13,18 +13,13 @@ class TestWorkspaceLiteSerializer: """Test that the serializer includes the correct fields""" # Create a user to be the owner owner = User.objects.create( - email="test@example.com", - first_name="Test", - last_name="User" + email="test@example.com", first_name="Test", last_name="User" ) # Create a workspace with explicit ID to test serialization workspace_id = uuid4() workspace = Workspace.objects.create( - name="Test Workspace", - slug="test-workspace", - id=workspace_id, - owner=owner + name="Test Workspace", slug="test-workspace", id=workspace_id, owner=owner ) # Serialize the workspace @@ -43,23 +38,17 @@ class TestWorkspaceLiteSerializer: """Test that the serializer fields are read-only""" # Create a user to be the owner owner = User.objects.create( - email="test2@example.com", - first_name="Test", - last_name="User" + email="test2@example.com", first_name="Test", last_name="User" ) # Create a workspace workspace = Workspace.objects.create( - name="Test Workspace", - slug="test-workspace", - id=uuid4(), - owner=owner + name="Test Workspace", slug="test-workspace", id=uuid4(), owner=owner ) # Try to update via serializer serializer = WorkspaceLiteSerializer( - workspace, - data={"name": "Updated Name", "slug": "updated-slug"} + workspace, data={"name": "Updated Name", "slug": "updated-slug"} ) # Serializer should be valid (since read-only fields are ignored) @@ -68,4 +57,4 @@ class TestWorkspaceLiteSerializer: # Save should not update the read-only fields updated_workspace = serializer.save() assert updated_workspace.name == "Test Workspace" - assert updated_workspace.slug == "test-workspace" \ No newline at end of file + assert updated_workspace.slug == "test-workspace" diff --git a/apiserver/plane/utils/__init__.py b/apps/api/plane/tests/unit/utils/__init__.py similarity index 100% rename from apiserver/plane/utils/__init__.py rename to apps/api/plane/tests/unit/utils/__init__.py diff --git a/apps/api/plane/tests/unit/utils/test_url.py b/apps/api/plane/tests/unit/utils/test_url.py new file mode 100644 index 000000000..ec3ef7a73 --- /dev/null +++ b/apps/api/plane/tests/unit/utils/test_url.py @@ -0,0 +1,262 @@ +import pytest +from plane.utils.url import ( + contains_url, + is_valid_url, + get_url_components, + normalize_url_path, +) + + +@pytest.mark.unit +class TestContainsURL: + """Test the contains_url function""" + + def test_contains_url_with_http_protocol(self): + """Test contains_url with HTTP protocol URLs""" + assert contains_url("Check out http://example.com") is True + assert contains_url("Visit http://google.com/search") is True + assert contains_url("http://localhost:8000") is True + + def test_contains_url_with_https_protocol(self): + """Test contains_url with HTTPS protocol URLs""" + assert contains_url("Check out https://example.com") is True + assert contains_url("Visit https://google.com/search") is True + assert contains_url("https://secure.example.com") is True + + def test_contains_url_with_www_prefix(self): + """Test contains_url with www prefix""" + assert contains_url("Visit www.example.com") is True + assert contains_url("Check www.google.com") is True + assert contains_url("Go to www.test-site.org") is True + + def test_contains_url_with_domain_patterns(self): + """Test contains_url with domain patterns""" + assert contains_url("Visit example.com") is True + assert contains_url("Check google.org") is True + assert contains_url("Go to test-site.co.uk") is True + assert contains_url("Visit sub.domain.com") is True + + def test_contains_url_with_ip_addresses(self): + """Test contains_url with IP addresses""" + assert contains_url("Connect to 192.168.1.1") is True + assert contains_url("Visit 10.0.0.1") is True + assert contains_url("Check 127.0.0.1") is True + assert contains_url("Go to 8.8.8.8") is True + + def test_contains_url_case_insensitive(self): + """Test contains_url is case insensitive""" + assert contains_url("Check HTTP://EXAMPLE.COM") is True + assert contains_url("Visit WWW.GOOGLE.COM") is True + assert contains_url("Go to Https://Test.Com") is True + + def test_contains_url_with_no_urls(self): + """Test contains_url with text that doesn't contain URLs""" + assert contains_url("This is just plain text") is False + assert contains_url("No URLs here!") is False + assert contains_url("com org net") is False # Just TLD words + assert contains_url("192.168") is False # Incomplete IP + assert contains_url("") is False # Empty string + + def test_contains_url_edge_cases(self): + """Test contains_url with edge cases""" + assert contains_url("example.c") is False # TLD too short + assert contains_url("999.999.999.999") is False # Invalid IP (octets > 255) + assert contains_url("just-a-hyphen") is False # No domain + assert ( + contains_url("www.") is False + ) # Incomplete www - needs at least one char after dot + + def test_contains_url_length_limit_under_1000(self): + """Test contains_url with input under 1000 characters containing URLs""" + # Create a string under 1000 characters with a URL + text_with_url = "a" * 970 + " https://example.com" # 970 + 1 + 19 = 990 chars + assert len(text_with_url) < 1000 + assert contains_url(text_with_url) is True + + # Test with exactly 1000 characters + text_exact_1000 = "a" * 981 + "https://example.com" # 981 + 19 = 1000 chars + assert len(text_exact_1000) == 1000 + assert contains_url(text_exact_1000) is True + + def test_contains_url_length_limit_over_1000(self): + """Test contains_url with input over 1000 characters returns False""" + # Create a string over 1000 characters with a URL + text_with_url = "a" * 982 + "https://example.com" # 982 + 19 = 1001 chars + assert len(text_with_url) > 1000 + assert contains_url(text_with_url) is False + + # Test with much longer input + long_text_with_url = "a" * 5000 + " https://example.com" + assert contains_url(long_text_with_url) is False + + def test_contains_url_length_limit_exactly_1000(self): + """Test contains_url with input exactly 1000 characters""" + # Test with exactly 1000 characters without URL + text_no_url = "a" * 1000 + assert len(text_no_url) == 1000 + assert contains_url(text_no_url) is False + + # Test with exactly 1000 characters with URL at the end + text_with_url = "a" * 981 + "https://example.com" # 981 + 19 = 1000 chars + assert len(text_with_url) == 1000 + assert contains_url(text_with_url) is True + + def test_contains_url_line_length_scenarios(self): + """Test contains_url with realistic line length scenarios""" + # Test with multiline input where total is under 1000 but we test line processing + # Short lines with URL + multiline_short = "Line 1\nLine 2 with https://example.com\nLine 3" + assert contains_url(multiline_short) is True + + # Multiple lines under total limit + multiline_text = ( + "a" * 200 + "\n" + "b" * 200 + "https://example.com\n" + "c" * 200 + ) + assert len(multiline_text) < 1000 + assert contains_url(multiline_text) is True + + def test_contains_url_total_length_vs_line_length(self): + """Test the interaction between total length limit and line processing""" + # Test that total length limit takes precedence + # Even if individual lines would be processed, total > 1000 means immediate False + over_limit_text = "a" * 1001 # No URL, but over total limit + assert contains_url(over_limit_text) is False + + # Test that under total limit, line processing works normally + under_limit_with_url = "a" * 900 + "https://example.com" # 919 chars total + assert len(under_limit_with_url) < 1000 + assert contains_url(under_limit_with_url) is True + + def test_contains_url_multiline_mixed_lengths(self): + """Test contains_url with multiple lines of different lengths""" + # Test realistic multiline scenario under 1000 chars total + multiline_text = ( + "Short line\n" + + "a" * 400 + + "https://example.com\n" # Line with URL + + "b" * 300 # Another line + ) + assert len(multiline_text) < 1000 + assert contains_url(multiline_text) is True + + # Test multiline without URLs + multiline_no_url = "Short line\n" + "a" * 400 + "\n" + "b" * 300 + assert len(multiline_no_url) < 1000 + assert contains_url(multiline_no_url) is False + + def test_contains_url_edge_cases_with_length_limits(self): + """Test contains_url edge cases related to length limits""" + # Empty string + assert contains_url("") is False + + # Very short string with URL + assert contains_url("http://a.co") is True + + # String with newlines and mixed content + mixed_content = "Line 1\nLine 2 with https://example.com\nLine 3" + assert contains_url(mixed_content) is True + + # String with many newlines under total limit + many_newlines = "\n" * 500 + "https://example.com" + assert len(many_newlines) < 1000 + assert contains_url(many_newlines) is True + + +@pytest.mark.unit +class TestIsValidURL: + """Test the is_valid_url function""" + + def test_is_valid_url_with_valid_urls(self): + """Test is_valid_url with valid URLs""" + assert is_valid_url("https://example.com") is True + assert is_valid_url("http://google.com") is True + assert is_valid_url("https://sub.domain.com/path") is True + assert is_valid_url("http://localhost:8000") is True + assert is_valid_url("https://example.com/path?query=1") is True + assert is_valid_url("ftp://files.example.com") is True + + def test_is_valid_url_with_invalid_urls(self): + """Test is_valid_url with invalid URLs""" + assert is_valid_url("not a url") is False + assert is_valid_url("example.com") is False # No scheme + assert is_valid_url("https://") is False # No netloc + assert is_valid_url("") is False # Empty string + assert is_valid_url("://example.com") is False # No scheme + assert is_valid_url("https:/example.com") is False # Malformed + + def test_is_valid_url_with_non_string_input(self): + """Test is_valid_url with non-string input""" + assert is_valid_url(None) is False + assert is_valid_url([]) is False + assert is_valid_url({}) is False + + def test_is_valid_url_with_special_schemes(self): + """Test is_valid_url with special URL schemes""" + assert is_valid_url("ftp://ftp.example.com") is True + assert is_valid_url("mailto:user@example.com") is False + assert is_valid_url("file:///path/to/file") is False + + +@pytest.mark.unit +class TestNormalizeURLPath: + """Test the normalize_url_path function""" + + def test_normalize_url_path_with_multiple_slashes(self): + """Test normalize_url_path with multiple consecutive slashes""" + result = normalize_url_path("https://example.com//foo///bar//baz") + assert result == "https://example.com/foo/bar/baz" + + def test_normalize_url_path_with_query_and_fragment(self): + """Test normalize_url_path preserves query and fragment""" + result = normalize_url_path( + "https://example.com//foo///bar//baz?x=1&y=2#fragment" + ) + assert result == "https://example.com/foo/bar/baz?x=1&y=2#fragment" + + def test_normalize_url_path_with_no_redundant_slashes(self): + """Test normalize_url_path with already normalized URL""" + url = "https://example.com/foo/bar/baz?x=1#fragment" + result = normalize_url_path(url) + assert result == url + + def test_normalize_url_path_with_root_path(self): + """Test normalize_url_path with root path""" + result = normalize_url_path("https://example.com//") + assert result == "https://example.com/" + + def test_normalize_url_path_with_empty_path(self): + """Test normalize_url_path with empty path""" + result = normalize_url_path("https://example.com") + assert result == "https://example.com" + + def test_normalize_url_path_with_complex_path(self): + """Test normalize_url_path with complex path structure""" + result = normalize_url_path( + "https://example.com///api//v1///users//123//profile" + ) + assert result == "https://example.com/api/v1/users/123/profile" + + def test_normalize_url_path_with_different_schemes(self): + """Test normalize_url_path with different URL schemes""" + # HTTP + result = normalize_url_path("http://example.com//path") + assert result == "http://example.com/path" + + # FTP + result = normalize_url_path("ftp://ftp.example.com//files//document.txt") + assert result == "ftp://ftp.example.com/files/document.txt" + + def test_normalize_url_path_with_port(self): + """Test normalize_url_path with port number""" + result = normalize_url_path("https://example.com:8080//api//v1") + assert result == "https://example.com:8080/api/v1" + + def test_normalize_url_path_edge_cases(self): + """Test normalize_url_path with edge cases""" + # Many consecutive slashes + result = normalize_url_path("https://example.com///////path") + assert result == "https://example.com/path" + + # Mixed single and multiple slashes + result = normalize_url_path("https://example.com/a//b/c///d") + assert result == "https://example.com/a/b/c/d" diff --git a/apiserver/plane/tests/unit/utils/test_uuid.py b/apps/api/plane/tests/unit/utils/test_uuid.py similarity index 90% rename from apiserver/plane/tests/unit/utils/test_uuid.py rename to apps/api/plane/tests/unit/utils/test_uuid.py index 81403c5be..5503f2bc3 100644 --- a/apiserver/plane/tests/unit/utils/test_uuid.py +++ b/apps/api/plane/tests/unit/utils/test_uuid.py @@ -19,7 +19,9 @@ class TestUUIDUtils: assert is_valid_uuid("not-a-uuid") is False assert is_valid_uuid("123456789") is False assert is_valid_uuid("") is False - assert is_valid_uuid("00000000-0000-0000-0000-000000000000") is False # This is a valid UUID but version 1 + assert ( + is_valid_uuid("00000000-0000-0000-0000-000000000000") is False + ) # This is a valid UUID but version 1 def test_convert_uuid_to_integer(self): """Test convert_uuid_to_integer function""" @@ -46,4 +48,6 @@ class TestUUIDUtils: test_uuid = uuid.UUID(test_uuid_str) # Should get the same result whether passing UUID or string - assert convert_uuid_to_integer(test_uuid) == convert_uuid_to_integer(test_uuid_str) \ No newline at end of file + assert convert_uuid_to_integer(test_uuid) == convert_uuid_to_integer( + test_uuid_str + ) diff --git a/apiserver/plane/urls.py b/apps/api/plane/urls.py similarity index 100% rename from apiserver/plane/urls.py rename to apps/api/plane/urls.py diff --git a/apiserver/plane/web/__init__.py b/apps/api/plane/utils/__init__.py similarity index 100% rename from apiserver/plane/web/__init__.py rename to apps/api/plane/utils/__init__.py diff --git a/apiserver/plane/utils/analytics_plot.py b/apps/api/plane/utils/analytics_plot.py similarity index 100% rename from apiserver/plane/utils/analytics_plot.py rename to apps/api/plane/utils/analytics_plot.py diff --git a/apiserver/plane/utils/build_chart.py b/apps/api/plane/utils/build_chart.py similarity index 100% rename from apiserver/plane/utils/build_chart.py rename to apps/api/plane/utils/build_chart.py diff --git a/apiserver/plane/utils/cache.py b/apps/api/plane/utils/cache.py similarity index 100% rename from apiserver/plane/utils/cache.py rename to apps/api/plane/utils/cache.py diff --git a/apiserver/plane/utils/constants.py b/apps/api/plane/utils/constants.py similarity index 100% rename from apiserver/plane/utils/constants.py rename to apps/api/plane/utils/constants.py diff --git a/apps/api/plane/utils/content_validator.py b/apps/api/plane/utils/content_validator.py new file mode 100644 index 000000000..7b9932a35 --- /dev/null +++ b/apps/api/plane/utils/content_validator.py @@ -0,0 +1,357 @@ +# Python imports +import base64 +import json +import re + + +# Maximum allowed size for binary data (10MB) +MAX_SIZE = 10 * 1024 * 1024 + +# Maximum recursion depth to prevent stack overflow +MAX_RECURSION_DEPTH = 20 + +# Dangerous text patterns that could indicate XSS or script injection +DANGEROUS_TEXT_PATTERNS = [ + r"]*>.*?", + r"javascript\s*:", + r"data\s*:\s*text/html", + r"eval\s*\(", + r"document\s*\.", + r"window\s*\.", + r"location\s*\.", +] + +# Dangerous attribute patterns for HTML attributes +DANGEROUS_ATTR_PATTERNS = [ + r"javascript\s*:", + r"data\s*:\s*text/html", + r"eval\s*\(", + r"alert\s*\(", + r"document\s*\.", + r"window\s*\.", +] + +# Suspicious patterns for binary data content +SUSPICIOUS_BINARY_PATTERNS = [ + "]*>", + r"", + # JavaScript URLs in various attributes + r'(?:href|src|action)\s*=\s*["\']?\s*javascript:', + # Data URLs with text/html (potential XSS) + r'(?:href|src|action)\s*=\s*["\']?\s*data:text/html', + # Dangerous event handlers with JavaScript-like content + r'on(?:load|error|click|focus|blur|change|submit|reset|select|resize|scroll|unload|beforeunload|hashchange|popstate|storage|message|offline|online)\s*=\s*["\']?[^"\']*(?:javascript|alert|eval|document\.|window\.|location\.|history\.)[^"\']*["\']?', + # Object and embed tags that could load external content + r"<(?:object|embed)[^>]*(?:data|src)\s*=", + # Base tag that could change relative URL resolution + r"]*href\s*=", + # Dangerous iframe sources + r']*src\s*=\s*["\']?(?:javascript:|data:text/html)', + # Meta refresh redirects + r']*http-equiv\s*=\s*["\']?refresh["\']?', + # Link tags - simplified patterns + r']*rel\s*=\s*["\']?stylesheet["\']?', + r']*href\s*=\s*["\']?https?://', + r']*href\s*=\s*["\']?//', + r']*href\s*=\s*["\']?(?:data:|javascript:)', + # Style tags with external imports + r"]*>.*?@import.*?(?:https?://|//)", + # Link tags with dangerous rel types + r']*rel\s*=\s*["\']?(?:import|preload|prefetch|dns-prefetch|preconnect)["\']?', + # Forms with action attributes + r"]*action\s*=", +] + +# Dangerous JavaScript patterns for event handlers +DANGEROUS_JS_PATTERNS = [ + r"alert\s*\(", + r"eval\s*\(", + r"document\s*\.", + r"window\s*\.", + r"location\s*\.", + r"fetch\s*\(", + r"XMLHttpRequest", + r"innerHTML\s*=", + r"outerHTML\s*=", + r"document\.write", + r"script\s*>", +] + +# HTML self-closing tags that don't need closing tags +SELF_CLOSING_TAGS = { + "img", + "br", + "hr", + "input", + "meta", + "link", + "area", + "base", + "col", + "embed", + "source", + "track", + "wbr", +} + + +def validate_binary_data(data): + """ + Validate that binary data appears to be valid document format and doesn't contain malicious content. + + Args: + data (bytes or str): The binary data to validate, or base64-encoded string + + Returns: + tuple: (is_valid: bool, error_message: str or None) + """ + if not data: + return True, None # Empty is OK + + # Handle base64-encoded strings by decoding them first + if isinstance(data, str): + try: + binary_data = base64.b64decode(data) + except Exception: + return False, "Invalid base64 encoding" + else: + binary_data = data + + # Size check - 10MB limit + if len(binary_data) > MAX_SIZE: + return False, "Binary data exceeds maximum size limit (10MB)" + + # Basic format validation + if len(binary_data) < 4: + return False, "Binary data too short to be valid document format" + + # Check for suspicious text patterns (HTML/JS) + try: + decoded_text = binary_data.decode("utf-8", errors="ignore")[:200] + if any( + pattern in decoded_text.lower() for pattern in SUSPICIOUS_BINARY_PATTERNS + ): + return False, "Binary data contains suspicious content patterns" + except Exception: + pass # Binary data might not be decodable as text, which is fine + + return True, None + + +def validate_html_content(html_content): + """ + Validate that HTML content is safe and doesn't contain malicious patterns. + + Args: + html_content (str): The HTML content to validate + + Returns: + tuple: (is_valid: bool, error_message: str or None) + """ + if not html_content: + return True, None # Empty is OK + + # Size check - 10MB limit (consistent with binary validation) + if len(html_content.encode("utf-8")) > MAX_SIZE: + return False, "HTML content exceeds maximum size limit (10MB)" + + # Check for specific malicious patterns (simplified and more reliable) + for pattern in MALICIOUS_HTML_PATTERNS: + if re.search(pattern, html_content, re.IGNORECASE | re.DOTALL): + return ( + False, + f"HTML content contains potentially malicious patterns: {pattern}", + ) + + # Additional check for inline event handlers that contain suspicious content + # This is more permissive - only blocks if the event handler contains actual dangerous code + event_handler_pattern = r'on\w+\s*=\s*["\']([^"\']*)["\']' + event_matches = re.findall(event_handler_pattern, html_content, re.IGNORECASE) + + for handler_content in event_matches: + for js_pattern in DANGEROUS_JS_PATTERNS: + if re.search(js_pattern, handler_content, re.IGNORECASE): + return ( + False, + f"HTML content contains dangerous JavaScript in event handler: {handler_content[:100]}", + ) + + # Basic HTML structure validation - check for common malformed tags + try: + # Count opening and closing tags for basic structure validation + opening_tags = re.findall(r"<(\w+)[^>]*>", html_content) + closing_tags = re.findall(r"", html_content) + + # Filter out self-closing tags from opening tags + opening_tags_filtered = [ + tag for tag in opening_tags if tag.lower() not in SELF_CLOSING_TAGS + ] + + # Basic check - if we have significantly more opening than closing tags, it might be malformed + if len(opening_tags_filtered) > len(closing_tags) + 10: # Allow some tolerance + return False, "HTML content appears to be malformed (unmatched tags)" + + except Exception: + # If HTML parsing fails, we'll allow it + pass + + return True, None + + +def validate_json_content(json_content): + """ + Validate that JSON content is safe and doesn't contain malicious patterns. + + Args: + json_content (dict): The JSON content to validate + + Returns: + tuple: (is_valid: bool, error_message: str or None) + """ + if not json_content: + return True, None # Empty is OK + + try: + # Size check - 10MB limit (consistent with other validations) + json_str = json.dumps(json_content) + if len(json_str.encode("utf-8")) > MAX_SIZE: + return False, "JSON content exceeds maximum size limit (10MB)" + + # Basic structure validation for page description JSON + if isinstance(json_content, dict): + # Check for expected page description structure + # This is based on ProseMirror/Tiptap JSON structure + if "type" in json_content and json_content.get("type") == "doc": + # Valid document structure + if "content" in json_content and isinstance( + json_content["content"], list + ): + # Recursively check content for suspicious patterns + is_valid, error_msg = _validate_json_content_array( + json_content["content"] + ) + if not is_valid: + return False, error_msg + elif "type" not in json_content and "content" not in json_content: + # Allow other JSON structures but validate for suspicious content + is_valid, error_msg = _validate_json_content_recursive(json_content) + if not is_valid: + return False, error_msg + else: + return False, "JSON description must be a valid object" + + except (TypeError, ValueError) as e: + return False, "Invalid JSON structure" + except Exception as e: + return False, "Failed to validate JSON content" + + return True, None + + +def _validate_json_content_array(content, depth=0): + """ + Validate JSON content array for suspicious patterns. + + Args: + content (list): Array of content nodes to validate + depth (int): Current recursion depth (default: 0) + + Returns: + tuple: (is_valid: bool, error_message: str or None) + """ + # Check recursion depth to prevent stack overflow + if depth > MAX_RECURSION_DEPTH: + return False, f"Maximum recursion depth ({MAX_RECURSION_DEPTH}) exceeded" + + if not isinstance(content, list): + return True, None + + for node in content: + if isinstance(node, dict): + # Check text content for suspicious patterns (more targeted) + if node.get("type") == "text" and "text" in node: + text_content = node["text"] + for pattern in DANGEROUS_TEXT_PATTERNS: + if re.search(pattern, text_content, re.IGNORECASE): + return ( + False, + "JSON content contains suspicious script patterns in text", + ) + + # Check attributes for suspicious content (more targeted) + if "attrs" in node and isinstance(node["attrs"], dict): + for attr_name, attr_value in node["attrs"].items(): + if isinstance(attr_value, str): + # Only check specific attributes that could be dangerous + if attr_name.lower() in [ + "href", + "src", + "action", + "onclick", + "onload", + "onerror", + ]: + for pattern in DANGEROUS_ATTR_PATTERNS: + if re.search(pattern, attr_value, re.IGNORECASE): + return ( + False, + f"JSON content contains dangerous pattern in {attr_name} attribute", + ) + + # Recursively check nested content + if "content" in node and isinstance(node["content"], list): + is_valid, error_msg = _validate_json_content_array( + node["content"], depth + 1 + ) + if not is_valid: + return False, error_msg + + return True, None + + +def _validate_json_content_recursive(obj, depth=0): + """ + Recursively validate JSON object for suspicious content. + + Args: + obj: JSON object (dict, list, or primitive) to validate + depth (int): Current recursion depth (default: 0) + + Returns: + tuple: (is_valid: bool, error_message: str or None) + """ + # Check recursion depth to prevent stack overflow + if depth > MAX_RECURSION_DEPTH: + return False, f"Maximum recursion depth ({MAX_RECURSION_DEPTH}) exceeded" + if isinstance(obj, dict): + for key, value in obj.items(): + if isinstance(value, str): + # Check for dangerous patterns using module constants + for pattern in DANGEROUS_TEXT_PATTERNS: + if re.search(pattern, value, re.IGNORECASE): + return ( + False, + "JSON content contains suspicious script patterns", + ) + elif isinstance(value, (dict, list)): + is_valid, error_msg = _validate_json_content_recursive(value, depth + 1) + if not is_valid: + return False, error_msg + elif isinstance(obj, list): + for item in obj: + is_valid, error_msg = _validate_json_content_recursive(item, depth + 1) + if not is_valid: + return False, error_msg + + return True, None diff --git a/apiserver/plane/utils/date_utils.py b/apps/api/plane/utils/date_utils.py similarity index 100% rename from apiserver/plane/utils/date_utils.py rename to apps/api/plane/utils/date_utils.py diff --git a/apiserver/plane/utils/error_codes.py b/apps/api/plane/utils/error_codes.py similarity index 100% rename from apiserver/plane/utils/error_codes.py rename to apps/api/plane/utils/error_codes.py diff --git a/apiserver/plane/utils/exception_logger.py b/apps/api/plane/utils/exception_logger.py similarity index 55% rename from apiserver/plane/utils/exception_logger.py rename to apps/api/plane/utils/exception_logger.py index 6ccccd32d..b0a6f8c38 100644 --- a/apiserver/plane/utils/exception_logger.py +++ b/apps/api/plane/utils/exception_logger.py @@ -6,13 +6,15 @@ import traceback from django.conf import settings -def log_exception(e): +def log_exception(e, warning=False): # Log the error logger = logging.getLogger("plane.exception") - logger.exception(e) + + if warning: + logger.warning(str(e)) + else: + logger.exception(e) if settings.DEBUG: - # Print the traceback if in debug mode - print(traceback.format_exc()) - + logger.debug(traceback.format_exc()) return diff --git a/apiserver/plane/utils/global_paginator.py b/apps/api/plane/utils/global_paginator.py similarity index 94% rename from apiserver/plane/utils/global_paginator.py rename to apps/api/plane/utils/global_paginator.py index 338d86117..1b7f908c5 100644 --- a/apiserver/plane/utils/global_paginator.py +++ b/apps/api/plane/utils/global_paginator.py @@ -50,11 +50,11 @@ def paginate(base_queryset, queryset, cursor, on_result): paginated_data = queryset[start_index:end_index] # Create the pagination info object - prev_cursor = f"{page_size}:{cursor_object.current_page-1}:0" + prev_cursor = f"{page_size}:{cursor_object.current_page - 1}:0" cursor = f"{page_size}:{cursor_object.current_page}:0" next_cursor = None if end_index < total_results: - next_cursor = f"{page_size}:{cursor_object.current_page+1}:0" + next_cursor = f"{page_size}:{cursor_object.current_page + 1}:0" prev_page_results = False if cursor_object.current_page > 0: diff --git a/apiserver/plane/utils/grouper.py b/apps/api/plane/utils/grouper.py similarity index 100% rename from apiserver/plane/utils/grouper.py rename to apps/api/plane/utils/grouper.py diff --git a/apiserver/plane/utils/host.py b/apps/api/plane/utils/host.py similarity index 100% rename from apiserver/plane/utils/host.py rename to apps/api/plane/utils/host.py diff --git a/apiserver/plane/utils/html_processor.py b/apps/api/plane/utils/html_processor.py similarity index 100% rename from apiserver/plane/utils/html_processor.py rename to apps/api/plane/utils/html_processor.py diff --git a/apiserver/plane/utils/imports.py b/apps/api/plane/utils/imports.py similarity index 100% rename from apiserver/plane/utils/imports.py rename to apps/api/plane/utils/imports.py diff --git a/apiserver/plane/utils/ip_address.py b/apps/api/plane/utils/ip_address.py similarity index 100% rename from apiserver/plane/utils/ip_address.py rename to apps/api/plane/utils/ip_address.py diff --git a/apiserver/plane/utils/issue_filters.py b/apps/api/plane/utils/issue_filters.py similarity index 100% rename from apiserver/plane/utils/issue_filters.py rename to apps/api/plane/utils/issue_filters.py diff --git a/apiserver/plane/utils/issue_relation_mapper.py b/apps/api/plane/utils/issue_relation_mapper.py similarity index 100% rename from apiserver/plane/utils/issue_relation_mapper.py rename to apps/api/plane/utils/issue_relation_mapper.py diff --git a/apiserver/plane/utils/issue_search.py b/apps/api/plane/utils/issue_search.py similarity index 100% rename from apiserver/plane/utils/issue_search.py rename to apps/api/plane/utils/issue_search.py diff --git a/apiserver/plane/utils/logging.py b/apps/api/plane/utils/logging.py similarity index 100% rename from apiserver/plane/utils/logging.py rename to apps/api/plane/utils/logging.py diff --git a/apiserver/plane/utils/markdown.py b/apps/api/plane/utils/markdown.py similarity index 100% rename from apiserver/plane/utils/markdown.py rename to apps/api/plane/utils/markdown.py diff --git a/apiserver/plane/utils/order_queryset.py b/apps/api/plane/utils/order_queryset.py similarity index 100% rename from apiserver/plane/utils/order_queryset.py rename to apps/api/plane/utils/order_queryset.py diff --git a/apiserver/plane/utils/paginator.py b/apps/api/plane/utils/paginator.py similarity index 99% rename from apiserver/plane/utils/paginator.py rename to apps/api/plane/utils/paginator.py index 0793d2a30..ce9c65f64 100644 --- a/apiserver/plane/utils/paginator.py +++ b/apps/api/plane/utils/paginator.py @@ -35,7 +35,7 @@ class Cursor: # Return the representation of the cursor def __repr__(self): - return f"{type(self).__name__,}: value={self.value} offset={self.offset}, is_prev={int(self.is_prev)}" + return f"{(type(self).__name__,)}: value={self.value} offset={self.offset}, is_prev={int(self.is_prev)}" # noqa: E501 # Return if the cursor is true def __bool__(self): diff --git a/apiserver/plane/utils/path_validator.py b/apps/api/plane/utils/path_validator.py similarity index 100% rename from apiserver/plane/utils/path_validator.py rename to apps/api/plane/utils/path_validator.py diff --git a/apiserver/plane/utils/telemetry.py b/apps/api/plane/utils/telemetry.py similarity index 100% rename from apiserver/plane/utils/telemetry.py rename to apps/api/plane/utils/telemetry.py diff --git a/apiserver/plane/utils/timezone_converter.py b/apps/api/plane/utils/timezone_converter.py similarity index 100% rename from apiserver/plane/utils/timezone_converter.py rename to apps/api/plane/utils/timezone_converter.py diff --git a/apiserver/plane/utils/url.py b/apps/api/plane/utils/url.py similarity index 60% rename from apiserver/plane/utils/url.py rename to apps/api/plane/utils/url.py index 1b4a229a8..6c196c298 100644 --- a/apiserver/plane/utils/url.py +++ b/apps/api/plane/utils/url.py @@ -3,13 +3,50 @@ import re from typing import Optional from urllib.parse import urlparse, urlunparse +# Compiled regex pattern for better performance and ReDoS protection +# Using atomic groups and length limits to prevent excessive backtracking +URL_PATTERN = re.compile( + r"(?i)" # Case insensitive + r"(?:" # Non-capturing group for alternatives + r"https?://[^\s]+" # http:// or https:// followed by non-whitespace + r"|" + r"www\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*" # www.domain with proper length limits + r"|" + r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}" # domain.tld with length limits + r"|" + r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" # IP address with proper validation + r")" +) + def contains_url(value: str) -> bool: """ Check if the value contains a URL. + + This function is protected against ReDoS attacks by: + 1. Using a pre-compiled regex pattern + 2. Limiting input length to prevent excessive processing + 3. Using atomic groups and specific quantifiers to avoid backtracking + + Args: + value (str): The input string to check for URLs + + Returns: + bool: True if the string contains a URL, False otherwise """ - url_pattern = re.compile(r"https?://|www\\.") - return bool(url_pattern.search(value)) + # Prevent ReDoS by limiting input length + if len(value) > 1000: # Reasonable limit for URL detection + return False + + # Additional safety: truncate very long lines that might contain URLs + lines = value.split("\n") + for line in lines: + if len(line) > 500: # Process only reasonable length lines + line = line[:500] + if URL_PATTERN.search(line): + return True + + return False def is_valid_url(url: str) -> bool: diff --git a/apiserver/plane/utils/uuid.py b/apps/api/plane/utils/uuid.py similarity index 100% rename from apiserver/plane/utils/uuid.py rename to apps/api/plane/utils/uuid.py diff --git a/packages/types/src/issues/issue_subscription.d.ts b/apps/api/plane/web/__init__.py similarity index 100% rename from packages/types/src/issues/issue_subscription.d.ts rename to apps/api/plane/web/__init__.py diff --git a/apiserver/plane/web/apps.py b/apps/api/plane/web/apps.py similarity index 100% rename from apiserver/plane/web/apps.py rename to apps/api/plane/web/apps.py diff --git a/apiserver/plane/web/urls.py b/apps/api/plane/web/urls.py similarity index 100% rename from apiserver/plane/web/urls.py rename to apps/api/plane/web/urls.py diff --git a/apiserver/plane/web/views.py b/apps/api/plane/web/views.py similarity index 100% rename from apiserver/plane/web/views.py rename to apps/api/plane/web/views.py diff --git a/apiserver/plane/wsgi.py b/apps/api/plane/wsgi.py similarity index 100% rename from apiserver/plane/wsgi.py rename to apps/api/plane/wsgi.py diff --git a/apiserver/pyproject.toml b/apps/api/pyproject.toml similarity index 100% rename from apiserver/pyproject.toml rename to apps/api/pyproject.toml diff --git a/apiserver/pytest.ini b/apps/api/pytest.ini similarity index 100% rename from apiserver/pytest.ini rename to apps/api/pytest.ini diff --git a/apiserver/requirements.txt b/apps/api/requirements.txt similarity index 100% rename from apiserver/requirements.txt rename to apps/api/requirements.txt diff --git a/apiserver/requirements/base.txt b/apps/api/requirements/base.txt similarity index 100% rename from apiserver/requirements/base.txt rename to apps/api/requirements/base.txt diff --git a/apiserver/requirements/local.txt b/apps/api/requirements/local.txt similarity index 100% rename from apiserver/requirements/local.txt rename to apps/api/requirements/local.txt diff --git a/apiserver/requirements/production.txt b/apps/api/requirements/production.txt similarity index 100% rename from apiserver/requirements/production.txt rename to apps/api/requirements/production.txt diff --git a/apiserver/requirements/test.txt b/apps/api/requirements/test.txt similarity index 100% rename from apiserver/requirements/test.txt rename to apps/api/requirements/test.txt diff --git a/apiserver/run_tests.py b/apps/api/run_tests.py similarity index 70% rename from apiserver/run_tests.py rename to apps/api/run_tests.py index f4f0951b1..6f42229c9 100755 --- a/apiserver/run_tests.py +++ b/apps/api/run_tests.py @@ -6,36 +6,20 @@ import sys def main(): parser = argparse.ArgumentParser(description="Run Plane tests") + parser.add_argument("-u", "--unit", action="store_true", help="Run unit tests only") parser.add_argument( - "-u", "--unit", - action="store_true", - help="Run unit tests only" + "-c", "--contract", action="store_true", help="Run contract tests only" ) parser.add_argument( - "-c", "--contract", - action="store_true", - help="Run contract tests only" + "-s", "--smoke", action="store_true", help="Run smoke tests only" ) parser.add_argument( - "-s", "--smoke", - action="store_true", - help="Run smoke tests only" + "-o", "--coverage", action="store_true", help="Generate coverage report" ) parser.add_argument( - "-o", "--coverage", - action="store_true", - help="Generate coverage report" - ) - parser.add_argument( - "-p", "--parallel", - action="store_true", - help="Run tests in parallel" - ) - parser.add_argument( - "-v", "--verbose", - action="store_true", - help="Verbose output" + "-p", "--parallel", action="store_true", help="Run tests in parallel" ) + parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output") args = parser.parse_args() # Build command @@ -71,10 +55,10 @@ def main(): # Print command print(f"Running: {' '.join(cmd)}") - + # Execute command result = subprocess.run(cmd) - + # Check coverage thresholds if coverage is enabled if args.coverage: print("Checking coverage thresholds...") @@ -83,9 +67,9 @@ def main(): if coverage_result.returncode != 0: print("Coverage below threshold (90%)") sys.exit(coverage_result.returncode) - + sys.exit(result.returncode) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/apiserver/run_tests.sh b/apps/api/run_tests.sh similarity index 100% rename from apiserver/run_tests.sh rename to apps/api/run_tests.sh diff --git a/apiserver/templates/admin/base_site.html b/apps/api/templates/admin/base_site.html similarity index 100% rename from apiserver/templates/admin/base_site.html rename to apps/api/templates/admin/base_site.html diff --git a/apiserver/templates/base.html b/apps/api/templates/base.html similarity index 100% rename from apiserver/templates/base.html rename to apps/api/templates/base.html diff --git a/apiserver/templates/csrf_failure.html b/apps/api/templates/csrf_failure.html similarity index 100% rename from apiserver/templates/csrf_failure.html rename to apps/api/templates/csrf_failure.html diff --git a/apiserver/templates/emails/auth/forgot_password.html b/apps/api/templates/emails/auth/forgot_password.html similarity index 100% rename from apiserver/templates/emails/auth/forgot_password.html rename to apps/api/templates/emails/auth/forgot_password.html diff --git a/apiserver/templates/emails/auth/magic_signin.html b/apps/api/templates/emails/auth/magic_signin.html similarity index 100% rename from apiserver/templates/emails/auth/magic_signin.html rename to apps/api/templates/emails/auth/magic_signin.html diff --git a/apiserver/templates/emails/exports/analytics.html b/apps/api/templates/emails/exports/analytics.html similarity index 100% rename from apiserver/templates/emails/exports/analytics.html rename to apps/api/templates/emails/exports/analytics.html diff --git a/apiserver/templates/emails/invitations/project_invitation.html b/apps/api/templates/emails/invitations/project_invitation.html similarity index 100% rename from apiserver/templates/emails/invitations/project_invitation.html rename to apps/api/templates/emails/invitations/project_invitation.html diff --git a/apiserver/templates/emails/invitations/workspace_invitation.html b/apps/api/templates/emails/invitations/workspace_invitation.html similarity index 100% rename from apiserver/templates/emails/invitations/workspace_invitation.html rename to apps/api/templates/emails/invitations/workspace_invitation.html diff --git a/apiserver/templates/emails/notifications/issue-updates.html b/apps/api/templates/emails/notifications/issue-updates.html similarity index 100% rename from apiserver/templates/emails/notifications/issue-updates.html rename to apps/api/templates/emails/notifications/issue-updates.html diff --git a/apiserver/templates/emails/notifications/project_addition.html b/apps/api/templates/emails/notifications/project_addition.html similarity index 100% rename from apiserver/templates/emails/notifications/project_addition.html rename to apps/api/templates/emails/notifications/project_addition.html diff --git a/apiserver/templates/emails/notifications/webhook-deactivate.html b/apps/api/templates/emails/notifications/webhook-deactivate.html similarity index 100% rename from apiserver/templates/emails/notifications/webhook-deactivate.html rename to apps/api/templates/emails/notifications/webhook-deactivate.html diff --git a/apiserver/templates/emails/test_email.html b/apps/api/templates/emails/test_email.html similarity index 100% rename from apiserver/templates/emails/test_email.html rename to apps/api/templates/emails/test_email.html diff --git a/apiserver/templates/emails/user/user_activation.html b/apps/api/templates/emails/user/user_activation.html similarity index 100% rename from apiserver/templates/emails/user/user_activation.html rename to apps/api/templates/emails/user/user_activation.html diff --git a/apiserver/templates/emails/user/user_deactivation.html b/apps/api/templates/emails/user/user_deactivation.html similarity index 100% rename from apiserver/templates/emails/user/user_deactivation.html rename to apps/api/templates/emails/user/user_deactivation.html diff --git a/live/.env.example b/apps/live/.env.example similarity index 97% rename from live/.env.example rename to apps/live/.env.example index 064258253..5fc90d75f 100644 --- a/live/.env.example +++ b/apps/live/.env.example @@ -1,3 +1,4 @@ +PORT=3100 API_BASE_URL="http://localhost:8000" WEB_BASE_URL="http://localhost:3000" diff --git a/live/.eslintignore b/apps/live/.eslintignore similarity index 100% rename from live/.eslintignore rename to apps/live/.eslintignore diff --git a/apps/live/.eslintrc.json b/apps/live/.eslintrc.json new file mode 100644 index 000000000..db20d9097 --- /dev/null +++ b/apps/live/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "root": true, + "extends": ["@plane/eslint-config/server.js"], + "parser": "@typescript-eslint/parser" +} diff --git a/live/.prettierignore b/apps/live/.prettierignore similarity index 100% rename from live/.prettierignore rename to apps/live/.prettierignore diff --git a/live/.prettierrc b/apps/live/.prettierrc similarity index 100% rename from live/.prettierrc rename to apps/live/.prettierrc diff --git a/live/Dockerfile.dev b/apps/live/Dockerfile.dev similarity index 73% rename from live/Dockerfile.dev rename to apps/live/Dockerfile.dev index d893194ca..4d251ee9a 100644 --- a/live/Dockerfile.dev +++ b/apps/live/Dockerfile.dev @@ -1,6 +1,6 @@ -FROM node:20-alpine +FROM node:22-alpine + RUN apk add --no-cache libc6-compat -# Set working directory WORKDIR /app COPY . . @@ -8,7 +8,7 @@ RUN yarn global add turbo RUN yarn install EXPOSE 3003 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV TURBO_TELEMETRY_DISABLED=1 VOLUME [ "/app/node_modules", "/app/live/node_modules"] diff --git a/apps/live/Dockerfile.live b/apps/live/Dockerfile.live new file mode 100644 index 000000000..c3455fdce --- /dev/null +++ b/apps/live/Dockerfile.live @@ -0,0 +1,54 @@ +FROM node:22-alpine AS base + +# ***************************************************************************** +# STAGE 1: Prune the project +# ***************************************************************************** +FROM base AS builder +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk update +RUN apk add --no-cache libc6-compat +# Set working directory +WORKDIR /app +RUN yarn global add turbo +COPY . . +RUN turbo prune live --docker + +# ***************************************************************************** +# STAGE 2: Install dependencies & build the project +# ***************************************************************************** +# Add lockfile and package.json's of isolated subworkspace +FROM base AS installer +RUN apk update +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# First install dependencies (as they change less often) +COPY .gitignore .gitignore +COPY --from=builder /app/out/json/ . +COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn install + +# Build the project and its dependencies +COPY --from=builder /app/out/full/ . +COPY turbo.json turbo.json + +ENV TURBO_TELEMETRY_DISABLED=1 + +RUN yarn turbo build --filter=live + +# ***************************************************************************** +# STAGE 3: Run the project +# ***************************************************************************** + +FROM base AS runner +WORKDIR /app + +COPY --from=installer /app/packages ./packages +COPY --from=installer /app/apps/live/dist ./live +COPY --from=installer /app/node_modules ./node_modules + +ENV TURBO_TELEMETRY_DISABLED=1 + +EXPOSE 3000 + +CMD ["node", "live/server.js"] \ No newline at end of file diff --git a/live/package.json b/apps/live/package.json similarity index 58% rename from live/package.json rename to apps/live/package.json index 031310165..7593ed118 100644 --- a/live/package.json +++ b/apps/live/package.json @@ -1,17 +1,21 @@ { "name": "live", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "A realtime collaborative server powers Plane's rich text editor", "main": "./src/server.ts", "private": true, "type": "module", "scripts": { - "dev": "PORT=3100 concurrently \"babel src --out-dir dist --extensions '.ts,.js' --watch\" \"nodemon dist/server.js\"", - "build": "babel src --out-dir dist --extensions \".ts,.js\"", - "start": "node dist/server.js", - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "dev": "tsup --watch --onSuccess 'node --env-file=.env dist/server.js'", + "build": "tsc --noEmit && tsup", + "start": "node --env-file=.env dist/server.js", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "keywords": [], "author": "", @@ -20,13 +24,12 @@ "@hocuspocus/extension-logger": "^2.15.0", "@hocuspocus/extension-redis": "^2.15.0", "@hocuspocus/server": "^2.15.0", - "@plane/constants": "*", "@plane/editor": "*", "@plane/types": "*", - "@tiptap/core": "2.10.4", - "@tiptap/html": "2.11.0", - "axios": "^1.8.3", - "compression": "^1.7.4", + "@tiptap/core": "^2.22.3", + "@tiptap/html": "^2.22.3", + "axios": "1.11.0", + "compression": "1.8.1", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.2", @@ -34,7 +37,7 @@ "helmet": "^7.1.0", "ioredis": "^5.4.1", "lodash": "^4.17.21", - "morgan": "^1.10.0", + "morgan": "1.10.1", "pino-http": "^10.3.0", "pino-pretty": "^11.2.2", "uuid": "^10.0.0", @@ -43,17 +46,15 @@ "yjs": "^13.6.20" }, "devDependencies": { - "@babel/cli": "^7.25.6", - "@babel/core": "^7.25.2", - "@babel/preset-env": "^7.25.4", - "@babel/preset-typescript": "^7.24.7", - "@types/compression": "^1.7.5", + "@plane/eslint-config": "*", + "@plane/typescript-config": "*", + "@types/compression": "1.8.1", "@types/cors": "^2.8.17", "@types/dotenv": "^8.2.0", "@types/express": "^4.17.21", "@types/express-ws": "^3.0.4", "@types/node": "^20.14.9", - "babel-plugin-module-resolver": "^5.0.2", + "@types/pino-http": "^5.8.4", "concurrently": "^9.0.1", "nodemon": "^3.1.7", "ts-node": "^10.9.2", diff --git a/live/src/ce/lib/fetch-document.ts b/apps/live/src/ce/lib/fetch-document.ts similarity index 98% rename from live/src/ce/lib/fetch-document.ts rename to apps/live/src/ce/lib/fetch-document.ts index 5a27c2179..f7b4d8ea6 100644 --- a/live/src/ce/lib/fetch-document.ts +++ b/apps/live/src/ce/lib/fetch-document.ts @@ -6,9 +6,9 @@ type TArgs = { documentType: TDocumentTypes | undefined; pageId: string; params: URLSearchParams; -} +}; export const fetchDocument = async (args: TArgs): Promise => { const { documentType } = args; throw Error(`Fetch failed: Invalid document type ${documentType} provided.`); -} \ No newline at end of file +}; diff --git a/live/src/ce/lib/update-document.ts b/apps/live/src/ce/lib/update-document.ts similarity index 98% rename from live/src/ce/lib/update-document.ts rename to apps/live/src/ce/lib/update-document.ts index b998e154f..cbef54e74 100644 --- a/live/src/ce/lib/update-document.ts +++ b/apps/live/src/ce/lib/update-document.ts @@ -7,9 +7,9 @@ type TArgs = { pageId: string; params: URLSearchParams; updatedDescription: Uint8Array; -} +}; export const updateDocument = async (args: TArgs): Promise => { const { documentType } = args; throw Error(`Update failed: Invalid document type ${documentType} provided.`); -} \ No newline at end of file +}; diff --git a/live/src/ce/types/common.d.ts b/apps/live/src/ce/types/common.d.ts similarity index 100% rename from live/src/ce/types/common.d.ts rename to apps/live/src/ce/types/common.d.ts diff --git a/live/src/core/extensions/index.ts b/apps/live/src/core/extensions/index.ts similarity index 81% rename from live/src/core/extensions/index.ts rename to apps/live/src/core/extensions/index.ts index 4867cad3d..7364169a4 100644 --- a/live/src/core/extensions/index.ts +++ b/apps/live/src/core/extensions/index.ts @@ -9,18 +9,12 @@ import { Redis as HocusPocusRedis } from "@hocuspocus/extension-redis"; import { manualLogger } from "@/core/helpers/logger.js"; import { getRedisUrl } from "@/core/lib/utils/redis-url.js"; // core libraries -import { - fetchPageDescriptionBinary, - updatePageDescription, -} from "@/core/lib/page.js"; +import { fetchPageDescriptionBinary, updatePageDescription } from "@/core/lib/page.js"; // plane live libraries import { fetchDocument } from "@/plane-live/lib/fetch-document.js"; import { updateDocument } from "@/plane-live/lib/update-document.js"; // types -import { - type HocusPocusServerContext, - type TDocumentTypes, -} from "@/core/types/common.js"; +import { type HocusPocusServerContext, type TDocumentTypes } from "@/core/types/common.js"; export const getExtensions: () => Promise = async () => { const extensions: Extension[] = [ @@ -35,20 +29,14 @@ export const getExtensions: () => Promise = async () => { const cookie = (context as HocusPocusServerContext).cookie; // query params const params = requestParameters; - const documentType = params.get("documentType")?.toString() as - | TDocumentTypes - | undefined; + const documentType = params.get("documentType")?.toString() as TDocumentTypes | undefined; // TODO: Fix this lint error. // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve) => { try { let fetchedData = null; if (documentType === "project_page") { - fetchedData = await fetchPageDescriptionBinary( - params, - pageId, - cookie, - ); + fetchedData = await fetchPageDescriptionBinary(params, pageId, cookie); } else { fetchedData = await fetchDocument({ cookie, @@ -63,18 +51,11 @@ export const getExtensions: () => Promise = async () => { } }); }, - store: async ({ - context, - state, - documentName: pageId, - requestParameters, - }) => { + store: async ({ context, state, documentName: pageId, requestParameters }) => { const cookie = (context as HocusPocusServerContext).cookie; // query params const params = requestParameters; - const documentType = params.get("documentType")?.toString() as - | TDocumentTypes - | undefined; + const documentType = params.get("documentType")?.toString() as TDocumentTypes | undefined; // TODO: Fix this lint error. // eslint-disable-next-line no-async-promise-executor @@ -107,16 +88,12 @@ export const getExtensions: () => Promise = async () => { await new Promise((resolve, reject) => { redisClient.on("error", (error: any) => { - if ( - error?.code === "ENOTFOUND" || - error.message.includes("WRONGPASS") || - error.message.includes("NOAUTH") - ) { + if (error?.code === "ENOTFOUND" || error.message.includes("WRONGPASS") || error.message.includes("NOAUTH")) { redisClient.disconnect(); } manualLogger.warn( `Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`, - error, + error ); reject(error); }); @@ -130,12 +107,12 @@ export const getExtensions: () => Promise = async () => { } catch (error) { manualLogger.warn( `Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`, - error, + error ); } } else { manualLogger.warn( - "Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)", + "Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)" ); } diff --git a/live/src/core/helpers/convert-document.ts b/apps/live/src/core/helpers/convert-document.ts similarity index 100% rename from live/src/core/helpers/convert-document.ts rename to apps/live/src/core/helpers/convert-document.ts diff --git a/live/src/core/helpers/error-handler.ts b/apps/live/src/core/helpers/error-handler.ts similarity index 76% rename from live/src/core/helpers/error-handler.ts rename to apps/live/src/core/helpers/error-handler.ts index 6cc46b6dd..fac75f92f 100644 --- a/live/src/core/helpers/error-handler.ts +++ b/apps/live/src/core/helpers/error-handler.ts @@ -11,10 +11,7 @@ export const errorHandler: ErrorRequestHandler = (err, _req, res) => { // Send the response res.json({ error: { - message: - process.env.NODE_ENV === "production" - ? "An unexpected error occurred" - : err.message, + message: process.env.NODE_ENV === "production" ? "An unexpected error occurred" : err.message, ...(process.env.NODE_ENV !== "production" && { stack: err.stack }), }, }); diff --git a/live/src/core/helpers/logger.ts b/apps/live/src/core/helpers/logger.ts similarity index 90% rename from live/src/core/helpers/logger.ts rename to apps/live/src/core/helpers/logger.ts index cba3f7cd1..07efaea6e 100644 --- a/live/src/core/helpers/logger.ts +++ b/apps/live/src/core/helpers/logger.ts @@ -1,4 +1,5 @@ import { pinoHttp } from "pino-http"; +import { Logger } from "pino"; const transport = { target: "pino-pretty", @@ -35,4 +36,4 @@ export const logger = pinoHttp({ }, }); -export const manualLogger = logger.logger; +export const manualLogger: Logger = logger.logger; diff --git a/live/src/core/helpers/page.ts b/apps/live/src/core/helpers/page.ts similarity index 60% rename from live/src/core/helpers/page.ts rename to apps/live/src/core/helpers/page.ts index 4e79afe6b..d4322d1ad 100644 --- a/live/src/core/helpers/page.ts +++ b/apps/live/src/core/helpers/page.ts @@ -1,17 +1,16 @@ import { getSchema } from "@tiptap/core"; import { generateHTML, generateJSON } from "@tiptap/html"; import { prosemirrorJSONToYDoc, yXmlFragmentToProseMirrorRootNode } from "y-prosemirror"; -import * as Y from "yjs" +import * as Y from "yjs"; // plane editor import { CoreEditorExtensionsWithoutProps, DocumentEditorExtensionsWithoutProps } from "@plane/editor/lib"; -const DOCUMENT_EDITOR_EXTENSIONS = [ - ...CoreEditorExtensionsWithoutProps, - ...DocumentEditorExtensionsWithoutProps, -]; +const DOCUMENT_EDITOR_EXTENSIONS = [...CoreEditorExtensionsWithoutProps, ...DocumentEditorExtensionsWithoutProps]; const documentEditorSchema = getSchema(DOCUMENT_EDITOR_EXTENSIONS); -export const getAllDocumentFormatsFromBinaryData = (description: Uint8Array): { +export const getAllDocumentFormatsFromBinaryData = ( + description: Uint8Array +): { contentBinaryEncoded: string; contentJSON: object; contentHTML: string; @@ -22,10 +21,7 @@ export const getAllDocumentFormatsFromBinaryData = (description: Uint8Array): { Y.applyUpdate(yDoc, description); // convert to JSON const type = yDoc.getXmlFragment("default"); - const contentJSON = yXmlFragmentToProseMirrorRootNode( - type, - documentEditorSchema - ).toJSON(); + const contentJSON = yXmlFragmentToProseMirrorRootNode(type, documentEditorSchema).toJSON(); // convert to HTML const contentHTML = generateHTML(contentJSON, DOCUMENT_EDITOR_EXTENSIONS); @@ -34,26 +30,21 @@ export const getAllDocumentFormatsFromBinaryData = (description: Uint8Array): { contentJSON, contentHTML, }; -} +}; -export const getBinaryDataFromHTMLString = (descriptionHTML: string): { - contentBinary: Uint8Array +export const getBinaryDataFromHTMLString = ( + descriptionHTML: string +): { + contentBinary: Uint8Array; } => { // convert HTML to JSON - const contentJSON = generateJSON( - descriptionHTML ?? "

", - DOCUMENT_EDITOR_EXTENSIONS - ); + const contentJSON = generateJSON(descriptionHTML ?? "

", DOCUMENT_EDITOR_EXTENSIONS); // convert JSON to Y.Doc format - const transformedData = prosemirrorJSONToYDoc( - documentEditorSchema, - contentJSON, - "default" - ); + const transformedData = prosemirrorJSONToYDoc(documentEditorSchema, contentJSON, "default"); // convert Y.Doc to Uint8Array format const encodedData = Y.encodeStateAsUpdate(transformedData); return { - contentBinary: encodedData - } -} \ No newline at end of file + contentBinary: encodedData, + }; +}; diff --git a/live/src/core/hocuspocus-server.ts b/apps/live/src/core/hocuspocus-server.ts similarity index 91% rename from live/src/core/hocuspocus-server.ts rename to apps/live/src/core/hocuspocus-server.ts index 51896c23b..072d45cbc 100644 --- a/live/src/core/hocuspocus-server.ts +++ b/apps/live/src/core/hocuspocus-server.ts @@ -4,10 +4,7 @@ import { v4 as uuidv4 } from "uuid"; import { handleAuthentication } from "@/core/lib/authentication.js"; // extensions import { getExtensions } from "@/core/extensions/index.js"; -import { - DocumentCollaborativeEvents, - TDocumentEventsServer, -} from "@plane/editor/lib"; +import { DocumentCollaborativeEvents, TDocumentEventsServer } from "@plane/editor/lib"; // editor types import { TUserDetails } from "@plane/editor"; // types @@ -61,8 +58,7 @@ export const getHocusPocusServer = async () => { }, async onStateless({ payload, document }) { // broadcast the client event (derived from the server event) to all the clients so that they can update their state - const response = - DocumentCollaborativeEvents[payload as TDocumentEventsServer].client; + const response = DocumentCollaborativeEvents[payload as TDocumentEventsServer].client; if (response) { document.broadcastStateless(response); } diff --git a/live/src/core/lib/authentication.ts b/apps/live/src/core/lib/authentication.ts similarity index 100% rename from live/src/core/lib/authentication.ts rename to apps/live/src/core/lib/authentication.ts diff --git a/live/src/core/lib/page.ts b/apps/live/src/core/lib/page.ts similarity index 57% rename from live/src/core/lib/page.ts rename to apps/live/src/core/lib/page.ts index c2110a2b8..7d23d8b19 100644 --- a/live/src/core/lib/page.ts +++ b/apps/live/src/core/lib/page.ts @@ -1,8 +1,5 @@ // helpers -import { - getAllDocumentFormatsFromBinaryData, - getBinaryDataFromHTMLString, -} from "@/core/helpers/page.js"; +import { getAllDocumentFormatsFromBinaryData, getBinaryDataFromHTMLString } from "@/core/helpers/page.js"; // services import { PageService } from "@/core/services/page.service.js"; import { manualLogger } from "../helpers/logger.js"; @@ -12,20 +9,17 @@ export const updatePageDescription = async ( params: URLSearchParams, pageId: string, updatedDescription: Uint8Array, - cookie: string | undefined, + cookie: string | undefined ) => { if (!(updatedDescription instanceof Uint8Array)) { - throw new Error( - "Invalid updatedDescription: must be an instance of Uint8Array", - ); + throw new Error("Invalid updatedDescription: must be an instance of Uint8Array"); } const workspaceSlug = params.get("workspaceSlug")?.toString(); const projectId = params.get("projectId")?.toString(); if (!workspaceSlug || !projectId || !cookie) return; - const { contentBinaryEncoded, contentHTML, contentJSON } = - getAllDocumentFormatsFromBinaryData(updatedDescription); + const { contentBinaryEncoded, contentHTML, contentJSON } = getAllDocumentFormatsFromBinaryData(updatedDescription); try { const payload = { description_binary: contentBinaryEncoded, @@ -33,13 +27,7 @@ export const updatePageDescription = async ( description: contentJSON, }; - await pageService.updateDescription( - workspaceSlug, - projectId, - pageId, - payload, - cookie, - ); + await pageService.updateDescription(workspaceSlug, projectId, pageId, payload, cookie); } catch (error) { manualLogger.error("Update error:", error); throw error; @@ -50,26 +38,16 @@ const fetchDescriptionHTMLAndTransform = async ( workspaceSlug: string, projectId: string, pageId: string, - cookie: string, + cookie: string ) => { if (!workspaceSlug || !projectId || !cookie) return; try { - const pageDetails = await pageService.fetchDetails( - workspaceSlug, - projectId, - pageId, - cookie, - ); - const { contentBinary } = getBinaryDataFromHTMLString( - pageDetails.description_html ?? "

", - ); + const pageDetails = await pageService.fetchDetails(workspaceSlug, projectId, pageId, cookie); + const { contentBinary } = getBinaryDataFromHTMLString(pageDetails.description_html ?? "

"); return contentBinary; } catch (error) { - manualLogger.error( - "Error while transforming from HTML to Uint8Array", - error, - ); + manualLogger.error("Error while transforming from HTML to Uint8Array", error); throw error; } }; @@ -77,28 +55,18 @@ const fetchDescriptionHTMLAndTransform = async ( export const fetchPageDescriptionBinary = async ( params: URLSearchParams, pageId: string, - cookie: string | undefined, + cookie: string | undefined ) => { const workspaceSlug = params.get("workspaceSlug")?.toString(); const projectId = params.get("projectId")?.toString(); if (!workspaceSlug || !projectId || !cookie) return null; try { - const response = await pageService.fetchDescriptionBinary( - workspaceSlug, - projectId, - pageId, - cookie, - ); + const response = await pageService.fetchDescriptionBinary(workspaceSlug, projectId, pageId, cookie); const binaryData = new Uint8Array(response); if (binaryData.byteLength === 0) { - const binary = await fetchDescriptionHTMLAndTransform( - workspaceSlug, - projectId, - pageId, - cookie, - ); + const binary = await fetchDescriptionHTMLAndTransform(workspaceSlug, projectId, pageId, cookie); if (binary) { return binary; } diff --git a/live/src/core/lib/utils/redis-url.ts b/apps/live/src/core/lib/utils/redis-url.ts similarity index 100% rename from live/src/core/lib/utils/redis-url.ts rename to apps/live/src/core/lib/utils/redis-url.ts diff --git a/live/src/core/services/api.service.ts b/apps/live/src/core/services/api.service.ts similarity index 100% rename from live/src/core/services/api.service.ts rename to apps/live/src/core/services/api.service.ts diff --git a/apps/live/src/core/services/page.service.ts b/apps/live/src/core/services/page.service.ts new file mode 100644 index 000000000..9c1ed8237 --- /dev/null +++ b/apps/live/src/core/services/page.service.ts @@ -0,0 +1,58 @@ +// types +import { TPage } from "@plane/types"; +// services +import { API_BASE_URL, APIService } from "@/core/services/api.service.js"; + +export class PageService extends APIService { + constructor() { + super(API_BASE_URL); + } + + async fetchDetails(workspaceSlug: string, projectId: string, pageId: string, cookie: string): Promise { + return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`, { + headers: { + Cookie: cookie, + }, + }) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + + async fetchDescriptionBinary(workspaceSlug: string, projectId: string, pageId: string, cookie: string): Promise { + return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/description/`, { + headers: { + "Content-Type": "application/octet-stream", + Cookie: cookie, + }, + responseType: "arraybuffer", + }) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + + async updateDescription( + workspaceSlug: string, + projectId: string, + pageId: string, + data: { + description_binary: string; + description_html: string; + description: object; + }, + cookie: string + ): Promise { + return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/description/`, data, { + headers: { + Cookie: cookie, + }, + }) + .then((response) => response?.data) + .catch((error) => { + throw error; + }); + } +} diff --git a/live/src/core/services/user.service.ts b/apps/live/src/core/services/user.service.ts similarity index 100% rename from live/src/core/services/user.service.ts rename to apps/live/src/core/services/user.service.ts diff --git a/live/src/core/types/common.d.ts b/apps/live/src/core/types/common.d.ts similarity index 100% rename from live/src/core/types/common.d.ts rename to apps/live/src/core/types/common.d.ts diff --git a/apps/live/src/ee/lib/fetch-document.ts b/apps/live/src/ee/lib/fetch-document.ts new file mode 100644 index 000000000..33aa90bba --- /dev/null +++ b/apps/live/src/ee/lib/fetch-document.ts @@ -0,0 +1 @@ +export * from "../../ce/lib/fetch-document.js"; diff --git a/apps/live/src/ee/lib/update-document.ts b/apps/live/src/ee/lib/update-document.ts new file mode 100644 index 000000000..0f9c964e7 --- /dev/null +++ b/apps/live/src/ee/lib/update-document.ts @@ -0,0 +1 @@ +export * from "../../ce/lib/update-document.js"; diff --git a/apps/live/src/ee/types/common.d.ts b/apps/live/src/ee/types/common.d.ts new file mode 100644 index 000000000..4f11c54d0 --- /dev/null +++ b/apps/live/src/ee/types/common.d.ts @@ -0,0 +1 @@ +export * from "../../ce/types/common.js"; diff --git a/apps/live/src/server.ts b/apps/live/src/server.ts new file mode 100644 index 000000000..c4a353538 --- /dev/null +++ b/apps/live/src/server.ts @@ -0,0 +1,131 @@ +import compression from "compression"; +import cors from "cors"; +import expressWs from "express-ws"; +import express, { Request, Response } from "express"; +import helmet from "helmet"; +// hocuspocus server +import { getHocusPocusServer } from "@/core/hocuspocus-server.js"; +// helpers +import { convertHTMLDocumentToAllFormats } from "@/core/helpers/convert-document.js"; +import { logger, manualLogger } from "@/core/helpers/logger.js"; +// types +import { TConvertDocumentRequestBody } from "@/core/types/common.js"; + +export class Server { + private app: any; + private router: any; + private hocuspocusServer: any; + private serverInstance: any; + + constructor() { + this.app = express(); + this.router = express.Router(); + expressWs(this.app); + this.app.set("port", process.env.PORT || 3000); + this.setupMiddleware(); + this.setupHocusPocus(); + this.setupRoutes(); + } + + private setupMiddleware() { + // Security middleware + this.app.use(helmet()); + // Middleware for response compression + this.app.use(compression({ level: 6, threshold: 5 * 1000 })); + // Logging middleware + this.app.use(logger); + // Body parsing middleware + this.app.use(express.json()); + this.app.use(express.urlencoded({ extended: true })); + // cors middleware + this.app.use(cors()); + this.app.use(process.env.LIVE_BASE_PATH || "/live", this.router); + } + + private async setupHocusPocus() { + this.hocuspocusServer = await getHocusPocusServer().catch((err) => { + manualLogger.error("Failed to initialize HocusPocusServer:", err); + process.exit(1); + }); + } + + private setupRoutes() { + this.router.get("/health", (_req: Request, res: Response) => { + res.status(200).json({ status: "OK" }); + }); + + this.router.ws("/collaboration", (ws: any, req: Request) => { + try { + this.hocuspocusServer.handleConnection(ws, req); + } catch (err) { + manualLogger.error("WebSocket connection error:", err); + ws.close(); + } + }); + + this.router.post("/convert-document", (req: Request, res: Response) => { + const { description_html, variant } = req.body as TConvertDocumentRequestBody; + try { + if (description_html === undefined || variant === undefined) { + res.status(400).send({ + message: "Missing required fields", + }); + return; + } + const { description, description_binary } = convertHTMLDocumentToAllFormats({ + document_html: description_html, + variant, + }); + res.status(200).json({ + description, + description_binary, + }); + } catch (error) { + manualLogger.error("Error in /convert-document endpoint:", error); + res.status(500).json({ + message: `Internal server error.`, + }); + } + }); + + this.app.use((_req: Request, res: Response) => { + res.status(404).json({ + message: "Not Found", + }); + }); + } + + public listen() { + this.serverInstance = this.app.listen(this.app.get("port"), () => { + manualLogger.info(`Plane Live server has started at port ${this.app.get("port")}`); + }); + } + + public async destroy() { + // Close the HocusPocus server WebSocket connections + await this.hocuspocusServer.destroy(); + manualLogger.info("HocusPocus server WebSocket connections closed gracefully."); + // Close the Express server + this.serverInstance.close(() => { + manualLogger.info("Express server closed gracefully."); + process.exit(1); + }); + } +} + +const server = new Server(); +server.listen(); + +// Graceful shutdown on unhandled rejection +process.on("unhandledRejection", async (err: any) => { + manualLogger.info("Unhandled Rejection: ", err); + manualLogger.info(`UNHANDLED REJECTION! 💥 Shutting down...`); + await server.destroy(); +}); + +// Graceful shutdown on uncaught exception +process.on("uncaughtException", async (err: any) => { + manualLogger.info("Uncaught Exception: ", err); + manualLogger.info(`UNCAUGHT EXCEPTION! 💥 Shutting down...`); + await server.destroy(); +}); diff --git a/live/tsconfig.json b/apps/live/tsconfig.json similarity index 76% rename from live/tsconfig.json rename to apps/live/tsconfig.json index 622dc2232..810a68a5c 100644 --- a/live/tsconfig.json +++ b/apps/live/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "@plane/typescript-config/base.json", "compilerOptions": { - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "ES2015", + "moduleResolution": "Bundler", "lib": ["ES2015"], + "target": "ES2015", "outDir": "./dist", "rootDir": ".", "baseUrl": ".", @@ -16,6 +17,8 @@ "skipLibCheck": true, "sourceMap": true, "inlineSources": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "sourceRoot": "/" }, "include": ["src/**/*.ts", "tsup.config.ts"], diff --git a/apps/live/tsup.config.ts b/apps/live/tsup.config.ts new file mode 100644 index 000000000..05fbe7e86 --- /dev/null +++ b/apps/live/tsup.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/server.ts"], + format: ["esm", "cjs"], + dts: true, + splitting: false, + sourcemap: true, + minify: false, + target: "node18", + outDir: "dist", + env: { + NODE_ENV: process.env.NODE_ENV || "development", + }, +}); diff --git a/apps/proxy/Caddyfile.ce b/apps/proxy/Caddyfile.ce new file mode 100644 index 000000000..7f8fc79f7 --- /dev/null +++ b/apps/proxy/Caddyfile.ce @@ -0,0 +1,34 @@ +(plane_proxy) { + request_body { + max_size {$FILE_SIZE_LIMIT} + } + + reverse_proxy /spaces/* space:3000 + + reverse_proxy /god-mode/* admin:3000 + + reverse_proxy /live/* live:3000 + + reverse_proxy /api/* api:8000 + + reverse_proxy /auth/* api:8000 + + reverse_proxy /{$BUCKET_NAME}/* plane-minio:9000 + + reverse_proxy /* web:3000 +} + +{ + {$CERT_EMAIL} + acme_ca {$CERT_ACME_CA:https://acme-v02.api.letsencrypt.org/directory} + {$CERT_ACME_DNS} + servers { + max_header_size 25MB + client_ip_headers X-Forwarded-For X-Real-IP + trusted_proxies static {$TRUSTED_PROXIES:0.0.0.0/0} + } +} + +{$SITE_ADDRESS} { + import plane_proxy +} \ No newline at end of file diff --git a/apps/proxy/Dockerfile.ce b/apps/proxy/Dockerfile.ce new file mode 100644 index 000000000..4d2f6dd0a --- /dev/null +++ b/apps/proxy/Dockerfile.ce @@ -0,0 +1,14 @@ +FROM caddy:2.10.0-builder-alpine AS caddy-builder + +RUN xcaddy build \ + --with github.com/caddy-dns/cloudflare@v0.2.1 \ + --with github.com/caddy-dns/digitalocean@04bde2867106aa1b44c2f9da41a285fa02e629c5 \ + --with github.com/mholt/caddy-l4@4d3c80e89c5f80438a3e048a410d5543ff5fb9f4 + +FROM caddy:2.10.0-builder-alpine + +RUN apk add --no-cache nss-tools bash curl + +COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy + +COPY Caddyfile.ce /etc/caddy/Caddyfile \ No newline at end of file diff --git a/space/.env.example b/apps/space/.env.example similarity index 100% rename from space/.env.example rename to apps/space/.env.example diff --git a/space/.eslintrc.js b/apps/space/.eslintrc.js similarity index 100% rename from space/.eslintrc.js rename to apps/space/.eslintrc.js diff --git a/space/.gitignore b/apps/space/.gitignore similarity index 100% rename from space/.gitignore rename to apps/space/.gitignore diff --git a/space/.prettierignore b/apps/space/.prettierignore similarity index 100% rename from space/.prettierignore rename to apps/space/.prettierignore diff --git a/space/.prettierrc.json b/apps/space/.prettierrc.json similarity index 100% rename from space/.prettierrc.json rename to apps/space/.prettierrc.json diff --git a/space/Dockerfile.dev b/apps/space/Dockerfile.dev similarity index 93% rename from space/Dockerfile.dev rename to apps/space/Dockerfile.dev index b7e42dab8..f735e0d84 100644 --- a/space/Dockerfile.dev +++ b/apps/space/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM node:20-alpine +FROM node:22-alpine RUN apk add --no-cache libc6-compat # Set working directory WORKDIR /app diff --git a/space/Dockerfile.space b/apps/space/Dockerfile.space similarity index 78% rename from space/Dockerfile.space rename to apps/space/Dockerfile.space index ecb3fbec7..525d72f7b 100644 --- a/space/Dockerfile.space +++ b/apps/space/Dockerfile.space @@ -1,4 +1,5 @@ -FROM node:20-alpine as base +FROM node:22-alpine AS base + # ***************************************************************************** # STAGE 1: Build the project # ***************************************************************************** @@ -45,6 +46,9 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 + RUN yarn turbo run build --filter=space # ***************************************************************************** @@ -53,13 +57,16 @@ RUN yarn turbo run build --filter=space FROM base AS runner WORKDIR /app -COPY --from=installer /app/space/next.config.js . -COPY --from=installer /app/space/package.json . +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs +USER nextjs -COPY --from=installer /app/space/.next/standalone ./ - -COPY --from=installer /app/space/.next ./space/.next -COPY --from=installer /app/space/public ./space/public +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=installer /app/apps/space/.next/standalone ./ +COPY --from=installer /app/apps/space/.next/static ./apps/space/.next/static +COPY --from=installer /app/apps/space/public ./apps/space/public ARG NEXT_PUBLIC_API_BASE_URL="" ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL @@ -79,7 +86,9 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL -ENV NEXT_TELEMETRY_DISABLED 1 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 EXPOSE 3000 + +CMD ["node", "apps/space/server.js"] \ No newline at end of file diff --git a/space/README.md b/apps/space/README.md similarity index 100% rename from space/README.md rename to apps/space/README.md diff --git a/space/additional.d.ts b/apps/space/additional.d.ts similarity index 100% rename from space/additional.d.ts rename to apps/space/additional.d.ts diff --git a/space/app/[workspaceSlug]/[projectId]/page.ts b/apps/space/app/[workspaceSlug]/[projectId]/page.ts similarity index 100% rename from space/app/[workspaceSlug]/[projectId]/page.ts rename to apps/space/app/[workspaceSlug]/[projectId]/page.ts diff --git a/space/app/error.tsx b/apps/space/app/error.tsx similarity index 100% rename from space/app/error.tsx rename to apps/space/app/error.tsx diff --git a/space/app/issues/[anchor]/client-layout.tsx b/apps/space/app/issues/[anchor]/client-layout.tsx similarity index 100% rename from space/app/issues/[anchor]/client-layout.tsx rename to apps/space/app/issues/[anchor]/client-layout.tsx diff --git a/space/app/issues/[anchor]/layout.tsx b/apps/space/app/issues/[anchor]/layout.tsx similarity index 100% rename from space/app/issues/[anchor]/layout.tsx rename to apps/space/app/issues/[anchor]/layout.tsx diff --git a/space/app/issues/[anchor]/page.tsx b/apps/space/app/issues/[anchor]/page.tsx similarity index 100% rename from space/app/issues/[anchor]/page.tsx rename to apps/space/app/issues/[anchor]/page.tsx diff --git a/space/app/layout.tsx b/apps/space/app/layout.tsx similarity index 97% rename from space/app/layout.tsx rename to apps/space/app/layout.tsx index 96a192273..d0c7435da 100644 --- a/space/app/layout.tsx +++ b/apps/space/app/layout.tsx @@ -33,6 +33,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) +
<>{children} diff --git a/space/app/not-found.tsx b/apps/space/app/not-found.tsx similarity index 100% rename from space/app/not-found.tsx rename to apps/space/app/not-found.tsx diff --git a/space/app/page.tsx b/apps/space/app/page.tsx similarity index 100% rename from space/app/page.tsx rename to apps/space/app/page.tsx diff --git a/space/app/provider.tsx b/apps/space/app/provider.tsx similarity index 100% rename from space/app/provider.tsx rename to apps/space/app/provider.tsx diff --git a/space/app/views/[anchor]/layout.tsx b/apps/space/app/views/[anchor]/layout.tsx similarity index 100% rename from space/app/views/[anchor]/layout.tsx rename to apps/space/app/views/[anchor]/layout.tsx diff --git a/space/app/views/[anchor]/page.tsx b/apps/space/app/views/[anchor]/page.tsx similarity index 100% rename from space/app/views/[anchor]/page.tsx rename to apps/space/app/views/[anchor]/page.tsx diff --git a/space/ce/components/editor/embeds/index.ts b/apps/space/ce/components/editor/embeds/index.ts similarity index 100% rename from space/ce/components/editor/embeds/index.ts rename to apps/space/ce/components/editor/embeds/index.ts diff --git a/space/ce/components/editor/embeds/mentions/index.ts b/apps/space/ce/components/editor/embeds/mentions/index.ts similarity index 100% rename from space/ce/components/editor/embeds/mentions/index.ts rename to apps/space/ce/components/editor/embeds/mentions/index.ts diff --git a/space/ce/components/editor/embeds/mentions/root.tsx b/apps/space/ce/components/editor/embeds/mentions/root.tsx similarity index 100% rename from space/ce/components/editor/embeds/mentions/root.tsx rename to apps/space/ce/components/editor/embeds/mentions/root.tsx diff --git a/space/ce/components/editor/index.ts b/apps/space/ce/components/editor/index.ts similarity index 100% rename from space/ce/components/editor/index.ts rename to apps/space/ce/components/editor/index.ts diff --git a/space/ce/components/issue-layouts/root.tsx b/apps/space/ce/components/issue-layouts/root.tsx similarity index 100% rename from space/ce/components/issue-layouts/root.tsx rename to apps/space/ce/components/issue-layouts/root.tsx diff --git a/space/ce/components/navbar/index.tsx b/apps/space/ce/components/navbar/index.tsx similarity index 100% rename from space/ce/components/navbar/index.tsx rename to apps/space/ce/components/navbar/index.tsx diff --git a/space/ce/hooks/store/index.ts b/apps/space/ce/hooks/store/index.ts similarity index 100% rename from space/ce/hooks/store/index.ts rename to apps/space/ce/hooks/store/index.ts diff --git a/space/ce/hooks/store/use-published-view.ts b/apps/space/ce/hooks/store/use-published-view.ts similarity index 100% rename from space/ce/hooks/store/use-published-view.ts rename to apps/space/ce/hooks/store/use-published-view.ts diff --git a/space/ce/store/root.store.ts b/apps/space/ce/store/root.store.ts similarity index 100% rename from space/ce/store/root.store.ts rename to apps/space/ce/store/root.store.ts diff --git a/space/core/components/account/auth-forms/auth-banner.tsx b/apps/space/core/components/account/auth-forms/auth-banner.tsx similarity index 100% rename from space/core/components/account/auth-forms/auth-banner.tsx rename to apps/space/core/components/account/auth-forms/auth-banner.tsx diff --git a/space/core/components/account/auth-forms/auth-header.tsx b/apps/space/core/components/account/auth-forms/auth-header.tsx similarity index 100% rename from space/core/components/account/auth-forms/auth-header.tsx rename to apps/space/core/components/account/auth-forms/auth-header.tsx diff --git a/space/core/components/account/auth-forms/auth-root.tsx b/apps/space/core/components/account/auth-forms/auth-root.tsx similarity index 100% rename from space/core/components/account/auth-forms/auth-root.tsx rename to apps/space/core/components/account/auth-forms/auth-root.tsx diff --git a/space/core/components/account/auth-forms/email.tsx b/apps/space/core/components/account/auth-forms/email.tsx similarity index 100% rename from space/core/components/account/auth-forms/email.tsx rename to apps/space/core/components/account/auth-forms/email.tsx diff --git a/space/core/components/account/auth-forms/index.ts b/apps/space/core/components/account/auth-forms/index.ts similarity index 100% rename from space/core/components/account/auth-forms/index.ts rename to apps/space/core/components/account/auth-forms/index.ts diff --git a/space/core/components/account/auth-forms/password.tsx b/apps/space/core/components/account/auth-forms/password.tsx similarity index 100% rename from space/core/components/account/auth-forms/password.tsx rename to apps/space/core/components/account/auth-forms/password.tsx diff --git a/space/core/components/account/auth-forms/unique-code.tsx b/apps/space/core/components/account/auth-forms/unique-code.tsx similarity index 98% rename from space/core/components/account/auth-forms/unique-code.tsx rename to apps/space/core/components/account/auth-forms/unique-code.tsx index 750b52ccd..abf233a29 100644 --- a/space/core/components/account/auth-forms/unique-code.tsx +++ b/apps/space/core/components/account/auth-forms/unique-code.tsx @@ -34,8 +34,6 @@ const defaultValues: TUniqueCodeFormValues = { export const AuthUniqueCodeForm: React.FC = (props) => { const { mode, email, nextPath, handleEmailClear, generateEmailUniqueCode } = props; - // hooks - // const { captureEvent } = useEventTracker(); // derived values const defaultResetTimerValue = 5; // states diff --git a/space/core/components/account/helpers/index.ts b/apps/space/core/components/account/helpers/index.ts similarity index 100% rename from space/core/components/account/helpers/index.ts rename to apps/space/core/components/account/helpers/index.ts diff --git a/space/core/components/account/helpers/password-strength-meter.tsx b/apps/space/core/components/account/helpers/password-strength-meter.tsx similarity index 100% rename from space/core/components/account/helpers/password-strength-meter.tsx rename to apps/space/core/components/account/helpers/password-strength-meter.tsx diff --git a/space/core/components/account/index.ts b/apps/space/core/components/account/index.ts similarity index 100% rename from space/core/components/account/index.ts rename to apps/space/core/components/account/index.ts diff --git a/space/core/components/account/oauth/github-button.tsx b/apps/space/core/components/account/oauth/github-button.tsx similarity index 100% rename from space/core/components/account/oauth/github-button.tsx rename to apps/space/core/components/account/oauth/github-button.tsx diff --git a/space/core/components/account/oauth/gitlab-button.tsx b/apps/space/core/components/account/oauth/gitlab-button.tsx similarity index 100% rename from space/core/components/account/oauth/gitlab-button.tsx rename to apps/space/core/components/account/oauth/gitlab-button.tsx diff --git a/space/core/components/account/oauth/google-button.tsx b/apps/space/core/components/account/oauth/google-button.tsx similarity index 100% rename from space/core/components/account/oauth/google-button.tsx rename to apps/space/core/components/account/oauth/google-button.tsx diff --git a/space/core/components/account/oauth/index.ts b/apps/space/core/components/account/oauth/index.ts similarity index 100% rename from space/core/components/account/oauth/index.ts rename to apps/space/core/components/account/oauth/index.ts diff --git a/space/core/components/account/oauth/oauth-options.tsx b/apps/space/core/components/account/oauth/oauth-options.tsx similarity index 100% rename from space/core/components/account/oauth/oauth-options.tsx rename to apps/space/core/components/account/oauth/oauth-options.tsx diff --git a/space/core/components/account/terms-and-conditions.tsx b/apps/space/core/components/account/terms-and-conditions.tsx similarity index 100% rename from space/core/components/account/terms-and-conditions.tsx rename to apps/space/core/components/account/terms-and-conditions.tsx diff --git a/space/core/components/account/user-logged-in.tsx b/apps/space/core/components/account/user-logged-in.tsx similarity index 100% rename from space/core/components/account/user-logged-in.tsx rename to apps/space/core/components/account/user-logged-in.tsx diff --git a/space/core/components/common/index.ts b/apps/space/core/components/common/index.ts similarity index 100% rename from space/core/components/common/index.ts rename to apps/space/core/components/common/index.ts diff --git a/space/core/components/common/logo-spinner.tsx b/apps/space/core/components/common/logo-spinner.tsx similarity index 100% rename from space/core/components/common/logo-spinner.tsx rename to apps/space/core/components/common/logo-spinner.tsx diff --git a/space/core/components/common/powered-by.tsx b/apps/space/core/components/common/powered-by.tsx similarity index 100% rename from space/core/components/common/powered-by.tsx rename to apps/space/core/components/common/powered-by.tsx diff --git a/space/core/components/common/project-logo.tsx b/apps/space/core/components/common/project-logo.tsx similarity index 100% rename from space/core/components/common/project-logo.tsx rename to apps/space/core/components/common/project-logo.tsx diff --git a/space/core/components/editor/embeds/index.ts b/apps/space/core/components/editor/embeds/index.ts similarity index 100% rename from space/core/components/editor/embeds/index.ts rename to apps/space/core/components/editor/embeds/index.ts diff --git a/space/core/components/editor/embeds/mentions/index.ts b/apps/space/core/components/editor/embeds/mentions/index.ts similarity index 100% rename from space/core/components/editor/embeds/mentions/index.ts rename to apps/space/core/components/editor/embeds/mentions/index.ts diff --git a/space/core/components/editor/embeds/mentions/root.tsx b/apps/space/core/components/editor/embeds/mentions/root.tsx similarity index 100% rename from space/core/components/editor/embeds/mentions/root.tsx rename to apps/space/core/components/editor/embeds/mentions/root.tsx diff --git a/space/core/components/editor/embeds/mentions/user.tsx b/apps/space/core/components/editor/embeds/mentions/user.tsx similarity index 100% rename from space/core/components/editor/embeds/mentions/user.tsx rename to apps/space/core/components/editor/embeds/mentions/user.tsx diff --git a/space/core/components/editor/index.ts b/apps/space/core/components/editor/index.ts similarity index 74% rename from space/core/components/editor/index.ts rename to apps/space/core/components/editor/index.ts index 894daf224..de164c837 100644 --- a/space/core/components/editor/index.ts +++ b/apps/space/core/components/editor/index.ts @@ -1,5 +1,5 @@ export * from "./embeds"; export * from "./lite-text-editor"; export * from "./lite-text-read-only-editor"; -export * from "./rich-text-read-only-editor"; +export * from "./rich-text-editor"; export * from "./toolbar"; diff --git a/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx similarity index 100% rename from space/core/components/editor/lite-text-editor.tsx rename to apps/space/core/components/editor/lite-text-editor.tsx diff --git a/space/core/components/editor/lite-text-read-only-editor.tsx b/apps/space/core/components/editor/lite-text-read-only-editor.tsx similarity index 100% rename from space/core/components/editor/lite-text-read-only-editor.tsx rename to apps/space/core/components/editor/lite-text-read-only-editor.tsx diff --git a/space/core/components/editor/rich-text-editor.tsx b/apps/space/core/components/editor/rich-text-editor.tsx similarity index 72% rename from space/core/components/editor/rich-text-editor.tsx rename to apps/space/core/components/editor/rich-text-editor.tsx index 63320cd2c..7a9178f65 100644 --- a/space/core/components/editor/rich-text-editor.tsx +++ b/apps/space/core/components/editor/rich-text-editor.tsx @@ -9,18 +9,24 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper"; // store hooks import { useMember } from "@/hooks/store"; -interface RichTextEditorWrapperProps - extends MakeOptional< - Omit, - "disabledExtensions" | "flaggedExtensions" - > { +type RichTextEditorWrapperProps = MakeOptional< + Omit, + "disabledExtensions" | "flaggedExtensions" +> & { anchor: string; - uploadFile: TFileHandler["upload"]; workspaceId: string; -} +} & ( + | { + editable: false; + } + | { + editable: true; + uploadFile: TFileHandler["upload"]; + } + ); export const RichTextEditor = forwardRef((props, ref) => { - const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props; + const { anchor, containerClassName, editable, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props; const { getMemberById } = useMember(); return ( "", workspaceId, })} flaggedExtensions={flaggedExtensions ?? []} diff --git a/space/core/components/editor/toolbar.tsx b/apps/space/core/components/editor/toolbar.tsx similarity index 100% rename from space/core/components/editor/toolbar.tsx rename to apps/space/core/components/editor/toolbar.tsx diff --git a/space/core/components/instance/index.ts b/apps/space/core/components/instance/index.ts similarity index 100% rename from space/core/components/instance/index.ts rename to apps/space/core/components/instance/index.ts diff --git a/space/core/components/instance/instance-failure-view.tsx b/apps/space/core/components/instance/instance-failure-view.tsx similarity index 100% rename from space/core/components/instance/instance-failure-view.tsx rename to apps/space/core/components/instance/instance-failure-view.tsx diff --git a/space/core/components/issues/filters/applied-filters/filters-list.tsx b/apps/space/core/components/issues/filters/applied-filters/filters-list.tsx similarity index 100% rename from space/core/components/issues/filters/applied-filters/filters-list.tsx rename to apps/space/core/components/issues/filters/applied-filters/filters-list.tsx diff --git a/space/core/components/issues/filters/applied-filters/label.tsx b/apps/space/core/components/issues/filters/applied-filters/label.tsx similarity index 100% rename from space/core/components/issues/filters/applied-filters/label.tsx rename to apps/space/core/components/issues/filters/applied-filters/label.tsx diff --git a/space/core/components/issues/filters/applied-filters/priority.tsx b/apps/space/core/components/issues/filters/applied-filters/priority.tsx similarity index 100% rename from space/core/components/issues/filters/applied-filters/priority.tsx rename to apps/space/core/components/issues/filters/applied-filters/priority.tsx diff --git a/space/core/components/issues/filters/applied-filters/root.tsx b/apps/space/core/components/issues/filters/applied-filters/root.tsx similarity index 91% rename from space/core/components/issues/filters/applied-filters/root.tsx rename to apps/space/core/components/issues/filters/applied-filters/root.tsx index 6bed90076..af7be085d 100644 --- a/space/core/components/issues/filters/applied-filters/root.tsx +++ b/apps/space/core/components/issues/filters/applied-filters/root.tsx @@ -35,9 +35,9 @@ export const IssueAppliedFilters: FC = observer((props) => const updateRouteParams = useCallback( (key: keyof TIssueQueryFilters, value: string[]) => { - const state = key === "state" ? value : issueFilters?.filters?.state ?? []; - const priority = key === "priority" ? value : issueFilters?.filters?.priority ?? []; - const labels = key === "labels" ? value : issueFilters?.filters?.labels ?? []; + const state = key === "state" ? value : (issueFilters?.filters?.state ?? []); + const priority = key === "priority" ? value : (issueFilters?.filters?.priority ?? []); + const labels = key === "labels" ? value : (issueFilters?.filters?.labels ?? []); let params: any = { board: activeLayout || "list" }; if (priority.length > 0) params = { ...params, priority: priority.join(",") }; diff --git a/space/core/components/issues/filters/applied-filters/state.tsx b/apps/space/core/components/issues/filters/applied-filters/state.tsx similarity index 100% rename from space/core/components/issues/filters/applied-filters/state.tsx rename to apps/space/core/components/issues/filters/applied-filters/state.tsx diff --git a/space/core/components/issues/filters/helpers/dropdown.tsx b/apps/space/core/components/issues/filters/helpers/dropdown.tsx similarity index 100% rename from space/core/components/issues/filters/helpers/dropdown.tsx rename to apps/space/core/components/issues/filters/helpers/dropdown.tsx diff --git a/space/core/components/issues/filters/helpers/filter-header.tsx b/apps/space/core/components/issues/filters/helpers/filter-header.tsx similarity index 100% rename from space/core/components/issues/filters/helpers/filter-header.tsx rename to apps/space/core/components/issues/filters/helpers/filter-header.tsx diff --git a/space/core/components/issues/filters/helpers/filter-option.tsx b/apps/space/core/components/issues/filters/helpers/filter-option.tsx similarity index 100% rename from space/core/components/issues/filters/helpers/filter-option.tsx rename to apps/space/core/components/issues/filters/helpers/filter-option.tsx diff --git a/space/core/components/issues/filters/helpers/index.ts b/apps/space/core/components/issues/filters/helpers/index.ts similarity index 100% rename from space/core/components/issues/filters/helpers/index.ts rename to apps/space/core/components/issues/filters/helpers/index.ts diff --git a/space/core/components/issues/filters/index.ts b/apps/space/core/components/issues/filters/index.ts similarity index 100% rename from space/core/components/issues/filters/index.ts rename to apps/space/core/components/issues/filters/index.ts diff --git a/space/core/components/issues/filters/labels.tsx b/apps/space/core/components/issues/filters/labels.tsx similarity index 100% rename from space/core/components/issues/filters/labels.tsx rename to apps/space/core/components/issues/filters/labels.tsx diff --git a/space/core/components/issues/filters/priority.tsx b/apps/space/core/components/issues/filters/priority.tsx similarity index 100% rename from space/core/components/issues/filters/priority.tsx rename to apps/space/core/components/issues/filters/priority.tsx diff --git a/space/core/components/issues/filters/root.tsx b/apps/space/core/components/issues/filters/root.tsx similarity index 100% rename from space/core/components/issues/filters/root.tsx rename to apps/space/core/components/issues/filters/root.tsx diff --git a/space/core/components/issues/filters/selection.tsx b/apps/space/core/components/issues/filters/selection.tsx similarity index 100% rename from space/core/components/issues/filters/selection.tsx rename to apps/space/core/components/issues/filters/selection.tsx diff --git a/space/core/components/issues/filters/state.tsx b/apps/space/core/components/issues/filters/state.tsx similarity index 100% rename from space/core/components/issues/filters/state.tsx rename to apps/space/core/components/issues/filters/state.tsx diff --git a/space/core/components/issues/index.ts b/apps/space/core/components/issues/index.ts similarity index 100% rename from space/core/components/issues/index.ts rename to apps/space/core/components/issues/index.ts diff --git a/space/core/components/issues/issue-layouts/error.tsx b/apps/space/core/components/issues/issue-layouts/error.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/error.tsx rename to apps/space/core/components/issues/issue-layouts/error.tsx diff --git a/space/core/components/issues/issue-layouts/index.ts b/apps/space/core/components/issues/issue-layouts/index.ts similarity index 100% rename from space/core/components/issues/issue-layouts/index.ts rename to apps/space/core/components/issues/issue-layouts/index.ts diff --git a/space/core/components/issues/issue-layouts/issue-layout-HOC.tsx b/apps/space/core/components/issues/issue-layouts/issue-layout-HOC.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/issue-layout-HOC.tsx rename to apps/space/core/components/issues/issue-layouts/issue-layout-HOC.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx b/apps/space/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx b/apps/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/block-reactions.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/block.tsx b/apps/space/core/components/issues/issue-layouts/kanban/block.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/block.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/block.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/blocks-list.tsx b/apps/space/core/components/issues/issue-layouts/kanban/blocks-list.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/blocks-list.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/blocks-list.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/default.tsx b/apps/space/core/components/issues/issue-layouts/kanban/default.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/default.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/default.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx b/apps/space/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx b/apps/space/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx diff --git a/space/core/components/issues/issue-layouts/kanban/index.ts b/apps/space/core/components/issues/issue-layouts/kanban/index.ts similarity index 100% rename from space/core/components/issues/issue-layouts/kanban/index.ts rename to apps/space/core/components/issues/issue-layouts/kanban/index.ts diff --git a/space/core/components/issues/issue-layouts/kanban/kanban-group.tsx b/apps/space/core/components/issues/issue-layouts/kanban/kanban-group.tsx similarity index 96% rename from space/core/components/issues/issue-layouts/kanban/kanban-group.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/kanban-group.tsx index 50e6ba774..e6090a938 100644 --- a/space/core/components/issues/issue-layouts/kanban/kanban-group.tsx +++ b/apps/space/core/components/issues/issue-layouts/kanban/kanban-group.tsx @@ -76,8 +76,8 @@ export const KanbanGroup = observer((props: IKanbanGroup) => { const isSubGroup = !!subGroupId && subGroupId !== "null"; const issueIds = isSubGroup - ? (groupedIssueIds as TSubGroupedIssues)?.[groupId]?.[subGroupId] ?? [] - : (groupedIssueIds as TGroupedIssues)?.[groupId] ?? []; + ? ((groupedIssueIds as TSubGroupedIssues)?.[groupId]?.[subGroupId] ?? []) + : ((groupedIssueIds as TGroupedIssues)?.[groupId] ?? []); const groupIssueCount = getGroupIssueCount(groupId, subGroupId, false) ?? 0; const nextPageResults = getPaginationData(groupId, subGroupId)?.nextPageResults; diff --git a/space/core/components/issues/issue-layouts/kanban/swimlanes.tsx b/apps/space/core/components/issues/issue-layouts/kanban/swimlanes.tsx similarity index 98% rename from space/core/components/issues/issue-layouts/kanban/swimlanes.tsx rename to apps/space/core/components/issues/issue-layouts/kanban/swimlanes.tsx index 48dd4047c..8860e7395 100644 --- a/space/core/components/issues/issue-layouts/kanban/swimlanes.tsx +++ b/apps/space/core/components/issues/issue-layouts/kanban/swimlanes.tsx @@ -133,12 +133,7 @@ const SubGroupSwimlaneHeader: React.FC = observer( if (subGroupByVisibilityToggle === false) return <>; return (
- +
); })} diff --git a/space/core/components/issues/issue-layouts/list/base-list-root.tsx b/apps/space/core/components/issues/issue-layouts/list/base-list-root.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/base-list-root.tsx rename to apps/space/core/components/issues/issue-layouts/list/base-list-root.tsx diff --git a/space/core/components/issues/issue-layouts/list/block.tsx b/apps/space/core/components/issues/issue-layouts/list/block.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/block.tsx rename to apps/space/core/components/issues/issue-layouts/list/block.tsx diff --git a/space/core/components/issues/issue-layouts/list/blocks-list.tsx b/apps/space/core/components/issues/issue-layouts/list/blocks-list.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/blocks-list.tsx rename to apps/space/core/components/issues/issue-layouts/list/blocks-list.tsx diff --git a/space/core/components/issues/issue-layouts/list/default.tsx b/apps/space/core/components/issues/issue-layouts/list/default.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/default.tsx rename to apps/space/core/components/issues/issue-layouts/list/default.tsx diff --git a/space/core/components/issues/issue-layouts/list/headers/group-by-card.tsx b/apps/space/core/components/issues/issue-layouts/list/headers/group-by-card.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/headers/group-by-card.tsx rename to apps/space/core/components/issues/issue-layouts/list/headers/group-by-card.tsx diff --git a/space/core/components/issues/issue-layouts/list/index.ts b/apps/space/core/components/issues/issue-layouts/list/index.ts similarity index 100% rename from space/core/components/issues/issue-layouts/list/index.ts rename to apps/space/core/components/issues/issue-layouts/list/index.ts diff --git a/space/core/components/issues/issue-layouts/list/list-group.tsx b/apps/space/core/components/issues/issue-layouts/list/list-group.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/list/list-group.tsx rename to apps/space/core/components/issues/issue-layouts/list/list-group.tsx diff --git a/space/core/components/issues/issue-layouts/properties/all-properties.tsx b/apps/space/core/components/issues/issue-layouts/properties/all-properties.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/all-properties.tsx rename to apps/space/core/components/issues/issue-layouts/properties/all-properties.tsx diff --git a/space/core/components/issues/issue-layouts/properties/cycle.tsx b/apps/space/core/components/issues/issue-layouts/properties/cycle.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/cycle.tsx rename to apps/space/core/components/issues/issue-layouts/properties/cycle.tsx diff --git a/space/core/components/issues/issue-layouts/properties/due-date.tsx b/apps/space/core/components/issues/issue-layouts/properties/due-date.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/due-date.tsx rename to apps/space/core/components/issues/issue-layouts/properties/due-date.tsx diff --git a/space/core/components/issues/issue-layouts/properties/index.ts b/apps/space/core/components/issues/issue-layouts/properties/index.ts similarity index 100% rename from space/core/components/issues/issue-layouts/properties/index.ts rename to apps/space/core/components/issues/issue-layouts/properties/index.ts diff --git a/space/core/components/issues/issue-layouts/properties/labels.tsx b/apps/space/core/components/issues/issue-layouts/properties/labels.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/labels.tsx rename to apps/space/core/components/issues/issue-layouts/properties/labels.tsx diff --git a/space/core/components/issues/issue-layouts/properties/member.tsx b/apps/space/core/components/issues/issue-layouts/properties/member.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/member.tsx rename to apps/space/core/components/issues/issue-layouts/properties/member.tsx diff --git a/space/core/components/issues/issue-layouts/properties/modules.tsx b/apps/space/core/components/issues/issue-layouts/properties/modules.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/modules.tsx rename to apps/space/core/components/issues/issue-layouts/properties/modules.tsx diff --git a/space/core/components/issues/issue-layouts/properties/priority.tsx b/apps/space/core/components/issues/issue-layouts/properties/priority.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/priority.tsx rename to apps/space/core/components/issues/issue-layouts/properties/priority.tsx diff --git a/space/core/components/issues/issue-layouts/properties/state.tsx b/apps/space/core/components/issues/issue-layouts/properties/state.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/properties/state.tsx rename to apps/space/core/components/issues/issue-layouts/properties/state.tsx diff --git a/space/core/components/issues/issue-layouts/root.tsx b/apps/space/core/components/issues/issue-layouts/root.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/root.tsx rename to apps/space/core/components/issues/issue-layouts/root.tsx diff --git a/space/core/components/issues/issue-layouts/utils.tsx b/apps/space/core/components/issues/issue-layouts/utils.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/utils.tsx rename to apps/space/core/components/issues/issue-layouts/utils.tsx diff --git a/space/core/components/issues/issue-layouts/with-display-properties-HOC.tsx b/apps/space/core/components/issues/issue-layouts/with-display-properties-HOC.tsx similarity index 100% rename from space/core/components/issues/issue-layouts/with-display-properties-HOC.tsx rename to apps/space/core/components/issues/issue-layouts/with-display-properties-HOC.tsx diff --git a/space/core/components/issues/navbar/controls.tsx b/apps/space/core/components/issues/navbar/controls.tsx similarity index 100% rename from space/core/components/issues/navbar/controls.tsx rename to apps/space/core/components/issues/navbar/controls.tsx diff --git a/space/core/components/issues/navbar/index.ts b/apps/space/core/components/issues/navbar/index.ts similarity index 100% rename from space/core/components/issues/navbar/index.ts rename to apps/space/core/components/issues/navbar/index.ts diff --git a/space/core/components/issues/navbar/layout-icon.tsx b/apps/space/core/components/issues/navbar/layout-icon.tsx similarity index 100% rename from space/core/components/issues/navbar/layout-icon.tsx rename to apps/space/core/components/issues/navbar/layout-icon.tsx diff --git a/space/core/components/issues/navbar/layout-selection.tsx b/apps/space/core/components/issues/navbar/layout-selection.tsx similarity index 100% rename from space/core/components/issues/navbar/layout-selection.tsx rename to apps/space/core/components/issues/navbar/layout-selection.tsx diff --git a/space/core/components/issues/navbar/root.tsx b/apps/space/core/components/issues/navbar/root.tsx similarity index 100% rename from space/core/components/issues/navbar/root.tsx rename to apps/space/core/components/issues/navbar/root.tsx diff --git a/space/core/components/issues/navbar/theme.tsx b/apps/space/core/components/issues/navbar/theme.tsx similarity index 100% rename from space/core/components/issues/navbar/theme.tsx rename to apps/space/core/components/issues/navbar/theme.tsx diff --git a/space/core/components/issues/navbar/user-avatar.tsx b/apps/space/core/components/issues/navbar/user-avatar.tsx similarity index 100% rename from space/core/components/issues/navbar/user-avatar.tsx rename to apps/space/core/components/issues/navbar/user-avatar.tsx diff --git a/space/core/components/issues/peek-overview/comment/add-comment.tsx b/apps/space/core/components/issues/peek-overview/comment/add-comment.tsx similarity index 100% rename from space/core/components/issues/peek-overview/comment/add-comment.tsx rename to apps/space/core/components/issues/peek-overview/comment/add-comment.tsx diff --git a/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx b/apps/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx similarity index 100% rename from space/core/components/issues/peek-overview/comment/comment-detail-card.tsx rename to apps/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx diff --git a/space/core/components/issues/peek-overview/comment/comment-reactions.tsx b/apps/space/core/components/issues/peek-overview/comment/comment-reactions.tsx similarity index 100% rename from space/core/components/issues/peek-overview/comment/comment-reactions.tsx rename to apps/space/core/components/issues/peek-overview/comment/comment-reactions.tsx diff --git a/space/core/components/issues/peek-overview/comment/index.ts b/apps/space/core/components/issues/peek-overview/comment/index.ts similarity index 100% rename from space/core/components/issues/peek-overview/comment/index.ts rename to apps/space/core/components/issues/peek-overview/comment/index.ts diff --git a/space/core/components/issues/peek-overview/full-screen-peek-view.tsx b/apps/space/core/components/issues/peek-overview/full-screen-peek-view.tsx similarity index 100% rename from space/core/components/issues/peek-overview/full-screen-peek-view.tsx rename to apps/space/core/components/issues/peek-overview/full-screen-peek-view.tsx diff --git a/space/core/components/issues/peek-overview/header.tsx b/apps/space/core/components/issues/peek-overview/header.tsx similarity index 100% rename from space/core/components/issues/peek-overview/header.tsx rename to apps/space/core/components/issues/peek-overview/header.tsx diff --git a/space/core/components/issues/peek-overview/index.ts b/apps/space/core/components/issues/peek-overview/index.ts similarity index 100% rename from space/core/components/issues/peek-overview/index.ts rename to apps/space/core/components/issues/peek-overview/index.ts diff --git a/space/core/components/issues/peek-overview/issue-activity.tsx b/apps/space/core/components/issues/peek-overview/issue-activity.tsx similarity index 100% rename from space/core/components/issues/peek-overview/issue-activity.tsx rename to apps/space/core/components/issues/peek-overview/issue-activity.tsx diff --git a/space/core/components/issues/peek-overview/issue-details.tsx b/apps/space/core/components/issues/peek-overview/issue-details.tsx similarity index 92% rename from space/core/components/issues/peek-overview/issue-details.tsx rename to apps/space/core/components/issues/peek-overview/issue-details.tsx index 32bcbc9bd..ad79dfde6 100644 --- a/space/core/components/issues/peek-overview/issue-details.tsx +++ b/apps/space/core/components/issues/peek-overview/issue-details.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; // components -import { RichTextReadOnlyEditor } from "@/components/editor"; +import { RichTextEditor } from "@/components/editor"; import { IssueReactions } from "@/components/issues/peek-overview"; import { usePublish } from "@/hooks/store"; // types @@ -25,7 +25,8 @@ export const PeekOverviewIssueDetails: React.FC = observer((props) => {

{issueDetails.name}

{description !== "" && description !== "

" && ( - fetchCurrentUser(), { shouldRetryOnError: false, - revalidateOnFocus: false, - revalidateIfStale: false, + revalidateOnFocus: true, + revalidateIfStale: true, }); if (!instance && !error) diff --git a/space/core/lib/store-provider.tsx b/apps/space/core/lib/store-provider.tsx similarity index 100% rename from space/core/lib/store-provider.tsx rename to apps/space/core/lib/store-provider.tsx diff --git a/space/core/lib/toast-provider.tsx b/apps/space/core/lib/toast-provider.tsx similarity index 100% rename from space/core/lib/toast-provider.tsx rename to apps/space/core/lib/toast-provider.tsx diff --git a/space/core/store/cycle.store.ts b/apps/space/core/store/cycle.store.ts similarity index 100% rename from space/core/store/cycle.store.ts rename to apps/space/core/store/cycle.store.ts diff --git a/space/core/store/helpers/base-issues.store.ts b/apps/space/core/store/helpers/base-issues.store.ts similarity index 100% rename from space/core/store/helpers/base-issues.store.ts rename to apps/space/core/store/helpers/base-issues.store.ts diff --git a/space/core/store/helpers/filter.helpers.ts b/apps/space/core/store/helpers/filter.helpers.ts similarity index 100% rename from space/core/store/helpers/filter.helpers.ts rename to apps/space/core/store/helpers/filter.helpers.ts diff --git a/space/core/store/instance.store.ts b/apps/space/core/store/instance.store.ts similarity index 100% rename from space/core/store/instance.store.ts rename to apps/space/core/store/instance.store.ts diff --git a/space/core/store/issue-detail.store.ts b/apps/space/core/store/issue-detail.store.ts similarity index 99% rename from space/core/store/issue-detail.store.ts rename to apps/space/core/store/issue-detail.store.ts index 715836946..8eee2f8b5 100644 --- a/space/core/store/issue-detail.store.ts +++ b/apps/space/core/store/issue-detail.store.ts @@ -5,8 +5,7 @@ import { computedFn } from "mobx-utils"; import { v4 as uuidv4 } from "uuid"; // plane imports import { SitesFileService, SitesIssueService } from "@plane/services"; -import { TFileSignedURLResponse, TIssuePublicComment } from "@plane/types"; -import { EFileAssetType } from "@plane/types/src/enums"; +import { EFileAssetType, TFileSignedURLResponse, TIssuePublicComment } from "@plane/types"; // store import { CoreRootStore } from "@/store/root.store"; // types diff --git a/space/core/store/issue-filters.store.ts b/apps/space/core/store/issue-filters.store.ts similarity index 100% rename from space/core/store/issue-filters.store.ts rename to apps/space/core/store/issue-filters.store.ts diff --git a/space/core/store/issue.store.ts b/apps/space/core/store/issue.store.ts similarity index 100% rename from space/core/store/issue.store.ts rename to apps/space/core/store/issue.store.ts diff --git a/space/core/store/label.store.ts b/apps/space/core/store/label.store.ts similarity index 100% rename from space/core/store/label.store.ts rename to apps/space/core/store/label.store.ts diff --git a/space/core/store/members.store.ts b/apps/space/core/store/members.store.ts similarity index 100% rename from space/core/store/members.store.ts rename to apps/space/core/store/members.store.ts diff --git a/space/core/store/module.store.ts b/apps/space/core/store/module.store.ts similarity index 100% rename from space/core/store/module.store.ts rename to apps/space/core/store/module.store.ts diff --git a/space/core/store/profile.store.ts b/apps/space/core/store/profile.store.ts similarity index 97% rename from space/core/store/profile.store.ts rename to apps/space/core/store/profile.store.ts index c032efba9..59feb088b 100644 --- a/space/core/store/profile.store.ts +++ b/apps/space/core/store/profile.store.ts @@ -1,9 +1,8 @@ import set from "lodash/set"; import { action, makeObservable, observable, runInAction } from "mobx"; // plane imports -import { EStartOfTheWeek } from "@plane/constants"; import { UserService } from "@plane/services"; -import { TUserProfile } from "@plane/types"; +import { EStartOfTheWeek, TUserProfile } from "@plane/types"; // store import { CoreRootStore } from "@/store/root.store"; diff --git a/space/core/store/publish/publish.store.ts b/apps/space/core/store/publish/publish.store.ts similarity index 100% rename from space/core/store/publish/publish.store.ts rename to apps/space/core/store/publish/publish.store.ts diff --git a/space/core/store/publish/publish_list.store.ts b/apps/space/core/store/publish/publish_list.store.ts similarity index 100% rename from space/core/store/publish/publish_list.store.ts rename to apps/space/core/store/publish/publish_list.store.ts diff --git a/space/core/store/root.store.ts b/apps/space/core/store/root.store.ts similarity index 100% rename from space/core/store/root.store.ts rename to apps/space/core/store/root.store.ts diff --git a/space/core/store/state.store.ts b/apps/space/core/store/state.store.ts similarity index 100% rename from space/core/store/state.store.ts rename to apps/space/core/store/state.store.ts diff --git a/space/core/store/user.store.ts b/apps/space/core/store/user.store.ts similarity index 95% rename from space/core/store/user.store.ts rename to apps/space/core/store/user.store.ts index 6765961f5..438b67aeb 100644 --- a/space/core/store/user.store.ts +++ b/apps/space/core/store/user.store.ts @@ -1,14 +1,13 @@ +import { AxiosError } from "axios"; import set from "lodash/set"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; // plane imports import { UserService } from "@plane/services"; -import { IUser } from "@plane/types"; +import { ActorDetail, IUser } from "@plane/types"; // store types import { ProfileStore, IProfileStore } from "@/store/profile.store"; // store import { CoreRootStore } from "@/store/root.store"; -// types -import { ActorDetail } from "@/types/issue"; type TUserErrorStatus = { status: string; @@ -114,6 +113,9 @@ export class UserStore implements IUserStore { status: "user-fetch-error", message: "Failed to fetch current user", }; + if (error instanceof AxiosError && error.status === 401) { + this.data = undefined; + } }); throw error; } diff --git a/space/core/types/auth.ts b/apps/space/core/types/auth.ts similarity index 100% rename from space/core/types/auth.ts rename to apps/space/core/types/auth.ts diff --git a/space/core/types/cycle.d.ts b/apps/space/core/types/cycle.d.ts similarity index 100% rename from space/core/types/cycle.d.ts rename to apps/space/core/types/cycle.d.ts diff --git a/space/core/types/intake.d.ts b/apps/space/core/types/intake.d.ts similarity index 100% rename from space/core/types/intake.d.ts rename to apps/space/core/types/intake.d.ts diff --git a/space/core/types/issue.d.ts b/apps/space/core/types/issue.d.ts similarity index 70% rename from space/core/types/issue.d.ts rename to apps/space/core/types/issue.d.ts index d57dd84de..ac7549a8a 100644 --- a/space/core/types/issue.d.ts +++ b/apps/space/core/types/issue.d.ts @@ -1,4 +1,4 @@ -import { IWorkspaceLite, TIssue, TIssuePriorities, TStateGroups, TIssuePublicComment } from "@plane/types"; +import { ActorDetail, TIssue, TIssuePriorities, TStateGroups, TIssuePublicComment } from "@plane/types"; export type TIssueLayout = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt"; export type TIssueLayoutOptions = { @@ -111,57 +111,6 @@ export interface IIssueReaction { reaction: string; } -export interface ActorDetail { - avatar_url?: string; - display_name?: string; - first_name?: string; - is_bot?: boolean; - id?: string; - last_name?: string; -} - -export interface IssueDetail { - id: string; - name: string; - description: Description; - description_html: string; - priority: string; - start_date: null; - target_date: null; - sequence_id: number; - sort_order: number; -} - -export interface Description { - type: string; - content: DescriptionContent[]; -} - -export interface DescriptionContent { - type: string; - attrs?: Attrs; - content: ContentContent[]; -} - -export interface Attrs { - level: number; -} - -export interface ContentContent { - text: string; - type: string; -} - -export interface ProjectDetail { - id: string; - identifier: string; - name: string; - cover_image: string; - icon_prop: null; - emoji: string; - description: string; -} - export interface IIssueFilterOptions { state?: string[] | null; labels?: string[] | null; diff --git a/space/core/types/member.d.ts b/apps/space/core/types/member.d.ts similarity index 100% rename from space/core/types/member.d.ts rename to apps/space/core/types/member.d.ts diff --git a/space/core/types/modules.d.ts b/apps/space/core/types/modules.d.ts similarity index 100% rename from space/core/types/modules.d.ts rename to apps/space/core/types/modules.d.ts diff --git a/space/ee/components/editor/index.ts b/apps/space/ee/components/editor/index.ts similarity index 100% rename from space/ee/components/editor/index.ts rename to apps/space/ee/components/editor/index.ts diff --git a/space/ee/components/issue-layouts/root.tsx b/apps/space/ee/components/issue-layouts/root.tsx similarity index 100% rename from space/ee/components/issue-layouts/root.tsx rename to apps/space/ee/components/issue-layouts/root.tsx diff --git a/space/ee/components/navbar/index.tsx b/apps/space/ee/components/navbar/index.tsx similarity index 100% rename from space/ee/components/navbar/index.tsx rename to apps/space/ee/components/navbar/index.tsx diff --git a/space/ee/hooks/store/index.ts b/apps/space/ee/hooks/store/index.ts similarity index 100% rename from space/ee/hooks/store/index.ts rename to apps/space/ee/hooks/store/index.ts diff --git a/space/ee/store/root.store.ts b/apps/space/ee/store/root.store.ts similarity index 100% rename from space/ee/store/root.store.ts rename to apps/space/ee/store/root.store.ts diff --git a/space/helpers/authentication.helper.tsx b/apps/space/helpers/authentication.helper.tsx similarity index 100% rename from space/helpers/authentication.helper.tsx rename to apps/space/helpers/authentication.helper.tsx diff --git a/space/helpers/common.helper.ts b/apps/space/helpers/common.helper.ts similarity index 100% rename from space/helpers/common.helper.ts rename to apps/space/helpers/common.helper.ts diff --git a/space/helpers/date-time.helper.ts b/apps/space/helpers/date-time.helper.ts similarity index 100% rename from space/helpers/date-time.helper.ts rename to apps/space/helpers/date-time.helper.ts diff --git a/space/helpers/editor.helper.ts b/apps/space/helpers/editor.helper.ts similarity index 87% rename from space/helpers/editor.helper.ts rename to apps/space/helpers/editor.helper.ts index e63ba8834..1b114ea58 100644 --- a/space/helpers/editor.helper.ts +++ b/apps/space/helpers/editor.helper.ts @@ -27,16 +27,19 @@ type TArgs = { export const getReadOnlyEditorFileHandlers = (args: Pick): TReadOnlyFileHandler => { const { anchor, workspaceId } = args; + const getAssetSrc = async (path: string) => { + if (!path) return ""; + if (path?.startsWith("http")) { + return path; + } else { + return getEditorAssetSrc(anchor, path) ?? ""; + } + }; + return { checkIfAssetExists: async () => true, - getAssetSrc: async (path) => { - if (!path) return ""; - if (path?.startsWith("http")) { - return path; - } else { - return getEditorAssetSrc(anchor, path) ?? ""; - } - }, + getAssetDownloadSrc: getAssetSrc, + getAssetSrc: getAssetSrc, restore: async (src: string) => { if (src?.startsWith("http")) { await sitesFileService.restoreOldEditorAsset(workspaceId, src); diff --git a/space/helpers/emoji.helper.tsx b/apps/space/helpers/emoji.helper.tsx similarity index 100% rename from space/helpers/emoji.helper.tsx rename to apps/space/helpers/emoji.helper.tsx diff --git a/space/helpers/file.helper.ts b/apps/space/helpers/file.helper.ts similarity index 100% rename from space/helpers/file.helper.ts rename to apps/space/helpers/file.helper.ts diff --git a/space/helpers/issue.helper.ts b/apps/space/helpers/issue.helper.ts similarity index 100% rename from space/helpers/issue.helper.ts rename to apps/space/helpers/issue.helper.ts diff --git a/space/helpers/password.helper.ts b/apps/space/helpers/password.helper.ts similarity index 100% rename from space/helpers/password.helper.ts rename to apps/space/helpers/password.helper.ts diff --git a/space/helpers/query-param-generator.ts b/apps/space/helpers/query-param-generator.ts similarity index 100% rename from space/helpers/query-param-generator.ts rename to apps/space/helpers/query-param-generator.ts diff --git a/space/helpers/state.helper.ts b/apps/space/helpers/state.helper.ts similarity index 100% rename from space/helpers/state.helper.ts rename to apps/space/helpers/state.helper.ts diff --git a/space/helpers/string.helper.ts b/apps/space/helpers/string.helper.ts similarity index 100% rename from space/helpers/string.helper.ts rename to apps/space/helpers/string.helper.ts diff --git a/web/next-env.d.ts b/apps/space/next-env.d.ts similarity index 100% rename from web/next-env.d.ts rename to apps/space/next-env.d.ts diff --git a/space/next.config.js b/apps/space/next.config.js similarity index 64% rename from space/next.config.js rename to apps/space/next.config.js index 2d3e4e788..a736f4f64 100644 --- a/space/next.config.js +++ b/apps/space/next.config.js @@ -23,19 +23,21 @@ const nextConfig = { ], unoptimized: true, }, - transpilePackages: [ - "@plane/constants", - "@plane/editor", - "@plane/hooks", - "@plane/i18n", - "@plane/logger", - "@plane/propel", - "@plane/services", - "@plane/shared-state", - "@plane/types", - "@plane/ui", - "@plane/utils", - ], + experimental: { + optimizePackageImports: [ + "@plane/constants", + "@plane/editor", + "@plane/hooks", + "@plane/i18n", + "@plane/logger", + "@plane/propel", + "@plane/services", + "@plane/shared-state", + "@plane/types", + "@plane/ui", + "@plane/utils", + ], + }, }; module.exports = nextConfig; diff --git a/space/package.json b/apps/space/package.json similarity index 79% rename from space/package.json rename to apps/space/package.json index 13356047e..848b0e2b9 100644 --- a/space/package.json +++ b/apps/space/package.json @@ -1,16 +1,18 @@ { "name": "space", - "version": "0.27.1", + "version": "0.28.0", "private": true, "license": "AGPL-3.0", "scripts": { - "dev": "turbo run develop", - "develop": "next dev -p 3002", + "dev": "next dev -p 3002", "build": "next build", "start": "next start", - "lint": "eslint . --ext .ts,.tsx", - "lint:errors": "eslint . --ext .ts,.tsx --quiet", - "export": "next export" + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"" }, "dependencies": { "@blueprintjs/core": "^4.16.3", @@ -26,7 +28,7 @@ "@plane/services": "*", "@plane/types": "*", "@plane/ui": "*", - "axios": "^1.8.3", + "axios": "1.11.0", "clsx": "^2.0.0", "date-fns": "^4.1.0", "dompurify": "^3.0.11", diff --git a/space/postcss.config.js b/apps/space/postcss.config.js similarity index 100% rename from space/postcss.config.js rename to apps/space/postcss.config.js diff --git a/space/public/404.svg b/apps/space/public/404.svg similarity index 100% rename from space/public/404.svg rename to apps/space/public/404.svg diff --git a/space/public/auth/background-pattern-dark.svg b/apps/space/public/auth/background-pattern-dark.svg similarity index 100% rename from space/public/auth/background-pattern-dark.svg rename to apps/space/public/auth/background-pattern-dark.svg diff --git a/space/public/auth/background-pattern.svg b/apps/space/public/auth/background-pattern.svg similarity index 100% rename from space/public/auth/background-pattern.svg rename to apps/space/public/auth/background-pattern.svg diff --git a/space/public/favicon/android-chrome-192x192.png b/apps/space/public/favicon/android-chrome-192x192.png similarity index 100% rename from space/public/favicon/android-chrome-192x192.png rename to apps/space/public/favicon/android-chrome-192x192.png diff --git a/space/public/favicon/android-chrome-512x512.png b/apps/space/public/favicon/android-chrome-512x512.png similarity index 100% rename from space/public/favicon/android-chrome-512x512.png rename to apps/space/public/favicon/android-chrome-512x512.png diff --git a/space/public/favicon/apple-touch-icon.png b/apps/space/public/favicon/apple-touch-icon.png similarity index 100% rename from space/public/favicon/apple-touch-icon.png rename to apps/space/public/favicon/apple-touch-icon.png diff --git a/space/public/favicon/favicon-16x16.png b/apps/space/public/favicon/favicon-16x16.png similarity index 100% rename from space/public/favicon/favicon-16x16.png rename to apps/space/public/favicon/favicon-16x16.png diff --git a/space/public/favicon/favicon-32x32.png b/apps/space/public/favicon/favicon-32x32.png similarity index 100% rename from space/public/favicon/favicon-32x32.png rename to apps/space/public/favicon/favicon-32x32.png diff --git a/space/public/favicon/favicon.ico b/apps/space/public/favicon/favicon.ico similarity index 100% rename from space/public/favicon/favicon.ico rename to apps/space/public/favicon/favicon.ico diff --git a/space/public/favicon/site.webmanifest b/apps/space/public/favicon/site.webmanifest similarity index 100% rename from space/public/favicon/site.webmanifest rename to apps/space/public/favicon/site.webmanifest diff --git a/space/public/images/logo-spinner-dark.gif b/apps/space/public/images/logo-spinner-dark.gif similarity index 100% rename from space/public/images/logo-spinner-dark.gif rename to apps/space/public/images/logo-spinner-dark.gif diff --git a/space/public/images/logo-spinner-light.gif b/apps/space/public/images/logo-spinner-light.gif similarity index 100% rename from space/public/images/logo-spinner-light.gif rename to apps/space/public/images/logo-spinner-light.gif diff --git a/space/public/instance/instance-failure-dark.svg b/apps/space/public/instance/instance-failure-dark.svg similarity index 100% rename from space/public/instance/instance-failure-dark.svg rename to apps/space/public/instance/instance-failure-dark.svg diff --git a/space/public/instance/instance-failure.svg b/apps/space/public/instance/instance-failure.svg similarity index 100% rename from space/public/instance/instance-failure.svg rename to apps/space/public/instance/instance-failure.svg diff --git a/space/public/instance/intake-sent-dark.png b/apps/space/public/instance/intake-sent-dark.png similarity index 100% rename from space/public/instance/intake-sent-dark.png rename to apps/space/public/instance/intake-sent-dark.png diff --git a/space/public/instance/intake-sent-light.png b/apps/space/public/instance/intake-sent-light.png similarity index 100% rename from space/public/instance/intake-sent-light.png rename to apps/space/public/instance/intake-sent-light.png diff --git a/space/public/instance/plane-instance-not-ready.webp b/apps/space/public/instance/plane-instance-not-ready.webp similarity index 100% rename from space/public/instance/plane-instance-not-ready.webp rename to apps/space/public/instance/plane-instance-not-ready.webp diff --git a/space/public/instance/plane-takeoff.png b/apps/space/public/instance/plane-takeoff.png similarity index 100% rename from space/public/instance/plane-takeoff.png rename to apps/space/public/instance/plane-takeoff.png diff --git a/space/public/logos/github-black.png b/apps/space/public/logos/github-black.png similarity index 100% rename from space/public/logos/github-black.png rename to apps/space/public/logos/github-black.png diff --git a/space/public/logos/github-dark.svg b/apps/space/public/logos/github-dark.svg similarity index 100% rename from space/public/logos/github-dark.svg rename to apps/space/public/logos/github-dark.svg diff --git a/space/public/logos/github-square.svg b/apps/space/public/logos/github-square.svg similarity index 100% rename from space/public/logos/github-square.svg rename to apps/space/public/logos/github-square.svg diff --git a/space/public/logos/github-white.svg b/apps/space/public/logos/github-white.svg similarity index 100% rename from space/public/logos/github-white.svg rename to apps/space/public/logos/github-white.svg diff --git a/space/public/logos/gitlab-logo.svg b/apps/space/public/logos/gitlab-logo.svg similarity index 100% rename from space/public/logos/gitlab-logo.svg rename to apps/space/public/logos/gitlab-logo.svg diff --git a/space/public/logos/google-logo.svg b/apps/space/public/logos/google-logo.svg similarity index 100% rename from space/public/logos/google-logo.svg rename to apps/space/public/logos/google-logo.svg diff --git a/space/public/plane-logo.svg b/apps/space/public/plane-logo.svg similarity index 100% rename from space/public/plane-logo.svg rename to apps/space/public/plane-logo.svg diff --git a/space/public/plane-logos/black-horizontal-with-blue-logo.png b/apps/space/public/plane-logos/black-horizontal-with-blue-logo.png similarity index 100% rename from space/public/plane-logos/black-horizontal-with-blue-logo.png rename to apps/space/public/plane-logos/black-horizontal-with-blue-logo.png diff --git a/space/public/plane-logos/blue-without-text-new.png b/apps/space/public/plane-logos/blue-without-text-new.png similarity index 100% rename from space/public/plane-logos/blue-without-text-new.png rename to apps/space/public/plane-logos/blue-without-text-new.png diff --git a/space/public/plane-logos/blue-without-text.png b/apps/space/public/plane-logos/blue-without-text.png similarity index 100% rename from space/public/plane-logos/blue-without-text.png rename to apps/space/public/plane-logos/blue-without-text.png diff --git a/space/public/plane-logos/white-horizontal-with-blue-logo.png b/apps/space/public/plane-logos/white-horizontal-with-blue-logo.png similarity index 100% rename from space/public/plane-logos/white-horizontal-with-blue-logo.png rename to apps/space/public/plane-logos/white-horizontal-with-blue-logo.png diff --git a/space/public/plane-logos/white-horizontal.svg b/apps/space/public/plane-logos/white-horizontal.svg similarity index 100% rename from space/public/plane-logos/white-horizontal.svg rename to apps/space/public/plane-logos/white-horizontal.svg diff --git a/space/public/project-not-published.svg b/apps/space/public/project-not-published.svg similarity index 100% rename from space/public/project-not-published.svg rename to apps/space/public/project-not-published.svg diff --git a/space/public/robots.txt b/apps/space/public/robots.txt similarity index 100% rename from space/public/robots.txt rename to apps/space/public/robots.txt diff --git a/space/public/site.webmanifest.json b/apps/space/public/site.webmanifest.json similarity index 100% rename from space/public/site.webmanifest.json rename to apps/space/public/site.webmanifest.json diff --git a/space/public/something-went-wrong.svg b/apps/space/public/something-went-wrong.svg similarity index 100% rename from space/public/something-went-wrong.svg rename to apps/space/public/something-went-wrong.svg diff --git a/space/public/user-logged-in.svg b/apps/space/public/user-logged-in.svg similarity index 100% rename from space/public/user-logged-in.svg rename to apps/space/public/user-logged-in.svg diff --git a/space/styles/globals.css b/apps/space/styles/globals.css similarity index 94% rename from space/styles/globals.css rename to apps/space/styles/globals.css index 5d27de674..60cfd7f06 100644 --- a/space/styles/globals.css +++ b/apps/space/styles/globals.css @@ -47,23 +47,31 @@ --color-border-300: 212, 212, 212; /* strong border- 1 */ --color-border-400: 185, 185, 185; /* strong border- 2 */ - --color-shadow-2xs: 0px 0px 1px 0px rgba(23, 23, 23, 0.06), 0px 1px 2px 0px rgba(23, 23, 23, 0.06), + --color-shadow-2xs: + 0px 0px 1px 0px rgba(23, 23, 23, 0.06), 0px 1px 2px 0px rgba(23, 23, 23, 0.06), 0px 1px 2px 0px rgba(23, 23, 23, 0.14); - --color-shadow-xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.16), 0px 2px 4px 0px rgba(16, 24, 40, 0.12), + --color-shadow-xs: + 0px 1px 2px 0px rgba(0, 0, 0, 0.16), 0px 2px 4px 0px rgba(16, 24, 40, 0.12), 0px 1px 8px -1px rgba(16, 24, 40, 0.1); - --color-shadow-sm: 0px 1px 4px 0px rgba(0, 0, 0, 0.01), 0px 4px 8px 0px rgba(0, 0, 0, 0.02), - 0px 1px 12px 0px rgba(0, 0, 0, 0.12); - --color-shadow-rg: 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 4px 4px 0px rgba(16, 24, 40, 0.08), + --color-shadow-sm: + 0px 1px 4px 0px rgba(0, 0, 0, 0.01), 0px 4px 8px 0px rgba(0, 0, 0, 0.02), 0px 1px 12px 0px rgba(0, 0, 0, 0.12); + --color-shadow-rg: + 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 4px 4px 0px rgba(16, 24, 40, 0.08), 0px 1px 12px 0px rgba(16, 24, 40, 0.04); - --color-shadow-md: 0px 4px 8px 0px rgba(0, 0, 0, 0.12), 0px 6px 12px 0px rgba(16, 24, 40, 0.12), + --color-shadow-md: + 0px 4px 8px 0px rgba(0, 0, 0, 0.12), 0px 6px 12px 0px rgba(16, 24, 40, 0.12), 0px 1px 16px 0px rgba(16, 24, 40, 0.12); - --color-shadow-lg: 0px 6px 12px 0px rgba(0, 0, 0, 0.12), 0px 8px 16px 0px rgba(0, 0, 0, 0.12), + --color-shadow-lg: + 0px 6px 12px 0px rgba(0, 0, 0, 0.12), 0px 8px 16px 0px rgba(0, 0, 0, 0.12), 0px 1px 24px 0px rgba(16, 24, 40, 0.12); - --color-shadow-xl: 0px 0px 18px 0px rgba(0, 0, 0, 0.16), 0px 0px 24px 0px rgba(16, 24, 40, 0.16), + --color-shadow-xl: + 0px 0px 18px 0px rgba(0, 0, 0, 0.16), 0px 0px 24px 0px rgba(16, 24, 40, 0.16), 0px 0px 52px 0px rgba(16, 24, 40, 0.16); - --color-shadow-2xl: 0px 8px 16px 0px rgba(0, 0, 0, 0.12), 0px 12px 24px 0px rgba(16, 24, 40, 0.12), + --color-shadow-2xl: + 0px 8px 16px 0px rgba(0, 0, 0, 0.12), 0px 12px 24px 0px rgba(16, 24, 40, 0.12), 0px 1px 32px 0px rgba(16, 24, 40, 0.12); - --color-shadow-3xl: 0px 12px 24px 0px rgba(0, 0, 0, 0.12), 0px 16px 32px 0px rgba(0, 0, 0, 0.12), + --color-shadow-3xl: + 0px 12px 24px 0px rgba(0, 0, 0, 0.12), 0px 16px 32px 0px rgba(0, 0, 0, 0.12), 0px 1px 48px 0px rgba(16, 24, 40, 0.12); --color-shadow-4xl: 0px 8px 40px 0px rgba(0, 0, 61, 0.05), 0px 12px 32px -16px rgba(0, 0, 0, 0.05); diff --git a/space/tailwind.config.js b/apps/space/tailwind.config.js similarity index 100% rename from space/tailwind.config.js rename to apps/space/tailwind.config.js diff --git a/space/tsconfig.json b/apps/space/tsconfig.json similarity index 100% rename from space/tsconfig.json rename to apps/space/tsconfig.json diff --git a/web/.env.example b/apps/web/.env.example similarity index 100% rename from web/.env.example rename to apps/web/.env.example diff --git a/web/.eslintignore b/apps/web/.eslintignore similarity index 100% rename from web/.eslintignore rename to apps/web/.eslintignore diff --git a/web/.eslintrc.js b/apps/web/.eslintrc.js similarity index 100% rename from web/.eslintrc.js rename to apps/web/.eslintrc.js diff --git a/web/.gitignore b/apps/web/.gitignore similarity index 100% rename from web/.gitignore rename to apps/web/.gitignore diff --git a/web/.prettierignore b/apps/web/.prettierignore similarity index 100% rename from web/.prettierignore rename to apps/web/.prettierignore diff --git a/web/.prettierrc b/apps/web/.prettierrc similarity index 100% rename from web/.prettierrc rename to apps/web/.prettierrc diff --git a/web/Dockerfile.dev b/apps/web/Dockerfile.dev similarity index 91% rename from web/Dockerfile.dev rename to apps/web/Dockerfile.dev index 64465755e..8ca879207 100644 --- a/web/Dockerfile.dev +++ b/apps/web/Dockerfile.dev @@ -1,12 +1,13 @@ -FROM node:20-alpine +FROM node:22-alpine + RUN apk add --no-cache libc6-compat # Set working directory WORKDIR /app - COPY . . RUN yarn global add turbo RUN yarn install + EXPOSE 3000 VOLUME [ "/app/node_modules", "/app/web/node_modules" ] CMD ["yarn", "dev", "--filter=web"] diff --git a/web/Dockerfile.web b/apps/web/Dockerfile.web similarity index 85% rename from web/Dockerfile.web rename to apps/web/Dockerfile.web index 56f931adc..ac1da79af 100644 --- a/web/Dockerfile.web +++ b/apps/web/Dockerfile.web @@ -1,4 +1,4 @@ -FROM node:20-alpine as base +FROM node:22-alpine AS base # ***************************************************************************** # STAGE 1: Build the project @@ -56,8 +56,8 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL -ENV NEXT_TELEMETRY_DISABLED 1 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 RUN yarn turbo run build --filter=web @@ -67,14 +67,17 @@ RUN yarn turbo run build --filter=web FROM base AS runner WORKDIR /app -COPY --from=installer /app/web/next.config.js . -COPY --from=installer /app/web/package.json . +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs +USER nextjs + # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=installer /app/web/.next/standalone ./ -COPY --from=installer /app/web/.next ./web/.next -COPY --from=installer /app/web/public ./web/public +COPY --from=installer /app/apps/web/.next/standalone ./ +COPY --from=installer /app/apps/web/.next/static ./apps/web/.next/static +COPY --from=installer /app/apps/web/public ./apps/web/public ARG NEXT_PUBLIC_API_BASE_URL="" ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL @@ -100,7 +103,9 @@ ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH ARG NEXT_PUBLIC_WEB_BASE_URL="" ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL -ENV NEXT_TELEMETRY_DISABLED 1 -ENV TURBO_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV TURBO_TELEMETRY_DISABLED=1 EXPOSE 3000 + +CMD ["node", "apps/web/server.js"] \ No newline at end of file diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx new file mode 100644 index 000000000..cd91d1c28 --- /dev/null +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx @@ -0,0 +1,63 @@ +"use client"; +import { FC, useState } from "react"; +import { observer } from "mobx-react"; +// plane imports +import { SIDEBAR_WIDTH } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; +// hooks +import { ResizableSidebar } from "@/components/sidebar"; +import { useAppTheme } from "@/hooks/store"; +import { useAppRail } from "@/hooks/use-app-rail"; +// local imports +import { ExtendedAppSidebar } from "./extended-sidebar"; +import { AppSidebar } from "./sidebar"; + +export const ProjectAppSidebar: FC = observer(() => { + // store hooks + const { + sidebarCollapsed, + toggleSidebar, + sidebarPeek, + toggleSidebarPeek, + isExtendedSidebarOpened, + isAnySidebarDropdownOpen, + } = useAppTheme(); + const { storedValue, setValue } = useLocalStorage("sidebarWidth", SIDEBAR_WIDTH); + // states + const [sidebarWidth, setSidebarWidth] = useState(storedValue ?? SIDEBAR_WIDTH); + // hooks + const { shouldRenderAppRail } = useAppRail(); + // derived values + const isAnyExtendedSidebarOpen = isExtendedSidebarOpened; + + // handlers + const handleWidthChange = (width: number) => setValue(width); + + return ( + <> + + + + } + isAnyExtendedSidebarExpanded={isAnyExtendedSidebarOpen} + isAnySidebarDropdownOpen={isAnySidebarDropdownOpen} + disablePeekTrigger={shouldRenderAppRail} + > + + + + ); +}); diff --git a/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/header.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/active-cycles/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/header.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/active-cycles/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/active-cycles/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/active-cycles/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/header.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/header.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx similarity index 91% rename from web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx index 6100bc8d5..829ebdec7 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx @@ -4,7 +4,7 @@ import { useMemo } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/navigation"; // plane package imports -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { type TabItem, Tabs } from "@plane/ui"; // components @@ -12,7 +12,8 @@ import AnalyticsFilterActions from "@/components/analytics/analytics-filter-acti import { PageHead } from "@/components/core"; import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state"; // hooks -import { useCommandPalette, useEventTracker, useProject, useUserPermissions, useWorkspace } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useProject, useUserPermissions, useWorkspace } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { getAnalyticsTabs } from "@/plane-web/components/analytics/tabs"; @@ -36,7 +37,6 @@ const AnalyticsPage = observer((props: Props) => { // store hooks const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { workspaceProjectIds, loader } = useProject(); const { currentWorkspace } = useWorkspace(); const { allowPermissions } = useUserPermissions(); @@ -101,8 +101,8 @@ const AnalyticsPage = observer((props: Props) => { title={t("workspace_analytics.empty_state.general.primary_button.comic.title")} description={t("workspace_analytics.empty_state.general.primary_button.comic.description")} onClick={() => { - setTrackElement("Analytics empty state"); toggleCreateProjectModal(true); + captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); }} disabled={!canPerformEmptyStateActions} /> diff --git a/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/header.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/header.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx similarity index 98% rename from web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx index 735474cd4..63c6aa2b7 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx @@ -6,8 +6,8 @@ import { useParams } from "next/navigation"; import { useTheme } from "next-themes"; import useSWR from "swr"; // plane imports -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EIssueServiceType } from "@plane/types"; import { Loader } from "@plane/ui"; // components import { EmptyState } from "@/components/common"; diff --git a/web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx similarity index 94% rename from web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx index 92cdfb1c1..84f60e9fc 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/header.tsx @@ -3,9 +3,10 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { PenSquare } from "lucide-react"; -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui +import { EIssuesStoreType } from "@plane/types"; import { Breadcrumbs, Button, Header } from "@plane/ui"; // components import { BreadcrumbLink, CountChip } from "@/components/common"; diff --git a/web/app/(all)/[workspaceSlug]/(projects)/drafts/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/drafts/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/drafts/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/drafts/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/drafts/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx similarity index 81% rename from web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx index 0cd87200c..ac3e3262a 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx @@ -5,17 +5,17 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports import { Plus, Search } from "lucide-react"; -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; -import { cn, copyUrlToClipboard, orderJoinedProjects } from "@plane/utils"; +import { copyUrlToClipboard, orderJoinedProjects } from "@plane/utils"; // components import { CreateProjectModal } from "@/components/project"; import { SidebarProjectsListItem } from "@/components/workspace"; // hooks import { useAppTheme, useProject, useUserPermissions } from "@/hooks/store"; -import useExtendedSidebarOutsideClickDetector from "@/hooks/use-extended-sidebar-overview-outside-click"; import { TProject } from "@/plane-web/types"; +import { ExtendedSidebarWrapper } from "./extended-sidebar-wrapper"; export const ExtendedProjectSidebar = observer(() => { // refs @@ -27,7 +27,7 @@ export const ExtendedProjectSidebar = observer(() => { const { workspaceSlug } = useParams(); // store hooks const { t } = useTranslation(); - const { sidebarCollapsed, extendedProjectSidebarCollapsed, toggleExtendedProjectSidebar } = useAppTheme(); + const { isExtendedProjectSidebarOpened, toggleExtendedProjectSidebar } = useAppTheme(); const { getPartialProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject(); const { allowPermissions } = useUserPermissions(); @@ -74,15 +74,7 @@ export const ExtendedProjectSidebar = observer(() => { EUserPermissionsLevel.WORKSPACE ); - useExtendedSidebarOutsideClickDetector( - extendedProjectSidebarRef, - () => { - if (!isProjectModalOpen) { - toggleExtendedProjectSidebar(false); - } - }, - "extended-project-sidebar-toggle" - ); + const handleClose = () => toggleExtendedProjectSidebar(false); const handleCopyText = (projectId: string) => { copyUrlToClipboard(`${workspaceSlug}/projects/${projectId}/issues`).then(() => { @@ -103,17 +95,11 @@ export const ExtendedProjectSidebar = observer(() => { workspaceSlug={workspaceSlug.toString()} /> )} -
@@ -122,6 +108,7 @@ export const ExtendedProjectSidebar = observer(() => {
-
+ ); }); diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx new file mode 100644 index 000000000..bf5fdb4e2 --- /dev/null +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx @@ -0,0 +1,46 @@ +"use client"; + +import React, { FC } from "react"; +import { observer } from "mobx-react"; +// plane imports +import { EXTENDED_SIDEBAR_WIDTH, SIDEBAR_WIDTH } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; +import { cn } from "@plane/utils"; +// hooks +import useExtendedSidebarOutsideClickDetector from "@/hooks/use-extended-sidebar-overview-outside-click"; + +type Props = { + children: React.ReactNode; + extendedSidebarRef: React.RefObject; + isExtendedSidebarOpened: boolean; + handleClose: () => void; + excludedElementId: string; +}; + +export const ExtendedSidebarWrapper: FC = observer((props) => { + const { children, extendedSidebarRef, isExtendedSidebarOpened, handleClose, excludedElementId } = props; + // store hooks + const { storedValue } = useLocalStorage("sidebarWidth", SIDEBAR_WIDTH); + + useExtendedSidebarOutsideClickDetector(extendedSidebarRef, handleClose, excludedElementId); + + return ( +
+ {children} +
+ ); +}); diff --git a/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx similarity index 77% rename from web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx index baa41eb9f..6af0e0b24 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx @@ -4,13 +4,13 @@ import React, { useMemo, useRef } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EUserWorkspaceRoles, WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS } from "@plane/constants"; -import { cn } from "@plane/utils"; +import { WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS } from "@plane/constants"; +import { EUserWorkspaceRoles } from "@plane/types"; // hooks import { useAppTheme, useWorkspace } from "@/hooks/store"; -import useExtendedSidebarOutsideClickDetector from "@/hooks/use-extended-sidebar-overview-outside-click"; // plane-web imports import { ExtendedSidebarItem } from "@/plane-web/components/workspace/sidebar"; +import { ExtendedSidebarWrapper } from "./extended-sidebar-wrapper"; export const ExtendedAppSidebar = observer(() => { // refs @@ -18,7 +18,7 @@ export const ExtendedAppSidebar = observer(() => { // routers const { workspaceSlug } = useParams(); // store hooks - const { sidebarCollapsed, extendedSidebarCollapsed, toggleExtendedSidebar } = useAppTheme(); + const { isExtendedSidebarOpened, toggleExtendedSidebar } = useAppTheme(); const { updateSidebarPreference, getNavigationPreferences } = useWorkspace(); // derived values @@ -94,24 +94,14 @@ export const ExtendedAppSidebar = observer(() => { }); }; - useExtendedSidebarOutsideClickDetector( - extendedSidebarRef, - () => toggleExtendedSidebar(true), - "extended-sidebar-toggle" - ); + const handleClose = () => toggleExtendedSidebar(false); return ( -
{sortedNavigationItems.map((item, index) => ( { handleOnNavigationItemDrop={handleOnNavigationItemDrop} /> ))} -
+ ); }); diff --git a/web/app/(all)/[workspaceSlug]/(projects)/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/header.tsx similarity index 57% rename from web/app/(all)/[workspaceSlug]/(projects)/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/header.tsx index 42e3222b3..0664a945c 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/header.tsx @@ -1,32 +1,34 @@ "use client"; +import { observer } from "mobx-react"; import Image from "next/image"; import { useTheme } from "next-themes"; -import { Home } from "lucide-react"; +import { Home, Shapes } from "lucide-react"; // images import githubBlackImage from "/public/logos/github-black.png"; import githubWhiteImage from "/public/logos/github-white.png"; // ui -import { GITHUB_REDIRECTED_TRACKER_EVENT } from "@plane/constants"; +import { GITHUB_REDIRECTED_TRACKER_EVENT, HEADER_GITHUB_ICON } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { Breadcrumbs, Header } from "@plane/ui"; +import { Breadcrumbs, Button, Header } from "@plane/ui"; // components import { BreadcrumbLink } from "@/components/common"; // constants // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; +import { useHome } from "@/hooks/store/use-home"; -export const WorkspaceDashboardHeader = () => { +export const WorkspaceDashboardHeader = observer(() => { // hooks - const { captureEvent } = useEventTracker(); const { resolvedTheme } = useTheme(); + const { toggleWidgetSettings } = useHome(); const { t } = useTranslation(); return ( <>
-
); -}; +}); diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx new file mode 100644 index 000000000..35408c491 --- /dev/null +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { CommandPalette } from "@/components/command-palette"; +import { AuthenticationWrapper } from "@/lib/wrappers"; +// plane web components +import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper"; +import { ProjectAppSidebar } from "./_sidebar"; + +export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { + return ( + + + +
+
+
+ +
+ {children} +
+
+
+ + + ); +} diff --git a/web/app/(all)/[workspaceSlug]/(projects)/notifications/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/notifications/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/notifications/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/notifications/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/notifications/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/notifications/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/notifications/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/notifications/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/[profileViewId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/[profileViewId]/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/[profileViewId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/[profileViewId]/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/header.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/header.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx similarity index 96% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx index 60ee2c351..ac7e04303 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/mobile-header.tsx @@ -6,17 +6,18 @@ import { useParams } from "next/navigation"; // icons import { ChevronDown } from "lucide-react"; // plane constants -import { - EIssueLayoutTypes, - EIssueFilterType, - EIssuesStoreType, - ISSUE_LAYOUTS, - ISSUE_DISPLAY_FILTERS_BY_PAGE, -} from "@plane/constants"; +import { EIssueFilterType, ISSUE_LAYOUTS, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; // plane i18n import { useTranslation } from "@plane/i18n"; // types -import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types"; +import { + EIssuesStoreType, + IIssueDisplayFilterOptions, + IIssueDisplayProperties, + IIssueFilterOptions, + TIssueLayouts, + EIssueLayoutTypes, +} from "@plane/types"; // ui import { CustomMenu } from "@plane/ui"; // components diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/navbar.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/profile/[userId]/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx similarity index 95% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx index 7bc67af5b..b7f59441f 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/page.tsx @@ -28,4 +28,4 @@ const ProjectArchivedCyclesPage = observer(() => { ); }); -export default ProjectArchivedCyclesPage; \ No newline at end of file +export default ProjectArchivedCyclesPage; diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx similarity index 98% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx index 5a588457a..40f407d6a 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx @@ -3,7 +3,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType } from "@plane/types"; // ui import { ArchiveIcon, Breadcrumbs, Tooltip, Header, ContrastIcon, DiceIcon, LayersIcon } from "@plane/ui"; // components diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/[archivedIssueId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/[archivedIssueId]/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/[archivedIssueId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/[archivedIssueId]/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/header.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/header.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(detail)/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx similarity index 95% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx index afa6c0d72..a52b3596f 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/page.tsx @@ -28,4 +28,4 @@ const ProjectArchivedIssuesPage = observer(() => { ); }); -export default ProjectArchivedIssuesPage; \ No newline at end of file +export default ProjectArchivedIssuesPage; diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/[cycleId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/[cycleId]/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/[cycleId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/[cycleId]/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx similarity index 85% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx index 5844c661b..8cadaea82 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx @@ -4,24 +4,25 @@ import { useCallback, useRef, useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // icons -import { PanelRight } from "lucide-react"; +import { ChartNoAxesColumn, ListFilter, PanelRight, SlidersHorizontal } from "lucide-react"; // plane imports import { EIssueFilterType, - EIssueLayoutTypes, - EIssuesStoreType, EUserPermissions, EUserPermissionsLevel, EProjectFeatureKey, ISSUE_DISPLAY_FILTERS_BY_PAGE, + WORK_ITEM_TRACKER_ELEMENTS, } from "@plane/constants"; import { usePlatformOS } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; import { + EIssuesStoreType, ICustomSearchSelectOption, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, + EIssueLayoutTypes, } from "@plane/types"; import { Breadcrumbs, Button, ContrastIcon, BreadcrumbNavigationSearchDropdown, Header, Tooltip } from "@plane/ui"; import { cn, isIssueFilterActive } from "@plane/utils"; @@ -29,12 +30,17 @@ import { cn, isIssueFilterActive } from "@plane/utils"; import { WorkItemsModal } from "@/components/analytics/work-items/modal"; import { SwitcherLabel } from "@/components/common"; import { CycleQuickActions } from "@/components/cycles"; -import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "@/components/issues"; +import { + DisplayFiltersSelection, + FiltersDropdown, + FilterSelection, + LayoutSelection, + MobileLayoutSelection, +} from "@/components/issues"; // hooks import { useCommandPalette, useCycle, - useEventTracker, useIssues, useLabel, useMember, @@ -68,7 +74,6 @@ export const CycleIssuesHeader: React.FC = observer(() => { } = useIssues(EIssuesStoreType.CYCLE); const { currentProjectCycleIds, getCycleById } = useCycle(); const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { currentProjectDetails, loader } = useProject(); const { projectStates } = useProjectState(); const { projectLabels } = useLabel(); @@ -208,21 +213,37 @@ export const CycleIssuesHeader: React.FC = observer(() => {
- handleLayoutChange(layout)} - selectedLayout={activeLayout} - /> +
+ handleLayoutChange(layout)} + selectedLayout={activeLayout} + /> +
+
+ handleLayoutChange(layout)} + activeLayout={activeLayout} + /> +
} > { moduleViewDisabled={!currentProjectDetails?.module_view} /> - + } + > { {canUserCreateIssue && ( <> {!isCompletedCycle && ( diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx similarity index 95% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx index 270faf985..58b69809b 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(list)/page.tsx @@ -3,9 +3,9 @@ import { observer } from "mobx-react"; import { useParams, useSearchParams } from "next/navigation"; // plane imports -import { EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TPageNavigationTabs } from "@plane/types"; +import { EUserProjectRoles, TPageNavigationTabs } from "@plane/types"; // components import { PageHead } from "@/components/core"; import { DetailedEmptyState } from "@/components/empty-state"; diff --git a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx similarity index 98% rename from web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx index 8e69ef888..2f3a17542 100644 --- a/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/header.tsx @@ -6,21 +6,22 @@ import { useParams } from "next/navigation"; import { Layers, Lock } from "lucide-react"; // plane constants import { - EIssueLayoutTypes, EIssueFilterType, - EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_PAGE, - EViewAccess, EUserPermissions, EUserPermissionsLevel, EProjectFeatureKey, + WORK_ITEM_TRACKER_ELEMENTS, } from "@plane/constants"; // types import { + EIssuesStoreType, + EViewAccess, ICustomSearchSelectOption, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, + EIssueLayoutTypes, } from "@plane/types"; // ui import { Breadcrumbs, Button, Tooltip, Header, BreadcrumbNavigationSearchDropdown } from "@plane/ui"; @@ -30,11 +31,9 @@ import { SwitcherIcon, SwitcherLabel } from "@/components/common"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "@/components/issues"; // constants import { ViewQuickActions } from "@/components/views"; -// helpers // hooks import { useCommandPalette, - useEventTracker, useIssues, useLabel, useMember, @@ -57,7 +56,6 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.PROJECT_VIEW); - const { setTrackElement } = useEventTracker(); const { toggleCreateIssueModal } = useCommandPalette(); const { allowPermissions } = useUserPermissions(); @@ -258,9 +256,9 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { {canUserCreateIssue ? (
diff --git a/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/workspace-views/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/layout.tsx similarity index 56% rename from web/app/(all)/[workspaceSlug]/(settings)/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/layout.tsx index 4bd4a5340..593a1b093 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/layout.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/layout.tsx @@ -11,14 +11,16 @@ export default function SettingsLayout({ children }: { children: React.ReactNode -
- {/* Header */} - - {/* Content */} - -
{children}
-
-
+
+
+ {/* Header */} + + {/* Content */} + +
{children}
+
+
+
); diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/billing/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/billing/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/billing/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/billing/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/exports/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/exports/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/exports/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/exports/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/imports/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/imports/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/imports/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/imports/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/integrations/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/integrations/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/integrations/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/integrations/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx similarity index 94% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx index bc3e69a7a..011659090 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx @@ -4,7 +4,8 @@ import { FC, ReactNode } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; // constants -import { EUserWorkspaceRoles, WORKSPACE_SETTINGS_ACCESS } from "@plane/constants"; +import { WORKSPACE_SETTINGS_ACCESS } from "@plane/constants"; +import { EUserWorkspaceRoles } from "@plane/types"; // components import { NotAuthorizedView } from "@/components/auth-screens"; import { SettingsMobileNav } from "@/components/settings"; diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx similarity index 79% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx index 001c00dd2..e05eb30f0 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx @@ -5,12 +5,17 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Search } from "lucide-react"; // types -import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_EVENTS } from "@plane/constants"; +import { + EUserPermissions, + EUserPermissionsLevel, + MEMBER_TRACKER_ELEMENTS, + MEMBER_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWorkspaceBulkInviteFormData } from "@plane/types"; // ui import { Button, TOAST_TYPE, setToast } from "@plane/ui"; -import { cn, getUserRole } from "@plane/utils"; +import { cn } from "@plane/utils"; // components import { NotAuthorizedView } from "@/components/auth-screens"; import { CountChip } from "@/components/common"; @@ -19,7 +24,8 @@ import { SettingsContentWrapper } from "@/components/settings"; import { WorkspaceMembersList } from "@/components/workspace"; // helpers // hooks -import { useEventTracker, useMember, useUserPermissions, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useMember, useUserPermissions, useWorkspace } from "@/hooks/store"; // plane web components import { BillingActionsButton } from "@/plane-web/components/workspace/billing"; import { SendWorkspaceInvitationModal } from "@/plane-web/components/workspace/members"; @@ -32,7 +38,6 @@ const WorkspaceMembersSettingsPage = observer(() => { const { workspaceSlug } = useParams(); // store hooks const { workspaceUserInfo, allowPermissions } = useUserPermissions(); - const { captureEvent } = useEventTracker(); const { workspace: { workspaceMemberIds, inviteMembersToWorkspace }, } = useMember(); @@ -52,16 +57,11 @@ const WorkspaceMembersSettingsPage = observer(() => { return inviteMembersToWorkspace(workspaceSlug.toString(), data) .then(() => { setInviteModal(false); - captureEvent(MEMBER_TRACKER_EVENTS.invite, { - emails: [ - ...data.emails.map((email) => ({ - email: email.email, - role: getUserRole(email.role as unknown as EUserPermissions), - })), - ], - project_id: undefined, - state: "SUCCESS", - element: "Workspace settings member page", + captureSuccess({ + eventName: MEMBER_TRACKER_EVENTS.invite, + payload: { + emails: [...data.emails.map((email) => email.email)], + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -70,16 +70,12 @@ const WorkspaceMembersSettingsPage = observer(() => { }); }) .catch((err) => { - captureEvent(MEMBER_TRACKER_EVENTS.invite, { - emails: [ - ...data.emails.map((email) => ({ - email: email.email, - role: getUserRole(email.role as unknown as EUserPermissions), - })), - ], - project_id: undefined, - state: "FAILED", - element: "Workspace settings member page", + captureError({ + eventName: MEMBER_TRACKER_EVENTS.invite, + payload: { + emails: [...data.emails.map((email) => email.email)], + }, + error: err, }); setToast({ type: TOAST_TYPE.ERROR, @@ -129,7 +125,12 @@ const WorkspaceMembersSettingsPage = observer(() => { />
{canPerformWorkspaceAdminActions && ( - )} diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/mobile-header-tabs.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/mobile-header-tabs.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/mobile-header-tabs.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/mobile-header-tabs.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx similarity index 97% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx index 8a97c8b05..08ad0f72f 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/sidebar.tsx @@ -4,10 +4,10 @@ import { EUserPermissionsLevel, GROUPED_WORKSPACE_SETTINGS, WORKSPACE_SETTINGS_CATEGORIES, - EUserWorkspaceRoles, EUserPermissions, WORKSPACE_SETTINGS_CATEGORY, } from "@plane/constants"; +import { EUserWorkspaceRoles } from "@plane/types"; import { SettingsSidebar } from "@/components/settings"; import { useUserPermissions } from "@/hooks/store/user"; import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper"; diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx similarity index 85% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx index a775ff3b1..c6a7d3f5a 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/[webhookId]/page.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, WORKSPACE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { IWebhook } from "@plane/types"; // ui import { TOAST_TYPE, setToast } from "@plane/ui"; @@ -14,6 +14,7 @@ import { PageHead } from "@/components/core"; import { SettingsContentWrapper } from "@/components/settings"; import { DeleteWebhookModal, WebhookDeleteSection, WebhookForm } from "@/components/web-hooks"; // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useUserPermissions, useWebhook, useWorkspace } from "@/hooks/store"; const WebhookDetailsPage = observer(() => { @@ -55,6 +56,12 @@ const WebhookDetailsPage = observer(() => { }; await updateWebhook(workspaceSlug.toString(), formData.id, payload) .then(() => { + captureSuccess({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_updated, + payload: { + webhook: formData.id, + }, + }); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -62,6 +69,13 @@ const WebhookDetailsPage = observer(() => { }); }) .catch((error) => { + captureError({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_updated, + payload: { + webhook: formData.id, + }, + error: error as Error, + }); setToast({ type: TOAST_TYPE.ERROR, title: "Error!", diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx similarity index 84% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx index 19f18717e..511ab96d9 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/webhooks/page.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane imports -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // components import { NotAuthorizedView } from "@/components/auth-screens"; @@ -15,6 +15,7 @@ import { SettingsContentWrapper, SettingsHeading } from "@/components/settings"; import { WebhookSettingsLoader } from "@/components/ui"; import { WebhooksList, CreateWebhookModal } from "@/components/web-hooks"; // hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useUserPermissions, useWebhook, useWorkspace } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; @@ -71,7 +72,12 @@ const WebhooksListPage = observer(() => { description={t("workspace_settings.settings.webhooks.description")} button={{ label: t("workspace_settings.settings.webhooks.add_webhook"), - onClick: () => setShowCreateWebhookModal(true), + onClick: () => { + captureClick({ + elementName: WORKSPACE_SETTINGS_TRACKER_ELEMENTS.HEADER_ADD_WEBHOOK_BUTTON, + }); + setShowCreateWebhookModal(true); + }, }} /> {Object.keys(webhooks).length > 0 ? ( @@ -89,7 +95,12 @@ const WebhooksListPage = observer(() => { size="md" primaryButton={{ text: t("workspace_settings.settings.webhooks.add_webhook"), - onClick: () => setShowCreateWebhookModal(true), + onClick: () => { + captureClick({ + elementName: WORKSPACE_SETTINGS_TRACKER_ELEMENTS.EMPTY_STATE_ADD_WEBHOOK_BUTTON, + }); + setShowCreateWebhookModal(true); + }, }} />
diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/activity/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/activity/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/activity/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/activity/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx similarity index 77% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx index 9a1883255..ecbc2f9aa 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/api-tokens/page.tsx @@ -4,6 +4,7 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; import useSWR from "swr"; // plane imports +import { PROFILE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // component import { APITokenService } from "@plane/services"; @@ -14,6 +15,7 @@ import { SettingsHeading } from "@/components/settings"; import { APITokenSettingsLoader } from "@/components/ui"; import { API_TOKENS_LIST } from "@/constants/fetch-keys"; // store hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useWorkspace } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // services @@ -53,7 +55,12 @@ const ApiTokensPage = observer(() => { description={t("account_settings.api_tokens.description")} button={{ label: t("workspace_settings.settings.api_tokens.add_token"), - onClick: () => setIsCreateTokenModalOpen(true), + onClick: () => { + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.HEADER_ADD_PAT_BUTTON, + }); + setIsCreateTokenModalOpen(true); + }, }} />
@@ -69,7 +76,12 @@ const ApiTokensPage = observer(() => { description={t("account_settings.api_tokens.description")} button={{ label: t("workspace_settings.settings.api_tokens.add_token"), - onClick: () => setIsCreateTokenModalOpen(true), + onClick: () => { + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.HEADER_ADD_PAT_BUTTON, + }); + setIsCreateTokenModalOpen(true); + }, }} />
@@ -81,7 +93,12 @@ const ApiTokensPage = observer(() => { size="md" primaryButton={{ text: t("workspace_settings.settings.api_tokens.add_token"), - onClick: () => setIsCreateTokenModalOpen(true), + onClick: () => { + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.EMPTY_STATE_ADD_PAT_BUTTON, + }); + setIsCreateTokenModalOpen(true); + }, }} />
diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/notifications/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/notifications/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/notifications/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/notifications/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/preferences/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/preferences/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/preferences/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/preferences/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/security/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/security/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/security/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/security/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/account/sidebar.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/sidebar.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/account/sidebar.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/account/sidebar.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/automations/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/estimates/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/estimates/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/estimates/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/estimates/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/features/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/features/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/features/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/features/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/labels/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/labels/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/labels/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/labels/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/states/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/states/page.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/states/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/states/page.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/layout.tsx similarity index 100% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/layout.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/layout.tsx diff --git a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx similarity index 85% rename from web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx rename to apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx index 65ea62701..f94ca2141 100644 --- a/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx @@ -2,6 +2,7 @@ import Image from "next/image"; import Link from "next/link"; import { useTheme } from "next-themes"; +import { PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { Button, getButtonStyling } from "@plane/ui"; import { cn } from "@plane/utils"; import { useCommandPalette } from "@/hooks/store"; @@ -27,7 +28,11 @@ const ProjectSettingsPage = () => { Learn more about projects -
diff --git a/apps/web/app/(all)/[workspaceSlug]/layout.tsx b/apps/web/app/(all)/[workspaceSlug]/layout.tsx new file mode 100644 index 000000000..7cecc697f --- /dev/null +++ b/apps/web/app/(all)/[workspaceSlug]/layout.tsx @@ -0,0 +1,12 @@ +"use client"; + +import { AppRailProvider } from "@/hooks/context/app-rail-context"; +import { WorkspaceContentWrapper } from "@/plane-web/components/workspace"; + +export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/web/app/(all)/accounts/forgot-password/layout.tsx b/apps/web/app/(all)/accounts/forgot-password/layout.tsx similarity index 100% rename from web/app/(all)/accounts/forgot-password/layout.tsx rename to apps/web/app/(all)/accounts/forgot-password/layout.tsx diff --git a/web/app/(all)/accounts/forgot-password/page.tsx b/apps/web/app/(all)/accounts/forgot-password/page.tsx similarity index 92% rename from web/app/(all)/accounts/forgot-password/page.tsx rename to apps/web/app/(all)/accounts/forgot-password/page.tsx index a7e3e7ed4..fa9ff9358 100644 --- a/web/app/(all)/accounts/forgot-password/page.tsx +++ b/apps/web/app/(all)/accounts/forgot-password/page.tsx @@ -9,14 +9,15 @@ import { Controller, useForm } from "react-hook-form"; // icons import { CircleCheck } from "lucide-react"; // plane imports -import { AUTH_TRACKER_EVENTS } from "@plane/constants"; +import { AUTH_TRACKER_ELEMENTS, AUTH_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; import { cn, checkEmailValidity } from "@plane/utils"; // helpers import { EPageTypes } from "@/helpers/authentication.helper"; // hooks -import { useEventTracker, useInstance } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useInstance } from "@/hooks/store"; import useTimer from "@/hooks/use-timer"; // wrappers import { AuthenticationWrapper } from "@/lib/wrappers"; @@ -45,8 +46,6 @@ const ForgotPasswordPage = observer(() => { const email = searchParams.get("email"); // plane hooks const { t } = useTranslation(); - // store hooks - const { captureEvent } = useEventTracker(); const { config } = useInstance(); // hooks const { resolvedTheme } = useTheme(); @@ -71,8 +70,11 @@ const ForgotPasswordPage = observer(() => { email: formData.email, }) .then(() => { - captureEvent(AUTH_TRACKER_EVENTS.forgot_password, { - state: "SUCCESS", + captureSuccess({ + eventName: AUTH_TRACKER_EVENTS.forgot_password, + payload: { + email: formData.email, + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -82,8 +84,11 @@ const ForgotPasswordPage = observer(() => { setResendCodeTimer(30); }) .catch((err) => { - captureEvent(AUTH_TRACKER_EVENTS.forgot_password, { - state: "FAILED", + captureError({ + eventName: AUTH_TRACKER_EVENTS.forgot_password, + payload: { + email: formData.email, + }, }); setToast({ type: TOAST_TYPE.ERROR, @@ -120,7 +125,7 @@ const ForgotPasswordPage = observer(() => { {t("auth.common.new_to_plane")} captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})} + data-ph-element={AUTH_TRACKER_ELEMENTS.SIGNUP_FROM_FORGOT_PASSWORD} className="font-semibold text-custom-primary-100 hover:underline" > {t("auth.common.create_account")} diff --git a/web/app/(all)/accounts/reset-password/layout.tsx b/apps/web/app/(all)/accounts/reset-password/layout.tsx similarity index 100% rename from web/app/(all)/accounts/reset-password/layout.tsx rename to apps/web/app/(all)/accounts/reset-password/layout.tsx diff --git a/web/app/(all)/accounts/reset-password/page.tsx b/apps/web/app/(all)/accounts/reset-password/page.tsx similarity index 100% rename from web/app/(all)/accounts/reset-password/page.tsx rename to apps/web/app/(all)/accounts/reset-password/page.tsx diff --git a/web/app/(all)/accounts/set-password/layout.tsx b/apps/web/app/(all)/accounts/set-password/layout.tsx similarity index 100% rename from web/app/(all)/accounts/set-password/layout.tsx rename to apps/web/app/(all)/accounts/set-password/layout.tsx diff --git a/web/app/(all)/accounts/set-password/page.tsx b/apps/web/app/(all)/accounts/set-password/page.tsx similarity index 100% rename from web/app/(all)/accounts/set-password/page.tsx rename to apps/web/app/(all)/accounts/set-password/page.tsx diff --git a/web/app/(all)/create-workspace/layout.tsx b/apps/web/app/(all)/create-workspace/layout.tsx similarity index 100% rename from web/app/(all)/create-workspace/layout.tsx rename to apps/web/app/(all)/create-workspace/layout.tsx diff --git a/web/app/(all)/create-workspace/page.tsx b/apps/web/app/(all)/create-workspace/page.tsx similarity index 100% rename from web/app/(all)/create-workspace/page.tsx rename to apps/web/app/(all)/create-workspace/page.tsx diff --git a/web/app/(all)/installations/[provider]/layout.tsx b/apps/web/app/(all)/installations/[provider]/layout.tsx similarity index 100% rename from web/app/(all)/installations/[provider]/layout.tsx rename to apps/web/app/(all)/installations/[provider]/layout.tsx diff --git a/web/app/(all)/installations/[provider]/page.tsx b/apps/web/app/(all)/installations/[provider]/page.tsx similarity index 100% rename from web/app/(all)/installations/[provider]/page.tsx rename to apps/web/app/(all)/installations/[provider]/page.tsx diff --git a/web/app/(all)/invitations/layout.tsx b/apps/web/app/(all)/invitations/layout.tsx similarity index 100% rename from web/app/(all)/invitations/layout.tsx rename to apps/web/app/(all)/invitations/layout.tsx diff --git a/web/app/(all)/invitations/page.tsx b/apps/web/app/(all)/invitations/page.tsx similarity index 89% rename from web/app/(all)/invitations/page.tsx rename to apps/web/app/(all)/invitations/page.tsx index 5e5f1958f..c3ba0e152 100644 --- a/web/app/(all)/invitations/page.tsx +++ b/apps/web/app/(all)/invitations/page.tsx @@ -9,20 +9,21 @@ import { useTheme } from "next-themes"; import useSWR, { mutate } from "swr"; import { CheckCircle2 } from "lucide-react"; // plane imports -import { ROLE, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants"; +import { ROLE, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS, GROUP_WORKSPACE_TRACKER_EVENT } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // types import type { IWorkspaceMemberInvitation } from "@plane/types"; // ui import { Button, TOAST_TYPE, setToast } from "@plane/ui"; -import { truncateText, getUserRole } from "@plane/utils"; +import { truncateText } from "@plane/utils"; // components import { EmptyState } from "@/components/common"; import { WorkspaceLogo } from "@/components/workspace/logo"; import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys"; // helpers // hooks -import { useEventTracker, useUser, useUserProfile, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess, joinEventGroup } from "@/helpers/event-tracker.helper"; +import { useUser, useUserProfile, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // services import { AuthenticationWrapper } from "@/lib/wrappers"; @@ -43,7 +44,6 @@ const UserInvitationsPage = observer(() => { const router = useAppRouter(); // store hooks const { t } = useTranslation(); - const { captureEvent, joinWorkspaceMetricGroup } = useEventTracker(); const { data: currentUser } = useUser(); const { updateUserProfile } = useUserProfile(); @@ -85,15 +85,17 @@ const UserInvitationsPage = observer(() => { const firstInviteId = invitationsRespond[0]; const invitation = invitations?.find((i) => i.id === firstInviteId); const redirectWorkspace = invitations?.find((i) => i.id === firstInviteId)?.workspace; - joinWorkspaceMetricGroup(redirectWorkspace?.id); - captureEvent(MEMBER_TRACKER_EVENTS.accept, { - member_id: invitation?.id, - // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain - role: getUserRole((invitation?.role as unknown as EUserPermissions)!), - project_id: undefined, - accepted_from: "App", - state: "SUCCESS", - element: "Workspace invitations page", + if (redirectWorkspace?.id) { + joinEventGroup(GROUP_WORKSPACE_TRACKER_EVENT, redirectWorkspace?.id, { + date: new Date().toDateString(), + workspace_id: redirectWorkspace?.id, + }); + } + captureSuccess({ + eventName: MEMBER_TRACKER_EVENTS.accept, + payload: { + member_id: invitation?.id, + }, }); updateUserProfile({ last_workspace_id: redirectWorkspace?.id }) .then(() => { @@ -111,12 +113,13 @@ const UserInvitationsPage = observer(() => { setIsJoiningWorkspaces(false); }); }) - .catch(() => { - captureEvent(MEMBER_TRACKER_EVENTS.accept, { - project_id: undefined, - accepted_from: "App", - state: "FAILED", - element: "Workspace invitations page", + .catch((err) => { + captureError({ + eventName: MEMBER_TRACKER_EVENTS.accept, + payload: { + member_id: invitationsRespond?.[0], + }, + error: err, }); setToast({ type: TOAST_TYPE.ERROR, @@ -194,6 +197,7 @@ const UserInvitationsPage = observer(() => { onClick={submitInvitations} disabled={isJoiningWorkspaces || invitationsRespond.length === 0} loading={isJoiningWorkspaces} + data-ph-element={MEMBER_TRACKER_ELEMENTS.ACCEPT_INVITATION_BUTTON} > {t("accept_and_join")} diff --git a/web/app/(all)/layout.preload.tsx b/apps/web/app/(all)/layout.preload.tsx similarity index 94% rename from web/app/(all)/layout.preload.tsx rename to apps/web/app/(all)/layout.preload.tsx index 18ca3b4b3..fb72b72a5 100644 --- a/web/app/(all)/layout.preload.tsx +++ b/apps/web/app/(all)/layout.preload.tsx @@ -18,7 +18,7 @@ export const usePreloadResources = () => { `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/workspaces/?v=${Date.now()}`, ]; - urls.forEach(url => preloadItem(url)); + urls.forEach((url) => preloadItem(url)); }, []); }; diff --git a/web/app/(all)/layout.tsx b/apps/web/app/(all)/layout.tsx similarity index 100% rename from web/app/(all)/layout.tsx rename to apps/web/app/(all)/layout.tsx diff --git a/web/app/(all)/onboarding/layout.tsx b/apps/web/app/(all)/onboarding/layout.tsx similarity index 100% rename from web/app/(all)/onboarding/layout.tsx rename to apps/web/app/(all)/onboarding/layout.tsx diff --git a/web/app/(all)/onboarding/page.tsx b/apps/web/app/(all)/onboarding/page.tsx similarity index 95% rename from web/app/(all)/onboarding/page.tsx rename to apps/web/app/(all)/onboarding/page.tsx index 078d6fefa..7e7d15a10 100644 --- a/web/app/(all)/onboarding/page.tsx +++ b/apps/web/app/(all)/onboarding/page.tsx @@ -16,7 +16,8 @@ import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys"; // helpers import { EPageTypes } from "@/helpers/authentication.helper"; // hooks -import { useUser, useWorkspace, useUserProfile, useEventTracker } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; +import { useUser, useWorkspace, useUserProfile } from "@/hooks/store"; // wrappers import { AuthenticationWrapper } from "@/lib/wrappers"; import { WorkspaceService } from "@/plane-web/services"; @@ -35,7 +36,6 @@ const OnboardingPage = observer(() => { const [step, setStep] = useState(null); const [totalSteps, setTotalSteps] = useState(null); // store hooks - const { captureEvent } = useEventTracker(); const { isLoading: userLoader, data: user, updateCurrentUser } = useUser(); const { data: profile, updateUserProfile, finishUserOnboarding } = useUserProfile(); const { workspaces, fetchWorkspaces } = useWorkspace(); @@ -73,10 +73,12 @@ const OnboardingPage = observer(() => { await finishUserOnboarding() .then(() => { - captureEvent(USER_TRACKER_EVENTS.onboarding_complete, { - email: user.email, - user_id: user.id, - status: "SUCCESS", + captureSuccess({ + eventName: USER_TRACKER_EVENTS.onboarding_complete, + payload: { + email: user.email, + user_id: user.id, + }, }); }) .catch(() => { diff --git a/web/app/(all)/profile/activity/page.tsx b/apps/web/app/(all)/profile/activity/page.tsx similarity index 100% rename from web/app/(all)/profile/activity/page.tsx rename to apps/web/app/(all)/profile/activity/page.tsx diff --git a/web/app/(all)/profile/appearance/page.tsx b/apps/web/app/(all)/profile/appearance/page.tsx similarity index 100% rename from web/app/(all)/profile/appearance/page.tsx rename to apps/web/app/(all)/profile/appearance/page.tsx diff --git a/web/app/(all)/profile/layout.tsx b/apps/web/app/(all)/profile/layout.tsx similarity index 94% rename from web/app/(all)/profile/layout.tsx rename to apps/web/app/(all)/profile/layout.tsx index 21bc6566d..21e02480d 100644 --- a/web/app/(all)/profile/layout.tsx +++ b/apps/web/app/(all)/profile/layout.tsx @@ -19,7 +19,7 @@ export default function ProfileSettingsLayout(props: Props) { <> -
+
{children}
diff --git a/web/app/(all)/profile/notifications/page.tsx b/apps/web/app/(all)/profile/notifications/page.tsx similarity index 100% rename from web/app/(all)/profile/notifications/page.tsx rename to apps/web/app/(all)/profile/notifications/page.tsx diff --git a/web/app/(all)/profile/page.tsx b/apps/web/app/(all)/profile/page.tsx similarity index 100% rename from web/app/(all)/profile/page.tsx rename to apps/web/app/(all)/profile/page.tsx diff --git a/web/app/(all)/profile/security/page.tsx b/apps/web/app/(all)/profile/security/page.tsx similarity index 100% rename from web/app/(all)/profile/security/page.tsx rename to apps/web/app/(all)/profile/security/page.tsx diff --git a/web/app/(all)/profile/sidebar.tsx b/apps/web/app/(all)/profile/sidebar.tsx similarity index 100% rename from web/app/(all)/profile/sidebar.tsx rename to apps/web/app/(all)/profile/sidebar.tsx diff --git a/web/app/(all)/sign-up/layout.tsx b/apps/web/app/(all)/sign-up/layout.tsx similarity index 98% rename from web/app/(all)/sign-up/layout.tsx rename to apps/web/app/(all)/sign-up/layout.tsx index 3ae097721..9e259b304 100644 --- a/web/app/(all)/sign-up/layout.tsx +++ b/apps/web/app/(all)/sign-up/layout.tsx @@ -5,7 +5,7 @@ export const metadata: Metadata = { robots: { index: true, follow: false, - } + }, }; export default function SignUpLayout({ children }: { children: React.ReactNode }) { diff --git a/web/app/(all)/sign-up/page.tsx b/apps/web/app/(all)/sign-up/page.tsx similarity index 91% rename from web/app/(all)/sign-up/page.tsx rename to apps/web/app/(all)/sign-up/page.tsx index 786b97384..25deaf8f1 100644 --- a/web/app/(all)/sign-up/page.tsx +++ b/apps/web/app/(all)/sign-up/page.tsx @@ -6,14 +6,12 @@ import Link from "next/link"; // ui import { useTheme } from "next-themes"; // components -import { AUTH_TRACKER_EVENTS } from "@plane/constants"; +import { AUTH_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { AuthRoot } from "@/components/account"; // constants // helpers import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper"; -// hooks -import { useEventTracker } from "@/hooks/store"; // assets import { AuthenticationWrapper } from "@/lib/wrappers"; import PlaneBackgroundPatternDark from "@/public/auth/background-pattern-dark.svg"; @@ -26,8 +24,6 @@ export type AuthType = "sign-in" | "sign-up"; const SignInPage = observer(() => { // plane hooks const { t } = useTranslation(); - // store hooks - const { captureEvent } = useEventTracker(); // hooks const { resolvedTheme } = useTheme(); @@ -54,7 +50,7 @@ const SignInPage = observer(() => { {t("auth.common.already_have_an_account")} captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_in, {})} + data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_FROM_SIGNUP} className="font-semibold text-custom-primary-100 hover:underline" > {t("auth.common.login")} diff --git a/web/app/(all)/workspace-invitations/layout.tsx b/apps/web/app/(all)/workspace-invitations/layout.tsx similarity index 100% rename from web/app/(all)/workspace-invitations/layout.tsx rename to apps/web/app/(all)/workspace-invitations/layout.tsx diff --git a/web/app/(all)/workspace-invitations/page.tsx b/apps/web/app/(all)/workspace-invitations/page.tsx similarity index 100% rename from web/app/(all)/workspace-invitations/page.tsx rename to apps/web/app/(all)/workspace-invitations/page.tsx diff --git a/web/app/(home)/layout.tsx b/apps/web/app/(home)/layout.tsx similarity index 90% rename from web/app/(home)/layout.tsx rename to apps/web/app/(home)/layout.tsx index 0ed40f86b..af7645f3c 100644 --- a/web/app/(home)/layout.tsx +++ b/apps/web/app/(home)/layout.tsx @@ -15,7 +15,5 @@ export const viewport: Viewport = { }; export default function HomeLayout({ children }: { children: React.ReactNode }) { - return ( - <>{children} - ); + return <>{children}; } diff --git a/web/app/(home)/page.tsx b/apps/web/app/(home)/page.tsx similarity index 92% rename from web/app/(home)/page.tsx rename to apps/web/app/(home)/page.tsx index 21e5c12d0..c9f0c4850 100644 --- a/web/app/(home)/page.tsx +++ b/apps/web/app/(home)/page.tsx @@ -6,7 +6,7 @@ import Link from "next/link"; // ui import { useTheme } from "next-themes"; // components -import { AUTH_TRACKER_EVENTS } from "@plane/constants"; +import { AUTH_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { AuthRoot } from "@/components/account"; import { PageHead } from "@/components/core"; @@ -14,7 +14,7 @@ import { PageHead } from "@/components/core"; // helpers import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper"; // hooks -import { useEventTracker, useInstance } from "@/hooks/store"; +import { useInstance } from "@/hooks/store"; // layouts import DefaultLayout from "@/layouts/default-layout"; // wrappers @@ -29,8 +29,6 @@ const HomePage = observer(() => { const { resolvedTheme } = useTheme(); // plane hooks const { t } = useTranslation(); - // hooks - const { captureEvent } = useEventTracker(); // store const { config } = useInstance(); // derived values @@ -63,7 +61,7 @@ const HomePage = observer(() => { {t("auth.common.new_to_plane")} captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})} + data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP} className="font-semibold text-custom-primary-100 hover:underline" > {t("auth.common.create_account")} diff --git a/web/app/error.tsx b/apps/web/app/error.tsx similarity index 100% rename from web/app/error.tsx rename to apps/web/app/error.tsx diff --git a/web/app/global-error.tsx b/apps/web/app/global-error.tsx similarity index 100% rename from web/app/global-error.tsx rename to apps/web/app/global-error.tsx diff --git a/web/app/layout.tsx b/apps/web/app/layout.tsx similarity index 99% rename from web/app/layout.tsx rename to apps/web/app/layout.tsx index fc454e54b..433dea7f9 100644 --- a/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -80,6 +80,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
+
<>; diff --git a/web/ce/components/breadcrumbs/common.tsx b/apps/web/ce/components/breadcrumbs/common.tsx similarity index 100% rename from web/ce/components/breadcrumbs/common.tsx rename to apps/web/ce/components/breadcrumbs/common.tsx diff --git a/web/ce/components/breadcrumbs/index.ts b/apps/web/ce/components/breadcrumbs/index.ts similarity index 100% rename from web/ce/components/breadcrumbs/index.ts rename to apps/web/ce/components/breadcrumbs/index.ts diff --git a/web/ce/components/breadcrumbs/project-feature.tsx b/apps/web/ce/components/breadcrumbs/project-feature.tsx similarity index 100% rename from web/ce/components/breadcrumbs/project-feature.tsx rename to apps/web/ce/components/breadcrumbs/project-feature.tsx diff --git a/web/ce/components/breadcrumbs/project.tsx b/apps/web/ce/components/breadcrumbs/project.tsx similarity index 98% rename from web/ce/components/breadcrumbs/project.tsx rename to apps/web/ce/components/breadcrumbs/project.tsx index e59f948df..00c815cdc 100644 --- a/web/ce/components/breadcrumbs/project.tsx +++ b/apps/web/ce/components/breadcrumbs/project.tsx @@ -65,6 +65,7 @@ export const ProjectBreadcrumb = observer((props: TProjectBreadcrumbProps) => { if (handleOnClick) handleOnClick(); else router.push(`/${workspaceSlug}/projects/${currentProjectDetails.id}/issues/`); }} + shouldTruncate /> } showSeparator={false} diff --git a/web/ce/components/command-palette/actions/index.ts b/apps/web/ce/components/command-palette/actions/index.ts similarity index 100% rename from web/ce/components/command-palette/actions/index.ts rename to apps/web/ce/components/command-palette/actions/index.ts diff --git a/web/ce/components/command-palette/actions/work-item-actions/change-state-list.tsx b/apps/web/ce/components/command-palette/actions/work-item-actions/change-state-list.tsx similarity index 100% rename from web/ce/components/command-palette/actions/work-item-actions/change-state-list.tsx rename to apps/web/ce/components/command-palette/actions/work-item-actions/change-state-list.tsx diff --git a/web/ce/components/command-palette/actions/work-item-actions/index.ts b/apps/web/ce/components/command-palette/actions/work-item-actions/index.ts similarity index 100% rename from web/ce/components/command-palette/actions/work-item-actions/index.ts rename to apps/web/ce/components/command-palette/actions/work-item-actions/index.ts diff --git a/web/ce/components/command-palette/helpers.tsx b/apps/web/ce/components/command-palette/helpers.tsx similarity index 100% rename from web/ce/components/command-palette/helpers.tsx rename to apps/web/ce/components/command-palette/helpers.tsx diff --git a/web/ce/components/command-palette/index.ts b/apps/web/ce/components/command-palette/index.ts similarity index 100% rename from web/ce/components/command-palette/index.ts rename to apps/web/ce/components/command-palette/index.ts diff --git a/web/ce/components/command-palette/modals/index.ts b/apps/web/ce/components/command-palette/modals/index.ts similarity index 100% rename from web/ce/components/command-palette/modals/index.ts rename to apps/web/ce/components/command-palette/modals/index.ts diff --git a/web/ce/components/command-palette/modals/issue-level.tsx b/apps/web/ce/components/command-palette/modals/issue-level.tsx similarity index 97% rename from web/ce/components/command-palette/modals/issue-level.tsx rename to apps/web/ce/components/command-palette/modals/issue-level.tsx index f88908f25..9f80727d3 100644 --- a/web/ce/components/command-palette/modals/issue-level.tsx +++ b/apps/web/ce/components/command-palette/modals/issue-level.tsx @@ -2,8 +2,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; // plane imports -import { EIssueServiceType, EIssuesStoreType } from "@plane/constants"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType, EIssuesStoreType, TIssue } from "@plane/types"; // components import { BulkDeleteIssuesModal } from "@/components/core"; import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; diff --git a/web/ce/components/command-palette/modals/project-level.tsx b/apps/web/ce/components/command-palette/modals/project-level.tsx similarity index 100% rename from web/ce/components/command-palette/modals/project-level.tsx rename to apps/web/ce/components/command-palette/modals/project-level.tsx diff --git a/web/ce/components/command-palette/modals/workspace-level.tsx b/apps/web/ce/components/command-palette/modals/workspace-level.tsx similarity index 100% rename from web/ce/components/command-palette/modals/workspace-level.tsx rename to apps/web/ce/components/command-palette/modals/workspace-level.tsx diff --git a/web/ce/components/comments/comment-block.tsx b/apps/web/ce/components/comments/comment-block.tsx similarity index 96% rename from web/ce/components/comments/comment-block.tsx rename to apps/web/ce/components/comments/comment-block.tsx index 11b98d6cb..08c5bb331 100644 --- a/web/ce/components/comments/comment-block.tsx +++ b/apps/web/ce/components/comments/comment-block.tsx @@ -6,7 +6,6 @@ import { TIssueComment } from "@plane/types"; import { Avatar, Tooltip } from "@plane/ui"; import { calculateTimeAgo, cn, getFileURL, renderFormattedDate, renderFormattedTime } from "@plane/utils"; // hooks -// import { useMember } from "@/hooks/store"; type TCommentBlock = { @@ -18,13 +17,17 @@ type TCommentBlock = { export const CommentBlock: FC = observer((props) => { const { comment, ends, quickActions, children } = props; + // refs const commentBlockRef = useRef(null); // store hooks const { getUserDetails } = useMember(); - const { t } = useTranslation(); + // derived values const userDetails = getUserDetails(comment?.actor); + // translation + const { t } = useTranslation(); + + if (!comment || !userDetails) return null; - if (!comment || !userDetails) return <>; return (
{ + const { header } = props; + // store hooks + const { sidebarCollapsed } = useAppTheme(); + + return ( + <> + {sidebarCollapsed && } +
{header}
+ + ); +}; diff --git a/apps/web/ce/components/common/index.ts b/apps/web/ce/components/common/index.ts new file mode 100644 index 000000000..38406d4cc --- /dev/null +++ b/apps/web/ce/components/common/index.ts @@ -0,0 +1,2 @@ +export * from "./subscription"; +export * from "./extended-app-header"; diff --git a/apps/web/ce/components/common/subscription/index.ts b/apps/web/ce/components/common/subscription/index.ts new file mode 100644 index 000000000..cfd65903d --- /dev/null +++ b/apps/web/ce/components/common/subscription/index.ts @@ -0,0 +1 @@ +export * from "./subscription-pill"; diff --git a/web/ce/components/common/subscription/subscription-pill.tsx b/apps/web/ce/components/common/subscription/subscription-pill.tsx similarity index 100% rename from web/ce/components/common/subscription/subscription-pill.tsx rename to apps/web/ce/components/common/subscription/subscription-pill.tsx diff --git a/web/ce/components/cycles/analytics-sidebar/index.ts b/apps/web/ce/components/cycles/active-cycle/index.ts similarity index 100% rename from web/ce/components/cycles/analytics-sidebar/index.ts rename to apps/web/ce/components/cycles/active-cycle/index.ts diff --git a/web/ce/components/cycles/active-cycle/root.tsx b/apps/web/ce/components/cycles/active-cycle/root.tsx similarity index 100% rename from web/ce/components/cycles/active-cycle/root.tsx rename to apps/web/ce/components/cycles/active-cycle/root.tsx diff --git a/web/ce/components/cycles/additional-actions.tsx b/apps/web/ce/components/cycles/additional-actions.tsx similarity index 100% rename from web/ce/components/cycles/additional-actions.tsx rename to apps/web/ce/components/cycles/additional-actions.tsx diff --git a/web/ce/components/cycles/analytics-sidebar/base.tsx b/apps/web/ce/components/cycles/analytics-sidebar/base.tsx similarity index 100% rename from web/ce/components/cycles/analytics-sidebar/base.tsx rename to apps/web/ce/components/cycles/analytics-sidebar/base.tsx diff --git a/web/ce/components/de-dupe/duplicate-modal/index.ts b/apps/web/ce/components/cycles/analytics-sidebar/index.ts similarity index 100% rename from web/ce/components/de-dupe/duplicate-modal/index.ts rename to apps/web/ce/components/cycles/analytics-sidebar/index.ts diff --git a/web/ce/components/cycles/analytics-sidebar/root.tsx b/apps/web/ce/components/cycles/analytics-sidebar/root.tsx similarity index 100% rename from web/ce/components/cycles/analytics-sidebar/root.tsx rename to apps/web/ce/components/cycles/analytics-sidebar/root.tsx diff --git a/web/ce/components/cycles/end-cycle/index.ts b/apps/web/ce/components/cycles/end-cycle/index.ts similarity index 100% rename from web/ce/components/cycles/end-cycle/index.ts rename to apps/web/ce/components/cycles/end-cycle/index.ts diff --git a/web/ce/components/cycles/end-cycle/modal.tsx b/apps/web/ce/components/cycles/end-cycle/modal.tsx similarity index 100% rename from web/ce/components/cycles/end-cycle/modal.tsx rename to apps/web/ce/components/cycles/end-cycle/modal.tsx diff --git a/web/ce/components/cycles/end-cycle/use-end-cycle.tsx b/apps/web/ce/components/cycles/end-cycle/use-end-cycle.tsx similarity index 100% rename from web/ce/components/cycles/end-cycle/use-end-cycle.tsx rename to apps/web/ce/components/cycles/end-cycle/use-end-cycle.tsx diff --git a/web/ce/components/cycles/index.ts b/apps/web/ce/components/cycles/index.ts similarity index 100% rename from web/ce/components/cycles/index.ts rename to apps/web/ce/components/cycles/index.ts diff --git a/web/ce/components/de-dupe/de-dupe-button.tsx b/apps/web/ce/components/de-dupe/de-dupe-button.tsx similarity index 100% rename from web/ce/components/de-dupe/de-dupe-button.tsx rename to apps/web/ce/components/de-dupe/de-dupe-button.tsx diff --git a/web/ce/components/de-dupe/duplicate-popover/index.ts b/apps/web/ce/components/de-dupe/duplicate-modal/index.ts similarity index 100% rename from web/ce/components/de-dupe/duplicate-popover/index.ts rename to apps/web/ce/components/de-dupe/duplicate-modal/index.ts diff --git a/web/ce/components/de-dupe/duplicate-modal/root.tsx b/apps/web/ce/components/de-dupe/duplicate-modal/root.tsx similarity index 100% rename from web/ce/components/de-dupe/duplicate-modal/root.tsx rename to apps/web/ce/components/de-dupe/duplicate-modal/root.tsx diff --git a/web/ce/components/editor/embeds/mentions/index.ts b/apps/web/ce/components/de-dupe/duplicate-popover/index.ts similarity index 100% rename from web/ce/components/editor/embeds/mentions/index.ts rename to apps/web/ce/components/de-dupe/duplicate-popover/index.ts diff --git a/web/ce/components/de-dupe/duplicate-popover/root.tsx b/apps/web/ce/components/de-dupe/duplicate-popover/root.tsx similarity index 100% rename from web/ce/components/de-dupe/duplicate-popover/root.tsx rename to apps/web/ce/components/de-dupe/duplicate-popover/root.tsx diff --git a/web/ce/components/de-dupe/index.ts b/apps/web/ce/components/de-dupe/index.ts similarity index 100% rename from web/ce/components/de-dupe/index.ts rename to apps/web/ce/components/de-dupe/index.ts diff --git a/web/ce/components/de-dupe/issue-block/button-label.tsx b/apps/web/ce/components/de-dupe/issue-block/button-label.tsx similarity index 100% rename from web/ce/components/de-dupe/issue-block/button-label.tsx rename to apps/web/ce/components/de-dupe/issue-block/button-label.tsx diff --git a/web/ce/components/de-dupe/issue-block/index.ts b/apps/web/ce/components/de-dupe/issue-block/index.ts similarity index 100% rename from web/ce/components/de-dupe/issue-block/index.ts rename to apps/web/ce/components/de-dupe/issue-block/index.ts diff --git a/web/ce/components/editor/embeds/index.ts b/apps/web/ce/components/editor/embeds/index.ts similarity index 100% rename from web/ce/components/editor/embeds/index.ts rename to apps/web/ce/components/editor/embeds/index.ts diff --git a/web/ce/components/issues/issue-details/issue-properties-activity/index.ts b/apps/web/ce/components/editor/embeds/mentions/index.ts similarity index 100% rename from web/ce/components/issues/issue-details/issue-properties-activity/index.ts rename to apps/web/ce/components/editor/embeds/mentions/index.ts diff --git a/web/ce/components/editor/embeds/mentions/root.tsx b/apps/web/ce/components/editor/embeds/mentions/root.tsx similarity index 100% rename from web/ce/components/editor/embeds/mentions/root.tsx rename to apps/web/ce/components/editor/embeds/mentions/root.tsx diff --git a/web/ce/components/editor/index.ts b/apps/web/ce/components/editor/index.ts similarity index 100% rename from web/ce/components/editor/index.ts rename to apps/web/ce/components/editor/index.ts diff --git a/web/ce/components/epics/epic-modal/index.ts b/apps/web/ce/components/epics/epic-modal/index.ts similarity index 100% rename from web/ce/components/epics/epic-modal/index.ts rename to apps/web/ce/components/epics/epic-modal/index.ts diff --git a/web/ce/components/epics/epic-modal/modal.tsx b/apps/web/ce/components/epics/epic-modal/modal.tsx similarity index 100% rename from web/ce/components/epics/epic-modal/modal.tsx rename to apps/web/ce/components/epics/epic-modal/modal.tsx diff --git a/web/ce/components/epics/index.ts b/apps/web/ce/components/epics/index.ts similarity index 100% rename from web/ce/components/epics/index.ts rename to apps/web/ce/components/epics/index.ts diff --git a/web/ce/components/estimates/estimate-list-item-buttons.tsx b/apps/web/ce/components/estimates/estimate-list-item-buttons.tsx similarity index 75% rename from web/ce/components/estimates/estimate-list-item-buttons.tsx rename to apps/web/ce/components/estimates/estimate-list-item-buttons.tsx index 72acb4dfc..58bae9b74 100644 --- a/web/ce/components/estimates/estimate-list-item-buttons.tsx +++ b/apps/web/ce/components/estimates/estimate-list-item-buttons.tsx @@ -1,6 +1,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { Pen, Trash } from "lucide-react"; +import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { Tooltip } from "@plane/ui"; // components import { ProIcon } from "@/components/common"; @@ -29,13 +30,17 @@ export const EstimateListItemButtons: FC = observer((props) = } position="top" > - diff --git a/web/ce/components/estimates/helper.tsx b/apps/web/ce/components/estimates/helper.tsx similarity index 68% rename from web/ce/components/estimates/helper.tsx rename to apps/web/ce/components/estimates/helper.tsx index 4d2196527..5a1d9eaf4 100644 --- a/web/ce/components/estimates/helper.tsx +++ b/apps/web/ce/components/estimates/helper.tsx @@ -1,5 +1,4 @@ -import { TEstimateSystemKeys } from "@plane/types"; -import { EEstimateSystem } from "@plane/types/src/enums"; +import { TEstimateSystemKeys, EEstimateSystem } from "@plane/types"; export const isEstimateSystemEnabled = (key: TEstimateSystemKeys) => { switch (key) { diff --git a/web/ce/components/estimates/index.ts b/apps/web/ce/components/estimates/index.ts similarity index 100% rename from web/ce/components/estimates/index.ts rename to apps/web/ce/components/estimates/index.ts diff --git a/web/ce/components/estimates/inputs/index.ts b/apps/web/ce/components/estimates/inputs/index.ts similarity index 100% rename from web/ce/components/estimates/inputs/index.ts rename to apps/web/ce/components/estimates/inputs/index.ts diff --git a/web/ce/components/estimates/inputs/time-input.tsx b/apps/web/ce/components/estimates/inputs/time-input.tsx similarity index 100% rename from web/ce/components/estimates/inputs/time-input.tsx rename to apps/web/ce/components/estimates/inputs/time-input.tsx diff --git a/web/ce/components/estimates/points/delete.tsx b/apps/web/ce/components/estimates/points/delete.tsx similarity index 100% rename from web/ce/components/estimates/points/delete.tsx rename to apps/web/ce/components/estimates/points/delete.tsx diff --git a/web/ce/components/estimates/points/index.ts b/apps/web/ce/components/estimates/points/index.ts similarity index 100% rename from web/ce/components/estimates/points/index.ts rename to apps/web/ce/components/estimates/points/index.ts diff --git a/web/ce/components/estimates/update/index.ts b/apps/web/ce/components/estimates/update/index.ts similarity index 100% rename from web/ce/components/estimates/update/index.ts rename to apps/web/ce/components/estimates/update/index.ts diff --git a/web/ce/components/estimates/update/modal.tsx b/apps/web/ce/components/estimates/update/modal.tsx similarity index 100% rename from web/ce/components/estimates/update/modal.tsx rename to apps/web/ce/components/estimates/update/modal.tsx diff --git a/web/core/components/gantt-chart/blocks/block-row-list.tsx b/apps/web/ce/components/gantt-chart/blocks/block-row-list.tsx similarity index 93% rename from web/core/components/gantt-chart/blocks/block-row-list.tsx rename to apps/web/ce/components/gantt-chart/blocks/block-row-list.tsx index 0be3bead7..ec7e52fd1 100644 --- a/web/core/components/gantt-chart/blocks/block-row-list.tsx +++ b/apps/web/ce/components/gantt-chart/blocks/block-row-list.tsx @@ -3,10 +3,10 @@ import { FC } from "react"; import type { IBlockUpdateData, IGanttBlock } from "@plane/types"; import RenderIfVisible from "@/components/core/render-if-visible-HOC"; // hooks +import { BlockRow } from "@/components/gantt-chart/blocks/block-row"; +import { BLOCK_HEIGHT } from "@/components/gantt-chart/constants"; import { TSelectionHelper } from "@/hooks/use-multiple-select"; // types -import { BLOCK_HEIGHT } from "../constants"; -import { BlockRow } from "./block-row"; export type GanttChartBlocksProps = { blockIds: string[]; diff --git a/web/core/components/gantt-chart/blocks/blocks-list.tsx b/apps/web/ce/components/gantt-chart/blocks/blocks-list.tsx similarity index 96% rename from web/core/components/gantt-chart/blocks/blocks-list.tsx rename to apps/web/ce/components/gantt-chart/blocks/blocks-list.tsx index 154a72d9f..0c8f2a7c0 100644 --- a/web/core/components/gantt-chart/blocks/blocks-list.tsx +++ b/apps/web/ce/components/gantt-chart/blocks/blocks-list.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; // import type { IBlockUpdateDependencyData } from "@plane/types"; -import { GanttChartBlock } from "./block"; +import { GanttChartBlock } from "@/components/gantt-chart/blocks/block"; export type GanttChartBlocksProps = { blockIds: string[]; diff --git a/web/ce/components/gantt-chart/dependency/blockDraggables/index.ts b/apps/web/ce/components/gantt-chart/dependency/blockDraggables/index.ts similarity index 100% rename from web/ce/components/gantt-chart/dependency/blockDraggables/index.ts rename to apps/web/ce/components/gantt-chart/dependency/blockDraggables/index.ts diff --git a/web/ce/components/gantt-chart/dependency/blockDraggables/left-draggable.tsx b/apps/web/ce/components/gantt-chart/dependency/blockDraggables/left-draggable.tsx similarity index 100% rename from web/ce/components/gantt-chart/dependency/blockDraggables/left-draggable.tsx rename to apps/web/ce/components/gantt-chart/dependency/blockDraggables/left-draggable.tsx diff --git a/web/ce/components/gantt-chart/dependency/blockDraggables/right-draggable.tsx b/apps/web/ce/components/gantt-chart/dependency/blockDraggables/right-draggable.tsx similarity index 100% rename from web/ce/components/gantt-chart/dependency/blockDraggables/right-draggable.tsx rename to apps/web/ce/components/gantt-chart/dependency/blockDraggables/right-draggable.tsx diff --git a/web/ce/components/gantt-chart/dependency/dependency-paths.tsx b/apps/web/ce/components/gantt-chart/dependency/dependency-paths.tsx similarity index 100% rename from web/ce/components/gantt-chart/dependency/dependency-paths.tsx rename to apps/web/ce/components/gantt-chart/dependency/dependency-paths.tsx diff --git a/web/ce/components/gantt-chart/dependency/draggable-dependency-path.tsx b/apps/web/ce/components/gantt-chart/dependency/draggable-dependency-path.tsx similarity index 100% rename from web/ce/components/gantt-chart/dependency/draggable-dependency-path.tsx rename to apps/web/ce/components/gantt-chart/dependency/draggable-dependency-path.tsx diff --git a/web/ce/components/gantt-chart/dependency/index.ts b/apps/web/ce/components/gantt-chart/dependency/index.ts similarity index 100% rename from web/ce/components/gantt-chart/dependency/index.ts rename to apps/web/ce/components/gantt-chart/dependency/index.ts diff --git a/web/ce/components/gantt-chart/index.ts b/apps/web/ce/components/gantt-chart/index.ts similarity index 100% rename from web/ce/components/gantt-chart/index.ts rename to apps/web/ce/components/gantt-chart/index.ts diff --git a/web/ce/components/global/index.ts b/apps/web/ce/components/global/index.ts similarity index 100% rename from web/ce/components/global/index.ts rename to apps/web/ce/components/global/index.ts diff --git a/web/ce/components/global/product-updates-header.tsx b/apps/web/ce/components/global/product-updates-header.tsx similarity index 98% rename from web/ce/components/global/product-updates-header.tsx rename to apps/web/ce/components/global/product-updates-header.tsx index 8a2a94c5b..776d9667d 100644 --- a/web/ce/components/global/product-updates-header.tsx +++ b/apps/web/ce/components/global/product-updates-header.tsx @@ -14,7 +14,7 @@ export const ProductUpdatesHeader = observer(() => {
{t("whats_new")}
-
{ const { t } = useTranslation(); - return {t("version")}: v{packageJson.version}; + return ( + + {t("version")}: v{packageJson.version} + + ); }; diff --git a/web/ce/components/home/header.tsx b/apps/web/ce/components/home/header.tsx similarity index 100% rename from web/ce/components/home/header.tsx rename to apps/web/ce/components/home/header.tsx diff --git a/web/ce/components/home/index.ts b/apps/web/ce/components/home/index.ts similarity index 100% rename from web/ce/components/home/index.ts rename to apps/web/ce/components/home/index.ts diff --git a/web/ce/components/home/peek-overviews.tsx b/apps/web/ce/components/home/peek-overviews.tsx similarity index 100% rename from web/ce/components/home/peek-overviews.tsx rename to apps/web/ce/components/home/peek-overviews.tsx diff --git a/web/ce/components/inbox/source-pill.tsx b/apps/web/ce/components/inbox/source-pill.tsx similarity index 71% rename from web/ce/components/inbox/source-pill.tsx rename to apps/web/ce/components/inbox/source-pill.tsx index 6e42f6880..07e721780 100644 --- a/web/ce/components/inbox/source-pill.tsx +++ b/apps/web/ce/components/inbox/source-pill.tsx @@ -1,4 +1,4 @@ -import { EInboxIssueSource } from "@plane/constants"; +import { EInboxIssueSource } from "@plane/types"; export type TInboxSourcePill = { source: EInboxIssueSource; diff --git a/web/ce/components/instance/index.ts b/apps/web/ce/components/instance/index.ts similarity index 100% rename from web/ce/components/instance/index.ts rename to apps/web/ce/components/instance/index.ts diff --git a/web/ce/components/instance/maintenance-message.tsx b/apps/web/ce/components/instance/maintenance-message.tsx similarity index 100% rename from web/ce/components/instance/maintenance-message.tsx rename to apps/web/ce/components/instance/maintenance-message.tsx diff --git a/web/ce/components/issues/quick-add/index.ts b/apps/web/ce/components/issues/bulk-operations/index.ts similarity index 100% rename from web/ce/components/issues/quick-add/index.ts rename to apps/web/ce/components/issues/bulk-operations/index.ts diff --git a/web/ce/components/issues/bulk-operations/root.tsx b/apps/web/ce/components/issues/bulk-operations/root.tsx similarity index 100% rename from web/ce/components/issues/bulk-operations/root.tsx rename to apps/web/ce/components/issues/bulk-operations/root.tsx diff --git a/web/ce/components/issues/filters/applied-filters/index.ts b/apps/web/ce/components/issues/filters/applied-filters/index.ts similarity index 100% rename from web/ce/components/issues/filters/applied-filters/index.ts rename to apps/web/ce/components/issues/filters/applied-filters/index.ts diff --git a/web/ce/components/issues/filters/applied-filters/issue-types.tsx b/apps/web/ce/components/issues/filters/applied-filters/issue-types.tsx similarity index 100% rename from web/ce/components/issues/filters/applied-filters/issue-types.tsx rename to apps/web/ce/components/issues/filters/applied-filters/issue-types.tsx diff --git a/web/ce/components/issues/filters/index.ts b/apps/web/ce/components/issues/filters/index.ts similarity index 100% rename from web/ce/components/issues/filters/index.ts rename to apps/web/ce/components/issues/filters/index.ts diff --git a/web/ce/components/issues/filters/issue-types.tsx b/apps/web/ce/components/issues/filters/issue-types.tsx similarity index 100% rename from web/ce/components/issues/filters/issue-types.tsx rename to apps/web/ce/components/issues/filters/issue-types.tsx diff --git a/web/ce/components/issues/filters/team-project.tsx b/apps/web/ce/components/issues/filters/team-project.tsx similarity index 100% rename from web/ce/components/issues/filters/team-project.tsx rename to apps/web/ce/components/issues/filters/team-project.tsx diff --git a/web/ce/components/issues/header.tsx b/apps/web/ce/components/issues/header.tsx similarity index 93% rename from web/ce/components/issues/header.tsx rename to apps/web/ce/components/issues/header.tsx index ed283fef5..cad3d0f22 100644 --- a/web/ce/components/issues/header.tsx +++ b/apps/web/ce/components/issues/header.tsx @@ -4,17 +4,17 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // icons import { Circle, ExternalLink } from "lucide-react"; +// plane imports import { - EIssuesStoreType, - EProjectFeatureKey, EUserPermissions, EUserPermissionsLevel, SPACE_BASE_PATH, SPACE_BASE_URL, + WORK_ITEM_TRACKER_ELEMENTS, + EProjectFeatureKey, } from "@plane/constants"; -// plane constants import { useTranslation } from "@plane/i18n"; -// ui +import { EIssuesStoreType } from "@plane/types"; import { Breadcrumbs, Button, Tooltip, Header } from "@plane/ui"; // components import { CountChip } from "@/components/common"; @@ -22,7 +22,7 @@ import { CountChip } from "@/components/common"; import HeaderFilters from "@/components/issues/filters"; // helpers // hooks -import { useEventTracker, useProject, useCommandPalette, useUserPermissions } from "@/hooks/store"; +import { useProject, useCommandPalette, useUserPermissions } from "@/hooks/store"; import { useIssues } from "@/hooks/store/use-issues"; import { useAppRouter } from "@/hooks/use-app-router"; import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -43,7 +43,6 @@ export const IssuesHeader = observer(() => { const { currentProjectDetails, loader } = useProject(); const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); const { isMobile } = usePlatformOS(); @@ -105,9 +104,9 @@ export const IssuesHeader = observer(() => { {canUserCreateIssue ? (
diff --git a/web/ce/components/workspace/billing/comparison/root.tsx b/apps/web/ce/components/workspace/billing/comparison/root.tsx similarity index 93% rename from web/ce/components/workspace/billing/comparison/root.tsx rename to apps/web/ce/components/workspace/billing/comparison/root.tsx index 469b9806d..cf8f3dec5 100644 --- a/web/ce/components/workspace/billing/comparison/root.tsx +++ b/apps/web/ce/components/workspace/billing/comparison/root.tsx @@ -1,7 +1,6 @@ import { observer } from "mobx-react"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; -import { TBillingFrequency } from "@plane/types"; +import { EProductSubscriptionEnum, TBillingFrequency } from "@plane/types"; // components import { PlansComparisonBase, shouldRenderPlanDetail } from "@/components/workspace/billing/comparison/base"; import { PLANE_PLANS, TPlanePlans } from "@/constants/plans"; diff --git a/web/ce/components/workspace/billing/index.ts b/apps/web/ce/components/workspace/billing/index.ts similarity index 100% rename from web/ce/components/workspace/billing/index.ts rename to apps/web/ce/components/workspace/billing/index.ts diff --git a/web/ce/components/workspace/billing/root.tsx b/apps/web/ce/components/workspace/billing/root.tsx similarity index 91% rename from web/ce/components/workspace/billing/root.tsx rename to apps/web/ce/components/workspace/billing/root.tsx index c61b19643..c089a4905 100644 --- a/web/ce/components/workspace/billing/root.tsx +++ b/apps/web/ce/components/workspace/billing/root.tsx @@ -1,17 +1,13 @@ import { useState } from "react"; import { observer } from "mobx-react"; // plane imports -import { - DEFAULT_PRODUCT_BILLING_FREQUENCY, - EProductSubscriptionEnum, - SUBSCRIPTION_WITH_BILLING_FREQUENCY, -} from "@plane/constants"; +import { DEFAULT_PRODUCT_BILLING_FREQUENCY, SUBSCRIPTION_WITH_BILLING_FREQUENCY } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TBillingFrequency, TProductBillingFrequency } from "@plane/types"; +import { EProductSubscriptionEnum, TBillingFrequency, TProductBillingFrequency } from "@plane/types"; +import { getSubscriptionTextColor } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { SettingsHeading } from "@/components/settings"; -import { getSubscriptionTextColor } from "@/components/workspace/billing/subscription"; // local imports import { PlansComparison } from "./comparison/root"; diff --git a/apps/web/ce/components/workspace/content-wrapper.tsx b/apps/web/ce/components/workspace/content-wrapper.tsx new file mode 100644 index 000000000..79a74f56f --- /dev/null +++ b/apps/web/ce/components/workspace/content-wrapper.tsx @@ -0,0 +1,9 @@ +"use client"; +import React from "react"; +import { observer } from "mobx-react"; + +export const WorkspaceContentWrapper = observer(({ children }: { children: React.ReactNode }) => ( +
+
{children}
+
+)); diff --git a/web/ce/components/workspace/delete-workspace-modal.tsx b/apps/web/ce/components/workspace/delete-workspace-modal.tsx similarity index 100% rename from web/ce/components/workspace/delete-workspace-modal.tsx rename to apps/web/ce/components/workspace/delete-workspace-modal.tsx diff --git a/web/ce/components/workspace/delete-workspace-section.tsx b/apps/web/ce/components/workspace/delete-workspace-section.tsx similarity index 87% rename from web/ce/components/workspace/delete-workspace-section.tsx rename to apps/web/ce/components/workspace/delete-workspace-section.tsx index 00fb7b878..33c85e5a9 100644 --- a/web/ce/components/workspace/delete-workspace-section.tsx +++ b/apps/web/ce/components/workspace/delete-workspace-section.tsx @@ -2,6 +2,7 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; import { ChevronDown, ChevronUp } from "lucide-react"; // types +import { WORKSPACE_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWorkspace } from "@plane/types"; // ui @@ -48,7 +49,11 @@ export const DeleteWorkspaceSection: FC = observer((props) => {t("workspace_settings.settings.general.delete_workspace_description")}
-
diff --git a/web/ce/components/workspace/edition-badge.tsx b/apps/web/ce/components/workspace/edition-badge.tsx similarity index 100% rename from web/ce/components/workspace/edition-badge.tsx rename to apps/web/ce/components/workspace/edition-badge.tsx diff --git a/web/ee/components/workspace/index.ts b/apps/web/ce/components/workspace/index.ts similarity index 63% rename from web/ee/components/workspace/index.ts rename to apps/web/ce/components/workspace/index.ts index b0b8ffd3a..489ef6352 100644 --- a/web/ee/components/workspace/index.ts +++ b/apps/web/ce/components/workspace/index.ts @@ -3,3 +3,6 @@ export * from "./upgrade-badge"; export * from "./billing"; export * from "./delete-workspace-section"; export * from "./sidebar"; +export * from "./members"; +export * from "./content-wrapper"; +export * from "./app-switcher"; diff --git a/web/ce/components/workspace/members/index.ts b/apps/web/ce/components/workspace/members/index.ts similarity index 100% rename from web/ce/components/workspace/members/index.ts rename to apps/web/ce/components/workspace/members/index.ts diff --git a/web/ce/components/workspace/members/invite-modal.tsx b/apps/web/ce/components/workspace/members/invite-modal.tsx similarity index 100% rename from web/ce/components/workspace/members/invite-modal.tsx rename to apps/web/ce/components/workspace/members/invite-modal.tsx diff --git a/web/ce/components/workspace/settings/useMemberColumns.tsx b/apps/web/ce/components/workspace/settings/useMemberColumns.tsx similarity index 100% rename from web/ce/components/workspace/settings/useMemberColumns.tsx rename to apps/web/ce/components/workspace/settings/useMemberColumns.tsx diff --git a/web/ce/components/workspace/sidebar/app-search.tsx b/apps/web/ce/components/workspace/sidebar/app-search.tsx similarity index 58% rename from web/ce/components/workspace/sidebar/app-search.tsx rename to apps/web/ce/components/workspace/sidebar/app-search.tsx index 01d7f0147..6b8a94f6b 100644 --- a/web/ce/components/workspace/sidebar/app-search.tsx +++ b/apps/web/ce/components/workspace/sidebar/app-search.tsx @@ -2,14 +2,11 @@ import { observer } from "mobx-react"; import { Search } from "lucide-react"; // plane imports import { useTranslation } from "@plane/i18n"; -// helpers -import { cn } from "@plane/utils"; // hooks -import { useAppTheme, useCommandPalette } from "@/hooks/store"; +import { useCommandPalette } from "@/hooks/store"; export const AppSearch = observer(() => { // store hooks - const { sidebarCollapsed } = useAppTheme(); const { toggleCommandPaletteModal } = useCommandPalette(); // translation const { t } = useTranslation(); @@ -17,12 +14,7 @@ export const AppSearch = observer(() => { return (
-
} multiple diff --git a/web/core/components/analytics/select/select-x-axis.tsx b/apps/web/core/components/analytics/select/select-x-axis.tsx similarity index 94% rename from web/core/components/analytics/select/select-x-axis.tsx rename to apps/web/core/components/analytics/select/select-x-axis.tsx index a655c9a13..1be296ff3 100644 --- a/web/core/components/analytics/select/select-x-axis.tsx +++ b/apps/web/core/components/analytics/select/select-x-axis.tsx @@ -1,6 +1,6 @@ "use client"; // plane package imports -import { ChartXAxisProperty } from "@plane/constants"; +import { ChartXAxisProperty } from "@plane/types"; import { CustomSelect } from "@plane/ui"; type Props = { diff --git a/web/core/components/analytics/select/select-y-axis.tsx b/apps/web/core/components/analytics/select/select-y-axis.tsx similarity index 94% rename from web/core/components/analytics/select/select-y-axis.tsx rename to apps/web/core/components/analytics/select/select-y-axis.tsx index 931b1976d..4982f8fb0 100644 --- a/web/core/components/analytics/select/select-y-axis.tsx +++ b/apps/web/core/components/analytics/select/select-y-axis.tsx @@ -3,7 +3,8 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Briefcase } from "lucide-react"; -import { ChartYAxisMetric, EEstimateSystem } from "@plane/constants"; +import { EEstimateSystem } from "@plane/constants"; +import { ChartYAxisMetric } from "@plane/types"; // plane package imports import { CustomSelect } from "@plane/ui"; // hooks diff --git a/web/core/components/analytics/total-insights.tsx b/apps/web/core/components/analytics/total-insights.tsx similarity index 98% rename from web/core/components/analytics/total-insights.tsx rename to apps/web/core/components/analytics/total-insights.tsx index e85c9c68a..258ac11e1 100644 --- a/web/core/components/analytics/total-insights.tsx +++ b/apps/web/core/components/analytics/total-insights.tsx @@ -1,5 +1,5 @@ // plane package imports -import { observer } from "mobx-react-lite"; +import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; import { IInsightField, ANALYTICS_INSIGHTS_FIELDS } from "@plane/constants"; diff --git a/web/core/components/analytics/trend-piece.tsx b/apps/web/core/components/analytics/trend-piece.tsx similarity index 100% rename from web/core/components/analytics/trend-piece.tsx rename to apps/web/core/components/analytics/trend-piece.tsx diff --git a/web/core/components/analytics/work-items/created-vs-resolved.tsx b/apps/web/core/components/analytics/work-items/created-vs-resolved.tsx similarity index 100% rename from web/core/components/analytics/work-items/created-vs-resolved.tsx rename to apps/web/core/components/analytics/work-items/created-vs-resolved.tsx diff --git a/web/core/components/analytics/work-items/customized-insights.tsx b/apps/web/core/components/analytics/work-items/customized-insights.tsx similarity index 92% rename from web/core/components/analytics/work-items/customized-insights.tsx rename to apps/web/core/components/analytics/work-items/customized-insights.tsx index 657465822..bafd0d8ef 100644 --- a/web/core/components/analytics/work-items/customized-insights.tsx +++ b/apps/web/core/components/analytics/work-items/customized-insights.tsx @@ -2,9 +2,8 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { useForm } from "react-hook-form"; // plane package imports -import { ChartXAxisProperty, ChartYAxisMetric } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IAnalyticsParams } from "@plane/types"; +import { ChartXAxisProperty, ChartYAxisMetric, IAnalyticsParams } from "@plane/types"; import { cn } from "@plane/utils"; // plane web components import AnalyticsSectionWrapper from "../analytics-section-wrapper"; diff --git a/web/core/components/editor/embeds/mentions/index.ts b/apps/web/core/components/analytics/work-items/index.ts similarity index 100% rename from web/core/components/editor/embeds/mentions/index.ts rename to apps/web/core/components/analytics/work-items/index.ts diff --git a/web/core/components/analytics/work-items/modal/content.tsx b/apps/web/core/components/analytics/work-items/modal/content.tsx similarity index 100% rename from web/core/components/analytics/work-items/modal/content.tsx rename to apps/web/core/components/analytics/work-items/modal/content.tsx diff --git a/web/core/components/analytics/work-items/modal/header.tsx b/apps/web/core/components/analytics/work-items/modal/header.tsx similarity index 100% rename from web/core/components/analytics/work-items/modal/header.tsx rename to apps/web/core/components/analytics/work-items/modal/header.tsx diff --git a/apps/web/core/components/analytics/work-items/modal/index.tsx b/apps/web/core/components/analytics/work-items/modal/index.tsx new file mode 100644 index 000000000..06d09aa1e --- /dev/null +++ b/apps/web/core/components/analytics/work-items/modal/index.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from "react"; +import { observer } from "mobx-react"; +// plane package imports +import { createPortal } from "react-dom"; +import { ICycle, IModule, IProject } from "@plane/types"; +import { cn } from "@plane/utils"; +import { useAnalytics } from "@/hooks/store"; +// plane web components +import { WorkItemsModalMainContent } from "./content"; +import { WorkItemsModalHeader } from "./header"; + +type Props = { + isOpen: boolean; + onClose: () => void; + projectDetails?: IProject | undefined; + cycleDetails?: ICycle | undefined; + moduleDetails?: IModule | undefined; + isEpic?: boolean; +}; + +export const WorkItemsModal: React.FC = observer((props) => { + const { isOpen, onClose, projectDetails, moduleDetails, cycleDetails, isEpic } = props; + const { updateIsEpic } = useAnalytics(); + const [fullScreen, setFullScreen] = useState(false); + + const handleClose = () => { + setFullScreen(false); + onClose(); + }; + + useEffect(() => { + updateIsEpic(isEpic ?? false); + }, [isEpic, updateIsEpic]); + + const portalContainer = document.getElementById("full-screen-portal") as HTMLElement; + + if (!isOpen) return null; + + const content = ( +
+
+
+ + +
+
+
+ ); + + return fullScreen && portalContainer ? createPortal(content, portalContainer) : content; +}); diff --git a/web/core/components/analytics/work-items/priority-chart.tsx b/apps/web/core/components/analytics/work-items/priority-chart.tsx similarity index 96% rename from web/core/components/analytics/work-items/priority-chart.tsx rename to apps/web/core/components/analytics/work-items/priority-chart.tsx index 5c0069978..ac7704628 100644 --- a/web/core/components/analytics/work-items/priority-chart.tsx +++ b/apps/web/core/components/analytics/work-items/priority-chart.tsx @@ -1,6 +1,5 @@ import { useMemo } from "react"; -import { ColumnDef, RowData, Table } from "@tanstack/react-table"; -import { mkConfig } from "export-to-csv"; +import { ColumnDef, Row, RowData, Table } from "@tanstack/react-table"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { useTheme } from "next-themes"; @@ -12,14 +11,11 @@ import { ANALYTICS_Y_AXIS_VALUES, CHART_COLOR_PALETTES, ChartXAxisDateGrouping, - ChartXAxisProperty, - ChartYAxisMetric, EChartModels, } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { BarChart } from "@plane/propel/charts/bar-chart"; -import { ExportConfig } from "@plane/types"; -import { TBarItem, TChart, TChartDatum } from "@plane/types/src/charts"; +import { TBarItem, TChart, TChartDatum, ChartXAxisProperty, ChartYAxisMetric } from "@plane/types"; // plane web components import { Button } from "@plane/ui"; import { generateExtendedColors, parseChartData } from "@/components/chart/utils"; @@ -36,7 +32,11 @@ import { generateBarColor } from "./utils"; declare module "@tanstack/react-table" { interface ColumnMeta { - export: ExportConfig; + export: { + key: string; + value: (row: Row) => string | number; + label?: string; + }; } } diff --git a/web/core/components/analytics/work-items/root.tsx b/apps/web/core/components/analytics/work-items/root.tsx similarity index 100% rename from web/core/components/analytics/work-items/root.tsx rename to apps/web/core/components/analytics/work-items/root.tsx diff --git a/web/core/components/analytics/work-items/utils.ts b/apps/web/core/components/analytics/work-items/utils.ts similarity index 90% rename from web/core/components/analytics/work-items/utils.ts rename to apps/web/core/components/analytics/work-items/utils.ts index 6e0b47a44..37c74ec81 100644 --- a/web/core/components/analytics/work-items/utils.ts +++ b/apps/web/core/components/analytics/work-items/utils.ts @@ -1,6 +1,5 @@ // plane package imports -import { ChartXAxisProperty, ChartYAxisMetric } from "@plane/constants"; -import { IState } from "@plane/types"; +import { ChartXAxisProperty, ChartYAxisMetric, IState } from "@plane/types"; interface ParamsProps { x_axis: ChartXAxisProperty; diff --git a/web/core/components/analytics/work-items/workitems-insight-table.tsx b/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx similarity index 97% rename from web/core/components/analytics/work-items/workitems-insight-table.tsx rename to apps/web/core/components/analytics/work-items/workitems-insight-table.tsx index 98935271f..d0b6262fd 100644 --- a/web/core/components/analytics/work-items/workitems-insight-table.tsx +++ b/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx @@ -6,7 +6,7 @@ import useSWR from "swr"; import { Briefcase, UserRound } from "lucide-react"; // plane package imports import { useTranslation } from "@plane/i18n"; -import { WorkItemInsightColumns, AnalyticsTableDataMap, ExportConfig } from "@plane/types"; +import { AnalyticsTableDataMap, WorkItemInsightColumns } from "@plane/types"; // plane web components import { Avatar } from "@plane/ui"; import { getFileURL } from "@plane/utils"; @@ -23,7 +23,11 @@ const analyticsService = new AnalyticsService(); declare module "@tanstack/react-table" { interface ColumnMeta { - export: ExportConfig; + export: { + key: string; + value: (row: Row) => string | number; + label?: string; + }; } } diff --git a/web/core/components/api-token/delete-token-modal.tsx b/apps/web/core/components/api-token/delete-token-modal.tsx similarity index 79% rename from web/core/components/api-token/delete-token-modal.tsx rename to apps/web/core/components/api-token/delete-token-modal.tsx index eed0ecdb9..f139a2783 100644 --- a/web/core/components/api-token/delete-token-modal.tsx +++ b/apps/web/core/components/api-token/delete-token-modal.tsx @@ -3,6 +3,7 @@ import { useState, FC } from "react"; import { mutate } from "swr"; // types +import { PROFILE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { APITokenService } from "@plane/services"; import { IApiToken } from "@plane/types"; @@ -10,6 +11,7 @@ import { IApiToken } from "@plane/types"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; // fetch-keys import { API_TOKENS_LIST } from "@/constants/fetch-keys"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; type Props = { isOpen: boolean; @@ -48,6 +50,12 @@ export const DeleteApiTokenModal: FC = (props) => { (prevData) => (prevData ?? []).filter((token) => token.id !== tokenId), false ); + captureSuccess({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.pat_deleted, + payload: { + token: tokenId, + }, + }); handleClose(); }) @@ -58,6 +66,15 @@ export const DeleteApiTokenModal: FC = (props) => { message: err?.message ?? t("workspace_settings.settings.api_tokens.delete.error.message"), }) ) + .catch((err) => { + captureError({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.pat_deleted, + payload: { + token: tokenId, + }, + error: err as Error, + }); + }) .finally(() => setDeleteLoading(false)); }; diff --git a/web/core/components/api-token/empty-state.tsx b/apps/web/core/components/api-token/empty-state.tsx similarity index 100% rename from web/core/components/api-token/empty-state.tsx rename to apps/web/core/components/api-token/empty-state.tsx diff --git a/web/core/components/api-token/index.ts b/apps/web/core/components/api-token/index.ts similarity index 100% rename from web/core/components/api-token/index.ts rename to apps/web/core/components/api-token/index.ts diff --git a/web/core/components/api-token/modal/create-token-modal.tsx b/apps/web/core/components/api-token/modal/create-token-modal.tsx similarity index 86% rename from web/core/components/api-token/modal/create-token-modal.tsx rename to apps/web/core/components/api-token/modal/create-token-modal.tsx index 94d72c56d..d7d6e14d3 100644 --- a/web/core/components/api-token/modal/create-token-modal.tsx +++ b/apps/web/core/components/api-token/modal/create-token-modal.tsx @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { mutate } from "swr"; // types +import { PROFILE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { APITokenService } from "@plane/services"; import { IApiToken } from "@plane/types"; // ui @@ -12,6 +13,7 @@ import { renderFormattedDate, csvDownload } from "@plane/utils"; import { CreateApiTokenForm, GeneratedTokenDetails } from "@/components/api-token"; // fetch-keys import { API_TOKENS_LIST } from "@/constants/fetch-keys"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; // helpers // services @@ -66,6 +68,12 @@ export const CreateApiTokenModal: React.FC = (props) => { }, false ); + captureSuccess({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.pat_created, + payload: { + token: res.id, + }, + }); }) .catch((err) => { setToast({ @@ -74,6 +82,10 @@ export const CreateApiTokenModal: React.FC = (props) => { message: err.message || err.detail, }); + captureError({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.pat_created, + }); + throw err; }); }; diff --git a/web/core/components/api-token/modal/form.tsx b/apps/web/core/components/api-token/modal/form.tsx similarity index 99% rename from web/core/components/api-token/modal/form.tsx rename to apps/web/core/components/api-token/modal/form.tsx index eafd3e821..279722cfd 100644 --- a/web/core/components/api-token/modal/form.tsx +++ b/apps/web/core/components/api-token/modal/form.tsx @@ -251,4 +251,4 @@ export const CreateApiTokenForm: React.FC = (props) => {
); -}; \ No newline at end of file +}; diff --git a/web/core/components/api-token/modal/generated-token-details.tsx b/apps/web/core/components/api-token/modal/generated-token-details.tsx similarity index 100% rename from web/core/components/api-token/modal/generated-token-details.tsx rename to apps/web/core/components/api-token/modal/generated-token-details.tsx diff --git a/web/core/components/api-token/modal/index.ts b/apps/web/core/components/api-token/modal/index.ts similarity index 100% rename from web/core/components/api-token/modal/index.ts rename to apps/web/core/components/api-token/modal/index.ts diff --git a/web/core/components/api-token/token-list-item.tsx b/apps/web/core/components/api-token/token-list-item.tsx similarity index 93% rename from web/core/components/api-token/token-list-item.tsx rename to apps/web/core/components/api-token/token-list-item.tsx index 37b354960..f5fe9fbd8 100644 --- a/web/core/components/api-token/token-list-item.tsx +++ b/apps/web/core/components/api-token/token-list-item.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { XCircle } from "lucide-react"; +import { PROFILE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { IApiToken } from "@plane/types"; // components import { Tooltip } from "@plane/ui"; @@ -31,6 +32,7 @@ export const ApiTokenListItem: React.FC = (props) => { @@ -60,4 +62,4 @@ export const ApiTokenListItem: React.FC = (props) => {
); -}; \ No newline at end of file +}; diff --git a/web/core/components/archives/archive-tabs-list.tsx b/apps/web/core/components/archives/archive-tabs-list.tsx similarity index 100% rename from web/core/components/archives/archive-tabs-list.tsx rename to apps/web/core/components/archives/archive-tabs-list.tsx diff --git a/web/core/components/archives/index.ts b/apps/web/core/components/archives/index.ts similarity index 100% rename from web/core/components/archives/index.ts rename to apps/web/core/components/archives/index.ts diff --git a/web/core/components/auth-screens/index.ts b/apps/web/core/components/auth-screens/index.ts similarity index 100% rename from web/core/components/auth-screens/index.ts rename to apps/web/core/components/auth-screens/index.ts diff --git a/web/core/components/auth-screens/not-authorized-view.tsx b/apps/web/core/components/auth-screens/not-authorized-view.tsx similarity index 100% rename from web/core/components/auth-screens/not-authorized-view.tsx rename to apps/web/core/components/auth-screens/not-authorized-view.tsx diff --git a/web/core/components/auth-screens/project/index.ts b/apps/web/core/components/auth-screens/project/index.ts similarity index 100% rename from web/core/components/auth-screens/project/index.ts rename to apps/web/core/components/auth-screens/project/index.ts diff --git a/web/core/components/auth-screens/project/join-project.tsx b/apps/web/core/components/auth-screens/project/join-project.tsx similarity index 100% rename from web/core/components/auth-screens/project/join-project.tsx rename to apps/web/core/components/auth-screens/project/join-project.tsx diff --git a/web/core/components/auth-screens/workspace/index.ts b/apps/web/core/components/auth-screens/workspace/index.ts similarity index 100% rename from web/core/components/auth-screens/workspace/index.ts rename to apps/web/core/components/auth-screens/workspace/index.ts diff --git a/web/core/components/auth-screens/workspace/not-a-member.tsx b/apps/web/core/components/auth-screens/workspace/not-a-member.tsx similarity index 100% rename from web/core/components/auth-screens/workspace/not-a-member.tsx rename to apps/web/core/components/auth-screens/workspace/not-a-member.tsx diff --git a/web/core/components/automation/auto-archive-automation.tsx b/apps/web/core/components/automation/auto-archive-automation.tsx similarity index 83% rename from web/core/components/automation/auto-archive-automation.tsx rename to apps/web/core/components/automation/auto-archive-automation.tsx index c1a8c0b75..91c7bd62c 100644 --- a/web/core/components/automation/auto-archive-automation.tsx +++ b/apps/web/core/components/automation/auto-archive-automation.tsx @@ -5,7 +5,13 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ArchiveRestore } from "lucide-react"; // types -import { PROJECT_AUTOMATION_MONTHS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { + PROJECT_AUTOMATION_MONTHS, + EUserPermissions, + EUserPermissionsLevel, + PROJECT_SETTINGS_TRACKER_ELEMENTS, + PROJECT_SETTINGS_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; // ui @@ -14,6 +20,7 @@ import { CustomSelect, Loader, ToggleSwitch } from "@plane/ui"; import { SelectMonthModal } from "@/components/automation"; // constants // hooks +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; import { useProject, useUserPermissions } from "@/hooks/store"; type Props = { @@ -39,7 +46,7 @@ export const AutoArchiveAutomation: React.FC = observer((props) => { EUserPermissionsLevel.PROJECT, workspaceSlug?.toString(), currentProjectDetails?.id -); + ); return ( <> @@ -65,11 +72,22 @@ export const AutoArchiveAutomation: React.FC = observer((props) => {
- currentProjectDetails?.archive_in === 0 - ? handleChange({ archive_in: 1 }) - : handleChange({ archive_in: 0 }) - } + onChange={async () => { + if (currentProjectDetails?.archive_in === 0) { + await handleChange({ archive_in: 1 }); + } else { + await handleChange({ archive_in: 0 }); + } + captureElementAndEvent({ + element: { + elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.AUTOMATIONS_ARCHIVE_TOGGLE_BUTTON, + }, + event: { + eventName: PROJECT_SETTINGS_TRACKER_EVENTS.auto_archive_workitems, + state: "SUCCESS", + }, + }); + }} size="sm" disabled={!isAdmin} /> diff --git a/web/core/components/automation/auto-close-automation.tsx b/apps/web/core/components/automation/auto-close-automation.tsx similarity index 88% rename from web/core/components/automation/auto-close-automation.tsx rename to apps/web/core/components/automation/auto-close-automation.tsx index 7aef61d13..170e5e655 100644 --- a/web/core/components/automation/auto-close-automation.tsx +++ b/apps/web/core/components/automation/auto-close-automation.tsx @@ -6,7 +6,14 @@ import { useParams } from "next/navigation"; // icons import { ArchiveX } from "lucide-react"; // types -import { PROJECT_AUTOMATION_MONTHS, EUserPermissions, EUserPermissionsLevel, EIconSize } from "@plane/constants"; +import { + PROJECT_AUTOMATION_MONTHS, + EUserPermissions, + EUserPermissionsLevel, + EIconSize, + PROJECT_SETTINGS_TRACKER_ELEMENTS, + PROJECT_SETTINGS_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; // ui @@ -15,6 +22,7 @@ import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleC import { SelectMonthModal } from "@/components/automation"; // constants // hooks +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; import { useProject, useProjectState, useUserPermissions } from "@/hooks/store"; type Props = { @@ -91,11 +99,22 @@ export const AutoCloseAutomation: React.FC = observer((props) => {
- currentProjectDetails?.close_in === 0 - ? handleChange({ close_in: 1, default_state: defaultState }) - : handleChange({ close_in: 0, default_state: null }) - } + onChange={async () => { + if (currentProjectDetails?.close_in === 0) { + await handleChange({ close_in: 1, default_state: defaultState }); + } else { + await handleChange({ close_in: 0, default_state: null }); + } + captureElementAndEvent({ + element: { + elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.AUTOMATIONS_CLOSE_TOGGLE_BUTTON, + }, + event: { + eventName: PROJECT_SETTINGS_TRACKER_EVENTS.auto_close_workitems, + state: "SUCCESS", + }, + }); + }} size="sm" disabled={!isAdmin} /> diff --git a/web/core/components/automation/index.ts b/apps/web/core/components/automation/index.ts similarity index 100% rename from web/core/components/automation/index.ts rename to apps/web/core/components/automation/index.ts diff --git a/web/core/components/automation/select-month-modal.tsx b/apps/web/core/components/automation/select-month-modal.tsx similarity index 100% rename from web/core/components/automation/select-month-modal.tsx rename to apps/web/core/components/automation/select-month-modal.tsx diff --git a/web/core/components/chart/utils.ts b/apps/web/core/components/chart/utils.ts similarity index 93% rename from web/core/components/chart/utils.ts rename to apps/web/core/components/chart/utils.ts index 092cc2c21..6d6895e06 100644 --- a/web/core/components/chart/utils.ts +++ b/apps/web/core/components/chart/utils.ts @@ -1,7 +1,13 @@ import { getWeekOfMonth, isValid } from "date-fns"; -import { CHART_X_AXIS_DATE_PROPERTIES, ChartXAxisDateGrouping, ChartXAxisProperty, TO_CAPITALIZE_PROPERTIES } from "@plane/constants"; -import { TChart, TChartDatum } from "@plane/types"; -import { capitalizeFirstLetter, hexToHsl, hslToHex, renderFormattedDate, renderFormattedDateWithoutYear } from "@plane/utils"; +import { CHART_X_AXIS_DATE_PROPERTIES, ChartXAxisDateGrouping, TO_CAPITALIZE_PROPERTIES } from "@plane/constants"; +import { ChartXAxisProperty, TChart, TChartDatum } from "@plane/types"; +import { + capitalizeFirstLetter, + hexToHsl, + hslToHex, + renderFormattedDate, + renderFormattedDateWithoutYear, +} from "@plane/utils"; // const getDateGroupingName = (date: string, dateGrouping: ChartXAxisDateGrouping): string => { @@ -61,7 +67,7 @@ export const parseChartData = ( const updatedWidgetData: TChartDatum[] = widgetData.map((datum) => { const keys = Object.keys(datum); const missingKeys = allKeys.filter((key) => !keys.includes(key)); - const missingValues: Record = Object.fromEntries(missingKeys.map(key => [key, 0])); + const missingValues: Record = Object.fromEntries(missingKeys.map((key) => [key, 0])); if (xAxisProperty) { // capitalize first letter if xAxisProperty is in TO_CAPITALIZE_PROPERTIES and no groupByProperty is set @@ -163,4 +169,4 @@ export const generateExtendedColors = (baseColorSet: string[], targetCount: numb } return colors.slice(0, targetCount); -}; \ No newline at end of file +}; diff --git a/web/core/components/command-palette/actions/help-actions.tsx b/apps/web/core/components/command-palette/actions/help-actions.tsx similarity index 100% rename from web/core/components/command-palette/actions/help-actions.tsx rename to apps/web/core/components/command-palette/actions/help-actions.tsx diff --git a/web/core/components/command-palette/actions/helper.tsx b/apps/web/core/components/command-palette/actions/helper.tsx similarity index 100% rename from web/core/components/command-palette/actions/helper.tsx rename to apps/web/core/components/command-palette/actions/helper.tsx diff --git a/web/core/components/command-palette/actions/index.ts b/apps/web/core/components/command-palette/actions/index.ts similarity index 100% rename from web/core/components/command-palette/actions/index.ts rename to apps/web/core/components/command-palette/actions/index.ts diff --git a/web/core/components/command-palette/actions/issue-actions/actions-list.tsx b/apps/web/core/components/command-palette/actions/issue-actions/actions-list.tsx similarity index 98% rename from web/core/components/command-palette/actions/issue-actions/actions-list.tsx rename to apps/web/core/components/command-palette/actions/issue-actions/actions-list.tsx index 812ffd984..e03d6363a 100644 --- a/web/core/components/command-palette/actions/issue-actions/actions-list.tsx +++ b/apps/web/core/components/command-palette/actions/issue-actions/actions-list.tsx @@ -4,8 +4,7 @@ import { Command } from "cmdk"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { LinkIcon, Signal, Trash2, UserMinus2, UserPlus2, Users } from "lucide-react"; -import { EIssueServiceType } from "@plane/constants"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType, TIssue } from "@plane/types"; // hooks import { DoubleCircleIcon, TOAST_TYPE, setToast } from "@plane/ui"; // helpers diff --git a/web/core/components/command-palette/actions/issue-actions/change-assignee.tsx b/apps/web/core/components/command-palette/actions/issue-actions/change-assignee.tsx similarity index 96% rename from web/core/components/command-palette/actions/issue-actions/change-assignee.tsx rename to apps/web/core/components/command-palette/actions/issue-actions/change-assignee.tsx index f4a3b0951..d442afde9 100644 --- a/web/core/components/command-palette/actions/issue-actions/change-assignee.tsx +++ b/apps/web/core/components/command-palette/actions/issue-actions/change-assignee.tsx @@ -4,9 +4,8 @@ import { Command } from "cmdk"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Check } from "lucide-react"; -import { EIssueServiceType } from "@plane/constants"; // plane types -import { TIssue } from "@plane/types"; +import { EIssueServiceType, TIssue } from "@plane/types"; // plane ui import { Avatar } from "@plane/ui"; // helpers diff --git a/web/core/components/command-palette/actions/issue-actions/change-priority.tsx b/apps/web/core/components/command-palette/actions/issue-actions/change-priority.tsx similarity index 92% rename from web/core/components/command-palette/actions/issue-actions/change-priority.tsx rename to apps/web/core/components/command-palette/actions/issue-actions/change-priority.tsx index 53bada187..84f8ef287 100644 --- a/web/core/components/command-palette/actions/issue-actions/change-priority.tsx +++ b/apps/web/core/components/command-palette/actions/issue-actions/change-priority.tsx @@ -5,9 +5,9 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Check } from "lucide-react"; // plane constants -import { EIssueServiceType, ISSUE_PRIORITIES } from "@plane/constants"; +import { ISSUE_PRIORITIES } from "@plane/constants"; // plane types -import { TIssue, TIssuePriorities } from "@plane/types"; +import { EIssueServiceType, TIssue, TIssuePriorities } from "@plane/types"; // mobx store import { PriorityIcon } from "@plane/ui"; import { useIssueDetail } from "@/hooks/store"; diff --git a/web/core/components/command-palette/actions/issue-actions/change-state.tsx b/apps/web/core/components/command-palette/actions/issue-actions/change-state.tsx similarity index 93% rename from web/core/components/command-palette/actions/issue-actions/change-state.tsx rename to apps/web/core/components/command-palette/actions/issue-actions/change-state.tsx index b89264ec1..7abc9326e 100644 --- a/web/core/components/command-palette/actions/issue-actions/change-state.tsx +++ b/apps/web/core/components/command-palette/actions/issue-actions/change-state.tsx @@ -3,8 +3,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssueServiceType } from "@plane/constants"; -import { TIssue } from "@plane/types"; +import { EIssueServiceType, TIssue } from "@plane/types"; // store hooks import { useIssueDetail } from "@/hooks/store"; // plane web imports diff --git a/web/core/components/command-palette/actions/issue-actions/index.ts b/apps/web/core/components/command-palette/actions/issue-actions/index.ts similarity index 100% rename from web/core/components/command-palette/actions/issue-actions/index.ts rename to apps/web/core/components/command-palette/actions/issue-actions/index.ts diff --git a/web/core/components/command-palette/actions/project-actions.tsx b/apps/web/core/components/command-palette/actions/project-actions.tsx similarity index 84% rename from web/core/components/command-palette/actions/project-actions.tsx rename to apps/web/core/components/command-palette/actions/project-actions.tsx index 7666fd0a8..677261dc5 100644 --- a/web/core/components/command-palette/actions/project-actions.tsx +++ b/apps/web/core/components/command-palette/actions/project-actions.tsx @@ -3,8 +3,10 @@ import { Command } from "cmdk"; import { ContrastIcon, FileText, Layers } from "lucide-react"; // hooks +import { CYCLE_TRACKER_ELEMENTS, MODULE_TRACKER_ELEMENTS, PROJECT_PAGE_TRACKER_ELEMENTS } from "@plane/constants"; import { DiceIcon } from "@plane/ui"; -import { useCommandPalette, useEventTracker } from "@/hooks/store"; +// hooks +import { useCommandPalette } from "@/hooks/store"; // ui type Props = { @@ -16,15 +18,14 @@ export const CommandPaletteProjectActions: React.FC = (props) => { // store hooks const { toggleCreateCycleModal, toggleCreateModuleModal, toggleCreatePageModal, toggleCreateViewModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); return ( <> { closePalette(); - setTrackElement("Command palette"); toggleCreateCycleModal(true); }} className="focus:outline-none" @@ -38,9 +39,9 @@ export const CommandPaletteProjectActions: React.FC = (props) => { { closePalette(); - setTrackElement("Command palette"); toggleCreateModuleModal(true); }} className="focus:outline-none" @@ -56,7 +57,6 @@ export const CommandPaletteProjectActions: React.FC = (props) => { { closePalette(); - setTrackElement("Command palette"); toggleCreateViewModal(true); }} className="focus:outline-none" @@ -70,9 +70,9 @@ export const CommandPaletteProjectActions: React.FC = (props) => { { closePalette(); - setTrackElement("Command palette"); toggleCreatePageModal({ isOpen: true }); }} className="focus:outline-none" diff --git a/web/core/components/command-palette/actions/search-results.tsx b/apps/web/core/components/command-palette/actions/search-results.tsx similarity index 100% rename from web/core/components/command-palette/actions/search-results.tsx rename to apps/web/core/components/command-palette/actions/search-results.tsx diff --git a/web/core/components/command-palette/actions/theme-actions.tsx b/apps/web/core/components/command-palette/actions/theme-actions.tsx similarity index 100% rename from web/core/components/command-palette/actions/theme-actions.tsx rename to apps/web/core/components/command-palette/actions/theme-actions.tsx diff --git a/web/core/components/command-palette/actions/workspace-settings-actions.tsx b/apps/web/core/components/command-palette/actions/workspace-settings-actions.tsx similarity index 100% rename from web/core/components/command-palette/actions/workspace-settings-actions.tsx rename to apps/web/core/components/command-palette/actions/workspace-settings-actions.tsx diff --git a/web/core/components/command-palette/command-modal.tsx b/apps/web/core/components/command-palette/command-modal.tsx similarity index 97% rename from web/core/components/command-palette/command-modal.tsx rename to apps/web/core/components/command-palette/command-modal.tsx index ce8d8528d..27493c846 100644 --- a/web/core/components/command-palette/command-modal.tsx +++ b/apps/web/core/components/command-palette/command-modal.tsx @@ -8,7 +8,13 @@ import useSWR from "swr"; import { CommandIcon, FolderPlus, Search, Settings, X } from "lucide-react"; import { Dialog, Transition } from "@headlessui/react"; // plane imports -import { EUserPermissions, EUserPermissionsLevel, WORKSPACE_DEFAULT_SEARCH_RESULT } from "@plane/constants"; +import { + EUserPermissions, + EUserPermissionsLevel, + PROJECT_TRACKER_ELEMENTS, + WORK_ITEM_TRACKER_ELEMENTS, + WORKSPACE_DEFAULT_SEARCH_RESULT, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWorkspaceSearchResults } from "@plane/types"; import { LayersIcon, Loader, ToggleSwitch } from "@plane/ui"; @@ -28,14 +34,8 @@ import { import { SimpleEmptyState } from "@/components/empty-state"; // helpers // hooks -import { - useCommandPalette, - useEventTracker, - useIssueDetail, - useProject, - useUser, - useUserPermissions, -} from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useIssueDetail, useProject, useUser, useUserPermissions } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import useDebounce from "@/hooks/use-debounce"; import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -74,7 +74,6 @@ export const CommandModal: React.FC = observer(() => { const { isCommandPaletteOpen, toggleCommandPaletteModal, toggleCreateIssueModal, toggleCreateProjectModal } = useCommandPalette(); const { allowPermissions } = useUserPermissions(); - const { setTrackElement } = useEventTracker(); const projectIdentifier = workItem?.toString().split("-")[0]; const sequence_id = workItem?.toString().split("-")[1]; // fetch work item details using identifier @@ -346,7 +345,9 @@ export const CommandModal: React.FC = observer(() => { { closePalette(); - setTrackElement("Command Palette"); + captureClick({ + elementName: WORK_ITEM_TRACKER_ELEMENTS.COMMAND_PALETTE_ADD_BUTTON, + }); toggleCreateIssueModal(true); }} className="focus:bg-custom-background-80" @@ -364,7 +365,7 @@ export const CommandModal: React.FC = observer(() => { { closePalette(); - setTrackElement("Command palette"); + captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.COMMAND_PALETTE_CREATE_BUTTON }); toggleCreateProjectModal(true); }} className="focus:outline-none" diff --git a/web/core/components/command-palette/command-palette.tsx b/apps/web/core/components/command-palette/command-palette.tsx similarity index 95% rename from web/core/components/command-palette/command-palette.tsx rename to apps/web/core/components/command-palette/command-palette.tsx index e7557c2fd..0bc174d6d 100644 --- a/web/core/components/command-palette/command-palette.tsx +++ b/apps/web/core/components/command-palette/command-palette.tsx @@ -5,21 +5,15 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // ui -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { COMMAND_PALETTE_TRACKER_ELEMENTS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { copyTextToClipboard } from "@plane/utils"; import { CommandModal, ShortcutsModal } from "@/components/command-palette"; // helpers // hooks -import { - useEventTracker, - useUser, - useAppTheme, - useCommandPalette, - useUserPermissions, - useIssueDetail, -} from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useUser, useAppTheme, useCommandPalette, useUserPermissions, useIssueDetail } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { @@ -42,7 +36,6 @@ export const CommandPalette: FC = observer(() => { // store hooks const { fetchIssueWithIdentifier } = useIssueDetail(); const { toggleSidebar } = useAppTheme(); - const { setTrackElement } = useEventTracker(); const { platform } = usePlatformOS(); const { data: currentUser, canPerformAnyCreateAction } = useUser(); const { toggleCommandPaletteModal, isShortcutModalOpen, toggleShortcutModal, isAnyModalOpen } = useCommandPalette(); @@ -203,7 +196,7 @@ export const CommandPalette: FC = observer(() => { toggleSidebar(); } } else if (!isAnyModalOpen) { - setTrackElement("Shortcut key"); + captureClick({ elementName: COMMAND_PALETTE_TRACKER_ELEMENTS.COMMAND_PALETTE_SHORTCUT_KEY }); if ( Object.keys(shortcutsList.global).includes(keyPressed) && ((!projectId && performAnyProjectCreateActions()) || performProjectCreateActions()) @@ -242,7 +235,6 @@ export const CommandPalette: FC = observer(() => { performProjectCreateActions, performWorkspaceCreateActions, projectId, - setTrackElement, shortcutsList, toggleCommandPaletteModal, toggleShortcutModal, diff --git a/web/core/components/command-palette/index.ts b/apps/web/core/components/command-palette/index.ts similarity index 100% rename from web/core/components/command-palette/index.ts rename to apps/web/core/components/command-palette/index.ts diff --git a/web/core/components/command-palette/shortcuts-modal/commands-list.tsx b/apps/web/core/components/command-palette/shortcuts-modal/commands-list.tsx similarity index 100% rename from web/core/components/command-palette/shortcuts-modal/commands-list.tsx rename to apps/web/core/components/command-palette/shortcuts-modal/commands-list.tsx diff --git a/web/core/components/command-palette/shortcuts-modal/index.ts b/apps/web/core/components/command-palette/shortcuts-modal/index.ts similarity index 100% rename from web/core/components/command-palette/shortcuts-modal/index.ts rename to apps/web/core/components/command-palette/shortcuts-modal/index.ts diff --git a/web/core/components/command-palette/shortcuts-modal/modal.tsx b/apps/web/core/components/command-palette/shortcuts-modal/modal.tsx similarity index 96% rename from web/core/components/command-palette/shortcuts-modal/modal.tsx rename to apps/web/core/components/command-palette/shortcuts-modal/modal.tsx index f4076db4c..0cf5f3ab9 100644 --- a/web/core/components/command-palette/shortcuts-modal/modal.tsx +++ b/apps/web/core/components/command-palette/shortcuts-modal/modal.tsx @@ -25,7 +25,7 @@ export const ShortcutsModal: FC = (props) => { return ( - + = (props) => {
-
+
; + showAccessSpecifier: boolean; + workspaceId: string; + workspaceSlug: string; +}; + +export const CommentCardDisplay: React.FC = observer((props) => { + const { + activityOperations, + comment, + disabled, + projectId, + readOnlyEditorRef, + showAccessSpecifier, + workspaceId, + workspaceSlug, + } = props; + // states + const [highlightClassName, setHighlightClassName] = useState(""); + // navigation + const pathname = usePathname(); + // derived values + const commentBlockId = `comment-${comment?.id}`; + // scroll to comment + const { isHashMatch } = useHashScroll({ + elementId: commentBlockId, + pathname, + }); + + useEffect(() => { + if (!isHashMatch) return; + setHighlightClassName("border-custom-primary-100"); + const timeout = setTimeout(() => { + setHighlightClassName(""); + }, 8000); + + return () => clearTimeout(timeout); + }, [isHashMatch]); + + return ( +
+ {showAccessSpecifier && ( +
+ {comment.access === EIssueCommentAccessSpecifier.INTERNAL ? ( + + ) : ( + + )} +
+ )} + + +
+ ); +}); diff --git a/apps/web/core/components/comments/card/edit-form.tsx b/apps/web/core/components/comments/card/edit-form.tsx new file mode 100644 index 000000000..5b837bd68 --- /dev/null +++ b/apps/web/core/components/comments/card/edit-form.tsx @@ -0,0 +1,130 @@ +import React, { useEffect, useRef } from "react"; +import { observer } from "mobx-react"; +import { useForm } from "react-hook-form"; +import { Check, X } from "lucide-react"; +// plane imports +import type { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; +import type { TCommentsOperations, TIssueComment } from "@plane/types"; +import { isCommentEmpty } from "@plane/utils"; +// components +import { LiteTextEditor } from "@/components/editor"; + +type Props = { + activityOperations: TCommentsOperations; + comment: TIssueComment; + isEditing: boolean; + projectId?: string; + readOnlyEditorRef: EditorReadOnlyRefApi | null; + setIsEditing: (isEditing: boolean) => void; + workspaceId: string; + workspaceSlug: string; +}; + +export const CommentCardEditForm: React.FC = observer((props) => { + const { + activityOperations, + comment, + isEditing, + projectId, + readOnlyEditorRef, + setIsEditing, + workspaceId, + workspaceSlug, + } = props; + // refs + const editorRef = useRef(null); + // form info + const { + formState: { isSubmitting }, + handleSubmit, + setFocus, + watch, + setValue, + } = useForm>({ + defaultValues: { comment_html: comment?.comment_html }, + }); + const commentHTML = watch("comment_html"); + + const isEmpty = isCommentEmpty(commentHTML ?? undefined); + const isEditorReadyToDiscard = editorRef.current?.isEditorReadyToDiscard(); + const isSubmitButtonDisabled = isSubmitting || !isEditorReadyToDiscard; + const isDisabled = isSubmitting || isEmpty || isSubmitButtonDisabled; + + const onEnter = async (formData: Partial) => { + if (isSubmitting || !comment) return; + + setIsEditing(false); + + await activityOperations.updateComment(comment.id, formData); + + editorRef.current?.setEditorValue(formData?.comment_html ?? "

"); + readOnlyEditorRef?.setEditorValue(formData?.comment_html ?? "

"); + }; + + useEffect(() => { + if (isEditing) { + setFocus("comment_html"); + } + }, [isEditing, setFocus]); + + return ( +
+
{ + if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty) handleSubmit(onEnter)(e); + }} + > + setValue("comment_html", comment_html)} + onEnterKeyPress={(e) => { + if (!isEmpty && !isSubmitting) { + handleSubmit(onEnter)(e); + } + }} + showSubmitButton={false} + uploadFile={async (blockId, file) => { + const { asset_id } = await activityOperations.uploadCommentAsset(blockId, file, comment.id); + return asset_id; + }} + projectId={projectId?.toString() ?? ""} + parentClassName="p-2" + displayConfig={{ + fontSize: "small-font", + }} + /> +
+
+ {!isEmpty && ( + + )} + +
+
+ ); +}); diff --git a/apps/web/core/components/comments/card/root.tsx b/apps/web/core/components/comments/card/root.tsx new file mode 100644 index 000000000..fac2e079c --- /dev/null +++ b/apps/web/core/components/comments/card/root.tsx @@ -0,0 +1,85 @@ +"use client"; + +import { FC, useRef, useState } from "react"; +import { observer } from "mobx-react"; +// plane imports +import type { EditorReadOnlyRefApi } from "@plane/editor"; +import type { TIssueComment, TCommentsOperations } from "@plane/types"; +// plane web imports +import { CommentBlock } from "@/plane-web/components/comments"; +// local imports +import { CommentQuickActions } from "../quick-actions"; +import { CommentCardDisplay } from "./display"; +import { CommentCardEditForm } from "./edit-form"; + +type TCommentCard = { + workspaceSlug: string; + comment: TIssueComment | undefined; + activityOperations: TCommentsOperations; + ends: "top" | "bottom" | undefined; + showAccessSpecifier: boolean; + showCopyLinkOption: boolean; + disabled?: boolean; + projectId?: string; +}; + +export const CommentCard: FC = observer((props) => { + const { + workspaceSlug, + comment, + activityOperations, + ends, + showAccessSpecifier, + showCopyLinkOption, + disabled = false, + projectId, + } = props; + const readOnlyEditorRef = useRef(null); + // states + const [isEditing, setIsEditing] = useState(false); + // derived values + const workspaceId = comment?.workspace; + + if (!comment || !workspaceId) return null; + + return ( + setIsEditing(true)} + showAccessSpecifier={showAccessSpecifier} + showCopyLinkOption={showCopyLinkOption} + /> + ) + } + ends={ends} + > + {isEditing ? ( + + ) : ( + + )} + + ); +}); diff --git a/web/core/components/comments/comment-create.tsx b/apps/web/core/components/comments/comment-create.tsx similarity index 100% rename from web/core/components/comments/comment-create.tsx rename to apps/web/core/components/comments/comment-create.tsx diff --git a/web/core/components/comments/comment-reaction.tsx b/apps/web/core/components/comments/comment-reaction.tsx similarity index 100% rename from web/core/components/comments/comment-reaction.tsx rename to apps/web/core/components/comments/comment-reaction.tsx diff --git a/web/core/components/comments/comments.tsx b/apps/web/core/components/comments/comments.tsx similarity index 83% rename from web/core/components/comments/comments.tsx rename to apps/web/core/components/comments/comments.tsx index bbda0f45f..bc15adcc1 100644 --- a/web/core/components/comments/comments.tsx +++ b/apps/web/core/components/comments/comments.tsx @@ -4,11 +4,10 @@ import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import smoothScrollIntoView from "smooth-scroll-into-view-if-needed"; import { E_SORT_ORDER } from "@plane/constants"; import { TCommentsOperations, TIssueComment } from "@plane/types"; // local components -import { CommentCard } from "./comment-card"; +import { CommentCard } from "./card/root"; import { CommentCreate } from "./comment-create"; type TCommentsWrapper = { @@ -19,10 +18,21 @@ type TCommentsWrapper = { comments: TIssueComment[] | string[]; sortOrder?: E_SORT_ORDER; getCommentById?: (activityId: string) => TIssueComment | undefined; + showAccessSpecifier?: boolean; + showCopyLinkOption?: boolean; }; export const CommentsWrapper: FC = observer((props) => { - const { entityId, activityOperations, comments, getCommentById, isEditingAllowed = true, projectId } = props; + const { + entityId, + activityOperations, + comments, + getCommentById, + isEditingAllowed = true, + projectId, + showAccessSpecifier = false, + showCopyLinkOption = false, + } = props; // router const { workspaceSlug: routerWorkspaceSlug } = useParams(); const workspaceSlug = routerWorkspaceSlug?.toString(); @@ -61,6 +71,8 @@ export const CommentsWrapper: FC = observer((props) => { disabled={!isEditingAllowed} ends={index === 0 ? "top" : index === comments.length - 1 ? "bottom" : undefined} projectId={projectId} + showAccessSpecifier={showAccessSpecifier} + showCopyLinkOption={showCopyLinkOption} /> ); })} diff --git a/web/core/components/comments/index.ts b/apps/web/core/components/comments/index.ts similarity index 100% rename from web/core/components/comments/index.ts rename to apps/web/core/components/comments/index.ts diff --git a/apps/web/core/components/comments/quick-actions.tsx b/apps/web/core/components/comments/quick-actions.tsx new file mode 100644 index 000000000..894e32630 --- /dev/null +++ b/apps/web/core/components/comments/quick-actions.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { FC, useMemo } from "react"; +import { observer } from "mobx-react"; +import { Globe2, Link, Lock, Pencil, Trash2 } from "lucide-react"; +// plane imports +import { EIssueCommentAccessSpecifier } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; +import type { TIssueComment, TCommentsOperations } from "@plane/types"; +import { CustomMenu, TContextMenuItem } from "@plane/ui"; +import { cn } from "@plane/utils"; +// hooks +import { useUser } from "@/hooks/store"; + +type TCommentCard = { + activityOperations: TCommentsOperations; + comment: TIssueComment; + setEditMode: () => void; + showAccessSpecifier: boolean; + showCopyLinkOption: boolean; +}; + +export const CommentQuickActions: FC = observer((props) => { + const { activityOperations, comment, setEditMode, showAccessSpecifier, showCopyLinkOption } = props; + // store hooks + const { data: currentUser } = useUser(); + // derived values + const isAuthor = currentUser?.id === comment.actor; + const canEdit = isAuthor; + const canDelete = isAuthor; + // translation + const { t } = useTranslation(); + + const MENU_ITEMS: TContextMenuItem[] = useMemo( + () => [ + { + key: "edit", + action: setEditMode, + title: t("common.actions.edit"), + icon: Pencil, + shouldRender: canEdit, + }, + { + key: "copy_link", + action: () => activityOperations.copyCommentLink(comment.id), + title: t("common.actions.copy_link"), + icon: Link, + shouldRender: showCopyLinkOption, + }, + { + key: "access_specifier", + action: () => + activityOperations.updateComment(comment.id, { + access: + comment.access === EIssueCommentAccessSpecifier.INTERNAL + ? EIssueCommentAccessSpecifier.EXTERNAL + : EIssueCommentAccessSpecifier.INTERNAL, + }), + title: + comment.access === EIssueCommentAccessSpecifier.INTERNAL + ? t("issue.comments.switch.public") + : t("issue.comments.switch.private"), + icon: comment.access === EIssueCommentAccessSpecifier.INTERNAL ? Globe2 : Lock, + shouldRender: showAccessSpecifier, + }, + { + key: "delete", + action: () => activityOperations.removeComment(comment.id), + title: t("common.actions.delete"), + icon: Trash2, + shouldRender: canDelete, + }, + ], + [activityOperations, canDelete, canEdit, comment, setEditMode, showAccessSpecifier, showCopyLinkOption] + ); + + return ( + + {MENU_ITEMS.map((item) => { + if (item.shouldRender === false) return null; + + return ( + item.action()} + className={cn( + "flex items-center gap-2", + { + "text-custom-text-400": item.disabled, + }, + item.className + )} + disabled={item.disabled} + > + {item.icon && } +
+
{item.title}
+ {item.description && ( +

+ {item.description} +

+ )} +
+
+ ); + })} +
+ ); +}); diff --git a/web/core/components/common/access-field.tsx b/apps/web/core/components/common/access-field.tsx similarity index 100% rename from web/core/components/common/access-field.tsx rename to apps/web/core/components/common/access-field.tsx diff --git a/web/core/components/common/activity/activity-block.tsx b/apps/web/core/components/common/activity/activity-block.tsx similarity index 100% rename from web/core/components/common/activity/activity-block.tsx rename to apps/web/core/components/common/activity/activity-block.tsx diff --git a/web/core/components/common/activity/activity-item.tsx b/apps/web/core/components/common/activity/activity-item.tsx similarity index 100% rename from web/core/components/common/activity/activity-item.tsx rename to apps/web/core/components/common/activity/activity-item.tsx diff --git a/web/core/components/common/activity/helper.tsx b/apps/web/core/components/common/activity/helper.tsx similarity index 100% rename from web/core/components/common/activity/helper.tsx rename to apps/web/core/components/common/activity/helper.tsx diff --git a/web/core/components/common/activity/index.ts b/apps/web/core/components/common/activity/index.ts similarity index 100% rename from web/core/components/common/activity/index.ts rename to apps/web/core/components/common/activity/index.ts diff --git a/web/core/components/common/activity/user.tsx b/apps/web/core/components/common/activity/user.tsx similarity index 100% rename from web/core/components/common/activity/user.tsx rename to apps/web/core/components/common/activity/user.tsx diff --git a/web/core/components/common/applied-filters/date.tsx b/apps/web/core/components/common/applied-filters/date.tsx similarity index 100% rename from web/core/components/common/applied-filters/date.tsx rename to apps/web/core/components/common/applied-filters/date.tsx diff --git a/web/core/components/common/applied-filters/index.ts b/apps/web/core/components/common/applied-filters/index.ts similarity index 100% rename from web/core/components/common/applied-filters/index.ts rename to apps/web/core/components/common/applied-filters/index.ts diff --git a/web/core/components/common/applied-filters/members.tsx b/apps/web/core/components/common/applied-filters/members.tsx similarity index 100% rename from web/core/components/common/applied-filters/members.tsx rename to apps/web/core/components/common/applied-filters/members.tsx diff --git a/web/core/components/common/breadcrumb-link.tsx b/apps/web/core/components/common/breadcrumb-link.tsx similarity index 98% rename from web/core/components/common/breadcrumb-link.tsx rename to apps/web/core/components/common/breadcrumb-link.tsx index 1dc85e3e2..a0fda7c14 100644 --- a/web/core/components/common/breadcrumb-link.tsx +++ b/apps/web/core/components/common/breadcrumb-link.tsx @@ -1,7 +1,7 @@ "use client"; import React, { ReactNode, useMemo, FC } from "react"; -import { observer } from "mobx-react-lite"; +import { observer } from "mobx-react"; import Link from "next/link"; import { Breadcrumbs } from "@plane/ui"; import { usePlatformOS } from "@/hooks/use-platform-os"; diff --git a/web/core/components/common/count-chip.tsx b/apps/web/core/components/common/count-chip.tsx similarity index 100% rename from web/core/components/common/count-chip.tsx rename to apps/web/core/components/common/count-chip.tsx diff --git a/web/core/components/common/empty-state.tsx b/apps/web/core/components/common/empty-state.tsx similarity index 100% rename from web/core/components/common/empty-state.tsx rename to apps/web/core/components/common/empty-state.tsx diff --git a/web/core/components/common/filters/created-at.tsx b/apps/web/core/components/common/filters/created-at.tsx similarity index 100% rename from web/core/components/common/filters/created-at.tsx rename to apps/web/core/components/common/filters/created-at.tsx diff --git a/web/core/components/common/filters/created-by.tsx b/apps/web/core/components/common/filters/created-by.tsx similarity index 100% rename from web/core/components/common/filters/created-by.tsx rename to apps/web/core/components/common/filters/created-by.tsx diff --git a/web/core/components/common/filters/index.ts b/apps/web/core/components/common/filters/index.ts similarity index 100% rename from web/core/components/common/filters/index.ts rename to apps/web/core/components/common/filters/index.ts diff --git a/web/core/components/common/index.ts b/apps/web/core/components/common/index.ts similarity index 100% rename from web/core/components/common/index.ts rename to apps/web/core/components/common/index.ts diff --git a/web/core/components/common/latest-feature-block.tsx b/apps/web/core/components/common/latest-feature-block.tsx similarity index 100% rename from web/core/components/common/latest-feature-block.tsx rename to apps/web/core/components/common/latest-feature-block.tsx diff --git a/web/core/components/common/logo-spinner.tsx b/apps/web/core/components/common/logo-spinner.tsx similarity index 100% rename from web/core/components/common/logo-spinner.tsx rename to apps/web/core/components/common/logo-spinner.tsx diff --git a/web/core/components/common/logo.tsx b/apps/web/core/components/common/logo.tsx similarity index 100% rename from web/core/components/common/logo.tsx rename to apps/web/core/components/common/logo.tsx diff --git a/web/core/components/common/new-empty-state.tsx b/apps/web/core/components/common/new-empty-state.tsx similarity index 100% rename from web/core/components/common/new-empty-state.tsx rename to apps/web/core/components/common/new-empty-state.tsx diff --git a/web/core/components/common/page-access-icon.tsx b/apps/web/core/components/common/page-access-icon.tsx similarity index 100% rename from web/core/components/common/page-access-icon.tsx rename to apps/web/core/components/common/page-access-icon.tsx diff --git a/web/core/components/common/pro-icon.tsx b/apps/web/core/components/common/pro-icon.tsx similarity index 100% rename from web/core/components/common/pro-icon.tsx rename to apps/web/core/components/common/pro-icon.tsx diff --git a/web/core/components/common/switcher-label.tsx b/apps/web/core/components/common/switcher-label.tsx similarity index 100% rename from web/core/components/common/switcher-label.tsx rename to apps/web/core/components/common/switcher-label.tsx diff --git a/web/core/components/core/activity.tsx b/apps/web/core/components/core/activity.tsx similarity index 100% rename from web/core/components/core/activity.tsx rename to apps/web/core/components/core/activity.tsx diff --git a/apps/web/core/components/core/app-header.tsx b/apps/web/core/components/core/app-header.tsx new file mode 100644 index 000000000..a63d5ab93 --- /dev/null +++ b/apps/web/core/components/core/app-header.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { ReactNode } from "react"; +import { observer } from "mobx-react"; +// plane imports +import { Row } from "@plane/ui"; +// components +import { ExtendedAppHeader } from "@/plane-web/components/common"; + +export interface AppHeaderProps { + header: ReactNode; + mobileHeader?: ReactNode; +} + +export const AppHeader = observer((props: AppHeaderProps) => { + const { header, mobileHeader } = props; + + return ( +
+ + + + {mobileHeader && mobileHeader} +
+ ); +}); diff --git a/web/core/components/core/content-overflow-HOC.tsx b/apps/web/core/components/core/content-overflow-HOC.tsx similarity index 100% rename from web/core/components/core/content-overflow-HOC.tsx rename to apps/web/core/components/core/content-overflow-HOC.tsx diff --git a/web/core/components/core/content-wrapper.tsx b/apps/web/core/components/core/content-wrapper.tsx similarity index 100% rename from web/core/components/core/content-wrapper.tsx rename to apps/web/core/components/core/content-wrapper.tsx diff --git a/web/core/components/core/description-versions/dropdown-item.tsx b/apps/web/core/components/core/description-versions/dropdown-item.tsx similarity index 100% rename from web/core/components/core/description-versions/dropdown-item.tsx rename to apps/web/core/components/core/description-versions/dropdown-item.tsx diff --git a/web/core/components/core/description-versions/dropdown.tsx b/apps/web/core/components/core/description-versions/dropdown.tsx similarity index 100% rename from web/core/components/core/description-versions/dropdown.tsx rename to apps/web/core/components/core/description-versions/dropdown.tsx diff --git a/web/core/components/pages/editor/header/index.ts b/apps/web/core/components/core/description-versions/index.ts similarity index 100% rename from web/core/components/pages/editor/header/index.ts rename to apps/web/core/components/core/description-versions/index.ts diff --git a/web/core/components/core/description-versions/modal.tsx b/apps/web/core/components/core/description-versions/modal.tsx similarity index 96% rename from web/core/components/core/description-versions/modal.tsx rename to apps/web/core/components/core/description-versions/modal.tsx index 984a52658..daa42cf30 100644 --- a/web/core/components/core/description-versions/modal.tsx +++ b/apps/web/core/components/core/description-versions/modal.tsx @@ -2,7 +2,7 @@ import { useCallback, useRef } from "react"; import { observer } from "mobx-react"; import { ChevronLeft, ChevronRight, Copy } from "lucide-react"; // plane imports -import { EditorReadOnlyRefApi } from "@plane/editor"; +import type { EditorRefApi } from "@plane/editor"; import { useTranslation } from "@plane/i18n"; import { TDescriptionVersion } from "@plane/types"; import { @@ -19,7 +19,7 @@ import { } from "@plane/ui"; import { calculateTimeAgo, cn, copyTextToClipboard, getFileURL } from "@plane/utils"; // components -import { RichTextReadOnlyEditor } from "@/components/editor"; +import { RichTextEditor } from "@/components/editor"; // hooks import { useMember, useWorkspace } from "@/hooks/store"; @@ -52,7 +52,7 @@ export const DescriptionVersionsModal: React.FC = observer((props) => { workspaceSlug, } = props; // refs - const editorRef = useRef(null); + const editorRef = useRef(null); // store hooks const { getUserDetails } = useMember(); const { getWorkspaceBySlug } = useWorkspace(); @@ -131,7 +131,8 @@ export const DescriptionVersionsModal: React.FC = observer((props) => { {/* Version description */}
{activeVersionDescription ? ( - = ({ title, handleClose, isOpen, o return ( - + = (props) => { return ( <> setSearchTerm("")} appear> - + = (props) => {
-
+
= (props) => { const [referenceElement, setReferenceElement] = useState(null); const [popperElement, setPopperElement] = useState(null); // refs - const editorRef = useRef(null); - const responseRef = useRef(null); + const editorRef = useRef(null); + const responseRef = useRef(null); // popper const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: placement ?? "auto", @@ -217,7 +216,8 @@ export const GptAssistantPopover: React.FC = (props) => { {prompt && (
Content: - = (props) => { {response !== "" && (
Response: - ${response}

`} ref={responseRef} diff --git a/web/core/components/core/modals/index.ts b/apps/web/core/components/core/modals/index.ts similarity index 100% rename from web/core/components/core/modals/index.ts rename to apps/web/core/components/core/modals/index.ts diff --git a/web/core/components/core/modals/issue-search-modal-empty-state.tsx b/apps/web/core/components/core/modals/issue-search-modal-empty-state.tsx similarity index 100% rename from web/core/components/core/modals/issue-search-modal-empty-state.tsx rename to apps/web/core/components/core/modals/issue-search-modal-empty-state.tsx diff --git a/web/core/components/core/modals/user-image-upload-modal.tsx b/apps/web/core/components/core/modals/user-image-upload-modal.tsx similarity index 99% rename from web/core/components/core/modals/user-image-upload-modal.tsx rename to apps/web/core/components/core/modals/user-image-upload-modal.tsx index a7693b8da..e411c0234 100644 --- a/web/core/components/core/modals/user-image-upload-modal.tsx +++ b/apps/web/core/components/core/modals/user-image-upload-modal.tsx @@ -7,7 +7,7 @@ import { UserCircle2 } from "lucide-react"; import { Transition, Dialog } from "@headlessui/react"; // plane imports import { ACCEPTED_AVATAR_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants"; -import { EFileAssetType } from "@plane/types/src/enums"; +import { EFileAssetType } from "@plane/types"; import { Button, TOAST_TYPE, setToast } from "@plane/ui"; import { getAssetIdFromUrl, getFileURL, checkURLValidity } from "@plane/utils"; // helpers diff --git a/web/core/components/core/modals/workspace-image-upload-modal.tsx b/apps/web/core/components/core/modals/workspace-image-upload-modal.tsx similarity index 99% rename from web/core/components/core/modals/workspace-image-upload-modal.tsx rename to apps/web/core/components/core/modals/workspace-image-upload-modal.tsx index 0bebeb653..314702346 100644 --- a/web/core/components/core/modals/workspace-image-upload-modal.tsx +++ b/apps/web/core/components/core/modals/workspace-image-upload-modal.tsx @@ -7,7 +7,7 @@ import { UserCircle2 } from "lucide-react"; import { Transition, Dialog } from "@headlessui/react"; // plane imports import { ACCEPTED_AVATAR_IMAGE_MIME_TYPES_FOR_REACT_DROPZONE, MAX_FILE_SIZE } from "@plane/constants"; -import { EFileAssetType } from "@plane/types/src/enums"; +import { EFileAssetType } from "@plane/types"; import { Button, TOAST_TYPE, setToast } from "@plane/ui"; import { getAssetIdFromUrl, getFileURL, checkURLValidity } from "@plane/utils"; // helpers diff --git a/web/core/components/core/multiple-select/entity-select-action.tsx b/apps/web/core/components/core/multiple-select/entity-select-action.tsx similarity index 100% rename from web/core/components/core/multiple-select/entity-select-action.tsx rename to apps/web/core/components/core/multiple-select/entity-select-action.tsx diff --git a/web/core/components/core/multiple-select/group-select-action.tsx b/apps/web/core/components/core/multiple-select/group-select-action.tsx similarity index 100% rename from web/core/components/core/multiple-select/group-select-action.tsx rename to apps/web/core/components/core/multiple-select/group-select-action.tsx diff --git a/web/core/components/core/multiple-select/index.ts b/apps/web/core/components/core/multiple-select/index.ts similarity index 100% rename from web/core/components/core/multiple-select/index.ts rename to apps/web/core/components/core/multiple-select/index.ts diff --git a/web/core/components/core/multiple-select/select-group.tsx b/apps/web/core/components/core/multiple-select/select-group.tsx similarity index 100% rename from web/core/components/core/multiple-select/select-group.tsx rename to apps/web/core/components/core/multiple-select/select-group.tsx diff --git a/web/core/components/core/page-title.tsx b/apps/web/core/components/core/page-title.tsx similarity index 100% rename from web/core/components/core/page-title.tsx rename to apps/web/core/components/core/page-title.tsx diff --git a/web/core/components/core/render-if-visible-HOC.tsx b/apps/web/core/components/core/render-if-visible-HOC.tsx similarity index 100% rename from web/core/components/core/render-if-visible-HOC.tsx rename to apps/web/core/components/core/render-if-visible-HOC.tsx diff --git a/web/core/components/core/sidebar/index.ts b/apps/web/core/components/core/sidebar/index.ts similarity index 100% rename from web/core/components/core/sidebar/index.ts rename to apps/web/core/components/core/sidebar/index.ts diff --git a/web/core/components/core/sidebar/progress-chart.tsx b/apps/web/core/components/core/sidebar/progress-chart.tsx similarity index 100% rename from web/core/components/core/sidebar/progress-chart.tsx rename to apps/web/core/components/core/sidebar/progress-chart.tsx diff --git a/apps/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx b/apps/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx new file mode 100644 index 000000000..764143176 --- /dev/null +++ b/apps/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { observer } from "mobx-react"; +import { PanelRight } from "lucide-react"; +import { useAppTheme } from "@/hooks/store"; + +export const SidebarHamburgerToggle = observer(() => { + // store hooks + const { toggleSidebar } = useAppTheme(); + + const handleClick = (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + toggleSidebar(); + }; + + return ( + + ); +}); diff --git a/web/core/components/core/sidebar/single-progress-stats.tsx b/apps/web/core/components/core/sidebar/single-progress-stats.tsx similarity index 100% rename from web/core/components/core/sidebar/single-progress-stats.tsx rename to apps/web/core/components/core/sidebar/single-progress-stats.tsx diff --git a/web/core/components/core/theme/color-picker-input.tsx b/apps/web/core/components/core/theme/color-picker-input.tsx similarity index 100% rename from web/core/components/core/theme/color-picker-input.tsx rename to apps/web/core/components/core/theme/color-picker-input.tsx diff --git a/web/core/components/core/theme/custom-theme-selector.tsx b/apps/web/core/components/core/theme/custom-theme-selector.tsx similarity index 90% rename from web/core/components/core/theme/custom-theme-selector.tsx rename to apps/web/core/components/core/theme/custom-theme-selector.tsx index d66fbe82f..3cc5469af 100644 --- a/web/core/components/core/theme/custom-theme-selector.tsx +++ b/apps/web/core/components/core/theme/custom-theme-selector.tsx @@ -4,11 +4,13 @@ import { useMemo } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // types +import { PROFILE_SETTINGS_TRACKER_ELEMENTS, PROFILE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IUserTheme } from "@plane/types"; // ui import { Button, InputColorPicker, setPromiseToast } from "@plane/ui"; // hooks +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; import { useUserProfile } from "@/hooks/store"; type TCustomThemeSelector = { @@ -81,6 +83,35 @@ export const CustomThemeSelector: React.FC = observer((pro message: () => t("failed_to_update_the_theme"), }, }); + updateCurrentUserThemePromise + .then(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.THEME_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.theme_updated, + payload: { + theme: payload.theme, + }, + state: "SUCCESS", + }, + }); + }) + .catch(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.THEME_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.theme_updated, + payload: { + theme: payload.theme, + }, + state: "ERROR", + }, + }); + }); return; }; diff --git a/web/core/components/core/theme/index.ts b/apps/web/core/components/core/theme/index.ts similarity index 100% rename from web/core/components/core/theme/index.ts rename to apps/web/core/components/core/theme/index.ts diff --git a/web/core/components/core/theme/theme-switch.tsx b/apps/web/core/components/core/theme/theme-switch.tsx similarity index 100% rename from web/core/components/core/theme/theme-switch.tsx rename to apps/web/core/components/core/theme/theme-switch.tsx diff --git a/web/core/components/cycles/active-cycle/cycle-stats.tsx b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx similarity index 99% rename from web/core/components/cycles/active-cycle/cycle-stats.tsx rename to apps/web/core/components/cycles/active-cycle/cycle-stats.tsx index 77e36f334..4f31e06d7 100644 --- a/web/core/components/cycles/active-cycle/cycle-stats.tsx +++ b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx @@ -7,9 +7,8 @@ import { CalendarCheck } from "lucide-react"; // headless ui import { Tab } from "@headlessui/react"; // plane imports -import { EIssuesStoreType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { ICycle, IIssueFilterOptions } from "@plane/types"; +import { EIssuesStoreType, ICycle, IIssueFilterOptions } from "@plane/types"; // ui import { Tooltip, Loader, PriorityIcon, Avatar } from "@plane/ui"; import { cn, renderFormattedDate, renderFormattedDateWithoutYear, getFileURL } from "@plane/utils"; diff --git a/web/core/components/cycles/active-cycle/index.ts b/apps/web/core/components/cycles/active-cycle/index.ts similarity index 100% rename from web/core/components/cycles/active-cycle/index.ts rename to apps/web/core/components/cycles/active-cycle/index.ts diff --git a/web/core/components/cycles/active-cycle/productivity.tsx b/apps/web/core/components/cycles/active-cycle/productivity.tsx similarity index 100% rename from web/core/components/cycles/active-cycle/productivity.tsx rename to apps/web/core/components/cycles/active-cycle/productivity.tsx diff --git a/web/core/components/cycles/active-cycle/progress.tsx b/apps/web/core/components/cycles/active-cycle/progress.tsx similarity index 100% rename from web/core/components/cycles/active-cycle/progress.tsx rename to apps/web/core/components/cycles/active-cycle/progress.tsx diff --git a/web/core/components/cycles/active-cycle/use-cycles-details.ts b/apps/web/core/components/cycles/active-cycle/use-cycles-details.ts similarity index 96% rename from web/core/components/cycles/active-cycle/use-cycles-details.ts rename to apps/web/core/components/cycles/active-cycle/use-cycles-details.ts index e0f48869a..447df1eb0 100644 --- a/web/core/components/cycles/active-cycle/use-cycles-details.ts +++ b/apps/web/core/components/cycles/active-cycle/use-cycles-details.ts @@ -2,8 +2,8 @@ import { useCallback } from "react"; import isEqual from "lodash/isEqual"; import { useRouter } from "next/navigation"; import useSWR from "swr"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; import { CYCLE_ISSUES_WITH_PARAMS } from "@/constants/fetch-keys"; import { useCycle, useIssues } from "@/hooks/store"; diff --git a/web/core/components/cycles/analytics-sidebar/index.ts b/apps/web/core/components/cycles/analytics-sidebar/index.ts similarity index 100% rename from web/core/components/cycles/analytics-sidebar/index.ts rename to apps/web/core/components/cycles/analytics-sidebar/index.ts diff --git a/web/core/components/cycles/analytics-sidebar/issue-progress.tsx b/apps/web/core/components/cycles/analytics-sidebar/issue-progress.tsx similarity index 97% rename from web/core/components/cycles/analytics-sidebar/issue-progress.tsx rename to apps/web/core/components/cycles/analytics-sidebar/issue-progress.tsx index 3b2c29250..90586d331 100644 --- a/web/core/components/cycles/analytics-sidebar/issue-progress.tsx +++ b/apps/web/core/components/cycles/analytics-sidebar/issue-progress.tsx @@ -7,9 +7,9 @@ import { observer } from "mobx-react"; import { useSearchParams } from "next/navigation"; import { ChevronUp, ChevronDown } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; +import { EIssueFilterType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { ICycle, IIssueFilterOptions, TCyclePlotType, TProgressSnapshot } from "@plane/types"; +import { EIssuesStoreType, ICycle, IIssueFilterOptions, TCyclePlotType, TProgressSnapshot } from "@plane/types"; // components import { getDate } from "@plane/utils"; import { CycleProgressStats } from "@/components/cycles"; diff --git a/web/core/components/cycles/analytics-sidebar/progress-stats.tsx b/apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx similarity index 100% rename from web/core/components/cycles/analytics-sidebar/progress-stats.tsx rename to apps/web/core/components/cycles/analytics-sidebar/progress-stats.tsx diff --git a/web/core/components/cycles/analytics-sidebar/root.tsx b/apps/web/core/components/cycles/analytics-sidebar/root.tsx similarity index 100% rename from web/core/components/cycles/analytics-sidebar/root.tsx rename to apps/web/core/components/cycles/analytics-sidebar/root.tsx diff --git a/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx b/apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx similarity index 100% rename from web/core/components/cycles/analytics-sidebar/sidebar-details.tsx rename to apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx diff --git a/web/core/components/cycles/analytics-sidebar/sidebar-header.tsx b/apps/web/core/components/cycles/analytics-sidebar/sidebar-header.tsx similarity index 79% rename from web/core/components/cycles/analytics-sidebar/sidebar-header.tsx rename to apps/web/core/components/cycles/analytics-sidebar/sidebar-header.tsx index bad633516..1fa7c26e0 100644 --- a/web/core/components/cycles/analytics-sidebar/sidebar-header.tsx +++ b/apps/web/core/components/cycles/analytics-sidebar/sidebar-header.tsx @@ -1,11 +1,17 @@ "use client"; -import React, { FC, useEffect, useState } from "react"; +import React, { FC, useEffect } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; import { ArrowRight, ChevronRight } from "lucide-react"; // Plane Imports -import { CYCLE_TRACKER_EVENTS, CYCLE_STATUS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { + CYCLE_TRACKER_EVENTS, + CYCLE_STATUS, + EUserPermissions, + EUserPermissionsLevel, + CYCLE_TRACKER_ELEMENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { ICycle } from "@plane/types"; import { setToast, TOAST_TYPE } from "@plane/ui"; @@ -13,13 +19,11 @@ import { getDate, renderFormattedPayloadDate } from "@plane/utils"; // components import { DateRangeDropdown } from "@/components/dropdowns"; // hooks -import { useCycle, useEventTracker, useUserPermissions } from "@/hooks/store"; +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; +import { useCycle, useUserPermissions } from "@/hooks/store"; import { useTimeZoneConverter } from "@/hooks/use-timezone-converter"; // services import { CycleService } from "@/services/cycle.service"; -// local imports -import { ArchiveCycleModal } from "../archived-cycles"; -import { CycleDeleteModal } from "../delete-modal"; type Props = { workspaceSlug: string; @@ -38,13 +42,9 @@ const cycleService = new CycleService(); export const CycleSidebarHeader: FC = observer((props) => { const { workspaceSlug, projectId, cycleDetails, handleClose, isArchived = false } = props; - // states - const [archiveCycleModal, setArchiveCycleModal] = useState(false); - const [cycleDeleteModal, setCycleDeleteModal] = useState(false); // hooks const { allowPermissions } = useUserPermissions(); const { updateCycleDetails } = useCycle(); - const { captureCycleEvent } = useEventTracker(); const { t } = useTranslation(); const { renderFormattedDateInUserTimezone, getProjectUTCOffset } = useTimeZoneConverter(projectId); @@ -61,29 +61,36 @@ export const CycleSidebarHeader: FC = observer((props) => { const currentCycle = CYCLE_STATUS.find((status) => status.value === cycleStatus); - const submitChanges = async (data: Partial, changedProperty: string) => { + const submitChanges = async (data: Partial) => { if (!workspaceSlug || !projectId || !cycleDetails.id) return; await updateCycleDetails(workspaceSlug.toString(), projectId.toString(), cycleDetails.id.toString(), data) - .then((res) => { - captureCycleEvent({ - eventName: CYCLE_TRACKER_EVENTS.update, - payload: { - ...res, - changed_properties: [changedProperty], - element: "Right side-peek", + .then(() => { + captureElementAndEvent({ + element: { + elementName: CYCLE_TRACKER_ELEMENTS.RIGHT_SIDEBAR, + }, + event: { + eventName: CYCLE_TRACKER_EVENTS.update, state: "SUCCESS", + payload: { + id: cycleDetails.id, + }, }, }); }) .catch(() => { - captureCycleEvent({ - eventName: CYCLE_TRACKER_EVENTS.update, - payload: { - ...data, - element: "Right side-peek", - state: "FAILED", + captureElementAndEvent({ + element: { + elementName: CYCLE_TRACKER_ELEMENTS.RIGHT_SIDEBAR, + }, + event: { + eventName: CYCLE_TRACKER_EVENTS.update, + state: "ERROR", + payload: { + id: cycleDetails.id, + }, }, }); }); @@ -122,7 +129,7 @@ export const CycleSidebarHeader: FC = observer((props) => { isDateValid = true; } if (isDateValid) { - submitChanges(payload, "date_range"); + submitChanges(payload); setToast({ type: TOAST_TYPE.SUCCESS, title: t("project_cycles.action.update.success.title"), @@ -145,24 +152,6 @@ export const CycleSidebarHeader: FC = observer((props) => { return ( <> - {cycleDetails && workspaceSlug && projectId && ( - <> - setArchiveCycleModal(false)} - /> - setCycleDeleteModal(false)} - workspaceSlug={workspaceSlug.toString()} - projectId={projectId.toString()} - /> - - )}
- - )} -
- ); - })} -
- ) : ( - <> - {!hideIcon && } - {placeholder} - - )} - {dropdownArrow && ( -
-
diff --git a/web/core/components/exporter/export-modal.tsx b/apps/web/core/components/exporter/export-modal.tsx similarity index 100% rename from web/core/components/exporter/export-modal.tsx rename to apps/web/core/components/exporter/export-modal.tsx diff --git a/web/core/components/exporter/guide.tsx b/apps/web/core/components/exporter/guide.tsx similarity index 100% rename from web/core/components/exporter/guide.tsx rename to apps/web/core/components/exporter/guide.tsx diff --git a/web/core/components/exporter/index.tsx b/apps/web/core/components/exporter/index.tsx similarity index 100% rename from web/core/components/exporter/index.tsx rename to apps/web/core/components/exporter/index.tsx diff --git a/web/core/components/exporter/prev-exports.tsx b/apps/web/core/components/exporter/prev-exports.tsx similarity index 100% rename from web/core/components/exporter/prev-exports.tsx rename to apps/web/core/components/exporter/prev-exports.tsx diff --git a/web/core/components/exporter/single-export.tsx b/apps/web/core/components/exporter/single-export.tsx similarity index 100% rename from web/core/components/exporter/single-export.tsx rename to apps/web/core/components/exporter/single-export.tsx diff --git a/web/core/components/gantt-chart/blocks/block-row.tsx b/apps/web/core/components/gantt-chart/blocks/block-row.tsx similarity index 100% rename from web/core/components/gantt-chart/blocks/block-row.tsx rename to apps/web/core/components/gantt-chart/blocks/block-row.tsx diff --git a/web/core/components/gantt-chart/blocks/block.tsx b/apps/web/core/components/gantt-chart/blocks/block.tsx similarity index 100% rename from web/core/components/gantt-chart/blocks/block.tsx rename to apps/web/core/components/gantt-chart/blocks/block.tsx diff --git a/web/core/components/gantt-chart/chart/header.tsx b/apps/web/core/components/gantt-chart/chart/header.tsx similarity index 100% rename from web/core/components/gantt-chart/chart/header.tsx rename to apps/web/core/components/gantt-chart/chart/header.tsx diff --git a/web/core/components/gantt-chart/chart/index.ts b/apps/web/core/components/gantt-chart/chart/index.ts similarity index 100% rename from web/core/components/gantt-chart/chart/index.ts rename to apps/web/core/components/gantt-chart/chart/index.ts diff --git a/web/core/components/gantt-chart/chart/main-content.tsx b/apps/web/core/components/gantt-chart/chart/main-content.tsx similarity index 96% rename from web/core/components/gantt-chart/chart/main-content.tsx rename to apps/web/core/components/gantt-chart/chart/main-content.tsx index 5f9fb0043..278994b0b 100644 --- a/web/core/components/gantt-chart/chart/main-content.tsx +++ b/apps/web/core/components/gantt-chart/chart/main-content.tsx @@ -6,23 +6,18 @@ import { ChartDataType, IBlockUpdateData, IBlockUpdateDependencyData, IGanttBloc import { cn, getDate } from "@plane/utils"; // components import { MultipleSelectGroup } from "@/components/core"; -import { - GanttChartBlocksList, - GanttChartSidebar, - MonthChartView, - QuarterChartView, - WeekChartView, -} from "@/components/gantt-chart"; +import { GanttChartSidebar, MonthChartView, QuarterChartView, WeekChartView } from "@/components/gantt-chart"; // helpers // hooks import { useTimeLineChartStore } from "@/hooks/use-timeline-chart"; // plane web components import { TimelineDependencyPaths, TimelineDraggablePath } from "@/plane-web/components/gantt-chart"; +import { GanttChartRowList } from "@/plane-web/components/gantt-chart/blocks/block-row-list"; +import { GanttChartBlocksList } from "@/plane-web/components/gantt-chart/blocks/blocks-list"; import { IssueBulkOperationsRoot } from "@/plane-web/components/issues"; // plane web hooks import { useBulkOperationStatus } from "@/plane-web/hooks/use-bulk-operation-status"; // -import { GanttChartRowList } from "../blocks/block-row-list"; import { DEFAULT_BLOCK_WIDTH, GANTT_SELECT_GROUP, HEADER_HEIGHT } from "../constants"; import { getItemPositionWidth } from "../views"; import { TimelineDragHelper } from "./timeline-drag-helper"; diff --git a/web/core/components/gantt-chart/chart/root.tsx b/apps/web/core/components/gantt-chart/chart/root.tsx similarity index 96% rename from web/core/components/gantt-chart/chart/root.tsx rename to apps/web/core/components/gantt-chart/chart/root.tsx index b69254cae..11bc0ee54 100644 --- a/web/core/components/gantt-chart/chart/root.tsx +++ b/apps/web/core/components/gantt-chart/chart/root.tsx @@ -1,7 +1,7 @@ import { FC, useEffect, useState } from "react"; +import { createPortal } from "react-dom"; import { observer } from "mobx-react"; // plane imports -import { EStartOfTheWeek } from "@plane/constants"; // components import type { ChartDataType, IBlockUpdateData, IBlockUpdateDependencyData, TGanttViews } from "@plane/types"; import { cn } from "@plane/utils"; @@ -177,10 +177,12 @@ export const ChartViewRoot: FC = observer((props) => { scrollContainer.scrollLeft = scrollWidth; }; - return ( + const portalContainer = document.getElementById("full-screen-portal") as HTMLElement; + + const content = (
@@ -218,4 +220,6 @@ export const ChartViewRoot: FC = observer((props) => { />
); + + return fullScreenMode && portalContainer ? createPortal(content, portalContainer) : content; }); diff --git a/web/core/components/gantt-chart/chart/timeline-drag-helper.tsx b/apps/web/core/components/gantt-chart/chart/timeline-drag-helper.tsx similarity index 100% rename from web/core/components/gantt-chart/chart/timeline-drag-helper.tsx rename to apps/web/core/components/gantt-chart/chart/timeline-drag-helper.tsx diff --git a/web/core/components/gantt-chart/chart/views/index.ts b/apps/web/core/components/gantt-chart/chart/views/index.ts similarity index 100% rename from web/core/components/gantt-chart/chart/views/index.ts rename to apps/web/core/components/gantt-chart/chart/views/index.ts diff --git a/web/core/components/gantt-chart/chart/views/month.tsx b/apps/web/core/components/gantt-chart/chart/views/month.tsx similarity index 100% rename from web/core/components/gantt-chart/chart/views/month.tsx rename to apps/web/core/components/gantt-chart/chart/views/month.tsx diff --git a/web/core/components/gantt-chart/chart/views/quarter.tsx b/apps/web/core/components/gantt-chart/chart/views/quarter.tsx similarity index 100% rename from web/core/components/gantt-chart/chart/views/quarter.tsx rename to apps/web/core/components/gantt-chart/chart/views/quarter.tsx diff --git a/web/core/components/gantt-chart/chart/views/week.tsx b/apps/web/core/components/gantt-chart/chart/views/week.tsx similarity index 100% rename from web/core/components/gantt-chart/chart/views/week.tsx rename to apps/web/core/components/gantt-chart/chart/views/week.tsx diff --git a/web/core/components/gantt-chart/constants.ts b/apps/web/core/components/gantt-chart/constants.ts similarity index 100% rename from web/core/components/gantt-chart/constants.ts rename to apps/web/core/components/gantt-chart/constants.ts diff --git a/web/core/components/gantt-chart/contexts/index.tsx b/apps/web/core/components/gantt-chart/contexts/index.tsx similarity index 94% rename from web/core/components/gantt-chart/contexts/index.tsx rename to apps/web/core/components/gantt-chart/contexts/index.tsx index 7a7c63f83..6d268be7e 100644 --- a/web/core/components/gantt-chart/contexts/index.tsx +++ b/apps/web/core/components/gantt-chart/contexts/index.tsx @@ -4,6 +4,7 @@ export enum ETimeLineTypeType { ISSUE = "ISSUE", MODULE = "MODULE", PROJECT = "PROJECT", + GROUPED = "GROUPED", } export const TimeLineTypeContext = createContext(undefined); diff --git a/web/core/components/gantt-chart/data/index.ts b/apps/web/core/components/gantt-chart/data/index.ts similarity index 96% rename from web/core/components/gantt-chart/data/index.ts rename to apps/web/core/components/gantt-chart/data/index.ts index 1871278f8..897af9ebd 100644 --- a/web/core/components/gantt-chart/data/index.ts +++ b/apps/web/core/components/gantt-chart/data/index.ts @@ -1,6 +1,5 @@ // types -import { EStartOfTheWeek } from "@plane/constants"; -import type { WeekMonthDataType, ChartDataType, TGanttViews } from "@plane/types"; +import { EStartOfTheWeek, WeekMonthDataType, ChartDataType, TGanttViews } from "@plane/types"; // constants export const generateWeeks = (startOfWeek: EStartOfTheWeek = EStartOfTheWeek.SUNDAY): WeekMonthDataType[] => [ diff --git a/web/core/components/gantt-chart/helpers/add-block.tsx b/apps/web/core/components/gantt-chart/helpers/add-block.tsx similarity index 99% rename from web/core/components/gantt-chart/helpers/add-block.tsx rename to apps/web/core/components/gantt-chart/helpers/add-block.tsx index fed218f91..742591a26 100644 --- a/web/core/components/gantt-chart/helpers/add-block.tsx +++ b/apps/web/core/components/gantt-chart/helpers/add-block.tsx @@ -48,6 +48,7 @@ export const ChartAddBlock: React.FC = observer((props) => { blockUpdateHandler(block.data, { start_date: renderFormattedPayloadDate(startDate) ?? undefined, target_date: renderFormattedPayloadDate(endDate) ?? undefined, + meta: block.meta, }); }; diff --git a/web/core/components/gantt-chart/helpers/blockResizables/left-resizable.tsx b/apps/web/core/components/gantt-chart/helpers/blockResizables/left-resizable.tsx similarity index 100% rename from web/core/components/gantt-chart/helpers/blockResizables/left-resizable.tsx rename to apps/web/core/components/gantt-chart/helpers/blockResizables/left-resizable.tsx diff --git a/web/core/components/gantt-chart/helpers/blockResizables/right-resizable.tsx b/apps/web/core/components/gantt-chart/helpers/blockResizables/right-resizable.tsx similarity index 100% rename from web/core/components/gantt-chart/helpers/blockResizables/right-resizable.tsx rename to apps/web/core/components/gantt-chart/helpers/blockResizables/right-resizable.tsx diff --git a/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts b/apps/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts similarity index 100% rename from web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts rename to apps/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts diff --git a/web/core/components/gantt-chart/helpers/draggable.tsx b/apps/web/core/components/gantt-chart/helpers/draggable.tsx similarity index 97% rename from web/core/components/gantt-chart/helpers/draggable.tsx rename to apps/web/core/components/gantt-chart/helpers/draggable.tsx index 6031f3efd..98eda46c4 100644 --- a/web/core/components/gantt-chart/helpers/draggable.tsx +++ b/apps/web/core/components/gantt-chart/helpers/draggable.tsx @@ -53,7 +53,7 @@ export const ChartDraggable: React.FC = observer((props) => { })} onMouseDown={(e) => enableBlockMove && handleBlockDrag(e, "move")} > - {blockToRender(block.data)} + {blockToRender({ ...block.data, meta: block.meta })}
{/* right resize drag handle */} = observer((props) => {
{t("common.duration")}
- + {sidebarToRender && sidebarToRender({ title, diff --git a/web/core/components/gantt-chart/sidebar/utils.ts b/apps/web/core/components/gantt-chart/sidebar/utils.ts similarity index 100% rename from web/core/components/gantt-chart/sidebar/utils.ts rename to apps/web/core/components/gantt-chart/sidebar/utils.ts diff --git a/web/core/components/gantt-chart/views/helpers.ts b/apps/web/core/components/gantt-chart/views/helpers.ts similarity index 100% rename from web/core/components/gantt-chart/views/helpers.ts rename to apps/web/core/components/gantt-chart/views/helpers.ts diff --git a/web/core/components/gantt-chart/views/index.ts b/apps/web/core/components/gantt-chart/views/index.ts similarity index 100% rename from web/core/components/gantt-chart/views/index.ts rename to apps/web/core/components/gantt-chart/views/index.ts diff --git a/web/core/components/gantt-chart/views/month-view.ts b/apps/web/core/components/gantt-chart/views/month-view.ts similarity index 100% rename from web/core/components/gantt-chart/views/month-view.ts rename to apps/web/core/components/gantt-chart/views/month-view.ts diff --git a/web/core/components/gantt-chart/views/quarter-view.ts b/apps/web/core/components/gantt-chart/views/quarter-view.ts similarity index 100% rename from web/core/components/gantt-chart/views/quarter-view.ts rename to apps/web/core/components/gantt-chart/views/quarter-view.ts diff --git a/web/core/components/gantt-chart/views/week-view.ts b/apps/web/core/components/gantt-chart/views/week-view.ts similarity index 98% rename from web/core/components/gantt-chart/views/week-view.ts rename to apps/web/core/components/gantt-chart/views/week-view.ts index c7b4ce6f4..a1e2b9db7 100644 --- a/web/core/components/gantt-chart/views/week-view.ts +++ b/apps/web/core/components/gantt-chart/views/week-view.ts @@ -1,6 +1,5 @@ // -import { EStartOfTheWeek } from "@plane/constants"; -import type { ChartDataType } from "@plane/types"; +import { EStartOfTheWeek, ChartDataType } from "@plane/types"; import { months, generateWeeks } from "../data"; import { getNumberOfDaysBetweenTwoDates, getWeekNumberByDate } from "./helpers"; export interface IDayBlock { diff --git a/web/core/components/global/index.ts b/apps/web/core/components/global/index.ts similarity index 100% rename from web/core/components/global/index.ts rename to apps/web/core/components/global/index.ts diff --git a/apps/web/core/components/global/product-updates/footer.tsx b/apps/web/core/components/global/product-updates/footer.tsx new file mode 100644 index 000000000..c6ef12036 --- /dev/null +++ b/apps/web/core/components/global/product-updates/footer.tsx @@ -0,0 +1,66 @@ +import Image from "next/image"; +import { useTranslation } from "@plane/i18n"; +// ui +import { getButtonStyling } from "@plane/ui"; +// helpers +import { cn } from "@plane/utils"; +// assets +import PlaneLogo from "@/public/plane-logos/blue-without-text.png"; + +export const ProductUpdatesFooter = () => { + const { t } = useTranslation(); + return ( +
+ ); +}; diff --git a/web/core/components/global/product-updates/index.ts b/apps/web/core/components/global/product-updates/index.ts similarity index 100% rename from web/core/components/global/product-updates/index.ts rename to apps/web/core/components/global/product-updates/index.ts diff --git a/web/core/components/global/product-updates/modal.tsx b/apps/web/core/components/global/product-updates/modal.tsx similarity index 97% rename from web/core/components/global/product-updates/modal.tsx rename to apps/web/core/components/global/product-updates/modal.tsx index b8982ce49..74bea07a5 100644 --- a/web/core/components/global/product-updates/modal.tsx +++ b/apps/web/core/components/global/product-updates/modal.tsx @@ -1,5 +1,5 @@ import { FC } from "react"; -import { observer } from "mobx-react-lite"; +import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; // ui import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; diff --git a/web/core/components/global/timezone-select.tsx b/apps/web/core/components/global/timezone-select.tsx similarity index 100% rename from web/core/components/global/timezone-select.tsx rename to apps/web/core/components/global/timezone-select.tsx diff --git a/web/core/components/home/home-dashboard-widgets.tsx b/apps/web/core/components/home/home-dashboard-widgets.tsx similarity index 100% rename from web/core/components/home/home-dashboard-widgets.tsx rename to apps/web/core/components/home/home-dashboard-widgets.tsx diff --git a/web/core/components/home/index.ts b/apps/web/core/components/home/index.ts similarity index 100% rename from web/core/components/home/index.ts rename to apps/web/core/components/home/index.ts diff --git a/web/core/components/home/root.tsx b/apps/web/core/components/home/root.tsx similarity index 75% rename from web/core/components/home/root.tsx rename to apps/web/core/components/home/root.tsx index 4c25bc3f6..a55f40c97 100644 --- a/web/core/components/home/root.tsx +++ b/apps/web/core/components/home/root.tsx @@ -1,18 +1,20 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -// components import useSWR from "swr"; +// plane imports import { PRODUCT_TOUR_TRACKER_EVENTS } from "@plane/constants"; import { ContentWrapper } from "@plane/ui"; import { cn } from "@plane/utils"; +// components import { TourRoot } from "@/components/onboarding"; -// constants // helpers +import { captureSuccess } from "@/helpers/event-tracker.helper"; // hooks -import { useUserProfile, useEventTracker, useUser } from "@/hooks/store"; +import { useUserProfile, useUser } from "@/hooks/store"; import { useHome } from "@/hooks/store/use-home"; -import useSize from "@/hooks/use-window-size"; +// plane web components import { HomePeekOverviewsRoot } from "@/plane-web/components/home"; +// local imports import { DashboardWidgets } from "./home-dashboard-widgets"; import { UserGreetingsView } from "./user-greetings"; @@ -21,9 +23,7 @@ export const WorkspaceHomeView = observer(() => { const { workspaceSlug } = useParams(); const { data: currentUser } = useUser(); const { data: currentUserProfile, updateTourCompleted } = useUserProfile(); - const { captureEvent } = useEventTracker(); - const { toggleWidgetSettings, fetchWidgets } = useHome(); - const [windowWidth] = useSize(); + const { fetchWidgets } = useHome(); useSWR( workspaceSlug ? `HOME_DASHBOARD_WIDGETS_${workspaceSlug}` : null, @@ -38,9 +38,11 @@ export const WorkspaceHomeView = observer(() => { const handleTourCompleted = () => { updateTourCompleted() .then(() => { - captureEvent(PRODUCT_TOUR_TRACKER_EVENTS.complete, { - user_id: currentUser?.id, - state: "SUCCESS", + captureSuccess({ + eventName: PRODUCT_TOUR_TRACKER_EVENTS.complete, + payload: { + user_id: currentUser?.id, + }, }); }) .catch((error) => { @@ -59,11 +61,9 @@ export const WorkspaceHomeView = observer(() => { <> = 768, - })} + className={cn("gap-6 bg-custom-background-100 max-w-[800px] mx-auto scrollbar-hide px-page-x lg:px-0")} > - {currentUser && toggleWidgetSettings(true)} />} + {currentUser && } diff --git a/web/core/components/home/user-greetings.tsx b/apps/web/core/components/home/user-greetings.tsx similarity index 56% rename from web/core/components/home/user-greetings.tsx rename to apps/web/core/components/home/user-greetings.tsx index 31fbab185..d88041d0a 100644 --- a/web/core/components/home/user-greetings.tsx +++ b/apps/web/core/components/home/user-greetings.tsx @@ -1,20 +1,17 @@ import { FC } from "react"; -import { Shapes } from "lucide-react"; // plane types import { useTranslation } from "@plane/i18n"; import { IUser } from "@plane/types"; // plane ui -import { Button } from "@plane/ui"; // hooks import { useCurrentTime } from "@/hooks/use-current-time"; export interface IUserGreetingsView { user: IUser; - handleWidgetModal: () => void; } export const UserGreetingsView: FC = (props) => { - const { user, handleWidgetModal } = props; + const { user } = props; // current time hook const { currentTime } = useCurrentTime(); // store hooks @@ -44,22 +41,16 @@ export const UserGreetingsView: FC = (props) => { const greeting = parseInt(hour, 10) < 12 ? "morning" : parseInt(hour, 10) < 18 ? "afternoon" : "evening"; return ( -
-
-

- {t("good")} {t(greeting)}, {user?.first_name} {user?.last_name} -

-
-
{greeting === "morning" ? "🌤️" : greeting === "afternoon" ? "🌥️" : "🌙️"}
-
- {weekDay}, {date} {timeString} -
-
-
- +
+

+ {t("good")} {t(greeting)}, {user?.first_name} {user?.last_name} +

+
+
{greeting === "morning" ? "🌤️" : greeting === "afternoon" ? "🌥️" : "🌙️"}
+
+ {weekDay}, {date} {timeString} +
+
); }; diff --git a/web/core/components/home/widgets/empty-states/index.ts b/apps/web/core/components/home/widgets/empty-states/index.ts similarity index 100% rename from web/core/components/home/widgets/empty-states/index.ts rename to apps/web/core/components/home/widgets/empty-states/index.ts diff --git a/web/core/components/home/widgets/empty-states/links.tsx b/apps/web/core/components/home/widgets/empty-states/links.tsx similarity index 100% rename from web/core/components/home/widgets/empty-states/links.tsx rename to apps/web/core/components/home/widgets/empty-states/links.tsx diff --git a/web/core/components/home/widgets/empty-states/no-projects.tsx b/apps/web/core/components/home/widgets/empty-states/no-projects.tsx similarity index 84% rename from web/core/components/home/widgets/empty-states/no-projects.tsx rename to apps/web/core/components/home/widgets/empty-states/no-projects.tsx index be4c8af64..7dd608b40 100644 --- a/web/core/components/home/widgets/empty-states/no-projects.tsx +++ b/apps/web/core/components/home/widgets/empty-states/no-projects.tsx @@ -5,20 +5,14 @@ import Link from "next/link"; import { useParams } from "next/navigation"; import { Briefcase, Check, Hotel, Users, X } from "lucide-react"; // plane ui -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useLocalStorage } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; import { cn, getFileURL } from "@plane/utils"; // helpers // hooks -import { - useCommandPalette, - useEventTracker, - useProject, - useUser, - useUserPermissions, - useWorkspace, -} from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useProject, useUser, useUserPermissions, useWorkspace } from "@/hooks/store"; // plane web constants export const NoProjectsEmptyState = observer(() => { @@ -27,7 +21,6 @@ export const NoProjectsEmptyState = observer(() => { // store hooks const { allowPermissions } = useUserPermissions(); const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { data: currentUser } = useUser(); const { joinedProjectIds } = useProject(); const { currentWorkspace: activeWorkspace } = useWorkspace(); @@ -51,7 +44,7 @@ export const NoProjectsEmptyState = observer(() => { id: "create-project", title: "home.empty.create_project.title", description: "home.empty.create_project.description", - icon: , + icon: , flag: "projects", cta: { text: "home.empty.create_project.cta", @@ -59,8 +52,8 @@ export const NoProjectsEmptyState = observer(() => { if (!canCreateProject) return; e.preventDefault(); e.stopPropagation(); - setTrackElement("Sidebar"); toggleCreateProjectModal(true); + captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); }, disabled: !canCreateProject, }, @@ -69,7 +62,7 @@ export const NoProjectsEmptyState = observer(() => { id: "invite-team", title: "home.empty.invite_team.title", description: "home.empty.invite_team.description", - icon: , + icon: , flag: "visited_members", cta: { text: "home.empty.invite_team.cta", @@ -81,7 +74,7 @@ export const NoProjectsEmptyState = observer(() => { id: "configure-workspace", title: "home.empty.configure_workspace.title", description: "home.empty.configure_workspace.description", - icon: , + icon: , flag: "visited_workspace", cta: { text: "home.empty.configure_workspace.cta", @@ -96,7 +89,7 @@ export const NoProjectsEmptyState = observer(() => { icon: currentUser?.avatar_url && currentUser?.avatar_url.trim() !== "" ? ( - + { ) : ( - + {(currentUser?.email ?? currentUser?.display_name ?? "?")[0]} @@ -149,17 +142,17 @@ export const NoProjectsEmptyState = observer(() => { {t("home.empty.not_right_now")}
-
+
{EMPTY_STATE_DATA.map((item) => { const isStateComplete = isComplete(item.flag); return (
{ > {item.icon}
-

{t(item.title)}

-

{t(item.description)}

+

{t(item.title)}

+

{t(item.description)}

{isStateComplete ? ( -
+
) : ( diff --git a/web/core/components/home/widgets/empty-states/recents.tsx b/apps/web/core/components/home/widgets/empty-states/recents.tsx similarity index 100% rename from web/core/components/home/widgets/empty-states/recents.tsx rename to apps/web/core/components/home/widgets/empty-states/recents.tsx diff --git a/web/core/components/home/widgets/empty-states/stickies.tsx b/apps/web/core/components/home/widgets/empty-states/stickies.tsx similarity index 100% rename from web/core/components/home/widgets/empty-states/stickies.tsx rename to apps/web/core/components/home/widgets/empty-states/stickies.tsx diff --git a/web/core/components/home/widgets/index.ts b/apps/web/core/components/home/widgets/index.ts similarity index 100% rename from web/core/components/home/widgets/index.ts rename to apps/web/core/components/home/widgets/index.ts diff --git a/web/core/components/home/widgets/links/action.tsx b/apps/web/core/components/home/widgets/links/action.tsx similarity index 100% rename from web/core/components/home/widgets/links/action.tsx rename to apps/web/core/components/home/widgets/links/action.tsx diff --git a/web/core/components/home/widgets/links/create-update-link-modal.tsx b/apps/web/core/components/home/widgets/links/create-update-link-modal.tsx similarity index 100% rename from web/core/components/home/widgets/links/create-update-link-modal.tsx rename to apps/web/core/components/home/widgets/links/create-update-link-modal.tsx diff --git a/web/core/components/home/widgets/links/index.ts b/apps/web/core/components/home/widgets/links/index.ts similarity index 100% rename from web/core/components/home/widgets/links/index.ts rename to apps/web/core/components/home/widgets/links/index.ts diff --git a/web/core/components/home/widgets/links/link-detail.tsx b/apps/web/core/components/home/widgets/links/link-detail.tsx similarity index 100% rename from web/core/components/home/widgets/links/link-detail.tsx rename to apps/web/core/components/home/widgets/links/link-detail.tsx diff --git a/web/core/components/home/widgets/links/links.tsx b/apps/web/core/components/home/widgets/links/links.tsx similarity index 100% rename from web/core/components/home/widgets/links/links.tsx rename to apps/web/core/components/home/widgets/links/links.tsx diff --git a/web/core/components/home/widgets/links/root.tsx b/apps/web/core/components/home/widgets/links/root.tsx similarity index 100% rename from web/core/components/home/widgets/links/root.tsx rename to apps/web/core/components/home/widgets/links/root.tsx diff --git a/web/core/components/home/widgets/links/use-links.tsx b/apps/web/core/components/home/widgets/links/use-links.tsx similarity index 100% rename from web/core/components/home/widgets/links/use-links.tsx rename to apps/web/core/components/home/widgets/links/use-links.tsx diff --git a/web/core/components/home/widgets/loaders/home-loader.tsx b/apps/web/core/components/home/widgets/loaders/home-loader.tsx similarity index 100% rename from web/core/components/home/widgets/loaders/home-loader.tsx rename to apps/web/core/components/home/widgets/loaders/home-loader.tsx diff --git a/web/core/components/home/widgets/loaders/index.ts b/apps/web/core/components/home/widgets/loaders/index.ts similarity index 100% rename from web/core/components/home/widgets/loaders/index.ts rename to apps/web/core/components/home/widgets/loaders/index.ts diff --git a/web/core/components/home/widgets/loaders/loader.tsx b/apps/web/core/components/home/widgets/loaders/loader.tsx similarity index 100% rename from web/core/components/home/widgets/loaders/loader.tsx rename to apps/web/core/components/home/widgets/loaders/loader.tsx diff --git a/web/core/components/home/widgets/loaders/quick-links.tsx b/apps/web/core/components/home/widgets/loaders/quick-links.tsx similarity index 100% rename from web/core/components/home/widgets/loaders/quick-links.tsx rename to apps/web/core/components/home/widgets/loaders/quick-links.tsx diff --git a/web/core/components/home/widgets/loaders/recent-activity.tsx b/apps/web/core/components/home/widgets/loaders/recent-activity.tsx similarity index 100% rename from web/core/components/home/widgets/loaders/recent-activity.tsx rename to apps/web/core/components/home/widgets/loaders/recent-activity.tsx diff --git a/web/core/components/home/widgets/manage/index.tsx b/apps/web/core/components/home/widgets/manage/index.tsx similarity index 100% rename from web/core/components/home/widgets/manage/index.tsx rename to apps/web/core/components/home/widgets/manage/index.tsx diff --git a/web/core/components/home/widgets/manage/widget-item-drag-handle.tsx b/apps/web/core/components/home/widgets/manage/widget-item-drag-handle.tsx similarity index 100% rename from web/core/components/home/widgets/manage/widget-item-drag-handle.tsx rename to apps/web/core/components/home/widgets/manage/widget-item-drag-handle.tsx diff --git a/web/core/components/home/widgets/manage/widget-item.tsx b/apps/web/core/components/home/widgets/manage/widget-item.tsx similarity index 100% rename from web/core/components/home/widgets/manage/widget-item.tsx rename to apps/web/core/components/home/widgets/manage/widget-item.tsx diff --git a/web/core/components/home/widgets/manage/widget-list.tsx b/apps/web/core/components/home/widgets/manage/widget-list.tsx similarity index 100% rename from web/core/components/home/widgets/manage/widget-list.tsx rename to apps/web/core/components/home/widgets/manage/widget-list.tsx diff --git a/web/core/components/home/widgets/manage/widget.helpers.ts b/apps/web/core/components/home/widgets/manage/widget.helpers.ts similarity index 100% rename from web/core/components/home/widgets/manage/widget.helpers.ts rename to apps/web/core/components/home/widgets/manage/widget.helpers.ts diff --git a/web/core/components/home/widgets/recents/filters.tsx b/apps/web/core/components/home/widgets/recents/filters.tsx similarity index 100% rename from web/core/components/home/widgets/recents/filters.tsx rename to apps/web/core/components/home/widgets/recents/filters.tsx diff --git a/web/core/components/home/widgets/recents/index.tsx b/apps/web/core/components/home/widgets/recents/index.tsx similarity index 100% rename from web/core/components/home/widgets/recents/index.tsx rename to apps/web/core/components/home/widgets/recents/index.tsx diff --git a/web/core/components/home/widgets/recents/issue.tsx b/apps/web/core/components/home/widgets/recents/issue.tsx similarity index 97% rename from web/core/components/home/widgets/recents/issue.tsx rename to apps/web/core/components/home/widgets/recents/issue.tsx index 33778b641..25fafa059 100644 --- a/web/core/components/home/widgets/recents/issue.tsx +++ b/apps/web/core/components/home/widgets/recents/issue.tsx @@ -1,8 +1,6 @@ import { observer } from "mobx-react"; -// plane constants -import { EIssueServiceType } from "@plane/constants"; // plane types -import { TActivityEntityData, TIssueEntityData } from "@plane/types"; +import { EIssueServiceType, TActivityEntityData, TIssueEntityData } from "@plane/types"; // plane ui import { LayersIcon, PriorityIcon, StateGroupIcon, Tooltip } from "@plane/ui"; import { calculateTimeAgo, generateWorkItemLink } from "@plane/utils"; diff --git a/web/core/components/home/widgets/recents/page.tsx b/apps/web/core/components/home/widgets/recents/page.tsx similarity index 100% rename from web/core/components/home/widgets/recents/page.tsx rename to apps/web/core/components/home/widgets/recents/page.tsx diff --git a/web/core/components/home/widgets/recents/project.tsx b/apps/web/core/components/home/widgets/recents/project.tsx similarity index 100% rename from web/core/components/home/widgets/recents/project.tsx rename to apps/web/core/components/home/widgets/recents/project.tsx diff --git a/web/core/components/icons/attachment/attachment-icon.tsx b/apps/web/core/components/icons/attachment/attachment-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/attachment-icon.tsx rename to apps/web/core/components/icons/attachment/attachment-icon.tsx diff --git a/web/core/components/icons/attachment/audio-file-icon.tsx b/apps/web/core/components/icons/attachment/audio-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/audio-file-icon.tsx rename to apps/web/core/components/icons/attachment/audio-file-icon.tsx diff --git a/web/core/components/icons/attachment/css-file-icon.tsx b/apps/web/core/components/icons/attachment/css-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/css-file-icon.tsx rename to apps/web/core/components/icons/attachment/css-file-icon.tsx diff --git a/web/core/components/icons/attachment/csv-file-icon.tsx b/apps/web/core/components/icons/attachment/csv-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/csv-file-icon.tsx rename to apps/web/core/components/icons/attachment/csv-file-icon.tsx diff --git a/web/core/components/icons/attachment/default-file-icon.tsx b/apps/web/core/components/icons/attachment/default-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/default-file-icon.tsx rename to apps/web/core/components/icons/attachment/default-file-icon.tsx diff --git a/web/core/components/icons/attachment/doc-file-icon.tsx b/apps/web/core/components/icons/attachment/doc-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/doc-file-icon.tsx rename to apps/web/core/components/icons/attachment/doc-file-icon.tsx diff --git a/web/core/components/icons/attachment/document-icon.tsx b/apps/web/core/components/icons/attachment/document-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/document-icon.tsx rename to apps/web/core/components/icons/attachment/document-icon.tsx diff --git a/web/core/components/icons/attachment/figma-file-icon.tsx b/apps/web/core/components/icons/attachment/figma-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/figma-file-icon.tsx rename to apps/web/core/components/icons/attachment/figma-file-icon.tsx diff --git a/web/core/components/icons/attachment/html-file-icon.tsx b/apps/web/core/components/icons/attachment/html-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/html-file-icon.tsx rename to apps/web/core/components/icons/attachment/html-file-icon.tsx diff --git a/web/core/components/icons/attachment/img-file-icon.tsx b/apps/web/core/components/icons/attachment/img-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/img-file-icon.tsx rename to apps/web/core/components/icons/attachment/img-file-icon.tsx diff --git a/web/core/components/icons/attachment/index.ts b/apps/web/core/components/icons/attachment/index.ts similarity index 100% rename from web/core/components/icons/attachment/index.ts rename to apps/web/core/components/icons/attachment/index.ts diff --git a/web/core/components/icons/attachment/jpg-file-icon.tsx b/apps/web/core/components/icons/attachment/jpg-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/jpg-file-icon.tsx rename to apps/web/core/components/icons/attachment/jpg-file-icon.tsx diff --git a/web/core/components/icons/attachment/js-file-icon.tsx b/apps/web/core/components/icons/attachment/js-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/js-file-icon.tsx rename to apps/web/core/components/icons/attachment/js-file-icon.tsx diff --git a/web/core/components/icons/attachment/pdf-file-icon.tsx b/apps/web/core/components/icons/attachment/pdf-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/pdf-file-icon.tsx rename to apps/web/core/components/icons/attachment/pdf-file-icon.tsx diff --git a/web/core/components/icons/attachment/png-file-icon.tsx b/apps/web/core/components/icons/attachment/png-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/png-file-icon.tsx rename to apps/web/core/components/icons/attachment/png-file-icon.tsx diff --git a/web/core/components/icons/attachment/rar-file-icon.tsx b/apps/web/core/components/icons/attachment/rar-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/rar-file-icon.tsx rename to apps/web/core/components/icons/attachment/rar-file-icon.tsx diff --git a/web/core/components/icons/attachment/setting-icon.tsx b/apps/web/core/components/icons/attachment/setting-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/setting-icon.tsx rename to apps/web/core/components/icons/attachment/setting-icon.tsx diff --git a/web/core/components/icons/attachment/sheet-file-icon.tsx b/apps/web/core/components/icons/attachment/sheet-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/sheet-file-icon.tsx rename to apps/web/core/components/icons/attachment/sheet-file-icon.tsx diff --git a/web/core/components/icons/attachment/svg-file-icon.tsx b/apps/web/core/components/icons/attachment/svg-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/svg-file-icon.tsx rename to apps/web/core/components/icons/attachment/svg-file-icon.tsx diff --git a/web/core/components/icons/attachment/tune-icon.tsx b/apps/web/core/components/icons/attachment/tune-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/tune-icon.tsx rename to apps/web/core/components/icons/attachment/tune-icon.tsx diff --git a/web/core/components/icons/attachment/txt-file-icon.tsx b/apps/web/core/components/icons/attachment/txt-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/txt-file-icon.tsx rename to apps/web/core/components/icons/attachment/txt-file-icon.tsx diff --git a/web/core/components/icons/attachment/video-file-icon.tsx b/apps/web/core/components/icons/attachment/video-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/video-file-icon.tsx rename to apps/web/core/components/icons/attachment/video-file-icon.tsx diff --git a/web/core/components/icons/attachment/zip-file-icon.tsx b/apps/web/core/components/icons/attachment/zip-file-icon.tsx similarity index 100% rename from web/core/components/icons/attachment/zip-file-icon.tsx rename to apps/web/core/components/icons/attachment/zip-file-icon.tsx diff --git a/web/core/components/icons/index.ts b/apps/web/core/components/icons/index.ts similarity index 100% rename from web/core/components/icons/index.ts rename to apps/web/core/components/icons/index.ts diff --git a/web/core/components/icons/locked-component.tsx b/apps/web/core/components/icons/locked-component.tsx similarity index 100% rename from web/core/components/icons/locked-component.tsx rename to apps/web/core/components/icons/locked-component.tsx diff --git a/web/core/components/icons/types.d.ts b/apps/web/core/components/icons/types.d.ts similarity index 100% rename from web/core/components/icons/types.d.ts rename to apps/web/core/components/icons/types.d.ts diff --git a/web/core/components/inbox/content/inbox-issue-header.tsx b/apps/web/core/components/inbox/content/inbox-issue-header.tsx similarity index 99% rename from web/core/components/inbox/content/inbox-issue-header.tsx rename to apps/web/core/components/inbox/content/inbox-issue-header.tsx index 16e4835cf..19e32a822 100644 --- a/web/core/components/inbox/content/inbox-issue-header.tsx +++ b/apps/web/core/components/inbox/content/inbox-issue-header.tsx @@ -15,9 +15,9 @@ import { MoveRight, Copy, } from "lucide-react"; -import { EUserPermissions, EUserPermissionsLevel, EInboxIssueStatus } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TNameDescriptionLoader } from "@plane/types"; +import { EInboxIssueStatus, TNameDescriptionLoader } from "@plane/types"; import { Button, ControlLink, CustomMenu, Row, TOAST_TYPE, setToast } from "@plane/ui"; import { copyUrlToClipboard, findHowManyDaysLeft, generateWorkItemLink } from "@plane/utils"; // components diff --git a/web/core/components/inbox/content/inbox-issue-mobile-header.tsx b/apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx similarity index 100% rename from web/core/components/inbox/content/inbox-issue-mobile-header.tsx rename to apps/web/core/components/inbox/content/inbox-issue-mobile-header.tsx diff --git a/web/core/components/inbox/content/index.ts b/apps/web/core/components/inbox/content/index.ts similarity index 100% rename from web/core/components/inbox/content/index.ts rename to apps/web/core/components/inbox/content/index.ts diff --git a/web/core/components/inbox/content/issue-properties.tsx b/apps/web/core/components/inbox/content/issue-properties.tsx similarity index 100% rename from web/core/components/inbox/content/issue-properties.tsx rename to apps/web/core/components/inbox/content/issue-properties.tsx diff --git a/web/core/components/inbox/content/issue-root.tsx b/apps/web/core/components/inbox/content/issue-root.tsx similarity index 83% rename from web/core/components/inbox/content/issue-root.tsx rename to apps/web/core/components/inbox/content/issue-root.tsx index 7f6558cbb..e77147fa0 100644 --- a/web/core/components/inbox/content/issue-root.tsx +++ b/apps/web/core/components/inbox/content/issue-root.tsx @@ -2,11 +2,10 @@ import { Dispatch, SetStateAction, useEffect, useMemo, useRef } from "react"; import { observer } from "mobx-react"; -import { usePathname } from "next/navigation"; // plane imports -import { EInboxIssueSource, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { EditorRefApi } from "@plane/editor"; -import { TIssue, TNameDescriptionLoader } from "@plane/types"; +import { EInboxIssueSource, TIssue, TNameDescriptionLoader } from "@plane/types"; import { Loader, TOAST_TYPE, setToast } from "@plane/ui"; // components import { getTextContent } from "@plane/utils"; @@ -22,7 +21,8 @@ import { } from "@/components/issues"; // helpers // hooks -import { useEventTracker, useIssueDetail, useMember, useProject, useProjectInbox, useUser } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail, useMember, useProject, useProjectInbox, useUser } from "@/hooks/store"; import useReloadConfirmations from "@/hooks/use-reload-confirmation"; // store types import { DeDupeIssuePopoverRoot } from "@/plane-web/components/de-dupe"; @@ -45,8 +45,6 @@ type Props = { export const InboxIssueMainContent: React.FC = observer((props) => { const { workspaceSlug, projectId, inboxIssue, isEditable, isSubmitting, setIsSubmitting } = props; - // navigation - const pathname = usePathname(); // refs const editorRef = useRef(null); // store hooks @@ -57,8 +55,6 @@ export const InboxIssueMainContent: React.FC = observer((props) => { const { removeIssue, archiveIssue } = useIssueDetail(); // reload confirmation const { setShowAlert } = useReloadConfirmations(isSubmitting === "submitting"); - // event tracker - const { captureIssueEvent } = useEventTracker(); useEffect(() => { if (isSubmitting === "submitted") { @@ -104,10 +100,9 @@ export const InboxIssueMainContent: React.FC = observer((props) => { type: TOAST_TYPE.SUCCESS, message: "Work item deleted successfully", }); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: _issueId, state: "SUCCESS", element: "Work item detail page" }, - path: pathname, + payload: { id: _issueId }, }); } catch (error) { console.log("Error in deleting work item:", error); @@ -116,56 +111,46 @@ export const InboxIssueMainContent: React.FC = observer((props) => { type: TOAST_TYPE.ERROR, message: "Work item delete failed", }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: _issueId, state: "FAILED", element: "Work item detail page" }, - path: pathname, + payload: { id: _issueId }, + error: error as Error, }); } }, update: async (_workspaceSlug: string, _projectId: string, _issueId: string, data: Partial) => { try { await inboxIssue.updateIssue(data); - captureIssueEvent({ - eventName: "Inbox work item updated", - payload: { ...data, state: "SUCCESS", element: "Inbox" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.update, + payload: { id: _issueId }, }); - } catch { + } catch (error) { setToast({ title: "Work item update failed", type: TOAST_TYPE.ERROR, message: "Work item update failed", }); - captureIssueEvent({ - eventName: "Inbox work item updated", - payload: { state: "SUCCESS", element: "Inbox" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.update, + payload: { id: _issueId }, + error: error as Error, }); } }, archive: async (workspaceSlug: string, projectId: string, issueId: string) => { try { await archiveIssue(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "SUCCESS", element: "Work item details page" }, - path: pathname, + payload: { id: issueId }, }); } catch (error) { console.log("Error in archiving issue:", error); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "FAILED", element: "Work item details page" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, diff --git a/web/core/components/inbox/content/root.tsx b/apps/web/core/components/inbox/content/root.tsx similarity index 100% rename from web/core/components/inbox/content/root.tsx rename to apps/web/core/components/inbox/content/root.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/date.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/date.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/date.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/index.ts b/apps/web/core/components/inbox/inbox-filter/applied-filters/index.ts similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/index.ts rename to apps/web/core/components/inbox/inbox-filter/applied-filters/index.ts diff --git a/web/core/components/inbox/inbox-filter/applied-filters/label.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/label.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/label.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/member.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/member.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/priority.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/priority.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/priority.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/priority.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/root.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/root.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/root.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/state.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/applied-filters/state.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/state.tsx diff --git a/web/core/components/inbox/inbox-filter/applied-filters/status.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx similarity index 95% rename from web/core/components/inbox/inbox-filter/applied-filters/status.tsx rename to apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx index 990f04dce..d19c80a22 100644 --- a/web/core/components/inbox/inbox-filter/applied-filters/status.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/status.tsx @@ -1,8 +1,9 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { X } from "lucide-react"; -import { INBOX_STATUS, TInboxIssueStatus } from "@plane/constants"; +import { INBOX_STATUS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { TInboxIssueStatus } from "@plane/types"; // constants import { Tag } from "@plane/ui"; // hooks diff --git a/web/core/components/inbox/inbox-filter/filters/date.tsx b/apps/web/core/components/inbox/inbox-filter/filters/date.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/date.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/date.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx b/apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/filter-selection.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/index.ts b/apps/web/core/components/inbox/inbox-filter/filters/index.ts similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/index.ts rename to apps/web/core/components/inbox/inbox-filter/filters/index.ts diff --git a/web/core/components/inbox/inbox-filter/filters/labels.tsx b/apps/web/core/components/inbox/inbox-filter/filters/labels.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/labels.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/labels.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/members.tsx b/apps/web/core/components/inbox/inbox-filter/filters/members.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/members.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/members.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/priority.tsx b/apps/web/core/components/inbox/inbox-filter/filters/priority.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/priority.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/priority.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/state.tsx b/apps/web/core/components/inbox/inbox-filter/filters/state.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/filters/state.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/state.tsx diff --git a/web/core/components/inbox/inbox-filter/filters/status.tsx b/apps/web/core/components/inbox/inbox-filter/filters/status.tsx similarity index 96% rename from web/core/components/inbox/inbox-filter/filters/status.tsx rename to apps/web/core/components/inbox/inbox-filter/filters/status.tsx index 730581e5f..98b12fa7d 100644 --- a/web/core/components/inbox/inbox-filter/filters/status.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/status.tsx @@ -1,8 +1,9 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; // types -import { INBOX_STATUS, TInboxIssueStatus } from "@plane/constants"; +import { INBOX_STATUS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { TInboxIssueStatus } from "@plane/types"; // components import { FilterHeader, FilterOption } from "@/components/issues"; // constants diff --git a/web/core/components/inbox/inbox-filter/index.ts b/apps/web/core/components/inbox/inbox-filter/index.ts similarity index 100% rename from web/core/components/inbox/inbox-filter/index.ts rename to apps/web/core/components/inbox/inbox-filter/index.ts diff --git a/web/core/components/inbox/inbox-filter/root.tsx b/apps/web/core/components/inbox/inbox-filter/root.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/root.tsx rename to apps/web/core/components/inbox/inbox-filter/root.tsx diff --git a/web/core/components/inbox/inbox-filter/sorting/index.ts b/apps/web/core/components/inbox/inbox-filter/sorting/index.ts similarity index 100% rename from web/core/components/inbox/inbox-filter/sorting/index.ts rename to apps/web/core/components/inbox/inbox-filter/sorting/index.ts diff --git a/web/core/components/inbox/inbox-filter/sorting/order-by.tsx b/apps/web/core/components/inbox/inbox-filter/sorting/order-by.tsx similarity index 100% rename from web/core/components/inbox/inbox-filter/sorting/order-by.tsx rename to apps/web/core/components/inbox/inbox-filter/sorting/order-by.tsx diff --git a/web/core/components/inbox/inbox-issue-status.tsx b/apps/web/core/components/inbox/inbox-issue-status.tsx similarity index 100% rename from web/core/components/inbox/inbox-issue-status.tsx rename to apps/web/core/components/inbox/inbox-issue-status.tsx diff --git a/web/core/components/inbox/inbox-status-icon.tsx b/apps/web/core/components/inbox/inbox-status-icon.tsx similarity index 96% rename from web/core/components/inbox/inbox-status-icon.tsx rename to apps/web/core/components/inbox/inbox-status-icon.tsx index 492ee504f..8cf91df0c 100644 --- a/web/core/components/inbox/inbox-status-icon.tsx +++ b/apps/web/core/components/inbox/inbox-status-icon.tsx @@ -1,5 +1,5 @@ import { AlertTriangle, CheckCircle2, Clock, Copy, XCircle } from "lucide-react"; -import { TInboxIssueStatus, EInboxIssueStatus } from "@plane/constants"; +import { TInboxIssueStatus, EInboxIssueStatus } from "@plane/types"; import { cn } from "@plane/utils"; export const ICON_PROPERTIES = { diff --git a/web/core/components/inbox/index.ts b/apps/web/core/components/inbox/index.ts similarity index 100% rename from web/core/components/inbox/index.ts rename to apps/web/core/components/inbox/index.ts diff --git a/web/core/components/inbox/modals/create-modal/create-root.tsx b/apps/web/core/components/inbox/modals/create-modal/create-root.tsx similarity index 95% rename from web/core/components/inbox/modals/create-modal/create-root.tsx rename to apps/web/core/components/inbox/modals/create-modal/create-root.tsx index 923a148e3..32dbfc42a 100644 --- a/web/core/components/inbox/modals/create-modal/create-root.tsx +++ b/apps/web/core/components/inbox/modals/create-modal/create-root.tsx @@ -2,7 +2,6 @@ import { FC, FormEvent, useCallback, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; -import { usePathname } from "next/navigation"; // plane imports import { ETabIndices, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { EditorRefApi } from "@plane/editor"; @@ -14,9 +13,9 @@ import { renderFormattedPayloadDate, getTabIndex } from "@plane/utils"; // components import { InboxIssueTitle, InboxIssueDescription, InboxIssueProperties } from "@/components/inbox/modals/create-modal"; // constants -// helpers // hooks -import { useEventTracker, useProject, useProjectInbox, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useProject, useProjectInbox, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import useKeypress from "@/hooks/use-keypress"; import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -53,14 +52,12 @@ export const InboxIssueCreateRoot: FC = observer((props) const [uploadedAssetIds, setUploadedAssetIds] = useState([]); // router const router = useAppRouter(); - const pathname = usePathname(); // refs const descriptionEditorRef = useRef(null); const submitBtnRef = useRef(null); const formRef = useRef(null); const modalContainerRef = useRef(null); // hooks - const { captureIssueEvent } = useEventTracker(); const { createInboxIssue } = useProjectInbox(); const { getWorkspaceBySlug } = useWorkspace(); const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id; @@ -167,14 +164,11 @@ export const InboxIssueCreateRoot: FC = observer((props) descriptionEditorRef?.current?.clearEditor(); setFormData(defaultIssueData); } - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.create, payload: { - ...formData, - state: "SUCCESS", - element: "Inbox page", + id: res?.issue?.id, }, - path: pathname, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -184,14 +178,12 @@ export const InboxIssueCreateRoot: FC = observer((props) }) .catch((error) => { console.error(error); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.create, payload: { - ...formData, - state: "FAILED", - element: "Inbox page", + id: formData?.id, }, - path: pathname, + error: error as Error, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/web/core/components/inbox/modals/create-modal/index.ts b/apps/web/core/components/inbox/modals/create-modal/index.ts similarity index 100% rename from web/core/components/inbox/modals/create-modal/index.ts rename to apps/web/core/components/inbox/modals/create-modal/index.ts diff --git a/web/core/components/inbox/modals/create-modal/issue-description.tsx b/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx similarity index 95% rename from web/core/components/inbox/modals/create-modal/issue-description.tsx rename to apps/web/core/components/inbox/modals/create-modal/issue-description.tsx index b2511e5d5..907f48e70 100644 --- a/web/core/components/inbox/modals/create-modal/issue-description.tsx +++ b/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx @@ -4,24 +4,19 @@ import { FC, RefObject } from "react"; import { observer } from "mobx-react"; // plane imports import { ETabIndices } from "@plane/constants"; -// editor import { EditorRefApi } from "@plane/editor"; -// i18n import { useTranslation } from "@plane/i18n"; -// types -import { TIssue } from "@plane/types"; -import { EFileAssetType } from "@plane/types/src/enums"; -// ui +import { EFileAssetType, TIssue } from "@plane/types"; import { Loader } from "@plane/ui"; import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils"; // components import { RichTextEditor } from "@/components/editor/rich-text-editor/rich-text-editor"; -// helpers // hooks import { useEditorAsset, useProjectInbox } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; -// plane web services +// services import { WorkspaceService } from "@/plane-web/services"; + const workspaceService = new WorkspaceService(); type TInboxIssueDescription = { @@ -67,6 +62,7 @@ export const InboxIssueDescription: FC = observer((props return (

" : data?.description_html} ref={editorRef} diff --git a/web/core/components/inbox/modals/create-modal/issue-properties.tsx b/apps/web/core/components/inbox/modals/create-modal/issue-properties.tsx similarity index 100% rename from web/core/components/inbox/modals/create-modal/issue-properties.tsx rename to apps/web/core/components/inbox/modals/create-modal/issue-properties.tsx diff --git a/web/core/components/inbox/modals/create-modal/issue-title.tsx b/apps/web/core/components/inbox/modals/create-modal/issue-title.tsx similarity index 100% rename from web/core/components/inbox/modals/create-modal/issue-title.tsx rename to apps/web/core/components/inbox/modals/create-modal/issue-title.tsx diff --git a/web/core/components/inbox/modals/create-modal/modal.tsx b/apps/web/core/components/inbox/modals/create-modal/modal.tsx similarity index 100% rename from web/core/components/inbox/modals/create-modal/modal.tsx rename to apps/web/core/components/inbox/modals/create-modal/modal.tsx diff --git a/web/core/components/inbox/modals/decline-issue-modal.tsx b/apps/web/core/components/inbox/modals/decline-issue-modal.tsx similarity index 100% rename from web/core/components/inbox/modals/decline-issue-modal.tsx rename to apps/web/core/components/inbox/modals/decline-issue-modal.tsx diff --git a/web/core/components/inbox/modals/delete-issue-modal.tsx b/apps/web/core/components/inbox/modals/delete-issue-modal.tsx similarity index 100% rename from web/core/components/inbox/modals/delete-issue-modal.tsx rename to apps/web/core/components/inbox/modals/delete-issue-modal.tsx diff --git a/web/core/components/inbox/modals/index.ts b/apps/web/core/components/inbox/modals/index.ts similarity index 100% rename from web/core/components/inbox/modals/index.ts rename to apps/web/core/components/inbox/modals/index.ts diff --git a/web/core/components/inbox/modals/select-duplicate.tsx b/apps/web/core/components/inbox/modals/select-duplicate.tsx similarity index 98% rename from web/core/components/inbox/modals/select-duplicate.tsx rename to apps/web/core/components/inbox/modals/select-duplicate.tsx index d0484ce66..39d66beec 100644 --- a/web/core/components/inbox/modals/select-duplicate.tsx +++ b/apps/web/core/components/inbox/modals/select-duplicate.tsx @@ -123,7 +123,7 @@ export const SelectDuplicateInboxIssueModal: React.FC = (props) => { setQuery("")} appear>
- + = (props) => {
-
+
{ // store hooks const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { workspaceProjectIds, getProjectById } = useProject(); // form info const { @@ -201,8 +202,9 @@ export const JiraGetImportDetail: React.FC = observer(() => {
) : ( <> diff --git a/web/core/components/issues/index.ts b/apps/web/core/components/issues/index.ts similarity index 100% rename from web/core/components/issues/index.ts rename to apps/web/core/components/issues/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/action-buttons.tsx b/apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/action-buttons.tsx rename to apps/web/core/components/issues/issue-detail-widgets/action-buttons.tsx diff --git a/web/core/components/issues/issue-detail-widgets/attachments/content.tsx b/apps/web/core/components/issues/issue-detail-widgets/attachments/content.tsx similarity index 90% rename from web/core/components/issues/issue-detail-widgets/attachments/content.tsx rename to apps/web/core/components/issues/issue-detail-widgets/attachments/content.tsx index 7441ad42f..1a3169104 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/content.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/attachments/content.tsx @@ -1,8 +1,7 @@ "use client"; import React, { FC } from "react"; import { observer } from "mobx-react"; -import { EIssueServiceType } from "@plane/constants"; -import { TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; // components import { IssueAttachmentItemList } from "@/components/issues/attachment"; // helper diff --git a/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx b/apps/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx similarity index 65% rename from web/core/components/issues/issue-detail-widgets/attachments/helper.tsx rename to apps/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx index 28684ac99..1a2d35f5e 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/attachments/helper.tsx @@ -1,11 +1,12 @@ "use client"; import { useMemo } from "react"; -import { EIssueServiceType } from "@plane/constants"; -import { TIssueServiceType } from "@plane/types"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; // plane ui import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui"; // hooks -import { useEventTracker, useIssueDetail } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail } from "@/hooks/store"; // types import { TAttachmentUploadStatus } from "@/store/issue/issue-details/attachment.store"; @@ -32,7 +33,6 @@ export const useAttachmentOperations = ( const { attachment: { createAttachment, removeAttachment, getAttachmentsUploadStatusByIssueId }, } = useIssueDetail(issueServiceType); - const { captureIssueEvent } = useEventTracker(); const attachmentOperations: TAttachmentOperations = useMemo( () => ({ @@ -52,19 +52,16 @@ export const useAttachmentOperations = ( }, }); - const res = await attachmentUploadPromise; - captureIssueEvent({ - eventName: "Issue attachment added", - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "attachment", - change_details: res.id, - }, + await attachmentUploadPromise; + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.attachment.add, + payload: { id: issueId }, }); } catch (error) { - captureIssueEvent({ - eventName: "Issue attachment added", - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.attachment.add, + payload: { id: issueId }, + error: error as Error, }); throw error; } @@ -78,22 +75,15 @@ export const useAttachmentOperations = ( type: TOAST_TYPE.SUCCESS, title: "Attachment removed", }); - captureIssueEvent({ - eventName: "Issue attachment deleted", - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "attachment", - change_details: "", - }, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.attachment.remove, + payload: { id: issueId }, }); } catch (error) { - captureIssueEvent({ - eventName: "Issue attachment deleted", - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "attachment", - change_details: "", - }, + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.attachment.remove, + payload: { id: issueId }, + error: error as Error, }); setToast({ message: "The Attachment could not be removed", @@ -103,7 +93,7 @@ export const useAttachmentOperations = ( } }, }), - [captureIssueEvent, workspaceSlug, projectId, issueId, createAttachment, removeAttachment] + [workspaceSlug, projectId, issueId, createAttachment, removeAttachment] ); const attachmentsUploadStatus = getAttachmentsUploadStatusByIssueId(issueId); diff --git a/web/core/components/issues/issue-detail-widgets/attachments/index.ts b/apps/web/core/components/issues/issue-detail-widgets/attachments/index.ts similarity index 100% rename from web/core/components/issues/issue-detail-widgets/attachments/index.ts rename to apps/web/core/components/issues/issue-detail-widgets/attachments/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx b/apps/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx rename to apps/web/core/components/issues/issue-detail-widgets/attachments/quick-action-button.tsx diff --git a/web/core/components/issues/issue-detail-widgets/attachments/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/attachments/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/attachments/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/attachments/root.tsx diff --git a/web/core/components/issues/issue-detail-widgets/attachments/title.tsx b/apps/web/core/components/issues/issue-detail-widgets/attachments/title.tsx similarity index 94% rename from web/core/components/issues/issue-detail-widgets/attachments/title.tsx rename to apps/web/core/components/issues/issue-detail-widgets/attachments/title.tsx index c96b6ffb8..4eb61fabd 100644 --- a/web/core/components/issues/issue-detail-widgets/attachments/title.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/attachments/title.tsx @@ -1,9 +1,8 @@ "use client"; import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; import { CollapsibleButton } from "@plane/ui"; // components import { IssueAttachmentActionButton } from "@/components/issues/issue-detail-widgets"; diff --git a/web/core/components/issues/issue-detail-widgets/index.ts b/apps/web/core/components/issues/issue-detail-widgets/index.ts similarity index 100% rename from web/core/components/issues/issue-detail-widgets/index.ts rename to apps/web/core/components/issues/issue-detail-widgets/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/issue-detail-widget-collapsibles.tsx b/apps/web/core/components/issues/issue-detail-widgets/issue-detail-widget-collapsibles.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/issue-detail-widget-collapsibles.tsx rename to apps/web/core/components/issues/issue-detail-widgets/issue-detail-widget-collapsibles.tsx diff --git a/web/core/components/issues/issue-detail-widgets/issue-detail-widget-modals.tsx b/apps/web/core/components/issues/issue-detail-widgets/issue-detail-widget-modals.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/issue-detail-widget-modals.tsx rename to apps/web/core/components/issues/issue-detail-widgets/issue-detail-widget-modals.tsx diff --git a/web/core/components/issues/issue-detail-widgets/links/content.tsx b/apps/web/core/components/issues/issue-detail-widgets/links/content.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/content.tsx rename to apps/web/core/components/issues/issue-detail-widgets/links/content.tsx diff --git a/web/core/components/issues/issue-detail-widgets/links/helper.tsx b/apps/web/core/components/issues/issue-detail-widgets/links/helper.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/helper.tsx rename to apps/web/core/components/issues/issue-detail-widgets/links/helper.tsx diff --git a/web/core/components/issues/issue-detail-widgets/links/index.ts b/apps/web/core/components/issues/issue-detail-widgets/links/index.ts similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/index.ts rename to apps/web/core/components/issues/issue-detail-widgets/links/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx b/apps/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx rename to apps/web/core/components/issues/issue-detail-widgets/links/quick-action-button.tsx diff --git a/web/core/components/issues/issue-detail-widgets/links/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/links/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/links/root.tsx diff --git a/web/core/components/issues/issue-detail-widgets/links/title.tsx b/apps/web/core/components/issues/issue-detail-widgets/links/title.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/links/title.tsx rename to apps/web/core/components/issues/issue-detail-widgets/links/title.tsx diff --git a/web/core/components/issues/issue-detail-widgets/relations/content.tsx b/apps/web/core/components/issues/issue-detail-widgets/relations/content.tsx similarity index 98% rename from web/core/components/issues/issue-detail-widgets/relations/content.tsx rename to apps/web/core/components/issues/issue-detail-widgets/relations/content.tsx index a80d59cc0..08d694a34 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/content.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/relations/content.tsx @@ -2,9 +2,8 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; // plane imports -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue, TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssue, TIssueServiceType } from "@plane/types"; import { Collapsible } from "@plane/ui"; // components import { RelationIssueList } from "@/components/issues"; diff --git a/web/core/components/issues/issue-detail-widgets/relations/helper.tsx b/apps/web/core/components/issues/issue-detail-widgets/relations/helper.tsx similarity index 62% rename from web/core/components/issues/issue-detail-widgets/relations/helper.tsx rename to apps/web/core/components/issues/issue-detail-widgets/relations/helper.tsx index 6e68be0d4..1073b2063 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/helper.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/relations/helper.tsx @@ -1,14 +1,14 @@ "use client"; import { useMemo } from "react"; -import { usePathname } from "next/navigation"; // plane imports -import { EIssueServiceType, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue, TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssue, TIssueServiceType } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; import { copyUrlToClipboard } from "@plane/utils"; // hooks -import { useEventTracker, useIssueDetail } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail } from "@/hooks/store"; export type TRelationIssueOperations = { copyLink: (path: string) => void; @@ -20,8 +20,6 @@ export const useRelationOperations = ( issueServiceType: TIssueServiceType = EIssueServiceType.ISSUES ): TRelationIssueOperations => { const { updateIssue, removeIssue } = useIssueDetail(issueServiceType); - const { captureIssueEvent } = useEventTracker(); - const pathname = usePathname(); const { t } = useTranslation(); // derived values const entityName = issueServiceType === EIssueServiceType.ISSUES ? "Work item" : "Epic"; @@ -40,29 +38,20 @@ export const useRelationOperations = ( update: async (workspaceSlug, projectId, issueId, data) => { try { await updateIssue(workspaceSlug, projectId, issueId, data); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + payload: { id: issueId }, }); setToast({ title: t("toast.success"), type: TOAST_TYPE.SUCCESS, message: t("entity.update.success", { entity: entityName }), }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); setToast({ title: t("toast.error"), @@ -74,22 +63,21 @@ export const useRelationOperations = ( remove: async (workspaceSlug, projectId, issueId) => { try { return removeIssue(workspaceSlug, projectId, issueId).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - path: pathname, + payload: { id: issueId }, }); }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, }), - [captureIssueEvent, entityName, pathname, removeIssue, t, updateIssue] + [entityName, removeIssue, t, updateIssue] ); return issueOperations; diff --git a/web/core/components/issues/issue-detail-widgets/relations/index.ts b/apps/web/core/components/issues/issue-detail-widgets/relations/index.ts similarity index 100% rename from web/core/components/issues/issue-detail-widgets/relations/index.ts rename to apps/web/core/components/issues/issue-detail-widgets/relations/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx b/apps/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx rename to apps/web/core/components/issues/issue-detail-widgets/relations/quick-action-button.tsx diff --git a/web/core/components/issues/issue-detail-widgets/relations/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/relations/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/relations/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/relations/root.tsx diff --git a/web/core/components/issues/issue-detail-widgets/relations/title.tsx b/apps/web/core/components/issues/issue-detail-widgets/relations/title.tsx similarity index 93% rename from web/core/components/issues/issue-detail-widgets/relations/title.tsx rename to apps/web/core/components/issues/issue-detail-widgets/relations/title.tsx index f1284eb47..32b9318eb 100644 --- a/web/core/components/issues/issue-detail-widgets/relations/title.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/relations/title.tsx @@ -1,9 +1,8 @@ "use client"; import React, { FC, useMemo } from "react"; import { observer } from "mobx-react"; -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; import { CollapsibleButton } from "@plane/ui"; // components import { RelationActionButton } from "@/components/issues/issue-detail-widgets"; diff --git a/web/core/components/issues/issue-detail-widgets/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/root.tsx diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx similarity index 97% rename from web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx index 6000959f2..00abc3799 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/content.tsx @@ -1,8 +1,7 @@ "use client"; import React, { FC, useEffect, useState, useCallback } from "react"; import { observer } from "mobx-react"; -import { EIssueServiceType, EIssuesStoreType } from "@plane/constants"; -import { TIssue, TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, EIssuesStoreType, TIssue, TIssueServiceType } from "@plane/types"; // components import { DeleteIssueModal } from "@/components/issues/delete-issue-modal"; import { CreateUpdateIssueModal } from "@/components/issues/issue-modal"; diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/display-filters.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/display-filters.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/sub-issues/display-filters.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/display-filters.tsx diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/filters.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/filters.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/sub-issues/filters.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/filters.tsx diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts similarity index 76% rename from web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts index 564e72c05..79b362fb7 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts @@ -1,22 +1,22 @@ "use client"; import { useMemo } from "react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // plane imports -import { EIssueServiceType } from "@plane/constants"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssueServiceType, TSubIssueOperations } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType, TSubIssueOperations } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; import { copyUrlToClipboard } from "@plane/utils"; // hooks -import { useEventTracker, useIssueDetail, useProjectState } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail, useProjectState } from "@/hooks/store"; // plane web helpers import { updateEpicAnalytics } from "@/plane-web/helpers/epic-analytics"; export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSubIssueOperations => { // router const { epicId: epicIdParam } = useParams(); - const pathname = usePathname(); // translation const { t } = useTranslation(); // store hooks @@ -33,7 +33,6 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub const { peekIssue: epicPeekIssue } = useIssueDetail(EIssueServiceType.EPICS); // const { updateEpicAnalytics } = useIssueTypes(); const { updateAnalytics } = updateEpicAnalytics(); - const { captureIssueEvent } = useEventTracker(); // derived values const epicId = epicIdParam || epicPeekIssue?.issueId; @@ -129,14 +128,9 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub } } } - captureIssueEvent({ - eventName: "Sub-issue updated", - payload: { ...oldIssue, ...issueData, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(issueData).join(","), - change_details: Object.values(issueData).join(","), - }, - path: pathname, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.update, + payload: { id: issueId, parent_id: parentIssueId }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -144,15 +138,11 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub message: t("sub_work_item.update.success"), }); setSubIssueHelpers(parentIssueId, "issue_loader", issueId); - } catch { - captureIssueEvent({ - eventName: "Sub-issue updated", - payload: { ...oldIssue, ...issueData, state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(issueData).join(","), - change_details: Object.values(issueData).join(","), - }, - path: pathname, + } catch (error) { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.update, + payload: { id: issueId, parent_id: parentIssueId }, + error: error as Error, }); setToast({ type: TOAST_TYPE.ERROR, @@ -180,25 +170,16 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub title: t("toast.success"), message: t("sub_work_item.remove.success"), }); - captureIssueEvent({ - eventName: "Sub-issue removed", - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "parent_id", - change_details: parentIssueId, - }, - path: pathname, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.remove, + payload: { id: issueId, parent_id: parentIssueId }, }); setSubIssueHelpers(parentIssueId, "issue_loader", issueId); - } catch { - captureIssueEvent({ - eventName: "Sub-issue removed", - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "parent_id", - change_details: parentIssueId, - }, - path: pathname, + } catch (error) { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.remove, + payload: { id: issueId, parent_id: parentIssueId }, + error: error as Error, }); setToast({ type: TOAST_TYPE.ERROR, @@ -211,18 +192,17 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub try { setSubIssueHelpers(parentIssueId, "issue_loader", issueId); return deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId).then(() => { - captureIssueEvent({ - eventName: "Sub-issue deleted", - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - path: pathname, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.delete, + payload: { id: issueId, parent_id: parentIssueId }, }); setSubIssueHelpers(parentIssueId, "issue_loader", issueId); }); - } catch { - captureIssueEvent({ - eventName: "Sub-issue removed", - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - path: pathname, + } catch (error) { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.sub_issue.delete, + payload: { id: issueId, parent_id: parentIssueId }, + error: error as Error, }); setToast({ type: TOAST_TYPE.ERROR, @@ -233,7 +213,6 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub }, }), [ - captureIssueEvent, createSubIssues, deleteSubIssue, epicId, @@ -241,7 +220,6 @@ export const useSubIssueOperations = (issueServiceType: TIssueServiceType): TSub getIssueById, getStateById, issueServiceType, - pathname, removeSubIssue, setSubIssueHelpers, t, diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/index.ts b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/index.ts similarity index 100% rename from web/core/components/issues/issue-detail-widgets/sub-issues/index.ts rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/index.ts diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx similarity index 94% rename from web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx index b860646ba..7bee0f513 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-group.tsx @@ -1,8 +1,8 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; import { ChevronRight, CircleDashed } from "lucide-react"; -import { ALL_ISSUES, EIssuesStoreType } from "@plane/constants"; -import { IGroupByColumn, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types"; +import { ALL_ISSUES } from "@plane/constants"; +import { EIssuesStoreType, IGroupByColumn, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types"; import { Collapsible } from "@plane/ui"; import { cn } from "@plane/utils"; import { SubIssuesListItem } from "./list-item"; diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx similarity index 94% rename from web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx index 73e5b29f0..62e59eb26 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/list-item.tsx @@ -3,16 +3,15 @@ import { observer } from "mobx-react"; import { ChevronRight, X, Pencil, Trash, Link as LinkIcon, Loader } from "lucide-react"; // plane imports -import { EIssueServiceType, EIssuesStoreType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types"; +import { EIssueServiceType, EIssuesStoreType, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types"; import { ControlLink, CustomMenu, Tooltip } from "@plane/ui"; import { cn, generateWorkItemLink } from "@plane/utils"; // helpers import { useSubIssueOperations } from "@/components/issues/issue-detail-widgets/sub-issues/helper"; import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/properties/with-display-properties-HOC"; // hooks -import { useIssueDetail, useProject, useProjectState } from "@/hooks/store"; +import { useIssueDetail, useProject } from "@/hooks/store"; import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components @@ -66,16 +65,12 @@ export const SubIssuesListItem: React.FC = observer((props) => { const { fetchSubIssues } = useSubIssueOperations(EIssueServiceType.ISSUES); const { toggleCreateIssueModal, toggleDeleteIssueModal } = useIssueDetail(issueServiceType); const project = useProject(); - const { getProjectStates } = useProjectState(); const { handleRedirection } = useIssuePeekOverviewRedirection(); const { isMobile } = usePlatformOS(); const issue = getIssueById(issueId); // derived values const projectDetail = (issue && issue.project_id && project.getProjectById(issue.project_id)) || undefined; - const currentIssueStateDetail = - (issue?.project_id && getProjectStates(issue?.project_id)?.find((state) => issue?.state_id == state.id)) || - undefined; const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId); const subIssueCount = issue?.sub_issues_count ?? 0; @@ -148,12 +143,6 @@ export const SubIssuesListItem: React.FC = observer((props) => {
-
{projectDetail && ( diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/properties.tsx diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx similarity index 89% rename from web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx index c99f99086..7b55d37ef 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/issues-list/root.tsx @@ -2,11 +2,17 @@ import { useCallback, useMemo } from "react"; import { observer } from "mobx-react"; // plane imports import { ListFilter } from "lucide-react"; -import { EIssueServiceType, EIssuesStoreType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { GroupByColumnTypes, TIssue, TIssueServiceType, TSubIssueOperations } from "@plane/types"; +import { + EIssueServiceType, + EIssuesStoreType, + GroupByColumnTypes, + TIssue, + TIssueServiceType, + TSubIssueOperations, +} from "@plane/types"; // hooks -import { Button, Loader } from "@plane/ui"; +import { Button } from "@plane/ui"; import { SectionEmptyState } from "@/components/empty-state"; import { getGroupByColumns, isWorkspaceLevel } from "@/components/issues/issue-layouts/utils"; import { useIssueDetail } from "@/hooks/store"; @@ -47,7 +53,6 @@ export const SubIssuesListRoot: React.FC = observer((props) => { const { subIssues: { subIssuesByIssueId, - loader, filters: { getSubIssueFilters, getGroupedSubWorkItems, getFilteredSubWorkItems, resetFilters }, }, } = useIssueDetail(issueServiceType); @@ -80,16 +85,6 @@ export const SubIssuesListRoot: React.FC = observer((props) => { const isSubWorkItems = issueServiceType === EIssueServiceType.ISSUES; - if (loader === "init-loader") { - return ( - - {Array.from({ length: 5 }).map((_, index) => ( - - ))} - - ); - } - return (
{isRootLevel && filteredSubWorkItemsCount === 0 ? ( diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx similarity index 88% rename from web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx index 7f1b9c6c7..ae1bc8742 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/quick-action-button.tsx @@ -3,11 +3,13 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { LayersIcon, Plus } from "lucide-react"; // plane imports +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { TIssue, TIssueServiceType } from "@plane/types"; import { CustomMenu } from "@plane/ui"; // hooks -import { useEventTracker, useIssueDetail } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssueDetail } from "@/hooks/store"; type Props = { issueId: string; @@ -28,7 +30,6 @@ export const SubIssuesActionButton: FC = observer((props) => { setIssueCrudOperationState, issueCrudOperationState, } = useIssueDetail(issueServiceType); - const { setTrackElement } = useEventTracker(); // derived values const issue = getIssueById(issueId); @@ -52,13 +53,13 @@ export const SubIssuesActionButton: FC = observer((props) => { }; const handleCreateNew = () => { - setTrackElement("Issue detail nested sub-issue"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.sub_issue.create }); handleIssueCrudState("create", issueId, null); toggleCreateIssueModal(true); }; const handleAddExisting = () => { - setTrackElement("Issue detail nested sub-issue"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.sub_issue.add_existing }); handleIssueCrudState("existing", issueId, null); toggleSubIssuesModal(issue.id); }; diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/root.tsx diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx similarity index 97% rename from web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx index e9e4393ed..b01dac11e 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/title-actions.tsx @@ -1,8 +1,9 @@ import { FC, useCallback } from "react"; import cloneDeep from "lodash/cloneDeep"; import { observer } from "mobx-react"; -import { EIssueFilterType, EIssueServiceType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; +import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; import { + EIssueServiceType, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, diff --git a/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx similarity index 95% rename from web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx rename to apps/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx index 041f0ca23..c38a398cb 100644 --- a/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx +++ b/apps/web/core/components/issues/issue-detail-widgets/sub-issues/title.tsx @@ -3,9 +3,8 @@ import { FC } from "react"; import { observer } from "mobx-react"; // plane imports -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; import { CircularProgressIndicator, CollapsibleButton } from "@plane/ui"; // hooks import { useIssueDetail } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-detail-widgets/widget-button.tsx b/apps/web/core/components/issues/issue-detail-widgets/widget-button.tsx similarity index 100% rename from web/core/components/issues/issue-detail-widgets/widget-button.tsx rename to apps/web/core/components/issues/issue-detail-widgets/widget-button.tsx diff --git a/web/core/components/issues/issue-detail/cycle-select.tsx b/apps/web/core/components/issues/issue-detail/cycle-select.tsx similarity index 100% rename from web/core/components/issues/issue-detail/cycle-select.tsx rename to apps/web/core/components/issues/issue-detail/cycle-select.tsx diff --git a/web/core/components/issues/issue-detail/index.ts b/apps/web/core/components/issues/issue-detail/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/index.ts rename to apps/web/core/components/issues/issue-detail/index.ts diff --git a/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx similarity index 73% rename from web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx index 2e9047098..5b0d073a1 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx +++ b/apps/web/core/components/issues/issue-detail/issue-activity/activity-comment-root.tsx @@ -1,16 +1,18 @@ import { FC } from "react"; import { observer } from "mobx-react"; -// constants +// plane imports import { E_SORT_ORDER, TActivityFilters, filterActivityOnSelectedFilters } from "@plane/constants"; -// hooks import { TCommentsOperations } from "@plane/types"; -import { CommentCard } from "@/components/comments/comment-card"; +// components +import { CommentCard } from "@/components/comments/card/root"; +// hooks import { useIssueDetail } from "@/hooks/store"; // plane web components import { IssueAdditionalPropertiesActivity } from "@/plane-web/components/issues"; import { IssueActivityWorklog } from "@/plane-web/components/issues/worklog/activity/root"; -// components +// local imports import { IssueActivityItem } from "./activity/activity-list"; +import { IssueActivityLoader } from "./loader"; type TIssueActivityCommentRoot = { workspaceSlug: string; @@ -34,21 +36,23 @@ export const IssueActivityCommentRoot: FC = observer( disabled, sortOrder, } = props; - // hooks + // store hooks const { - activity: { getActivityCommentByIssueId }, + activity: { getActivityAndCommentsByIssueId }, comment: { getCommentById }, } = useIssueDetail(); + // derived values + const activityAndComments = getActivityAndCommentsByIssueId(issueId, sortOrder); - const activityComments = getActivityCommentByIssueId(issueId, sortOrder); + if (!activityAndComments) return ; - if (!activityComments || (activityComments && activityComments.length <= 0)) return <>; + if (activityAndComments.length <= 0) return null; - const filteredActivityComments = filterActivityOnSelectedFilters(activityComments, selectedFilters); + const filteredActivityAndComments = filterActivityOnSelectedFilters(activityAndComments, selectedFilters); return (
- {filteredActivityComments.map((activityComment, index) => { + {filteredActivityAndComments.map((activityComment, index) => { const comment = getCommentById(activityComment.id); return activityComment.activity_type === "COMMENT" ? ( = observer( workspaceSlug={workspaceSlug} comment={comment} activityOperations={activityOperations} - ends={index === 0 ? "top" : index === filteredActivityComments.length - 1 ? "bottom" : undefined} - showAccessSpecifier={showAccessSpecifier} + ends={index === 0 ? "top" : index === filteredActivityAndComments.length - 1 ? "bottom" : undefined} + showAccessSpecifier={!!showAccessSpecifier} + showCopyLinkOption disabled={disabled} projectId={projectId} /> ) : activityComment.activity_type === "ACTIVITY" ? ( ) : activityComment.activity_type === "ISSUE_ADDITIONAL_PROPERTIES_ACTIVITY" ? ( ) : activityComment.activity_type === "WORKLOG" ? ( = observer( projectId={projectId} issueId={issueId} activityComment={activityComment} - ends={index === 0 ? "top" : index === filteredActivityComments.length - 1 ? "bottom" : undefined} + ends={index === 0 ? "top" : index === filteredActivityAndComments.length - 1 ? "bottom" : undefined} /> ) : ( <> diff --git a/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity-filter.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/archived-at.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/archived-at.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/archived-at.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/archived-at.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/assignee.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/assignee.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/assignee.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/assignee.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/attachment.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/attachment.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/attachment.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/attachment.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/cycle.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/cycle.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/cycle.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/cycle.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx similarity index 96% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx index b9a1f4bbe..3d2270750 100644 --- a/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx +++ b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/default.tsx @@ -3,7 +3,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; // plane imports -import { EInboxIssueSource } from "@plane/constants"; +import { EInboxIssueSource } from "@plane/types"; import { LayersIcon } from "@plane/ui"; // hooks import { capitalizeFirstLetter } from "@plane/utils"; diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/description.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/description.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/description.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/description.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/estimate.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/estimate.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/estimate.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/estimate.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/activity-block.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-link.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-link.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-link.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-link.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-user.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-user.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-user.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/helpers/issue-user.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/inbox.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/inbox.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/inbox.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/inbox.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/index.ts diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/label-activity-chip.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/label-activity-chip.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/label-activity-chip.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/label-activity-chip.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/label.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/label.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/label.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/label.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/link.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/link.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/link.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/link.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/module.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/module.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/module.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/module.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/name.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/name.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/name.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/name.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/parent.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/parent.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/parent.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/parent.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/priority.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/priority.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/priority.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/priority.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/relation.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/relation.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/relation.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/relation.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/start_date.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/start_date.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/start_date.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/start_date.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/state.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/state.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/state.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/state.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/actions/target_date.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/target_date.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/actions/target_date.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/actions/target_date.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/activity/activity-list.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/helper.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx similarity index 70% rename from web/core/components/issues/issue-detail/issue-activity/helper.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx index af30a389f..884c2325e 100644 --- a/web/core/components/issues/issue-detail/issue-activity/helper.tsx +++ b/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx @@ -1,10 +1,9 @@ import { useMemo } from "react"; import { useTranslation } from "@plane/i18n"; -import { TCommentsOperations, TIssueActivity, TIssueComment } from "@plane/types"; -import { EFileAssetType } from "@plane/types/src/enums"; +import { EFileAssetType, type TCommentsOperations } from "@plane/types"; import { setToast, TOAST_TYPE } from "@plane/ui"; -import { formatTextList } from "@plane/utils"; -import { useEditorAsset, useIssueDetail, useMember, useUser } from "@/hooks/store"; +import { copyUrlToClipboard, formatTextList, generateWorkItemLink } from "@plane/utils"; +import { useEditorAsset, useIssueDetail, useMember, useProject, useUser } from "@/hooks/store"; export const useCommentOperations = ( workspaceSlug: string | undefined, @@ -19,16 +18,49 @@ export const useCommentOperations = ( removeComment, createCommentReaction, removeCommentReaction, + issue: { getIssueById }, } = useIssueDetail(); + const { getProjectById } = useProject(); const { getUserDetails } = useMember(); const { uploadEditorAsset } = useEditorAsset(); const { data: currentUser } = useUser(); + // derived values + const issueDetails = issueId ? getIssueById(issueId) : undefined; + const projectDetails = projectId ? getProjectById(projectId) : undefined; + // translation const { t } = useTranslation(); - const operations = useMemo(() => { + const operations: TCommentsOperations = useMemo(() => { // Define operations object with all methods - const ops = { - createComment: async (data: Partial) => { + const ops: TCommentsOperations = { + copyCommentLink: (id) => { + if (!workspaceSlug || !issueDetails) return; + try { + const workItemLink = generateWorkItemLink({ + workspaceSlug, + projectId: issueDetails.project_id, + issueId, + projectIdentifier: projectDetails?.identifier, + sequenceId: issueDetails.sequence_id, + }); + const commentLink = `${workItemLink}#comment-${id}`; + copyUrlToClipboard(commentLink).then(() => { + setToast({ + title: t("common.success"), + type: TOAST_TYPE.SUCCESS, + message: t("issue.comments.copy_link.success"), + }); + }); + } catch (error) { + console.error("Error in copying comment link:", error); + setToast({ + title: t("common.error.label"), + type: TOAST_TYPE.ERROR, + message: t("issue.comments.copy_link.error"), + }); + } + }, + createComment: async (data) => { try { if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields"); const comment = await createComment(workspaceSlug, projectId, issueId, data); @@ -46,7 +78,7 @@ export const useCommentOperations = ( }); } }, - updateComment: async (commentId: string, data: Partial) => { + updateComment: async (commentId, data) => { try { if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields"); await updateComment(workspaceSlug, projectId, issueId, commentId, data); @@ -63,7 +95,7 @@ export const useCommentOperations = ( }); } }, - removeComment: async (commentId: string) => { + removeComment: async (commentId) => { try { if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields"); await removeComment(workspaceSlug, projectId, issueId, commentId); @@ -80,7 +112,7 @@ export const useCommentOperations = ( }); } }, - uploadCommentAsset: async (blockId: string, file: File, commentId?: string) => { + uploadCommentAsset: async (blockId, file, commentId) => { try { if (!workspaceSlug || !projectId) throw new Error("Missing fields"); const res = await uploadEditorAsset({ @@ -99,7 +131,7 @@ export const useCommentOperations = ( throw new Error(t("issue.comments.upload.error")); } }, - addCommentReaction: async (commentId: string, reaction: string) => { + addCommentReaction: async (commentId, reaction) => { try { if (!workspaceSlug || !projectId || !commentId) throw new Error("Missing fields"); await createCommentReaction(workspaceSlug, projectId, commentId, reaction); @@ -108,7 +140,7 @@ export const useCommentOperations = ( type: TOAST_TYPE.SUCCESS, message: "Reaction created successfully", }); - } catch (error) { + } catch { setToast({ title: "Error!", type: TOAST_TYPE.ERROR, @@ -116,7 +148,7 @@ export const useCommentOperations = ( }); } }, - deleteCommentReaction: async (commentId: string, reaction: string) => { + deleteCommentReaction: async (commentId, reaction) => { try { if (!workspaceSlug || !projectId || !commentId || !currentUser?.id) throw new Error("Missing fields"); removeCommentReaction(workspaceSlug, projectId, commentId, reaction, currentUser.id); @@ -125,7 +157,7 @@ export const useCommentOperations = ( type: TOAST_TYPE.SUCCESS, message: "Reaction removed successfully", }); - } catch (error) { + } catch { setToast({ title: "Error!", type: TOAST_TYPE.ERROR, @@ -133,14 +165,14 @@ export const useCommentOperations = ( }); } }, - react: async (commentId: string, reactionEmoji: string, userReactions: string[]) => { + react: async (commentId, reactionEmoji, userReactions) => { if (userReactions.includes(reactionEmoji)) await ops.deleteCommentReaction(commentId, reactionEmoji); else await ops.addCommentReaction(commentId, reactionEmoji); }, - reactionIds: (commentId: string) => getCommentReactionsByCommentId(commentId), - userReactions: (commentId: string) => + reactionIds: (commentId) => getCommentReactionsByCommentId(commentId), + userReactions: (commentId) => currentUser ? commentReactionsByUser(commentId, currentUser?.id).map((r) => r.reaction) : [], - getReactionUsers: (reaction: string, reactionIds: Record): string => { + getReactionUsers: (reaction, reactionIds) => { const reactionUsers = (reactionIds?.[reaction] || []) .map((reactionId) => { const reactionDetails = getCommentReactionById(reactionId); diff --git a/web/core/components/issues/issue-detail/issue-activity/index.ts b/apps/web/core/components/issues/issue-detail/issue-activity/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/index.ts rename to apps/web/core/components/issues/issue-detail/issue-activity/index.ts diff --git a/apps/web/core/components/issues/issue-detail/issue-activity/loader.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/loader.tsx new file mode 100644 index 000000000..915b5b207 --- /dev/null +++ b/apps/web/core/components/issues/issue-detail/issue-activity/loader.tsx @@ -0,0 +1,31 @@ +// plane imports +import { Loader } from "@plane/ui"; + +export const IssueActivityLoader = () => ( + +
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+); diff --git a/web/core/components/issues/issue-detail/issue-activity/root.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/root.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/root.tsx diff --git a/web/core/components/issues/issue-detail/issue-activity/sort-root.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/sort-root.tsx similarity index 100% rename from web/core/components/issues/issue-detail/issue-activity/sort-root.tsx rename to apps/web/core/components/issues/issue-detail/issue-activity/sort-root.tsx diff --git a/apps/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx b/apps/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx new file mode 100644 index 000000000..242c1399d --- /dev/null +++ b/apps/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx @@ -0,0 +1,174 @@ +"use client"; + +import React, { FC, useRef } from "react"; +import { observer } from "mobx-react"; +import { LinkIcon } from "lucide-react"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; +import { EIssuesStoreType } from "@plane/types"; +import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; +import { generateWorkItemLink, copyTextToClipboard } from "@plane/utils"; +// components +import { IssueSubscription } from "@/components/issues"; +// helpers +// hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail, useIssues, useProject, useUser } from "@/hooks/store"; +import { useAppRouter } from "@/hooks/use-app-router"; +import { usePlatformOS } from "@/hooks/use-platform-os"; +import { WorkItemDetailQuickActions } from "../issue-layouts/quick-action-dropdowns"; + +type Props = { + workspaceSlug: string; + projectId: string; + issueId: string; +}; + +export const IssueDetailQuickActions: FC = observer((props) => { + const { workspaceSlug, projectId, issueId } = props; + const { t } = useTranslation(); + + // ref + const parentRef = useRef(null); + + // router + const router = useAppRouter(); + + // hooks + const { data: currentUser } = useUser(); + const { isMobile } = usePlatformOS(); + const { getProjectIdentifierById } = useProject(); + const { + issue: { getIssueById }, + removeIssue, + archiveIssue, + } = useIssueDetail(); + const { + issues: { restoreIssue }, + } = useIssues(EIssuesStoreType.ARCHIVED); + const { + issues: { removeIssue: removeArchivedIssue }, + } = useIssues(EIssuesStoreType.ARCHIVED); + + // derived values + const issue = getIssueById(issueId); + if (!issue) return <>; + + const projectIdentifier = getProjectIdentifierById(projectId); + + const workItemLink = generateWorkItemLink({ + workspaceSlug: workspaceSlug, + projectId, + issueId, + projectIdentifier, + sequenceId: issue?.sequence_id, + }); + + // handlers + const handleCopyText = () => { + const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; + copyTextToClipboard(`${originURL}${workItemLink}`).then(() => { + setToast({ + type: TOAST_TYPE.SUCCESS, + title: t("common.link_copied"), + message: t("common.copied_to_clipboard"), + }); + }); + }; + + const handleDeleteIssue = async () => { + try { + const deleteIssue = issue?.archived_at ? removeArchivedIssue : removeIssue; + const redirectionPath = issue?.archived_at + ? `/${workspaceSlug}/projects/${projectId}/archives/issues` + : `/${workspaceSlug}/projects/${projectId}/issues`; + + return deleteIssue(workspaceSlug, projectId, issueId).then(() => { + router.push(redirectionPath); + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: issueId }, + }); + }); + } catch (error) { + setToast({ + title: t("toast.error "), + type: TOAST_TYPE.ERROR, + message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), + }); + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: issueId }, + error: error as Error, + }); + } + }; + + const handleArchiveIssue = async () => { + try { + await archiveIssue(workspaceSlug, projectId, issueId); + router.push(`/${workspaceSlug}/projects/${projectId}/issues`); + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.archive, + payload: { id: issueId }, + }); + } catch (error) { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.archive, + payload: { id: issueId }, + error: error as Error, + }); + } + }; + + const handleRestore = async () => { + if (!workspaceSlug || !projectId || !issueId) return; + + await restoreIssue(workspaceSlug.toString(), projectId.toString(), issueId.toString()) + .then(() => { + setToast({ + type: TOAST_TYPE.SUCCESS, + title: t("issue.restore.success.title"), + message: t("issue.restore.success.message"), + }); + router.push(workItemLink); + }) + .catch(() => { + setToast({ + type: TOAST_TYPE.ERROR, + title: t("toast.error"), + message: t("issue.restore.failed.message"), + }); + }); + }; + + return ( + <> +
+
+ {currentUser && !issue?.archived_at && ( + + )} +
+ + + + +
+
+
+ + ); +}); diff --git a/web/core/components/issues/issue-detail/label/create-label.tsx b/apps/web/core/components/issues/issue-detail/label/create-label.tsx similarity index 100% rename from web/core/components/issues/issue-detail/label/create-label.tsx rename to apps/web/core/components/issues/issue-detail/label/create-label.tsx diff --git a/web/core/components/issues/issue-detail/label/index.ts b/apps/web/core/components/issues/issue-detail/label/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/label/index.ts rename to apps/web/core/components/issues/issue-detail/label/index.ts diff --git a/web/core/components/issues/issue-detail/label/label-list-item.tsx b/apps/web/core/components/issues/issue-detail/label/label-list-item.tsx similarity index 100% rename from web/core/components/issues/issue-detail/label/label-list-item.tsx rename to apps/web/core/components/issues/issue-detail/label/label-list-item.tsx diff --git a/web/core/components/issues/issue-detail/label/label-list.tsx b/apps/web/core/components/issues/issue-detail/label/label-list.tsx similarity index 100% rename from web/core/components/issues/issue-detail/label/label-list.tsx rename to apps/web/core/components/issues/issue-detail/label/label-list.tsx diff --git a/web/core/components/issues/issue-detail/label/root.tsx b/apps/web/core/components/issues/issue-detail/label/root.tsx similarity index 96% rename from web/core/components/issues/issue-detail/label/root.tsx rename to apps/web/core/components/issues/issue-detail/label/root.tsx index ba31a81d0..89670dbb3 100644 --- a/web/core/components/issues/issue-detail/label/root.tsx +++ b/apps/web/core/components/issues/issue-detail/label/root.tsx @@ -2,9 +2,8 @@ import { FC, useMemo } from "react"; import { observer } from "mobx-react"; -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueLabel, TIssue, TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, IIssueLabel, TIssue, TIssueServiceType } from "@plane/types"; // components import { TOAST_TYPE, setToast } from "@plane/ui"; // hooks diff --git a/web/core/components/issues/issue-detail/label/select/label-select.tsx b/apps/web/core/components/issues/issue-detail/label/select/label-select.tsx similarity index 98% rename from web/core/components/issues/issue-detail/label/select/label-select.tsx rename to apps/web/core/components/issues/issue-detail/label/select/label-select.tsx index 509b0a5ca..a2ad09307 100644 --- a/web/core/components/issues/issue-detail/label/select/label-select.tsx +++ b/apps/web/core/components/issues/issue-detail/label/select/label-select.tsx @@ -4,9 +4,9 @@ import { usePopper } from "react-popper"; import { Check, Loader, Search, Tag } from "lucide-react"; import { Combobox } from "@headlessui/react"; // plane imports -import { EUserPermissionsLevel, EUserProjectRoles, getRandomLabelColor } from "@plane/constants"; +import { EUserPermissionsLevel, getRandomLabelColor } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueLabel } from "@plane/types"; +import { EUserProjectRoles, IIssueLabel } from "@plane/types"; // helpers import { getTabIndex } from "@plane/utils"; // hooks diff --git a/web/core/components/issues/issue-detail/label/select/root.tsx b/apps/web/core/components/issues/issue-detail/label/select/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail/label/select/root.tsx rename to apps/web/core/components/issues/issue-detail/label/select/root.tsx diff --git a/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx b/apps/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx similarity index 100% rename from web/core/components/issues/issue-detail/links/create-update-link-modal.tsx rename to apps/web/core/components/issues/issue-detail/links/create-update-link-modal.tsx diff --git a/web/core/components/issues/issue-detail/links/index.ts b/apps/web/core/components/issues/issue-detail/links/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/links/index.ts rename to apps/web/core/components/issues/issue-detail/links/index.ts diff --git a/web/core/components/issues/issue-detail/links/link-detail.tsx b/apps/web/core/components/issues/issue-detail/links/link-detail.tsx similarity index 100% rename from web/core/components/issues/issue-detail/links/link-detail.tsx rename to apps/web/core/components/issues/issue-detail/links/link-detail.tsx diff --git a/web/core/components/issues/issue-detail/links/link-item.tsx b/apps/web/core/components/issues/issue-detail/links/link-item.tsx similarity index 95% rename from web/core/components/issues/issue-detail/links/link-item.tsx rename to apps/web/core/components/issues/issue-detail/links/link-item.tsx index 526336c73..107c6ef43 100644 --- a/web/core/components/issues/issue-detail/links/link-item.tsx +++ b/apps/web/core/components/issues/issue-detail/links/link-item.tsx @@ -3,12 +3,11 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { Pencil, Trash2, Copy, Link } from "lucide-react"; -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssueServiceType } from "@plane/types"; // ui import { Tooltip, TOAST_TYPE, setToast, CustomMenu } from "@plane/ui"; -import { calculateTimeAgo, getIconForLink, copyTextToClipboard } from "@plane/utils"; +import { calculateTimeAgo, copyTextToClipboard } from "@plane/utils"; // helpers // hooks import { useIssueDetail } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-detail/links/link-list.tsx b/apps/web/core/components/issues/issue-detail/links/link-list.tsx similarity index 100% rename from web/core/components/issues/issue-detail/links/link-list.tsx rename to apps/web/core/components/issues/issue-detail/links/link-list.tsx diff --git a/web/core/components/issues/issue-detail/links/links.tsx b/apps/web/core/components/issues/issue-detail/links/links.tsx similarity index 100% rename from web/core/components/issues/issue-detail/links/links.tsx rename to apps/web/core/components/issues/issue-detail/links/links.tsx diff --git a/web/core/components/issues/issue-detail/links/root.tsx b/apps/web/core/components/issues/issue-detail/links/root.tsx similarity index 97% rename from web/core/components/issues/issue-detail/links/root.tsx rename to apps/web/core/components/issues/issue-detail/links/root.tsx index e37f1cadc..4512eb30b 100644 --- a/web/core/components/issues/issue-detail/links/root.tsx +++ b/apps/web/core/components/issues/issue-detail/links/root.tsx @@ -3,8 +3,7 @@ import { FC, useCallback, useMemo, useState } from "react"; import { Plus } from "lucide-react"; // plane imports -import { EIssueServiceType } from "@plane/constants"; -import { TIssueLink } from "@plane/types"; +import { EIssueServiceType, TIssueLink } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // hooks import { useIssueDetail } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-detail/main-content.tsx b/apps/web/core/components/issues/issue-detail/main-content.tsx similarity index 98% rename from web/core/components/issues/issue-detail/main-content.tsx rename to apps/web/core/components/issues/issue-detail/main-content.tsx index 175f03f1e..29a22c9c4 100644 --- a/web/core/components/issues/issue-detail/main-content.tsx +++ b/apps/web/core/components/issues/issue-detail/main-content.tsx @@ -3,9 +3,8 @@ import { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; // plane imports -import { EIssueServiceType } from "@plane/constants"; import { EditorRefApi } from "@plane/editor"; -import { TNameDescriptionLoader } from "@plane/types"; +import { EIssueServiceType, TNameDescriptionLoader } from "@plane/types"; // components import { getTextContent } from "@plane/utils"; import { DescriptionVersionsRoot } from "@/components/core/description-versions"; diff --git a/web/core/components/issues/issue-detail/module-select.tsx b/apps/web/core/components/issues/issue-detail/module-select.tsx similarity index 100% rename from web/core/components/issues/issue-detail/module-select.tsx rename to apps/web/core/components/issues/issue-detail/module-select.tsx diff --git a/web/core/components/issues/issue-detail/parent-select.tsx b/apps/web/core/components/issues/issue-detail/parent-select.tsx similarity index 100% rename from web/core/components/issues/issue-detail/parent-select.tsx rename to apps/web/core/components/issues/issue-detail/parent-select.tsx diff --git a/web/core/components/issues/issue-detail/parent/index.ts b/apps/web/core/components/issues/issue-detail/parent/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/parent/index.ts rename to apps/web/core/components/issues/issue-detail/parent/index.ts diff --git a/web/core/components/issues/issue-detail/parent/root.tsx b/apps/web/core/components/issues/issue-detail/parent/root.tsx similarity index 100% rename from web/core/components/issues/issue-detail/parent/root.tsx rename to apps/web/core/components/issues/issue-detail/parent/root.tsx diff --git a/web/core/components/issues/issue-detail/parent/sibling-item.tsx b/apps/web/core/components/issues/issue-detail/parent/sibling-item.tsx similarity index 100% rename from web/core/components/issues/issue-detail/parent/sibling-item.tsx rename to apps/web/core/components/issues/issue-detail/parent/sibling-item.tsx diff --git a/web/core/components/issues/issue-detail/parent/siblings.tsx b/apps/web/core/components/issues/issue-detail/parent/siblings.tsx similarity index 100% rename from web/core/components/issues/issue-detail/parent/siblings.tsx rename to apps/web/core/components/issues/issue-detail/parent/siblings.tsx diff --git a/web/core/components/issues/issue-detail/reactions/index.ts b/apps/web/core/components/issues/issue-detail/reactions/index.ts similarity index 100% rename from web/core/components/issues/issue-detail/reactions/index.ts rename to apps/web/core/components/issues/issue-detail/reactions/index.ts diff --git a/web/core/components/issues/issue-detail/reactions/issue-comment.tsx b/apps/web/core/components/issues/issue-detail/reactions/issue-comment.tsx similarity index 100% rename from web/core/components/issues/issue-detail/reactions/issue-comment.tsx rename to apps/web/core/components/issues/issue-detail/reactions/issue-comment.tsx diff --git a/web/core/components/issues/issue-detail/reactions/issue.tsx b/apps/web/core/components/issues/issue-detail/reactions/issue.tsx similarity index 100% rename from web/core/components/issues/issue-detail/reactions/issue.tsx rename to apps/web/core/components/issues/issue-detail/reactions/issue.tsx diff --git a/web/core/components/issues/issue-detail/reactions/reaction-selector.tsx b/apps/web/core/components/issues/issue-detail/reactions/reaction-selector.tsx similarity index 100% rename from web/core/components/issues/issue-detail/reactions/reaction-selector.tsx rename to apps/web/core/components/issues/issue-detail/reactions/reaction-selector.tsx diff --git a/web/core/components/issues/issue-detail/relation-select.tsx b/apps/web/core/components/issues/issue-detail/relation-select.tsx similarity index 100% rename from web/core/components/issues/issue-detail/relation-select.tsx rename to apps/web/core/components/issues/issue-detail/relation-select.tsx diff --git a/web/core/components/issues/issue-detail/root.tsx b/apps/web/core/components/issues/issue-detail/root.tsx similarity index 71% rename from web/core/components/issues/issue-detail/root.tsx rename to apps/web/core/components/issues/issue-detail/root.tsx index cbd679045..66c12d1f8 100644 --- a/web/core/components/issues/issue-detail/root.tsx +++ b/apps/web/core/components/issues/issue-detail/root.tsx @@ -2,11 +2,10 @@ import { FC, useMemo } from "react"; import { observer } from "mobx-react"; -import { usePathname } from "next/navigation"; // types -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue } from "@plane/types"; +import { EIssuesStoreType, TIssue } from "@plane/types"; // ui import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui"; // components @@ -14,7 +13,8 @@ import { EmptyState } from "@/components/common"; import { IssueDetailsSidebar, IssuePeekOverview } from "@/components/issues"; // constants // hooks -import { useAppTheme, useEventTracker, useIssueDetail, useIssues, useUserPermissions } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useAppTheme, useIssueDetail, useIssues, useUserPermissions } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // images import emptyIssue from "@/public/empty-state/issue.svg"; @@ -57,7 +57,6 @@ export const IssueDetailRoot: FC = observer((props) => { const { workspaceSlug, projectId, issueId, is_archived = false } = props; // router const router = useAppRouter(); - const pathname = usePathname(); // hooks const { issue: { getIssueById }, @@ -74,7 +73,6 @@ export const IssueDetailRoot: FC = observer((props) => { const { issues: { removeIssue: removeArchivedIssue }, } = useIssues(EIssuesStoreType.ARCHIVED); - const { captureIssueEvent } = useEventTracker(); const { allowPermissions } = useUserPermissions(); const { issueDetailSidebarCollapsed } = useAppTheme(); @@ -90,25 +88,16 @@ export const IssueDetailRoot: FC = observer((props) => { update: async (workspaceSlug: string, projectId: string, issueId: string, data: Partial) => { try { await updateIssue(workspaceSlug, projectId, issueId, data); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + payload: { id: issueId }, }); } catch (error) { console.log("Error in updating issue:", error); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); setToast({ title: t("common.error.label"), @@ -126,10 +115,9 @@ export const IssueDetailRoot: FC = observer((props) => { type: TOAST_TYPE.SUCCESS, message: t("entity.delete.success", { entity: t("issue.label") }), }); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - path: pathname, + payload: { id: issueId }, }); } catch (error) { console.log("Error in deleting issue:", error); @@ -138,85 +126,66 @@ export const IssueDetailRoot: FC = observer((props) => { type: TOAST_TYPE.ERROR, message: t("entity.delete.failed", { entity: t("issue.label") }), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, archive: async (workspaceSlug: string, projectId: string, issueId: string) => { try { await archiveIssue(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "SUCCESS", element: "Issue details page" }, - path: pathname, + payload: { id: issueId }, }); } catch (error) { console.log("Error in archiving issue:", error); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "FAILED", element: "Issue details page" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, addCycleToIssue: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => { try { await addCycleToIssue(workspaceSlug, projectId, cycleId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, }); - } catch { + } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: t("common.error.label"), message: t("issue.add.cycle.failed"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { try { await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, }); - } catch { + } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: t("common.error.label"), message: t("issue.add.cycle.failed"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -235,24 +204,15 @@ export const IssueDetailRoot: FC = observer((props) => { }, }); await removeFromCyclePromise; - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "cycle_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -271,24 +231,15 @@ export const IssueDetailRoot: FC = observer((props) => { }, }); await removeFromModulePromise; - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "module_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "FAILED", element: "Issue detail page" }, - updates: { - changed_property: "module_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -300,14 +251,9 @@ export const IssueDetailRoot: FC = observer((props) => { removeModuleIds: string[] ) => { const promise = await changeModulesInIssue(workspaceSlug, projectId, issueId, addModuleIds, removeModuleIds); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "module_id", - change_details: { addModuleIds, removeModuleIds }, - }, - path: pathname, + payload: { id: issueId }, }); return promise; }, @@ -324,9 +270,8 @@ export const IssueDetailRoot: FC = observer((props) => { removeIssueFromCycle, changeModulesInIssue, removeIssueFromModule, - captureIssueEvent, - pathname, t, + issueId, ] ); diff --git a/web/core/components/issues/issue-detail/sidebar.tsx b/apps/web/core/components/issues/issue-detail/sidebar.tsx similarity index 100% rename from web/core/components/issues/issue-detail/sidebar.tsx rename to apps/web/core/components/issues/issue-detail/sidebar.tsx diff --git a/web/core/components/issues/issue-detail/subscription.tsx b/apps/web/core/components/issues/issue-detail/subscription.tsx similarity index 95% rename from web/core/components/issues/issue-detail/subscription.tsx rename to apps/web/core/components/issues/issue-detail/subscription.tsx index 8239d08ac..504b625f6 100644 --- a/web/core/components/issues/issue-detail/subscription.tsx +++ b/apps/web/core/components/issues/issue-detail/subscription.tsx @@ -5,9 +5,10 @@ import isNil from "lodash/isNil"; import { observer } from "mobx-react"; import { Bell, BellOff } from "lucide-react"; // plane-i18n -import { EUserPermissions, EUserPermissionsLevel, EIssueServiceType } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // UI +import { EIssueServiceType } from "@plane/types"; import { Button, Loader, TOAST_TYPE, setToast } from "@plane/ui"; // hooks import { useIssueDetail, useUserPermissions } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx index 092ac047c..9ca5d12f8 100644 --- a/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx @@ -3,8 +3,8 @@ import { FC, useCallback, useEffect } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueGroupByToServerOptions, EIssuesStoreType,EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { TGroupedIssues } from "@plane/types"; +import { EIssueGroupByToServerOptions, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType, TGroupedIssues } from "@plane/types"; // components import { TOAST_TYPE, setToast } from "@plane/ui"; import { CalendarChart } from "@/components/issues"; diff --git a/web/core/components/issues/issue-layouts/calendar/calendar.tsx b/apps/web/core/components/issues/issue-layouts/calendar/calendar.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/calendar/calendar.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/calendar.tsx index 428beafc0..47d75531d 100644 --- a/web/core/components/issues/issue-layouts/calendar/calendar.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/calendar.tsx @@ -5,9 +5,10 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react"; // plane constants -import { EIssueLayoutTypes, EIssueFilterType, EIssuesStoreType } from "@plane/constants"; +import { EIssueFilterType } from "@plane/constants"; // types -import type { +import { + EIssuesStoreType, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, @@ -17,6 +18,7 @@ import type { TIssueMap, TPaginationData, ICalendarWeek, + EIssueLayoutTypes, } from "@plane/types"; // ui import { Spinner } from "@plane/ui"; diff --git a/web/core/components/issues/issue-layouts/calendar/day-tile.tsx b/apps/web/core/components/issues/issue-layouts/calendar/day-tile.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/day-tile.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/day-tile.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/dropdowns/index.ts b/apps/web/core/components/issues/issue-layouts/calendar/dropdowns/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/dropdowns/index.ts rename to apps/web/core/components/issues/issue-layouts/calendar/dropdowns/index.ts diff --git a/web/core/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx b/apps/web/core/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx b/apps/web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx index 35c2c281c..f41dbc06c 100644 --- a/web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/dropdowns/options-dropdown.tsx @@ -73,9 +73,9 @@ export const CalendarOptionsDropdown: React.FC = observer((prop const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false; const handleLayoutChange = (layout: TCalendarLayouts, closePopover: any) => { - if (!projectId || !updateFilters) return; + if (!updateFilters) return; - updateFilters(projectId.toString(), EIssueFilterType.DISPLAY_FILTERS, { + updateFilters(projectId?.toString(), EIssueFilterType.DISPLAY_FILTERS, { calendar: { ...issuesFilterStore.issueFilters?.displayFilters?.calendar, layout, @@ -93,9 +93,9 @@ export const CalendarOptionsDropdown: React.FC = observer((prop const handleToggleWeekends = () => { const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false; - if (!projectId || !updateFilters) return; + if (!updateFilters) return; - updateFilters(projectId.toString(), EIssueFilterType.DISPLAY_FILTERS, { + updateFilters(projectId?.toString(), EIssueFilterType.DISPLAY_FILTERS, { calendar: { ...issuesFilterStore.issueFilters?.displayFilters?.calendar, show_weekends: !showWeekends, diff --git a/web/core/components/issues/issue-layouts/calendar/header.tsx b/apps/web/core/components/issues/issue-layouts/calendar/header.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/header.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/header.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/index.ts b/apps/web/core/components/issues/issue-layouts/calendar/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/index.ts rename to apps/web/core/components/issues/issue-layouts/calendar/index.ts diff --git a/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/issue-block-root.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/issue-block.tsx b/apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/issue-block.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/issue-blocks.tsx b/apps/web/core/components/issues/issue-layouts/calendar/issue-blocks.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/issue-blocks.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/issue-blocks.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx b/apps/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx index a668e6a11..8f05892f1 100644 --- a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx @@ -5,12 +5,10 @@ import { differenceInCalendarDays } from "date-fns/differenceInCalendarDays"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { PlusIcon } from "lucide-react"; -// plane constants -import { EIssueLayoutTypes } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; // types -import { ISearchIssueResponse, TIssue } from "@plane/types"; +import { ISearchIssueResponse, TIssue, EIssueLayoutTypes } from "@plane/types"; // ui import { CustomMenu, setPromiseToast } from "@plane/ui"; // components diff --git a/web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx index ba85fb80f..d10e28b23 100644 --- a/web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/roots/cycle-root.tsx @@ -1,8 +1,8 @@ import { useCallback } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; +import { EIssuesStoreType } from "@plane/types"; //hooks -import { EIssuesStoreType } from "@plane/constants"; import { CycleIssueQuickActions } from "@/components/issues"; import { useCycle, useIssues } from "@/hooks/store"; // components diff --git a/web/core/components/issues/issue-layouts/calendar/roots/index.ts b/apps/web/core/components/issues/issue-layouts/calendar/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/calendar/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx index 296b4c5a3..0e1038e2f 100644 --- a/web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/roots/module-root.tsx @@ -1,9 +1,9 @@ import { useCallback } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; +import { EIssuesStoreType } from "@plane/types"; // hooks // components -import { EIssuesStoreType } from "@plane/constants"; import { ModuleIssueQuickActions } from "@/components/issues"; // types // constants diff --git a/web/core/components/issues/issue-layouts/calendar/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/roots/project-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/roots/project-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/roots/project-root.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/calendar/roots/project-view-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/roots/project-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/roots/project-view-root.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/utils.ts b/apps/web/core/components/issues/issue-layouts/calendar/utils.ts similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/utils.ts rename to apps/web/core/components/issues/issue-layouts/calendar/utils.ts diff --git a/web/core/components/issues/issue-layouts/calendar/week-days.tsx b/apps/web/core/components/issues/issue-layouts/calendar/week-days.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/calendar/week-days.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/week-days.tsx diff --git a/web/core/components/issues/issue-layouts/calendar/week-header.tsx b/apps/web/core/components/issues/issue-layouts/calendar/week-header.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/calendar/week-header.tsx rename to apps/web/core/components/issues/issue-layouts/calendar/week-header.tsx index dc2c9fbcf..d1164d1a5 100644 --- a/web/core/components/issues/issue-layouts/calendar/week-header.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/week-header.tsx @@ -1,5 +1,5 @@ import { observer } from "mobx-react"; -import { EStartOfTheWeek } from "@plane/constants"; +import { EStartOfTheWeek } from "@plane/types"; import { getOrderedDays } from "@plane/utils"; import { DAYS_LIST } from "@/constants/calendar"; // helpers diff --git a/web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx index f9aca06f2..73d138fcf 100644 --- a/web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/archived-issues.tsx @@ -2,9 +2,9 @@ import size from "lodash/size"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssueFilterType, EIssuesStoreType, EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EIssueFilterType, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssuesStoreType, EUserProjectRoles, IIssueFilterOptions } from "@plane/types"; // components import { DetailedEmptyState } from "@/components/empty-state"; // hooks diff --git a/web/core/components/issues/issue-layouts/empty-states/cycle.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx similarity index 92% rename from web/core/components/issues/issue-layouts/empty-states/cycle.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx index a29a4f280..59a7acdaf 100644 --- a/web/core/components/issues/issue-layouts/empty-states/cycle.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx @@ -6,14 +6,15 @@ import size from "lodash/size"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssueFilterType, EIssuesStoreType, EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EIssueFilterType, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueFilterOptions, ISearchIssueResponse } from "@plane/types"; +import { EIssuesStoreType, EUserProjectRoles, IIssueFilterOptions, ISearchIssueResponse } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { ExistingIssuesListModal } from "@/components/core"; import { DetailedEmptyState } from "@/components/empty-state"; -import { useCommandPalette, useCycle, useEventTracker, useIssues, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useCycle, useIssues, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const CycleEmptyState: React.FC = observer(() => { @@ -27,7 +28,6 @@ export const CycleEmptyState: React.FC = observer(() => { const { getCycleById } = useCycle(); const { issues, issuesFilter } = useIssues(EIssuesStoreType.CYCLE); const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); // derived values const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; @@ -133,7 +133,7 @@ export const CycleEmptyState: React.FC = observer(() => { primaryButton={{ text: t("project_cycles.empty_state.no_issues.primary_button.text"), onClick: () => { - setTrackElement("Cycle issue empty state"); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE }); toggleCreateIssueModal(true, EIssuesStoreType.CYCLE); }, disabled: !canPerformEmptyStateActions, diff --git a/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/draft-issues.tsx diff --git a/web/core/components/issues/issue-layouts/empty-states/global-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx similarity index 84% rename from web/core/components/issues/issue-layouts/empty-states/global-view.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx index 03d4c62ed..0d12f31dc 100644 --- a/web/core/components/issues/issue-layouts/empty-states/global-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx @@ -1,12 +1,14 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssuesStoreType, EUserPermissionsLevel, EUserWorkspaceRoles } from "@plane/constants"; +import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types"; // components import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state"; // hooks -import { useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useProject, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const GlobalViewEmptyState: React.FC = observer(() => { @@ -16,7 +18,6 @@ export const GlobalViewEmptyState: React.FC = observer(() => { // store hooks const { workspaceProjectIds } = useProject(); const { toggleCreateIssueModal, toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); // derived values const hasMemberLevelPermission = allowPermissions( @@ -45,8 +46,8 @@ export const GlobalViewEmptyState: React.FC = observer(() => { title={t("workspace_projects.empty_state.no_projects.primary_button.comic.title")} description={t("workspace_projects.empty_state.no_projects.primary_button.comic.description")} onClick={() => { - setTrackElement("All issues empty state"); toggleCreateProjectModal(true); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW }); }} disabled={!hasMemberLevelPermission} /> @@ -66,7 +67,7 @@ export const GlobalViewEmptyState: React.FC = observer(() => { ? { text: t(`workspace_views.empty_state.${resolvedCurrentView}.primary_button.text`), onClick: () => { - setTrackElement("All issues empty state"); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW }); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); }, disabled: !hasMemberLevelPermission, diff --git a/web/core/components/issues/issue-layouts/empty-states/index.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/empty-states/index.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/index.tsx index decf0e402..e51fa932d 100644 --- a/web/core/components/issues/issue-layouts/empty-states/index.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/index.tsx @@ -1,5 +1,5 @@ -import { EIssuesStoreType } from "@plane/constants"; // plane web components +import { EIssuesStoreType } from "@plane/types"; import { TeamEmptyState, TeamViewEmptyState } from "@/plane-web/components/issues/issue-layouts/empty-states"; // components import { ProjectArchivedEmptyState } from "./archived-issues"; diff --git a/web/core/components/issues/issue-layouts/empty-states/module.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx similarity index 91% rename from web/core/components/issues/issue-layouts/empty-states/module.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/module.tsx index 55edda7fe..f71010c58 100644 --- a/web/core/components/issues/issue-layouts/empty-states/module.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx @@ -5,15 +5,16 @@ import size from "lodash/size"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssueFilterType, EIssuesStoreType, EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EIssueFilterType, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueFilterOptions, ISearchIssueResponse } from "@plane/types"; +import { EIssuesStoreType, EUserProjectRoles, IIssueFilterOptions, ISearchIssueResponse } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { ExistingIssuesListModal } from "@/components/core"; import { DetailedEmptyState } from "@/components/empty-state"; +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks -import { useCommandPalette, useEventTracker, useIssues, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useIssues, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const ModuleEmptyState: React.FC = observer(() => { @@ -26,7 +27,6 @@ export const ModuleEmptyState: React.FC = observer(() => { // store hooks const { issues, issuesFilter } = useIssues(EIssuesStoreType.MODULE); const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); // derived values const userFilters = issuesFilter?.issueFilters?.filters; @@ -119,7 +119,7 @@ export const ModuleEmptyState: React.FC = observer(() => { primaryButton={{ text: t("project_module.empty_state.no_issues.primary_button.text"), onClick: () => { - setTrackElement("Module issue empty state"); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.MODULE }); toggleCreateIssueModal(true, EIssuesStoreType.MODULE); }, disabled: !canPerformEmptyStateActions, diff --git a/web/core/components/issues/issue-layouts/empty-states/profile-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/profile-view.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/empty-states/profile-view.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/profile-view.tsx diff --git a/web/core/components/issues/issue-layouts/empty-states/project-epic.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-epic.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/empty-states/project-epic.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/project-epic.tsx diff --git a/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx similarity index 87% rename from web/core/components/issues/issue-layouts/empty-states/project-issues.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx index 109b67c28..842a3485b 100644 --- a/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx @@ -2,13 +2,14 @@ import size from "lodash/size"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EIssueFilterType, EIssuesStoreType, EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EIssueFilterType, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssuesStoreType, EUserProjectRoles, IIssueFilterOptions } from "@plane/types"; // components import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state"; +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks -import { useCommandPalette, useEventTracker, useIssues, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useIssues, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; export const ProjectEmptyState: React.FC = observer(() => { @@ -18,7 +19,6 @@ export const ProjectEmptyState: React.FC = observer(() => { const { t } = useTranslation(); // store hooks const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT); const { allowPermissions } = useUserPermissions(); // derived values @@ -76,7 +76,7 @@ export const ProjectEmptyState: React.FC = observer(() => { title={t("project_issues.empty_state.no_issues.primary_button.comic.title")} description={t("project_issues.empty_state.no_issues.primary_button.comic.description")} onClick={() => { - setTrackElement("Project issue empty state"); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.WORK_ITEMS }); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); }} disabled={!canPerformEmptyStateActions} diff --git a/web/core/components/issues/issue-layouts/empty-states/project-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx similarity index 76% rename from web/core/components/issues/issue-layouts/empty-states/project-view.tsx rename to apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx index dd1760452..bd0ab5b2f 100644 --- a/web/core/components/issues/issue-layouts/empty-states/project-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx @@ -1,18 +1,18 @@ import { observer } from "mobx-react"; import { PlusIcon } from "lucide-react"; // components -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; +import { EIssuesStoreType } from "@plane/types"; import { EmptyState } from "@/components/common"; -// constants +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks -import { useCommandPalette, useEventTracker, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useUserPermissions } from "@/hooks/store"; // assets import emptyIssue from "@/public/empty-state/issue.svg"; export const ProjectViewEmptyState: React.FC = observer(() => { // store hooks const { toggleCreateIssueModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); // auth @@ -33,7 +33,7 @@ export const ProjectViewEmptyState: React.FC = observer(() => { text: "New work item", icon: , onClick: () => { - setTrackElement("View work item empty state"); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.PROJECT_VIEW }); toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW); }, } diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/cycle.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/cycle.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/cycle.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/cycle.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/date.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/date.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/date.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/date.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/filters-list.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/index.ts b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/index.ts rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/index.ts diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/label.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/label.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/label.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/label.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/module.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/module.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/module.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/module.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/priority.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/priority.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/priority.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/priority.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/project.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/project.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/project.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/project.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx index 91d720776..b27328a82 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks import { AppliedFiltersList } from "@/components/issues"; import { useIssues, useLabel, useProjectState } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx index 2628fe41d..d7af6e899 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/cycle-root.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks import { Header, EHeaderVariant } from "@plane/ui"; import { AppliedFiltersList, SaveFilterView } from "@/components/issues"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx index a596b4248..b774d2d34 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/draft-issue.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks import { AppliedFiltersList } from "@/components/issues"; import { useIssues, useLabel, useProjectState } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx similarity index 87% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx index 6bf8ed361..937523e03 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/global-view-root.tsx @@ -5,28 +5,24 @@ import cloneDeep from "lodash/cloneDeep"; import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -// types +// Plane imports import { DEFAULT_GLOBAL_VIEWS_LIST, EIssueFilterType, - EIssuesStoreType, - EViewAccess, EUserPermissions, EUserPermissionsLevel, - GLOBAL_VIEW_TOUR_TRACKER_EVENTS, + GLOBAL_VIEW_TRACKER_EVENTS, } from "@plane/constants"; -import { IIssueFilterOptions, TStaticViewTypes } from "@plane/types"; -//ui -// components +import { EIssuesStoreType, EViewAccess, IIssueFilterOptions, TStaticViewTypes } from "@plane/types"; import { Header, EHeaderVariant, Loader } from "@plane/ui"; import { cn } from "@plane/utils"; +// components import { AppliedFiltersList } from "@/components/issues"; import { UpdateViewComponent } from "@/components/views/update-view-component"; import { CreateUpdateWorkspaceViewModal } from "@/components/workspace"; -// constants -// helpers // hooks -import { useEventTracker, useGlobalView, useIssues, useLabel, useUser, useUserPermissions } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useGlobalView, useIssues, useLabel, useUser, useUserPermissions } from "@/hooks/store"; import { getAreFiltersEqual } from "../../../utils"; type Props = { @@ -44,7 +40,6 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => { } = useIssues(EIssuesStoreType.GLOBAL); const { workspaceLabels } = useLabel(); const { globalViewMap, updateGlobalView } = useGlobalView(); - const { captureEvent } = useEventTracker(); const { data } = useUser(); const { allowPermissions } = useUserPermissions(); @@ -112,15 +107,25 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => { const handleUpdateView = () => { if (!workspaceSlug || !globalViewId) return; - updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters).then((res) => { - if (res) - captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, { - view_id: res.id, - applied_filters: res.filters, - state: "SUCCESS", - element: "Spreadsheet view", + updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters) + .then((res) => { + if (res) + captureSuccess({ + eventName: GLOBAL_VIEW_TRACKER_EVENTS.update, + payload: { + view_id: globalViewId, + }, + }); + }) + .catch((error) => { + captureError({ + eventName: GLOBAL_VIEW_TRACKER_EVENTS.update, + payload: { + view_id: globalViewId, + }, + error: error, }); - }); + }); }; // add a placeholder object instead of appliedFilters if it is undefined diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/index.ts b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx index 10820d354..4e43a730a 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/module-root.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks import { Header, EHeaderVariant } from "@plane/ui"; import { AppliedFiltersList, SaveFilterView } from "@/components/issues"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx index eebf4fd9d..cbd41be9e 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { EIssueFilterType, EIssuesStoreType } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // hooks // components import { AppliedFiltersList } from "@/components/issues"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx index 90652c129..f20c9613f 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx @@ -1,8 +1,8 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // types -import { EIssueFilterType, EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType, IIssueFilterOptions } from "@plane/types"; // ui import { Header, EHeaderVariant } from "@plane/ui"; // components diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx index 6812c8119..beeecf9bb 100644 --- a/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-view-root.tsx @@ -6,14 +6,8 @@ import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // types -import { - EIssueFilterType, - EIssuesStoreType, - EViewAccess, - EUserPermissions, - EUserPermissionsLevel, -} from "@plane/constants"; -import { IIssueFilterOptions } from "@plane/types"; +import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType, EViewAccess, IIssueFilterOptions } from "@plane/types"; // components import { Header, EHeaderVariant } from "@plane/ui"; import { AppliedFiltersList } from "@/components/issues"; diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/state-group.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/state-group.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/state-group.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/state-group.tsx diff --git a/web/core/components/issues/issue-layouts/filters/applied-filters/state.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/state.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/applied-filters/state.tsx rename to apps/web/core/components/issues/issue-layouts/filters/applied-filters/state.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/extra-options.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/group-by.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/index.ts b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/index.ts rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/index.ts diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/issue-grouping.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/order-by.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/display-filters/sub-group-by.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/cycle.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/due-date.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/due-date.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/due-date.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/due-date.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/index.ts b/apps/web/core/components/issues/issue-layouts/filters/header/filters/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/index.ts rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/index.ts diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/labels.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/module.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/module.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/module.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/module.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/priority.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/project.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/project.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/project.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/project.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/start-date.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/state-group.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/state.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/state.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/filters/header/filters/state.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/filters/state.tsx diff --git a/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx similarity index 61% rename from web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx rename to apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx index f7c8deab1..c831b647e 100644 --- a/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx @@ -13,6 +13,7 @@ import { Button } from "@plane/ui"; type Props = { children: React.ReactNode; icon?: React.ReactNode; + miniIcon?: React.ReactNode; title?: string; placement?: Placement; disabled?: boolean; @@ -24,6 +25,7 @@ type Props = { export const FiltersDropdown: React.FC = (props) => { const { children, + miniIcon, icon, title = "Dropdown", placement, @@ -33,7 +35,7 @@ export const FiltersDropdown: React.FC = (props) => { isFiltersApplied = false, } = props; - const [referenceElement, setReferenceElement] = useState(null); + const [referenceElement, setReferenceElement] = useState(null); const [popperElement, setPopperElement] = useState(null); const { styles, attributes } = usePopper(referenceElement, popperElement, { @@ -53,27 +55,42 @@ export const FiltersDropdown: React.FC = (props) => { {menuButton} ) : ( - +
+
+ +
+
+ +
+
)} void; + activeLayout?: EIssueLayoutTypes; + isMobile?: boolean; +}) => { + const { t } = useTranslation(); + return ( + + + + + ) : ( +
+ {t("common.layout")} + +
+ ) + } + customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm" + closeOnSelect + > + {ISSUE_LAYOUTS.filter((l) => layouts.includes(l.key)).map((layout, index) => ( + { + onChange(layout.key); + }} + className="flex items-center gap-2" + > + +
{t(layout.i18n_label)}
+
+ ))} +
+ ); +}; diff --git a/web/core/components/issues/issue-layouts/filters/index.ts b/apps/web/core/components/issues/issue-layouts/filters/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/filters/index.ts rename to apps/web/core/components/issues/issue-layouts/filters/index.ts diff --git a/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx b/apps/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx rename to apps/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx index 594bcd2fa..89f63d96b 100644 --- a/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx @@ -2,15 +2,9 @@ import React, { useCallback, useEffect } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane constants -import { - ALL_ISSUES, - EIssueLayoutTypes, - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, -} from "@plane/constants"; +import { ALL_ISSUES, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import type { IBlockUpdateData, TIssue } from "@plane/types"; +import { EIssuesStoreType, IBlockUpdateData, TIssue, EIssueLayoutTypes } from "@plane/types"; import { setToast, TOAST_TYPE } from "@plane/ui"; // hooks import { renderFormattedPayloadDate } from "@plane/utils"; diff --git a/web/core/components/issues/issue-layouts/gantt/blocks.tsx b/apps/web/core/components/issues/issue-layouts/gantt/blocks.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/gantt/blocks.tsx rename to apps/web/core/components/issues/issue-layouts/gantt/blocks.tsx diff --git a/web/core/components/issues/issue-layouts/gantt/index.ts b/apps/web/core/components/issues/issue-layouts/gantt/index.ts similarity index 98% rename from web/core/components/issues/issue-layouts/gantt/index.ts rename to apps/web/core/components/issues/issue-layouts/gantt/index.ts index 1cd0649fc..b0eb6d232 100644 --- a/web/core/components/issues/issue-layouts/gantt/index.ts +++ b/apps/web/core/components/issues/issue-layouts/gantt/index.ts @@ -1,3 +1,2 @@ export * from "./blocks"; export * from "./base-gantt-root"; - diff --git a/web/core/components/issues/issue-layouts/group-drag-overlay.tsx b/apps/web/core/components/issues/issue-layouts/group-drag-overlay.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/group-drag-overlay.tsx rename to apps/web/core/components/issues/issue-layouts/group-drag-overlay.tsx diff --git a/web/core/components/issues/issue-layouts/index.ts b/apps/web/core/components/issues/issue-layouts/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/index.ts rename to apps/web/core/components/issues/issue-layouts/index.ts diff --git a/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx b/apps/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/issue-layout-HOC.tsx rename to apps/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx index 24cf204f9..517e11828 100644 --- a/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx +++ b/apps/web/core/components/issues/issue-layouts/issue-layout-HOC.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; // plane constants -import { EIssueLayoutTypes } from "@plane/constants"; +import { EIssueLayoutTypes } from "@plane/types"; import { CalendarLayoutLoader, GanttLayoutLoader, diff --git a/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx similarity index 70% rename from web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx index d4b29a35d..bed7a3ba0 100644 --- a/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx @@ -5,20 +5,14 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; -import { - EIssueLayoutTypes, - EIssueServiceType, - EIssueFilterType, - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, - WORK_ITEM_TRACKER_EVENTS, -} from "@plane/constants"; +import { useParams } from "next/navigation"; +import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { EIssueServiceType, EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; import { DeleteIssueModal } from "@/components/issues"; //constants //hooks -import { useEventTracker, useIssueDetail, useIssues, useKanbanView, useUserPermissions } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail, useIssues, useKanbanView, useUserPermissions } from "@/hooks/store"; import { useGroupIssuesDragNDrop } from "@/hooks/use-group-dragndrop"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { useIssuesActions } from "@/hooks/use-issues-actions"; @@ -63,11 +57,9 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas } = props; // router const { workspaceSlug, projectId } = useParams(); - const pathname = usePathname(); // store hooks const storeType = useIssueStoreType() as KanbanStoreType; const { allowPermissions } = useUserPermissions(); - const { captureIssueEvent } = useEventTracker(); const { issueMap, issuesFilter, issues } = useIssues(storeType); const { issue: { getIssueById }, @@ -206,15 +198,23 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas if (!draggedIssueId || !draggedIssue) return; - await removeIssue(draggedIssue.project_id, draggedIssueId).finally(() => { - setDeleteIssueModal(false); - setDraggedIssueId(undefined); - captureIssueEvent({ - eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: draggedIssueId, state: "FAILED", element: "Kanban layout drag & drop" }, - path: pathname, + await removeIssue(draggedIssue.project_id, draggedIssueId) + .then(() => { + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: draggedIssueId }, + }); + }) + .catch(() => { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: draggedIssueId }, + }); + }) + .finally(() => { + setDeleteIssueModal(false); + setDraggedIssueId(undefined); }); - }); }; const handleCollapsedGroups = useCallback( @@ -237,64 +237,65 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas const collapsedGroups = issuesFilter?.issueFilters?.kanbanFilters || { group_by: [], sub_group_by: [] }; return ( - + <> setDeleteIssueModal(false)} onSubmit={handleDeleteIssue} + isEpic={isEpic} /> - + {/* drag and delete component */}
-
- {/* drag and delete component */} -
-
- Drop here to delete the work item. -
-
- -
- -
+
+ Drop here to delete the work item.
- + +
+
+
+ +
+
+
+
+ ); }); diff --git a/web/core/components/issues/issue-layouts/kanban/block.tsx b/apps/web/core/components/issues/issue-layouts/kanban/block.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/kanban/block.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/block.tsx index 2347df968..f0fe531de 100644 --- a/web/core/components/issues/issue-layouts/kanban/block.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/block.tsx @@ -7,10 +7,9 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane helpers import { MoreHorizontal } from "lucide-react"; -import { EIssueServiceType } from "@plane/constants"; import { useOutsideClickDetector } from "@plane/hooks"; // types -import { TIssue, IIssueDisplayProperties, IIssueMap } from "@plane/types"; +import { EIssueServiceType, TIssue, IIssueDisplayProperties, IIssueMap } from "@plane/types"; // ui import { ControlLink, DropIndicator, TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { cn, generateWorkItemLink } from "@plane/utils"; diff --git a/web/core/components/issues/issue-layouts/kanban/blocks-list.tsx b/apps/web/core/components/issues/issue-layouts/kanban/blocks-list.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/blocks-list.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/blocks-list.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/default.tsx b/apps/web/core/components/issues/issue-layouts/kanban/default.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/default.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/default.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx b/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx index 6166b158a..d40fbf0d5 100644 --- a/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx @@ -5,6 +5,7 @@ import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; // lucide icons import { Minimize2, Maximize2, Circle, Plus } from "lucide-react"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { TIssue, ISearchIssueResponse, TIssueKanbanFilters, TIssueGroupByOptions } from "@plane/types"; // ui import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui"; @@ -12,8 +13,7 @@ import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui"; import { ExistingIssuesListModal } from "@/components/core"; import { CreateUpdateIssueModal } from "@/components/issues"; // constants -// hooks -import { useEventTracker } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { CreateUpdateEpicModal } from "@/plane-web/components/epics/epic-modal"; // types @@ -56,7 +56,6 @@ export const HeaderGroupByCard: FC = observer((props) => { const [openExistingIssueListModal, setOpenExistingIssueListModal] = React.useState(false); // hooks const storeType = useIssueStoreType(); - const { setTrackElement } = useEventTracker(); // router const { workspaceSlug, projectId, moduleId, cycleId } = useParams(); const pathname = usePathname(); @@ -167,7 +166,7 @@ export const HeaderGroupByCard: FC = observer((props) => { > { - setTrackElement("Kanban layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.create }); setIsOpen(true); }} > @@ -175,7 +174,7 @@ export const HeaderGroupByCard: FC = observer((props) => { { - setTrackElement("Kanban layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.add_existing }); setOpenExistingIssueListModal(true); }} > @@ -186,7 +185,7 @@ export const HeaderGroupByCard: FC = observer((props) => {
{ - setTrackElement("Kanban layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.create }); setIsOpen(true); }} > diff --git a/web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx b/apps/web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/index.ts b/apps/web/core/components/issues/issue-layouts/kanban/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/index.ts rename to apps/web/core/components/issues/issue-layouts/kanban/index.ts diff --git a/web/core/components/issues/issue-layouts/kanban/kanban-group.tsx b/apps/web/core/components/issues/issue-layouts/kanban/kanban-group.tsx similarity index 99% rename from web/core/components/issues/issue-layouts/kanban/kanban-group.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/kanban-group.tsx index 988f24486..a95109ad5 100644 --- a/web/core/components/issues/issue-layouts/kanban/kanban-group.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/kanban-group.tsx @@ -6,7 +6,7 @@ import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react"; // plane constants -import { EIssueLayoutTypes, DRAG_ALLOWED_GROUPS } from "@plane/constants"; +import { DRAG_ALLOWED_GROUPS } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; //types @@ -18,6 +18,7 @@ import { TSubGroupedIssues, TIssueGroupByOptions, TIssueOrderByOptions, + EIssueLayoutTypes, } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; import { cn } from "@plane/utils"; diff --git a/web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx similarity index 93% rename from web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx index 0dce7e181..16f0990d9 100644 --- a/web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/roots/cycle-root.tsx @@ -2,7 +2,8 @@ import React, { useCallback } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // components -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType } from "@plane/types"; import { CycleIssueQuickActions } from "@/components/issues"; // constants // hooks diff --git a/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/draft-issue-root.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/roots/index.ts b/apps/web/core/components/issues/issue-layouts/kanban/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/kanban/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx index 0e46fc505..7944ffc79 100644 --- a/web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/roots/module-root.tsx @@ -1,8 +1,8 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; +import { EIssuesStoreType } from "@plane/types"; // hook -import { EIssuesStoreType } from "@plane/constants"; import { ModuleIssueQuickActions } from "@/components/issues"; import { useIssues } from "@/hooks/store"; // components diff --git a/web/core/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/project-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/roots/project-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/project-root.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/kanban/roots/project-view-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/roots/project-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/roots/project-view-root.tsx diff --git a/web/core/components/issues/issue-layouts/kanban/swimlanes.tsx b/apps/web/core/components/issues/issue-layouts/kanban/swimlanes.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/kanban/swimlanes.tsx rename to apps/web/core/components/issues/issue-layouts/kanban/swimlanes.tsx diff --git a/web/core/components/issues/issue-layouts/layout-icon.tsx b/apps/web/core/components/issues/issue-layouts/layout-icon.tsx similarity index 92% rename from web/core/components/issues/issue-layouts/layout-icon.tsx rename to apps/web/core/components/issues/issue-layouts/layout-icon.tsx index 01243c374..edf0a78ed 100644 --- a/web/core/components/issues/issue-layouts/layout-icon.tsx +++ b/apps/web/core/components/issues/issue-layouts/layout-icon.tsx @@ -1,5 +1,5 @@ import { List, Kanban, Calendar, Sheet, GanttChartSquare, LucideProps } from "lucide-react"; -import { EIssueLayoutTypes } from "@plane/constants"; +import { EIssueLayoutTypes } from "@plane/types"; export const IssueLayoutIcon = ({ layout, ...props }: { layout: EIssueLayoutTypes } & LucideProps) => { switch (layout) { diff --git a/web/core/components/issues/issue-layouts/list/base-list-root.tsx b/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/list/base-list-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx index ceccd87d2..5f0e71f7f 100644 --- a/web/core/components/issues/issue-layouts/list/base-list-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/base-list-root.tsx @@ -2,15 +2,15 @@ import { FC, useCallback, useEffect } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane constants -import { - EIssueLayoutTypes, - EIssueFilterType, - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, -} from "@plane/constants"; +import { EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; // types -import { GroupByColumnTypes, TGroupedIssues, TIssueKanbanFilters } from "@plane/types"; +import { + EIssuesStoreType, + GroupByColumnTypes, + TGroupedIssues, + TIssueKanbanFilters, + EIssueLayoutTypes, +} from "@plane/types"; // constants // hooks import { useIssues, useUserPermissions } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-layouts/list/block-root.tsx b/apps/web/core/components/issues/issue-layouts/list/block-root.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/list/block-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/block-root.tsx index bcb2ef189..ca5c45616 100644 --- a/web/core/components/issues/issue-layouts/list/block-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/block-root.tsx @@ -5,11 +5,10 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item"; import { observer } from "mobx-react"; -import { EIssueServiceType } from "@plane/constants"; // plane helpers import { useOutsideClickDetector } from "@plane/hooks"; // types -import { IIssueDisplayProperties, TIssue, TIssueMap } from "@plane/types"; +import { EIssueServiceType, IIssueDisplayProperties, TIssue, TIssueMap } from "@plane/types"; // components import { DropIndicator } from "@plane/ui"; import RenderIfVisible from "@/components/core/render-if-visible-HOC"; diff --git a/web/core/components/issues/issue-layouts/list/block.tsx b/apps/web/core/components/issues/issue-layouts/list/block.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/list/block.tsx rename to apps/web/core/components/issues/issue-layouts/list/block.tsx index 67d282753..755d46295 100644 --- a/web/core/components/issues/issue-layouts/list/block.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/block.tsx @@ -6,9 +6,8 @@ import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronRight } from "lucide-react"; -import { EIssueServiceType } from "@plane/constants"; // types -import { TIssue, IIssueDisplayProperties, TIssueMap } from "@plane/types"; +import { EIssueServiceType, TIssue, IIssueDisplayProperties, TIssueMap } from "@plane/types"; // ui import { Spinner, Tooltip, ControlLink, setToast, TOAST_TYPE, Row } from "@plane/ui"; import { cn, generateWorkItemLink } from "@plane/utils"; diff --git a/web/core/components/issues/issue-layouts/list/blocks-list.tsx b/apps/web/core/components/issues/issue-layouts/list/blocks-list.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/blocks-list.tsx rename to apps/web/core/components/issues/issue-layouts/list/blocks-list.tsx diff --git a/web/core/components/issues/issue-layouts/list/default.tsx b/apps/web/core/components/issues/issue-layouts/list/default.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/default.tsx rename to apps/web/core/components/issues/issue-layouts/list/default.tsx diff --git a/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx b/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx rename to apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx index 44bc95bff..f107c28b6 100644 --- a/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx @@ -5,6 +5,7 @@ import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; import { CircleDashed, Plus } from "lucide-react"; // types +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { TIssue, ISearchIssueResponse, TIssueGroupByOptions } from "@plane/types"; // ui import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui"; @@ -13,9 +14,7 @@ import { cn } from "@plane/utils"; import { ExistingIssuesListModal, MultipleSelectGroupAction } from "@/components/core"; import { CreateUpdateIssueModal } from "@/components/issues"; // constants -// helpers -// hooks -import { useEventTracker } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { TSelectionHelper } from "@/hooks/use-multiple-select"; // plane-web @@ -59,8 +58,6 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => { // router const { workspaceSlug, projectId, moduleId, cycleId } = useParams(); const pathname = usePathname(); - // hooks - const { setTrackElement } = useEventTracker(); const storeType = useIssueStoreType(); // derived values const isDraftIssue = pathname.includes("draft-issue"); @@ -134,7 +131,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => { > { - setTrackElement("List layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.create }); setIsOpen(true); }} > @@ -142,7 +139,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => { { - setTrackElement("List layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.add_existing }); setOpenExistingIssueListModal(true); }} > @@ -153,7 +150,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
{ - setTrackElement("List layout"); + captureClick({ elementName: WORK_ITEM_TRACKER_EVENTS.create }); setIsOpen(true); }} > diff --git a/web/core/components/issues/issue-layouts/list/index.ts b/apps/web/core/components/issues/issue-layouts/list/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/list/index.ts rename to apps/web/core/components/issues/issue-layouts/list/index.ts diff --git a/web/core/components/issues/issue-layouts/list/list-group.tsx b/apps/web/core/components/issues/issue-layouts/list/list-group.tsx similarity index 99% rename from web/core/components/issues/issue-layouts/list/list-group.tsx rename to apps/web/core/components/issues/issue-layouts/list/list-group.tsx index 99fa9de99..5d43fec4d 100644 --- a/web/core/components/issues/issue-layouts/list/list-group.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/list-group.tsx @@ -5,7 +5,7 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; // plane constants -import { EIssueLayoutTypes, DRAG_ALLOWED_GROUPS } from "@plane/constants"; +import { DRAG_ALLOWED_GROUPS } from "@plane/constants"; // plane i18n import { useTranslation } from "@plane/i18n"; // plane ui @@ -17,6 +17,7 @@ import { TIssue, IIssueDisplayProperties, TIssueKanbanFilters, + EIssueLayoutTypes, } from "@plane/types"; import { Row, setToast, TOAST_TYPE } from "@plane/ui"; // plane utils diff --git a/web/core/components/issues/issue-layouts/list/list-view-types.d.ts b/apps/web/core/components/issues/issue-layouts/list/list-view-types.d.ts similarity index 100% rename from web/core/components/issues/issue-layouts/list/list-view-types.d.ts rename to apps/web/core/components/issues/issue-layouts/list/list-view-types.d.ts diff --git a/web/core/components/issues/issue-layouts/list/roots/archived-issue-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/archived-issue-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/archived-issue-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/archived-issue-root.tsx diff --git a/web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx similarity index 93% rename from web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx index 2d3eb4a8a..a542537dc 100644 --- a/web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/roots/cycle-root.tsx @@ -2,7 +2,8 @@ import React, { useCallback } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // components -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType } from "@plane/types"; import { CycleIssueQuickActions } from "@/components/issues"; // constants // hooks diff --git a/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/draft-issue-root.tsx diff --git a/web/core/components/issues/issue-layouts/list/roots/index.ts b/apps/web/core/components/issues/issue-layouts/list/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/list/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/list/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/module-root.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/list/roots/module-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/module-root.tsx index 257a6be97..c04be1ac1 100644 --- a/web/core/components/issues/issue-layouts/list/roots/module-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/list/roots/module-root.tsx @@ -1,8 +1,8 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; +import { EIssuesStoreType } from "@plane/types"; // mobx store -import { EIssuesStoreType } from "@plane/constants"; import { ModuleIssueQuickActions } from "@/components/issues"; import { useIssues } from "@/hooks/store"; // components diff --git a/web/core/components/issues/issue-layouts/list/roots/profile-issues-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/profile-issues-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/profile-issues-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/profile-issues-root.tsx diff --git a/web/core/components/issues/issue-layouts/list/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/project-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/project-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/project-root.tsx diff --git a/web/core/components/issues/issue-layouts/list/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/list/roots/project-view-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/list/roots/project-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/list/roots/project-view-root.tsx diff --git a/web/core/components/issues/issue-layouts/properties/all-properties.tsx b/apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx similarity index 87% rename from web/core/components/issues/issue-layouts/properties/all-properties.tsx rename to apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx index dce2b943e..852c5f5a3 100644 --- a/web/core/components/issues/issue-layouts/properties/all-properties.tsx +++ b/apps/web/core/components/issues/issue-layouts/properties/all-properties.tsx @@ -3,7 +3,7 @@ import { useCallback, useMemo, SyntheticEvent } from "react"; import xor from "lodash/xor"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // icons import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react"; // types @@ -34,7 +34,8 @@ import { // constants // helpers // hooks -import { useEventTracker, useLabel, useIssues, useProjectState, useProject, useProjectEstimates } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; +import { useLabel, useIssues, useProjectState, useProject, useProjectEstimates } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -55,13 +56,12 @@ export interface IIssueProperties { } export const IssueProperties: React.FC = observer((props) => { - const { issue, updateIssue, displayProperties, activeLayout, isReadOnly, className, isEpic = false } = props; + const { issue, updateIssue, displayProperties, isReadOnly, className, isEpic = false } = props; // i18n const { t } = useTranslation(); // store hooks const { getProjectById } = useProject(); const { labelMap } = useLabel(); - const { captureIssueEvent } = useEventTracker(); const storeType = useIssueStoreType(); const { issues: { changeModulesInIssue }, @@ -77,9 +77,7 @@ export const IssueProperties: React.FC = observer((props) => { // router const router = useAppRouter(); const { workspaceSlug, projectId } = useParams(); - const pathname = usePathname(); - const currentLayout = `${activeLayout} layout`; // derived values const stateDetails = getStateById(issue.state_id); const subIssueCount = issue?.sub_issues_count ?? 0; @@ -109,14 +107,9 @@ export const IssueProperties: React.FC = observer((props) => { const handleState = (stateId: string) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { state_id: stateId }).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "state", - change_details: stateId, - }, + payload: { id: issue.id }, }); }); }; @@ -124,14 +117,9 @@ export const IssueProperties: React.FC = observer((props) => { const handlePriority = (value: TIssuePriorities) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { priority: value }).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "priority", - change_details: value, - }, + payload: { id: issue.id }, }); }); }; @@ -139,14 +127,9 @@ export const IssueProperties: React.FC = observer((props) => { const handleLabel = (ids: string[]) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { label_ids: ids }).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "labels", - change_details: ids, - }, + payload: { id: issue.id }, }); }); }; @@ -154,14 +137,9 @@ export const IssueProperties: React.FC = observer((props) => { const handleAssignee = (ids: string[]) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { assignee_ids: ids }).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "assignees", - change_details: ids, - }, + payload: { id: issue.id }, }); }); }; @@ -179,14 +157,12 @@ export const IssueProperties: React.FC = observer((props) => { if (modulesToAdd.length > 0) issueOperations.addModulesToIssue(modulesToAdd); if (modulesToRemove.length > 0) issueOperations.removeModulesFromIssue(modulesToRemove); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { changed_property: "module_ids", change_details: { module_ids: moduleIds } }, + payload: { id: issue.id }, }); }, - [issueOperations, captureIssueEvent, currentLayout, pathname, issue] + [issueOperations, issue] ); const handleCycle = useCallback( @@ -195,28 +171,21 @@ export const IssueProperties: React.FC = observer((props) => { if (cycleId) issueOperations.addIssueToCycle?.(cycleId); else issueOperations.removeIssueFromCycle?.(); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { changed_property: "cycle", change_details: { cycle_id: cycleId } }, + payload: { id: issue.id }, }); }, - [issue, issueOperations, captureIssueEvent, currentLayout, pathname] + [issue, issueOperations] ); const handleStartDate = (date: Date | null) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { start_date: date ? renderFormattedPayloadDate(date) : null }).then( () => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "start_date", - change_details: date ? renderFormattedPayloadDate(date) : null, - }, + payload: { id: issue.id }, }); } ); @@ -226,14 +195,9 @@ export const IssueProperties: React.FC = observer((props) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { target_date: date ? renderFormattedPayloadDate(date) : null }).then( () => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "target_date", - change_details: date ? renderFormattedPayloadDate(date) : null, - }, + payload: { id: issue.id }, }); } ); @@ -242,14 +206,9 @@ export const IssueProperties: React.FC = observer((props) => { const handleEstimate = (value: string | undefined) => { if (updateIssue) updateIssue(issue.project_id, issue.id, { estimate_point: value }).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issue, state: "SUCCESS", element: currentLayout }, - path: pathname, - updates: { - changed_property: "estimate_point", - change_details: value, - }, + payload: { id: issue.id }, }); }); }; diff --git a/web/core/components/issues/issue-layouts/properties/index.ts b/apps/web/core/components/issues/issue-layouts/properties/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/properties/index.ts rename to apps/web/core/components/issues/issue-layouts/properties/index.ts diff --git a/web/core/components/issues/issue-layouts/properties/label-dropdown.tsx b/apps/web/core/components/issues/issue-layouts/properties/label-dropdown.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/properties/label-dropdown.tsx rename to apps/web/core/components/issues/issue-layouts/properties/label-dropdown.tsx index 931d0f30c..354567eaf 100644 --- a/web/core/components/issues/issue-layouts/properties/label-dropdown.tsx +++ b/apps/web/core/components/issues/issue-layouts/properties/label-dropdown.tsx @@ -5,11 +5,11 @@ import { usePopper } from "react-popper"; import { Check, ChevronDown, Loader, Search } from "lucide-react"; import { Combobox } from "@headlessui/react"; // plane imports -import { EUserPermissionsLevel, EUserProjectRoles, getRandomLabelColor } from "@plane/constants"; +import { EUserPermissionsLevel, getRandomLabelColor } from "@plane/constants"; import { useOutsideClickDetector } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; // types -import { IIssueLabel } from "@plane/types"; +import { EUserProjectRoles, IIssueLabel } from "@plane/types"; // components import { ComboDropDown } from "@plane/ui"; // hooks diff --git a/web/core/components/issues/issue-layouts/properties/labels.tsx b/apps/web/core/components/issues/issue-layouts/properties/labels.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/properties/labels.tsx rename to apps/web/core/components/issues/issue-layouts/properties/labels.tsx diff --git a/web/core/components/issues/issue-layouts/properties/with-display-properties-HOC.tsx b/apps/web/core/components/issues/issue-layouts/properties/with-display-properties-HOC.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/properties/with-display-properties-HOC.tsx rename to apps/web/core/components/issues/issue-layouts/properties/with-display-properties-HOC.tsx diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx similarity index 90% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx index d3524559d..2087a1bdc 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx @@ -5,14 +5,15 @@ import omit from "lodash/omit"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { ARCHIVABLE_STATE_GROUPS, EIssuesStoreType } from "@plane/constants"; -import { TIssue } from "@plane/types"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { ARCHIVABLE_STATE_GROUPS, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; // hooks -import { useEventTracker, useProject, useProjectState } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useProject, useProjectState } from "@/hooks/store"; // plane-web components import { DuplicateWorkItemModal } from "@/plane-web/components/issues/issue-layouts/quick-action-dropdowns"; import { IQuickActionProps } from "../list/list-view-types"; @@ -39,8 +40,6 @@ export const AllIssueQuickActions: React.FC = observer((props const [duplicateWorkItemModal, setDuplicateWorkItemModal] = useState(false); // router const { workspaceSlug } = useParams(); - // store hooks - const { setTrackElement } = useEventTracker(); const { getStateById } = useProjectState(); const { getProjectIdentifierById } = useProject(); // derived values @@ -70,7 +69,6 @@ export const AllIssueQuickActions: React.FC = observer((props isArchivingAllowed, isDeletingAllowed: isEditingAllowed, isInArchivableGroup, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -84,6 +82,14 @@ export const AllIssueQuickActions: React.FC = observer((props const MENU_ITEMS = useAllIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.GLOBAL_VIEW }); + item.action(); + }, + })); + return ( <> {/* Modals */} @@ -122,7 +128,7 @@ export const AllIssueQuickActions: React.FC = observer((props /> )} - + = observer((props onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.GLOBAL_VIEW }); nestedItem.action(); }} className={cn( @@ -208,6 +215,7 @@ export const AllIssueQuickActions: React.FC = observer((props onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.GLOBAL_VIEW }); item.action(); }} className={cn( diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx similarity index 82% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx index b8b74764d..347a07c1f 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx @@ -4,14 +4,16 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // ui -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; +import { EIssuesStoreType } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { DeleteIssueModal } from "@/components/issues"; // helpers // hooks -import { useEventTracker, useIssues, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssues, useUserPermissions } from "@/hooks/store"; // types import { IQuickActionProps } from "../list/list-view-types"; // helper @@ -35,7 +37,6 @@ export const ArchivedIssueQuickActions: React.FC = observer(( // store hooks const { allowPermissions } = useUserPermissions(); - const { setTrackElement } = useEventTracker(); const { issuesFilter } = useIssues(EIssuesStoreType.ARCHIVED); // derived values const activeLayout = `${issuesFilter.issueFilters?.displayFilters?.layout} layout`; @@ -53,7 +54,6 @@ export const ArchivedIssueQuickActions: React.FC = observer(( isEditingAllowed, isDeletingAllowed: isEditingAllowed, isRestoringAllowed: !!isRestoringAllowed, - setTrackElement, setIssueToEdit: () => {}, setCreateUpdateIssueModal: () => {}, setDeleteIssueModal, @@ -63,6 +63,13 @@ export const ArchivedIssueQuickActions: React.FC = observer(( const MENU_ITEMS = useArchivedIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.ARCHIVED }); + item.action(); + }, + })); return ( <> {/* Modals */} @@ -73,7 +80,7 @@ export const ArchivedIssueQuickActions: React.FC = observer(( onSubmit={handleDelete} /> - + = observer(( e.preventDefault(); e.stopPropagation(); item.action(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.ARCHIVED }); }} className={cn( "flex items-center gap-2", diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx similarity index 89% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx index 75bb8633a..055335c8c 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx @@ -5,14 +5,20 @@ import omit from "lodash/omit"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { ARCHIVABLE_STATE_GROUPS, EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { TIssue } from "@plane/types"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { + ARCHIVABLE_STATE_GROUPS, + EUserPermissions, + EUserPermissionsLevel, + WORK_ITEM_TRACKER_ELEMENTS, +} from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; // hooks -import { useEventTracker, useIssues, useProject, useProjectState, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssues, useProject, useProjectState, useUserPermissions } from "@/hooks/store"; // plane-web components import { DuplicateWorkItemModal } from "@/plane-web/components/issues/issue-layouts/quick-action-dropdowns"; // types @@ -41,8 +47,6 @@ export const CycleIssueQuickActions: React.FC = observer((pro const [duplicateWorkItemModal, setDuplicateWorkItemModal] = useState(false); // router const { workspaceSlug, cycleId } = useParams(); - // store hooks - const { setTrackElement } = useEventTracker(); const { issuesFilter } = useIssues(EIssuesStoreType.CYCLE); const { allowPermissions } = useUserPermissions(); const { getStateById } = useProjectState(); @@ -78,7 +82,6 @@ export const CycleIssueQuickActions: React.FC = observer((pro isArchivingAllowed, isDeletingAllowed, isInArchivableGroup, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -94,6 +97,14 @@ export const CycleIssueQuickActions: React.FC = observer((pro const MENU_ITEMS = useCycleIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.CYCLE }); + item.action(); + }, + })); + return ( <> {/* Modals */} @@ -132,7 +143,7 @@ export const CycleIssueQuickActions: React.FC = observer((pro /> )} - + = observer((pro onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.CYCLE }); nestedItem.action(); }} className={cn( @@ -218,6 +230,7 @@ export const CycleIssueQuickActions: React.FC = observer((pro onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.CYCLE }); item.action(); }} className={cn( diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx similarity index 85% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx index e3d89f8a2..386c5f1e9 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx @@ -5,14 +5,15 @@ import omit from "lodash/omit"; import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; // plane imports -import { EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { TIssue } from "@plane/types"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; // hooks -import { useEventTracker, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useUserPermissions } from "@/hooks/store"; // local imports import { IQuickActionProps } from "../list/list-view-types"; import { useDraftIssueMenuItems, MenuItemFactoryProps } from "./helper"; @@ -37,7 +38,6 @@ export const DraftIssueQuickActions: React.FC = observer((pro const [deleteIssueModal, setDeleteIssueModal] = useState(false); // store hooks const { allowPermissions } = useUserPermissions(); - const { setTrackElement } = useEventTracker(); // derived values const activeLayout = "Draft Issues"; // auth @@ -70,7 +70,6 @@ export const DraftIssueQuickActions: React.FC = observer((pro isEditingAllowed, isDeletingAllowed, isDraftIssue, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -81,6 +80,14 @@ export const DraftIssueQuickActions: React.FC = observer((pro const MENU_ITEMS = useDraftIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.DRAFT }); + item.action(); + }, + })); + return ( <> {/* Modals */} @@ -104,7 +111,7 @@ export const DraftIssueQuickActions: React.FC = observer((pro isDraft={isDraftIssue} /> - + = observer((pro onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.DRAFT }); item.action(); }} className={cn( diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx similarity index 94% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx index 3ebcc7e70..9d6862aaa 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/helper.tsx @@ -1,9 +1,8 @@ import { useMemo } from "react"; import { Copy, ExternalLink, Link, Pencil, Trash2, XCircle, ArchiveRestoreIcon } from "lucide-react"; // plane imports -import { EIssuesStoreType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue } from "@plane/types"; +import { EIssuesStoreType, TIssue } from "@plane/types"; import { ArchiveIcon, TContextMenuItem, TOAST_TYPE, setToast } from "@plane/ui"; import { copyUrlToClipboard, generateWorkItemLink } from "@plane/utils"; // types @@ -57,7 +56,6 @@ export interface MenuItemFactoryProps { issueTypeDetail?: { is_active?: boolean }; isDraftIssue?: boolean; // Action handlers - setTrackElement: (element: string) => void; setIssueToEdit: (issue: TIssue | undefined) => void; setCreateUpdateIssueModal: (open: boolean) => void; setDeleteIssueModal: (open: boolean) => void; @@ -145,7 +143,6 @@ export const useMenuItemFactory = (props: MenuItemFactoryProps) => { isRestoringAllowed = false, isInArchivableGroup = false, issueTypeDetail, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -161,20 +158,18 @@ export const useMenuItemFactory = (props: MenuItemFactoryProps) => { action: customEditAction || (() => { - setTrackElement(activeLayout); setIssueToEdit(issue); setCreateUpdateIssueModal(true); }), shouldRender: isEditingAllowed, }); - const createCopyMenuItem = (): TContextMenuItem => { + const createCopyMenuItem = (workspaceSlug?: string): TContextMenuItem => { const baseItem = { key: "make-a-copy", title: t("common.actions.make_a_copy"), icon: Copy, action: () => { - setTrackElement(activeLayout); setCreateUpdateIssueModal(true); }, shouldRender: isEditingAllowed && (issueTypeDetail?.is_active ?? true), @@ -183,9 +178,9 @@ export const useMenuItemFactory = (props: MenuItemFactoryProps) => { return createCopyMenuWithDuplication({ baseItem, activeLayout, - setTrackElement, setCreateUpdateIssueModal, setDuplicateWorkItemModal, + workspaceSlug, }); }; @@ -244,7 +239,6 @@ export const useMenuItemFactory = (props: MenuItemFactoryProps) => { title: t("common.actions.delete"), icon: Trash2, action: () => { - setTrackElement(activeLayout); setDeleteIssueModal(true); }, shouldRender: isDeletingAllowed, @@ -281,6 +275,21 @@ export const useProjectIssueMenuItems = (props: MenuItemFactoryProps): TContextM ); }; +export const useWorkItemDetailMenuItems = (props: MenuItemFactoryProps): TContextMenuItem[] => { + const factory = useMenuItemFactory(props); + + return useMemo( + () => [ + factory.createCopyMenuItem(props.workspaceSlug), + factory.createOpenInNewTabMenuItem(), + factory.createArchiveMenuItem(), + factory.createRestoreMenuItem(), + factory.createDeleteMenuItem(), + ], + [factory] + ); +}; + export const useAllIssueMenuItems = (props: MenuItemFactoryProps): TContextMenuItem[] => { const factory = useMenuItemFactory(props); @@ -305,7 +314,6 @@ export const useCycleIssueMenuItems = (props: MenuItemFactoryProps): TContextMen ...props.issue, cycle_id: props.cycleId ?? null, }); - props.setTrackElement(props.activeLayout || ""); props.setCreateUpdateIssueModal(true); }; @@ -331,7 +339,6 @@ export const useModuleIssueMenuItems = (props: MenuItemFactoryProps): TContextMe ...props.issue, module_ids: props.moduleId ? [props.moduleId] : [], }); - props.setTrackElement(props.activeLayout || ""); props.setCreateUpdateIssueModal(true); }; diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts similarity index 89% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts index 075f8ae0a..0862c68a9 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/index.ts @@ -6,3 +6,4 @@ export * from "./module-issue"; export * from "./project-issue"; export * from "./helper"; export * from "../../workspace-draft/quick-action"; +export * from "./issue-detail"; diff --git a/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx new file mode 100644 index 000000000..5a33febc6 --- /dev/null +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/issue-detail.tsx @@ -0,0 +1,352 @@ +"use client"; + +import { useState } from "react"; +import omit from "lodash/omit"; +import { observer } from "mobx-react"; +import { useParams, usePathname } from "next/navigation"; +// plane imports +import { + ARCHIVABLE_STATE_GROUPS, + EUserPermissions, + EUserPermissionsLevel, + WORK_ITEM_TRACKER_ELEMENTS, +} from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; +import { cn } from "@plane/utils"; +// components +import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; +// hooks +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssues, useProject, useProjectState, useUserPermissions } from "@/hooks/store"; +// plane-web components +import { DuplicateWorkItemModal } from "@/plane-web/components/issues/issue-layouts/quick-action-dropdowns"; +import { IQuickActionProps } from "../list/list-view-types"; +// helper +import { MenuItemFactoryProps, useWorkItemDetailMenuItems } from "./helper"; + +type TWorkItemDetailQuickActionProps = IQuickActionProps & { + toggleEditIssueModal?: (value: boolean) => void; + toggleDeleteIssueModal?: (value: boolean) => void; + toggleDuplicateIssueModal?: (value: boolean) => void; + toggleArchiveIssueModal?: (value: boolean) => void; + isPeekMode?: boolean; +}; + +export const WorkItemDetailQuickActions: React.FC = observer((props) => { + const { + issue, + handleDelete, + handleUpdate, + handleArchive, + handleRestore, + customActionButton, + portalElement, + readOnly = false, + placements = "bottom-end", + parentRef, + toggleEditIssueModal, + toggleDeleteIssueModal, + toggleDuplicateIssueModal, + toggleArchiveIssueModal, + isPeekMode = false, + } = props; + // router + const { workspaceSlug } = useParams(); + const pathname = usePathname(); + // states + const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); + const [issueToEdit, setIssueToEdit] = useState(undefined); + const [deleteIssueModal, setDeleteIssueModal] = useState(false); + const [archiveIssueModal, setArchiveIssueModal] = useState(false); + const [duplicateWorkItemModal, setDuplicateWorkItemModal] = useState(false); + // store hooks + const { allowPermissions } = useUserPermissions(); + const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT); + const { getStateById } = useProjectState(); + const { getProjectIdentifierById } = useProject(); + // derived values + const activeLayout = `${issuesFilter.issueFilters?.displayFilters?.layout} layout`; + const stateDetails = getStateById(issue.state_id); + const projectIdentifier = getProjectIdentifierById(issue?.project_id); + // auth + const isEditingAllowed = + allowPermissions( + [EUserPermissions.ADMIN, EUserPermissions.MEMBER], + EUserPermissionsLevel.PROJECT, + workspaceSlug?.toString(), + issue.project_id ?? undefined + ) && !readOnly; + + const isArchivingAllowed = !issue.archived_at && isEditingAllowed; + const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group); + const isRestoringAllowed = !!issue.archived_at && isEditingAllowed; + + const isDeletingAllowed = isEditingAllowed; + + const isDraftIssue = pathname?.includes("draft-issues") || false; + + const duplicateIssuePayload = omit( + { + ...issue, + name: `${issue.name} (copy)`, + is_draft: isDraftIssue ? false : issue.is_draft, + sourceIssueId: issue.id, + }, + ["id"] + ); + + const customEditAction = () => { + setCreateUpdateIssueModal(true); + if (toggleEditIssueModal) toggleEditIssueModal(true); + }; + + const customDeleteAction = async () => { + setDeleteIssueModal(true); + if (toggleDeleteIssueModal) toggleDeleteIssueModal(true); + }; + + const customDuplicateAction = async () => { + setDuplicateWorkItemModal(true); + if (toggleDuplicateIssueModal) { + toggleDuplicateIssueModal(true); + } + }; + + const customArchiveAction = async () => { + setArchiveIssueModal(true); + if (toggleArchiveIssueModal) toggleArchiveIssueModal(true); + }; + + const customRestoreAction = async () => { + if (handleRestore) await handleRestore(); + }; + + // Menu items and modals using helper + const menuItemProps: MenuItemFactoryProps = { + issue, + workspaceSlug: workspaceSlug?.toString(), + projectIdentifier, + activeLayout, + isEditingAllowed, + isArchivingAllowed, + isRestoringAllowed, + isDeletingAllowed, + isInArchivableGroup, + isDraftIssue, + setIssueToEdit, + setCreateUpdateIssueModal: customEditAction, + setDeleteIssueModal: customDeleteAction, + setArchiveIssueModal: customArchiveAction, + setDuplicateWorkItemModal: customDuplicateAction, + handleDelete: customDeleteAction, + handleUpdate, + handleArchive: customArchiveAction, + handleRestore: customRestoreAction, + storeType: EIssuesStoreType.PROJECT, + }; + + // const MENU_ITEMS = useWorkItemDetailMenuItems(menuItemProps); + const baseMenuItems = useWorkItemDetailMenuItems(menuItemProps); + + const MENU_ITEMS = baseMenuItems + .map((item) => { + // Customize edit action for work item + if (item.key === "edit") { + return { + ...item, + shouldRender: isEditingAllowed && !isPeekMode, + }; + } + // Customize delete action for work item + if (item.key === "delete") { + return { + ...item, + }; + } + // Hide copy link in peek mode + if (item.key === "copy-link") { + return { + ...item, + shouldRender: !isPeekMode, + }; + } + return item; + }) + .filter((item) => item.shouldRender !== false); + + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); + item.action(); + }, + })); + + return ( + <> + {/* Modals */} + { + setArchiveIssueModal(false); + if (toggleArchiveIssueModal) toggleArchiveIssueModal(false); + }} + onSubmit={handleArchive} + /> + { + setDeleteIssueModal(false); + if (toggleDeleteIssueModal) toggleDeleteIssueModal(false); + }} + onSubmit={handleDelete} + /> + { + setCreateUpdateIssueModal(false); + setIssueToEdit(undefined); + if (toggleEditIssueModal) toggleEditIssueModal(false); + }} + data={issueToEdit ?? duplicateIssuePayload} + onSubmit={async (data) => { + if (issueToEdit && handleUpdate) await handleUpdate(data); + }} + storeType={EIssuesStoreType.PROJECT} + isDraft={isDraftIssue} + fetchIssueDetails={false} + /> + {issue.project_id && workspaceSlug && ( + { + setDuplicateWorkItemModal(false); + if (toggleDuplicateIssueModal) toggleDuplicateIssueModal(false); + }} + workspaceSlug={workspaceSlug.toString()} + projectId={issue.project_id} + /> + )} + + + + {MENU_ITEMS.map((item) => { + if (item.shouldRender === false) return null; + + // Render submenu if nestedMenuItems exist + if (item.nestedMenuItems && item.nestedMenuItems.length > 0) { + return ( + + {item.icon && } +
{item.title}
+ {item.description && ( +

+ {item.description} +

+ )} +
+ } + disabled={item.disabled} + className={cn( + "flex items-center gap-2", + { + "text-custom-text-400": item.disabled, + }, + item.className + )} + > + {item.nestedMenuItems.map((nestedItem) => ( + { + e.preventDefault(); + e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); + nestedItem.action(); + }} + className={cn( + "flex items-center gap-2", + { + "text-custom-text-400": nestedItem.disabled, + }, + nestedItem.className + )} + disabled={nestedItem.disabled} + > + {nestedItem.icon && } +
+
{nestedItem.title}
+ {nestedItem.description && ( +

+ {nestedItem.description} +

+ )} +
+
+ ))} + + ); + } + + // Render regular menu item + return ( + { + e.preventDefault(); + e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); + item.action(); + }} + className={cn( + "flex items-center gap-2", + { + "text-custom-text-400": item.disabled, + }, + item.className + )} + disabled={item.disabled} + > + {item.icon && } +
+
{item.title}
+ {item.description && ( +

+ {item.description} +

+ )} +
+
+ ); + })} + + + ); +}); diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx similarity index 89% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx index e23ff7501..5d512ce47 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx @@ -5,14 +5,20 @@ import omit from "lodash/omit"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { ARCHIVABLE_STATE_GROUPS, EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { TIssue } from "@plane/types"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { + ARCHIVABLE_STATE_GROUPS, + EUserPermissions, + EUserPermissionsLevel, + WORK_ITEM_TRACKER_ELEMENTS, +} from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; // hooks -import { useIssues, useEventTracker, useProjectState, useUserPermissions, useProject } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssues, useProjectState, useUserPermissions, useProject } from "@/hooks/store"; // plane-web components import { DuplicateWorkItemModal } from "@/plane-web/components/issues/issue-layouts/quick-action-dropdowns"; import { IQuickActionProps } from "../list/list-view-types"; @@ -41,7 +47,6 @@ export const ModuleIssueQuickActions: React.FC = observer((pr // router const { workspaceSlug, moduleId } = useParams(); // store hooks - const { setTrackElement } = useEventTracker(); const { issuesFilter } = useIssues(EIssuesStoreType.MODULE); const { allowPermissions } = useUserPermissions(); const { getStateById } = useProjectState(); @@ -77,7 +82,6 @@ export const ModuleIssueQuickActions: React.FC = observer((pr isArchivingAllowed, isDeletingAllowed, isInArchivableGroup, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -93,6 +97,13 @@ export const ModuleIssueQuickActions: React.FC = observer((pr const MENU_ITEMS = useModuleIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.MODULE }); + item.action(); + }, + })); return ( <> {/* Modals */} @@ -131,7 +142,7 @@ export const ModuleIssueQuickActions: React.FC = observer((pr /> )} - + = observer((pr onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.MODULE }); nestedItem.action(); }} className={cn( @@ -217,6 +229,7 @@ export const ModuleIssueQuickActions: React.FC = observer((pr onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.MODULE }); item.action(); }} className={cn( diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx similarity index 89% rename from web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx rename to apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx index 994648544..266ebbe74 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx @@ -5,14 +5,20 @@ import omit from "lodash/omit"; import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; // plane imports -import { ARCHIVABLE_STATE_GROUPS, EIssuesStoreType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { TIssue } from "@plane/types"; -import { ContextMenu, CustomMenu } from "@plane/ui"; +import { + ARCHIVABLE_STATE_GROUPS, + EUserPermissions, + EUserPermissionsLevel, + WORK_ITEM_TRACKER_ELEMENTS, +} from "@plane/constants"; +import { EIssuesStoreType, TIssue } from "@plane/types"; +import { ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui"; import { cn } from "@plane/utils"; // components import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues"; // hooks -import { useEventTracker, useIssues, useProject, useProjectState, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useIssues, useProject, useProjectState, useUserPermissions } from "@/hooks/store"; // plane-web components import { DuplicateWorkItemModal } from "@/plane-web/components/issues/issue-layouts/quick-action-dropdowns"; import { IQuickActionProps } from "../list/list-view-types"; @@ -42,7 +48,6 @@ export const ProjectIssueQuickActions: React.FC = observer((p const [duplicateWorkItemModal, setDuplicateWorkItemModal] = useState(false); // store hooks const { allowPermissions } = useUserPermissions(); - const { setTrackElement } = useEventTracker(); const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT); const { getStateById } = useProjectState(); const { getProjectIdentifierById } = useProject(); @@ -85,7 +90,6 @@ export const ProjectIssueQuickActions: React.FC = observer((p isDeletingAllowed, isInArchivableGroup, isDraftIssue, - setTrackElement, setIssueToEdit, setCreateUpdateIssueModal, setDeleteIssueModal, @@ -99,6 +103,14 @@ export const ProjectIssueQuickActions: React.FC = observer((p const MENU_ITEMS = useProjectIssueMenuItems(menuItemProps); + const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({ + ...item, + onClick: () => { + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); + item.action(); + }, + })); + return ( <> {/* Modals */} @@ -137,7 +149,7 @@ export const ProjectIssueQuickActions: React.FC = observer((p /> )} - + = observer((p onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); nestedItem.action(); }} className={cn( @@ -222,6 +235,7 @@ export const ProjectIssueQuickActions: React.FC = observer((p onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.QUICK_ACTIONS.PROJECT_VIEW }); item.action(); }} className={cn( diff --git a/web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/button/gantt.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/button/index.ts b/apps/web/core/components/issues/issue-layouts/quick-add/button/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/button/index.ts rename to apps/web/core/components/issues/issue-layouts/quick-add/button/index.ts diff --git a/web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/button/kanban.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/button/list.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/button/list.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/button/list.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/button/list.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/button/spreadsheet.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/form/calendar.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/form/gantt.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/form/index.ts b/apps/web/core/components/issues/issue-layouts/quick-add/form/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/index.ts rename to apps/web/core/components/issues/issue-layouts/quick-add/form/index.ts diff --git a/web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/form/kanban.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/form/list.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/form/list.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/list.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/form/list.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/form/spreadsheet.tsx diff --git a/web/core/components/issues/issue-layouts/quick-add/index.ts b/apps/web/core/components/issues/issue-layouts/quick-add/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/quick-add/index.ts rename to apps/web/core/components/issues/issue-layouts/quick-add/index.ts diff --git a/web/core/components/issues/issue-layouts/quick-add/root.tsx b/apps/web/core/components/issues/issue-layouts/quick-add/root.tsx similarity index 88% rename from web/core/components/issues/issue-layouts/quick-add/root.tsx rename to apps/web/core/components/issues/issue-layouts/quick-add/root.tsx index b6cd83e66..701083663 100644 --- a/web/core/components/issues/issue-layouts/quick-add/root.tsx +++ b/apps/web/core/components/issues/issue-layouts/quick-add/root.tsx @@ -2,14 +2,14 @@ import { FC, useEffect, useState } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; import { useForm, UseFormRegister } from "react-hook-form"; import { PlusIcon } from "lucide-react"; // plane constants -import { EIssueLayoutTypes, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; -import { IProject, TIssue } from "@plane/types"; +import { IProject, TIssue, EIssueLayoutTypes } from "@plane/types"; // ui import { setPromiseToast } from "@plane/ui"; import { cn, createIssuePayload } from "@plane/utils"; @@ -18,7 +18,7 @@ import { CreateIssueToastActionItems } from "@/components/issues"; // constants // helpers // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; // plane web components import { QuickAddIssueFormRoot } from "@/plane-web/components/issues"; @@ -69,11 +69,8 @@ export const QuickAddIssueRoot: FC = observer((props) => { const { t } = useTranslation(); // router const { workspaceSlug, projectId } = useParams(); - const pathname = usePathname(); // states const [isOpen, setIsOpen] = useState(isQuickAddOpen ?? false); - // store hooks - const { captureIssueEvent } = useEventTracker(); // form info const { reset, @@ -136,17 +133,16 @@ export const QuickAddIssueRoot: FC = observer((props) => { await quickAddPromise .then((res) => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.create, - payload: { ...res, state: "SUCCESS", element: ` ${layout} quick add` }, - path: pathname, + payload: { id: res?.id }, }); }) - .catch(() => { - captureIssueEvent({ + .catch((error) => { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.create, - payload: { ...payload, state: "FAILED", element: `${layout} quick ad` }, - path: pathname, + payload: { id: payload.id }, + error: error as Error, }); }); } diff --git a/web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx index 2bebdb96a..d9a9fbf8b 100644 --- a/web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/all-issue-layout-root.tsx @@ -2,12 +2,11 @@ import React, { useCallback } from "react"; import { isEmpty } from "lodash"; import { observer } from "mobx-react"; import { useParams, useSearchParams } from "next/navigation"; -// plane constants import useSWR from "swr"; -import { EIssueFilterType, EIssueLayoutTypes, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; -// hooks +// plane imports +import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components -// hooks import { EmptyState } from "@/components/common"; import { WorkspaceActiveLayout } from "@/components/views/helper"; import { useGlobalView, useIssues } from "@/hooks/store"; diff --git a/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx similarity index 96% rename from web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx index 86f299ef2..b96afb599 100644 --- a/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx @@ -2,9 +2,9 @@ import React, { Fragment } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; +import { EIssuesStoreType } from "@plane/types"; // mobx store // components -import { EIssuesStoreType } from "@plane/constants"; import { LogoSpinner } from "@/components/common"; import { ArchivedIssueListLayout, ArchivedIssueAppliedFiltersRoot, IssuePeekOverview } from "@/components/issues"; // ui diff --git a/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx similarity index 98% rename from web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx index a9c9fe0e8..4ffba95c9 100644 --- a/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { LogoSpinner } from "@/components/common"; import { TransferIssues, TransferIssuesModal } from "@/components/cycles"; diff --git a/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx index 13597c578..9de55b2ec 100644 --- a/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { LogoSpinner } from "@/components/common"; import { IssuePeekOverview } from "@/components/issues/peek-overview"; diff --git a/web/core/components/issues/issue-layouts/roots/index.ts b/apps/web/core/components/issues/issue-layouts/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/roots/module-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx index f64f28cc7..14e20ae53 100644 --- a/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { Row, ERowVariant } from "@plane/ui"; import { LogoSpinner } from "@/components/common"; diff --git a/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/roots/project-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx index 4007468dc..2d1be0cc2 100644 --- a/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { Spinner } from "@plane/ui"; import { LogoSpinner } from "@/components/common"; diff --git a/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx b/apps/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx rename to apps/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx index fd0a54a31..b6bf4755b 100644 --- a/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType } from "@plane/constants"; +import { EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { LogoSpinner } from "@/components/common"; import { diff --git a/web/core/components/issues/issue-layouts/save-filter-view.tsx b/apps/web/core/components/issues/issue-layouts/save-filter-view.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/save-filter-view.tsx rename to apps/web/core/components/issues/issue-layouts/save-filter-view.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx index f8d2f32c3..c3ddad73e 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx @@ -2,8 +2,8 @@ import { FC, useCallback, useEffect } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { ALL_ISSUES, EIssueLayoutTypes, EIssuesStoreType, EIssueFilterType , EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { IIssueDisplayFilterOptions } from "@plane/types"; +import { ALL_ISSUES, EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EIssuesStoreType, IIssueDisplayFilterOptions, EIssueLayoutTypes } from "@plane/types"; // hooks import { useIssues, useUserPermissions } from "@/hooks/store"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx similarity index 78% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx index f9f17d4f5..fc923331b 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/cycle-column.tsx @@ -1,12 +1,13 @@ import React, { useCallback } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // types +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { TIssue } from "@plane/types"; // components import { CycleDropdown } from "@/components/dropdowns"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; import { useIssuesStore } from "@/hooks/use-issue-layout-store"; type Props = { @@ -19,9 +20,7 @@ export const SpreadsheetCycleColumn: React.FC = observer((props) => { const { issue, disabled, onClose } = props; // router const { workspaceSlug } = useParams(); - const pathname = usePathname(); // hooks - const { captureIssueEvent } = useEventTracker(); const { issues: { addCycleToIssue, removeCycleFromIssue }, } = useIssuesStore(); @@ -31,18 +30,14 @@ export const SpreadsheetCycleColumn: React.FC = observer((props) => { if (!workspaceSlug || !issue || !issue.project_id || issue.cycle_id === cycleId) return; if (cycleId) await addCycleToIssue(workspaceSlug.toString(), issue.project_id, cycleId, issue.id); else await removeCycleFromIssue(workspaceSlug.toString(), issue.project_id, issue.id); - captureIssueEvent({ - eventName: "Work item updated", + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.update, payload: { - ...issue, - cycle_id: cycleId, - element: "Spreadsheet layout", + id: issue.id, }, - updates: { changed_property: "cycle", change_details: { cycle_id: cycleId } }, - path: pathname, }); }, - [workspaceSlug, issue, addCycleToIssue, removeCycleFromIssue, captureIssueEvent, pathname] + [workspaceSlug, issue, addCycleToIssue, removeCycleFromIssue] ); return ( diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/index.ts diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx similarity index 79% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx index b95610cdd..b30f7716f 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/module-column.tsx @@ -1,14 +1,15 @@ import React, { useCallback } from "react"; import xor from "lodash/xor"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // types +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { TIssue } from "@plane/types"; // components import { ModuleDropdown } from "@/components/dropdowns"; // constants // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; import { useIssuesStore } from "@/hooks/use-issue-layout-store"; type Props = { @@ -21,9 +22,7 @@ export const SpreadsheetModuleColumn: React.FC = observer((props) => { const { issue, disabled, onClose } = props; // router const { workspaceSlug } = useParams(); - const pathname = usePathname(); // hooks - const { captureIssueEvent } = useEventTracker(); const { issues: { changeModulesInIssue }, } = useIssuesStore(); @@ -41,18 +40,14 @@ export const SpreadsheetModuleColumn: React.FC = observer((props) => { } changeModulesInIssue(workspaceSlug.toString(), issue.project_id, issue.id, modulesToAdd, modulesToRemove); - captureIssueEvent({ - eventName: "Work item updated", + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.update, payload: { - ...issue, - module_ids: moduleIds, - element: "Spreadsheet layout", + id: issue.id, }, - updates: { changed_property: "module_ids", change_details: { module_ids: moduleIds } }, - path: pathname, }); }, - [workspaceSlug, issue, changeModulesInIssue, captureIssueEvent, pathname] + [workspaceSlug, issue, changeModulesInIssue] ); return ( diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/index.ts b/apps/web/core/components/issues/issue-layouts/spreadsheet/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/index.ts rename to apps/web/core/components/issues/issue-layouts/spreadsheet/index.ts diff --git a/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx similarity index 78% rename from web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx index cf6b4febb..34b5bfdfc 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx @@ -1,15 +1,14 @@ import { useRef } from "react"; import { observer } from "mobx-react"; -import { usePathname } from "next/navigation"; // types +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { IIssueDisplayProperties, TIssue } from "@plane/types"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; // components import { SPREADSHEET_COLUMNS } from "@/plane-web/components/issues/issue-layouts/utils"; import { shouldRenderColumn } from "@/plane-web/helpers/issue-filter.helper"; import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC"; -// utils type Props = { displayProperties: IIssueDisplayProperties; @@ -23,9 +22,7 @@ type Props = { export const IssueColumn = observer((props: Props) => { const { displayProperties, issueDetail, disableUserActions, property, updateIssue } = props; // router - const pathname = usePathname(); const tableCellRef = useRef(null); - const { captureIssueEvent } = useEventTracker(); const shouldRenderProperty = shouldRenderColumn(property); @@ -46,18 +43,14 @@ export const IssueColumn = observer((props: Props) => { > , updates: any) => + onChange={(issue: TIssue, data: Partial) => updateIssue && updateIssue(issue.project_id, issue.id, data).then(() => { - captureIssueEvent({ - eventName: "Issue updated", + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.update, payload: { - ...issue, - ...data, - element: "Spreadsheet layout", + id: issue.id, }, - updates: updates, - path: pathname, }); }) } diff --git a/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx similarity index 99% rename from web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx index a645bffe2..8594e72fa 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/issue-row.tsx @@ -4,11 +4,11 @@ import { Dispatch, MouseEvent, MutableRefObject, SetStateAction, useRef, useStat import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronRight, MoreHorizontal } from "lucide-react"; -import { EIssueServiceType, SPREADSHEET_SELECT_GROUP } from "@plane/constants"; +import { SPREADSHEET_SELECT_GROUP } from "@plane/constants"; // plane helpers import { useOutsideClickDetector } from "@plane/hooks"; // types -import { IIssueDisplayProperties, TIssue } from "@plane/types"; +import { EIssueServiceType, IIssueDisplayProperties, TIssue } from "@plane/types"; // ui import { ControlLink, Row, Tooltip } from "@plane/ui"; import { cn, generateWorkItemLink } from "@plane/utils"; diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/cycle-root.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/index.ts b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/index.ts similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/index.ts rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/index.ts diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/module-root.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/project-root.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/project-view-root.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx similarity index 95% rename from web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx index caba1176d..b78f95881 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/roots/workspace-root.tsx @@ -1,16 +1,8 @@ import React, { useCallback } from "react"; import { observer } from "mobx-react"; // plane constants -import { - ALL_ISSUES, - EIssueLayoutTypes, - EIssueFilterType, - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, -} from "@plane/constants"; -import { IIssueDisplayFilterOptions } from "@plane/types"; -// hooks +import { ALL_ISSUES, EIssueFilterType, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { IIssueDisplayFilterOptions, EIssuesStoreType, EIssueLayoutTypes } from "@plane/types"; // components import { SpreadsheetView } from "@/components/issues/issue-layouts"; import { AllIssueQuickActions } from "@/components/issues/issue-layouts/quick-action-dropdowns"; diff --git a/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header-column.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header-column.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header-column.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header-column.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx similarity index 100% rename from web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-table.tsx diff --git a/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx b/apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx similarity index 97% rename from web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx rename to apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx index 4cdb2aafe..8f348c717 100644 --- a/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx +++ b/apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx @@ -1,9 +1,9 @@ import React, { useRef } from "react"; import { observer } from "mobx-react"; // plane constants -import { EIssueLayoutTypes, SPREADSHEET_SELECT_GROUP, SPREADSHEET_PROPERTY_LIST } from "@plane/constants"; +import { SPREADSHEET_SELECT_GROUP, SPREADSHEET_PROPERTY_LIST } from "@plane/constants"; // types -import { TIssue, IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types"; +import { TIssue, IIssueDisplayFilterOptions, IIssueDisplayProperties, EIssueLayoutTypes } from "@plane/types"; // components import { LogoSpinner } from "@/components/common"; import { MultipleSelectGroup } from "@/components/core"; diff --git a/web/core/components/issues/issue-layouts/utils.tsx b/apps/web/core/components/issues/issue-layouts/utils.tsx similarity index 99% rename from web/core/components/issues/issue-layouts/utils.tsx rename to apps/web/core/components/issues/issue-layouts/utils.tsx index 510fbf5a6..83943f84d 100644 --- a/web/core/components/issues/issue-layouts/utils.tsx +++ b/apps/web/core/components/issues/issue-layouts/utils.tsx @@ -11,8 +11,9 @@ import uniq from "lodash/uniq"; import scrollIntoView from "smooth-scroll-into-view-if-needed"; import { ContrastIcon } from "lucide-react"; // plane types -import { EIconSize, EIssuesStoreType, ISSUE_PRIORITIES, STATE_GROUPS } from "@plane/constants"; +import { EIconSize, ISSUE_PRIORITIES, STATE_GROUPS } from "@plane/constants"; import { + EIssuesStoreType, GroupByColumnTypes, IGroupByColumn, TCycleGroups, diff --git a/web/core/components/issues/issue-modal/base.tsx b/apps/web/core/components/issues/issue-modal/base.tsx similarity index 93% rename from web/core/components/issues/issue-modal/base.tsx rename to apps/web/core/components/issues/issue-modal/base.tsx index 494eb80e7..b4a01c56d 100644 --- a/web/core/components/issues/issue-modal/base.tsx +++ b/apps/web/core/components/issues/issue-modal/base.tsx @@ -2,19 +2,18 @@ import React, { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; -import { EIssuesStoreType, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +import { useParams } from "next/navigation"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; +// Plane imports import { useTranslation } from "@plane/i18n"; -// types -import type { TBaseIssue, TIssue } from "@plane/types"; -// ui +import { EIssuesStoreType, TBaseIssue, TIssue } from "@plane/types"; import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; +// components import { CreateIssueToastActionItems, IssuesModalProps } from "@/components/issues"; -// constants // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useIssueModal } from "@/hooks/context/use-issue-modal"; import { useCycle } from "@/hooks/store/use-cycle"; -import { useEventTracker } from "@/hooks/store/use-event-tracker"; import { useIssueDetail } from "@/hooks/store/use-issue-detail"; import { useIssues } from "@/hooks/store/use-issues"; import { useModule } from "@/hooks/store/use-module"; @@ -62,7 +61,6 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( const [isDuplicateModalOpen, setIsDuplicateModalOpen] = useState(false); // store hooks const { t } = useTranslation(); - const { captureIssueEvent } = useEventTracker(); const { workspaceSlug, projectId: routerProjectId, cycleId, moduleId, workItem } = useParams(); const { fetchCycleDetails } = useCycle(); const { fetchModuleDetails } = useModule(); @@ -70,10 +68,8 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( const { issues: projectIssues } = useIssues(EIssuesStoreType.PROJECT); const { issues: draftIssues } = useIssues(EIssuesStoreType.WORKSPACE_DRAFT); const { fetchIssue } = useIssueDetail(); - const { allowedProjectIds, handleCreateUpdatePropertyValues } = useIssueModal(); + const { allowedProjectIds, handleCreateUpdatePropertyValues, handleCreateSubWorkItem } = useIssueModal(); const { getProjectByIdentifier } = useProject(); - // pathname - const pathname = usePathname(); // current store details const { createIssue, updateIssue } = useIssuesActions(storeType); // derived values @@ -226,6 +222,13 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( workspaceSlug: workspaceSlug?.toString(), isDraft: is_draft_issue, }); + + // create sub work item + await handleCreateSubWorkItem({ + workspaceSlug: workspaceSlug?.toString(), + projectId: response.project_id, + parentId: response.id, + }); } setToast({ @@ -240,10 +243,9 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( /> ), }); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.create, - payload: { ...response, state: "SUCCESS" }, - path: pathname, + payload: { id: response.id }, }); if (!createMore) handleClose(); if (createMore && issueTitleRef) issueTitleRef?.current?.focus(); @@ -256,10 +258,10 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( title: t("error"), message: error?.error ?? t(is_draft_issue ? "draft_creation_failed" : "issue_creation_failed"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.create, - payload: { ...payload, state: "FAILED" }, - path: pathname, + payload: { id: payload.id }, + error: error as Error, }); throw error; } @@ -302,10 +304,9 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( title: t("success"), message: t("issue_updated_successfully"), }); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...payload, issueId: data.id, state: "SUCCESS" }, - path: pathname, + payload: { id: data.id }, }); handleClose(); } catch (error: any) { @@ -315,10 +316,10 @@ export const CreateUpdateIssueModalBase: React.FC = observer(( title: t("error"), message: error?.error ?? t("issue_could_not_be_updated"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...payload, state: "FAILED" }, - path: pathname, + payload: { id: data.id }, + error: error as Error, }); } }; diff --git a/web/core/components/issues/issue-modal/components/default-properties.tsx b/apps/web/core/components/issues/issue-modal/components/default-properties.tsx similarity index 100% rename from web/core/components/issues/issue-modal/components/default-properties.tsx rename to apps/web/core/components/issues/issue-modal/components/default-properties.tsx diff --git a/web/core/components/issues/issue-modal/components/description-editor.tsx b/apps/web/core/components/issues/issue-modal/components/description-editor.tsx similarity index 98% rename from web/core/components/issues/issue-modal/components/description-editor.tsx rename to apps/web/core/components/issues/issue-modal/components/description-editor.tsx index b1bbce5b9..8e0bc68f5 100644 --- a/web/core/components/issues/issue-modal/components/description-editor.tsx +++ b/apps/web/core/components/issues/issue-modal/components/description-editor.tsx @@ -6,14 +6,9 @@ import { Control, Controller } from "react-hook-form"; import { Sparkle } from "lucide-react"; // plane imports import { ETabIndices } from "@plane/constants"; -// editor -import { EditorRefApi } from "@plane/editor"; -// i18n +import type { EditorRefApi } from "@plane/editor"; import { useTranslation } from "@plane/i18n"; -// types -import { TIssue } from "@plane/types"; -import { EFileAssetType } from "@plane/types/src/enums"; -// ui +import { EFileAssetType, TIssue } from "@plane/types"; import { Loader, setToast, TOAST_TYPE } from "@plane/ui"; import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils"; // components @@ -178,6 +173,7 @@ export const IssueDescriptionEditor: React.FC = ob control={control} render={({ field: { value, onChange } }) => ( = observer(( }} multiple={false} buttonVariant="border-with-text" - renderCondition={(project) => allowedProjectIds.includes(project.id)} + renderCondition={(projectId) => allowedProjectIds.includes(projectId)} tabIndex={getIndex("project_id")} disabled={disabled} /> diff --git a/web/core/components/issues/issue-modal/components/title-input.tsx b/apps/web/core/components/issues/issue-modal/components/title-input.tsx similarity index 100% rename from web/core/components/issues/issue-modal/components/title-input.tsx rename to apps/web/core/components/issues/issue-modal/components/title-input.tsx diff --git a/web/core/components/issues/issue-modal/context/index.ts b/apps/web/core/components/issues/issue-modal/context/index.ts similarity index 100% rename from web/core/components/issues/issue-modal/context/index.ts rename to apps/web/core/components/issues/issue-modal/context/index.ts diff --git a/web/core/components/issues/issue-modal/context/issue-modal-context.tsx b/apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx similarity index 90% rename from web/core/components/issues/issue-modal/context/issue-modal-context.tsx rename to apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx index e2c2f3957..13b608fe9 100644 --- a/web/core/components/issues/issue-modal/context/issue-modal-context.tsx +++ b/apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx @@ -1,12 +1,12 @@ import { createContext } from "react"; // ce imports // react-hook-form +import { TIssueFields } from "ce/components/issues"; import { UseFormReset, UseFormWatch } from "react-hook-form"; // plane imports import { EditorRefApi } from "@plane/editor"; import { ISearchIssueResponse, TIssue } from "@plane/types"; import { TIssuePropertyValues, TIssuePropertyValueErrors } from "@/plane-web/types/issue-types"; -import { TIssueFields } from "ce/components/issues"; export type TPropertyValuesValidationProps = { projectId: string | null; @@ -28,6 +28,12 @@ export type TCreateUpdatePropertyValuesProps = { isDraft?: boolean; }; +export type TCreateSubWorkItemProps = { + workspaceSlug: string; + projectId: string; + parentId: string; +}; + export type THandleTemplateChangeProps = { workspaceSlug: string; reset: UseFormReset; @@ -35,8 +41,9 @@ export type THandleTemplateChangeProps = { }; export type THandleProjectEntitiesFetchProps = { + workItemProjectId: string | null | undefined; + workItemTypeId: string | undefined; workspaceSlug: string; - templateId: string; }; export type THandleParentWorkItemDetailsProps = { @@ -65,6 +72,7 @@ export type TIssueModalContext = { handleProjectEntitiesFetch: (props: THandleProjectEntitiesFetchProps) => Promise; handleTemplateChange: (props: THandleTemplateChangeProps) => Promise; handleConvert: (workspaceSlug: string, data: Partial) => Promise; + handleCreateSubWorkItem: (props: TCreateSubWorkItemProps) => Promise; }; export const IssueModalContext = createContext(undefined); diff --git a/web/core/components/issues/issue-modal/draft-issue-layout.tsx b/apps/web/core/components/issues/issue-modal/draft-issue-layout.tsx similarity index 88% rename from web/core/components/issues/issue-modal/draft-issue-layout.tsx rename to apps/web/core/components/issues/issue-modal/draft-issue-layout.tsx index 96cc4a322..cc2ad0c27 100644 --- a/web/core/components/issues/issue-modal/draft-issue-layout.tsx +++ b/apps/web/core/components/issues/issue-modal/draft-issue-layout.tsx @@ -3,7 +3,8 @@ import React, { useState } from "react"; import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; +import { WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // types import type { TIssue } from "@plane/types"; @@ -14,8 +15,9 @@ import { isEmptyHtmlString } from "@plane/utils"; import { ConfirmIssueDiscard } from "@/components/issues"; // helpers // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useIssueModal } from "@/hooks/context/use-issue-modal"; -import { useEventTracker, useWorkspaceDraftIssues } from "@/hooks/store"; +import { useWorkspaceDraftIssues } from "@/hooks/store"; // local components import { IssueFormRoot, type IssueFormProps } from "./form"; @@ -30,10 +32,7 @@ export const DraftIssueLayout: React.FC = observer((props) => { const [issueDiscardModal, setIssueDiscardModal] = useState(false); // router params const { workspaceSlug } = useParams(); - // pathname - const pathname = usePathname(); // store hooks - const { captureIssueEvent } = useEventTracker(); const { handleCreateUpdatePropertyValues } = useIssueModal(); const { createIssue } = useWorkspaceDraftIssues(); const { t } = useTranslation(); @@ -92,26 +91,25 @@ export const DraftIssueLayout: React.FC = observer((props) => { title: `${t("success")}!`, message: t("workspace_draft_issues.toasts.created.success"), }); - captureIssueEvent({ - eventName: "Draft work item created", - payload: { ...res, state: "SUCCESS" }, - path: pathname, + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.draft.create, + payload: { id: res?.id }, }); onChange(null); setIssueDiscardModal(false); onClose(); return res; }) - .catch(() => { + .catch((error) => { setToast({ type: TOAST_TYPE.ERROR, title: `${t("error")}!`, message: t("workspace_draft_issues.toasts.created.error"), }); - captureIssueEvent({ - eventName: "Draft work item created", - payload: { ...payload, state: "FAILED" }, - path: pathname, + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.draft.create, + payload: { id: payload.id }, + error, }); }); diff --git a/web/core/components/issues/issue-modal/form.tsx b/apps/web/core/components/issues/issue-modal/form.tsx similarity index 93% rename from web/core/components/issues/issue-modal/form.tsx rename to apps/web/core/components/issues/issue-modal/form.tsx index addf1917a..8c20e2763 100644 --- a/web/core/components/issues/issue-modal/form.tsx +++ b/apps/web/core/components/issues/issue-modal/form.tsx @@ -5,15 +5,21 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { FormProvider, useForm } from "react-hook-form"; // editor -import { ETabIndices, EIssuesStoreType, DEFAULT_WORK_ITEM_FORM_VALUES } from "@plane/constants"; +import { ETabIndices, DEFAULT_WORK_ITEM_FORM_VALUES } from "@plane/constants"; import { EditorRefApi } from "@plane/editor"; // i18n import { useTranslation } from "@plane/i18n"; -// types -import type { TIssue, TWorkspaceDraftIssue } from "@plane/types"; +import { EIssuesStoreType, TIssue, TWorkspaceDraftIssue } from "@plane/types"; // hooks import { Button, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; -import { convertWorkItemDataToSearchResponse, getUpdateFormDataForReset, cn, getTextContent, getChangedIssuefields, getTabIndex } from "@plane/utils"; +import { + convertWorkItemDataToSearchResponse, + getUpdateFormDataForReset, + cn, + getTextContent, + getChangedIssuefields, + getTabIndex, +} from "@plane/utils"; // components import { IssueDefaultProperties, @@ -26,16 +32,13 @@ import { CreateLabelModal } from "@/components/labels"; // helpers // hooks import { useIssueModal } from "@/hooks/context/use-issue-modal"; -import { useIssueDetail, useProject, useProjectState, useWorkspaceDraftIssues } from "@/hooks/store"; +import { useIssueDetail, useLabel, useProject, useProjectState, useWorkspaceDraftIssues } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; import { useProjectIssueProperties } from "@/hooks/use-project-issue-properties"; // plane web imports import { DeDupeButtonRoot, DuplicateModalRoot } from "@/plane-web/components/de-dupe"; -import { - IssueAdditionalProperties, - IssueTypeSelect, - WorkItemTemplateSelect, -} from "@/plane-web/components/issues/issue-modal"; +import { IssueTypeSelect, WorkItemTemplateSelect } from "@/plane-web/components/issues/issue-modal"; +import { WorkItemModalAdditionalProperties } from "@/plane-web/components/issues/issue-modal/modal-additional-properties"; import { useDebouncedDuplicateIssues } from "@/plane-web/hooks/use-debounced-duplicate-issues"; export interface IssueFormProps { @@ -118,6 +121,7 @@ export const IssueFormRoot: FC = observer((props) => { } = useIssueModal(); const { isMobile } = usePlatformOS(); const { moveIssue } = useWorkspaceDraftIssues(); + const { createLabel } = useLabel(); const { issue: { getIssueById }, @@ -356,9 +360,9 @@ export const IssueFormRoot: FC = observer((props) => { {projectId && ( setLabelModal(false)} - projectId={projectId} onSuccess={(response) => { setValue<"label_ids">("label_ids", [...watch("label_ids"), response.id]); handleFormChange(); @@ -468,25 +472,19 @@ export const IssueFormRoot: FC = observer((props) => { onClose={onClose} />
-
- {projectId && ( - - )} -
+
-
+
0 && "shadow-custom-shadow-xs" + )} + >
= ({ return ( <> setSearchTerm("")} appear> - + = ({
-
+
void; - toggleArchiveIssueModal: (issueId: string | null) => void; - handleRestoreIssue: () => void; + toggleDeleteIssueModal: (value: boolean) => void; + toggleArchiveIssueModal: (value: boolean) => void; + toggleDuplicateIssueModal: (value: boolean) => void; + toggleEditIssueModal: (value: boolean) => void; + handleRestoreIssue: () => Promise; isSubmitting: TNameDescriptionLoader; }; @@ -75,23 +79,32 @@ export const IssuePeekOverviewHeader: FC = observer((pr removeRoutePeekId, toggleDeleteIssueModal, toggleArchiveIssueModal, + toggleDuplicateIssueModal, + toggleEditIssueModal, handleRestoreIssue, isSubmitting, } = props; + // ref + const parentRef = useRef(null); const { t } = useTranslation(); // store hooks const { data: currentUser } = useUser(); const { issue: { getIssueById }, + setPeekIssue, + removeIssue, + archiveIssue, + getIsIssuePeeked, } = useIssueDetail(); - const { getStateById } = useProjectState(); const { isMobile } = usePlatformOS(); const { getProjectIdentifierById } = useProject(); // derived values const issueDetails = getIssueById(issueId); - const stateDetails = issueDetails ? getStateById(issueDetails?.state_id) : undefined; const currentMode = PEEK_OPTIONS.find((m) => m.key === peekMode); const projectIdentifier = getProjectIdentifierById(issueDetails?.project_id); + const { + issues: { removeIssue: removeArchivedIssue }, + } = useIssues(EIssuesStoreType.ARCHIVED); const workItemLink = generateWorkItemLink({ workspaceSlug, @@ -113,10 +126,51 @@ export const IssuePeekOverviewHeader: FC = observer((pr }); }); }; - // auth - const isArchivingAllowed = !isArchived && !disabled; - const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group); - const isRestoringAllowed = isArchived && !disabled; + + const handleDeleteIssue = async () => { + try { + const deleteIssue = issueDetails?.archived_at ? removeArchivedIssue : removeIssue; + + return deleteIssue(workspaceSlug, projectId, issueId).then(() => { + setPeekIssue(undefined); + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: issueId }, + }); + }); + } catch (error) { + setToast({ + title: t("toast.error"), + type: TOAST_TYPE.ERROR, + message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), + }); + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.delete, + payload: { id: issueId }, + error: error as Error, + }); + } + }; + + const handleArchiveIssue = async () => { + try { + await archiveIssue(workspaceSlug, projectId, issueId); + // check and remove if issue is peeked + if (getIsIssuePeeked(issueId)) { + removeRoutePeekId(); + } + captureSuccess({ + eventName: WORK_ITEM_TRACKER_EVENTS.archive, + payload: { id: issueId }, + }); + } catch (error) { + captureError({ + eventName: WORK_ITEM_TRACKER_EVENTS.archive, + payload: { id: issueId }, + error: error as Error, + }); + } + }; return (
= observer((pr - {isArchivingAllowed && ( - - - - )} - {isRestoringAllowed && ( - - - - )} - {!disabled && ( - - - + {issueDetails && ( + )}
diff --git a/web/core/components/issues/peek-overview/index.ts b/apps/web/core/components/issues/peek-overview/index.ts similarity index 100% rename from web/core/components/issues/peek-overview/index.ts rename to apps/web/core/components/issues/peek-overview/index.ts diff --git a/web/core/components/issues/peek-overview/issue-detail.tsx b/apps/web/core/components/issues/peek-overview/issue-detail.tsx similarity index 100% rename from web/core/components/issues/peek-overview/issue-detail.tsx rename to apps/web/core/components/issues/peek-overview/issue-detail.tsx diff --git a/web/core/components/issues/peek-overview/loader.tsx b/apps/web/core/components/issues/peek-overview/loader.tsx similarity index 100% rename from web/core/components/issues/peek-overview/loader.tsx rename to apps/web/core/components/issues/peek-overview/loader.tsx diff --git a/web/core/components/issues/peek-overview/properties.tsx b/apps/web/core/components/issues/peek-overview/properties.tsx similarity index 100% rename from web/core/components/issues/peek-overview/properties.tsx rename to apps/web/core/components/issues/peek-overview/properties.tsx diff --git a/web/core/components/issues/peek-overview/root.tsx b/apps/web/core/components/issues/peek-overview/root.tsx similarity index 67% rename from web/core/components/issues/peek-overview/root.tsx rename to apps/web/core/components/issues/peek-overview/root.tsx index dfeedadce..b38415c2f 100644 --- a/web/core/components/issues/peek-overview/root.tsx +++ b/apps/web/core/components/issues/peek-overview/root.tsx @@ -3,23 +3,16 @@ import { FC, useEffect, useState, useMemo, useCallback } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; -// plane types -import { - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, - EIssueServiceType, - WORK_ITEM_TRACKER_EVENTS, -} from "@plane/constants"; +// Plane imports +import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue, IWorkItemPeekOverview } from "@plane/types"; -// plane ui +import { EIssueServiceType, EIssuesStoreType, IWorkItemPeekOverview, TIssue } from "@plane/types"; import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui"; // components import { IssueView, TIssueOperations } from "@/components/issues"; -// constants // hooks -import { useEventTracker, useIssueDetail, useIssues, useUserPermissions } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useIssueDetail, useIssues, useUserPermissions } from "@/hooks/store"; import { useIssueStoreType } from "@/hooks/use-issue-layout-store"; import { useWorkItemProperties } from "@/plane-web/hooks/use-issue-properties"; @@ -48,7 +41,6 @@ export const IssuePeekOverview: FC = observer((props) => const issueStoreType = useIssueStoreType(); const storeType = issueStoreFromProps ?? issueStoreType; const { issues } = useIssues(storeType); - const { captureIssueEvent } = useEventTracker(); useWorkItemProperties( peekIssue?.projectId, @@ -81,21 +73,16 @@ export const IssuePeekOverview: FC = observer((props) => .updateIssue(workspaceSlug, projectId, issueId, data) .then(async () => { fetchActivities(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...data, issueId, state: "SUCCESS", element: "Issue peek-overview" }, - updates: { - changed_property: Object.keys(data).join(","), - change_details: Object.values(data).join(","), - }, - path: pathname, + payload: { id: issueId }, }); }) - .catch(() => { - captureIssueEvent({ + .catch((error) => { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); setToast({ title: t("toast.error"), @@ -108,23 +95,22 @@ export const IssuePeekOverview: FC = observer((props) => remove: async (workspaceSlug: string, projectId: string, issueId: string) => { try { return issues?.removeIssue(workspaceSlug, projectId, issueId).then(() => { - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, }); removeRoutePeekId(); }); - } catch { + } catch (error) { setToast({ title: t("toast.error"), type: TOAST_TYPE.ERROR, message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -132,16 +118,15 @@ export const IssuePeekOverview: FC = observer((props) => try { if (!issues?.archiveIssue) return; await issues.archiveIssue(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -153,21 +138,20 @@ export const IssuePeekOverview: FC = observer((props) => title: t("issue.restore.success.title"), message: t("issue.restore.success.message"), }); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.restore, - payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, }); - } catch { + } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: t("toast.error"), message: t("issue.restore.failed.message"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.restore, - payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -175,58 +159,40 @@ export const IssuePeekOverview: FC = observer((props) => try { await issues.addCycleToIssue(workspaceSlug, projectId, cycleId, issueId); fetchActivities(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, }); - } catch { + } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: t("toast.error"), message: t("issue.add.cycle.failed"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { try { await issues.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueIds }, }); - } catch { + } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: t("toast.error"), message: t("issue.add.cycle.failed"), }); - captureIssueEvent({ + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: cycleId, - }, - path: pathname, + payload: { id: issueIds }, + error: error as Error, }); } }, @@ -246,24 +212,15 @@ export const IssuePeekOverview: FC = observer((props) => }); await removeFromCyclePromise; fetchActivities(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { issueId, state: "SUCCESS", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { state: "FAILED", element: "Issue peek-overview" }, - updates: { - changed_property: "cycle_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, @@ -282,14 +239,9 @@ export const IssuePeekOverview: FC = observer((props) => removeModuleIds ); fetchActivities(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" }, - updates: { - changed_property: "module_id", - change_details: { addModuleIds, removeModuleIds }, - }, - path: pathname, + payload: { id: issueId }, }); return promise; }, @@ -309,30 +261,21 @@ export const IssuePeekOverview: FC = observer((props) => }); await removeFromModulePromise; fetchActivities(workspaceSlug, projectId, issueId); - captureIssueEvent({ + captureSuccess({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" }, - updates: { - changed_property: "module_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, }); - } catch { - captureIssueEvent({ + } catch (error) { + captureError({ eventName: WORK_ITEM_TRACKER_EVENTS.update, - payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" }, - updates: { - changed_property: "module_id", - change_details: "", - }, - path: pathname, + payload: { id: issueId }, + error: error as Error, }); } }, }), // eslint-disable-next-line react-hooks/exhaustive-deps - [fetchIssue, is_draft, issues, fetchActivities, captureIssueEvent, pathname, removeRoutePeekId, restoreIssue] + [fetchIssue, is_draft, issues, fetchActivities, pathname, removeRoutePeekId, restoreIssue] ); useEffect(() => { diff --git a/apps/web/core/components/issues/peek-overview/view.tsx b/apps/web/core/components/issues/peek-overview/view.tsx new file mode 100644 index 000000000..6d1fe4756 --- /dev/null +++ b/apps/web/core/components/issues/peek-overview/view.tsx @@ -0,0 +1,266 @@ +import { FC, useRef, useState } from "react"; +import { observer } from "mobx-react"; +import { createPortal } from "react-dom"; +// types +import { EIssueServiceType, TNameDescriptionLoader } from "@plane/types"; +// components +import { cn } from "@plane/utils"; +import { + IssuePeekOverviewHeader, + TPeekModes, + PeekOverviewIssueDetails, + PeekOverviewProperties, + TIssueOperations, + IssuePeekOverviewLoader, + IssuePeekOverviewError, + IssueDetailWidgets, +} from "@/components/issues"; +// helpers +// hooks +import { useIssueDetail } from "@/hooks/store"; +import useKeypress from "@/hooks/use-keypress"; +import usePeekOverviewOutsideClickDetector from "@/hooks/use-peek-overview-outside-click"; +// store hooks +import { IssueActivity } from "../issue-detail/issue-activity"; + +interface IIssueView { + workspaceSlug: string; + projectId: string; + issueId: string; + isLoading?: boolean; + isError?: boolean; + is_archived: boolean; + disabled?: boolean; + embedIssue?: boolean; + embedRemoveCurrentNotification?: () => void; + issueOperations: TIssueOperations; +} + +export const IssueView: FC = observer((props) => { + const { + workspaceSlug, + projectId, + issueId, + isLoading, + isError, + is_archived, + disabled = false, + embedIssue = false, + embedRemoveCurrentNotification, + issueOperations, + } = props; + // states + const [peekMode, setPeekMode] = useState("side-peek"); + const [isSubmitting, setIsSubmitting] = useState("saved"); + const [isDeleteIssueModalOpen, setIsDeleteIssueModalOpen] = useState(false); + const [isArchiveIssueModalOpen, setIsArchiveIssueModalOpen] = useState(false); + const [isDuplicateIssueModalOpen, setIsDuplicateIssueModalOpen] = useState(false); + const [isEditIssueModalOpen, setIsEditIssueModalOpen] = useState(false); + // ref + const issuePeekOverviewRef = useRef(null); + // store hooks + const { + setPeekIssue, + isAnyModalOpen, + issue: { getIssueById, getIsLocalDBIssueDescription }, + } = useIssueDetail(); + const { isAnyModalOpen: isAnyEpicModalOpen } = useIssueDetail(EIssueServiceType.EPICS); + const issue = getIssueById(issueId); + // remove peek id + const removeRoutePeekId = () => { + setPeekIssue(undefined); + if (embedIssue && embedRemoveCurrentNotification) embedRemoveCurrentNotification(); + }; + + const isLocalDBIssueDescription = getIsLocalDBIssueDescription(issueId); + + const toggleDeleteIssueModal = (value: boolean) => setIsDeleteIssueModalOpen(value); + const toggleArchiveIssueModal = (value: boolean) => setIsArchiveIssueModalOpen(value); + const toggleDuplicateIssueModal = (value: boolean) => setIsDuplicateIssueModalOpen(value); + const toggleEditIssueModal = (value: boolean) => setIsEditIssueModalOpen(value); + + const isAnyLocalModalOpen = + isDeleteIssueModalOpen || isArchiveIssueModalOpen || isDuplicateIssueModalOpen || isEditIssueModalOpen; + + usePeekOverviewOutsideClickDetector( + issuePeekOverviewRef, + () => { + if (!embedIssue) { + if (!isAnyModalOpen && !isAnyEpicModalOpen && !isAnyLocalModalOpen) { + removeRoutePeekId(); + } + } + }, + issueId + ); + + const handleKeyDown = () => { + const slashCommandDropdownElement = document.querySelector("#slash-command"); + const editorImageFullScreenModalElement = document.querySelector(".editor-image-full-screen-modal"); + const dropdownElement = document.activeElement?.tagName === "INPUT"; + if (!isAnyModalOpen && !slashCommandDropdownElement && !dropdownElement && !editorImageFullScreenModalElement) { + removeRoutePeekId(); + const issueElement = document.getElementById(`issue-${issueId}`); + if (issueElement) issueElement?.focus(); + } + }; + + useKeypress("Escape", () => !embedIssue && handleKeyDown()); + + const handleRestore = async () => { + if (!issueOperations.restore) return; + await issueOperations.restore(workspaceSlug, projectId, issueId); + removeRoutePeekId(); + }; + + const peekOverviewIssueClassName = cn( + !embedIssue + ? "fixed z-[25] flex flex-col overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 transition-all duration-300" + : `w-full h-full`, + !embedIssue && { + "top-2 bottom-2 right-2 w-full md:w-[50%] border-0 border-l": peekMode === "side-peek", + "size-5/6 top-[8.33%] left-[8.33%]": peekMode === "modal", + "inset-0 m-4 absolute": peekMode === "full-screen", + } + ); + + const shouldUsePortal = !embedIssue && peekMode === "full-screen"; + + const portalContainer = document.getElementById("full-screen-portal") as HTMLElement; + + const content = ( +
+ {issueId && ( +
+ {isError ? ( +
+ +
+ ) : ( + isLoading && + )} + {!isLoading && !isError && issue && ( + <> + {/* header */} + setPeekMode(value)} + removeRoutePeekId={removeRoutePeekId} + toggleDeleteIssueModal={toggleDeleteIssueModal} + toggleArchiveIssueModal={toggleArchiveIssueModal} + toggleDuplicateIssueModal={toggleDuplicateIssueModal} + toggleEditIssueModal={toggleEditIssueModal} + handleRestoreIssue={handleRestore} + isArchived={is_archived} + issueId={issueId} + workspaceSlug={workspaceSlug} + projectId={projectId} + isSubmitting={isSubmitting} + disabled={disabled} + embedIssue={embedIssue} + /> + {/* content */} +
+ {["side-peek", "modal"].includes(peekMode) ? ( +
+ setIsSubmitting(value)} + /> + +
+ +
+ + + + +
+ ) : ( +
+
+
+ setIsSubmitting(value)} + /> + +
+ +
+ + +
+
+
+ +
+
+ )} +
+ + )} +
+ )} +
+ ); + + return <>{shouldUsePortal && portalContainer ? createPortal(content, portalContainer) : content}; +}); diff --git a/web/core/components/issues/relations/index.ts b/apps/web/core/components/issues/relations/index.ts similarity index 100% rename from web/core/components/issues/relations/index.ts rename to apps/web/core/components/issues/relations/index.ts diff --git a/web/core/components/issues/relations/issue-list-item.tsx b/apps/web/core/components/issues/relations/issue-list-item.tsx similarity index 92% rename from web/core/components/issues/relations/issue-list-item.tsx rename to apps/web/core/components/issues/relations/issue-list-item.tsx index eeedabdf9..a344969e2 100644 --- a/web/core/components/issues/relations/issue-list-item.tsx +++ b/apps/web/core/components/issues/relations/issue-list-item.tsx @@ -4,16 +4,15 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { X, Pencil, Trash, Link as LinkIcon } from "lucide-react"; // Plane -import { EIssueServiceType } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TIssue, TIssueServiceType } from "@plane/types"; +import { EIssueServiceType, TIssue, TIssueServiceType } from "@plane/types"; import { ControlLink, CustomMenu, Tooltip } from "@plane/ui"; // components import { generateWorkItemLink } from "@plane/utils"; import { RelationIssueProperty } from "@/components/issues/relations"; // helpers // hooks -import { useIssueDetail, useProject, useProjectState } from "@/hooks/store"; +import { useIssueDetail, useProject } from "@/hooks/store"; import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components @@ -59,7 +58,6 @@ export const RelationIssueListItem: FC = observer((props) => { toggleDeleteIssueModal, } = useIssueDetail(issueServiceType); const project = useProject(); - const { getProjectStates } = useProjectState(); const { isMobile } = usePlatformOS(); // derived values const issue = getIssueById(relationIssueId); @@ -67,9 +65,7 @@ export const RelationIssueListItem: FC = observer((props) => { const issueOperations = useRelationOperations(!!issue?.is_epic ? EIssueServiceType.EPICS : EIssueServiceType.ISSUES); const projectDetail = (issue && issue.project_id && project.getProjectById(issue.project_id)) || undefined; const projectId = issue?.project_id; - const currentIssueStateDetail = - (issue?.project_id && getProjectStates(issue?.project_id)?.find((state) => issue?.state_id == state.id)) || - undefined; + if (!issue || !projectId) return <>; const workItemLink = generateWorkItemLink({ @@ -130,12 +126,6 @@ export const RelationIssueListItem: FC = observer((props) => {
-
{projectDetail && ( >; - value: string[]; - onChange: (value: string[]) => void; - projectId: string | undefined; - label?: JSX.Element; - disabled?: boolean; - tabIndex?: number; - createLabelEnabled?: boolean; - buttonContainerClassName?: string; +export type TWorkItemLabelSelectBaseProps = { buttonClassName?: string; + buttonContainerClassName?: string; + createLabelEnabled?: boolean; + disabled?: boolean; + getLabelById: (labelId: string) => IIssueLabel | null; + label?: JSX.Element; + labelIds: string[]; + onChange: (value: string[]) => void; + onDropdownOpen?: () => void; placement?: Placement; + setIsOpen: React.Dispatch>; + tabIndex?: number; + value: string[]; }; -export const IssueLabelSelect: React.FC = observer((props) => { +export const WorkItemLabelSelectBase: React.FC = observer((props) => { const { - setIsOpen, - value, - onChange, - projectId, - label, - disabled = false, - tabIndex, - createLabelEnabled = false, - buttonContainerClassName, buttonClassName, + buttonContainerClassName, + createLabelEnabled = false, + disabled = false, + getLabelById, + label, + labelIds, + onChange, + onDropdownOpen, placement, + setIsOpen, + tabIndex, + value, } = props; - const { t } = useTranslation(); - // router - const { workspaceSlug } = useParams(); - // store hooks - const { getProjectLabels, fetchProjectLabels } = useLabel(); - const { isMobile } = usePlatformOS(); + // refs + const dropdownRef = useRef(null); + const inputRef = useRef(null); // states const [query, setQuery] = useState(""); const [referenceElement, setReferenceElement] = useState(null); const [popperElement, setPopperElement] = useState(null); const [isDropdownOpen, setIsDropdownOpen] = useState(false); - // refs - const dropdownRef = useRef(null); - const inputRef = useRef(null); - // popper + // plane hooks + const { t } = useTranslation(); + // store hooks + const { isMobile } = usePlatformOS(); + // popper-js init const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: placement ?? "bottom-start", }); - - const projectLabels = getProjectLabels(projectId); - // derived values + const labelsList = labelIds.map((labelId) => getLabelById(labelId)).filter((label) => !!label); const filteredOptions = - query === "" ? projectLabels : projectLabels?.filter((l) => l.name.toLowerCase().includes(query.toLowerCase())); + query === "" ? labelsList : labelsList?.filter((l) => l.name.toLowerCase().includes(query.toLowerCase())); const onOpen = () => { - if (!projectLabels && workspaceSlug && projectId) fetchProjectLabels(workspaceSlug.toString(), projectId); if (referenceElement) referenceElement.focus(); + onDropdownOpen?.(); }; const handleClose = () => { @@ -131,13 +130,18 @@ export const IssueLabelSelect: React.FC = observer((props) => { ) : value && value.length > 0 ? ( projectLabels?.find((l) => l.id === v)) ?? []} + labels={value.map((v) => labelsList?.find((l) => l.id === v)) ?? []} length={3} showLength /> ) : ( -
+
{t("labels")}
@@ -164,10 +168,10 @@ export const IssueLabelSelect: React.FC = observer((props) => { />
- {projectLabels && filteredOptions ? ( + {labelsList && filteredOptions ? ( filteredOptions.length > 0 ? ( filteredOptions.map((label) => { - const children = projectLabels?.filter((l) => l.parent === label.id); + const children = labelsList?.filter((l) => l.parent === label.id); if (children.length === 0) { if (!label.parent) diff --git a/apps/web/core/components/issues/select/dropdown.tsx b/apps/web/core/components/issues/select/dropdown.tsx new file mode 100644 index 000000000..2a86e03ab --- /dev/null +++ b/apps/web/core/components/issues/select/dropdown.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { observer } from "mobx-react"; +import { useParams } from "next/navigation"; +// hooks +import { useLabel } from "@/hooks/store"; +// local imports +import { TWorkItemLabelSelectBaseProps, WorkItemLabelSelectBase } from "./base"; + +type TWorkItemLabelSelectProps = Omit & { + projectId: string | undefined; +}; + +export const IssueLabelSelect: React.FC = observer((props) => { + const { projectId } = props; + // router + const { workspaceSlug } = useParams(); + // store hooks + const { getProjectLabelIds, getLabelById, fetchProjectLabels } = useLabel(); + // derived values + const projectLabelIds = getProjectLabelIds(projectId); + + const onDropdownOpen = () => { + if (projectLabelIds === undefined && workspaceSlug && projectId) + fetchProjectLabels(workspaceSlug.toString(), projectId); + }; + + return ( + + ); +}); diff --git a/apps/web/core/components/issues/select/index.ts b/apps/web/core/components/issues/select/index.ts new file mode 100644 index 000000000..22dfbe30b --- /dev/null +++ b/apps/web/core/components/issues/select/index.ts @@ -0,0 +1 @@ +export * from "./dropdown"; diff --git a/web/core/components/issues/title-input.tsx b/apps/web/core/components/issues/title-input.tsx similarity index 75% rename from web/core/components/issues/title-input.tsx rename to apps/web/core/components/issues/title-input.tsx index bc04dbbb4..e2b4be881 100644 --- a/web/core/components/issues/title-input.tsx +++ b/apps/web/core/components/issues/title-input.tsx @@ -1,6 +1,6 @@ "use client"; -import { FC, useState, useEffect, useCallback } from "react"; +import { FC, useState, useEffect, useCallback, useRef } from "react"; import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; import { TNameDescriptionLoader } from "@plane/types"; @@ -42,11 +42,20 @@ export const IssueTitleInput: FC = observer((props) => { // states const [title, setTitle] = useState(""); const [isLengthVisible, setIsLengthVisible] = useState(false); + // ref to track if there are unsaved changes + const hasUnsavedChanges = useRef(false); + // ref to store current title value for cleanup function + const currentTitleRef = useRef(title); // hooks const debouncedValue = useDebounce(title, 1500); useEffect(() => { - if (value) setTitle(value); + if (value) { + setTitle(value); + currentTitleRef.current = value; + // Reset unsaved changes flag when value is set from props + hasUnsavedChanges.current = false; + } }, [value]); useEffect(() => { @@ -55,6 +64,7 @@ export const IssueTitleInput: FC = observer((props) => { if (debouncedValue.trim().length > 0) { issueOperations.update(workspaceSlug, projectId, issueId, { name: debouncedValue }).finally(() => { setIsSubmitting("saved"); + hasUnsavedChanges.current = false; if (textarea && !textarea.matches(":focus")) { const trimmedTitle = debouncedValue.trim(); if (trimmedTitle !== title) setTitle(trimmedTitle); @@ -63,6 +73,7 @@ export const IssueTitleInput: FC = observer((props) => { } else { setTitle(value || ""); setIsSubmitting("saved"); + hasUnsavedChanges.current = false; } } // DO NOT Add more dependencies here. It will cause multiple requests to be sent. @@ -76,9 +87,11 @@ export const IssueTitleInput: FC = observer((props) => { if (trimmedTitle.length > 0) { setTitle(trimmedTitle); setIsSubmitting("submitting"); + hasUnsavedChanges.current = true; } else { setTitle(value || ""); setIsSubmitting("saved"); + hasUnsavedChanges.current = false; } } }; @@ -95,10 +108,32 @@ export const IssueTitleInput: FC = observer((props) => { }; }, [title, isSubmitting, setIsSubmitting]); + // Save on unmount if there are unsaved changes + useEffect( + () => () => { + if (hasUnsavedChanges.current && currentTitleRef.current.trim().length > 0) { + issueOperations + .update(workspaceSlug, projectId, issueId, { name: currentTitleRef.current.trim() }) + .catch((error) => { + console.error("Failed to save title on unmount:", error); + }) + .finally(() => { + setIsSubmitting("saved"); + hasUnsavedChanges.current = false; + }); + } + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ); + const handleTitleChange = useCallback( (e: React.ChangeEvent) => { setIsSubmitting("submitting"); - setTitle(e.target.value); + const titleFromEvent = e.target.value; + setTitle(titleFromEvent); + currentTitleRef.current = titleFromEvent; + hasUnsavedChanges.current = true; }, [setIsSubmitting] ); diff --git a/web/core/components/issues/workspace-draft/delete-modal.tsx b/apps/web/core/components/issues/workspace-draft/delete-modal.tsx similarity index 100% rename from web/core/components/issues/workspace-draft/delete-modal.tsx rename to apps/web/core/components/issues/workspace-draft/delete-modal.tsx diff --git a/web/core/components/issues/workspace-draft/draft-issue-block.tsx b/apps/web/core/components/issues/workspace-draft/draft-issue-block.tsx similarity index 98% rename from web/core/components/issues/workspace-draft/draft-issue-block.tsx rename to apps/web/core/components/issues/workspace-draft/draft-issue-block.tsx index 423231c6c..4c9a9736c 100644 --- a/web/core/components/issues/workspace-draft/draft-issue-block.tsx +++ b/apps/web/core/components/issues/workspace-draft/draft-issue-block.tsx @@ -4,9 +4,7 @@ import { omit } from "lodash"; import { observer } from "mobx-react"; import { Copy, Pencil, SquareStackIcon, Trash2 } from "lucide-react"; // types -import { EIssuesStoreType } from "@plane/constants"; -import { TWorkspaceDraftIssue } from "@plane/types"; -// ui +import { EIssuesStoreType, TWorkspaceDraftIssue } from "@plane/types"; import { Row, TContextMenuItem, Tooltip } from "@plane/ui"; // constants // helper diff --git a/web/core/components/issues/workspace-draft/draft-issue-properties.tsx b/apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx similarity index 100% rename from web/core/components/issues/workspace-draft/draft-issue-properties.tsx rename to apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx diff --git a/web/core/components/issues/workspace-draft/empty-state.tsx b/apps/web/core/components/issues/workspace-draft/empty-state.tsx similarity index 90% rename from web/core/components/issues/workspace-draft/empty-state.tsx rename to apps/web/core/components/issues/workspace-draft/empty-state.tsx index 1c0b51fbb..3cd990d07 100644 --- a/web/core/components/issues/workspace-draft/empty-state.tsx +++ b/apps/web/core/components/issues/workspace-draft/empty-state.tsx @@ -3,8 +3,9 @@ import { FC, Fragment, useState } from "react"; // components import { observer } from "mobx-react"; -import { EIssuesStoreType, EUserPermissionsLevel, EUserWorkspaceRoles } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types"; import { DetailedEmptyState } from "@/components/empty-state"; import { CreateUpdateIssueModal } from "@/components/issues"; // constants @@ -42,7 +43,7 @@ export const WorkspaceDraftEmptyState: FC = observer(() => { onClick: () => { setIsDraftIssueModalOpen(true); }, - disabled: !canPerformEmptyStateActions + disabled: !canPerformEmptyStateActions, }} />
diff --git a/web/core/components/issues/workspace-draft/index.ts b/apps/web/core/components/issues/workspace-draft/index.ts similarity index 100% rename from web/core/components/issues/workspace-draft/index.ts rename to apps/web/core/components/issues/workspace-draft/index.ts diff --git a/web/core/components/issues/workspace-draft/loader.tsx b/apps/web/core/components/issues/workspace-draft/loader.tsx similarity index 100% rename from web/core/components/issues/workspace-draft/loader.tsx rename to apps/web/core/components/issues/workspace-draft/loader.tsx diff --git a/web/core/components/issues/workspace-draft/quick-action.tsx b/apps/web/core/components/issues/workspace-draft/quick-action.tsx similarity index 100% rename from web/core/components/issues/workspace-draft/quick-action.tsx rename to apps/web/core/components/issues/workspace-draft/quick-action.tsx diff --git a/web/core/components/issues/workspace-draft/root.tsx b/apps/web/core/components/issues/workspace-draft/root.tsx similarity index 92% rename from web/core/components/issues/workspace-draft/root.tsx rename to apps/web/core/components/issues/workspace-draft/root.tsx index 8f4577e80..499a42c81 100644 --- a/web/core/components/issues/workspace-draft/root.tsx +++ b/apps/web/core/components/issues/workspace-draft/root.tsx @@ -4,12 +4,13 @@ import { FC, Fragment } from "react"; import { observer } from "mobx-react"; import useSWR from "swr"; // plane imports -import { EDraftIssuePaginationType } from "@plane/constants"; -import { EUserPermissionsLevel, EUserWorkspaceRoles } from "@plane/constants/src/user"; +import { EUserPermissionsLevel, EDraftIssuePaginationType, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EUserWorkspaceRoles } from "@plane/types"; // components import { cn } from "@plane/utils"; import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state"; +import { captureClick } from "@/helpers/event-tracker.helper"; // constants // helpers @@ -76,6 +77,7 @@ export const WorkspaceDraftIssuesRoot: FC = observer( description={t("workspace_projects.empty_state.no_projects.primary_button.comic.description")} onClick={() => { toggleCreateProjectModal(true); + captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); }} disabled={!hasMemberLevelPermission} /> diff --git a/web/core/components/labels/create-label-modal.tsx b/apps/web/core/components/labels/create-label-modal.tsx similarity index 95% rename from web/core/components/labels/create-label-modal.tsx rename to apps/web/core/components/labels/create-label-modal.tsx index a186783b4..413429c8a 100644 --- a/web/core/components/labels/create-label-modal.tsx +++ b/apps/web/core/components/labels/create-label-modal.tsx @@ -2,7 +2,6 @@ import React, { useEffect } from "react"; import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; import { TwitterPicker } from "react-color"; import { Controller, useForm } from "react-hook-form"; import { ChevronDown } from "lucide-react"; @@ -16,14 +15,14 @@ import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; // helpers import { getTabIndex } from "@plane/utils"; // hooks -import { useLabel } from "@/hooks/store"; + import { usePlatformOS } from "@/hooks/use-platform-os"; // types type Props = { - isOpen: boolean; - projectId: string; + createLabel: (data: Partial) => Promise; handleClose: () => void; + isOpen: boolean; onSuccess?: (response: IIssueLabel) => void; }; @@ -33,11 +32,8 @@ const defaultValues: Partial = { }; export const CreateLabelModal: React.FC = observer((props) => { - const { isOpen, projectId, handleClose, onSuccess } = props; - // router - const { workspaceSlug } = useParams(); + const { createLabel, handleClose, isOpen, onSuccess } = props; // store hooks - const { createLabel } = useLabel(); const { isMobile } = usePlatformOS(); // form info const { @@ -71,9 +67,7 @@ export const CreateLabelModal: React.FC = observer((props) => { }; const onSubmit = async (formData: IIssueLabel) => { - if (!workspaceSlug) return; - - await createLabel(workspaceSlug.toString(), projectId.toString(), formData) + await createLabel(formData) .then((res) => { onClose(); if (onSuccess) onSuccess(res); diff --git a/web/core/components/labels/create-update-label-inline.tsx b/apps/web/core/components/labels/create-update-label-inline.tsx similarity index 100% rename from web/core/components/labels/create-update-label-inline.tsx rename to apps/web/core/components/labels/create-update-label-inline.tsx diff --git a/web/core/components/labels/delete-label-modal.tsx b/apps/web/core/components/labels/delete-label-modal.tsx similarity index 100% rename from web/core/components/labels/delete-label-modal.tsx rename to apps/web/core/components/labels/delete-label-modal.tsx diff --git a/web/core/components/labels/index.ts b/apps/web/core/components/labels/index.ts similarity index 100% rename from web/core/components/labels/index.ts rename to apps/web/core/components/labels/index.ts diff --git a/web/core/components/labels/label-block/label-item-block.tsx b/apps/web/core/components/labels/label-block/label-item-block.tsx similarity index 92% rename from web/core/components/labels/label-block/label-item-block.tsx rename to apps/web/core/components/labels/label-block/label-item-block.tsx index d74fabc76..06350275a 100644 --- a/web/core/components/labels/label-block/label-item-block.tsx +++ b/apps/web/core/components/labels/label-block/label-item-block.tsx @@ -3,6 +3,7 @@ import { MutableRefObject, useRef, useState } from "react"; import { LucideIcon, X } from "lucide-react"; // plane helpers +import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useOutsideClickDetector } from "@plane/hooks"; // types import { IIssueLabel } from "@plane/types"; @@ -90,7 +91,10 @@ export const LabelItemBlock = (props: ILabelItemBlock) => {
diff --git a/web/core/components/labels/label-block/label-name.tsx b/apps/web/core/components/labels/label-block/label-name.tsx similarity index 100% rename from web/core/components/labels/label-block/label-name.tsx rename to apps/web/core/components/labels/label-block/label-name.tsx diff --git a/web/core/components/labels/label-drag-n-drop-HOC.tsx b/apps/web/core/components/labels/label-drag-n-drop-HOC.tsx similarity index 100% rename from web/core/components/labels/label-drag-n-drop-HOC.tsx rename to apps/web/core/components/labels/label-drag-n-drop-HOC.tsx diff --git a/web/core/components/labels/label-utils.ts b/apps/web/core/components/labels/label-utils.ts similarity index 100% rename from web/core/components/labels/label-utils.ts rename to apps/web/core/components/labels/label-utils.ts diff --git a/web/core/components/labels/project-setting-label-group.tsx b/apps/web/core/components/labels/project-setting-label-group.tsx similarity index 100% rename from web/core/components/labels/project-setting-label-group.tsx rename to apps/web/core/components/labels/project-setting-label-group.tsx diff --git a/web/core/components/labels/project-setting-label-item.tsx b/apps/web/core/components/labels/project-setting-label-item.tsx similarity index 93% rename from web/core/components/labels/project-setting-label-item.tsx rename to apps/web/core/components/labels/project-setting-label-item.tsx index 5eabffd77..897b756a9 100644 --- a/web/core/components/labels/project-setting-label-item.tsx +++ b/apps/web/core/components/labels/project-setting-label-item.tsx @@ -2,8 +2,10 @@ import React, { Dispatch, SetStateAction, useState } from "react"; import { useParams } from "next/navigation"; import { X, Pencil } from "lucide-react"; // types +import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { IIssueLabel } from "@plane/types"; // hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useLabel } from "@/hooks/store"; // components import { CreateUpdateLabelInline, TLabelOperationsCallbacks } from "./create-update-label-inline"; @@ -67,6 +69,9 @@ export const ProjectSettingLabelItem: React.FC = (props) => { onClick: () => { setEditLabelForm(true); setIsUpdating(true); + captureClick({ + elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_CONTEXT_MENU, + }); }, isVisible: true, text: "Edit label", diff --git a/web/core/components/labels/project-setting-label-list.tsx b/apps/web/core/components/labels/project-setting-label-list.tsx similarity index 89% rename from web/core/components/labels/project-setting-label-list.tsx rename to apps/web/core/components/labels/project-setting-label-list.tsx index 86f82579c..088e7440e 100644 --- a/web/core/components/labels/project-setting-label-list.tsx +++ b/apps/web/core/components/labels/project-setting-label-list.tsx @@ -4,10 +4,10 @@ import React, { useState, useRef } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IIssueLabel } from "@plane/types"; -import { Button, Loader } from "@plane/ui"; +import { Loader } from "@plane/ui"; import { DetailedEmptyState } from "@/components/empty-state"; import { CreateUpdateLabelInline, @@ -17,6 +17,7 @@ import { TLabelOperationsCallbacks, } from "@/components/labels"; // hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useLabel, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; import { SettingsHeading } from "../settings"; @@ -81,7 +82,12 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { description={t("project_settings.labels.description")} button={{ label: t("common.add_label"), - onClick: newLabel, + onClick: () => { + newLabel(); + captureClick({ + elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_HEADER_CREATE_BUTTON, + }); + }, }} showButton={isEditable} /> @@ -110,7 +116,12 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { description={""} primaryButton={{ text: "Create your first label", - onClick: newLabel, + onClick: () => { + newLabel(); + captureClick({ + elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_EMPTY_STATE_CREATE_BUTTON, + }); + }, }} assetPath={resolvedPath} className="w-full !px-0 !py-0" diff --git a/web/core/components/license/index.ts b/apps/web/core/components/license/index.ts similarity index 100% rename from web/core/components/license/index.ts rename to apps/web/core/components/license/index.ts diff --git a/web/core/components/license/modal/card/base-paid-plan-card.tsx b/apps/web/core/components/license/modal/card/base-paid-plan-card.tsx similarity index 93% rename from web/core/components/license/modal/card/base-paid-plan-card.tsx rename to apps/web/core/components/license/modal/card/base-paid-plan-card.tsx index cfbb44fe6..746aea24a 100644 --- a/web/core/components/license/modal/card/base-paid-plan-card.tsx +++ b/apps/web/core/components/license/modal/card/base-paid-plan-card.tsx @@ -5,15 +5,10 @@ import { observer } from "mobx-react"; import { CheckCircle } from "lucide-react"; import { Tab } from "@headlessui/react"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; // helpers -import { TBillingFrequency, TSubscriptionPrice } from "@plane/types"; +import { EProductSubscriptionEnum, TBillingFrequency, TSubscriptionPrice } from "@plane/types"; +import { getSubscriptionBackgroundColor, getUpgradeCardVariantStyle } from "@plane/ui"; import { cn, getBaseSubscriptionName, getSubscriptionName } from "@plane/utils"; -// components -import { - getSubscriptionBackgroundColor, - getUpgradeCardVariantStyle, -} from "@/components/workspace/billing/subscription"; export type TBasePaidPlanCardProps = { planVariant: EProductSubscriptionEnum; diff --git a/web/core/components/license/modal/card/checkout-button.tsx b/apps/web/core/components/license/modal/card/checkout-button.tsx similarity index 92% rename from web/core/components/license/modal/card/checkout-button.tsx rename to apps/web/core/components/license/modal/card/checkout-button.tsx index 71a5bebc9..6ab4d23a3 100644 --- a/web/core/components/license/modal/card/checkout-button.tsx +++ b/apps/web/core/components/license/modal/card/checkout-button.tsx @@ -2,12 +2,9 @@ import { FC } from "react"; import { observer } from "mobx-react"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; -import { IPaymentProduct, TSubscriptionPrice } from "@plane/types"; -import { getButtonStyling, Loader } from "@plane/ui"; +import { EProductSubscriptionEnum, IPaymentProduct, TSubscriptionPrice } from "@plane/types"; +import { getButtonStyling, getUpgradeButtonStyle, Loader } from "@plane/ui"; import { cn } from "@plane/utils"; -// components -import { getUpgradeButtonStyle } from "@/components/workspace/billing/subscription"; // local imports import { DiscountInfo } from "./discount-info"; diff --git a/web/core/components/license/modal/card/discount-info.tsx b/apps/web/core/components/license/modal/card/discount-info.tsx similarity index 93% rename from web/core/components/license/modal/card/discount-info.tsx rename to apps/web/core/components/license/modal/card/discount-info.tsx index 27ca78796..3b5695cee 100644 --- a/web/core/components/license/modal/card/discount-info.tsx +++ b/apps/web/core/components/license/modal/card/discount-info.tsx @@ -1,7 +1,6 @@ import { useTheme } from "next-themes"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; -import { TBillingFrequency } from "@plane/types"; +import { EProductSubscriptionEnum, TBillingFrequency } from "@plane/types"; import { cn } from "@plane/utils"; type TDiscountInfoProps = { diff --git a/web/core/components/license/modal/card/free-plan.tsx b/apps/web/core/components/license/modal/card/free-plan.tsx similarity index 100% rename from web/core/components/license/modal/card/free-plan.tsx rename to apps/web/core/components/license/modal/card/free-plan.tsx diff --git a/web/core/components/license/modal/card/index.ts b/apps/web/core/components/license/modal/card/index.ts similarity index 100% rename from web/core/components/license/modal/card/index.ts rename to apps/web/core/components/license/modal/card/index.ts diff --git a/web/core/components/license/modal/card/plan-upgrade.tsx b/apps/web/core/components/license/modal/card/plan-upgrade.tsx similarity index 93% rename from web/core/components/license/modal/card/plan-upgrade.tsx rename to apps/web/core/components/license/modal/card/plan-upgrade.tsx index ef21459c6..6b88b7b49 100644 --- a/web/core/components/license/modal/card/plan-upgrade.tsx +++ b/apps/web/core/components/license/modal/card/plan-upgrade.tsx @@ -3,13 +3,12 @@ import { FC } from "react"; import { observer } from "mobx-react"; // plane imports -import { EProductSubscriptionEnum, TALK_TO_SALES_URL } from "@plane/constants"; -import { IPaymentProduct, TSubscriptionPrice } from "@plane/types"; +import { TALK_TO_SALES_URL } from "@plane/constants"; +import { EProductSubscriptionEnum, IPaymentProduct, TSubscriptionPrice } from "@plane/types"; +import { getDiscountPillStyle } from "@plane/ui"; import { calculateYearlyDiscount, cn, getSubscriptionName, getSubscriptionPriceDetails } from "@plane/utils"; // components import { BasePaidPlanCard, TalkToSalesCard } from "@/components/license"; -// helpers -import { getDiscountPillStyle } from "@/components/workspace/billing/subscription"; // local components import { PlanCheckoutButton, TCheckoutParams } from "./checkout-button"; diff --git a/web/core/components/license/modal/card/talk-to-sales.tsx b/apps/web/core/components/license/modal/card/talk-to-sales.tsx similarity index 92% rename from web/core/components/license/modal/card/talk-to-sales.tsx rename to apps/web/core/components/license/modal/card/talk-to-sales.tsx index cfd5e7744..41541562a 100644 --- a/web/core/components/license/modal/card/talk-to-sales.tsx +++ b/apps/web/core/components/license/modal/card/talk-to-sales.tsx @@ -3,13 +3,10 @@ import { FC } from "react"; import { observer } from "mobx-react"; // types -import { EProductSubscriptionEnum } from "@plane/constants"; // plane imports -import { IPaymentProduct, TSubscriptionPrice } from "@plane/types"; -import { getButtonStyling, Loader } from "@plane/ui"; +import { EProductSubscriptionEnum, IPaymentProduct, TSubscriptionPrice } from "@plane/types"; +import { getButtonStyling, getUpgradeButtonStyle, Loader } from "@plane/ui"; import { cn } from "@plane/utils"; -// plane web imports -import { getUpgradeButtonStyle } from "@/components/workspace/billing/subscription"; // local imports import { BasePaidPlanCard } from "./base-paid-plan-card"; diff --git a/web/core/components/license/modal/index.ts b/apps/web/core/components/license/modal/index.ts similarity index 100% rename from web/core/components/license/modal/index.ts rename to apps/web/core/components/license/modal/index.ts diff --git a/web/core/components/modules/analytics-sidebar/index.ts b/apps/web/core/components/modules/analytics-sidebar/index.ts similarity index 100% rename from web/core/components/modules/analytics-sidebar/index.ts rename to apps/web/core/components/modules/analytics-sidebar/index.ts diff --git a/web/core/components/modules/analytics-sidebar/issue-progress.tsx b/apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx similarity index 98% rename from web/core/components/modules/analytics-sidebar/issue-progress.tsx rename to apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx index 81ee66a80..13a491ab2 100644 --- a/web/core/components/modules/analytics-sidebar/issue-progress.tsx +++ b/apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx @@ -6,9 +6,9 @@ import { observer } from "mobx-react"; import { useSearchParams } from "next/navigation"; import { AlertCircle, ChevronUp, ChevronDown } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; -import { EIssueFilterType, EIssuesStoreType, EEstimateSystem } from "@plane/constants"; +import { EIssueFilterType, EEstimateSystem } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { IIssueFilterOptions, TModulePlotType } from "@plane/types"; +import { EIssuesStoreType, IIssueFilterOptions, TModulePlotType } from "@plane/types"; import { CustomSelect, Spinner } from "@plane/ui"; // components // constants diff --git a/web/core/components/modules/analytics-sidebar/progress-stats.tsx b/apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx similarity index 100% rename from web/core/components/modules/analytics-sidebar/progress-stats.tsx rename to apps/web/core/components/modules/analytics-sidebar/progress-stats.tsx diff --git a/web/core/components/modules/analytics-sidebar/root.tsx b/apps/web/core/components/modules/analytics-sidebar/root.tsx similarity index 91% rename from web/core/components/modules/analytics-sidebar/root.tsx rename to apps/web/core/components/modules/analytics-sidebar/root.tsx index 8142515b0..343077ac2 100644 --- a/web/core/components/modules/analytics-sidebar/root.tsx +++ b/apps/web/core/components/modules/analytics-sidebar/root.tsx @@ -12,6 +12,7 @@ import { EUserPermissionsLevel, EEstimateSystem, MODULE_TRACKER_EVENTS, + MODULE_TRACKER_ELEMENTS, } from "@plane/constants"; // plane types import { useTranslation } from "@plane/i18n"; @@ -22,15 +23,10 @@ import { Loader, LayersIcon, CustomSelect, ModuleStatusIcon, TOAST_TYPE, setToas // helpers import { getDate, renderFormattedPayloadDate } from "@plane/utils"; import { DateRangeDropdown, MemberDropdown } from "@/components/dropdowns"; -import { - ArchiveModuleModal, - DeleteModuleModal, - CreateUpdateModuleLinkModal, - ModuleAnalyticsProgress, - ModuleLinksList, -} from "@/components/modules"; +import { CreateUpdateModuleLinkModal, ModuleAnalyticsProgress, ModuleLinksList } from "@/components/modules"; +import { captureElementAndEvent, captureSuccess, captureError } from "@/helpers/event-tracker.helper"; // hooks -import { useModule, useEventTracker, useProjectEstimates, useUserPermissions } from "@/hooks/store"; +import { useModule, useProjectEstimates, useUserPermissions } from "@/hooks/store"; // plane web constants const defaultValues: Partial = { lead_id: "", @@ -50,8 +46,6 @@ type Props = { export const ModuleAnalyticsSidebar: React.FC = observer((props) => { const { moduleId, handleClose, isArchived } = props; // states - const [moduleDeleteModal, setModuleDeleteModal] = useState(false); - const [archiveModuleModal, setArchiveModuleModal] = useState(false); const [moduleLinkModal, setModuleLinkModal] = useState(false); const [selectedLinkToUpdate, setSelectedLinkToUpdate] = useState(null); // router @@ -62,7 +56,6 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { const { allowPermissions } = useUserPermissions(); const { getModuleById, updateModuleDetails, createModuleLink, updateModuleLink, deleteModuleLink } = useModule(); - const { captureModuleEvent, captureEvent } = useEventTracker(); const { areEstimateEnabledByProjectId, currentActiveEstimateId, estimateById } = useProjectEstimates(); // derived values @@ -79,15 +72,22 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { if (!workspaceSlug || !projectId || !moduleId) return; updateModuleDetails(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), data) .then((res) => { - captureModuleEvent({ - eventName: MODULE_TRACKER_EVENTS.update, - payload: { ...res, changed_properties: Object.keys(data)[0], element: "Right side-peek", state: "SUCCESS" }, + captureElementAndEvent({ + element: { + elementName: MODULE_TRACKER_ELEMENTS.RIGHT_SIDEBAR, + }, + event: { + eventName: MODULE_TRACKER_EVENTS.update, + payload: { id: res.id }, + state: "SUCCESS", + }, }); }) - .catch(() => { - captureModuleEvent({ + .catch((error) => { + captureError({ eventName: MODULE_TRACKER_EVENTS.update, - payload: { ...data, state: "FAILED" }, + payload: { id: moduleId }, + error, }); }); }; @@ -97,12 +97,20 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { const payload = { metadata: {}, ...formData }; - await createModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), payload).then(() => - captureEvent(MODULE_TRACKER_EVENTS.link.create, { - module_id: moduleId, - state: "SUCCESS", - }) - ); + await createModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), payload) + .then(() => + captureSuccess({ + eventName: MODULE_TRACKER_EVENTS.link.create, + payload: { id: moduleId }, + }) + ) + .catch((error) => { + captureError({ + eventName: MODULE_TRACKER_EVENTS.link.create, + payload: { id: moduleId }, + error, + }); + }); }; const handleUpdateLink = async (formData: ModuleLink, linkId: string) => { @@ -110,13 +118,20 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { const payload = { metadata: {}, ...formData }; - await updateModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId, payload).then( - () => - captureEvent(MODULE_TRACKER_EVENTS.link.update, { - module_id: moduleId, - state: "SUCCESS", + await updateModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId, payload) + .then(() => + captureSuccess({ + eventName: MODULE_TRACKER_EVENTS.link.update, + payload: { id: moduleId }, }) - ); + ) + .catch((error) => { + captureError({ + eventName: MODULE_TRACKER_EVENTS.link.update, + payload: { id: moduleId }, + error, + }); + }); }; const handleDeleteLink = async (linkId: string) => { @@ -124,9 +139,9 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { deleteModuleLink(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), linkId) .then(() => { - captureEvent(MODULE_TRACKER_EVENTS.link.delete, { - module_id: moduleId, - state: "SUCCESS", + captureSuccess({ + eventName: MODULE_TRACKER_EVENTS.link.delete, + payload: { id: moduleId }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -140,6 +155,10 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { title: "Error!", message: "Some error occurred", }); + captureError({ + eventName: MODULE_TRACKER_EVENTS.link.delete, + payload: { id: moduleId }, + }); }); }; @@ -213,16 +232,6 @@ export const ModuleAnalyticsSidebar: React.FC = observer((props) => { createLink={handleCreateLink} updateLink={handleUpdateLink} /> - {workspaceSlug && projectId && ( - setArchiveModuleModal(false)} - /> - )} - setModuleDeleteModal(false)} data={moduleDetails} /> <>
= observer((props) => { const router = useAppRouter(); const { workspaceSlug, projectId, moduleId, peekModule } = useParams(); // store hooks - const { captureModuleEvent } = useEventTracker(); const { deleteModule } = useModule(); const { t } = useTranslation(); @@ -51,9 +52,9 @@ export const DeleteModuleModal: React.FC = observer((props) => { title: "Success!", message: "Module deleted successfully.", }); - captureModuleEvent({ + captureSuccess({ eventName: MODULE_TRACKER_EVENTS.delete, - payload: { ...data, state: "SUCCESS" }, + payload: { id: data.id }, }); }) .catch((errors) => { @@ -66,9 +67,10 @@ export const DeleteModuleModal: React.FC = observer((props) => { type: TOAST_TYPE.ERROR, message: currentError.i18n_message && t(currentError.i18n_message), }); - captureModuleEvent({ + captureError({ eventName: MODULE_TRACKER_EVENTS.delete, - payload: { ...data, state: "FAILED" }, + payload: { id: data.id }, + error: errors, }); }) .finally(() => handleClose()); diff --git a/web/core/components/modules/dropdowns/filters/index.ts b/apps/web/core/components/modules/dropdowns/filters/index.ts similarity index 100% rename from web/core/components/modules/dropdowns/filters/index.ts rename to apps/web/core/components/modules/dropdowns/filters/index.ts diff --git a/web/core/components/modules/dropdowns/filters/lead.tsx b/apps/web/core/components/modules/dropdowns/filters/lead.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/lead.tsx rename to apps/web/core/components/modules/dropdowns/filters/lead.tsx diff --git a/web/core/components/modules/dropdowns/filters/members.tsx b/apps/web/core/components/modules/dropdowns/filters/members.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/members.tsx rename to apps/web/core/components/modules/dropdowns/filters/members.tsx diff --git a/web/core/components/modules/dropdowns/filters/root.tsx b/apps/web/core/components/modules/dropdowns/filters/root.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/root.tsx rename to apps/web/core/components/modules/dropdowns/filters/root.tsx diff --git a/web/core/components/modules/dropdowns/filters/start-date.tsx b/apps/web/core/components/modules/dropdowns/filters/start-date.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/start-date.tsx rename to apps/web/core/components/modules/dropdowns/filters/start-date.tsx diff --git a/web/core/components/modules/dropdowns/filters/status.tsx b/apps/web/core/components/modules/dropdowns/filters/status.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/status.tsx rename to apps/web/core/components/modules/dropdowns/filters/status.tsx diff --git a/web/core/components/modules/dropdowns/filters/target-date.tsx b/apps/web/core/components/modules/dropdowns/filters/target-date.tsx similarity index 100% rename from web/core/components/modules/dropdowns/filters/target-date.tsx rename to apps/web/core/components/modules/dropdowns/filters/target-date.tsx diff --git a/web/core/components/modules/dropdowns/index.ts b/apps/web/core/components/modules/dropdowns/index.ts similarity index 100% rename from web/core/components/modules/dropdowns/index.ts rename to apps/web/core/components/modules/dropdowns/index.ts diff --git a/web/core/components/modules/dropdowns/order-by.tsx b/apps/web/core/components/modules/dropdowns/order-by.tsx similarity index 100% rename from web/core/components/modules/dropdowns/order-by.tsx rename to apps/web/core/components/modules/dropdowns/order-by.tsx diff --git a/web/core/components/modules/form.tsx b/apps/web/core/components/modules/form.tsx similarity index 98% rename from web/core/components/modules/form.tsx rename to apps/web/core/components/modules/form.tsx index 7a702c584..aab66235d 100644 --- a/web/core/components/modules/form.tsx +++ b/apps/web/core/components/modules/form.tsx @@ -93,7 +93,7 @@ export const ModuleForm: React.FC = (props) => { }} multiple={false} buttonVariant="border-with-text" - renderCondition={(project) => !!projectsWithCreatePermissions?.[project.id]} + renderCondition={(projectId) => !!projectsWithCreatePermissions?.[projectId]} tabIndex={getIndex("cover_image")} />
diff --git a/web/core/components/modules/gantt-chart/blocks.tsx b/apps/web/core/components/modules/gantt-chart/blocks.tsx similarity index 100% rename from web/core/components/modules/gantt-chart/blocks.tsx rename to apps/web/core/components/modules/gantt-chart/blocks.tsx diff --git a/web/core/components/modules/gantt-chart/index.ts b/apps/web/core/components/modules/gantt-chart/index.ts similarity index 100% rename from web/core/components/modules/gantt-chart/index.ts rename to apps/web/core/components/modules/gantt-chart/index.ts diff --git a/web/core/components/modules/gantt-chart/modules-list-layout.tsx b/apps/web/core/components/modules/gantt-chart/modules-list-layout.tsx similarity index 96% rename from web/core/components/modules/gantt-chart/modules-list-layout.tsx rename to apps/web/core/components/modules/gantt-chart/modules-list-layout.tsx index c87f1c4d5..1260d5621 100644 --- a/web/core/components/modules/gantt-chart/modules-list-layout.tsx +++ b/apps/web/core/components/modules/gantt-chart/modules-list-layout.tsx @@ -3,10 +3,7 @@ import { useParams } from "next/navigation"; // PLane import { IBlockUpdateData, IBlockUpdateDependencyData, IModule } from "@plane/types"; // components -import { - GanttChartRoot, - ModuleGanttSidebar, -} from "@/components/gantt-chart"; +import { GanttChartRoot, ModuleGanttSidebar } from "@/components/gantt-chart"; import { ETimeLineTypeType, TimeLineTypeContext } from "@/components/gantt-chart/contexts"; import { ModuleGanttBlock } from "@/components/modules"; // hooks diff --git a/web/core/components/modules/index.ts b/apps/web/core/components/modules/index.ts similarity index 100% rename from web/core/components/modules/index.ts rename to apps/web/core/components/modules/index.ts diff --git a/web/core/components/modules/links/create-update-modal.tsx b/apps/web/core/components/modules/links/create-update-modal.tsx similarity index 100% rename from web/core/components/modules/links/create-update-modal.tsx rename to apps/web/core/components/modules/links/create-update-modal.tsx diff --git a/web/core/components/modules/links/index.ts b/apps/web/core/components/modules/links/index.ts similarity index 100% rename from web/core/components/modules/links/index.ts rename to apps/web/core/components/modules/links/index.ts diff --git a/web/core/components/modules/links/list-item.tsx b/apps/web/core/components/modules/links/list-item.tsx similarity index 94% rename from web/core/components/modules/links/list-item.tsx rename to apps/web/core/components/modules/links/list-item.tsx index 283062cc7..2a83514d2 100644 --- a/web/core/components/modules/links/list-item.tsx +++ b/apps/web/core/components/modules/links/list-item.tsx @@ -1,6 +1,7 @@ import { observer } from "mobx-react"; import { Copy, Pencil, Trash2 } from "lucide-react"; // plane types +import { MODULE_TRACKER_ELEMENTS } from "@plane/constants"; import { ILinkDetails } from "@plane/types"; // plane ui import { setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; @@ -58,6 +59,7 @@ export const ModulesLinksListItem: React.FC = observer((props) => {
)} - + {MENU_ITEMS.map((item) => { if (item.shouldRender === false) return null; @@ -176,6 +198,9 @@ export const ModuleQuickActions: React.FC = observer((props) => { onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ + elementName: MODULE_TRACKER_ELEMENTS.QUICK_ACTIONS, + }); item.action(); }} className={cn( diff --git a/web/core/components/modules/select/index.ts b/apps/web/core/components/modules/select/index.ts similarity index 100% rename from web/core/components/modules/select/index.ts rename to apps/web/core/components/modules/select/index.ts diff --git a/web/core/components/modules/select/status.tsx b/apps/web/core/components/modules/select/status.tsx similarity index 100% rename from web/core/components/modules/select/status.tsx rename to apps/web/core/components/modules/select/status.tsx diff --git a/web/core/components/modules/sidebar-select/index.ts b/apps/web/core/components/modules/sidebar-select/index.ts similarity index 100% rename from web/core/components/modules/sidebar-select/index.ts rename to apps/web/core/components/modules/sidebar-select/index.ts diff --git a/web/core/components/modules/sidebar-select/select-status.tsx b/apps/web/core/components/modules/sidebar-select/select-status.tsx similarity index 100% rename from web/core/components/modules/sidebar-select/select-status.tsx rename to apps/web/core/components/modules/sidebar-select/select-status.tsx diff --git a/web/core/components/onboarding/create-or-join-workspaces.tsx b/apps/web/core/components/onboarding/create-or-join-workspaces.tsx similarity index 100% rename from web/core/components/onboarding/create-or-join-workspaces.tsx rename to apps/web/core/components/onboarding/create-or-join-workspaces.tsx diff --git a/web/core/components/onboarding/create-workspace.tsx b/apps/web/core/components/onboarding/create-workspace.tsx similarity index 93% rename from web/core/components/onboarding/create-workspace.tsx rename to apps/web/core/components/onboarding/create-workspace.tsx index 157beec74..e37e3c311 100644 --- a/web/core/components/onboarding/create-workspace.tsx +++ b/apps/web/core/components/onboarding/create-workspace.tsx @@ -5,10 +5,10 @@ import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // constants import { - ONBOARDING_TRACKER_EVENTS, ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_TRACKER_EVENTS, + WORKSPACE_TRACKER_ELEMENTS, } from "@plane/constants"; // types import { useTranslation } from "@plane/i18n"; @@ -16,7 +16,8 @@ import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; // ui import { Button, CustomSelect, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { useEventTracker, useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -41,7 +42,6 @@ export const CreateWorkspace: React.FC = observer((props) => { const { updateUserProfile } = useUserProfile(); const { fetchCurrentUserSettings } = useUserSettings(); const { createWorkspace, fetchWorkspaces } = useWorkspace(); - const { captureWorkspaceEvent } = useEventTracker(); // form info const { handleSubmit, @@ -73,26 +73,18 @@ export const CreateWorkspace: React.FC = observer((props) => { title: t("workspace_creation.toast.success.title"), message: t("workspace_creation.toast.success.message"), }); - captureWorkspaceEvent({ + captureSuccess({ eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - ...workspaceResponse, - state: "SUCCESS", - first_time: true, - element: ONBOARDING_TRACKER_EVENTS.root, - }, + payload: { slug: formData.slug }, }); await fetchWorkspaces(); await completeStep(workspaceResponse.id); }) .catch(() => { - captureWorkspaceEvent({ + captureError({ eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - state: "FAILED", - first_time: true, - element: ONBOARDING_TRACKER_EVENTS.root, - }, + payload: { slug: formData.slug }, + error: new Error("Error creating workspace"), }); setToast({ type: TOAST_TYPE.ERROR, @@ -290,7 +282,14 @@ export const CreateWorkspace: React.FC = observer((props) => { )}
- diff --git a/web/core/components/onboarding/header.tsx b/apps/web/core/components/onboarding/header.tsx similarity index 100% rename from web/core/components/onboarding/header.tsx rename to apps/web/core/components/onboarding/header.tsx diff --git a/web/core/components/onboarding/index.ts b/apps/web/core/components/onboarding/index.ts similarity index 100% rename from web/core/components/onboarding/index.ts rename to apps/web/core/components/onboarding/index.ts diff --git a/web/core/components/onboarding/invitations.tsx b/apps/web/core/components/onboarding/invitations.tsx similarity index 84% rename from web/core/components/onboarding/invitations.tsx rename to apps/web/core/components/onboarding/invitations.tsx index 349b91431..3d16af81b 100644 --- a/web/core/components/onboarding/invitations.tsx +++ b/apps/web/core/components/onboarding/invitations.tsx @@ -2,17 +2,18 @@ import React, { useState } from "react"; // plane imports -import { ROLE, MEMBER_TRACKER_EVENTS } from "@plane/constants"; +import { ROLE, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; // types import { IWorkspaceMemberInvitation } from "@plane/types"; // ui import { Button, Checkbox, Spinner } from "@plane/ui"; -import { truncateText, getUserRole } from "@plane/utils"; +import { truncateText } from "@plane/utils"; // constants // helpers import { WorkspaceLogo } from "@/components/workspace/logo"; // hooks -import { useEventTracker, useUserSettings, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useUserSettings, useWorkspace } from "@/hooks/store"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -29,7 +30,6 @@ export const Invitations: React.FC = (props) => { const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false); const [invitationsRespond, setInvitationsRespond] = useState([]); // store hooks - const { captureEvent } = useEventTracker(); const { fetchWorkspaces } = useWorkspace(); const { fetchCurrentUserSettings } = useUserSettings(); @@ -50,26 +50,23 @@ export const Invitations: React.FC = (props) => { try { await workspaceService.joinWorkspaces({ invitations: invitationsRespond }); - captureEvent(MEMBER_TRACKER_EVENTS.accept, { - member_id: invitation?.id, - role: getUserRole(invitation?.role as any), - project_id: undefined, - accepted_from: "App", - state: "SUCCESS", - element: "Workspace invitations page", + captureSuccess({ + eventName: MEMBER_TRACKER_EVENTS.accept, + payload: { + member_id: invitation?.id, + }, }); await fetchWorkspaces(); await fetchCurrentUserSettings(); await handleNextStep(); - } catch (error) { + } catch (error: any) { console.error(error); - captureEvent(MEMBER_TRACKER_EVENTS.accept, { - member_id: invitation?.id, - role: getUserRole(invitation?.role as any), - project_id: undefined, - accepted_from: "App", - state: "FAILED", - element: "Workspace invitations page", + captureError({ + eventName: MEMBER_TRACKER_EVENTS.accept, + payload: { + member_id: invitation?.id, + }, + error: error, }); setIsJoiningWorkspaces(false); } @@ -117,6 +114,7 @@ export const Invitations: React.FC = (props) => { className="w-full" onClick={submitInvitations} disabled={isJoiningWorkspaces || !invitationsRespond.length} + data-ph-element={MEMBER_TRACKER_ELEMENTS.ONBOARDING_JOIN_WORKSPACE} > {isJoiningWorkspaces ? : "Continue to workspace"} diff --git a/web/core/components/onboarding/invite-members.tsx b/apps/web/core/components/onboarding/invite-members.tsx similarity index 95% rename from web/core/components/onboarding/invite-members.tsx rename to apps/web/core/components/onboarding/invite-members.tsx index 6865b7856..bb7b24f7a 100644 --- a/web/core/components/onboarding/invite-members.tsx +++ b/apps/web/core/components/onboarding/invite-members.tsx @@ -20,7 +20,7 @@ import { usePopper } from "react-popper"; import { Check, ChevronDown, Plus, XCircle } from "lucide-react"; import { Listbox } from "@headlessui/react"; // plane imports -import { ROLE, ROLE_DETAILS, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants"; +import { ROLE, ROLE_DETAILS, EUserPermissions, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // types import { IUser, IWorkspace } from "@plane/types"; @@ -28,9 +28,8 @@ import { IUser, IWorkspace } from "@plane/types"; import { Button, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui"; // constants // helpers -import { getUserRole } from "@plane/utils"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; // services import { WorkspaceService } from "@/plane-web/services"; // assets @@ -276,8 +275,6 @@ export const InviteMembers: React.FC = (props) => { const [isInvitationDisabled, setIsInvitationDisabled] = useState(true); const { resolvedTheme } = useTheme(); - // store hooks - const { captureEvent } = useEventTracker(); const { control, @@ -311,16 +308,11 @@ export const InviteMembers: React.FC = (props) => { })), }) .then(async () => { - captureEvent(MEMBER_TRACKER_EVENTS.invite, { - emails: [ - ...payload.emails.map((email) => ({ - email: email.email, - role: getUserRole(email.role), - })), - ], - project_id: undefined, - state: "SUCCESS", - element: "Onboarding", + captureSuccess({ + eventName: MEMBER_TRACKER_EVENTS.invite, + payload: { + workspace: workspace.slug, + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -331,10 +323,12 @@ export const InviteMembers: React.FC = (props) => { await nextStep(); }) .catch((err) => { - captureEvent(MEMBER_TRACKER_EVENTS.invite, { - project_id: undefined, - state: "FAILED", - element: "Onboarding", + captureError({ + eventName: MEMBER_TRACKER_EVENTS.invite, + payload: { + workspace: workspace.slug, + }, + error: err, }); setToast({ type: TOAST_TYPE.ERROR, @@ -426,6 +420,7 @@ export const InviteMembers: React.FC = (props) => { size="lg" className="w-full" disabled={isInvitationDisabled || !isValid || isSubmitting} + data-ph-element={MEMBER_TRACKER_ELEMENTS.ONBOARDING_INVITE_MEMBER} > {isSubmitting ? : "Continue"} diff --git a/web/core/components/onboarding/profile-setup.tsx b/apps/web/core/components/onboarding/profile-setup.tsx similarity index 95% rename from web/core/components/onboarding/profile-setup.tsx rename to apps/web/core/components/onboarding/profile-setup.tsx index 68c4d7c05..8fbafd6af 100644 --- a/web/core/components/onboarding/profile-setup.tsx +++ b/apps/web/core/components/onboarding/profile-setup.tsx @@ -6,7 +6,7 @@ import Image from "next/image"; import { useTheme } from "next-themes"; import { Controller, useForm } from "react-hook-form"; import { Eye, EyeOff } from "lucide-react"; -import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_EVENTS, USER_TRACKER_EVENTS } from "@plane/constants"; +import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_ELEMENTS, USER_TRACKER_EVENTS } from "@plane/constants"; // types import { useTranslation } from "@plane/i18n"; import { IUser, TUserProfile, TOnboardingSteps } from "@plane/types"; @@ -20,7 +20,8 @@ import { OnboardingHeader, SwitchAccountDropdown } from "@/components/onboarding // constants // helpers // hooks -import { useEventTracker, useUser, useUserProfile } from "@/hooks/store"; +import { captureError, captureSuccess, captureView } from "@/helpers/event-tracker.helper"; +import { useUser, useUserProfile } from "@/hooks/store"; // assets import ProfileSetupDark from "@/public/onboarding/profile-setup-dark.webp"; import ProfileSetupLight from "@/public/onboarding/profile-setup-light.webp"; @@ -98,7 +99,6 @@ export const ProfileSetup: React.FC = observer((props) => { // store hooks const { updateCurrentUser } = useUser(); const { updateUserProfile } = useUserProfile(); - const { captureEvent } = useEventTracker(); // form info const { getValues, @@ -143,11 +143,12 @@ export const ProfileSetup: React.FC = observer((props) => { updateUserProfile(profileUpdatePayload), totalSteps > 2 && stepChange({ profile_complete: true }), ]); - captureEvent(USER_TRACKER_EVENTS.add_details, { - use_case: formData.use_case, - role: formData.role, - state: "SUCCESS", - element: ONBOARDING_TRACKER_EVENTS.step_1, + captureSuccess({ + eventName: USER_TRACKER_EVENTS.add_details, + payload: { + use_case: formData.use_case, + role: formData.role, + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -159,9 +160,8 @@ export const ProfileSetup: React.FC = observer((props) => { finishOnboarding(); } } catch { - captureEvent(USER_TRACKER_EVENTS.add_details, { - state: "FAILED", - element: ONBOARDING_TRACKER_EVENTS.step_1, + captureError({ + eventName: USER_TRACKER_EVENTS.add_details, }); setToast({ type: TOAST_TYPE.ERROR, @@ -183,9 +183,8 @@ export const ProfileSetup: React.FC = observer((props) => { formData.password && handleSetPassword(formData.password), ]).then(() => setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION)); } catch { - captureEvent(USER_TRACKER_EVENTS.add_details, { - state: "FAILED", - element: ONBOARDING_TRACKER_EVENTS.step_1, + captureError({ + eventName: USER_TRACKER_EVENTS.add_details, }); setToast({ type: TOAST_TYPE.ERROR, @@ -205,11 +204,12 @@ export const ProfileSetup: React.FC = observer((props) => { updateUserProfile(profileUpdatePayload), totalSteps > 2 && stepChange({ profile_complete: true }), ]); - captureEvent(USER_TRACKER_EVENTS.add_details, { - use_case: formData.use_case, - role: formData.role, - state: "SUCCESS", - element: ONBOARDING_TRACKER_EVENTS.step_2, + captureSuccess({ + eventName: USER_TRACKER_EVENTS.add_details, + payload: { + use_case: formData.use_case, + role: formData.role, + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -221,9 +221,8 @@ export const ProfileSetup: React.FC = observer((props) => { finishOnboarding(); } } catch { - captureEvent(USER_TRACKER_EVENTS.add_details, { - state: "FAILED", - element: ONBOARDING_TRACKER_EVENTS.step_2, + captureError({ + eventName: USER_TRACKER_EVENTS.add_details, }); setToast({ type: TOAST_TYPE.ERROR, @@ -235,6 +234,9 @@ export const ProfileSetup: React.FC = observer((props) => { const onSubmit = async (formData: TProfileSetupFormValues) => { if (!user) return; + captureView({ + elementName: ONBOARDING_TRACKER_ELEMENTS.PROFILE_SETUP_FORM, + }); if (profileSetupStep === EProfileSetupSteps.ALL) await handleSubmitProfileSetup(formData); if (profileSetupStep === EProfileSetupSteps.USER_DETAILS) await handleSubmitUserDetail(formData); if (profileSetupStep === EProfileSetupSteps.USER_PERSONALIZATION) await handleSubmitUserPersonalization(formData); diff --git a/web/core/components/onboarding/step-indicator.tsx b/apps/web/core/components/onboarding/step-indicator.tsx similarity index 100% rename from web/core/components/onboarding/step-indicator.tsx rename to apps/web/core/components/onboarding/step-indicator.tsx diff --git a/web/core/components/onboarding/switch-account-dropdown.tsx b/apps/web/core/components/onboarding/switch-account-dropdown.tsx similarity index 100% rename from web/core/components/onboarding/switch-account-dropdown.tsx rename to apps/web/core/components/onboarding/switch-account-dropdown.tsx diff --git a/web/core/components/onboarding/switch-account-modal.tsx b/apps/web/core/components/onboarding/switch-account-modal.tsx similarity index 100% rename from web/core/components/onboarding/switch-account-modal.tsx rename to apps/web/core/components/onboarding/switch-account-modal.tsx diff --git a/web/core/components/onboarding/tour/index.ts b/apps/web/core/components/onboarding/tour/index.ts similarity index 100% rename from web/core/components/onboarding/tour/index.ts rename to apps/web/core/components/onboarding/tour/index.ts diff --git a/web/core/components/onboarding/tour/root.tsx b/apps/web/core/components/onboarding/tour/root.tsx similarity index 91% rename from web/core/components/onboarding/tour/root.tsx rename to apps/web/core/components/onboarding/tour/root.tsx index 90a183e0b..167ee752f 100644 --- a/web/core/components/onboarding/tour/root.tsx +++ b/apps/web/core/components/onboarding/tour/root.tsx @@ -5,13 +5,14 @@ import { observer } from "mobx-react"; import Image, { StaticImageData } from "next/image"; import { X } from "lucide-react"; // ui -import { PRODUCT_TOUR_TRACKER_EVENTS } from "@plane/constants"; +import { PRODUCT_TOUR_TRACKER_ELEMENTS } from "@plane/constants"; import { Button } from "@plane/ui"; // components import { TourSidebar } from "@/components/onboarding"; // constants // hooks -import { useCommandPalette, useEventTracker, useUser } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useCommandPalette, useUser } from "@/hooks/store"; // assets import CyclesTour from "@/public/onboarding/cycles.webp"; import IssuesTour from "@/public/onboarding/issues.webp"; @@ -85,7 +86,6 @@ export const TourRoot: React.FC = observer((props) => { const [step, setStep] = useState("welcome"); // store hooks const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement, captureEvent } = useEventTracker(); const { data: currentUser } = useUser(); const currentStepIndex = TOUR_STEPS.findIndex((tourStep) => tourStep.key === step); @@ -112,7 +112,9 @@ export const TourRoot: React.FC = observer((props) => { ); export const OutlineHeading2 = ({ marking, onClick }: THeadingComponentProps) => ( - ); export const OutlineHeading3 = ({ marking, onClick }: THeadingComponentProps) => ( - ); diff --git a/web/core/components/pages/editor/summary/index.ts b/apps/web/core/components/pages/editor/summary/index.ts similarity index 100% rename from web/core/components/pages/editor/summary/index.ts rename to apps/web/core/components/pages/editor/summary/index.ts diff --git a/web/core/components/pages/editor/title.tsx b/apps/web/core/components/pages/editor/title.tsx similarity index 100% rename from web/core/components/pages/editor/title.tsx rename to apps/web/core/components/pages/editor/title.tsx diff --git a/web/core/components/pages/editor/toolbar/color-dropdown.tsx b/apps/web/core/components/pages/editor/toolbar/color-dropdown.tsx similarity index 100% rename from web/core/components/pages/editor/toolbar/color-dropdown.tsx rename to apps/web/core/components/pages/editor/toolbar/color-dropdown.tsx diff --git a/web/core/components/pages/editor/toolbar/index.ts b/apps/web/core/components/pages/editor/toolbar/index.ts similarity index 79% rename from web/core/components/pages/editor/toolbar/index.ts rename to apps/web/core/components/pages/editor/toolbar/index.ts index 66652b2db..2c36785bd 100644 --- a/web/core/components/pages/editor/toolbar/index.ts +++ b/apps/web/core/components/pages/editor/toolbar/index.ts @@ -1,5 +1,4 @@ export * from "./color-dropdown"; -export * from "./info-popover"; export * from "./options-dropdown"; export * from "./root"; export * from "./toolbar"; diff --git a/web/core/components/pages/editor/toolbar/options-dropdown.tsx b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx similarity index 85% rename from web/core/components/pages/editor/toolbar/options-dropdown.tsx rename to apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx index 407ee03c4..a5ba7c606 100644 --- a/web/core/components/pages/editor/toolbar/options-dropdown.tsx +++ b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx @@ -2,21 +2,22 @@ import { useMemo, useState } from "react"; import { observer } from "mobx-react"; -import { useRouter } from "next/navigation"; import { ArrowUpToLine, Clipboard, History } from "lucide-react"; // plane imports import { TContextMenuItem, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui"; -// components import { copyTextToClipboard } from "@plane/utils"; +// components import { ExportPageModal, PageActions, TPageActions } from "@/components/pages"; -// helpers // hooks +import { useAppRouter } from "@/hooks/use-app-router"; import { usePageFilters } from "@/hooks/use-page-filters"; import { useQueryParams } from "@/hooks/use-query-params"; -// plane web hooks +// plane web imports +import { TPageNavigationPaneTab } from "@/plane-web/components/pages/navigation-pane"; import { EPageStoreType } from "@/plane-web/hooks/store"; // store import { TPageInstance } from "@/store/pages/base-page"; +import { PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM } from "../../navigation-pane"; type Props = { page: TPageInstance; @@ -27,13 +28,17 @@ export const PageOptionsDropdown: React.FC = observer((props) => { const { page, storeType } = props; // states const [isExportModalOpen, setIsExportModalOpen] = useState(false); - // router - const router = useRouter(); + // navigation + const router = useAppRouter(); // store values - const { name, isContentEditable, editorRef } = page; + const { + name, + isContentEditable, + editor: { editorRef }, + } = page; // page filters const { isFullWidth, handleFullWidth, isStickyToolbarEnabled, handleStickyToolbar } = usePageFilters(); - // update query params + // query params const { updateQueryParams } = useQueryParams(); // menu items list const EXTRA_MENU_OPTIONS: (TContextMenuItem & { key: TPageActions })[] = useMemo( @@ -80,9 +85,11 @@ export const PageOptionsDropdown: React.FC = observer((props) => { { key: "version-history", action: () => { - // add query param, version=current to the route + // update query param to show info tab in navigation pane const updatedRoute = updateQueryParams({ - paramsToAdd: { version: "current" }, + paramsToAdd: { + [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM]: "info" satisfies TPageNavigationPaneTab, + }, }); router.push(updatedRoute); }, diff --git a/apps/web/core/components/pages/editor/toolbar/root.tsx b/apps/web/core/components/pages/editor/toolbar/root.tsx new file mode 100644 index 000000000..e779c618e --- /dev/null +++ b/apps/web/core/components/pages/editor/toolbar/root.tsx @@ -0,0 +1,88 @@ +import { observer } from "mobx-react"; +import { PanelRight } from "lucide-react"; +// plane imports +import { useTranslation } from "@plane/i18n"; +import { Tooltip } from "@plane/ui"; +import { cn } from "@plane/utils"; +// components +import { PageToolbar } from "@/components/pages"; +// helpers +// hooks +import { usePageFilters } from "@/hooks/use-page-filters"; +// plane web components +import { PageCollaboratorsList } from "@/plane-web/components/pages/header/collaborators-list"; +// store +import { TPageInstance } from "@/store/pages/base-page"; + +type Props = { + handleOpenNavigationPane: () => void; + isNavigationPaneOpen: boolean; + page: TPageInstance; +}; + +export const PageEditorToolbarRoot: React.FC = observer((props) => { + const { handleOpenNavigationPane, isNavigationPaneOpen, page } = props; + // translation + const { t } = useTranslation(); + // derived values + const { + isContentEditable, + editor: { editorRef }, + } = page; + // page filters + const { isFullWidth, isStickyToolbarEnabled } = usePageFilters(); + // derived values + const shouldHideToolbar = !isStickyToolbarEnabled || !isContentEditable; + + return ( + <> +
+
+
+ {editorRef && } +
+ + {!isNavigationPaneOpen && ( + + )} +
+
+
+
+ {shouldHideToolbar && ( +
+ {!isNavigationPaneOpen && ( + + + + )} +
+ )} + + ); +}); diff --git a/web/core/components/pages/editor/toolbar/toolbar.tsx b/apps/web/core/components/pages/editor/toolbar/toolbar.tsx similarity index 100% rename from web/core/components/pages/editor/toolbar/toolbar.tsx rename to apps/web/core/components/pages/editor/toolbar/toolbar.tsx diff --git a/web/core/components/pages/header/actions.tsx b/apps/web/core/components/pages/header/actions.tsx similarity index 92% rename from web/core/components/pages/header/actions.tsx rename to apps/web/core/components/pages/header/actions.tsx index 6c6cb2f6c..ccf07191a 100644 --- a/web/core/components/pages/header/actions.tsx +++ b/apps/web/core/components/pages/header/actions.tsx @@ -2,7 +2,7 @@ import { observer } from "mobx-react"; // components -import { PageInfoPopover, PageOptionsDropdown } from "@/components/pages"; +import { PageOptionsDropdown } from "@/components/pages"; // plane web components import { PageLockControl } from "@/plane-web/components/pages/header/lock-control"; import { PageMoveControl } from "@/plane-web/components/pages/header/move-control"; @@ -31,7 +31,6 @@ export const PageHeaderActions: React.FC = observer((props) => { - diff --git a/web/core/components/pages/header/archived-badge.tsx b/apps/web/core/components/pages/header/archived-badge.tsx similarity index 100% rename from web/core/components/pages/header/archived-badge.tsx rename to apps/web/core/components/pages/header/archived-badge.tsx diff --git a/web/core/components/pages/header/copy-link-control.tsx b/apps/web/core/components/pages/header/copy-link-control.tsx similarity index 100% rename from web/core/components/pages/header/copy-link-control.tsx rename to apps/web/core/components/pages/header/copy-link-control.tsx diff --git a/web/core/components/pages/header/favorite-control.tsx b/apps/web/core/components/pages/header/favorite-control.tsx similarity index 70% rename from web/core/components/pages/header/favorite-control.tsx rename to apps/web/core/components/pages/header/favorite-control.tsx index 948ce4f52..e94c53bb4 100644 --- a/web/core/components/pages/header/favorite-control.tsx +++ b/apps/web/core/components/pages/header/favorite-control.tsx @@ -1,6 +1,10 @@ import { observer } from "mobx-react"; -// plane imports +// constants +import { PROJECT_PAGE_TRACKER_ELEMENTS } from "@plane/constants"; +// ui import { FavoriteStar } from "@plane/ui"; +// helpers +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { usePageOperations } from "@/hooks/use-page-operations"; // store @@ -23,7 +27,12 @@ export const PageFavoriteControl = observer(({ page }: Props) => { return ( { + captureClick({ + elementName: PROJECT_PAGE_TRACKER_ELEMENTS.FAVORITE_BUTTON, + }); + pageOperations.toggleFavorite(); + }} buttonClassName="flex-shrink-0 size-6 group rounded hover:bg-custom-background-80 transition-colors" iconClassName="size-3.5 text-custom-text-200 group-hover:text-custom-text-10" /> diff --git a/web/core/components/pages/list/filters/index.ts b/apps/web/core/components/pages/header/index.ts similarity index 100% rename from web/core/components/pages/list/filters/index.ts rename to apps/web/core/components/pages/header/index.ts diff --git a/web/core/components/pages/header/offline-badge.tsx b/apps/web/core/components/pages/header/offline-badge.tsx similarity index 100% rename from web/core/components/pages/header/offline-badge.tsx rename to apps/web/core/components/pages/header/offline-badge.tsx diff --git a/web/core/components/pages/header/root.tsx b/apps/web/core/components/pages/header/root.tsx similarity index 100% rename from web/core/components/pages/header/root.tsx rename to apps/web/core/components/pages/header/root.tsx diff --git a/web/core/components/pages/index.ts b/apps/web/core/components/pages/index.ts similarity index 100% rename from web/core/components/pages/index.ts rename to apps/web/core/components/pages/index.ts diff --git a/web/core/components/settings/project/sidebar/index.ts b/apps/web/core/components/pages/list/applied-filters/index.ts similarity index 100% rename from web/core/components/settings/project/sidebar/index.ts rename to apps/web/core/components/pages/list/applied-filters/index.ts diff --git a/web/core/components/pages/list/applied-filters/root.tsx b/apps/web/core/components/pages/list/applied-filters/root.tsx similarity index 100% rename from web/core/components/pages/list/applied-filters/root.tsx rename to apps/web/core/components/pages/list/applied-filters/root.tsx diff --git a/web/core/components/pages/list/block-item-action.tsx b/apps/web/core/components/pages/list/block-item-action.tsx similarity index 91% rename from web/core/components/pages/list/block-item-action.tsx rename to apps/web/core/components/pages/list/block-item-action.tsx index 4b382b488..c3cb980e1 100644 --- a/web/core/components/pages/list/block-item-action.tsx +++ b/apps/web/core/components/pages/list/block-item-action.tsx @@ -3,12 +3,15 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { Earth, Info, Lock, Minus } from "lucide-react"; +// constants +import { PROJECT_PAGE_TRACKER_ELEMENTS } from "@plane/constants"; // ui import { Avatar, FavoriteStar, Tooltip } from "@plane/ui"; import { renderFormattedDate, getFileURL } from "@plane/utils"; // components import { PageActions } from "@/components/pages"; // helpers +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks import { useMember } from "@/hooks/store"; import { usePageOperations } from "@/hooks/use-page-operations"; @@ -64,6 +67,9 @@ export const BlockItemAction: FC = observer((props) => { onClick={(e) => { e.preventDefault(); e.stopPropagation(); + captureClick({ + elementName: PROJECT_PAGE_TRACKER_ELEMENTS.FAVORITE_BUTTON, + }); pageOperations.toggleFavorite(); }} selected={is_favorite} diff --git a/web/core/components/pages/list/block.tsx b/apps/web/core/components/pages/list/block.tsx similarity index 100% rename from web/core/components/pages/list/block.tsx rename to apps/web/core/components/pages/list/block.tsx diff --git a/web/core/components/settings/sidebar/index.ts b/apps/web/core/components/pages/list/filters/index.ts similarity index 100% rename from web/core/components/settings/sidebar/index.ts rename to apps/web/core/components/pages/list/filters/index.ts diff --git a/web/core/components/pages/list/filters/root.tsx b/apps/web/core/components/pages/list/filters/root.tsx similarity index 100% rename from web/core/components/pages/list/filters/root.tsx rename to apps/web/core/components/pages/list/filters/root.tsx diff --git a/web/core/components/pages/list/index.ts b/apps/web/core/components/pages/list/index.ts similarity index 100% rename from web/core/components/pages/list/index.ts rename to apps/web/core/components/pages/list/index.ts diff --git a/web/core/components/pages/list/order-by.tsx b/apps/web/core/components/pages/list/order-by.tsx similarity index 100% rename from web/core/components/pages/list/order-by.tsx rename to apps/web/core/components/pages/list/order-by.tsx diff --git a/web/core/components/pages/list/root.tsx b/apps/web/core/components/pages/list/root.tsx similarity index 100% rename from web/core/components/pages/list/root.tsx rename to apps/web/core/components/pages/list/root.tsx diff --git a/web/core/components/pages/list/search-input.tsx b/apps/web/core/components/pages/list/search-input.tsx similarity index 100% rename from web/core/components/pages/list/search-input.tsx rename to apps/web/core/components/pages/list/search-input.tsx diff --git a/web/core/components/pages/list/tab-navigation.tsx b/apps/web/core/components/pages/list/tab-navigation.tsx similarity index 100% rename from web/core/components/pages/list/tab-navigation.tsx rename to apps/web/core/components/pages/list/tab-navigation.tsx diff --git a/web/core/components/pages/loaders/index.ts b/apps/web/core/components/pages/loaders/index.ts similarity index 100% rename from web/core/components/pages/loaders/index.ts rename to apps/web/core/components/pages/loaders/index.ts diff --git a/web/core/components/pages/loaders/page-content-loader.tsx b/apps/web/core/components/pages/loaders/page-content-loader.tsx similarity index 100% rename from web/core/components/pages/loaders/page-content-loader.tsx rename to apps/web/core/components/pages/loaders/page-content-loader.tsx diff --git a/web/core/components/pages/loaders/page-loader.tsx b/apps/web/core/components/pages/loaders/page-loader.tsx similarity index 100% rename from web/core/components/pages/loaders/page-loader.tsx rename to apps/web/core/components/pages/loaders/page-loader.tsx diff --git a/web/core/components/pages/modals/create-page-modal.tsx b/apps/web/core/components/pages/modals/create-page-modal.tsx similarity index 89% rename from web/core/components/pages/modals/create-page-modal.tsx rename to apps/web/core/components/pages/modals/create-page-modal.tsx index 894e1b70d..9e7472a58 100644 --- a/web/core/components/pages/modals/create-page-modal.tsx +++ b/apps/web/core/components/pages/modals/create-page-modal.tsx @@ -7,7 +7,7 @@ import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; // components import { PageForm } from "@/components/pages"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureSuccess, captureError } from "@/helpers/event-tracker.helper"; import { useAppRouter } from "@/hooks/use-app-router"; // plane web hooks import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store"; @@ -42,7 +42,6 @@ export const CreatePageModal: FC = (props) => { const router = useAppRouter(); // store hooks const { createPage } = usePageStore(storeType); - const { capturePageEvent } = useEventTracker(); const handlePageFormData = (key: T, value: TPage[T]) => setPageFormData((prev) => ({ ...prev, [key]: value })); @@ -62,22 +61,19 @@ export const CreatePageModal: FC = (props) => { try { const pageData = await createPage(pageFormData); if (pageData) { - capturePageEvent({ + captureSuccess({ eventName: PROJECT_PAGE_TRACKER_EVENTS.create, payload: { - ...pageData, - state: "SUCCESS", + id: pageData.id, }, }); handleStateClear(); if (redirectionEnabled) router.push(`/${workspaceSlug}/projects/${projectId}/pages/${pageData.id}`); } - } catch { - capturePageEvent({ + } catch (error: any) { + captureError({ eventName: PROJECT_PAGE_TRACKER_EVENTS.create, - payload: { - state: "FAILED", - }, + error, }); } }; diff --git a/web/core/components/pages/modals/delete-page-modal.tsx b/apps/web/core/components/pages/modals/delete-page-modal.tsx similarity index 90% rename from web/core/components/pages/modals/delete-page-modal.tsx rename to apps/web/core/components/pages/modals/delete-page-modal.tsx index daf44e950..992d2b95b 100644 --- a/web/core/components/pages/modals/delete-page-modal.tsx +++ b/apps/web/core/components/pages/modals/delete-page-modal.tsx @@ -8,7 +8,7 @@ import { PROJECT_PAGE_TRACKER_EVENTS } from "@plane/constants"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; // plane web hooks import { useAppRouter } from "@/hooks/use-app-router"; import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store"; @@ -28,7 +28,6 @@ export const DeletePageModal: React.FC = observer((pr const [isDeleting, setIsDeleting] = useState(false); // store hooks const { removePage } = usePageStore(storeType); - const { capturePageEvent } = useEventTracker(); if (!page || !page.id) return null; // derived values const { id: pageId, name } = page; @@ -45,11 +44,10 @@ export const DeletePageModal: React.FC = observer((pr setIsDeleting(true); await removePage(pageId) .then(() => { - capturePageEvent({ + captureSuccess({ eventName: PROJECT_PAGE_TRACKER_EVENTS.delete, payload: { - ...page, - state: "SUCCESS", + id: pageId, }, }); handleClose(); @@ -64,11 +62,10 @@ export const DeletePageModal: React.FC = observer((pr } }) .catch(() => { - capturePageEvent({ + captureError({ eventName: PROJECT_PAGE_TRACKER_EVENTS.delete, payload: { - ...page, - state: "FAILED", + id: pageId, }, }); setToast({ diff --git a/web/core/components/pages/modals/export-page-modal.tsx b/apps/web/core/components/pages/modals/export-page-modal.tsx similarity index 100% rename from web/core/components/pages/modals/export-page-modal.tsx rename to apps/web/core/components/pages/modals/export-page-modal.tsx diff --git a/web/core/components/pages/modals/index.ts b/apps/web/core/components/pages/modals/index.ts similarity index 100% rename from web/core/components/pages/modals/index.ts rename to apps/web/core/components/pages/modals/index.ts diff --git a/web/core/components/pages/modals/page-form.tsx b/apps/web/core/components/pages/modals/page-form.tsx similarity index 100% rename from web/core/components/pages/modals/page-form.tsx rename to apps/web/core/components/pages/modals/page-form.tsx diff --git a/apps/web/core/components/pages/navigation-pane/index.ts b/apps/web/core/components/pages/navigation-pane/index.ts new file mode 100644 index 000000000..fc8595eaa --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/index.ts @@ -0,0 +1,11 @@ +// plane web imports +import { ORDERED_PAGE_NAVIGATION_TABS_LIST } from "@/plane-web/components/pages/navigation-pane"; + +export * from "./root"; + +export const PAGE_NAVIGATION_PANE_WIDTH = 294; + +export const PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM = "paneTab"; +export const PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM = "version"; + +export const PAGE_NAVIGATION_PANE_TAB_KEYS = ORDERED_PAGE_NAVIGATION_TABS_LIST.map((tab) => tab.key); diff --git a/apps/web/core/components/pages/navigation-pane/root.tsx b/apps/web/core/components/pages/navigation-pane/root.tsx new file mode 100644 index 000000000..a2497d385 --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/root.tsx @@ -0,0 +1,88 @@ +import React, { useCallback } from "react"; +import { observer } from "mobx-react"; +import { useRouter, useSearchParams } from "next/navigation"; +import { ArrowRightCircle } from "lucide-react"; +import { Tab } from "@headlessui/react"; +// plane imports +import { useTranslation } from "@plane/i18n"; +import { Tooltip } from "@plane/ui"; +// hooks +import { useQueryParams } from "@/hooks/use-query-params"; +// plane web components +import { TPageNavigationPaneTab } from "@/plane-web/components/pages/navigation-pane"; +// store +import { TPageInstance } from "@/store/pages/base-page"; +// local imports +import { TPageRootHandlers } from "../editor"; +import { PageNavigationPaneTabPanelsRoot } from "./tab-panels/root"; +import { PageNavigationPaneTabsList } from "./tabs-list"; +import { + PAGE_NAVIGATION_PANE_TAB_KEYS, + PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM, + PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM, + PAGE_NAVIGATION_PANE_WIDTH, +} from "./index"; + +type Props = { + handleClose: () => void; + isNavigationPaneOpen: boolean; + page: TPageInstance; + versionHistory: Pick; +}; + +export const PageNavigationPaneRoot: React.FC = observer((props) => { + const { handleClose, isNavigationPaneOpen, page, versionHistory } = props; + // navigation + const router = useRouter(); + const searchParams = useSearchParams(); + // query params + const { updateQueryParams } = useQueryParams(); + // derived values + const navigationPaneQueryParam = searchParams.get( + PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM + ) as TPageNavigationPaneTab | null; + const activeTab: TPageNavigationPaneTab = navigationPaneQueryParam || "outline"; + const selectedIndex = PAGE_NAVIGATION_PANE_TAB_KEYS.indexOf(activeTab); + // translation + const { t } = useTranslation(); + + const handleTabChange = useCallback( + (index: number) => { + const updatedTab = PAGE_NAVIGATION_PANE_TAB_KEYS[index]; + const isUpdatedTabInfo = updatedTab === "info"; + const updatedRoute = updateQueryParams({ + paramsToAdd: { [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM]: updatedTab }, + paramsToRemove: !isUpdatedTabInfo ? [PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM] : undefined, + }); + router.push(updatedRoute); + }, + [router, updateQueryParams] + ); + + return ( + + ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/assets.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/assets.tsx new file mode 100644 index 000000000..357b759ad --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/assets.tsx @@ -0,0 +1,119 @@ +import { useMemo } from "react"; +import { observer } from "mobx-react"; +import { useParams } from "next/navigation"; +import { Download } from "lucide-react"; +// plane imports +import { CORE_EXTENSIONS, type TEditorAsset } from "@plane/editor"; +import { useTranslation } from "@plane/i18n"; +import { getEditorAssetDownloadSrc, getEditorAssetSrc } from "@plane/utils"; +// plane web imports +import { AdditionalPageNavigationPaneAssetItem } from "@/plane-web/components/pages/navigation-pane/tab-panels/assets"; +import { PageNavigationPaneAssetsTabEmptyState } from "@/plane-web/components/pages/navigation-pane/tab-panels/empty-states/assets"; +// store +import { TPageInstance } from "@/store/pages/base-page"; + +type Props = { + page: TPageInstance; +}; + +type AssetItemProps = { + asset: TEditorAsset; + page: TPageInstance; +}; + +const AssetItem = observer((props: AssetItemProps) => { + const { asset, page } = props; + // navigation + const { workspaceSlug } = useParams(); + // derived values + const { project_ids } = page; + // translation + const { t } = useTranslation(); + + const assetSrc: string = useMemo(() => { + if (!asset.src || !workspaceSlug) return ""; + if (asset.src.startsWith("http")) { + return asset.src; + } else { + return ( + getEditorAssetSrc({ + assetId: asset.src, + projectId: project_ids?.[0], + workspaceSlug: workspaceSlug.toString(), + }) ?? "" + ); + } + }, [asset.src, project_ids, workspaceSlug]); + + const assetDownloadSrc: string = useMemo(() => { + if (!asset.src || !workspaceSlug) return ""; + if (asset.src.startsWith("http")) { + return asset.src; + } else { + return ( + getEditorAssetDownloadSrc({ + assetId: asset.src, + projectId: project_ids?.[0], + workspaceSlug: workspaceSlug.toString(), + }) ?? "" + ); + } + }, [asset.src, project_ids, workspaceSlug]); + + if ([CORE_EXTENSIONS.IMAGE, CORE_EXTENSIONS.CUSTOM_IMAGE].includes(asset.type as CORE_EXTENSIONS)) + return ( + +
+ + + ); + + return ( + + ); +}); + +export const PageNavigationPaneAssetsTabPanel: React.FC = observer((props) => { + const { page } = props; + // derived values + const { + editor: { assetsList }, + } = page; + + if (assetsList.length === 0) return ; + + return ( +
+ {assetsList?.map((asset) => ( + + ))} +
+ ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx new file mode 100644 index 000000000..d0bd1b907 --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx @@ -0,0 +1,68 @@ +import { observer } from "mobx-react"; +import Link from "next/link"; +import { useParams } from "next/navigation"; +// plane imports +import { useTranslation } from "@plane/i18n"; +import { Avatar } from "@plane/ui"; +import { calculateTimeAgoShort, getFileURL, renderFormattedDate } from "@plane/utils"; +// hooks +import { useMember } from "@/hooks/store"; +// store +import { TPageInstance } from "@/store/pages/base-page"; + +type Props = { + page: TPageInstance; +}; + +export const PageNavigationPaneInfoTabActorsInfo: React.FC = observer((props) => { + const { page } = props; + // navigation + const { workspaceSlug } = useParams(); + // store hooks + const { getUserDetails } = useMember(); + // derived values + const { owned_by, updated_by } = page; + const editorInformation = updated_by ? getUserDetails(updated_by) : undefined; + const creatorInformation = owned_by ? getUserDetails(owned_by) : undefined; + // translation + const { t } = useTranslation(); + + return ( +
+
+

+ {t("page_navigation_pane.tabs.info.actors_info.edited_by")} +

+
+ + + {editorInformation?.display_name ?? t("common.deactivated_user")} + + {calculateTimeAgoShort(page.updated_at ?? "")} ago +
+
+
+

+ {t("page_navigation_pane.tabs.info.actors_info.created_by")} +

+
+ + + {creatorInformation?.display_name ?? t("common.deactivated_user")} + + {renderFormattedDate(page.created_at)} +
+
+
+ ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/document-info.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/document-info.tsx new file mode 100644 index 000000000..b301e9cbe --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/document-info.tsx @@ -0,0 +1,82 @@ +import { useCallback, useEffect, useMemo, useState } from "react"; +import { observer } from "mobx-react"; +// plane imports +import type { TDocumentInfo } from "@plane/editor"; +import { useTranslation } from "@plane/i18n"; +import { getReadTimeFromWordsCount } from "@plane/utils"; +// store +import { TPageInstance } from "@/store/pages/base-page"; + +type Props = { + page: TPageInstance; +}; + +const DEFAULT_DOCUMENT_INFO: TDocumentInfo = { + words: 0, + characters: 0, + paragraphs: 0, +}; + +export const PageNavigationPaneInfoTabDocumentInfo: React.FC = observer((props) => { + const { page } = props; + // states + const [documentInfo, setDocumentInfo] = useState(DEFAULT_DOCUMENT_INFO); + // derived values + const { + editor: { editorRef }, + } = page; + // translation + const { t } = useTranslation(); + // subscribe to asset changes + useEffect(() => { + const unsubscribe = editorRef?.onDocumentInfoChange(setDocumentInfo); + // for initial render of this component to get the editor assets + setDocumentInfo(editorRef?.getDocumentInfo() ?? DEFAULT_DOCUMENT_INFO); + return () => { + unsubscribe?.(); + }; + }, [editorRef]); + + const secondsToReadableTime = useCallback(() => { + const wordsCount = documentInfo.words; + const readTimeInSeconds = Number(getReadTimeFromWordsCount(wordsCount).toFixed(0)); + return readTimeInSeconds < 60 ? `${readTimeInSeconds}s` : `${Math.ceil(readTimeInSeconds / 60)}m`; + }, [documentInfo.words]); + + const documentInfoCards = useMemo( + () => [ + { + key: "words-count", + title: t("page_navigation_pane.tabs.info.document_info.words"), + info: documentInfo.words, + }, + { + key: "characters-count", + title: t("page_navigation_pane.tabs.info.document_info.characters"), + info: documentInfo.characters, + }, + { + key: "paragraphs-count", + title: t("page_navigation_pane.tabs.info.document_info.paragraphs"), + info: documentInfo.paragraphs, + }, + { + key: "read-time", + title: t("page_navigation_pane.tabs.info.document_info.read_time"), + info: secondsToReadableTime(), + }, + ], + [documentInfo, secondsToReadableTime, t] + ); + + return ( +
+ {documentInfoCards.map((card) => ( +
+
{card.info}
+

{card.title}

+
+ ))} +
+ ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/root.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/root.tsx new file mode 100644 index 000000000..77edc24e0 --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/root.tsx @@ -0,0 +1,27 @@ +import { observer } from "mobx-react"; +// components +import { TPageRootHandlers } from "@/components/pages/editor"; +// store +import { TPageInstance } from "@/store/pages/base-page"; +// local imports +import { PageNavigationPaneInfoTabActorsInfo } from "./actors-info"; +import { PageNavigationPaneInfoTabDocumentInfo } from "./document-info"; +import { PageNavigationPaneInfoTabVersionHistory } from "./version-history"; + +type Props = { + page: TPageInstance; + versionHistory: Pick; +}; + +export const PageNavigationPaneInfoTabPanel: React.FC = observer((props) => { + const { page, versionHistory } = props; + + return ( +
+ + +
+ +
+ ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx new file mode 100644 index 000000000..d1454b12c --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx @@ -0,0 +1,142 @@ +import { useCallback } from "react"; +import { observer } from "mobx-react"; +import Link from "next/link"; +import { useSearchParams } from "next/navigation"; +import useSWR from "swr"; +// plane imports +import { useTranslation } from "@plane/i18n"; +import { TPageVersion } from "@plane/types"; +import { Avatar } from "@plane/ui"; +import { cn, getFileURL, renderFormattedDate, renderFormattedTime } from "@plane/utils"; +// components +import { TPageRootHandlers } from "@/components/pages/editor"; +// hooks +import { useMember } from "@/hooks/store"; +import { useQueryParams } from "@/hooks/use-query-params"; +// store +import { TPageInstance } from "@/store/pages/base-page"; +// local imports +import { PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM } from "../.."; + +type Props = { + page: TPageInstance; + versionHistory: Pick; +}; + +type VersionHistoryItemProps = { + getVersionLink: (versionID: string) => string; + isVersionActive: boolean; + version: TPageVersion; +}; + +const VersionHistoryItem = observer((props: VersionHistoryItemProps) => { + const { getVersionLink, isVersionActive, version } = props; + // store hooks + const { getUserDetails } = useMember(); + // derived values + const versionCreator = getUserDetails(version.owned_by); + // translation + const { t } = useTranslation(); + + return ( +
  • + {/* timeline icon */} +
    +
    +
    + {/* end timeline icon */} + +

    + {renderFormattedDate(version.last_saved_at)}, {renderFormattedTime(version.last_saved_at)} +

    +

    + + {versionCreator?.display_name ?? t("common.deactivated_user")} +

    + +
  • + ); +}); + +export const PageNavigationPaneInfoTabVersionHistory: React.FC = observer((props) => { + const { page, versionHistory } = props; + // navigation + const searchParams = useSearchParams(); + const activeVersion = searchParams.get(PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM); + // derived values + const { id } = page; + // translation + const { t } = useTranslation(); + // query params + const { updateQueryParams } = useQueryParams(); + // fetch all versions + const { data: versionsList } = useSWR( + id ? `PAGE_VERSIONS_LIST_${id}` : null, + id ? () => versionHistory.fetchAllVersions(id) : null + ); + + const getVersionLink = useCallback( + (versionID?: string) => { + if (versionID) { + return updateQueryParams({ + paramsToAdd: { [PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM]: versionID }, + }); + } else { + return updateQueryParams({ + paramsToRemove: [PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM], + }); + } + }, + [updateQueryParams] + ); + + return ( +
    +

    + {t("page_navigation_pane.tabs.info.version_history.label")} +

    +
    +
      + {/* timeline line */} +
      +
      +
      + {/* end timeline line */} +
    • + {/* timeline icon */} +
      +
      +
      + {/* end timeline icon */} + + {t("page_navigation_pane.tabs.info.version_history.current_version")} + +
    • + {versionsList?.map((version) => ( + + ))} +
    +
    +
    + ); +}); diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/outline.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/outline.tsx new file mode 100644 index 000000000..d563e52eb --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/outline.tsx @@ -0,0 +1,28 @@ +// plane web imports +import { PageNavigationPaneOutlineTabEmptyState } from "@/plane-web/components/pages/navigation-pane/tab-panels/empty-states/outline"; +// store +import { TPageInstance } from "@/store/pages/base-page"; +// local imports +import { PageContentBrowser } from "../../editor"; + +type Props = { + page: TPageInstance; +}; + +export const PageNavigationPaneOutlineTabPanel: React.FC = (props) => { + const { page } = props; + // derived values + const { + editor: { editorRef }, + } = page; + + return ( +
    + } + /> +
    + ); +}; diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx new file mode 100644 index 000000000..c9880f0d5 --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/root.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import { Tab } from "@headlessui/react"; +// components +import { TPageRootHandlers } from "@/components/pages/editor"; +// plane web imports +import { ORDERED_PAGE_NAVIGATION_TABS_LIST } from "@/plane-web/components/pages/navigation-pane"; +import { PageNavigationPaneAdditionalTabPanelsRoot } from "@/plane-web/components/pages/navigation-pane/tab-panels/root"; +// store +import { TPageInstance } from "@/store/pages/base-page"; +// local imports +import { PageNavigationPaneAssetsTabPanel } from "./assets"; +import { PageNavigationPaneInfoTabPanel } from "./info/root"; +import { PageNavigationPaneOutlineTabPanel } from "./outline"; + +type Props = { + page: TPageInstance; + versionHistory: Pick; +}; + +export const PageNavigationPaneTabPanelsRoot: React.FC = (props) => { + const { page, versionHistory } = props; + + return ( + + {ORDERED_PAGE_NAVIGATION_TABS_LIST.map((tab) => ( + + {tab.key === "outline" && } + {tab.key === "info" && } + {tab.key === "assets" && } + + + ))} + + ); +}; diff --git a/apps/web/core/components/pages/navigation-pane/tabs-list.tsx b/apps/web/core/components/pages/navigation-pane/tabs-list.tsx new file mode 100644 index 000000000..bf4383216 --- /dev/null +++ b/apps/web/core/components/pages/navigation-pane/tabs-list.tsx @@ -0,0 +1,37 @@ +import { Tab } from "@headlessui/react"; +// plane imports +import { useTranslation } from "@plane/i18n"; +// plane web components +import { ORDERED_PAGE_NAVIGATION_TABS_LIST } from "@/plane-web/components/pages/navigation-pane"; + +export const PageNavigationPaneTabsList = () => { + // translation + const { t } = useTranslation(); + + return ( + + {({ selectedIndex }) => ( + <> + {ORDERED_PAGE_NAVIGATION_TABS_LIST.map((tab) => ( + + {t(tab.i18n_label)} + + ))} + {/* active tab indicator */} +
    + + )} + + ); +}; diff --git a/web/core/components/pages/pages-list-main-content.tsx b/apps/web/core/components/pages/pages-list-main-content.tsx similarity index 90% rename from web/core/components/pages/pages-list-main-content.tsx rename to apps/web/core/components/pages/pages-list-main-content.tsx index 660b0b461..625f35244 100644 --- a/web/core/components/pages/pages-list-main-content.tsx +++ b/apps/web/core/components/pages/pages-list-main-content.tsx @@ -1,12 +1,13 @@ import { observer } from "mobx-react"; import Image from "next/image"; // plane imports -import { EUserPermissionsLevel, EUserProjectRoles, EPageAccess } from "@plane/constants"; +import { EUserPermissionsLevel, EPageAccess, PROJECT_PAGE_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TPageNavigationTabs } from "@plane/types"; +import { EUserProjectRoles, TPageNavigationTabs } from "@plane/types"; // components import { DetailedEmptyState } from "@/components/empty-state"; import { PageLoader } from "@/components/pages"; +import { captureClick } from "@/helpers/event-tracker.helper"; import { useCommandPalette, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // plane web hooks @@ -63,6 +64,7 @@ export const PagesListMainContent: React.FC = observer((props) => { text: t("project_page.empty_state.general.primary_button.text"), onClick: () => { toggleCreatePageModal({ isOpen: true }); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); }, disabled: !canPerformEmptyStateActions, }} @@ -79,6 +81,7 @@ export const PagesListMainContent: React.FC = observer((props) => { text: t("project_page.empty_state.public.primary_button.text"), onClick: () => { toggleCreatePageModal({ isOpen: true, pageAccess: EPageAccess.PUBLIC }); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); }, disabled: !canPerformEmptyStateActions, }} @@ -94,6 +97,7 @@ export const PagesListMainContent: React.FC = observer((props) => { text: t("project_page.empty_state.private.primary_button.text"), onClick: () => { toggleCreatePageModal({ isOpen: true, pageAccess: EPageAccess.PRIVATE }); + captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON }); }, disabled: !canPerformEmptyStateActions, }} diff --git a/web/core/components/pages/pages-list-view.tsx b/apps/web/core/components/pages/pages-list-view.tsx similarity index 100% rename from web/core/components/pages/pages-list-view.tsx rename to apps/web/core/components/pages/pages-list-view.tsx diff --git a/web/core/components/pages/version/editor.tsx b/apps/web/core/components/pages/version/editor.tsx similarity index 92% rename from web/core/components/pages/version/editor.tsx rename to apps/web/core/components/pages/version/editor.tsx index 8491408ac..1a2c23e28 100644 --- a/web/core/components/pages/version/editor.tsx +++ b/apps/web/core/components/pages/version/editor.tsx @@ -16,13 +16,11 @@ import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; export type TVersionEditorProps = { activeVersion: string | null; - currentVersionDescription: string | null; - isCurrentVersionActive: boolean; versionDetails: TPageVersion | undefined; }; export const PagesVersionEditor: React.FC = observer((props) => { - const { activeVersion, currentVersionDescription, isCurrentVersionActive, versionDetails } = props; + const { activeVersion, versionDetails } = props; // store hooks const { getUserDetails } = useMember(); // params @@ -49,7 +47,7 @@ export const PagesVersionEditor: React.FC = observer((props wideLayout: true, }; - if (!isCurrentVersionActive && !versionDetails) + if (!versionDetails) return (
    @@ -91,7 +89,7 @@ export const PagesVersionEditor: React.FC = observer((props
    ); - const description = isCurrentVersionActive ? currentVersionDescription : versionDetails?.description_html; + const description = versionDetails?.description_html; if (description === undefined || description?.trim() === "") return null; return ( diff --git a/apps/web/core/components/pages/version/index.ts b/apps/web/core/components/pages/version/index.ts new file mode 100644 index 000000000..5da43e959 --- /dev/null +++ b/apps/web/core/components/pages/version/index.ts @@ -0,0 +1,3 @@ +export * from "./editor"; +export * from "./main-content"; +export * from "./root"; diff --git a/web/core/components/pages/version/main-content.tsx b/apps/web/core/components/pages/version/main-content.tsx similarity index 76% rename from web/core/components/pages/version/main-content.tsx rename to apps/web/core/components/pages/version/main-content.tsx index e94bfefa7..ab05ba256 100644 --- a/web/core/components/pages/version/main-content.tsx +++ b/apps/web/core/components/pages/version/main-content.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import useSWR from "swr"; -import { TriangleAlert } from "lucide-react"; +import { EyeIcon, TriangleAlert } from "lucide-react"; // plane types import { TPageVersion } from "@plane/types"; // plane ui @@ -13,7 +13,6 @@ import { TVersionEditorProps } from "@/components/pages"; type Props = { activeVersion: string | null; - currentVersionDescription: string | null; editorComponent: React.FC; fetchVersionDetails: (pageId: string, versionId: string) => Promise; handleClose: () => void; @@ -23,16 +22,8 @@ type Props = { }; export const PageVersionsMainContent: React.FC = observer((props) => { - const { - activeVersion, - currentVersionDescription, - editorComponent, - fetchVersionDetails, - handleClose, - handleRestore, - pageId, - restoreEnabled, - } = props; + const { activeVersion, editorComponent, fetchVersionDetails, handleClose, handleRestore, pageId, restoreEnabled } = + props; // states const [isRestoring, setIsRestoring] = useState(false); const [isRetrying, setIsRetrying] = useState(false); @@ -42,12 +33,10 @@ export const PageVersionsMainContent: React.FC = observer((props) => { error: versionDetailsError, mutate: mutateVersionDetails, } = useSWR( - pageId && activeVersion && activeVersion !== "current" ? `PAGE_VERSION_${activeVersion}` : null, - pageId && activeVersion && activeVersion !== "current" ? () => fetchVersionDetails(pageId, activeVersion) : null + pageId && activeVersion ? `PAGE_VERSION_${activeVersion}` : null, + pageId && activeVersion ? () => fetchVersionDetails(pageId, activeVersion) : null ); - const isCurrentVersionActive = activeVersion === "current"; - const handleRestoreVersion = async () => { if (!restoreEnabled) return; setIsRestoring(true); @@ -96,14 +85,18 @@ export const PageVersionsMainContent: React.FC = observer((props) => { ) : ( <>
    -
    - {isCurrentVersionActive - ? "Current version" - : versionDetails +
    +
    + {versionDetails ? `${renderFormattedDate(versionDetails.last_saved_at)} ${renderFormattedTime(versionDetails.last_saved_at)}` : "Loading version details"} -
    - {!isCurrentVersionActive && restoreEnabled && ( +
    + + + View only + +
    + {restoreEnabled && (
    - +
    )} diff --git a/apps/web/core/components/pages/version/root.tsx b/apps/web/core/components/pages/version/root.tsx new file mode 100644 index 000000000..64b4f43da --- /dev/null +++ b/apps/web/core/components/pages/version/root.tsx @@ -0,0 +1,63 @@ +import { useCallback } from "react"; +import { observer } from "mobx-react"; +import { useRouter, useSearchParams } from "next/navigation"; +// plane imports +import { TPageVersion } from "@plane/types"; +import { cn } from "@plane/utils"; +// components +import { PageVersionsMainContent, TVersionEditorProps } from "@/components/pages"; +// hooks +import { useQueryParams } from "@/hooks/use-query-params"; +// local imports +import { PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM, PAGE_NAVIGATION_PANE_WIDTH } from "../navigation-pane"; + +type Props = { + editorComponent: React.FC; + fetchVersionDetails: (pageId: string, versionId: string) => Promise; + handleRestore: (descriptionHTML: string) => Promise; + pageId: string; + restoreEnabled: boolean; +}; + +export const PageVersionsOverlay: React.FC = observer((props) => { + const { editorComponent, fetchVersionDetails, handleRestore, pageId, restoreEnabled } = props; + // navigation + const router = useRouter(); + const searchParams = useSearchParams(); + // query params + const { updateQueryParams } = useQueryParams(); + // derived values + const activeVersion = searchParams.get(PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM); + const isOpen = !!activeVersion; + + const handleClose = useCallback(() => { + const updatedRoute = updateQueryParams({ + paramsToRemove: [PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM], + }); + router.push(updatedRoute); + }, [router, updateQueryParams]); + + return ( +
    + +
    + ); +}); diff --git a/web/core/components/preferences/list.tsx b/apps/web/core/components/preferences/list.tsx similarity index 100% rename from web/core/components/preferences/list.tsx rename to apps/web/core/components/preferences/list.tsx diff --git a/web/core/components/preferences/section.tsx b/apps/web/core/components/preferences/section.tsx similarity index 100% rename from web/core/components/preferences/section.tsx rename to apps/web/core/components/preferences/section.tsx diff --git a/web/core/components/profile/activity/activity-list.tsx b/apps/web/core/components/profile/activity/activity-list.tsx similarity index 98% rename from web/core/components/profile/activity/activity-list.tsx rename to apps/web/core/components/profile/activity/activity-list.tsx index 5eb8e8b7d..34886eb59 100644 --- a/web/core/components/profile/activity/activity-list.tsx +++ b/apps/web/core/components/profile/activity/activity-list.tsx @@ -9,7 +9,7 @@ import { calculateTimeAgo, getFileURL } from "@plane/utils"; // components import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core"; // editor -import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor"; +import { RichTextEditor } from "@/components/editor"; // ui import { ActivitySettingsLoader } from "@/components/ui"; // helpers @@ -73,7 +73,8 @@ export const ActivityList: React.FC = observer((props) => {

    - = observer((props) => {

    - { message: () => `There was some error in updating your profile. Please try again.`, }, }); + updateUserAndProfile + .then(() => { + captureSuccess({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.update_profile, + }); + }) + .catch(() => { + captureError({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.update_profile, + }); + }); }; return ( @@ -344,7 +357,12 @@ export const ProfileForm = observer((props: TProfileFormProps) => {
    -
    @@ -371,7 +389,11 @@ export const ProfileForm = observer((props: TProfileFormProps) => {
    {t("deactivate_account_description")}
    -
    diff --git a/web/core/components/profile/index.ts b/apps/web/core/components/profile/index.ts similarity index 100% rename from web/core/components/profile/index.ts rename to apps/web/core/components/profile/index.ts diff --git a/web/core/components/profile/notification/email-notification-form.tsx b/apps/web/core/components/profile/notification/email-notification-form.tsx similarity index 84% rename from web/core/components/profile/notification/email-notification-form.tsx rename to apps/web/core/components/profile/notification/email-notification-form.tsx index 9aab9a92f..d0ec45ae5 100644 --- a/web/core/components/profile/notification/email-notification-form.tsx +++ b/apps/web/core/components/profile/notification/email-notification-form.tsx @@ -2,11 +2,13 @@ import React, { FC, useEffect } from "react"; import { Controller, useForm } from "react-hook-form"; +import { PROFILE_SETTINGS_TRACKER_ELEMENTS, PROFILE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IUserEmailNotificationSettings } from "@plane/types"; // ui import { ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; // services +import { captureClick, captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { UserService } from "@/services/user.service"; // types interface IEmailNotificationFormProps { @@ -31,6 +33,12 @@ export const EmailNotificationForm: FC = (props) => await userService.updateCurrentUserEmailNotificationSettings({ [key]: value, }); + captureSuccess({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.notifications_updated, + payload: { + [key]: value, + }, + }); setToast({ title: t("success"), type: TOAST_TYPE.SUCCESS, @@ -38,6 +46,12 @@ export const EmailNotificationForm: FC = (props) => }); } catch (err) { console.error(err); + captureError({ + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.notifications_updated, + payload: { + [key]: value, + }, + }); setToast({ title: t("error"), type: TOAST_TYPE.ERROR, @@ -68,6 +82,9 @@ export const EmailNotificationForm: FC = (props) => value={value} onChange={(newValue) => { onChange(newValue); + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.PROPERTY_CHANGES_TOGGLE, + }); handleSettingChange("property_change", newValue); }} size="sm" @@ -90,6 +107,9 @@ export const EmailNotificationForm: FC = (props) => value={value} onChange={(newValue) => { onChange(newValue); + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.STATE_CHANGES_TOGGLE, + }); handleSettingChange("state_change", newValue); }} size="sm" @@ -134,6 +154,9 @@ export const EmailNotificationForm: FC = (props) => value={value} onChange={(newValue) => { onChange(newValue); + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.COMMENTS_TOGGLE, + }); handleSettingChange("comment", newValue); }} size="sm" @@ -156,6 +179,9 @@ export const EmailNotificationForm: FC = (props) => value={value} onChange={(newValue) => { onChange(newValue); + captureClick({ + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.MENTIONS_TOGGLE, + }); handleSettingChange("mention", newValue); }} size="sm" diff --git a/web/core/components/profile/notification/index.ts b/apps/web/core/components/profile/notification/index.ts similarity index 100% rename from web/core/components/profile/notification/index.ts rename to apps/web/core/components/profile/notification/index.ts diff --git a/web/core/components/profile/overview/activity.tsx b/apps/web/core/components/profile/overview/activity.tsx similarity index 97% rename from web/core/components/profile/overview/activity.tsx rename to apps/web/core/components/profile/overview/activity.tsx index 10313ef92..002286c77 100644 --- a/web/core/components/profile/overview/activity.tsx +++ b/apps/web/core/components/profile/overview/activity.tsx @@ -63,7 +63,9 @@ export const ProfileActivity = observer(() => {

    - {currentUser?.id === activity.actor_detail?.id ? "You" : activity.actor_detail?.display_name}{" "} + {currentUser?.id === activity.actor_detail?.id + ? "You" + : activity.actor_detail?.display_name}{" "} {activity.field ? ( diff --git a/web/core/components/profile/overview/index.ts b/apps/web/core/components/profile/overview/index.ts similarity index 100% rename from web/core/components/profile/overview/index.ts rename to apps/web/core/components/profile/overview/index.ts diff --git a/web/core/components/profile/overview/priority-distribution.tsx b/apps/web/core/components/profile/overview/priority-distribution.tsx similarity index 100% rename from web/core/components/profile/overview/priority-distribution.tsx rename to apps/web/core/components/profile/overview/priority-distribution.tsx diff --git a/web/core/components/profile/overview/state-distribution.tsx b/apps/web/core/components/profile/overview/state-distribution.tsx similarity index 100% rename from web/core/components/profile/overview/state-distribution.tsx rename to apps/web/core/components/profile/overview/state-distribution.tsx diff --git a/web/core/components/profile/overview/stats.tsx b/apps/web/core/components/profile/overview/stats.tsx similarity index 100% rename from web/core/components/profile/overview/stats.tsx rename to apps/web/core/components/profile/overview/stats.tsx diff --git a/web/core/components/profile/overview/workload.tsx b/apps/web/core/components/profile/overview/workload.tsx similarity index 100% rename from web/core/components/profile/overview/workload.tsx rename to apps/web/core/components/profile/overview/workload.tsx diff --git a/web/core/components/profile/preferences/language-timezone.tsx b/apps/web/core/components/profile/preferences/language-timezone.tsx similarity index 70% rename from web/core/components/profile/preferences/language-timezone.tsx rename to apps/web/core/components/profile/preferences/language-timezone.tsx index 9a40cb880..8d171ee36 100644 --- a/web/core/components/profile/preferences/language-timezone.tsx +++ b/apps/web/core/components/profile/preferences/language-timezone.tsx @@ -1,7 +1,9 @@ import { observer } from "mobx-react"; +import { PROFILE_SETTINGS_TRACKER_ELEMENTS, PROFILE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { SUPPORTED_LANGUAGES, useTranslation } from "@plane/i18n"; import { CustomSelect, TOAST_TYPE, setToast } from "@plane/ui"; import { TimezoneSelect } from "@/components/global"; +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; import { useUser, useUserProfile } from "@/hooks/store"; export const LanguageTimezone = observer(() => { @@ -17,6 +19,18 @@ export const LanguageTimezone = observer(() => { const handleTimezoneChange = (value: string) => { updateCurrentUser({ user_timezone: value }) .then(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.TIMEZONE_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.timezone_updated, + payload: { + timezone: value, + }, + state: "SUCCESS", + }, + }); setToast({ title: "Success!", message: "Timezone updated successfully", @@ -24,6 +38,15 @@ export const LanguageTimezone = observer(() => { }); }) .catch(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.TIMEZONE_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.timezone_updated, + state: "ERROR", + }, + }); setToast({ title: "Error!", message: "Failed to update timezone", @@ -34,6 +57,18 @@ export const LanguageTimezone = observer(() => { const handleLanguageChange = (value: string) => { updateUserProfile({ language: value }) .then(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.LANGUAGE_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.language_updated, + payload: { + language: value, + }, + state: "SUCCESS", + }, + }); setToast({ title: "Success!", message: "Language updated successfully", @@ -41,6 +76,15 @@ export const LanguageTimezone = observer(() => { }); }) .catch(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.LANGUAGE_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.language_updated, + state: "ERROR", + }, + }); setToast({ title: "Error!", message: "Failed to update language", diff --git a/web/core/components/profile/profile-issues-filter.tsx b/apps/web/core/components/profile/profile-issues-filter.tsx similarity index 91% rename from web/core/components/profile/profile-issues-filter.tsx rename to apps/web/core/components/profile/profile-issues-filter.tsx index 70a76de95..2b91194ba 100644 --- a/web/core/components/profile/profile-issues-filter.tsx +++ b/apps/web/core/components/profile/profile-issues-filter.tsx @@ -2,11 +2,17 @@ import { useCallback } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane constants -import { EIssueLayoutTypes, EIssuesStoreType, EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; +import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; // types -import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types"; +import { + EIssuesStoreType, + IIssueDisplayFilterOptions, + IIssueDisplayProperties, + IIssueFilterOptions, + EIssueLayoutTypes, +} from "@plane/types"; // components import { isIssueFilterActive } from "@plane/utils"; import { DisplayFiltersSelection, FilterSelection, FiltersDropdown, LayoutSelection } from "@/components/issues"; @@ -107,7 +113,11 @@ export const ProfileIssuesFilter = observer(() => { selectedLayout={activeLayout} /> - + { updateUserProfile({ start_of_the_week: val }) .then(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.FIRST_DAY_OF_WEEK_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.first_day_updated, + payload: { + start_of_the_week: val, + }, + state: "SUCCESS", + }, + }); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success", @@ -35,6 +53,15 @@ export const StartOfWeekPreference = observer((props: { option: { title: string; }); }) .catch(() => { + captureElementAndEvent({ + element: { + elementName: PROFILE_SETTINGS_TRACKER_ELEMENTS.FIRST_DAY_OF_WEEK_DROPDOWN, + }, + event: { + eventName: PROFILE_SETTINGS_TRACKER_EVENTS.first_day_updated, + state: "ERROR", + }, + }); setToast({ type: TOAST_TYPE.ERROR, title: "Update failed", message: "Please try again later." }); }); }} diff --git a/web/core/components/profile/time.tsx b/apps/web/core/components/profile/time.tsx similarity index 100% rename from web/core/components/profile/time.tsx rename to apps/web/core/components/profile/time.tsx diff --git a/web/core/components/project-states/create-update/create.tsx b/apps/web/core/components/project-states/create-update/create.tsx similarity index 69% rename from web/core/components/project-states/create-update/create.tsx rename to apps/web/core/components/project-states/create-update/create.tsx index 821ea8eb6..25972f7c0 100644 --- a/web/core/components/project-states/create-update/create.tsx +++ b/apps/web/core/components/project-states/create-update/create.tsx @@ -2,13 +2,13 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; -import { EventProps, STATE_TRACKER_EVENTS, STATE_GROUPS } from "@plane/constants"; +import { STATE_TRACKER_EVENTS, STATE_GROUPS } from "@plane/constants"; import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { StateForm } from "@/components/project-states"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; type TStateCreate = { groupKey: TStateGroups; @@ -19,17 +19,10 @@ type TStateCreate = { export const StateCreate: FC = observer((props) => { const { groupKey, shouldTrackEvents, createStateCallback, handleClose } = props; - // hooks - const { captureProjectStateEvent, setTrackElement } = useEventTracker(); + // states const [loader, setLoader] = useState(false); - const captureEventIfEnabled = (props: EventProps) => { - if (shouldTrackEvents) { - captureProjectStateEvent(props); - } - }; - const onCancel = () => { setLoader(false); handleClose(); @@ -38,19 +31,16 @@ export const StateCreate: FC = observer((props) => { const onSubmit = async (formData: Partial) => { if (!groupKey) return { status: "error" }; - if (shouldTrackEvents) { - setTrackElement("PROJECT_SETTINGS_STATE_PAGE"); - } try { - const stateResponse = await createStateCallback({ ...formData, group: groupKey }); - captureEventIfEnabled({ - eventName: STATE_TRACKER_EVENTS.create, - payload: { - ...stateResponse, - state: "SUCCESS", - element: "Project settings states page", - }, - }); + const response = await createStateCallback({ ...formData, group: groupKey }); + if (shouldTrackEvents) + captureSuccess({ + eventName: STATE_TRACKER_EVENTS.create, + payload: { + state_group: groupKey, + id: response.id, + }, + }); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -60,14 +50,13 @@ export const StateCreate: FC = observer((props) => { return { status: "success" }; } catch (error) { const errorStatus = error as unknown as { status: number; data: { error: string } }; - captureEventIfEnabled({ - eventName: STATE_TRACKER_EVENTS.create, - payload: { - ...formData, - state: "FAILED", - element: "Project settings states page", - }, - }); + if (shouldTrackEvents) + captureError({ + eventName: STATE_TRACKER_EVENTS.create, + payload: { + state_group: groupKey, + }, + }); if (errorStatus?.status === 400) { setToast({ type: TOAST_TYPE.ERROR, diff --git a/web/core/components/project-states/create-update/form.tsx b/apps/web/core/components/project-states/create-update/form.tsx similarity index 100% rename from web/core/components/project-states/create-update/form.tsx rename to apps/web/core/components/project-states/create-update/form.tsx diff --git a/web/core/components/project-states/create-update/index.ts b/apps/web/core/components/project-states/create-update/index.ts similarity index 100% rename from web/core/components/project-states/create-update/index.ts rename to apps/web/core/components/project-states/create-update/index.ts diff --git a/web/core/components/project-states/create-update/update.tsx b/apps/web/core/components/project-states/create-update/update.tsx similarity index 68% rename from web/core/components/project-states/create-update/update.tsx rename to apps/web/core/components/project-states/create-update/update.tsx index d43774021..b242f900c 100644 --- a/web/core/components/project-states/create-update/update.tsx +++ b/apps/web/core/components/project-states/create-update/update.tsx @@ -2,13 +2,13 @@ import { FC, useState } from "react"; import { observer } from "mobx-react"; -import { EventProps, STATE_TRACKER_EVENTS } from "@plane/constants"; +import { STATE_TRACKER_EVENTS } from "@plane/constants"; import { IState, TStateOperationsCallbacks } from "@plane/types"; import { TOAST_TYPE, setToast } from "@plane/ui"; // components import { StateForm } from "@/components/project-states"; // hooks -import { useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; type TStateUpdate = { state: IState; @@ -19,8 +19,6 @@ type TStateUpdate = { export const StateUpdate: FC = observer((props) => { const { state, updateStateCallback, shouldTrackEvents, handleClose } = props; - // hooks - const { captureProjectStateEvent, setTrackElement } = useEventTracker(); // states const [loader, setLoader] = useState(false); @@ -29,28 +27,20 @@ export const StateUpdate: FC = observer((props) => { handleClose(); }; - const captureEventIfEnabled = (props: EventProps) => { - if (shouldTrackEvents) { - captureProjectStateEvent(props); - } - }; - const onSubmit = async (formData: Partial) => { if (!state.id) return { status: "error" }; - if (shouldTrackEvents) { - setTrackElement("PROJECT_SETTINGS_STATE_PAGE"); - } try { - const stateResponse = await updateStateCallback(state.id, formData); - captureEventIfEnabled({ - eventName: STATE_TRACKER_EVENTS.update, - payload: { - ...stateResponse, - state: "SUCCESS", - element: "Project settings states page", - }, - }); + await updateStateCallback(state.id, formData); + if (shouldTrackEvents) { + captureSuccess({ + eventName: STATE_TRACKER_EVENTS.update, + payload: { + state_group: state.group, + id: state.id, + }, + }); + } setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -73,14 +63,15 @@ export const StateUpdate: FC = observer((props) => { title: "Error!", message: "State could not be updated. Please try again.", }); - captureEventIfEnabled({ - eventName: STATE_TRACKER_EVENTS.update, - payload: { - ...formData, - state: "FAILED", - element: "Project settings states page", - }, - }); + if (shouldTrackEvents) { + captureError({ + eventName: STATE_TRACKER_EVENTS.update, + payload: { + state_group: state.group, + id: state.id, + }, + }); + } return { status: "error" }; } } diff --git a/web/core/components/project-states/group-item.tsx b/apps/web/core/components/project-states/group-item.tsx similarity index 96% rename from web/core/components/project-states/group-item.tsx rename to apps/web/core/components/project-states/group-item.tsx index bcb08c006..82a68a4d6 100644 --- a/web/core/components/project-states/group-item.tsx +++ b/apps/web/core/components/project-states/group-item.tsx @@ -4,7 +4,7 @@ import { FC, useState, useRef } from "react"; import { observer } from "mobx-react"; import { ChevronDown, Plus } from "lucide-react"; // plane imports -import { EIconSize } from "@plane/constants"; +import { EIconSize, STATE_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IState, TStateGroups, TStateOperationsCallbacks } from "@plane/types"; import { StateGroupIcon } from "@plane/ui"; @@ -81,6 +81,7 @@ export const GroupItem: FC = observer((props) => {

    diff --git a/web/core/components/project-states/state-item.tsx b/apps/web/core/components/project-states/state-item.tsx similarity index 100% rename from web/core/components/project-states/state-item.tsx rename to apps/web/core/components/project-states/state-item.tsx diff --git a/web/core/components/project-states/state-list.tsx b/apps/web/core/components/project-states/state-list.tsx similarity index 100% rename from web/core/components/project-states/state-list.tsx rename to apps/web/core/components/project-states/state-list.tsx diff --git a/web/core/components/project/applied-filters/access.tsx b/apps/web/core/components/project/applied-filters/access.tsx similarity index 100% rename from web/core/components/project/applied-filters/access.tsx rename to apps/web/core/components/project/applied-filters/access.tsx diff --git a/web/core/components/project/applied-filters/date.tsx b/apps/web/core/components/project/applied-filters/date.tsx similarity index 100% rename from web/core/components/project/applied-filters/date.tsx rename to apps/web/core/components/project/applied-filters/date.tsx diff --git a/web/core/components/project/applied-filters/index.ts b/apps/web/core/components/project/applied-filters/index.ts similarity index 100% rename from web/core/components/project/applied-filters/index.ts rename to apps/web/core/components/project/applied-filters/index.ts diff --git a/web/core/components/project/applied-filters/members.tsx b/apps/web/core/components/project/applied-filters/members.tsx similarity index 100% rename from web/core/components/project/applied-filters/members.tsx rename to apps/web/core/components/project/applied-filters/members.tsx diff --git a/web/core/components/project/applied-filters/project-display-filters.tsx b/apps/web/core/components/project/applied-filters/project-display-filters.tsx similarity index 100% rename from web/core/components/project/applied-filters/project-display-filters.tsx rename to apps/web/core/components/project/applied-filters/project-display-filters.tsx diff --git a/web/core/components/project/applied-filters/root.tsx b/apps/web/core/components/project/applied-filters/root.tsx similarity index 100% rename from web/core/components/project/applied-filters/root.tsx rename to apps/web/core/components/project/applied-filters/root.tsx diff --git a/web/core/components/project/card-list.tsx b/apps/web/core/components/project/card-list.tsx similarity index 91% rename from web/core/components/project/card-list.tsx rename to apps/web/core/components/project/card-list.tsx index 606f533f1..d2c1f7dad 100644 --- a/web/core/components/project/card-list.tsx +++ b/apps/web/core/components/project/card-list.tsx @@ -1,15 +1,16 @@ import { observer } from "mobx-react"; import Image from "next/image"; // plane imports -import { EUserPermissionsLevel, EUserPermissions } from "@plane/constants"; +import { EUserPermissionsLevel, EUserPermissions, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { ContentWrapper } from "@plane/ui"; // components import { ComicBoxButton, DetailedEmptyState } from "@/components/empty-state"; import { ProjectCard } from "@/components/project"; import { ProjectsLoader } from "@/components/ui"; +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks -import { useCommandPalette, useEventTracker, useProject, useProjectFilter, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useProject, useProjectFilter, useUserPermissions } from "@/hooks/store"; import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path"; // assets import AllFiltersImage from "@/public/empty-state/project/all-filters.svg"; @@ -26,7 +27,6 @@ export const ProjectCardList = observer((props: TProjectCardListProps) => { const { t } = useTranslation(); // store hooks const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { loader, fetchStatus, @@ -65,8 +65,8 @@ export const ProjectCardList = observer((props: TProjectCardListProps) => { title={t("workspace_projects.empty_state.general.primary_button.comic.title")} description={t("workspace_projects.empty_state.general.primary_button.comic.description")} onClick={() => { - setTrackElement("Project empty state"); toggleCreateProjectModal(true); + captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON }); }} disabled={!canPerformEmptyStateActions} /> diff --git a/web/core/components/project/card.tsx b/apps/web/core/components/project/card.tsx similarity index 100% rename from web/core/components/project/card.tsx rename to apps/web/core/components/project/card.tsx diff --git a/web/core/components/project/confirm-project-member-remove.tsx b/apps/web/core/components/project/confirm-project-member-remove.tsx similarity index 100% rename from web/core/components/project/confirm-project-member-remove.tsx rename to apps/web/core/components/project/confirm-project-member-remove.tsx diff --git a/web/core/components/project/create-project-modal.tsx b/apps/web/core/components/project/create-project-modal.tsx similarity index 100% rename from web/core/components/project/create-project-modal.tsx rename to apps/web/core/components/project/create-project-modal.tsx diff --git a/web/core/components/project/create/common-attributes.tsx b/apps/web/core/components/project/create/common-attributes.tsx similarity index 100% rename from web/core/components/project/create/common-attributes.tsx rename to apps/web/core/components/project/create/common-attributes.tsx diff --git a/web/core/components/project/create/header.tsx b/apps/web/core/components/project/create/header.tsx similarity index 100% rename from web/core/components/project/create/header.tsx rename to apps/web/core/components/project/create/header.tsx diff --git a/web/core/components/project/create/project-create-buttons.tsx b/apps/web/core/components/project/create/project-create-buttons.tsx similarity index 100% rename from web/core/components/project/create/project-create-buttons.tsx rename to apps/web/core/components/project/create/project-create-buttons.tsx diff --git a/web/core/components/project/delete-project-modal.tsx b/apps/web/core/components/project/delete-project-modal.tsx similarity index 95% rename from web/core/components/project/delete-project-modal.tsx rename to apps/web/core/components/project/delete-project-modal.tsx index d5888161e..7c48fb30a 100644 --- a/web/core/components/project/delete-project-modal.tsx +++ b/apps/web/core/components/project/delete-project-modal.tsx @@ -12,7 +12,8 @@ import type { IProject } from "@plane/types"; import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks -import { useEventTracker, useProject } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useProject } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; type DeleteProjectModal = { @@ -29,7 +30,6 @@ const defaultValues = { export const DeleteProjectModal: React.FC = (props) => { const { isOpen, project, onClose } = props; // store hooks - const { captureProjectEvent } = useEventTracker(); const { deleteProject } = useProject(); // router const router = useAppRouter(); @@ -62,9 +62,11 @@ export const DeleteProjectModal: React.FC = (props) => { if (projectId && projectId.toString() === project.id) router.push(`/${workspaceSlug}/projects`); handleClose(); - captureProjectEvent({ + captureSuccess({ eventName: PROJECT_TRACKER_EVENTS.delete, - payload: { ...project, state: "SUCCESS", element: "Project general settings" }, + payload: { + id: project.id, + }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -73,9 +75,11 @@ export const DeleteProjectModal: React.FC = (props) => { }); }) .catch(() => { - captureProjectEvent({ + captureError({ eventName: PROJECT_TRACKER_EVENTS.delete, - payload: { ...project, state: "FAILED", element: "Project general settings" }, + payload: { + id: project.id, + }, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/web/core/components/project/dropdowns/filters/access.tsx b/apps/web/core/components/project/dropdowns/filters/access.tsx similarity index 100% rename from web/core/components/project/dropdowns/filters/access.tsx rename to apps/web/core/components/project/dropdowns/filters/access.tsx diff --git a/web/core/components/project/dropdowns/filters/created-at.tsx b/apps/web/core/components/project/dropdowns/filters/created-at.tsx similarity index 100% rename from web/core/components/project/dropdowns/filters/created-at.tsx rename to apps/web/core/components/project/dropdowns/filters/created-at.tsx diff --git a/web/core/components/project/dropdowns/filters/index.ts b/apps/web/core/components/project/dropdowns/filters/index.ts similarity index 100% rename from web/core/components/project/dropdowns/filters/index.ts rename to apps/web/core/components/project/dropdowns/filters/index.ts diff --git a/web/core/components/project/dropdowns/filters/lead.tsx b/apps/web/core/components/project/dropdowns/filters/lead.tsx similarity index 100% rename from web/core/components/project/dropdowns/filters/lead.tsx rename to apps/web/core/components/project/dropdowns/filters/lead.tsx diff --git a/web/core/components/project/dropdowns/filters/members.tsx b/apps/web/core/components/project/dropdowns/filters/members.tsx similarity index 100% rename from web/core/components/project/dropdowns/filters/members.tsx rename to apps/web/core/components/project/dropdowns/filters/members.tsx diff --git a/web/core/components/project/dropdowns/filters/root.tsx b/apps/web/core/components/project/dropdowns/filters/root.tsx similarity index 100% rename from web/core/components/project/dropdowns/filters/root.tsx rename to apps/web/core/components/project/dropdowns/filters/root.tsx diff --git a/web/core/components/project/dropdowns/index.ts b/apps/web/core/components/project/dropdowns/index.ts similarity index 100% rename from web/core/components/project/dropdowns/index.ts rename to apps/web/core/components/project/dropdowns/index.ts diff --git a/web/core/components/project/dropdowns/order-by.tsx b/apps/web/core/components/project/dropdowns/order-by.tsx similarity index 100% rename from web/core/components/project/dropdowns/order-by.tsx rename to apps/web/core/components/project/dropdowns/order-by.tsx diff --git a/web/core/components/project/empty-state.tsx b/apps/web/core/components/project/empty-state.tsx similarity index 100% rename from web/core/components/project/empty-state.tsx rename to apps/web/core/components/project/empty-state.tsx diff --git a/web/core/components/project/filters.tsx b/apps/web/core/components/project/filters.tsx similarity index 100% rename from web/core/components/project/filters.tsx rename to apps/web/core/components/project/filters.tsx diff --git a/web/core/components/project/form-loader.tsx b/apps/web/core/components/project/form-loader.tsx similarity index 100% rename from web/core/components/project/form-loader.tsx rename to apps/web/core/components/project/form-loader.tsx diff --git a/web/core/components/project/form.tsx b/apps/web/core/components/project/form.tsx similarity index 87% rename from web/core/components/project/form.tsx rename to apps/web/core/components/project/form.tsx index 27c8ec840..452d9d0b6 100644 --- a/web/core/components/project/form.tsx +++ b/apps/web/core/components/project/form.tsx @@ -3,7 +3,7 @@ import { FC, useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { Info, Lock } from "lucide-react"; -import { NETWORK_CHOICES, PROJECT_TRACKER_EVENTS } from "@plane/constants"; +import { NETWORK_CHOICES, PROJECT_TRACKER_ELEMENTS, PROJECT_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // plane types import { IProject, IWorkspace } from "@plane/types"; @@ -27,7 +27,8 @@ import { TimezoneSelect } from "@/components/global"; import { ProjectNetworkIcon } from "@/components/project"; // helpers // hooks -import { useEventTracker, useProject } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useProject } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // services import { ProjectService } from "@/services/project"; @@ -46,7 +47,6 @@ export const ProjectDetailsForm: FC = (props) => { const [isOpen, setIsOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); // store hooks - const { captureProjectEvent } = useEventTracker(); const { updateProject } = useProject(); const { isMobile } = usePlatformOS(); @@ -58,7 +58,7 @@ export const ProjectDetailsForm: FC = (props) => { setValue, setError, reset, - formState: { errors, dirtyFields }, + formState: { errors }, getValues, } = useForm({ defaultValues: { @@ -92,15 +92,10 @@ export const ProjectDetailsForm: FC = (props) => { if (!workspaceSlug || !project) return; return updateProject(workspaceSlug.toString(), project.id, payload) .then((res) => { - const changed_properties = Object.keys(dirtyFields); - - captureProjectEvent({ + captureSuccess({ eventName: PROJECT_TRACKER_EVENTS.update, payload: { - ...res, - changed_properties: changed_properties, - state: "SUCCESS", - element: "Project general settings", + id: projectId, }, }); setToast({ @@ -109,16 +104,53 @@ export const ProjectDetailsForm: FC = (props) => { message: t("project_settings.general.toast.success"), }); }) - .catch((error) => { - captureProjectEvent({ - eventName: PROJECT_TRACKER_EVENTS.update, - payload: { ...payload, state: "FAILED", element: "Project general settings" }, - }); - setToast({ - type: TOAST_TYPE.ERROR, - title: t("toast.error"), - message: error?.error ?? t("project_settings.general.toast.error"), - }); + .catch((err) => { + try { + captureError({ + eventName: PROJECT_TRACKER_EVENTS.update, + payload: { + id: projectId, + }, + }); + + // Handle the new error format where codes are nested in arrays under field names + const errorData = err ?? {}; + + const nameError = errorData.name?.includes("PROJECT_NAME_ALREADY_EXIST"); + const identifierError = errorData?.identifier?.includes("PROJECT_IDENTIFIER_ALREADY_EXIST"); + + if (nameError || identifierError) { + if (nameError) { + setToast({ + type: TOAST_TYPE.ERROR, + title: t("toast.error"), + message: t("project_name_already_taken"), + }); + } + + if (identifierError) { + setToast({ + type: TOAST_TYPE.ERROR, + title: t("toast.error"), + message: t("project_identifier_already_taken"), + }); + } + } else { + setToast({ + type: TOAST_TYPE.ERROR, + title: t("toast.error"), + message: t("something_went_wrong"), + }); + } + } catch (error) { + // Fallback error handling if the error processing fails + console.error("Error processing API error:", error); + setToast({ + type: TOAST_TYPE.ERROR, + title: t("toast.error"), + message: t("something_went_wrong"), + }); + } }); }; @@ -397,7 +429,13 @@ export const ProjectDetailsForm: FC = (props) => {
    <> - diff --git a/web/core/components/project/header.tsx b/apps/web/core/components/project/header.tsx similarity index 87% rename from web/core/components/project/header.tsx rename to apps/web/core/components/project/header.tsx index e40280373..1abd5a91d 100644 --- a/web/core/components/project/header.tsx +++ b/apps/web/core/components/project/header.tsx @@ -4,14 +4,15 @@ import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; import { Briefcase } from "lucide-react"; // i18n -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui import { Breadcrumbs, Button, Header } from "@plane/ui"; // components import { BreadcrumbLink } from "@/components/common"; +import { captureClick } from "@/helpers/event-tracker.helper"; // hooks -import { useCommandPalette, useEventTracker, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useUserPermissions } from "@/hooks/store"; // plane web constants // components import HeaderFilters from "./filters"; @@ -22,7 +23,6 @@ export const ProjectsBaseHeader = observer(() => { const { t } = useTranslation(); // store hooks const { toggleCreateProjectModal } = useCommandPalette(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); const pathname = usePathname(); @@ -57,9 +57,9 @@ export const ProjectsBaseHeader = observer(() => { diff --git a/web/core/components/project/member-select.tsx b/apps/web/core/components/project/member-select.tsx similarity index 98% rename from web/core/components/project/member-select.tsx rename to apps/web/core/components/project/member-select.tsx index 15aaee224..8a61883e2 100644 --- a/web/core/components/project/member-select.tsx +++ b/apps/web/core/components/project/member-select.tsx @@ -4,8 +4,8 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Ban } from "lucide-react"; +import { EUserProjectRoles } from "@plane/types"; // plane ui -import { EUserProjectRoles } from "@plane/constants"; import { Avatar, CustomSearchSelect } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; diff --git a/web/core/components/project/multi-select-modal.tsx b/apps/web/core/components/project/multi-select-modal.tsx similarity index 100% rename from web/core/components/project/multi-select-modal.tsx rename to apps/web/core/components/project/multi-select-modal.tsx diff --git a/web/core/components/project/project-feature-update.tsx b/apps/web/core/components/project/project-feature-update.tsx similarity index 100% rename from web/core/components/project/project-feature-update.tsx rename to apps/web/core/components/project/project-feature-update.tsx diff --git a/web/core/components/project/project-network-icon.tsx b/apps/web/core/components/project/project-network-icon.tsx similarity index 100% rename from web/core/components/project/project-network-icon.tsx rename to apps/web/core/components/project/project-network-icon.tsx diff --git a/web/core/components/project/project-settings-member-defaults.tsx b/apps/web/core/components/project/project-settings-member-defaults.tsx similarity index 100% rename from web/core/components/project/project-settings-member-defaults.tsx rename to apps/web/core/components/project/project-settings-member-defaults.tsx diff --git a/web/core/components/project/publish-project/index.ts b/apps/web/core/components/project/publish-project/index.ts similarity index 100% rename from web/core/components/project/publish-project/index.ts rename to apps/web/core/components/project/publish-project/index.ts diff --git a/web/core/components/project/publish-project/modal.tsx b/apps/web/core/components/project/publish-project/modal.tsx similarity index 93% rename from web/core/components/project/publish-project/modal.tsx rename to apps/web/core/components/project/publish-project/modal.tsx index a980b2eac..5cef17448 100644 --- a/web/core/components/project/publish-project/modal.tsx +++ b/apps/web/core/components/project/publish-project/modal.tsx @@ -7,7 +7,7 @@ import { Controller, useForm } from "react-hook-form"; import { Check, ExternalLink, Globe2 } from "lucide-react"; // types import { SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants"; -import { IProject, TProjectPublishLayouts, TProjectPublishSettings } from "@plane/types"; +import { TProjectPublishLayouts, TProjectPublishSettings } from "@plane/types"; // ui import { Button, Loader, ToggleSwitch, TOAST_TYPE, setToast, CustomSelect, ModalCore, EModalWidth } from "@plane/ui"; // helpers @@ -17,7 +17,7 @@ import { useProjectPublish } from "@/hooks/store"; type Props = { isOpen: boolean; - project: IProject; + projectId: string; onClose: () => void; }; @@ -41,7 +41,7 @@ const VIEW_OPTIONS: { ]; export const PublishProjectModal: React.FC = observer((props) => { - const { isOpen, project, onClose } = props; + const { isOpen, onClose, projectId } = props; // states const [isUnPublishing, setIsUnPublishing] = useState(false); // router @@ -56,7 +56,8 @@ export const PublishProjectModal: React.FC = observer((props) => { fetchSettingsLoader, } = useProjectPublish(); // derived values - const projectPublishSettings = getPublishSettingsByProjectID(project.id); + const projectPublishSettings = getPublishSettingsByProjectID(projectId); + const isProjectPublished = !!projectPublishSettings?.anchor; // form info const { control, @@ -77,19 +78,19 @@ export const PublishProjectModal: React.FC = observer((props) => { if (!workspaceSlug || !isOpen) return; if (!projectPublishSettings) { - fetchPublishSettings(workspaceSlug.toString(), project.id); + fetchPublishSettings(workspaceSlug.toString(), projectId); } - }, [fetchPublishSettings, isOpen, project, projectPublishSettings, workspaceSlug]); + }, [fetchPublishSettings, isOpen, projectId, projectPublishSettings, workspaceSlug]); const handlePublishProject = async (payload: Partial) => { if (!workspaceSlug) return; - await publishProject(workspaceSlug.toString(), project.id, payload); + await publishProject(workspaceSlug.toString(), projectId, payload); }; const handleUpdatePublishSettings = async (payload: Partial) => { if (!workspaceSlug || !payload.id) return; - await updatePublishSettings(workspaceSlug.toString(), project.id, payload.id, payload).then((res) => { + await updatePublishSettings(workspaceSlug.toString(), projectId, payload.id, payload).then((res) => { setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -106,7 +107,7 @@ export const PublishProjectModal: React.FC = observer((props) => { setIsUnPublishing(true); - await unPublishProject(workspaceSlug.toString(), project.id, publishId) + await unPublishProject(workspaceSlug.toString(), projectId, publishId) .catch(() => setToast({ type: TOAST_TYPE.ERROR, @@ -142,7 +143,7 @@ export const PublishProjectModal: React.FC = observer((props) => { view_props: formData.view_props, }; - if (formData.id && project.anchor) await handleUpdatePublishSettings(payload); + if (formData.id && isProjectPublished) await handleUpdatePublishSettings(payload); else await handlePublishProject(payload); }; @@ -173,7 +174,7 @@ export const PublishProjectModal: React.FC = observer((props) => {
    Publish project
    - {project.anchor && ( + {isProjectPublished && ( @@ -190,7 +191,7 @@ export const PublishProjectModal: React.FC = observer((props) => { ) : (
    - {project.anchor && projectPublishSettings && ( + {isProjectPublished && projectPublishSettings && ( <>
    = observer((props) => { - {project.anchor ? ( + {isProjectPublished ? ( isDirty && (
    diff --git a/web/core/components/project/settings/features-list.tsx b/apps/web/core/components/project/settings/features-list.tsx similarity index 89% rename from web/core/components/project/settings/features-list.tsx rename to apps/web/core/components/project/settings/features-list.tsx index faa41a0e1..48b1fcac9 100644 --- a/web/core/components/project/settings/features-list.tsx +++ b/apps/web/core/components/project/settings/features-list.tsx @@ -2,12 +2,14 @@ import { FC } from "react"; import { observer } from "mobx-react"; +import { PROJECT_TRACKER_ELEMENTS, PROJECT_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IProject } from "@plane/types"; import { ToggleSwitch, Tooltip, setPromiseToast } from "@plane/ui"; // hooks import { SettingsHeading } from "@/components/settings"; -import { useEventTracker, useProject, useUser } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; +import { useProject, useUser } from "@/hooks/store"; // plane web components import { UpgradeBadge } from "@/plane-web/components/workspace"; // plane web constants @@ -23,7 +25,6 @@ export const ProjectFeaturesList: FC = observer((props) => { const { workspaceSlug, projectId, isAdmin } = props; // store hooks const { t } = useTranslation(); - const { captureEvent } = useEventTracker(); const { data: currentUser } = useUser(); const { getProjectById, updateProject } = useProject(); // derived values @@ -32,17 +33,12 @@ export const ProjectFeaturesList: FC = observer((props) => { const handleSubmit = async (featureKey: string, featureProperty: string) => { if (!workspaceSlug || !projectId || !currentProjectDetails) return; - // capturing event - captureEvent(`Toggle ${featureKey}`, { - enabled: !currentProjectDetails?.[featureProperty as keyof IProject], - element: "Project settings feature page", - }); - // making the request to update the project feature const settingsPayload = { [featureProperty]: !currentProjectDetails?.[featureProperty as keyof IProject], }; const updateProjectPromise = updateProject(workspaceSlug, projectId, settingsPayload); + setPromiseToast(updateProjectPromise, { loading: "Updating project feature...", success: { @@ -54,6 +50,14 @@ export const ProjectFeaturesList: FC = observer((props) => { message: () => "Something went wrong while updating project feature. Please try again.", }, }); + updateProjectPromise.then(() => { + captureSuccess({ + eventName: PROJECT_TRACKER_EVENTS.feature_toggled, + payload: { + feature_key: featureKey, + }, + }); + }); }; if (!currentUser) return <>; @@ -92,6 +96,7 @@ export const ProjectFeaturesList: FC = observer((props) => { onChange={() => handleSubmit(featureItemKey, featureItem.property)} disabled={!featureItem.isEnabled || !isAdmin} size="sm" + data-ph-element={PROJECT_TRACKER_ELEMENTS.TOGGLE_FEATURE} />
    diff --git a/web/core/components/project/settings/index.ts b/apps/web/core/components/project/settings/index.ts similarity index 100% rename from web/core/components/project/settings/index.ts rename to apps/web/core/components/project/settings/index.ts diff --git a/web/core/components/project/settings/member-columns.tsx b/apps/web/core/components/project/settings/member-columns.tsx similarity index 96% rename from web/core/components/project/settings/member-columns.tsx rename to apps/web/core/components/project/settings/member-columns.tsx index 393a4012a..74315bbd5 100644 --- a/web/core/components/project/settings/member-columns.tsx +++ b/apps/web/core/components/project/settings/member-columns.tsx @@ -4,8 +4,8 @@ import { Controller, useForm } from "react-hook-form"; import { CircleMinus } from "lucide-react"; import { Disclosure } from "@headlessui/react"; // plane imports -import { ROLE, EUserPermissions, EUserProjectRoles } from "@plane/constants"; -import { IUser, IWorkspaceMember, TProjectMembership } from "@plane/types"; +import { ROLE, EUserPermissions, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; +import { EUserProjectRoles, IUser, IWorkspaceMember, TProjectMembership } from "@plane/types"; import { CustomMenu, CustomSelect, TOAST_TYPE, setToast } from "@plane/ui"; import { getFileURL } from "@plane/utils"; // hooks @@ -70,6 +70,7 @@ export const NameColumn: React.FC = (props) => {
    setRemoveMemberModal(rowData)} > diff --git a/web/core/components/settings/content-wrapper.tsx b/apps/web/core/components/settings/content-wrapper.tsx similarity index 100% rename from web/core/components/settings/content-wrapper.tsx rename to apps/web/core/components/settings/content-wrapper.tsx diff --git a/web/core/components/settings/header.tsx b/apps/web/core/components/settings/header.tsx similarity index 88% rename from web/core/components/settings/header.tsx rename to apps/web/core/components/settings/header.tsx index 0beb28c93..832f7f39b 100644 --- a/web/core/components/settings/header.tsx +++ b/apps/web/core/components/settings/header.tsx @@ -2,6 +2,7 @@ import { observer } from "mobx-react"; import Link from "next/link"; +import { useTheme } from "next-themes"; import { ChevronLeftIcon } from "lucide-react"; import { useTranslation } from "@plane/i18n"; import { getButtonStyling } from "@plane/ui/src/button"; @@ -15,16 +16,16 @@ export const SettingsHeader = observer(() => { const { t } = useTranslation(); const { currentWorkspace } = useWorkspace(); const { isScrolled } = useUserSettings(); + // resolved theme + const { resolvedTheme } = useTheme(); // redirect url for normal mode return (
    { diff --git a/web/core/components/settings/heading.tsx b/apps/web/core/components/settings/heading.tsx similarity index 100% rename from web/core/components/settings/heading.tsx rename to apps/web/core/components/settings/heading.tsx diff --git a/web/core/components/settings/helper.ts b/apps/web/core/components/settings/helper.ts similarity index 100% rename from web/core/components/settings/helper.ts rename to apps/web/core/components/settings/helper.ts diff --git a/web/core/components/settings/index.ts b/apps/web/core/components/settings/index.ts similarity index 100% rename from web/core/components/settings/index.ts rename to apps/web/core/components/settings/index.ts diff --git a/web/core/components/settings/layout.tsx b/apps/web/core/components/settings/layout.tsx similarity index 100% rename from web/core/components/settings/layout.tsx rename to apps/web/core/components/settings/layout.tsx diff --git a/web/core/components/settings/mobile/index.ts b/apps/web/core/components/settings/mobile/index.ts similarity index 100% rename from web/core/components/settings/mobile/index.ts rename to apps/web/core/components/settings/mobile/index.ts diff --git a/web/core/components/settings/mobile/nav.tsx b/apps/web/core/components/settings/mobile/nav.tsx similarity index 100% rename from web/core/components/settings/mobile/nav.tsx rename to apps/web/core/components/settings/mobile/nav.tsx diff --git a/web/core/components/stickies/sticky/index.ts b/apps/web/core/components/settings/project/sidebar/index.ts similarity index 100% rename from web/core/components/stickies/sticky/index.ts rename to apps/web/core/components/settings/project/sidebar/index.ts diff --git a/web/core/components/settings/project/sidebar/nav-item-children.tsx b/apps/web/core/components/settings/project/sidebar/nav-item-children.tsx similarity index 100% rename from web/core/components/settings/project/sidebar/nav-item-children.tsx rename to apps/web/core/components/settings/project/sidebar/nav-item-children.tsx diff --git a/web/core/components/settings/project/sidebar/root.tsx b/apps/web/core/components/settings/project/sidebar/root.tsx similarity index 100% rename from web/core/components/settings/project/sidebar/root.tsx rename to apps/web/core/components/settings/project/sidebar/root.tsx diff --git a/web/core/components/settings/sidebar/header.tsx b/apps/web/core/components/settings/sidebar/header.tsx similarity index 100% rename from web/core/components/settings/sidebar/header.tsx rename to apps/web/core/components/settings/sidebar/header.tsx diff --git a/web/ee/components/issues/issue-details/issue-properties-activity/index.ts b/apps/web/core/components/settings/sidebar/index.ts similarity index 100% rename from web/ee/components/issues/issue-details/issue-properties-activity/index.ts rename to apps/web/core/components/settings/sidebar/index.ts diff --git a/web/core/components/settings/sidebar/nav-item.tsx b/apps/web/core/components/settings/sidebar/nav-item.tsx similarity index 98% rename from web/core/components/settings/sidebar/nav-item.tsx rename to apps/web/core/components/settings/sidebar/nav-item.tsx index 14bac592b..af1d139d6 100644 --- a/web/core/components/settings/sidebar/nav-item.tsx +++ b/apps/web/core/components/settings/sidebar/nav-item.tsx @@ -4,8 +4,8 @@ import Link from "next/link"; import { useParams } from "next/navigation"; import { Disclosure } from "@headlessui/react"; // plane imports -import { EUserWorkspaceRoles } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EUserWorkspaceRoles } from "@plane/types"; import { cn, joinUrlPath } from "@plane/utils"; // hooks import { useUserSettings } from "@/hooks/store"; diff --git a/web/core/components/settings/sidebar/root.tsx b/apps/web/core/components/settings/sidebar/root.tsx similarity index 95% rename from web/core/components/settings/sidebar/root.tsx rename to apps/web/core/components/settings/sidebar/root.tsx index c681a8cc1..7dd07744f 100644 --- a/web/core/components/settings/sidebar/root.tsx +++ b/apps/web/core/components/settings/sidebar/root.tsx @@ -45,12 +45,12 @@ export const SettingsSidebar = observer((props: SettingsSidebarProps) => { {/* Header */} {/* Navigation */} -
    +
    {categories.map((category) => { if (groupedSettings[category].length === 0) return null; return (
    - {t(category)} + {t(category)}
    {groupedSettings[category].map( (setting) => diff --git a/web/core/components/settings/tabs.tsx b/apps/web/core/components/settings/tabs.tsx similarity index 100% rename from web/core/components/settings/tabs.tsx rename to apps/web/core/components/settings/tabs.tsx diff --git a/apps/web/core/components/sidebar/index.ts b/apps/web/core/components/sidebar/index.ts new file mode 100644 index 000000000..c639b0bac --- /dev/null +++ b/apps/web/core/components/sidebar/index.ts @@ -0,0 +1,4 @@ +export * from "./sidebar-navigation"; +export * from "./resizable-sidebar"; +export * from "./sidebar-item"; +export * from "./sidebar-toggle-button"; diff --git a/apps/web/core/components/sidebar/resizable-sidebar.tsx b/apps/web/core/components/sidebar/resizable-sidebar.tsx new file mode 100644 index 000000000..ddfd2ef9f --- /dev/null +++ b/apps/web/core/components/sidebar/resizable-sidebar.tsx @@ -0,0 +1,296 @@ +"use client"; + +import React, { Dispatch, ReactElement, SetStateAction, useCallback, useEffect, useState, useRef } from "react"; +// helpers +import { cn } from "@plane/utils"; + +interface ResizableSidebarProps { + showPeek?: boolean; + togglePeek: (value?: boolean) => void; + isCollapsed?: boolean; + width: number; + setWidth: Dispatch>; + defaultWidth?: number; + minWidth?: number; + maxWidth?: number; + defaultCollapsed?: boolean; + peekDuration?: number; + toggleCollapsed: (value?: boolean) => void; + onWidthChange?: (width: number) => void; + onCollapsedChange?: (collapsed: boolean) => void; + className?: string; + children?: ReactElement; + extendedSidebar?: ReactElement; + isAnyExtendedSidebarExpanded?: boolean; + isAnySidebarDropdownOpen?: boolean; + disablePeekTrigger?: boolean; +} + +export function ResizableSidebar({ + showPeek = false, + togglePeek, + peekDuration = 500, + isCollapsed = false, + toggleCollapsed: toggleCollapsedProp, + onCollapsedChange, + width, + setWidth, + onWidthChange, + minWidth = 236, + maxWidth = 350, + className = "", + children, + extendedSidebar, + isAnyExtendedSidebarExpanded = false, + isAnySidebarDropdownOpen = false, + disablePeekTrigger = false, +}: ResizableSidebarProps) { + // states + const [isResizing, setIsResizing] = useState(false); + const [isHoveringTrigger, setIsHoveringTrigger] = useState(false); + // refs + const peekTimeoutRef = useRef>(); + const initialWidthRef = useRef(0); + const initialMouseXRef = useRef(0); + + // handlers + const setShowPeek = useCallback( + (value: boolean) => { + togglePeek(value); + }, + [togglePeek] + ); + + const handleResize = useCallback( + (e: MouseEvent) => { + if (!isResizing) return; + + const deltaX = e.clientX - initialMouseXRef.current; + const newWidth = Math.min(Math.max(initialWidthRef.current + deltaX, minWidth), maxWidth); + setWidth(newWidth); + }, + [isResizing, minWidth, maxWidth, setWidth] + ); + + const startResizing = useCallback( + (e: React.MouseEvent) => { + setIsResizing(true); + initialWidthRef.current = width; + initialMouseXRef.current = e.clientX; + }, + [width] + ); + + const stopResizing = useCallback(() => { + setIsResizing(false); + }, []); + + const toggleCollapsed = useCallback(() => { + toggleCollapsedProp(); + setShowPeek(false); + setIsHoveringTrigger(false); + if (peekTimeoutRef.current) { + clearTimeout(peekTimeoutRef.current); + } + }, [toggleCollapsedProp, setShowPeek]); + + const handleTriggerEnter = useCallback(() => { + if (isCollapsed) { + setIsHoveringTrigger(true); + setShowPeek(true); + if (peekTimeoutRef.current) { + clearTimeout(peekTimeoutRef.current); + } + } + }, [isCollapsed, setShowPeek]); + + const handleTriggerLeave = useCallback(() => { + if (isCollapsed && !isAnyExtendedSidebarExpanded) { + setIsHoveringTrigger(false); + peekTimeoutRef.current = setTimeout(() => { + setShowPeek(false); + }, peekDuration); + } + }, [isCollapsed, peekDuration, setShowPeek, isAnyExtendedSidebarExpanded]); + + const handlePeekEnter = useCallback(() => { + if (isCollapsed && showPeek) { + if (peekTimeoutRef.current) { + clearTimeout(peekTimeoutRef.current); + } + } + }, [isCollapsed, showPeek]); + + const handlePeekLeave = useCallback(() => { + if (isCollapsed && !isAnyExtendedSidebarExpanded && !isAnySidebarDropdownOpen) { + peekTimeoutRef.current = setTimeout(() => { + setShowPeek(false); + }, peekDuration); + } + }, [isCollapsed, peekDuration, setShowPeek, isAnyExtendedSidebarExpanded, isAnySidebarDropdownOpen]); + + // Set up event listeners for resizing + useEffect(() => { + if (isResizing) { + document.addEventListener("mousemove", handleResize); + document.addEventListener("mouseup", stopResizing); + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; + } + + return () => { + document.removeEventListener("mousemove", handleResize); + document.removeEventListener("mouseup", stopResizing); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + }; + }, [isResizing, handleResize, stopResizing]); + + // Clean up timeout on unmount + useEffect( + () => () => { + if (peekTimeoutRef.current) { + clearTimeout(peekTimeoutRef.current); + } + }, + [] + ); + + useEffect(() => { + if (!isAnySidebarDropdownOpen && isCollapsed && isHoveringTrigger) { + handlePeekLeave(); + } + }, [isAnySidebarDropdownOpen]); + + useEffect(() => { + if (!isAnyExtendedSidebarExpanded && isCollapsed && isHoveringTrigger) { + handlePeekLeave(); + } + }, [isAnyExtendedSidebarExpanded]); + + // Reset peek when sidebar is expanded + useEffect(() => { + if (!isCollapsed) { + setShowPeek(false); + setIsHoveringTrigger(false); + if (peekTimeoutRef.current) { + clearTimeout(peekTimeoutRef.current); + } + } + }, [isCollapsed, setShowPeek]); + + // Call external handlers when state changes + useEffect(() => { + onWidthChange?.(width); + }, [width, onWidthChange]); + + useEffect(() => { + onCollapsedChange?.(isCollapsed); + }, [isCollapsed, onCollapsedChange]); + + return ( + <> + {/* Main Sidebar */} +
    + +
    + + {/* Peek Trigger Area */} + {isCollapsed && !disablePeekTrigger && ( +
    + )} + + {/* Peek View */} +
    + +
    + + {/* Extended Sidebar */} + {extendedSidebar && extendedSidebar} + + ); +} diff --git a/apps/web/core/components/sidebar/sidebar-item.tsx b/apps/web/core/components/sidebar/sidebar-item.tsx new file mode 100644 index 000000000..48d0b0ccf --- /dev/null +++ b/apps/web/core/components/sidebar/sidebar-item.tsx @@ -0,0 +1,158 @@ +import Link from "next/link"; +import { cn } from "@plane/utils"; + +// ============================================================================ +// TYPES +// ============================================================================ + +interface AppSidebarItemData { + href?: string; + label?: string; + icon?: React.ReactNode; + isActive?: boolean; + onClick?: () => void; + disabled?: boolean; +} + +interface AppSidebarItemProps { + variant?: "link" | "button"; + item?: AppSidebarItemData; +} + +interface AppSidebarItemLabelProps { + highlight?: boolean; + label?: string; +} + +interface AppSidebarItemIconProps { + icon?: React.ReactNode; + highlight?: boolean; +} + +interface AppSidebarLinkItemProps { + href?: string; + children: React.ReactNode; + className?: string; +} + +interface AppSidebarButtonItemProps { + children: React.ReactNode; + onClick?: () => void; + disabled?: boolean; + className?: string; +} + +// ============================================================================ +// STYLES +// ============================================================================ + +const styles = { + base: "group flex flex-col gap-0.5 items-center justify-center text-custom-text-300", + icon: "flex items-center justify-center gap-2 size-8 rounded-md text-custom-text-300", + iconActive: "bg-custom-background-80 text-custom-text-200", + iconInactive: "group-hover:text-custom-text-200 group-hover:bg-custom-background-80", + label: "text-xs font-semibold", + labelActive: "text-custom-text-200", + labelInactive: "group-hover:text-custom-text-200 text-custom-text-300", +} as const; + +// ============================================================================ +// SUB-COMPONENTS +// ============================================================================ + +const AppSidebarItemLabel: React.FC = ({ highlight = false, label }) => { + if (!label) return null; + + return ( + + {label} + + ); +}; + +const AppSidebarItemIcon: React.FC = ({ icon, highlight }) => { + if (!icon) return null; + + return ( +
    + {icon} +
    + ); +}; + +const AppSidebarLinkItem: React.FC = ({ href, children, className }) => { + if (!href) return null; + + return ( + + {children} + + ); +}; + +const AppSidebarButtonItem: React.FC = ({ + children, + onClick, + disabled = false, + className, +}) => ( + +); + +// ============================================================================ +// MAIN COMPONENT +// ============================================================================ + +type AppSidebarItemComponent = React.FC & { + Label: React.FC; + Icon: React.FC; + Link: React.FC; + Button: React.FC; +}; + +const AppSidebarItem: AppSidebarItemComponent = ({ variant = "link", item }) => { + if (!item) return null; + + const { icon, isActive, label, href, onClick, disabled } = item; + + const commonItems = ( + <> + + + + ); + + if (variant === "link") { + return {commonItems}; + } + + return ( + + {commonItems} + + ); +}; + +// ============================================================================ +// COMPOUND COMPONENT ASSIGNMENT +// ============================================================================ + +AppSidebarItem.Label = AppSidebarItemLabel; +AppSidebarItem.Icon = AppSidebarItemIcon; +AppSidebarItem.Link = AppSidebarLinkItem; +AppSidebarItem.Button = AppSidebarButtonItem; + +export { AppSidebarItem }; +export type { AppSidebarItemData, AppSidebarItemProps }; diff --git a/web/core/components/sidebar/sidebar-navigation.tsx b/apps/web/core/components/sidebar/sidebar-navigation.tsx similarity index 100% rename from web/core/components/sidebar/sidebar-navigation.tsx rename to apps/web/core/components/sidebar/sidebar-navigation.tsx diff --git a/apps/web/core/components/sidebar/sidebar-toggle-button.tsx b/apps/web/core/components/sidebar/sidebar-toggle-button.tsx new file mode 100644 index 000000000..45caea0c6 --- /dev/null +++ b/apps/web/core/components/sidebar/sidebar-toggle-button.tsx @@ -0,0 +1,23 @@ +"use client"; + +import { observer } from "mobx-react"; +import { PanelLeft } from "lucide-react"; +// hooks +import { useAppTheme } from "@/hooks/store"; + +export const AppSidebarToggleButton = observer(() => { + // store hooks + const { toggleSidebar, sidebarPeek, toggleSidebarPeek } = useAppTheme(); + + return ( + + ); +}); diff --git a/web/core/components/stickies/action-bar.tsx b/apps/web/core/components/stickies/action-bar.tsx similarity index 100% rename from web/core/components/stickies/action-bar.tsx rename to apps/web/core/components/stickies/action-bar.tsx diff --git a/web/core/components/stickies/delete-modal.tsx b/apps/web/core/components/stickies/delete-modal.tsx similarity index 100% rename from web/core/components/stickies/delete-modal.tsx rename to apps/web/core/components/stickies/delete-modal.tsx diff --git a/web/core/components/stickies/index.ts b/apps/web/core/components/stickies/index.ts similarity index 100% rename from web/core/components/stickies/index.ts rename to apps/web/core/components/stickies/index.ts diff --git a/web/core/components/stickies/layout/index.ts b/apps/web/core/components/stickies/layout/index.ts similarity index 100% rename from web/core/components/stickies/layout/index.ts rename to apps/web/core/components/stickies/layout/index.ts diff --git a/web/core/components/stickies/layout/stickies-infinite.tsx b/apps/web/core/components/stickies/layout/stickies-infinite.tsx similarity index 100% rename from web/core/components/stickies/layout/stickies-infinite.tsx rename to apps/web/core/components/stickies/layout/stickies-infinite.tsx diff --git a/web/core/components/stickies/layout/stickies-list.tsx b/apps/web/core/components/stickies/layout/stickies-list.tsx similarity index 97% rename from web/core/components/stickies/layout/stickies-list.tsx rename to apps/web/core/components/stickies/layout/stickies-list.tsx index 47e6e6698..a04424ce3 100644 --- a/web/core/components/stickies/layout/stickies-list.tsx +++ b/apps/web/core/components/stickies/layout/stickies-list.tsx @@ -9,8 +9,9 @@ import { usePathname } from "next/navigation"; import Masonry from "react-masonry-component"; import { Plus } from "lucide-react"; // plane imports -import { EUserPermissionsLevel, EUserWorkspaceRoles } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EUserWorkspaceRoles } from "@plane/types"; // components import { DetailedEmptyState, SimpleEmptyState } from "@/components/empty-state"; import { StickiesEmptyState } from "@/components/home/widgets/empty-states/stickies"; @@ -184,7 +185,7 @@ export const StickiesLayout = (props: TStickiesLayout) => { if (width === null) return 4; if (width < 640) return 2; // sm - if (width < 768) return 3; // md + if (width < 850) return 3; // md if (width < 1024) return 4; // lg if (width < 1280) return 5; // xl return 6; // 2xl and above diff --git a/web/core/components/stickies/layout/stickies-loader.tsx b/apps/web/core/components/stickies/layout/stickies-loader.tsx similarity index 100% rename from web/core/components/stickies/layout/stickies-loader.tsx rename to apps/web/core/components/stickies/layout/stickies-loader.tsx diff --git a/web/core/components/stickies/layout/stickies-truncated.tsx b/apps/web/core/components/stickies/layout/stickies-truncated.tsx similarity index 100% rename from web/core/components/stickies/layout/stickies-truncated.tsx rename to apps/web/core/components/stickies/layout/stickies-truncated.tsx diff --git a/web/core/components/stickies/layout/sticky-dnd-wrapper.tsx b/apps/web/core/components/stickies/layout/sticky-dnd-wrapper.tsx similarity index 100% rename from web/core/components/stickies/layout/sticky-dnd-wrapper.tsx rename to apps/web/core/components/stickies/layout/sticky-dnd-wrapper.tsx diff --git a/web/core/components/stickies/layout/sticky.helpers.ts b/apps/web/core/components/stickies/layout/sticky.helpers.ts similarity index 100% rename from web/core/components/stickies/layout/sticky.helpers.ts rename to apps/web/core/components/stickies/layout/sticky.helpers.ts diff --git a/web/core/components/stickies/modal/index.tsx b/apps/web/core/components/stickies/modal/index.tsx similarity index 100% rename from web/core/components/stickies/modal/index.tsx rename to apps/web/core/components/stickies/modal/index.tsx diff --git a/web/core/components/stickies/modal/search.tsx b/apps/web/core/components/stickies/modal/search.tsx similarity index 100% rename from web/core/components/stickies/modal/search.tsx rename to apps/web/core/components/stickies/modal/search.tsx diff --git a/web/core/components/stickies/modal/stickies.tsx b/apps/web/core/components/stickies/modal/stickies.tsx similarity index 100% rename from web/core/components/stickies/modal/stickies.tsx rename to apps/web/core/components/stickies/modal/stickies.tsx diff --git a/web/ee/components/issues/quick-add/index.ts b/apps/web/core/components/stickies/sticky/index.ts similarity index 100% rename from web/ee/components/issues/quick-add/index.ts rename to apps/web/core/components/stickies/sticky/index.ts diff --git a/web/core/components/stickies/sticky/inputs.tsx b/apps/web/core/components/stickies/sticky/inputs.tsx similarity index 100% rename from web/core/components/stickies/sticky/inputs.tsx rename to apps/web/core/components/stickies/sticky/inputs.tsx diff --git a/web/core/components/stickies/sticky/root.tsx b/apps/web/core/components/stickies/sticky/root.tsx similarity index 100% rename from web/core/components/stickies/sticky/root.tsx rename to apps/web/core/components/stickies/sticky/root.tsx diff --git a/web/core/components/stickies/sticky/sticky-item-drag-handle.tsx b/apps/web/core/components/stickies/sticky/sticky-item-drag-handle.tsx similarity index 100% rename from web/core/components/stickies/sticky/sticky-item-drag-handle.tsx rename to apps/web/core/components/stickies/sticky/sticky-item-drag-handle.tsx diff --git a/web/core/components/stickies/sticky/use-operations.tsx b/apps/web/core/components/stickies/sticky/use-operations.tsx similarity index 100% rename from web/core/components/stickies/sticky/use-operations.tsx rename to apps/web/core/components/stickies/sticky/use-operations.tsx diff --git a/web/core/components/stickies/widget.tsx b/apps/web/core/components/stickies/widget.tsx similarity index 100% rename from web/core/components/stickies/widget.tsx rename to apps/web/core/components/stickies/widget.tsx diff --git a/web/core/components/ui/empty-space.tsx b/apps/web/core/components/ui/empty-space.tsx similarity index 100% rename from web/core/components/ui/empty-space.tsx rename to apps/web/core/components/ui/empty-space.tsx diff --git a/web/core/components/ui/index.ts b/apps/web/core/components/ui/index.ts similarity index 100% rename from web/core/components/ui/index.ts rename to apps/web/core/components/ui/index.ts diff --git a/web/core/components/ui/integration-and-import-export-banner.tsx b/apps/web/core/components/ui/integration-and-import-export-banner.tsx similarity index 100% rename from web/core/components/ui/integration-and-import-export-banner.tsx rename to apps/web/core/components/ui/integration-and-import-export-banner.tsx diff --git a/web/core/components/ui/labels-list.tsx b/apps/web/core/components/ui/labels-list.tsx similarity index 100% rename from web/core/components/ui/labels-list.tsx rename to apps/web/core/components/ui/labels-list.tsx diff --git a/web/core/components/ui/loader/cycle-module-board-loader.tsx b/apps/web/core/components/ui/loader/cycle-module-board-loader.tsx similarity index 100% rename from web/core/components/ui/loader/cycle-module-board-loader.tsx rename to apps/web/core/components/ui/loader/cycle-module-board-loader.tsx diff --git a/web/core/components/ui/loader/cycle-module-list-loader.tsx b/apps/web/core/components/ui/loader/cycle-module-list-loader.tsx similarity index 100% rename from web/core/components/ui/loader/cycle-module-list-loader.tsx rename to apps/web/core/components/ui/loader/cycle-module-list-loader.tsx diff --git a/web/core/components/ui/loader/index.ts b/apps/web/core/components/ui/loader/index.ts similarity index 100% rename from web/core/components/ui/loader/index.ts rename to apps/web/core/components/ui/loader/index.ts diff --git a/web/core/components/ui/loader/layouts/calendar-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/calendar-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/calendar-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/calendar-layout-loader.tsx diff --git a/web/core/components/ui/loader/layouts/gantt-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/gantt-layout-loader.tsx similarity index 92% rename from web/core/components/ui/loader/layouts/gantt-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/gantt-layout-loader.tsx index 50a5ac56a..c658d1914 100644 --- a/web/core/components/ui/loader/layouts/gantt-layout-loader.tsx +++ b/apps/web/core/components/ui/loader/layouts/gantt-layout-loader.tsx @@ -17,7 +17,7 @@ export const GanttLayoutLoader = () => (
    - +
    @@ -33,7 +33,7 @@ export const GanttLayoutLoader = () => (
    -
    +
    diff --git a/web/core/components/ui/loader/layouts/index.ts b/apps/web/core/components/ui/loader/layouts/index.ts similarity index 100% rename from web/core/components/ui/loader/layouts/index.ts rename to apps/web/core/components/ui/loader/layouts/index.ts diff --git a/web/core/components/ui/loader/layouts/kanban-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/kanban-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/kanban-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/kanban-layout-loader.tsx diff --git a/web/core/components/ui/loader/layouts/list-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/list-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/list-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/list-layout-loader.tsx diff --git a/web/core/components/ui/loader/layouts/members-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/members-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/members-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/members-layout-loader.tsx diff --git a/web/core/components/ui/loader/layouts/project-inbox/inbox-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/project-inbox/inbox-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/project-inbox/inbox-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/project-inbox/inbox-layout-loader.tsx diff --git a/web/core/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader.tsx b/apps/web/core/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader.tsx rename to apps/web/core/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader.tsx diff --git a/web/core/components/ui/loader/layouts/project-inbox/index.ts b/apps/web/core/components/ui/loader/layouts/project-inbox/index.ts similarity index 100% rename from web/core/components/ui/loader/layouts/project-inbox/index.ts rename to apps/web/core/components/ui/loader/layouts/project-inbox/index.ts diff --git a/web/core/components/ui/loader/layouts/spreadsheet-layout-loader.tsx b/apps/web/core/components/ui/loader/layouts/spreadsheet-layout-loader.tsx similarity index 100% rename from web/core/components/ui/loader/layouts/spreadsheet-layout-loader.tsx rename to apps/web/core/components/ui/loader/layouts/spreadsheet-layout-loader.tsx diff --git a/web/core/components/ui/loader/notification-loader.tsx b/apps/web/core/components/ui/loader/notification-loader.tsx similarity index 100% rename from web/core/components/ui/loader/notification-loader.tsx rename to apps/web/core/components/ui/loader/notification-loader.tsx diff --git a/web/core/components/ui/loader/pages-loader.tsx b/apps/web/core/components/ui/loader/pages-loader.tsx similarity index 100% rename from web/core/components/ui/loader/pages-loader.tsx rename to apps/web/core/components/ui/loader/pages-loader.tsx diff --git a/web/core/components/ui/loader/projects-loader.tsx b/apps/web/core/components/ui/loader/projects-loader.tsx similarity index 100% rename from web/core/components/ui/loader/projects-loader.tsx rename to apps/web/core/components/ui/loader/projects-loader.tsx diff --git a/web/core/components/ui/loader/settings/activity.tsx b/apps/web/core/components/ui/loader/settings/activity.tsx similarity index 100% rename from web/core/components/ui/loader/settings/activity.tsx rename to apps/web/core/components/ui/loader/settings/activity.tsx diff --git a/web/core/components/ui/loader/settings/api-token.tsx b/apps/web/core/components/ui/loader/settings/api-token.tsx similarity index 100% rename from web/core/components/ui/loader/settings/api-token.tsx rename to apps/web/core/components/ui/loader/settings/api-token.tsx diff --git a/web/core/components/ui/loader/settings/email.tsx b/apps/web/core/components/ui/loader/settings/email.tsx similarity index 100% rename from web/core/components/ui/loader/settings/email.tsx rename to apps/web/core/components/ui/loader/settings/email.tsx diff --git a/web/core/components/ui/loader/settings/import-and-export.tsx b/apps/web/core/components/ui/loader/settings/import-and-export.tsx similarity index 100% rename from web/core/components/ui/loader/settings/import-and-export.tsx rename to apps/web/core/components/ui/loader/settings/import-and-export.tsx diff --git a/web/core/components/ui/loader/settings/index.ts b/apps/web/core/components/ui/loader/settings/index.ts similarity index 100% rename from web/core/components/ui/loader/settings/index.ts rename to apps/web/core/components/ui/loader/settings/index.ts diff --git a/web/core/components/ui/loader/settings/integration.tsx b/apps/web/core/components/ui/loader/settings/integration.tsx similarity index 100% rename from web/core/components/ui/loader/settings/integration.tsx rename to apps/web/core/components/ui/loader/settings/integration.tsx diff --git a/web/core/components/ui/loader/settings/members.tsx b/apps/web/core/components/ui/loader/settings/members.tsx similarity index 100% rename from web/core/components/ui/loader/settings/members.tsx rename to apps/web/core/components/ui/loader/settings/members.tsx diff --git a/web/core/components/ui/loader/settings/web-hook.tsx b/apps/web/core/components/ui/loader/settings/web-hook.tsx similarity index 100% rename from web/core/components/ui/loader/settings/web-hook.tsx rename to apps/web/core/components/ui/loader/settings/web-hook.tsx diff --git a/web/core/components/ui/loader/utils.tsx b/apps/web/core/components/ui/loader/utils.tsx similarity index 100% rename from web/core/components/ui/loader/utils.tsx rename to apps/web/core/components/ui/loader/utils.tsx diff --git a/web/core/components/ui/loader/view-list-loader.tsx b/apps/web/core/components/ui/loader/view-list-loader.tsx similarity index 100% rename from web/core/components/ui/loader/view-list-loader.tsx rename to apps/web/core/components/ui/loader/view-list-loader.tsx diff --git a/web/core/components/ui/markdown-to-component.tsx b/apps/web/core/components/ui/markdown-to-component.tsx similarity index 100% rename from web/core/components/ui/markdown-to-component.tsx rename to apps/web/core/components/ui/markdown-to-component.tsx diff --git a/web/core/components/ui/profile-empty-state.tsx b/apps/web/core/components/ui/profile-empty-state.tsx similarity index 100% rename from web/core/components/ui/profile-empty-state.tsx rename to apps/web/core/components/ui/profile-empty-state.tsx diff --git a/web/core/components/user/index.ts b/apps/web/core/components/user/index.ts similarity index 100% rename from web/core/components/user/index.ts rename to apps/web/core/components/user/index.ts diff --git a/web/core/components/user/user-greetings.tsx b/apps/web/core/components/user/user-greetings.tsx similarity index 76% rename from web/core/components/user/user-greetings.tsx rename to apps/web/core/components/user/user-greetings.tsx index 216da7a52..1327d2686 100644 --- a/web/core/components/user/user-greetings.tsx +++ b/apps/web/core/components/user/user-greetings.tsx @@ -1,4 +1,6 @@ import { FC } from "react"; +// plane types +import { useTranslation } from "@plane/i18n"; // hooks import { IUser } from "@plane/types"; import { useCurrentTime } from "@/hooks/use-current-time"; @@ -12,6 +14,8 @@ export const UserGreetingsView: FC = (props) => { const { user } = props; // current time hook const { currentTime } = useCurrentTime(); + // store hooks + const { t } = useTranslation(); const hour = new Intl.DateTimeFormat("en-US", { hour12: false, @@ -37,16 +41,16 @@ export const UserGreetingsView: FC = (props) => { const greeting = parseInt(hour, 10) < 12 ? "morning" : parseInt(hour, 10) < 18 ? "afternoon" : "evening"; return ( -
    -

    - Good {greeting}, {user?.first_name} {user?.last_name} -

    -
    +
    +

    + {t("good")} {t(greeting)}, {user?.first_name} {user?.last_name} +

    +
    {greeting === "morning" ? "🌤️" : greeting === "afternoon" ? "🌥️" : "🌙️"}
    {weekDay}, {date} {timeString}
    -
    +
    ); }; diff --git a/web/core/components/views/applied-filters/access.tsx b/apps/web/core/components/views/applied-filters/access.tsx similarity index 96% rename from web/core/components/views/applied-filters/access.tsx rename to apps/web/core/components/views/applied-filters/access.tsx index ce46a800a..d328f61e1 100644 --- a/web/core/components/views/applied-filters/access.tsx +++ b/apps/web/core/components/views/applied-filters/access.tsx @@ -2,9 +2,9 @@ import { observer } from "mobx-react"; // icons import { X } from "lucide-react"; // constants -import { EViewAccess } from "@plane/constants"; // helpers import { useTranslation } from "@plane/i18n"; +import { EViewAccess } from "@plane/types"; import { VIEW_ACCESS_SPECIFIERS } from "@/helpers/views.helper"; type Props = { diff --git a/web/core/components/views/applied-filters/index.tsx b/apps/web/core/components/views/applied-filters/index.tsx similarity index 100% rename from web/core/components/views/applied-filters/index.tsx rename to apps/web/core/components/views/applied-filters/index.tsx diff --git a/web/core/components/views/applied-filters/root.tsx b/apps/web/core/components/views/applied-filters/root.tsx similarity index 96% rename from web/core/components/views/applied-filters/root.tsx rename to apps/web/core/components/views/applied-filters/root.tsx index bb654338e..18e7c04fd 100644 --- a/web/core/components/views/applied-filters/root.tsx +++ b/apps/web/core/components/views/applied-filters/root.tsx @@ -1,7 +1,6 @@ import { X } from "lucide-react"; -import { EViewAccess } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; -import { TViewFilterProps } from "@plane/types"; +import { EViewAccess, TViewFilterProps } from "@plane/types"; // components import { Tag } from "@plane/ui"; import { replaceUnderscoreIfSnakeCase } from "@plane/utils"; diff --git a/web/core/components/views/delete-view-modal.tsx b/apps/web/core/components/views/delete-view-modal.tsx similarity index 100% rename from web/core/components/views/delete-view-modal.tsx rename to apps/web/core/components/views/delete-view-modal.tsx diff --git a/web/core/components/views/filters/filter-selection.tsx b/apps/web/core/components/views/filters/filter-selection.tsx similarity index 97% rename from web/core/components/views/filters/filter-selection.tsx rename to apps/web/core/components/views/filters/filter-selection.tsx index d2a32fb79..9dd7d0a4d 100644 --- a/web/core/components/views/filters/filter-selection.tsx +++ b/apps/web/core/components/views/filters/filter-selection.tsx @@ -1,8 +1,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { Search, X } from "lucide-react"; -import { EViewAccess } from "@plane/constants"; -import { TViewFilterProps, TViewFilters } from "@plane/types"; +import { EViewAccess, TViewFilterProps, TViewFilters } from "@plane/types"; // components import { FilterCreatedBy, FilterCreatedDate } from "@/components/common/filters"; import { FilterOption } from "@/components/issues"; diff --git a/web/core/components/views/filters/order-by.tsx b/apps/web/core/components/views/filters/order-by.tsx similarity index 100% rename from web/core/components/views/filters/order-by.tsx rename to apps/web/core/components/views/filters/order-by.tsx diff --git a/web/core/components/views/form.tsx b/apps/web/core/components/views/form.tsx similarity index 97% rename from web/core/components/views/form.tsx rename to apps/web/core/components/views/form.tsx index 2b5e6ab9f..5bfa8bb2d 100644 --- a/web/core/components/views/form.tsx +++ b/apps/web/core/components/views/form.tsx @@ -5,14 +5,26 @@ import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; import { Layers } from "lucide-react"; // plane constants -import { EIssueLayoutTypes, ETabIndices, EViewAccess, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; +import { ETabIndices, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; // types -import { IProjectView, IIssueFilterOptions, IIssueDisplayProperties, IIssueDisplayFilterOptions } from "@plane/types"; +import { + EViewAccess, + IIssueDisplayFilterOptions, + IIssueDisplayProperties, + IIssueFilterOptions, + IProjectView, + EIssueLayoutTypes, +} from "@plane/types"; // ui import { Button, EmojiIconPicker, EmojiIconPickerTypes, Input, TextArea } from "@plane/ui"; -import { convertHexEmojiToDecimal, getComputedDisplayFilters, getComputedDisplayProperties, getTabIndex } from "@plane/utils"; +import { + convertHexEmojiToDecimal, + getComputedDisplayFilters, + getComputedDisplayProperties, + getTabIndex, +} from "@plane/utils"; // components import { Logo } from "@/components/common"; import { AppliedFiltersList, DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues"; diff --git a/web/core/components/views/helper.tsx b/apps/web/core/components/views/helper.tsx similarity index 96% rename from web/core/components/views/helper.tsx rename to apps/web/core/components/views/helper.tsx index 975e103fd..1d4177509 100644 --- a/web/core/components/views/helper.tsx +++ b/apps/web/core/components/views/helper.tsx @@ -1,4 +1,4 @@ -import { EIssueLayoutTypes } from "@plane/constants"; +import { EIssueLayoutTypes } from "@plane/types"; import { WorkspaceAdditionalLayouts } from "@/plane-web/components/views/helper"; import { WorkspaceSpreadsheetRoot } from "../issues/issue-layouts/spreadsheet/roots/workspace-root"; diff --git a/web/core/components/views/index.ts b/apps/web/core/components/views/index.ts similarity index 100% rename from web/core/components/views/index.ts rename to apps/web/core/components/views/index.ts diff --git a/web/core/components/views/modal.tsx b/apps/web/core/components/views/modal.tsx similarity index 100% rename from web/core/components/views/modal.tsx rename to apps/web/core/components/views/modal.tsx diff --git a/web/core/components/views/quick-actions.tsx b/apps/web/core/components/views/quick-actions.tsx similarity index 100% rename from web/core/components/views/quick-actions.tsx rename to apps/web/core/components/views/quick-actions.tsx diff --git a/web/core/components/views/update-view-component.tsx b/apps/web/core/components/views/update-view-component.tsx similarity index 82% rename from web/core/components/views/update-view-component.tsx rename to apps/web/core/components/views/update-view-component.tsx index 5b3f8c79b..0e7990b50 100644 --- a/web/core/components/views/update-view-component.tsx +++ b/apps/web/core/components/views/update-view-component.tsx @@ -1,4 +1,5 @@ import { SetStateAction, useEffect, useState } from "react"; +import { GLOBAL_VIEW_TRACKER_ELEMENTS } from "@plane/constants"; import { Button } from "@plane/ui"; import { LockedComponent } from "../icons/locked-component"; @@ -58,7 +59,13 @@ export const UpdateViewComponent = (props: Props) => { !areFiltersEqual && isAuthorizedUser && ( <> - {isOwner && <>{updateButton}} diff --git a/web/core/components/views/view-list-header.tsx b/apps/web/core/components/views/view-list-header.tsx similarity index 100% rename from web/core/components/views/view-list-header.tsx rename to apps/web/core/components/views/view-list-header.tsx diff --git a/web/core/components/views/view-list-item-action.tsx b/apps/web/core/components/views/view-list-item-action.tsx similarity index 96% rename from web/core/components/views/view-list-item-action.tsx rename to apps/web/core/components/views/view-list-item-action.tsx index 1dbed08ac..8a0ec89c3 100644 --- a/web/core/components/views/view-list-item-action.tsx +++ b/apps/web/core/components/views/view-list-item-action.tsx @@ -3,9 +3,9 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Earth, Lock } from "lucide-react"; // types -import { EViewAccess, EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; import { useLocalStorage } from "@plane/hooks"; -import { IProjectView } from "@plane/types"; +import { EViewAccess, IProjectView } from "@plane/types"; // ui import { Tooltip, FavoriteStar } from "@plane/ui"; import { calculateTotalFilters, getPublishViewLink } from "@plane/utils"; diff --git a/web/core/components/views/view-list-item.tsx b/apps/web/core/components/views/view-list-item.tsx similarity index 100% rename from web/core/components/views/view-list-item.tsx rename to apps/web/core/components/views/view-list-item.tsx diff --git a/web/core/components/views/views-list.tsx b/apps/web/core/components/views/views-list.tsx similarity index 96% rename from web/core/components/views/views-list.tsx rename to apps/web/core/components/views/views-list.tsx index 29a0c4cb0..6fa5e4b05 100644 --- a/web/core/components/views/views-list.tsx +++ b/apps/web/core/components/views/views-list.tsx @@ -1,8 +1,9 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports -import { EUserPermissionsLevel, EUserProjectRoles } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EUserProjectRoles } from "@plane/types"; // components import { ListLayout } from "@/components/core/list"; import { ComicBoxButton, DetailedEmptyState, SimpleEmptyState } from "@/components/empty-state"; diff --git a/web/core/components/web-hooks/create-webhook-modal.tsx b/apps/web/core/components/web-hooks/create-webhook-modal.tsx similarity index 86% rename from web/core/components/web-hooks/create-webhook-modal.tsx rename to apps/web/core/components/web-hooks/create-webhook-modal.tsx index 838916a69..a7cb43ab7 100644 --- a/web/core/components/web-hooks/create-webhook-modal.tsx +++ b/apps/web/core/components/web-hooks/create-webhook-modal.tsx @@ -3,6 +3,7 @@ import React, { useState } from "react"; import { useParams } from "next/navigation"; // types +import { WORKSPACE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWebhook, IWorkspace, TWebhookEventTypes } from "@plane/types"; // ui @@ -10,6 +11,7 @@ import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@p // helpers import { csvDownload } from "@plane/utils"; // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import useKeypress from "@/hooks/use-keypress"; // components import { WebhookForm } from "./form"; @@ -67,6 +69,12 @@ export const CreateWebhookModal: React.FC = (props) => { await createWebhook(workspaceSlug.toString(), payload) .then(({ webHook, secretKey }) => { + captureSuccess({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_created, + payload: { + webhook: formData?.url, + }, + }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("workspace_settings.settings.webhooks.toasts.created.title"), @@ -79,6 +87,13 @@ export const CreateWebhookModal: React.FC = (props) => { csvDownload(csvData, `webhook-secret-key-${Date.now()}`); }) .catch((error) => { + captureError({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_created, + payload: { + webhook: formData?.url, + }, + error: error as Error, + }); setToast({ type: TOAST_TYPE.ERROR, title: t("workspace_settings.settings.webhooks.toasts.not_created.title"), diff --git a/web/core/components/web-hooks/delete-webhook-modal.tsx b/apps/web/core/components/web-hooks/delete-webhook-modal.tsx similarity index 75% rename from web/core/components/web-hooks/delete-webhook-modal.tsx rename to apps/web/core/components/web-hooks/delete-webhook-modal.tsx index 615c50f68..6e32d9f66 100644 --- a/web/core/components/web-hooks/delete-webhook-modal.tsx +++ b/apps/web/core/components/web-hooks/delete-webhook-modal.tsx @@ -3,8 +3,10 @@ import React, { FC, useState } from "react"; import { useParams } from "next/navigation"; // ui +import { WORKSPACE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; // hooks +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useWebhook } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; @@ -35,6 +37,12 @@ export const DeleteWebhookModal: FC = (props) => { removeWebhook(workspaceSlug.toString(), webhookId.toString()) .then(() => { + captureSuccess({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_deleted, + payload: { + webhook: webhookId, + }, + }); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -42,13 +50,20 @@ export const DeleteWebhookModal: FC = (props) => { }); router.replace(`/${workspaceSlug}/settings/webhooks/`); }) - .catch((error) => + .catch((error) => { + captureError({ + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_deleted, + payload: { + webhook: webhookId, + }, + error: error as Error, + }); setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: error?.error ?? "Something went wrong. Please try again.", - }) - ) + }); + }) .finally(() => setIsDeleting(false)); }; diff --git a/web/core/components/web-hooks/empty-state.tsx b/apps/web/core/components/web-hooks/empty-state.tsx similarity index 100% rename from web/core/components/web-hooks/empty-state.tsx rename to apps/web/core/components/web-hooks/empty-state.tsx diff --git a/web/core/components/web-hooks/form/delete-section.tsx b/apps/web/core/components/web-hooks/form/delete-section.tsx similarity index 84% rename from web/core/components/web-hooks/form/delete-section.tsx rename to apps/web/core/components/web-hooks/form/delete-section.tsx index 1029d792f..8201804a1 100644 --- a/web/core/components/web-hooks/form/delete-section.tsx +++ b/apps/web/core/components/web-hooks/form/delete-section.tsx @@ -2,6 +2,7 @@ import { ChevronDown, ChevronUp } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { Button } from "@plane/ui"; type Props = { @@ -36,7 +37,11 @@ export const WebhookDeleteSection: React.FC = (props) => { webhook.
    -
    diff --git a/web/core/components/web-hooks/form/event-types.tsx b/apps/web/core/components/web-hooks/form/event-types.tsx similarity index 100% rename from web/core/components/web-hooks/form/event-types.tsx rename to apps/web/core/components/web-hooks/form/event-types.tsx diff --git a/web/core/components/web-hooks/form/form.tsx b/apps/web/core/components/web-hooks/form/form.tsx similarity index 93% rename from web/core/components/web-hooks/form/form.tsx rename to apps/web/core/components/web-hooks/form/form.tsx index 5ecd7ff8e..804b708e8 100644 --- a/web/core/components/web-hooks/form/form.tsx +++ b/apps/web/core/components/web-hooks/form/form.tsx @@ -3,6 +3,7 @@ import React, { FC, useEffect, useState } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; +import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWebhook, TWebhookEventTypes } from "@plane/types"; // hooks @@ -93,7 +94,11 @@ export const WebhookForm: FC = observer((props) => { {data ? (
    -
    diff --git a/web/core/components/web-hooks/form/index.ts b/apps/web/core/components/web-hooks/form/index.ts similarity index 100% rename from web/core/components/web-hooks/form/index.ts rename to apps/web/core/components/web-hooks/form/index.ts diff --git a/web/core/components/web-hooks/form/individual-event-options.tsx b/apps/web/core/components/web-hooks/form/individual-event-options.tsx similarity index 100% rename from web/core/components/web-hooks/form/individual-event-options.tsx rename to apps/web/core/components/web-hooks/form/individual-event-options.tsx diff --git a/web/core/components/web-hooks/form/input.tsx b/apps/web/core/components/web-hooks/form/input.tsx similarity index 100% rename from web/core/components/web-hooks/form/input.tsx rename to apps/web/core/components/web-hooks/form/input.tsx diff --git a/web/core/components/web-hooks/form/secret-key.tsx b/apps/web/core/components/web-hooks/form/secret-key.tsx similarity index 100% rename from web/core/components/web-hooks/form/secret-key.tsx rename to apps/web/core/components/web-hooks/form/secret-key.tsx diff --git a/web/core/components/web-hooks/form/toggle.tsx b/apps/web/core/components/web-hooks/form/toggle.tsx similarity index 69% rename from web/core/components/web-hooks/form/toggle.tsx rename to apps/web/core/components/web-hooks/form/toggle.tsx index ca240435b..76dfca3ed 100644 --- a/web/core/components/web-hooks/form/toggle.tsx +++ b/apps/web/core/components/web-hooks/form/toggle.tsx @@ -1,10 +1,13 @@ "use client"; import { Control, Controller } from "react-hook-form"; +// constants +import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants"; import { IWebhook } from "@plane/types"; // ui import { ToggleSwitch } from "@plane/ui"; -// types +// hooks +import { captureClick } from "@/helpers/event-tracker.helper"; interface IWebHookToggle { control: Control; @@ -20,6 +23,9 @@ export const WebhookToggle = ({ control }: IWebHookToggle) => ( { + captureClick({ + elementName: WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_DETAILS_PAGE_TOGGLE_SWITCH, + }); onChange(val); }} size="sm" diff --git a/web/core/components/web-hooks/generated-hook-details.tsx b/apps/web/core/components/web-hooks/generated-hook-details.tsx similarity index 78% rename from web/core/components/web-hooks/generated-hook-details.tsx rename to apps/web/core/components/web-hooks/generated-hook-details.tsx index bf616e880..66dc2c9e5 100644 --- a/web/core/components/web-hooks/generated-hook-details.tsx +++ b/apps/web/core/components/web-hooks/generated-hook-details.tsx @@ -21,12 +21,8 @@ export const GeneratedHookDetails: React.FC = (props) => { <>
    -

    - {t("workspace_settings.settings.webhooks.modal.secret_key.created")} -

    -

    - {t("workspace_settings.settings.webhooks.modal.secret_key.copy_message")} -

    +

    {t("workspace_settings.key_created")}

    +

    {t("workspace_settings.copy_key")}

    diff --git a/web/core/components/web-hooks/index.ts b/apps/web/core/components/web-hooks/index.ts similarity index 100% rename from web/core/components/web-hooks/index.ts rename to apps/web/core/components/web-hooks/index.ts diff --git a/web/core/components/web-hooks/utils.ts b/apps/web/core/components/web-hooks/utils.ts similarity index 100% rename from web/core/components/web-hooks/utils.ts rename to apps/web/core/components/web-hooks/utils.ts diff --git a/web/core/components/web-hooks/webhooks-list-item.tsx b/apps/web/core/components/web-hooks/webhooks-list-item.tsx similarity index 51% rename from web/core/components/web-hooks/webhooks-list-item.tsx rename to apps/web/core/components/web-hooks/webhooks-list-item.tsx index 0c5d0ea8e..5419207d8 100644 --- a/web/core/components/web-hooks/webhooks-list-item.tsx +++ b/apps/web/core/components/web-hooks/webhooks-list-item.tsx @@ -3,9 +3,11 @@ import { FC } from "react"; import Link from "next/link"; import { useParams } from "next/navigation"; +import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS, WORKSPACE_SETTINGS_TRACKER_EVENTS } from "@plane/constants"; import { IWebhook } from "@plane/types"; // hooks import { ToggleSwitch } from "@plane/ui"; +import { captureElementAndEvent } from "@/helpers/event-tracker.helper"; import { useWebhook } from "@/hooks/store"; // ui // types @@ -23,8 +25,35 @@ export const WebhooksListItem: FC = (props) => { const handleToggle = () => { if (!workspaceSlug || !webhook.id) return; - - updateWebhook(workspaceSlug.toString(), webhook.id, { is_active: !webhook.is_active }); + updateWebhook(workspaceSlug.toString(), webhook.id, { is_active: !webhook.is_active }) + .then(() => { + captureElementAndEvent({ + element: { + elementName: WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_LIST_ITEM_TOGGLE_SWITCH, + }, + event: { + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_toggled, + state: "SUCCESS", + payload: { + webhook: webhook.url, + }, + }, + }); + }) + .catch(() => { + captureElementAndEvent({ + element: { + elementName: WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_LIST_ITEM_TOGGLE_SWITCH, + }, + event: { + eventName: WORKSPACE_SETTINGS_TRACKER_EVENTS.webhook_toggled, + state: "ERROR", + payload: { + webhook: webhook.url, + }, + }, + }); + }); }; return ( diff --git a/web/core/components/web-hooks/webhooks-list.tsx b/apps/web/core/components/web-hooks/webhooks-list.tsx similarity index 100% rename from web/core/components/web-hooks/webhooks-list.tsx rename to apps/web/core/components/web-hooks/webhooks-list.tsx diff --git a/web/core/components/workspace-notifications/index.ts b/apps/web/core/components/workspace-notifications/index.ts similarity index 100% rename from web/core/components/workspace-notifications/index.ts rename to apps/web/core/components/workspace-notifications/index.ts diff --git a/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx b/apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx similarity index 84% rename from web/core/components/workspace-notifications/notification-app-sidebar-option.tsx rename to apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx index 358026806..3a2e9071c 100644 --- a/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx +++ b/apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx @@ -12,11 +12,10 @@ import { useWorkspaceNotifications } from "@/hooks/store"; type TNotificationAppSidebarOption = { workspaceSlug: string; - isSidebarCollapsed: boolean | undefined; }; export const NotificationAppSidebarOption: FC = observer((props) => { - const { workspaceSlug, isSidebarCollapsed } = props; + const { workspaceSlug } = props; // hooks const { unreadNotificationsCount, getUnreadNotificationsCount } = useWorkspaceNotifications(); @@ -33,9 +32,6 @@ export const NotificationAppSidebarOption: FC = o if (totalNotifications <= 0) return <>; - if (isSidebarCollapsed) - return
    ; - return (
    diff --git a/web/core/components/workspace-notifications/root.tsx b/apps/web/core/components/workspace-notifications/root.tsx similarity index 100% rename from web/core/components/workspace-notifications/root.tsx rename to apps/web/core/components/workspace-notifications/root.tsx diff --git a/web/core/components/workspace-notifications/sidebar/empty-state.tsx b/apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/empty-state.tsx rename to apps/web/core/components/workspace-notifications/sidebar/empty-state.tsx diff --git a/web/core/components/workspace-notifications/sidebar/filters/applied-filter.tsx b/apps/web/core/components/workspace-notifications/sidebar/filters/applied-filter.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/filters/applied-filter.tsx rename to apps/web/core/components/workspace-notifications/sidebar/filters/applied-filter.tsx diff --git a/web/core/components/workspace-notifications/sidebar/filters/index.ts b/apps/web/core/components/workspace-notifications/sidebar/filters/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/filters/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/filters/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/filters/menu/index.ts b/apps/web/core/components/workspace-notifications/sidebar/filters/menu/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/filters/menu/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/filters/menu/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/filters/menu/menu-option-item.tsx b/apps/web/core/components/workspace-notifications/sidebar/filters/menu/menu-option-item.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/filters/menu/menu-option-item.tsx rename to apps/web/core/components/workspace-notifications/sidebar/filters/menu/menu-option-item.tsx diff --git a/web/core/components/workspace-notifications/sidebar/filters/menu/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/filters/menu/root.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/filters/menu/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/filters/menu/root.tsx diff --git a/web/core/components/workspace-notifications/sidebar/header/index.ts b/apps/web/core/components/workspace-notifications/sidebar/header/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/header/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/header/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/header/options/index.ts b/apps/web/core/components/workspace-notifications/sidebar/header/options/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/header/options/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/header/options/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/header/options/menu-option/index.ts b/apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/header/options/menu-option/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/header/options/menu-option/menu-item.tsx b/apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/menu-item.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/header/options/menu-option/menu-item.tsx rename to apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/menu-item.tsx diff --git a/web/core/components/workspace-notifications/sidebar/header/options/menu-option/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/root.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/header/options/menu-option/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/header/options/menu-option/root.tsx diff --git a/web/core/components/workspace-notifications/sidebar/header/options/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/header/options/root.tsx similarity index 85% rename from web/core/components/workspace-notifications/sidebar/header/options/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/header/options/root.tsx index 4de953759..f15520ec3 100644 --- a/web/core/components/workspace-notifications/sidebar/header/options/root.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/header/options/root.tsx @@ -2,14 +2,20 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { CheckCheck, RefreshCw } from "lucide-react"; // plane imports -import { ENotificationLoader, ENotificationQueryParamType, NOTIFICATION_TRACKER_EVENTS } from "@plane/constants"; +import { + ENotificationLoader, + ENotificationQueryParamType, + NOTIFICATION_TRACKER_ELEMENTS, + NOTIFICATION_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Spinner, Tooltip } from "@plane/ui"; // components import { NotificationFilter, NotificationHeaderMenuOption } from "@/components/workspace-notifications"; // constants // hooks -import { useEventTracker, useWorkspaceNotifications } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; +import { useWorkspaceNotifications } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; type TNotificationSidebarHeaderOptions = { @@ -21,7 +27,6 @@ export const NotificationSidebarHeaderOptions: FC { @@ -49,8 +54,11 @@ export const NotificationSidebarHeaderOptions: FC
    { - captureEvent(NOTIFICATION_TRACKER_EVENTS.all_marked_read); + captureSuccess({ + eventName: NOTIFICATION_TRACKER_EVENTS.all_marked_read, + }); handleMarkAllNotificationsAsRead(); }} > diff --git a/web/core/components/workspace-notifications/sidebar/header/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/header/root.tsx similarity index 89% rename from web/core/components/workspace-notifications/sidebar/header/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/header/root.tsx index 7ed9ea528..bd935b665 100644 --- a/web/core/components/workspace-notifications/sidebar/header/root.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/header/root.tsx @@ -9,6 +9,8 @@ import { Breadcrumbs, Header } from "@plane/ui"; import { BreadcrumbLink } from "@/components/common"; import { SidebarHamburgerToggle } from "@/components/core"; import { NotificationSidebarHeaderOptions } from "@/components/workspace-notifications"; +// hooks +import { useAppTheme } from "@/hooks/store"; type TNotificationSidebarHeader = { workspaceSlug: string; @@ -17,14 +19,14 @@ type TNotificationSidebarHeader = { export const NotificationSidebarHeader: FC = observer((props) => { const { workspaceSlug } = props; const { t } = useTranslation(); + const { sidebarCollapsed } = useAppTheme(); if (!workspaceSlug) return <>; return (
    -
    - -
    + {sidebarCollapsed && } + = observer((props) => { const { workspaceSlug, notification } = props; // hooks - const { captureEvent } = useEventTracker(); const { currentNotificationTab } = useWorkspaceNotifications(); const { asJson: data, archiveNotification, unArchiveNotification } = notification; const { t } = useTranslation(); @@ -31,10 +31,12 @@ export const NotificationItemArchiveOption: FC = try { const request = data.archived_at ? unArchiveNotification : archiveNotification; await request(workspaceSlug); - captureEvent(NOTIFICATION_TRACKER_EVENTS.archive, { - issue_id: data?.data?.issue?.id, - tab: currentNotificationTab, - state: "SUCCESS", + captureSuccess({ + eventName: data.archived_at ? NOTIFICATION_TRACKER_EVENTS.unarchive : NOTIFICATION_TRACKER_EVENTS.archive, + payload: { + id: data?.data?.issue?.id, + tab: currentNotificationTab, + }, }); setToast({ title: data.archived_at ? t("notification.toasts.unarchived") : t("notification.toasts.archived"), @@ -42,11 +44,19 @@ export const NotificationItemArchiveOption: FC = }); } catch (e) { console.error(e); + captureError({ + eventName: data.archived_at ? NOTIFICATION_TRACKER_EVENTS.unarchive : NOTIFICATION_TRACKER_EVENTS.archive, + payload: { + id: data?.data?.issue?.id, + tab: currentNotificationTab, + }, + }); } }; return ( = observer((props) => { const { workspaceSlug, notification } = props; // hooks - const { captureEvent } = useEventTracker(); const { currentNotificationTab } = useWorkspaceNotifications(); const { asJson: data, markNotificationAsRead, markNotificationAsUnRead } = notification; const { t } = useTranslation(); @@ -31,10 +31,12 @@ export const NotificationItemReadOption: FC = obser try { const request = data.read_at ? markNotificationAsUnRead : markNotificationAsRead; await request(workspaceSlug); - captureEvent(NOTIFICATION_TRACKER_EVENTS.all_marked_read, { - issue_id: data?.data?.issue?.id, - tab: currentNotificationTab, - state: "SUCCESS", + captureSuccess({ + eventName: data.read_at ? NOTIFICATION_TRACKER_EVENTS.mark_unread : NOTIFICATION_TRACKER_EVENTS.mark_read, + payload: { + id: data?.data?.issue?.id, + tab: currentNotificationTab, + }, }); setToast({ title: data.read_at ? t("notification.toasts.unread") : t("notification.toasts.read"), @@ -42,11 +44,19 @@ export const NotificationItemReadOption: FC = obser }); } catch (e) { console.error(e); + captureError({ + eventName: data.read_at ? NOTIFICATION_TRACKER_EVENTS.mark_unread : NOTIFICATION_TRACKER_EVENTS.mark_read, + payload: { + id: data?.data?.issue?.id, + tab: currentNotificationTab, + }, + }); } }; return ( diff --git a/web/core/components/workspace-notifications/sidebar/notification-card/options/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/notification-card/options/root.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/notification-card/options/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/notification-card/options/root.tsx diff --git a/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/index.ts b/apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/index.ts similarity index 100% rename from web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/index.ts rename to apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/index.ts diff --git a/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/modal.tsx b/apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/modal.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/modal.tsx rename to apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/modal.tsx diff --git a/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/root.tsx similarity index 100% rename from web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/notification-card/options/snooze/root.tsx diff --git a/web/core/components/workspace-notifications/sidebar/root.tsx b/apps/web/core/components/workspace-notifications/sidebar/root.tsx similarity index 97% rename from web/core/components/workspace-notifications/sidebar/root.tsx rename to apps/web/core/components/workspace-notifications/sidebar/root.tsx index 95d70d8fa..0439d5cda 100644 --- a/web/core/components/workspace-notifications/sidebar/root.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/root.tsx @@ -58,7 +58,7 @@ export const NotificationsSidebarRoot: FC = observer(() => { )} >
    - + diff --git a/web/core/components/workspace/ConfirmWorkspaceMemberRemove.tsx b/apps/web/core/components/workspace/ConfirmWorkspaceMemberRemove.tsx similarity index 100% rename from web/core/components/workspace/ConfirmWorkspaceMemberRemove.tsx rename to apps/web/core/components/workspace/ConfirmWorkspaceMemberRemove.tsx diff --git a/web/core/components/workspace/billing/comparison/base.tsx b/apps/web/core/components/workspace/billing/comparison/base.tsx similarity index 100% rename from web/core/components/workspace/billing/comparison/base.tsx rename to apps/web/core/components/workspace/billing/comparison/base.tsx diff --git a/web/core/components/workspace/billing/comparison/feature-detail.tsx b/apps/web/core/components/workspace/billing/comparison/feature-detail.tsx similarity index 84% rename from web/core/components/workspace/billing/comparison/feature-detail.tsx rename to apps/web/core/components/workspace/billing/comparison/feature-detail.tsx index 90b3d709e..43d5a5da4 100644 --- a/web/core/components/workspace/billing/comparison/feature-detail.tsx +++ b/apps/web/core/components/workspace/billing/comparison/feature-detail.tsx @@ -1,10 +1,10 @@ import { FC } from "react"; import { CheckCircle2, Minus, MinusCircle } from "lucide-react"; +import { EProductSubscriptionEnum } from "@plane/types"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; +import { getSubscriptionTextColor } from "@plane/ui"; import { cn } from "@plane/utils"; // constants -import { getSubscriptionTextColor } from "@/components/workspace/billing/subscription"; import { TPlanFeatureData } from "@/constants/plans"; type TPlanFeatureDetailProps = { diff --git a/web/core/components/workspace/billing/comparison/index.ts b/apps/web/core/components/workspace/billing/comparison/index.ts similarity index 100% rename from web/core/components/workspace/billing/comparison/index.ts rename to apps/web/core/components/workspace/billing/comparison/index.ts diff --git a/web/core/components/workspace/billing/index.ts b/apps/web/core/components/workspace/billing/index.ts similarity index 100% rename from web/core/components/workspace/billing/index.ts rename to apps/web/core/components/workspace/billing/index.ts diff --git a/web/core/components/workspace/confirm-workspace-member-remove.tsx b/apps/web/core/components/workspace/confirm-workspace-member-remove.tsx similarity index 100% rename from web/core/components/workspace/confirm-workspace-member-remove.tsx rename to apps/web/core/components/workspace/confirm-workspace-member-remove.tsx diff --git a/web/core/components/workspace/create-workspace-form.tsx b/apps/web/core/components/workspace/create-workspace-form.tsx similarity index 92% rename from web/core/components/workspace/create-workspace-form.tsx rename to apps/web/core/components/workspace/create-workspace-form.tsx index 0f51e74b2..d7d54c661 100644 --- a/web/core/components/workspace/create-workspace-form.tsx +++ b/apps/web/core/components/workspace/create-workspace-form.tsx @@ -3,7 +3,12 @@ import { Dispatch, SetStateAction, useEffect, useState, FC } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; -import { ORGANIZATION_SIZE, RESTRICTED_URLS, WORKSPACE_TRACKER_EVENTS } from "@plane/constants"; +import { + ORGANIZATION_SIZE, + RESTRICTED_URLS, + WORKSPACE_TRACKER_ELEMENTS, + WORKSPACE_TRACKER_EVENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // constants // types @@ -11,7 +16,8 @@ import { IWorkspace } from "@plane/types"; // ui import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; // hooks -import { useEventTracker, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // services import { WorkspaceService } from "@/plane-web/services"; @@ -51,7 +57,6 @@ export const CreateWorkspaceForm: FC = observer((props) => { // router const router = useAppRouter(); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { createWorkspace } = useWorkspace(); // form info const { @@ -71,13 +76,9 @@ export const CreateWorkspaceForm: FC = observer((props) => { await createWorkspace(formData) .then(async (res) => { - captureWorkspaceEvent({ + captureSuccess({ eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - ...res, - state: "SUCCESS", - element: "Create workspace page", - }, + payload: { slug: formData.slug }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -88,12 +89,10 @@ export const CreateWorkspaceForm: FC = observer((props) => { if (onSubmit) await onSubmit(res); }) .catch(() => { - captureWorkspaceEvent({ + captureError({ eventName: WORKSPACE_TRACKER_EVENTS.create, - payload: { - state: "FAILED", - element: "Create workspace page", - }, + payload: { slug: formData.slug }, + error: new Error("Error creating workspace"), }); setToast({ type: TOAST_TYPE.ERROR, @@ -248,7 +247,14 @@ export const CreateWorkspaceForm: FC = observer((props) => {
    {secondaryButton} - {!secondaryButton && ( diff --git a/web/core/components/workspace/delete-workspace-form.tsx b/apps/web/core/components/workspace/delete-workspace-form.tsx similarity index 91% rename from web/core/components/workspace/delete-workspace-form.tsx rename to apps/web/core/components/workspace/delete-workspace-form.tsx index c668ad300..14cffe545 100644 --- a/web/core/components/workspace/delete-workspace-form.tsx +++ b/apps/web/core/components/workspace/delete-workspace-form.tsx @@ -13,7 +13,8 @@ import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks import { cn } from "@plane/utils"; -import { useEventTracker, useUserSettings, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useUserSettings, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; type Props = { @@ -31,7 +32,6 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { // router const router = useAppRouter(); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { deleteWorkspace } = useWorkspace(); const { t } = useTranslation(); const { getWorkspaceRedirectionUrl } = useWorkspace(); @@ -64,13 +64,9 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { await fetchCurrentUserSettings(); handleClose(); router.push(getWorkspaceRedirectionUrl()); - captureWorkspaceEvent({ + captureSuccess({ eventName: WORKSPACE_TRACKER_EVENTS.delete, - payload: { - ...data, - state: "SUCCESS", - element: "Workspace general settings page", - }, + payload: { slug: data.slug }, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -84,13 +80,10 @@ export const DeleteWorkspaceForm: React.FC = observer((props) => { title: t("workspace_settings.settings.general.delete_modal.error_title"), message: t("workspace_settings.settings.general.delete_modal.error_message"), }); - captureWorkspaceEvent({ + captureError({ eventName: WORKSPACE_TRACKER_EVENTS.delete, - payload: { - ...data, - state: "FAILED", - element: "Workspace general settings page", - }, + payload: { slug: data.slug }, + error: new Error("Error deleting workspace"), }); }); }; diff --git a/web/core/components/workspace/index.ts b/apps/web/core/components/workspace/index.ts similarity index 100% rename from web/core/components/workspace/index.ts rename to apps/web/core/components/workspace/index.ts diff --git a/web/core/components/workspace/invite-modal/actions.tsx b/apps/web/core/components/workspace/invite-modal/actions.tsx similarity index 100% rename from web/core/components/workspace/invite-modal/actions.tsx rename to apps/web/core/components/workspace/invite-modal/actions.tsx diff --git a/web/core/components/workspace/invite-modal/fields.tsx b/apps/web/core/components/workspace/invite-modal/fields.tsx similarity index 100% rename from web/core/components/workspace/invite-modal/fields.tsx rename to apps/web/core/components/workspace/invite-modal/fields.tsx diff --git a/web/core/components/workspace/invite-modal/form.tsx b/apps/web/core/components/workspace/invite-modal/form.tsx similarity index 100% rename from web/core/components/workspace/invite-modal/form.tsx rename to apps/web/core/components/workspace/invite-modal/form.tsx diff --git a/web/core/components/workspace/invite-modal/index.ts b/apps/web/core/components/workspace/invite-modal/index.ts similarity index 100% rename from web/core/components/workspace/invite-modal/index.ts rename to apps/web/core/components/workspace/invite-modal/index.ts diff --git a/web/core/components/workspace/logo.tsx b/apps/web/core/components/workspace/logo.tsx similarity index 99% rename from web/core/components/workspace/logo.tsx rename to apps/web/core/components/workspace/logo.tsx index c956fe5ab..77b6ed97d 100644 --- a/web/core/components/workspace/logo.tsx +++ b/apps/web/core/components/workspace/logo.tsx @@ -3,7 +3,6 @@ import { observer } from "mobx-react"; import { useTranslation } from "@plane/i18n"; import { cn, getFileURL } from "@plane/utils"; - type Props = { logo: string | null | undefined; name: string | undefined; diff --git a/web/core/components/workspace/settings/index.ts b/apps/web/core/components/workspace/settings/index.ts similarity index 100% rename from web/core/components/workspace/settings/index.ts rename to apps/web/core/components/workspace/settings/index.ts diff --git a/web/core/components/workspace/settings/invitations-list-item.tsx b/apps/web/core/components/workspace/settings/invitations-list-item.tsx similarity index 95% rename from web/core/components/workspace/settings/invitations-list-item.tsx rename to apps/web/core/components/workspace/settings/invitations-list-item.tsx index dc815b52c..1fa1fce2f 100644 --- a/web/core/components/workspace/settings/invitations-list-item.tsx +++ b/apps/web/core/components/workspace/settings/invitations-list-item.tsx @@ -5,13 +5,14 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronDown, LinkIcon, Trash2 } from "lucide-react"; // plane imports -import { ROLE, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { ROLE, EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { CustomSelect, TOAST_TYPE, setToast, TContextMenuItem, CustomMenu } from "@plane/ui"; import { cn, copyTextToClipboard } from "@plane/utils"; // components import { ConfirmWorkspaceMemberRemove } from "@/components/workspace"; // hooks +import { captureClick } from "@/helpers/event-tracker.helper"; import { useMember, useUserPermissions } from "@/hooks/store"; type Props = { @@ -93,7 +94,12 @@ export const WorkspaceInvitationsListItem: FC = observer((props) => { }, { key: "remove", - action: () => setRemoveMemberModal(true), + action: () => { + captureClick({ + elementName: MEMBER_TRACKER_ELEMENTS.WORKSPACE_INVITATIONS_LIST_CONTEXT_MENU, + }); + setRemoveMemberModal(true); + }, title: t("common.remove"), icon: Trash2, shouldRender: isAdmin, diff --git a/web/core/components/workspace/settings/member-columns.tsx b/apps/web/core/components/workspace/settings/member-columns.tsx similarity index 96% rename from web/core/components/workspace/settings/member-columns.tsx rename to apps/web/core/components/workspace/settings/member-columns.tsx index 1e5036fef..edff3f15a 100644 --- a/web/core/components/workspace/settings/member-columns.tsx +++ b/apps/web/core/components/workspace/settings/member-columns.tsx @@ -4,7 +4,7 @@ import { Controller, useForm } from "react-hook-form"; import { Trash2 } from "lucide-react"; import { Disclosure } from "@headlessui/react"; // plane imports -import { ROLE, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { ROLE, EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; import { IUser, IWorkspaceMember } from "@plane/types"; // plane ui import { CustomSelect, PopoverMenu, TOAST_TYPE, setToast } from "@plane/ui"; @@ -74,6 +74,7 @@ export const NameColumn: React.FC = (props) => {
    setRemoveMemberModal(rowData)} + data-ph-element={MEMBER_TRACKER_ELEMENTS.WORKSPACE_MEMBER_TABLE_CONTEXT_MENU} > {id === currentUser?.id ? "Leave " : "Remove "}
    diff --git a/web/core/components/workspace/settings/members-list-item.tsx b/apps/web/core/components/workspace/settings/members-list-item.tsx similarity index 86% rename from web/core/components/workspace/settings/members-list-item.tsx rename to apps/web/core/components/workspace/settings/members-list-item.tsx index 978b757b3..db7e7e275 100644 --- a/web/core/components/workspace/settings/members-list-item.tsx +++ b/apps/web/core/components/workspace/settings/members-list-item.tsx @@ -13,7 +13,8 @@ import { MembersLayoutLoader } from "@/components/ui/loader/layouts/members-layo import { ConfirmWorkspaceMemberRemove } from "@/components/workspace"; // constants // hooks -import { useEventTracker, useMember, useUser, useUserPermissions, useUserSettings, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useMember, useUser, useUserPermissions, useUserSettings, useWorkspace } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import { useMemberColumns } from "@/plane-web/components/workspace/settings/useMemberColumns"; @@ -32,7 +33,6 @@ export const WorkspaceMembersListItem: FC = observer((props) => { workspace: { removeMemberFromWorkspace }, } = useMember(); const { leaveWorkspace } = useUserPermissions(); - const { captureEvent } = useEventTracker(); const { getWorkspaceRedirectionUrl } = useWorkspace(); const { fetchCurrentUserSettings } = useUserSettings(); const { t } = useTranslation(); @@ -45,18 +45,27 @@ export const WorkspaceMembersListItem: FC = observer((props) => { .then(async () => { await fetchCurrentUserSettings(); router.push(getWorkspaceRedirectionUrl()); - captureEvent(MEMBER_TRACKER_EVENTS.workspace.leave, { - state: "SUCCESS", - element: "Workspace settings members page", + captureSuccess({ + eventName: MEMBER_TRACKER_EVENTS.workspace.leave, + payload: { + workspace: workspaceSlug, + }, }); }) - .catch((err: any) => + .catch((err: any) => { + captureError({ + eventName: MEMBER_TRACKER_EVENTS.workspace.leave, + payload: { + workspace: workspaceSlug, + }, + error: err, + }); setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: err?.error || t("something_went_wrong_please_try_again"), - }) - ); + }); + }); }; const handleRemoveMember = async (memberId: string) => { diff --git a/web/core/components/workspace/settings/members-list.tsx b/apps/web/core/components/workspace/settings/members-list.tsx similarity index 100% rename from web/core/components/workspace/settings/members-list.tsx rename to apps/web/core/components/workspace/settings/members-list.tsx diff --git a/web/core/components/workspace/settings/workspace-details.tsx b/apps/web/core/components/workspace/settings/workspace-details.tsx similarity index 93% rename from web/core/components/workspace/settings/workspace-details.tsx rename to apps/web/core/components/workspace/settings/workspace-details.tsx index e9a83784b..577f5acd0 100644 --- a/web/core/components/workspace/settings/workspace-details.tsx +++ b/apps/web/core/components/workspace/settings/workspace-details.tsx @@ -5,7 +5,13 @@ import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; import { Pencil } from "lucide-react"; // constants -import { ORGANIZATION_SIZE, EUserPermissions, EUserPermissionsLevel, WORKSPACE_TRACKER_EVENTS } from "@plane/constants"; +import { + ORGANIZATION_SIZE, + EUserPermissions, + EUserPermissionsLevel, + WORKSPACE_TRACKER_EVENTS, + WORKSPACE_TRACKER_ELEMENTS, +} from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWorkspace } from "@plane/types"; import { Button, CustomSelect, Input, TOAST_TYPE, setToast } from "@plane/ui"; @@ -15,7 +21,8 @@ import { LogoSpinner } from "@/components/common"; import { WorkspaceImageUploadModal } from "@/components/core"; // helpers // hooks -import { useEventTracker, useUserPermissions, useWorkspace } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useUserPermissions, useWorkspace } from "@/hooks/store"; // plane web components import { DeleteWorkspaceSection } from "@/plane-web/components/workspace"; @@ -31,7 +38,6 @@ export const WorkspaceDetails: FC = observer(() => { const [isLoading, setIsLoading] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); // store hooks - const { captureWorkspaceEvent } = useEventTracker(); const { currentWorkspace, updateWorkspace } = useWorkspace(); const { allowPermissions } = useUserPermissions(); const { t } = useTranslation(); @@ -61,13 +67,9 @@ export const WorkspaceDetails: FC = observer(() => { await updateWorkspace(currentWorkspace.slug, payload) .then((res) => { - captureWorkspaceEvent({ + captureSuccess({ eventName: WORKSPACE_TRACKER_EVENTS.update, - payload: { - ...res, - state: "SUCCESS", - element: "Workspace general settings page", - }, + payload: { slug: currentWorkspace.slug }, }); setToast({ title: "Success!", @@ -76,12 +78,10 @@ export const WorkspaceDetails: FC = observer(() => { }); }) .catch((err) => { - captureWorkspaceEvent({ + captureError({ eventName: WORKSPACE_TRACKER_EVENTS.update, - payload: { - state: "FAILED", - element: "Workspace general settings page", - }, + payload: { slug: currentWorkspace.slug }, + error: err, }); console.error(err); }); @@ -282,7 +282,12 @@ export const WorkspaceDetails: FC = observer(() => { {isAdmin && (
    -
    diff --git a/web/core/components/workspace/sidebar/dropdown-item.tsx b/apps/web/core/components/workspace/sidebar/dropdown-item.tsx similarity index 97% rename from web/core/components/workspace/sidebar/dropdown-item.tsx rename to apps/web/core/components/workspace/sidebar/dropdown-item.tsx index 68b2d5b2e..97d226307 100644 --- a/web/core/components/workspace/sidebar/dropdown-item.tsx +++ b/apps/web/core/components/workspace/sidebar/dropdown-item.tsx @@ -64,7 +64,7 @@ const SidebarDropdownItem = observer((props: TProps) => {
    {workspace.name}
    diff --git a/apps/web/core/components/workspace/sidebar/dropdown.tsx b/apps/web/core/components/workspace/sidebar/dropdown.tsx new file mode 100644 index 000000000..e9f3adee0 --- /dev/null +++ b/apps/web/core/components/workspace/sidebar/dropdown.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { observer } from "mobx-react"; +// hooks +import { useAppRail } from "@/hooks/use-app-rail"; +// components +import { WorkspaceAppSwitcher } from "@/plane-web/components/workspace/app-switcher"; +import { UserMenuRoot } from "./user-menu-root"; +import { WorkspaceMenuRoot } from "./workspace-menu-root"; + +export const SidebarDropdown = observer(() => { + // hooks + const { shouldRenderAppRail, isEnabled: isAppRailEnabled } = useAppRail(); + + return ( +
    + + {isAppRailEnabled && !shouldRenderAppRail && } + +
    + ); +}); diff --git a/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx similarity index 59% rename from web/core/components/workspace/sidebar/favorites/favorite-folder.tsx rename to apps/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx index 91f8addd8..bc9f1e9d9 100644 --- a/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx +++ b/apps/web/core/components/workspace/sidebar/favorites/favorite-folder.tsx @@ -25,7 +25,6 @@ import { CustomMenu, Tooltip, DropIndicator, FavoriteFolderIcon, DragHandle } fr // helpers import { cn } from "@plane/utils"; // hooks -import { useAppTheme } from "@/hooks/store"; import { useFavorite } from "@/hooks/store/use-favorite"; import { usePlatformOS } from "@/hooks/use-platform-os"; // local imports @@ -44,7 +43,6 @@ type Props = { export const FavoriteFolder: React.FC = (props) => { const { favorite, handleRemoveFromFavorites, isLastChild, handleDrop } = props; // store hooks - const { sidebarCollapsed: isSidebarCollapsed } = useAppTheme(); const { getGroupedFavorites } = useFavorite(); const { isMobile } = usePlatformOS(); const { workspaceSlug } = useParams(); @@ -159,7 +157,6 @@ export const FavoriteFolder: React.FC = (props) => { "group/project-item relative w-full px-2 py-1.5 flex items-center rounded-md text-custom-sidebar-text-100 hover:bg-custom-sidebar-background-90", { "bg-custom-sidebar-background-90": isMenuActive, - "p-0 size-8 aspect-square justify-center mx-auto": isSidebarCollapsed, } )} > @@ -169,117 +166,95 @@ export const FavoriteFolder: React.FC = (props) => {
    - {isSidebarCollapsed ? ( -
    - + <> + +
    -
    + + + +
    +

    {favorite.name}

    - -
    - ) : ( - <> - -
    - - - - -
    - -
    -

    {favorite.name}

    -
    -
    -
    - - - +
    +
    + + + + } + menuButtonOnClick={() => setIsMenuActive(!isMenuActive)} + className={cn( + "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", + { + "opacity-100 pointer-events-auto": isMenuActive, } - menuButtonOnClick={() => setIsMenuActive(!isMenuActive)} - className={cn( - "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", - { - "opacity-100 pointer-events-auto": isMenuActive, - } - )} - customButtonClassName="grid place-items-center" - placement="bottom-start" - ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} - > - handleRemoveFromFavorites(favorite)}> - - - Remove from favorites - - - setFolderToRename(favorite.id)}> -
    - - Rename Folder -
    -
    -
    - - - - - )} + )} + customButtonClassName="grid place-items-center" + placement="bottom-start" + ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} + > + handleRemoveFromFavorites(favorite)}> + + + Remove from favorites + + + setFolderToRename(favorite.id)}> +
    + + Rename Folder +
    +
    + + + + +
    {favorite.children && favorite.children.length > 0 && ( = (props) => { leaveFrom="transform scale-100 opacity-100" leaveTo="transform scale-95 opacity-0" > - + {orderBy(favorite.children, "sequence", "desc").map((child, index) => ( = observer((props) => { + const { href, title, icon } = props; + // store hooks + const { toggleSidebar } = useAppTheme(); + const { isMobile } = usePlatformOS(); + + const handleOnClick = () => { + if (isMobile) toggleSidebar(); + }; + + return ( + + + {icon} + {title} + + + ); +}); diff --git a/apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx new file mode 100644 index 000000000..7b9606085 --- /dev/null +++ b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx @@ -0,0 +1,29 @@ +"use client"; +import React, { FC } from "react"; +// helpers +import { cn } from "@plane/utils"; + +type Props = { + children: React.ReactNode; + elementRef: React.RefObject; + isMenuActive?: boolean; +}; + +export const FavoriteItemWrapper: FC = (props) => { + const { children, elementRef, isMenuActive = false } = props; + return ( + <> +
    + {children} +
    + + ); +}; diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/common/helper.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/helper.tsx similarity index 100% rename from web/core/components/workspace/sidebar/favorites/favorite-items/common/helper.tsx rename to apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/helper.tsx diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/common/index.ts b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/index.ts similarity index 100% rename from web/core/components/workspace/sidebar/favorites/favorite-items/common/index.ts rename to apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/index.ts diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/index.ts b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/index.ts similarity index 100% rename from web/core/components/workspace/sidebar/favorites/favorite-items/index.ts rename to apps/web/core/components/workspace/sidebar/favorites/favorite-items/index.ts diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx similarity index 85% rename from web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx rename to apps/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx index 49931802e..1b5c9436e 100644 --- a/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx +++ b/apps/web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx @@ -27,7 +27,6 @@ import { FavoriteItemTitle, } from "@/components/workspace/sidebar/favorites"; // hooks -import { useAppTheme } from "@/hooks/store"; import { useFavoriteItemDetails } from "@/hooks/use-favorite-item-details"; //helpers import { getCanDrop, getInstructionFromPayload } from "../favorites.helpers"; @@ -45,7 +44,6 @@ export const FavoriteRoot: FC = observer((props) => { // props const { isLastChild, parentId, workspaceSlug, favorite, handleRemoveFromFavorites, handleDrop } = props; // store hooks - const { sidebarCollapsed } = useAppTheme(); const { itemLink, itemIcon, itemTitle } = useFavoriteItemDetails(workspaceSlug, favorite); //state const [isDragging, setIsDragging] = useState(false); @@ -82,12 +80,7 @@ export const FavoriteRoot: FC = observer((props) => { const root = createRoot(container); root.render(
    - +
    ); return () => root.unmount(); @@ -138,18 +131,16 @@ export const FavoriteRoot: FC = observer((props) => { return ( <> - - {!sidebarCollapsed && } - - {!sidebarCollapsed && ( - - )} + + + + {isLastChild && } diff --git a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx similarity index 61% rename from web/core/components/workspace/sidebar/favorites/favorites-menu.tsx rename to apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx index d2d30a37d..607e572c9 100644 --- a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx +++ b/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx @@ -23,10 +23,8 @@ import { setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; // helpers import { cn } from "@plane/utils"; // hooks -import { useAppTheme } from "@/hooks/store"; import { useFavorite } from "@/hooks/store/use-favorite"; import useLocalStorage from "@/hooks/use-local-storage"; -import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { FavoriteFolder } from "./favorite-folder"; import { FavoriteRoot } from "./favorite-items"; @@ -40,19 +38,10 @@ export const SidebarFavoritesMenu = observer(() => { // navigation const { workspaceSlug } = useParams(); // store hooks - const { sidebarCollapsed } = useAppTheme(); - const { - favoriteIds, - groupedFavorites, - deleteFavorite, - removeFromFavoriteFolder, - reOrderFavorite, - moveFavoriteToFolder, - } = useFavorite(); + const { groupedFavorites, deleteFavorite, removeFromFavoriteFolder, reOrderFavorite, moveFavoriteToFolder } = + useFavorite(); // translation const { t } = useTranslation(); - // platform hooks - const { isMobile } = usePlatformOS(); // local storage const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage(IS_FAVORITE_MENU_OPEN, false); // derived values @@ -154,10 +143,6 @@ export const SidebarFavoritesMenu = observer(() => { [workspaceSlug, reOrderFavorite, t] ); - useEffect(() => { - if (sidebarCollapsed) toggleFavoriteMenu(true); - }, [sidebarCollapsed, toggleFavoriteMenu]); - useEffect(() => { const element = elementRef.current; @@ -189,27 +174,48 @@ export const SidebarFavoritesMenu = observer(() => { return ( <> - {!sidebarCollapsed && ( -
    + toggleFavoriteMenu(!isFavoriteMenuOpen)} + aria-label={t( + isFavoriteMenuOpen + ? "aria_labels.projects_sidebar.close_favorites_menu" + : "aria_labels.projects_sidebar.open_favorites_menu" + )} > + {t("favorites")} + +
    + + + toggleFavoriteMenu(!isFavoriteMenuOpen)} aria-label={t( isFavoriteMenuOpen @@ -217,42 +223,14 @@ export const SidebarFavoritesMenu = observer(() => { : "aria_labels.projects_sidebar.open_favorites_menu" )} > - {t("favorites")} + -
    - - - - toggleFavoriteMenu(!isFavoriteMenuOpen)} - aria-label={t( - isFavoriteMenuOpen - ? "aria_labels.projects_sidebar.close_favorites_menu" - : "aria_labels.projects_sidebar.open_favorites_menu" - )} - > - - -
    - )} +
    { leaveTo="transform scale-95 opacity-0" > {isFavoriteMenuOpen && ( - + {createNewFolder && } {Object.keys(groupedFavorites).length === 0 ? ( <> - {!sidebarCollapsed && ( - - {t("no_favorites_yet")} - - )} + {t("no_favorites_yet")} ) : ( orderBy(Object.values(groupedFavorites), "sequence", "desc") .filter((fav) => !fav.parent) .map((fav, index, { length }) => ( <> - {fav?.id && ( - - {fav?.is_folder ? ( - - ) : ( - - )} - + {fav?.is_folder ? ( + + ) : ( + )} )) @@ -320,10 +277,6 @@ export const SidebarFavoritesMenu = observer(() => { )}
    - - {sidebarCollapsed && favoriteIds.length > 0 && ( -
    - )} ); }); diff --git a/web/core/components/workspace/sidebar/favorites/favorites.helpers.ts b/apps/web/core/components/workspace/sidebar/favorites/favorites.helpers.ts similarity index 97% rename from web/core/components/workspace/sidebar/favorites/favorites.helpers.ts rename to apps/web/core/components/workspace/sidebar/favorites/favorites.helpers.ts index a7364c9ed..37ae56c60 100644 --- a/web/core/components/workspace/sidebar/favorites/favorites.helpers.ts +++ b/apps/web/core/components/workspace/sidebar/favorites/favorites.helpers.ts @@ -7,7 +7,7 @@ export type TargetData = { parentId: string | null; isGroup: boolean; isChild: boolean; -} +}; /** * extracts the Payload and translates the instruction for the current dropTarget based on drag and drop payload @@ -58,11 +58,10 @@ export const getCanDrop = (source: TDropTarget, favorite: IFavorite | undefined, if (!sourceData) return false; // a favorite cannot be dropped on to itself - if (sourceData.id === favorite?.id ) return false; - + if (sourceData.id === favorite?.id) return false; // if current dropTarget is a child and the favorite being dropped is a group then don't enable drop if (isCurrentChild && sourceData.isGroup) return false; return true; -}; \ No newline at end of file +}; diff --git a/web/core/components/workspace/sidebar/favorites/index.ts b/apps/web/core/components/workspace/sidebar/favorites/index.ts similarity index 80% rename from web/core/components/workspace/sidebar/favorites/index.ts rename to apps/web/core/components/workspace/sidebar/favorites/index.ts index 7998acef8..fd92ae14a 100644 --- a/web/core/components/workspace/sidebar/favorites/index.ts +++ b/apps/web/core/components/workspace/sidebar/favorites/index.ts @@ -2,4 +2,4 @@ export * from "./favorite-folder"; export * from "./favorite-items"; export * from "./favorites-menu"; export * from "./favorites.helpers"; -export * from "./new-fav-folder"; \ No newline at end of file +export * from "./new-fav-folder"; diff --git a/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx b/apps/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx similarity index 100% rename from web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx rename to apps/web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx diff --git a/apps/web/core/components/workspace/sidebar/help-menu.tsx b/apps/web/core/components/workspace/sidebar/help-menu.tsx new file mode 100644 index 000000000..3a1dc8320 --- /dev/null +++ b/apps/web/core/components/workspace/sidebar/help-menu.tsx @@ -0,0 +1,149 @@ +"use client"; + +import React, { useState } from "react"; +import { observer } from "mobx-react"; +import { useParams } from "next/navigation"; +import { FileText, HelpCircle, MessagesSquare, User } from "lucide-react"; +import { useTranslation } from "@plane/i18n"; +// ui +import { CustomMenu, Tooltip, ToggleSwitch } from "@plane/ui"; +// components +import { cn } from "@plane/utils"; +import { ProductUpdatesModal } from "@/components/global"; +// helpers +// hooks +import { useCommandPalette, useInstance, useTransient, useUserSettings } from "@/hooks/store"; +import { usePlatformOS } from "@/hooks/use-platform-os"; +// plane web components +import { PlaneVersionNumber } from "@/plane-web/components/global"; + +export interface WorkspaceHelpSectionProps { + setSidebarActive?: React.Dispatch>; +} + +export const HelpMenu: React.FC = observer(() => { + const { workspaceSlug, projectId } = useParams(); + // store hooks + const { t } = useTranslation(); + const { toggleShortcutModal } = useCommandPalette(); + const { isMobile } = usePlatformOS(); + const { config } = useInstance(); + const { isIntercomToggle, toggleIntercom } = useTransient(); + const { canUseLocalDB, toggleLocalDB } = useUserSettings(); + // states + const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); + const [isProductUpdatesModalOpen, setProductUpdatesModalOpen] = useState(false); + + const handleCrispWindowShow = () => { + toggleIntercom(!isIntercomToggle); + }; + + return ( + <> + setProductUpdatesModalOpen(false)} /> +
    + + + + +
    + } + customButtonClassName="relative grid place-items-center rounded-md p-1.5 outline-none" + menuButtonOnClick={() => !isNeedHelpOpen && setIsNeedHelpOpen(true)} + onMenuClose={() => setIsNeedHelpOpen(false)} + placement="top-end" + maxHeight="lg" + closeOnSelect + > + + + + {t("documentation")} + + + {config?.intercom_app_id && config?.is_intercom_enabled && ( + + + + )} + + + + {t("contact_sales")} + + +
    + + ); +}); diff --git a/web/core/components/workspace/sidebar/help-section.tsx b/apps/web/core/components/workspace/sidebar/help-section.tsx similarity index 83% rename from web/core/components/workspace/sidebar/help-section.tsx rename to apps/web/core/components/workspace/sidebar/help-section.tsx index 73f036cd4..5aff74d56 100644 --- a/web/core/components/workspace/sidebar/help-section.tsx +++ b/apps/web/core/components/workspace/sidebar/help-section.tsx @@ -26,7 +26,7 @@ export const SidebarHelpSection: React.FC = observer( const { workspaceSlug, projectId } = useParams(); // store hooks const { t } = useTranslation(); - const { sidebarCollapsed, toggleSidebar } = useAppTheme(); + const { sidebarCollapsed: isCollapsed, toggleSidebar, sidebarPeek, toggleSidebarPeek } = useAppTheme(); const { toggleShortcutModal } = useCommandPalette(); const { isMobile } = usePlatformOS(); const { config } = useInstance(); @@ -40,22 +40,11 @@ export const SidebarHelpSection: React.FC = observer( toggleIntercom(!isIntercomToggle); }; - const isCollapsed = sidebarCollapsed || false; - return ( <> setProductUpdatesModalOpen(false)} /> -
    -
    +
    +
    = observer(
    } - customButtonClassName={`relative grid place-items-center rounded-md p-1.5 outline-none ${isCollapsed ? "w-full" : ""}`} + customButtonClassName="relative grid place-items-center rounded-md p-1.5 outline-none" menuButtonOnClick={() => !isNeedHelpOpen && setIsNeedHelpOpen(true)} onMenuClose={() => setIsNeedHelpOpen(false)} - placement={isCollapsed ? "left-end" : "top-end"} + placement="top-end" maxHeight="lg" closeOnSelect > @@ -158,23 +147,18 @@ export const SidebarHelpSection: React.FC = observer(
    -
    +
    -
    +
    + + )} + + + + {t("contact_sales")} + + +
    + +
    { + e.preventDefault(); + e.stopPropagation(); + }} + className="flex w-full items-center justify-between text-xs hover:bg-custom-background-80" + > + {t("hyper_mode")} + toggleLocalDB(workspaceSlug?.toString(), projectId?.toString())} + /> +
    +
    + + + + + + + + + Discord + + +
    + +
    + + + ); +}); diff --git a/web/core/components/workspace/sidebar/index.ts b/apps/web/core/components/workspace/sidebar/index.ts similarity index 92% rename from web/core/components/workspace/sidebar/index.ts rename to apps/web/core/components/workspace/sidebar/index.ts index 0a1f2a920..8c18ceae6 100644 --- a/web/core/components/workspace/sidebar/index.ts +++ b/apps/web/core/components/workspace/sidebar/index.ts @@ -10,3 +10,4 @@ export * from "./user-menu-item"; export * from "./workspace-menu"; export * from "./workspace-menu-item"; export * from "./workspace-menu-header"; +export * from "./help-section"; diff --git a/web/core/components/workspace/sidebar/project-navigation.tsx b/apps/web/core/components/workspace/sidebar/project-navigation.tsx similarity index 80% rename from web/core/components/workspace/sidebar/project-navigation.tsx rename to apps/web/core/components/workspace/sidebar/project-navigation.tsx index f4add66e6..754f45de5 100644 --- a/web/core/components/workspace/sidebar/project-navigation.tsx +++ b/apps/web/core/components/workspace/sidebar/project-navigation.tsx @@ -5,16 +5,15 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useParams, usePathname } from "next/navigation"; import { FileText, Layers } from "lucide-react"; -import { EUserPermissionsLevel, EUserPermissions, EUserProjectRoles } from "@plane/constants"; +import { EUserPermissionsLevel, EUserPermissions } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { EUserProjectRoles } from "@plane/types"; // plane ui -import { Tooltip, DiceIcon, ContrastIcon, LayersIcon, Intake } from "@plane/ui"; +import { DiceIcon, ContrastIcon, LayersIcon, Intake } from "@plane/ui"; // components import { SidebarNavItem } from "@/components/sidebar"; // hooks import { useAppTheme, useIssueDetail, useProject, useUserPermissions } from "@/hooks/store"; -import { usePlatformOS } from "@/hooks/use-platform-os"; -// plane-web constants export type TNavigationItem = { name: string; @@ -31,17 +30,15 @@ type TProjectItemsProps = { workspaceSlug: string; projectId: string; additionalNavigationItems?: (workspaceSlug: string, projectId: string) => TNavigationItem[]; - isSidebarCollapsed: boolean; }; export const ProjectNavigation: FC = observer((props) => { - const { workspaceSlug, projectId, additionalNavigationItems, isSidebarCollapsed } = props; + const { workspaceSlug, projectId, additionalNavigationItems } = props; const { workItem: workItemIdentifierFromRoute } = useParams(); // store hooks const { t } = useTranslation(); const { toggleSidebar } = useAppTheme(); const { getPartialProjectById } = useProject(); - const { isMobile } = usePlatformOS(); const { allowPermissions } = useUserPermissions(); const { issue: { getIssueIdByIdentifier, getIssueById }, @@ -175,28 +172,14 @@ export const ProjectNavigation: FC = observer((props) => { if (!hasAccess) return null; return ( - - - -
    - - {!isSidebarCollapsed && {t(item.i18n_key)}} -
    -
    - -
    + + +
    + + {t(item.i18n_key)} +
    +
    + ); })} diff --git a/web/core/components/workspace/sidebar/projects-list-item.tsx b/apps/web/core/components/workspace/sidebar/projects-list-item.tsx similarity index 62% rename from web/core/components/workspace/sidebar/projects-list-item.tsx rename to apps/web/core/components/workspace/sidebar/projects-list-item.tsx index d6f436579..714c36eca 100644 --- a/web/core/components/workspace/sidebar/projects-list-item.tsx +++ b/apps/web/core/components/workspace/sidebar/projects-list-item.tsx @@ -12,7 +12,7 @@ import { createRoot } from "react-dom/client"; import { LinkIcon, Settings, Share2, LogOut, MoreHorizontal, ChevronRight } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; // plane helpers -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_ELEMENTS } from "@plane/constants"; import { useOutsideClickDetector } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; // ui @@ -23,7 +23,7 @@ import { Logo } from "@/components/common/logo"; import { LeaveProjectModal, PublishProjectModal } from "@/components/project"; // helpers // hooks -import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store"; +import { useAppTheme, useCommandPalette, useProject, useUserPermissions } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane-web components import { ProjectNavigationRoot } from "@/plane-web/components/sidebar"; @@ -57,13 +57,13 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { renderInExtendedSidebar = false, } = props; // store hooks - const { sidebarCollapsed } = useAppTheme(); const { t } = useTranslation(); - const { setTrackElement } = useEventTracker(); const { getPartialProjectById } = useProject(); const { isMobile } = usePlatformOS(); const { allowPermissions } = useUserPermissions(); const { getIsProjectListOpen, toggleProjectListOpen } = useCommandPalette(); + const { toggleAnySidebarDropdown } = useAppTheme(); + // states const [leaveProjectModalOpen, setLeaveProjectModal] = useState(false); const [publishModalOpen, setPublishModal] = useState(false); @@ -97,12 +97,9 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { ); const handleLeaveProject = () => { - setTrackElement("APP_SIDEBAR_PROJECT_DROPDOWN"); setLeaveProjectModal(true); }; - const isSidebarCollapsed = sidebarCollapsed && !renderInExtendedSidebar; - useEffect(() => { const element = projectRef.current; const dragHandleElement = dragHandleRef.current; @@ -112,7 +109,7 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { return combine( draggable({ element, - canDrag: () => !disableDrag && !isSidebarCollapsed, + canDrag: () => !disableDrag, dragHandle: dragHandleElement ?? undefined, getInitialData: () => ({ id: projectId, dragInstanceId: "PROJECTS" }), onDragStart: () => { @@ -192,6 +189,11 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { ); }, [projectId, isLastChild, projectListType, handleOnProjectDrop]); + useEffect(() => { + if (isMenuActive) toggleAnySidebarDropdown(true); + else toggleAnySidebarDropdown(false); + }, [isMenuActive]); + useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false)); useOutsideClickDetector(projectRef, () => projectRef?.current?.classList?.remove(HIGHLIGHT_CLASS)); @@ -204,7 +206,7 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { const handleItemClick = () => setIsProjectListOpen(!isProjectListOpen); return ( <> - setPublishModal(false)} /> + setPublishModal(false)} /> setLeaveProjectModal(false)} />
    = observer((props) => { "group/project-item relative w-full px-2 py-1.5 flex items-center rounded-md text-custom-sidebar-text-100 hover:bg-custom-sidebar-background-90", { "bg-custom-sidebar-background-90": isMenuActive, - "p-0 size-8 aspect-square justify-center mx-auto": isSidebarCollapsed, } )} id={`${project?.id}`} @@ -242,7 +243,6 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { "cursor-not-allowed opacity-60": project.sort_order === null, "cursor-grabbing": isDragging, flex: isMenuActive || renderInExtendedSidebar, - "!hidden": isSidebarCollapsed, } )} ref={dragHandleRef} @@ -251,76 +251,53 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { )} - {isSidebarCollapsed ? ( + <> - +
    +

    {project.name}

    - ) : ( - <> - - setIsMenuActive(!isMenuActive)} > - -
    - -
    -

    {project.name}

    -
    -
    -
    - setIsMenuActive(!isMenuActive)} - > - - + + + } + className={cn( + "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", + { + "opacity-100 pointer-events-auto": isMenuActive, } - className={cn( - "opacity-0 pointer-events-none flex-shrink-0 group-hover/project-item:opacity-100 group-hover/project-item:pointer-events-auto", - { - "opacity-100 pointer-events-auto": isMenuActive, - } - )} - customButtonClassName="grid place-items-center" - placement="bottom-start" - ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} - useCaptureForOutsideClick - closeOnSelect - > - {/* TODO: Removed is_favorite logic due to the optimization in projects API */} - {/* {isAuthorized && ( + )} + customButtonClassName="grid place-items-center" + placement="bottom-start" + ariaLabel={t("aria_labels.projects_sidebar.toggle_quick_actions_menu")} + useCaptureForOutsideClick + closeOnSelect + onMenuClose={() => setIsMenuActive(false)} + > + {/* TODO: Removed is_favorite logic due to the optimization in projects API */} + {/* {isAuthorized && ( @@ -335,79 +312,81 @@ export const SidebarProjectsListItem: React.FC = observer((props) => { )} */} - {/* publish project settings */} - {isAdmin && ( - setPublishModal(true)}> -
    -
    - -
    -
    {t("publish_project")}
    + {/* publish project settings */} + {isAdmin && ( + setPublishModal(true)}> +
    +
    +
    - - )} - - - - {t("copy_link")} - +
    {t("publish_project")}
    +
    - {isAuthorized && ( - { - router.push(`/${workspaceSlug}/projects/${project?.id}/archives/issues`); - }} - > -
    - - {t("archives")} -
    -
    - )} + )} + + + + {t("copy_link")} + + + {isAuthorized && ( { - router.push(`/${workspaceSlug}/settings/projects/${project?.id}`); + router.push(`/${workspaceSlug}/projects/${project?.id}/archives/issues`); }} >
    - - {t("settings")} + + {t("archives")}
    - {/* leave project */} - {!isAuthorized && ( - -
    - - {t("leave_project")} -
    -
    - )} - - setIsProjectListOpen(!isProjectListOpen)} - aria-label={t( - isProjectListOpen - ? "aria_labels.projects_sidebar.close_project_menu" - : "aria_labels.projects_sidebar.open_project_menu" - )} + )} + { + router.push(`/${workspaceSlug}/settings/projects/${project?.id}`); + }} > - - - - )} +
    + + {t("settings")} +
    + + {/* leave project */} + {!isAuthorized && ( + +
    + + {t("leave_project")} +
    +
    + )} + + setIsProjectListOpen(!isProjectListOpen)} + aria-label={t( + isProjectListOpen + ? "aria_labels.projects_sidebar.close_project_menu" + : "aria_labels.projects_sidebar.open_project_menu" + )} + > + + +
    = observer((props) => { > {isProjectListOpen && ( - + )} diff --git a/web/core/components/workspace/sidebar/projects-list.tsx b/apps/web/core/components/workspace/sidebar/projects-list.tsx similarity index 64% rename from web/core/components/workspace/sidebar/projects-list.tsx rename to apps/web/core/components/workspace/sidebar/projects-list.tsx index 2ef487468..1f4a8f71f 100644 --- a/web/core/components/workspace/sidebar/projects-list.tsx +++ b/apps/web/core/components/workspace/sidebar/projects-list.tsx @@ -5,9 +5,9 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; -import { Briefcase, ChevronRight, Plus } from "lucide-react"; +import { ChevronRight, Plus } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui import { Loader, TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; @@ -17,7 +17,7 @@ import { CreateProjectModal } from "@/components/project"; import { SidebarProjectsListItem } from "@/components/workspace"; // helpers // hooks -import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useProject, useUserPermissions } from "@/hooks/store"; // plane web types import { TProject } from "@/plane-web/types"; @@ -32,8 +32,6 @@ export const SidebarProjectsList: FC = observer(() => { // store hooks const { t } = useTranslation(); const { toggleCreateProjectModal } = useCommandPalette(); - const { sidebarCollapsed } = useAppTheme(); - const { setTrackElement } = useEventTracker(); const { allowPermissions } = useUserPermissions(); const { loader, getPartialProjectById, joinedProjectIds: joinedProjects, updateProjectView } = useProject(); @@ -87,8 +85,6 @@ export const SidebarProjectsList: FC = observer(() => { }); }; - const isCollapsed = sidebarCollapsed || false; - /** * Implementing scroll animation styles based on the scroll length of the container */ @@ -152,24 +148,11 @@ export const SidebarProjectsList: FC = observer(() => { > <> -
    +
    toggleListDisclosure(!isAllProjectsListOpen)} aria-label={t( isAllProjectsListOpen @@ -177,52 +160,42 @@ export const SidebarProjectsList: FC = observer(() => { : "aria_labels.projects_sidebar.open_projects_menu" )} > - - <> - {isCollapsed ? ( - - ) : ( - {t("projects")} - )} - - + {t("projects")} - {!isCollapsed && ( -
    - {isAuthorizedUser && ( - - - +
    + {isAuthorizedUser && ( + + + + )} + toggleListDisclosure(!isAllProjectsListOpen)} + aria-label={t( + isAllProjectsListOpen + ? "aria_labels.projects_sidebar.close_projects_menu" + : "aria_labels.projects_sidebar.open_projects_menu" )} - toggleListDisclosure(!isAllProjectsListOpen)} - aria-label={t( - isAllProjectsListOpen - ? "aria_labels.projects_sidebar.close_projects_menu" - : "aria_labels.projects_sidebar.open_projects_menu" - )} - > - - -
    - )} + > + + +
    { )} {isAllProjectsListOpen && ( - + <> {joinedProjects.map((projectId, index) => ( { {isAuthorizedUser && joinedProjects?.length === 0 && ( )}
    diff --git a/web/core/components/workspace/sidebar/quick-actions.tsx b/apps/web/core/components/workspace/sidebar/quick-actions.tsx similarity index 77% rename from web/core/components/workspace/sidebar/quick-actions.tsx rename to apps/web/core/components/workspace/sidebar/quick-actions.tsx index 8ba2506c3..878447233 100644 --- a/web/core/components/workspace/sidebar/quick-actions.tsx +++ b/apps/web/core/components/workspace/sidebar/quick-actions.tsx @@ -2,7 +2,7 @@ import { useRef, useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { PenSquare } from "lucide-react"; -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, SIDEBAR_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // types import { TIssue } from "@plane/types"; @@ -12,7 +12,7 @@ import { CreateUpdateIssueModal } from "@/components/issues"; // constants // helpers // hooks -import { useAppTheme, useCommandPalette, useEventTracker, useProject, useUserPermissions } from "@/hooks/store"; +import { useCommandPalette, useProject, useUserPermissions } from "@/hooks/store"; import useLocalStorage from "@/hooks/use-local-storage"; // plane web components import { AppSearch } from "@/plane-web/components/workspace"; @@ -30,8 +30,6 @@ export const SidebarQuickActions = observer(() => { const workspaceSlug = routerWorkspaceSlug?.toString(); // store hooks const { toggleCreateIssueModal } = useCommandPalette(); - const { sidebarCollapsed: isSidebarCollapsed } = useAppTheme(); - const { setTrackElement } = useEventTracker(); const { joinedProjectIds } = useProject(); const { allowPermissions } = useUserPermissions(); // local storage @@ -74,23 +72,17 @@ export const SidebarQuickActions = observer(() => { onSubmit={() => removeWorkspaceDraftIssue()} isDraft /> -
    +
    diff --git a/apps/web/core/components/workspace/sidebar/sidebar-menu-items.tsx b/apps/web/core/components/workspace/sidebar/sidebar-menu-items.tsx new file mode 100644 index 000000000..3a2676c81 --- /dev/null +++ b/apps/web/core/components/workspace/sidebar/sidebar-menu-items.tsx @@ -0,0 +1,138 @@ +"use client"; +import React, { useMemo } from "react"; +import { observer } from "mobx-react"; +import { useParams } from "next/navigation"; +import { ChevronRight, Ellipsis } from "lucide-react"; +import { Disclosure, Transition } from "@headlessui/react"; +// plane imports +import { + WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS, + WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS, + WORKSPACE_SIDEBAR_STATIC_PINNED_NAVIGATION_ITEMS_LINKS, +} from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; +import { cn } from "@plane/utils"; +// components +import { SidebarNavItem } from "@/components/sidebar"; +// store hooks +import { useAppTheme, useWorkspace } from "@/hooks/store"; +import useLocalStorage from "@/hooks/use-local-storage"; +// plane-web imports +import { SidebarItem } from "@/plane-web/components/workspace/sidebar"; + +export const SidebarMenuItems = observer(() => { + // routers + const { workspaceSlug } = useParams(); + const { setValue: toggleWorkspaceMenu, storedValue: isWorkspaceMenuOpen } = useLocalStorage( + "is_workspace_menu_open", + true + ); + + // store hooks + const { isExtendedSidebarOpened, toggleExtendedSidebar } = useAppTheme(); + const { getNavigationPreferences } = useWorkspace(); + // translation + const { t } = useTranslation(); + // derived values + const currentWorkspaceNavigationPreferences = getNavigationPreferences(workspaceSlug.toString()); + + const toggleListDisclosure = (isOpen: boolean) => { + toggleWorkspaceMenu(isOpen); + }; + + const sortedNavigationItems = useMemo( + () => + WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS.map((item) => { + const preference = currentWorkspaceNavigationPreferences?.[item.key]; + return { + ...item, + sort_order: preference ? preference.sort_order : 0, + }; + }).sort((a, b) => a.sort_order - b.sort_order), + [currentWorkspaceNavigationPreferences] + ); + + return ( + <> +
    + {WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS.map((item, _index) => ( + + ))} +
    + +
    + toggleListDisclosure(!isWorkspaceMenuOpen)} + aria-label={t( + isWorkspaceMenuOpen + ? "aria_labels.app_sidebar.close_workspace_menu" + : "aria_labels.app_sidebar.open_workspace_menu" + )} + > + {t("workspace")} + +
    + toggleListDisclosure(!isWorkspaceMenuOpen)} + aria-label={t( + isWorkspaceMenuOpen + ? "aria_labels.app_sidebar.close_workspace_menu" + : "aria_labels.app_sidebar.open_workspace_menu" + )} + > + + +
    +
    + + {isWorkspaceMenuOpen && ( + + <> + {WORKSPACE_SIDEBAR_STATIC_PINNED_NAVIGATION_ITEMS_LINKS.map((item, _index) => ( + + ))} + {sortedNavigationItems.map((item, _index) => ( + + ))} + + + + + + )} + +
    + + ); +}); diff --git a/web/core/components/workspace/sidebar/user-menu-item.tsx b/apps/web/core/components/workspace/sidebar/user-menu-item.tsx similarity index 50% rename from web/core/components/workspace/sidebar/user-menu-item.tsx rename to apps/web/core/components/workspace/sidebar/user-menu-item.tsx index 3f89dd687..5d0b555dc 100644 --- a/web/core/components/workspace/sidebar/user-menu-item.tsx +++ b/apps/web/core/components/workspace/sidebar/user-menu-item.tsx @@ -3,15 +3,16 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useParams, usePathname } from "next/navigation"; // plane imports -import { EUserPermissionsLevel, EUserWorkspaceRoles, SIDEBAR_TRACKER_EVENTS } from "@plane/constants"; -import { usePlatformOS } from "@plane/hooks"; +import { EUserPermissionsLevel, SIDEBAR_TRACKER_ELEMENTS } from "@plane/constants"; + import { useTranslation } from "@plane/i18n"; -import { Tooltip } from "@plane/ui"; +import { EUserWorkspaceRoles } from "@plane/types"; // components import { SidebarNavItem } from "@/components/sidebar"; import { NotificationAppSidebarOption } from "@/components/workspace-notifications"; // hooks -import { useAppTheme, useEventTracker, useUserPermissions } from "@/hooks/store"; +import { captureClick } from "@/helpers/event-tracker.helper"; +import { useAppTheme, useUserPermissions } from "@/hooks/store"; export interface SidebarUserMenuItemProps { item: { @@ -33,10 +34,8 @@ export const SidebarUserMenuItem: FC = observer((props // package hooks const { t } = useTranslation(); // store hooks - const { captureEvent } = useEventTracker(); const { allowPermissions } = useUserPermissions(); - const { toggleSidebar, sidebarCollapsed } = useAppTheme(); - const { isMobile } = usePlatformOS(); + const { toggleSidebar } = useAppTheme(); const isActive = pathname === item.href; @@ -49,36 +48,23 @@ export const SidebarUserMenuItem: FC = observer((props if (window.innerWidth < 768) { toggleSidebar(); } - captureEvent(SIDEBAR_TRACKER_EVENTS.click, { - destination: itemKey, + captureClick({ + elementName: SIDEBAR_TRACKER_ELEMENTS.USER_MENU_ITEM, + context: { + destination: itemKey, + }, }); }; return ( - - handleLinkClick(item.key)}> - -
    - - {!sidebarCollapsed &&

    {t(item.labelTranslationKey)}

    } -
    - {item.key === "notifications" && ( - - )} -
    - -
    + handleLinkClick(item.key)}> + +
    + +

    {t(item.labelTranslationKey)}

    +
    + {item.key === "notifications" && } +
    + ); }); diff --git a/apps/web/core/components/workspace/sidebar/user-menu-root.tsx b/apps/web/core/components/workspace/sidebar/user-menu-root.tsx new file mode 100644 index 000000000..1dda94995 --- /dev/null +++ b/apps/web/core/components/workspace/sidebar/user-menu-root.tsx @@ -0,0 +1,159 @@ +"use client"; + +import { Fragment, Ref, useState, useEffect } from "react"; +import { observer } from "mobx-react"; +import Link from "next/link"; +import { useParams } from "next/navigation"; +import { usePopper } from "react-popper"; +// icons +import { LogOut, PanelLeftDashed, Settings } from "lucide-react"; +// ui +import { Menu, Transition } from "@headlessui/react"; +// plane imports +import { GOD_MODE_URL } from "@plane/constants"; +import { useTranslation } from "@plane/i18n"; +import { Avatar, TOAST_TYPE, setToast } from "@plane/ui"; +import { getFileURL } from "@plane/utils"; +// hooks +import { useAppTheme, useUser } from "@/hooks/store"; +import { useAppRail } from "@/hooks/use-app-rail"; + +type Props = { + size?: "sm" | "md"; +}; + +export const UserMenuRoot = observer((props: Props) => { + const { size = "sm" } = props; + const { workspaceSlug } = useParams(); + // store hooks + const { toggleAnySidebarDropdown, sidebarPeek, toggleSidebarPeek } = useAppTheme(); + + const { isEnabled, shouldRenderAppRail, toggleAppRail } = useAppRail(); + const { data: currentUser } = useUser(); + const { signOut } = useUser(); + // derived values + + const isUserInstanceAdmin = false; + // translation + const { t } = useTranslation(); + // local state + const [isUserMenuOpen, setIsUserMenuOpen] = useState(false); + // popper-js refs + const [referenceElement, setReferenceElement] = useState(null); + const [popperElement, setPopperElement] = useState(null); + // popper-js init + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement: "right", + modifiers: [{ name: "preventOverflow", options: { padding: 12 } }], + }); + + const handleSignOut = async () => { + await signOut().catch(() => + setToast({ + type: TOAST_TYPE.ERROR, + title: t("sign_out.toast.error.title"), + message: t("sign_out.toast.error.message"), + }) + ); + }; + + // Toggle sidebar dropdown state when either menu is open + useEffect(() => { + if (isUserMenuOpen) toggleAnySidebarDropdown(true); + else toggleAnySidebarDropdown(false); + }, [isUserMenuOpen]); + + return ( + + {({ open, close }: { open: boolean; close: () => void }) => { + // Update local state directly + if (isUserMenuOpen !== open) { + setIsUserMenuOpen(open); + } + + return ( + <> + + + + + } + style={styles.popper} + {...attributes.popper} + > +
    + {currentUser?.email} + + + + + {t("settings")} + + + + {isEnabled && ( + { + if (sidebarPeek) toggleSidebarPeek(false); + toggleAppRail(); + }} + > + + {shouldRenderAppRail ? "Undock AppRail" : "Dock AppRail"} + + )} +
    +
    + + + {t("sign_out")} + +
    + {isUserInstanceAdmin && ( +
    + + + + {t("enter_god_mode")} + + + +
    + )} +
    +
    + + ); + }} +
    + ); +}); diff --git a/web/core/components/workspace/sidebar/user-menu.tsx b/apps/web/core/components/workspace/sidebar/user-menu.tsx similarity index 84% rename from web/core/components/workspace/sidebar/user-menu.tsx rename to apps/web/core/components/workspace/sidebar/user-menu.tsx index 5e3ee4b0a..9826a77b9 100644 --- a/web/core/components/workspace/sidebar/user-menu.tsx +++ b/apps/web/core/components/workspace/sidebar/user-menu.tsx @@ -4,19 +4,16 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Home, Inbox, PenSquare } from "lucide-react"; +import { EUserWorkspaceRoles } from "@plane/types"; // plane imports -import { EUserWorkspaceRoles } from "@plane/constants"; import { UserActivityIcon } from "@plane/ui"; // components -import { cn } from "@plane/utils"; import { SidebarUserMenuItem } from "@/components/workspace/sidebar"; -// helpers // hooks -import { useAppTheme, useUserPermissions, useUser } from "@/hooks/store"; +import { useUserPermissions, useUser } from "@/hooks/store"; export const SidebarUserMenu = observer(() => { const { workspaceSlug } = useParams(); - const { sidebarCollapsed } = useAppTheme(); const { workspaceUserInfo } = useUserPermissions(); const { data: currentUser } = useUser(); @@ -54,11 +51,7 @@ export const SidebarUserMenu = observer(() => { const draftIssueCount = workspaceUserInfo[workspaceSlug.toString()]?.draft_issue_count; return ( -
    +
    {SIDEBAR_USER_MENU_ITEMS.map((item) => ( ))} diff --git a/web/core/components/workspace/sidebar/workspace-menu-header.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx similarity index 89% rename from web/core/components/workspace/sidebar/workspace-menu-header.tsx rename to apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx index 3367a2b34..0d2a736f3 100644 --- a/web/core/components/workspace/sidebar/workspace-menu-header.tsx +++ b/apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx @@ -5,13 +5,14 @@ import { useParams } from "next/navigation"; import { MoreHorizontal, ArchiveIcon, ChevronRight, Settings } from "lucide-react"; import { Disclosure } from "@headlessui/react"; // plane imports -import { EUserWorkspaceRoles, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissionsLevel } from "@plane/constants"; import { useOutsideClickDetector } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; +import { EUserWorkspaceRoles } from "@plane/types"; import { CustomMenu } from "@plane/ui"; import { cn } from "@plane/utils"; // store hooks -import { useAppTheme, useUserPermissions } from "@/hooks/store"; +import { useUserPermissions } from "@/hooks/store"; export type SidebarWorkspaceMenuHeaderProps = { isWorkspaceMenuOpen: boolean; @@ -26,7 +27,6 @@ export const SidebarWorkspaceMenuHeader: FC = o const actionSectionRef = useRef(null); // hooks const { workspaceSlug } = useParams(); - const { sidebarCollapsed } = useAppTheme(); const { allowPermissions } = useUserPermissions(); const { t } = useTranslation(); @@ -36,19 +36,8 @@ export const SidebarWorkspaceMenuHeader: FC = o // eslint-disable-next-line @typescript-eslint/no-explicit-any const isAdmin = allowPermissions([EUserWorkspaceRoles.ADMIN] as any, EUserPermissionsLevel.WORKSPACE); - if (sidebarCollapsed) { - return <>; - } - return ( -
    +
    = obser const { workspaceSlug } = useParams(); const { allowPermissions } = useUserPermissions(); // store hooks - const { toggleSidebar, sidebarCollapsed } = useAppTheme(); - const { isMobile } = usePlatformOS(); + const { toggleSidebar } = useAppTheme(); const handleLinkClick = () => { if (window.innerWidth < 768) { @@ -50,33 +48,20 @@ export const SidebarWorkspaceMenuItem: FC = obser const isActive = item.href === pathname; return ( - - handleLinkClick()}> - -
    - - {!sidebarCollapsed &&

    {t(item.labelTranslationKey)}

    } -
    - {!sidebarCollapsed && item.key === "active_cycles" && ( -
    - -
    - )} -
    - -
    + handleLinkClick()}> + +
    + +

    {t(item.labelTranslationKey)}

    +
    +
    + +
    +
    + ); }); diff --git a/web/core/components/workspace/sidebar/dropdown.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx similarity index 51% rename from web/core/components/workspace/sidebar/dropdown.tsx rename to apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx index d1d5e5249..c6f1d3ec2 100644 --- a/web/core/components/workspace/sidebar/dropdown.tsx +++ b/apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx @@ -1,21 +1,19 @@ "use client"; -import { Fragment, Ref, useState } from "react"; +import React, { Fragment, useState, useEffect } from "react"; import { observer } from "mobx-react"; import Link from "next/link"; -import { useParams } from "next/navigation"; -import { usePopper } from "react-popper"; // icons -import { ChevronDown, CirclePlus, LogOut, Mails, Settings } from "lucide-react"; +import { ChevronDown, CirclePlus, LogOut, Mails } from "lucide-react"; // ui import { Menu, Transition } from "@headlessui/react"; // plane imports -import { GOD_MODE_URL } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { IWorkspace } from "@plane/types"; -import { Avatar, Loader, TOAST_TYPE, setToast } from "@plane/ui"; -import { orderWorkspacesList, cn, getFileURL } from "@plane/utils"; +import { Loader, TOAST_TYPE, setToast } from "@plane/ui"; +import { orderWorkspacesList, cn } from "@plane/utils"; // helpers +import { AppSidebarItem } from "@/components/sidebar"; // hooks import { useAppTheme, useUser, useUserProfile, useWorkspace } from "@/hooks/store"; // plane web helpers @@ -24,27 +22,24 @@ import { getIsWorkspaceCreationDisabled } from "@/plane-web/helpers/instance.hel import { WorkspaceLogo } from "../logo"; import SidebarDropdownItem from "./dropdown-item"; -export const SidebarDropdown = observer(() => { - const { workspaceSlug } = useParams(); +type WorkspaceMenuRootProps = { + renderLogoOnly?: boolean; +}; + +export const WorkspaceMenuRoot = observer((props: WorkspaceMenuRootProps) => { + const { renderLogoOnly } = props; // store hooks - const { sidebarCollapsed, toggleSidebar } = useAppTheme(); + const { toggleSidebar, toggleAnySidebarDropdown } = useAppTheme(); const { data: currentUser } = useUser(); const { signOut } = useUser(); const { updateUserProfile } = useUserProfile(); const { currentWorkspace: activeWorkspace, workspaces } = useWorkspace(); // derived values const isWorkspaceCreationEnabled = getIsWorkspaceCreationDisabled() === false; - const isUserInstanceAdmin = false; // translation const { t } = useTranslation(); - // popper-js refs - const [referenceElement, setReferenceElement] = useState(null); - const [popperElement, setPopperElement] = useState(null); - // popper-js init - const { styles, attributes } = usePopper(referenceElement, popperElement, { - placement: "right", - modifiers: [{ name: "preventOverflow", options: { padding: 12 } }], - }); + // local state + const [isWorkspaceMenuOpen, setIsWorkspaceMenuOpen] = useState(false); const handleWorkspaceNavigation = (workspace: IWorkspace) => updateUserProfile({ last_workspace_id: workspace?.id }); @@ -65,57 +60,86 @@ export const SidebarDropdown = observer(() => { }; const workspacesList = orderWorkspacesList(Object.values(workspaces ?? {})); // TODO: fix workspaces list scroll + + // Toggle sidebar dropdown state when either menu is open + useEffect(() => { + if (isWorkspaceMenuOpen) toggleAnySidebarDropdown(true); + else toggleAnySidebarDropdown(false); + }, [isWorkspaceMenuOpen]); + + const logo = activeWorkspace?.logo_url; + const name = activeWorkspace?.name; + return ( -
    - - {({ open, close }) => ( + {({ open, close }: { open: boolean; close: () => void }) => { + // Update local state directly + if (isWorkspaceMenuOpen !== open) { + setIsWorkspaceMenuOpen(open); + } + + return ( <> - -
    - - {!sidebarCollapsed && ( + {renderLogoOnly ? ( + + + ), + }} + /> + + ) : ( + +
    +

    {activeWorkspace?.name ?? t("loading")}

    - )} -
    - {!sidebarCollapsed && ( +
    + + )} + -
    +
    - + {currentUser?.email} {workspacesList ? ( @@ -185,74 +209,8 @@ export const SidebarDropdown = observer(() => { - )} -
    - - - - - - } - style={styles.popper} - {...attributes.popper} - > -
    - {currentUser?.email} - - - - - {t("settings")} - - - -
    -
    - - - {t("sign_out")} - -
    - {isUserInstanceAdmin && ( -
    - - - - {t("enter_god_mode")} - - - -
    - )} -
    -
    -
    -
    + ); + }} + ); }); diff --git a/web/core/components/workspace/sidebar/workspace-menu.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu.tsx similarity index 82% rename from web/core/components/workspace/sidebar/workspace-menu.tsx rename to apps/web/core/components/workspace/sidebar/workspace-menu.tsx index 57582c6c8..a43224d8d 100644 --- a/web/core/components/workspace/sidebar/workspace-menu.tsx +++ b/apps/web/core/components/workspace/sidebar/workspace-menu.tsx @@ -1,35 +1,27 @@ "use client"; -import React, { useEffect } from "react"; +import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { BarChart2, Briefcase, Layers } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +import { EUserWorkspaceRoles } from "@plane/types"; // ui -import { EUserWorkspaceRoles } from "@plane/constants"; import { ContrastIcon } from "@plane/ui"; // components import { cn } from "@plane/utils"; import { SidebarWorkspaceMenuHeader, SidebarWorkspaceMenuItem } from "@/components/workspace/sidebar"; -// helpers // hooks -import { useAppTheme } from "@/hooks/store"; import useLocalStorage from "@/hooks/use-local-storage"; export const SidebarWorkspaceMenu = observer(() => { // router params const { workspaceSlug } = useParams(); - // store hooks - const { sidebarCollapsed } = useAppTheme(); // local storage const { setValue: toggleWorkspaceMenu, storedValue } = useLocalStorage("is_workspace_menu_open", true); // derived values const isWorkspaceMenuOpen = !!storedValue; - useEffect(() => { - if (sidebarCollapsed) toggleWorkspaceMenu(true); - }, [sidebarCollapsed, toggleWorkspaceMenu]); - const SIDEBAR_WORKSPACE_MENU_ITEMS = [ { key: "projects", @@ -74,13 +66,7 @@ export const SidebarWorkspaceMenu = observer(() => { leaveTo="transform scale-95 opacity-0" > {isWorkspaceMenuOpen && ( - + {SIDEBAR_WORKSPACE_MENU_ITEMS.map((item) => ( ))} diff --git a/web/core/components/workspace/views/default-view-list-item.tsx b/apps/web/core/components/workspace/views/default-view-list-item.tsx similarity index 100% rename from web/core/components/workspace/views/default-view-list-item.tsx rename to apps/web/core/components/workspace/views/default-view-list-item.tsx diff --git a/web/core/components/workspace/views/default-view-quick-action.tsx b/apps/web/core/components/workspace/views/default-view-quick-action.tsx similarity index 100% rename from web/core/components/workspace/views/default-view-quick-action.tsx rename to apps/web/core/components/workspace/views/default-view-quick-action.tsx diff --git a/web/core/components/workspace/views/delete-view-modal.tsx b/apps/web/core/components/workspace/views/delete-view-modal.tsx similarity index 78% rename from web/core/components/workspace/views/delete-view-modal.tsx rename to apps/web/core/components/workspace/views/delete-view-modal.tsx index 65f4efdd4..0e6c5857e 100644 --- a/web/core/components/workspace/views/delete-view-modal.tsx +++ b/apps/web/core/components/workspace/views/delete-view-modal.tsx @@ -4,13 +4,14 @@ import React, { useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // types -import { GLOBAL_VIEW_TOUR_TRACKER_EVENTS } from "@plane/constants"; +import { GLOBAL_VIEW_TRACKER_EVENTS } from "@plane/constants"; import { IWorkspaceView } from "@plane/types"; // ui import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; // constants // hooks -import { useGlobalView, useEventTracker } from "@/hooks/store"; +import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; +import { useGlobalView } from "@/hooks/store"; type Props = { data: IWorkspaceView; @@ -26,7 +27,6 @@ export const DeleteGlobalViewModal: React.FC = observer((props) => { const { workspaceSlug } = useParams(); // store hooks const { deleteGlobalView } = useGlobalView(); - const { captureEvent } = useEventTracker(); const handleClose = () => onClose(); @@ -37,15 +37,20 @@ export const DeleteGlobalViewModal: React.FC = observer((props) => { await deleteGlobalView(workspaceSlug.toString(), data.id) .then(() => { - captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, { - view_id: data.id, - state: "SUCCESS", + captureSuccess({ + eventName: GLOBAL_VIEW_TRACKER_EVENTS.delete, + payload: { + view_id: data.id, + }, }); }) .catch((error: any) => { - captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.delete, { - view_id: data.id, - state: "FAILED", + captureError({ + eventName: GLOBAL_VIEW_TRACKER_EVENTS.delete, + payload: { + view_id: data.id, + }, + error: error, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/web/core/components/workspace/views/form.tsx b/apps/web/core/components/workspace/views/form.tsx similarity index 97% rename from web/core/components/workspace/views/form.tsx rename to apps/web/core/components/workspace/views/form.tsx index 676182216..ece0918f7 100644 --- a/web/core/components/workspace/views/form.tsx +++ b/apps/web/core/components/workspace/views/form.tsx @@ -4,11 +4,18 @@ import { useEffect } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // constant -import { EIssueLayoutTypes, ISSUE_DISPLAY_FILTERS_BY_PAGE, EViewAccess } from "@plane/constants"; +import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants"; // i18n import { useTranslation } from "@plane/i18n"; // types -import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, IWorkspaceView } from "@plane/types"; +import { + EViewAccess, + IIssueDisplayFilterOptions, + IIssueDisplayProperties, + IIssueFilterOptions, + IWorkspaceView, + EIssueLayoutTypes, +} from "@plane/types"; // ui import { Button, Input, TextArea } from "@plane/ui"; // components diff --git a/web/core/components/workspace/views/header.tsx b/apps/web/core/components/workspace/views/header.tsx similarity index 83% rename from web/core/components/workspace/views/header.tsx rename to apps/web/core/components/workspace/views/header.tsx index 4aa17493c..05401dca8 100644 --- a/web/core/components/workspace/views/header.tsx +++ b/apps/web/core/components/workspace/views/header.tsx @@ -8,7 +8,8 @@ import { DEFAULT_GLOBAL_VIEWS_LIST, EUserPermissions, EUserPermissionsLevel, - GLOBAL_VIEW_TOUR_TRACKER_EVENTS, + GLOBAL_VIEW_TRACKER_ELEMENTS, + GLOBAL_VIEW_TRACKER_EVENTS, } from "@plane/constants"; import { TStaticViewTypes } from "@plane/types"; // components @@ -20,7 +21,8 @@ import { } from "@/components/workspace"; // constants // store hooks -import { useEventTracker, useGlobalView, useUserPermissions } from "@/hooks/store"; +import { captureSuccess } from "@/helpers/event-tracker.helper"; +import { useGlobalView, useUserPermissions } from "@/hooks/store"; const ViewTab = observer((props: { viewId: string }) => { const { viewId } = props; @@ -72,16 +74,17 @@ export const GlobalViewsHeader: React.FC = observer(() => { const { currentWorkspaceViews } = useGlobalView(); const { allowPermissions } = useUserPermissions(); - const { captureEvent } = useEventTracker(); - // bring the active view to the centre of the header useEffect(() => { if (globalViewId && currentWorkspaceViews) { - captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.open, { - view_id: globalViewId, - view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString()) - ? "Default" - : "Custom", + captureSuccess({ + eventName: GLOBAL_VIEW_TRACKER_EVENTS.open, + payload: { + view_id: globalViewId, + view_type: ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString()) + ? "Default" + : "Custom", + }, }); const activeTabElement = document.querySelector(`#global-view-${globalViewId.toString()}`); if (activeTabElement && containerRef.current) { @@ -91,7 +94,7 @@ export const GlobalViewsHeader: React.FC = observer(() => { activeTabElement.scrollIntoView({ behavior: "smooth", inline: diff > 500 ? "center" : "nearest" }); } } - }, [globalViewId, currentWorkspaceViews, containerRef, captureEvent]); + }, [globalViewId, currentWorkspaceViews, containerRef]); const isAuthorizedUser = allowPermissions( [EUserPermissions.ADMIN, EUserPermissions.MEMBER], @@ -109,12 +112,15 @@ export const GlobalViewsHeader: React.FC = observer(() => { ))} - {currentWorkspaceViews?.map((viewId) => )} + {currentWorkspaceViews?.map((viewId) => ( + + ))}
    {isAuthorizedUser ? ( + + {isDropdownOpen && ( +
    + {IMAGE_ALIGNMENT_OPTIONS.map((option) => ( + + + + ))} +
    + )} +
    + ); +}; diff --git a/packages/editor/src/core/extensions/custom-image/components/toolbar/download.tsx b/packages/editor/src/core/extensions/custom-image/components/toolbar/download.tsx new file mode 100644 index 000000000..2f0a665ae --- /dev/null +++ b/packages/editor/src/core/extensions/custom-image/components/toolbar/download.tsx @@ -0,0 +1,24 @@ +import { Download } from "lucide-react"; +// plane imports +import { Tooltip } from "@plane/ui"; + +type Props = { + src: string; +}; + +export const ImageDownloadAction: React.FC = (props) => { + const { src } = props; + + return ( + + + + ); +}; diff --git a/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/index.ts b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/index.ts new file mode 100644 index 000000000..1efe34c51 --- /dev/null +++ b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/index.ts @@ -0,0 +1 @@ +export * from "./root"; diff --git a/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/modal.tsx similarity index 57% rename from packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx rename to packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/modal.tsx index 1d2e52ca0..9a30908c2 100644 --- a/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/modal.tsx @@ -1,37 +1,39 @@ -import { ExternalLink, Maximize, Minus, Plus, X } from "lucide-react"; -import { useCallback, useEffect, useMemo, useState, useRef } from "react"; +import { Download, ExternalLink, Minus, Plus, X } from "lucide-react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import ReactDOM from "react-dom"; // plane imports import { cn } from "@plane/utils"; -type Props = { - image: { - width: string; - height: string; - aspectRatio: number; - src: string; - }; - isOpen: boolean; - toggleFullScreenMode: (val: boolean) => void; -}; - const MIN_ZOOM = 0.5; const MAX_ZOOM = 2; const ZOOM_SPEED = 0.05; const ZOOM_STEPS = [0.5, 1, 1.5, 2]; -export const ImageFullScreenAction: React.FC = (props) => { - const { image, isOpen: isFullScreenEnabled, toggleFullScreenMode } = props; - const { src, width, aspectRatio } = image; +type Props = { + aspectRatio: number; + isFullScreenEnabled: boolean; + downloadSrc: string; + src: string; + toggleFullScreenMode: (val: boolean) => void; + width: string; +}; + +const ImageFullScreenModalWithoutPortal = (props: Props) => { + const { aspectRatio, isFullScreenEnabled, downloadSrc, src, toggleFullScreenMode, width } = props; + // refs + const dragStart = useRef({ x: 0, y: 0 }); + const dragOffset = useRef({ x: 0, y: 0 }); const [magnification, setMagnification] = useState(1); const [initialMagnification, setInitialMagnification] = useState(1); const [isDragging, setIsDragging] = useState(false); - const dragStart = useRef({ x: 0, y: 0 }); - const dragOffset = useRef({ x: 0, y: 0 }); const modalRef = useRef(null); const imgRef = useRef(null); - const widthInNumber = useMemo(() => Number(width?.replace("px", "")), [width]); + const widthInNumber = useMemo(() => { + if (!width) return 0; + return Number(width.replace("px", "")); + }, [width]); const setImageRef = useCallback( (node: HTMLImageElement | null) => { @@ -148,7 +150,7 @@ export const ImageFullScreenAction: React.FC = (props) => { e.preventDefault(); // Handle pinch-to-zoom - if (e.ctrlKey) { + if (e.ctrlKey || e.metaKey) { const delta = e.deltaY; setMagnification((prev) => { const newZoom = prev * (1 - delta * ZOOM_SPEED); @@ -165,7 +167,7 @@ export const ImageFullScreenAction: React.FC = (props) => { return; } }, - [isFullScreenEnabled, magnification] + [isFullScreenEnabled] ); // Event listeners @@ -185,84 +187,99 @@ export const ImageFullScreenAction: React.FC = (props) => { }; }, [isFullScreenEnabled, handleKeyDown, handleMouseMove, handleMouseUp, handleWheel]); + if (!isFullScreenEnabled) return null; + return ( - <> +
    e.target === modalRef.current && handleClose()} + className="relative size-full grid place-items-center overflow-hidden" > -
    e.target === modalRef.current && handleClose()} - className="relative size-full grid place-items-center overflow-hidden" + - -
    -
    - - {Math.round(100 * magnification)}% - -
    + + + +
    +
    + {Math.round(100 * magnification)}% +
    + +
    - - +
    ); }; + +export const ImageFullScreenModal: React.FC = (props) => { + let modal = ; + const portal = document.querySelector("#editor-portal"); + if (portal) { + modal = ReactDOM.createPortal(modal, portal); + } else { + console.warn("Portal element #editor-portal not found. Rendering inline."); + } + return modal; +}; diff --git a/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/root.tsx b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/root.tsx new file mode 100644 index 000000000..2108bfeaa --- /dev/null +++ b/packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen/root.tsx @@ -0,0 +1,56 @@ +import { Maximize } from "lucide-react"; +import { useEffect, useState } from "react"; +// plane imports +import { Tooltip } from "@plane/ui"; +// local imports +import { ImageFullScreenModal } from "./modal"; + +type Props = { + image: { + downloadSrc: string; + src: string; + height: string; + width: string; + aspectRatio: number; + }; + toggleToolbarViewStatus: (val: boolean) => void; +}; + +export const ImageFullScreenActionRoot: React.FC = (props) => { + const { image, toggleToolbarViewStatus } = props; + // states + const [isFullScreenEnabled, setIsFullScreenEnabled] = useState(false); + // derived values + const { downloadSrc, src, width, aspectRatio } = image; + + useEffect(() => { + toggleToolbarViewStatus(isFullScreenEnabled); + }, [isFullScreenEnabled, toggleToolbarViewStatus]); + + return ( + <> + + + + + + ); +}; diff --git a/packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx b/packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx index f9cd28d48..06277fa25 100644 --- a/packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx @@ -2,35 +2,43 @@ import { useState } from "react"; // plane imports import { cn } from "@plane/utils"; // local imports -import { ImageFullScreenAction } from "./full-screen"; +import type { TCustomImageAlignment } from "../../types"; +import { ImageAlignmentAction } from "./alignment"; +import { ImageDownloadAction } from "./download"; +import { ImageFullScreenActionRoot } from "./full-screen"; type Props = { - containerClassName?: string; - image: { - width: string; - height: string; - aspectRatio: number; - src: string; - }; + alignment: TCustomImageAlignment; + width: string; + height: string; + aspectRatio: number; + src: string; + downloadSrc: string; + handleAlignmentChange: (alignment: TCustomImageAlignment) => void; }; export const ImageToolbarRoot: React.FC = (props) => { - const { containerClassName, image } = props; - // state - const [isFullScreenEnabled, setIsFullScreenEnabled] = useState(false); + const { alignment, downloadSrc, handleAlignmentChange } = props; + // states + const [shouldShowToolbar, setShouldShowToolbar] = useState(false); return ( <>
    - setIsFullScreenEnabled(val)} + + +
    ); diff --git a/packages/editor/src/core/extensions/custom-image/components/uploader.tsx b/packages/editor/src/core/extensions/custom-image/components/uploader.tsx index 68626084a..109ec3e30 100644 --- a/packages/editor/src/core/extensions/custom-image/components/uploader.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/uploader.tsx @@ -165,7 +165,7 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => { } return "Add an image"; - }, [draggedInside, failedToLoadImage, isImageBeingUploaded, editor.isEditable]); + }, [draggedInside, editor.isEditable, failedToLoadImage, isImageBeingUploaded]); return (
    { const { fileHandler, isEditable } = props; // derived values - const { getAssetSrc, restore: restoreImageFn } = fileHandler; + const { getAssetSrc, getAssetDownloadSrc, restore: restoreImageFn } = fileHandler; return CustomImageExtensionConfig.extend({ selectable: isEditable, @@ -31,6 +31,7 @@ export const CustomImageExtension = (props: Props) => { return { ...this.parent?.(), + getImageDownloadSource: getAssetDownloadSrc, getImageSource: getAssetSrc, restoreImage: restoreImageFn, uploadImage: upload, @@ -115,7 +116,9 @@ export const CustomImageExtension = (props: Props) => { }, addNodeView() { - return ReactNodeViewRenderer(CustomImageNodeView); + return ReactNodeViewRenderer((props) => ( + + )); }, }); }; diff --git a/packages/editor/src/core/extensions/custom-image/types.ts b/packages/editor/src/core/extensions/custom-image/types.ts index 675d8a221..4ed5cd6ce 100644 --- a/packages/editor/src/core/extensions/custom-image/types.ts +++ b/packages/editor/src/core/extensions/custom-image/types.ts @@ -8,6 +8,7 @@ export enum ECustomImageAttributeNames { HEIGHT = "height", ASPECT_RATIO = "aspectRatio", SOURCE = "src", + ALIGNMENT = "alignment", } export type Pixel = `${number}px`; @@ -20,12 +21,15 @@ export type TCustomImageSize = { aspectRatio: number | null; }; +export type TCustomImageAlignment = "left" | "center" | "right"; + export type TCustomImageAttributes = { [ECustomImageAttributeNames.ID]: string | null; [ECustomImageAttributeNames.WIDTH]: PixelAttribute<"35%" | number> | null; [ECustomImageAttributeNames.HEIGHT]: PixelAttribute<"auto" | number> | null; [ECustomImageAttributeNames.ASPECT_RATIO]: number | null; [ECustomImageAttributeNames.SOURCE]: string | null; + [ECustomImageAttributeNames.ALIGNMENT]: TCustomImageAlignment; }; export type UploadEntity = ({ event: "insert" } | { event: "drop"; file: File }) & { hasOpenedFileInputOnce?: boolean }; @@ -37,6 +41,7 @@ export type InsertImageComponentProps = { }; export type CustomImageExtensionOptions = { + getImageDownloadSource: TFileHandler["getAssetDownloadSrc"]; getImageSource: TFileHandler["getAssetSrc"]; restoreImage: TFileHandler["restore"]; uploadImage?: TFileHandler["upload"]; diff --git a/packages/editor/src/core/extensions/custom-image/utils.ts b/packages/editor/src/core/extensions/custom-image/utils.ts index 0711e094f..10f2bb1e2 100644 --- a/packages/editor/src/core/extensions/custom-image/utils.ts +++ b/packages/editor/src/core/extensions/custom-image/utils.ts @@ -1,10 +1,11 @@ import type { Editor } from "@tiptap/core"; +import { AlignCenter, AlignLeft, AlignRight, type LucideIcon } from "lucide-react"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; // helpers import { getExtensionStorage } from "@/helpers/get-extension-storage"; // local imports -import { ECustomImageAttributeNames, type Pixel, type TCustomImageAttributes } from "./types"; +import { ECustomImageAttributeNames, TCustomImageAlignment, type Pixel, type TCustomImageAttributes } from "./types"; export const DEFAULT_CUSTOM_IMAGE_ATTRIBUTES: TCustomImageAttributes = { [ECustomImageAttributeNames.SOURCE]: null, @@ -12,6 +13,7 @@ export const DEFAULT_CUSTOM_IMAGE_ATTRIBUTES: TCustomImageAttributes = { [ECustomImageAttributeNames.WIDTH]: "35%", [ECustomImageAttributeNames.HEIGHT]: "auto", [ECustomImageAttributeNames.ASPECT_RATIO]: null, + [ECustomImageAttributeNames.ALIGNMENT]: "left", }; export const getImageComponentImageFileMap = (editor: Editor) => @@ -31,3 +33,26 @@ export const ensurePixelString = ( return value; }; + +export const IMAGE_ALIGNMENT_OPTIONS: { + label: string; + value: TCustomImageAlignment; + icon: LucideIcon; +}[] = [ + { + label: "Left", + value: "left", + icon: AlignLeft, + }, + { + label: "Center", + value: "center", + icon: AlignCenter, + }, + { + label: "Right", + value: "right", + icon: AlignRight, + }, +]; +export const getImageBlockId = (id: string) => `editor-image-block-${id}`; diff --git a/packages/editor/src/core/extensions/custom-link/extension.tsx b/packages/editor/src/core/extensions/custom-link/extension.tsx index 182afc9f8..9be125ce6 100644 --- a/packages/editor/src/core/extensions/custom-link/extension.tsx +++ b/packages/editor/src/core/extensions/custom-link/extension.tsx @@ -3,6 +3,8 @@ import { Plugin } from "@tiptap/pm/state"; import { find, registerCustomProtocol, reset } from "linkifyjs"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +// helpers +import { isValidHttpUrl } from "@/helpers/common"; // local imports import { autolink } from "./helpers/autolink"; import { clickHandler } from "./helpers/clickHandler"; @@ -112,13 +114,14 @@ export const CustomLinkExtension = Mark.create({ linkOnPaste: true, autolink: true, inclusive: false, - protocols: [], + protocols: ["http", "https"], HTMLAttributes: { target: "_blank", rel: "noopener noreferrer nofollow", - class: null, + class: + "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", }, - validate: undefined, + validate: (url: string) => isValidHttpUrl(url).isValid, }; }, diff --git a/packages/editor/src/core/extensions/emoji/components/emojis-list.tsx b/packages/editor/src/core/extensions/emoji/components/emojis-list.tsx new file mode 100644 index 000000000..049d3b2d8 --- /dev/null +++ b/packages/editor/src/core/extensions/emoji/components/emojis-list.tsx @@ -0,0 +1,199 @@ +import { computePosition, flip, shift } from "@floating-ui/dom"; +import { Editor, posToDOMRect } from "@tiptap/react"; +import { SuggestionKeyDownProps } from "@tiptap/suggestion"; +import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react"; +// plane imports +import { cn } from "@plane/utils"; + +export interface EmojiItem { + name: string; + emoji: string; + shortcodes: string[]; + tags: string[]; + fallbackImage?: string; +} + +export interface EmojiListProps { + items: EmojiItem[]; + command: (item: { name: string }) => void; + editor: Editor; + query: string; +} + +export interface EmojiListRef { + onKeyDown: (props: SuggestionKeyDownProps) => boolean; +} + +const updatePosition = (editor: Editor, element: HTMLElement) => { + const virtualElement = { + getBoundingClientRect: () => posToDOMRect(editor.view, editor.state.selection.from, editor.state.selection.to), + }; + + computePosition(virtualElement, element, { + placement: "bottom-start", + strategy: "absolute", + middleware: [shift(), flip()], + }).then(({ x, y, strategy }) => { + Object.assign(element.style, { + width: "max-content", + position: strategy, + left: `${x}px`, + top: `${y}px`, + }); + }); +}; + +export const EmojiList = forwardRef((props, ref) => { + const { items, command, editor, query } = props; + const [selectedIndex, setSelectedIndex] = useState(0); + const [isVisible, setIsVisible] = useState(false); + const containerRef = useRef(null); + + const selectItem = useCallback( + (index: number): void => { + const item = items[index]; + if (item) { + command({ name: item.name }); + } + }, + [command, items] + ); + + const handleKeyDown = useCallback( + (event: KeyboardEvent): boolean => { + if (event.key === "Escape") { + event.preventDefault(); + return true; + } + + if (event.key === "ArrowUp") { + event.preventDefault(); + setSelectedIndex((prev) => (prev + items.length - 1) % items.length); + return true; + } + + if (event.key === "ArrowDown") { + event.preventDefault(); + setSelectedIndex((prev) => (prev + 1) % items.length); + return true; + } + + if (event.key === "Enter") { + event.preventDefault(); + selectItem(selectedIndex); + return true; + } + + return false; + }, + [items.length, selectedIndex, selectItem] + ); + + // Update position when items change + useEffect(() => { + if (containerRef.current && editor) { + updatePosition(editor, containerRef.current); + } + }, [items, editor]); + + // Handle scroll events + useEffect(() => { + const handleScroll = () => { + if (containerRef.current && editor) { + updatePosition(editor, containerRef.current); + } + }; + + document.addEventListener("scroll", handleScroll, true); + return () => document.removeEventListener("scroll", handleScroll, true); + }, [editor]); + + // Show animation + useEffect(() => { + setIsVisible(false); + const timeout = setTimeout(() => setIsVisible(true), 50); + return () => clearTimeout(timeout); + }, []); + + // Reset selection when items change + useEffect(() => setSelectedIndex(0), [items]); + + // Scroll selected item into view + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const item = container.querySelector(`#emoji-item-${selectedIndex}`) as HTMLElement; + if (item) { + const containerRect = container.getBoundingClientRect(); + const itemRect = item.getBoundingClientRect(); + + if (itemRect.top < containerRect.top || itemRect.bottom > containerRect.bottom) { + item.scrollIntoView({ block: "nearest" }); + } + } + }, [selectedIndex]); + + useImperativeHandle( + ref, + () => ({ + onKeyDown: ({ event }: SuggestionKeyDownProps): boolean => handleKeyDown(event), + }), + [handleKeyDown] + ); + + if (query.length <= 0) { + return null; + } + + return ( +
    +
    + {items.length ? ( + items.map((item, index) => { + const isSelected = index === selectedIndex; + const emojiKey = item.shortcodes.join(" - "); + + return ( + + ); + }) + ) : ( +
    No emojis found
    + )} +
    +
    + ); +}); + +EmojiList.displayName = "EmojiList"; diff --git a/packages/editor/src/core/extensions/emoji/emoji.ts b/packages/editor/src/core/extensions/emoji/emoji.ts new file mode 100644 index 000000000..581a094b8 --- /dev/null +++ b/packages/editor/src/core/extensions/emoji/emoji.ts @@ -0,0 +1,447 @@ +import { + combineTransactionSteps, + escapeForRegEx, + findChildrenInRange, + getChangedRanges, + InputRule, + mergeAttributes, + Node, + nodeInputRule, + PasteRule, + removeDuplicates, +} from "@tiptap/core"; +import { emojis, emojiToShortcode, shortcodeToEmoji } from "@tiptap/extension-emoji"; +import { Plugin, PluginKey, Transaction } from "@tiptap/pm/state"; +import Suggestion, { SuggestionOptions } from "@tiptap/suggestion"; +import emojiRegex from "emoji-regex"; +import { isEmojiSupported } from "is-emoji-supported"; +// helpers +import { customFindSuggestionMatch } from "@/helpers/find-suggestion-match"; + +declare module "@tiptap/core" { + interface Commands { + emoji: { + /** + * Add an emoji + */ + setEmoji: (shortcode: string) => ReturnType; + }; + } +} + +export type EmojiItem = { + /** + * A unique name of the emoji which will be stored as attribute + */ + name: string; + /** + * The emoji unicode character + */ + emoji?: string; + /** + * A list of unique shortcodes that are used by input rules to find the emoji + */ + shortcodes: string[]; + /** + * A list of tags that can help for searching emojis + */ + tags: string[]; + /** + * A name that can help to group emojis + */ + group?: string; + /** + * A list of unique emoticons + */ + emoticons?: string[]; + /** + * The unicode version the emoji was introduced + */ + version?: number; + /** + * A fallback image if the current system doesn't support the emoji or for custom emojis + */ + fallbackImage?: string; + /** + * Store some custom data + */ + [key: string]: any; +}; + +export type EmojiOptions = { + HTMLAttributes: Record; + emojis: EmojiItem[]; + enableEmoticons: boolean; + forceFallbackImages: boolean; + suggestion: Omit; +}; + +export type EmojiStorage = { + emojis: EmojiItem[]; + isSupported: (item: EmojiItem) => boolean; +}; + +export const EmojiSuggestionPluginKey = new PluginKey("emojiSuggestion"); + +export const inputRegex = /:([a-zA-Z0-9_+-]+):$/; + +export const pasteRegex = /:([a-zA-Z0-9_+-]+):/g; + +export const Emoji = Node.create({ + name: "emoji", + + inline: true, + + group: "inline", + + selectable: false, + + addOptions() { + return { + HTMLAttributes: {}, + // emojis: , + emojis: emojis, + enableEmoticons: false, + forceFallbackImages: false, + suggestion: { + char: ":", + pluginKey: EmojiSuggestionPluginKey, + command: ({ editor, range, props }) => { + // increase range.to by one when the next node is of type "text" + // and starts with a space character + const nodeAfter = editor.view.state.selection.$to.nodeAfter; + const overrideSpace = nodeAfter?.text?.startsWith(" "); + + if (overrideSpace) { + range.to += 1; + } + + editor + .chain() + .focus() + .insertContentAt(range, [ + { + type: this.name, + attrs: props, + }, + { + type: "text", + text: " ", + }, + ]) + .command(({ tr, state }) => { + tr.setStoredMarks(state.doc.resolve(state.selection.to - 2).marks()); + return true; + }) + .run(); + }, + allow: ({ state, range }) => { + const $from = state.doc.resolve(range.from); + const type = state.schema.nodes[this.name]; + const allow = !!$from.parent.type.contentMatch.matchType(type); + + return allow; + }, + }, + }; + }, + + addStorage() { + const { emojis } = this.options; + const supportMap: Record = removeDuplicates(emojis.map((item) => item.version)) + .filter((version) => typeof version === "number") + .reduce((versions, version) => { + const emoji = emojis.find((item) => item.version === version && item.emoji); + + return { + ...versions, + [version as number]: emoji ? isEmojiSupported(emoji.emoji as string) : false, + }; + }, {}); + + return { + emojis: this.options.emojis, + isSupported: (emojiItem) => (emojiItem.version ? supportMap[emojiItem.version] : false), + }; + }, + + addAttributes() { + return { + name: { + default: null, + parseHTML: (element) => element.dataset.name, + renderHTML: (attributes) => ({ + "data-name": attributes.name, + }), + }, + }; + }, + + parseHTML() { + return [ + { + tag: `span[data-type="${this.name}"]`, + }, + ]; + }, + + renderHTML({ HTMLAttributes, node }) { + const emojiItem = shortcodeToEmoji(node.attrs.name, this.options.emojis); + const attributes = mergeAttributes(HTMLAttributes, this.options.HTMLAttributes, { "data-type": this.name }); + + if (!emojiItem) { + return ["span", attributes, `:${node.attrs.name}:`]; + } + + const renderFallbackImage = false; + + return [ + "span", + attributes, + renderFallbackImage + ? [ + "img", + { + src: emojiItem.fallbackImage, + draggable: "false", + loading: "lazy", + align: "absmiddle", + }, + ] + : emojiItem.emoji || `:${emojiItem.shortcodes[0]}:`, + ]; + }, + + renderText({ node }) { + const emojiItem = shortcodeToEmoji(node.attrs.name, this.options.emojis); + + return emojiItem?.emoji || `:${node.attrs.name}:`; + }, + + addCommands() { + return { + setEmoji: + (shortcode) => + ({ chain }) => { + const emojiItem = shortcodeToEmoji(shortcode, this.options.emojis); + + if (!emojiItem) { + return false; + } + + chain() + .insertContent({ + type: this.name, + attrs: { + name: emojiItem.name, + }, + }) + .command(({ tr, state }) => { + tr.setStoredMarks(state.doc.resolve(state.selection.to - 1).marks()); + return true; + }) + .run(); + + return true; + }, + }; + }, + + addInputRules() { + const inputRules: InputRule[] = []; + + inputRules.push( + new InputRule({ + find: inputRegex, + handler: ({ range, match, chain }) => { + const name = match[1]; + + if (!shortcodeToEmoji(name, this.options.emojis)) { + return; + } + + chain() + .insertContentAt(range, { + type: this.name, + attrs: { + name, + }, + }) + .command(({ tr, state }) => { + tr.setStoredMarks(state.doc.resolve(state.selection.to - 1).marks()); + return true; + }) + .run(); + }, + }) + ); + + if (this.options.enableEmoticons) { + // get the list of supported emoticons + const emoticons = this.options.emojis + .map((item) => item.emoticons) + .flat() + .filter((item) => item) as string[]; + + const emoticonRegex = new RegExp(`(?:^|\\s)(${emoticons.map((item) => escapeForRegEx(item)).join("|")}) $`); + + inputRules.push( + nodeInputRule({ + find: emoticonRegex, + type: this.type, + getAttributes: (match) => { + const emoji = this.options.emojis.find((item) => item.emoticons?.includes(match[1])); + + if (!emoji) { + return; + } + + return { + name: emoji.name, + }; + }, + }) + ); + } + + return inputRules; + }, + + addPasteRules() { + return [ + new PasteRule({ + find: pasteRegex, + handler: ({ range, match, chain }) => { + const name = match[1]; + + if (!shortcodeToEmoji(name, this.options.emojis)) { + return; + } + + chain() + .insertContentAt( + range, + { + type: this.name, + attrs: { + name, + }, + }, + { + updateSelection: false, + } + ) + .command(({ tr, state }) => { + tr.setStoredMarks(state.doc.resolve(state.selection.to - 1).marks()); + return true; + }) + .run(); + }, + }), + ]; + }, + + addProseMirrorPlugins() { + return [ + Suggestion({ + editor: this.editor, + findSuggestionMatch: customFindSuggestionMatch, + ...this.options.suggestion, + }), + + new Plugin({ + key: new PluginKey("emoji"), + props: { + // double click to select emoji doesn’t work by default + // that’s why we simulate this behavior + handleDoubleClickOn: (view, pos, node) => { + if (node.type !== this.type) { + return false; + } + + const from = pos; + const to = from + node.nodeSize; + + this.editor.commands.setTextSelection({ + from, + to, + }); + + return true; + }, + }, + + // replace text emojis with emoji node on any change + appendTransaction: (transactions, oldState, newState) => { + const docChanges = + transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc); + + if (!docChanges) { + return; + } + + const { tr } = newState; + const transform = combineTransactionSteps(oldState.doc, transactions as Transaction[]); + const changes = getChangedRanges(transform); + + changes.forEach(({ newRange }) => { + // We don’t want to add emoji inline nodes within code blocks. + // Because this would split the code block. + + // This only works if the range of changes is within a code node. + // For all other cases (e.g. the whole document is set/pasted and the parent of the range is `doc`) + // it doesn't and we have to double check later. + if (newState.doc.resolve(newRange.from).parent.type.spec.code) { + return; + } + + const textNodes = findChildrenInRange(newState.doc, newRange, (node) => node.type.isText); + + textNodes.forEach(({ node, pos }) => { + if (!node.text) { + return; + } + + const matches = [...node.text.matchAll(emojiRegex())]; + + matches.forEach((match) => { + if (match.index === undefined) { + return; + } + + const emoji = match[0]; + const name = emojiToShortcode(emoji, this.options.emojis); + + if (!name) { + return; + } + + const from = tr.mapping.map(pos + match.index); + + // Double check parent node is not a code block. + if (newState.doc.resolve(from).parent.type.spec.code) { + return; + } + + const to = from + emoji.length; + const emojiNode = this.type.create({ + name, + }); + + tr.replaceRangeWith(from, to, emojiNode); + + tr.setStoredMarks(newState.doc.resolve(from).marks()); + }); + }); + }); + + if (!tr.steps.length) { + return; + } + + return tr; + }, + }), + ]; + }, +}); diff --git a/packages/editor/src/core/extensions/emoji/extension.ts b/packages/editor/src/core/extensions/emoji/extension.ts new file mode 100644 index 000000000..7e35038cc --- /dev/null +++ b/packages/editor/src/core/extensions/emoji/extension.ts @@ -0,0 +1,30 @@ +// local imports +import { gitHubEmojis, shortcodeToEmoji } from "@tiptap/extension-emoji"; +import { MarkdownSerializerState } from "@tiptap/pm/markdown"; +import { Node as ProseMirrorNode } from "@tiptap/pm/model"; +import { Emoji } from "./emoji"; +import suggestion from "./suggestion"; + +export const EmojiExtension = Emoji.extend({ + addStorage() { + return { + ...this.parent?.(), + markdown: { + serialize(state: MarkdownSerializerState, node: ProseMirrorNode) { + const emojiItem = shortcodeToEmoji(node.attrs.name, this.options.emojis); + if (emojiItem?.emoji) { + state.write(emojiItem?.emoji); + } else if (emojiItem?.fallbackImage) { + state.write(`\n![${emojiItem.name}-${emojiItem.shortcodes[0]}](${emojiItem?.fallbackImage})\n`); + } else { + state.write(`:${node.attrs.name}:`); + } + }, + }, + }; + }, +}).configure({ + emojis: gitHubEmojis, + suggestion: suggestion, + enableEmoticons: true, +}); diff --git a/packages/editor/src/core/extensions/emoji/suggestion.ts b/packages/editor/src/core/extensions/emoji/suggestion.ts new file mode 100644 index 000000000..a0aa91688 --- /dev/null +++ b/packages/editor/src/core/extensions/emoji/suggestion.ts @@ -0,0 +1,120 @@ +import type { EmojiOptions } from "@tiptap/extension-emoji"; +import { ReactRenderer, Editor } from "@tiptap/react"; +import { SuggestionProps, SuggestionKeyDownProps } from "@tiptap/suggestion"; +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +// helpers +import { getExtensionStorage } from "@/helpers/get-extension-storage"; +// local imports +import { EmojiItem, EmojiList, EmojiListRef } from "./components/emojis-list"; + +const DEFAULT_EMOJIS = ["+1", "-1", "smile", "orange_heart", "eyes"]; + +const emojiSuggestion: EmojiOptions["suggestion"] = { + items: ({ editor, query }: { editor: Editor; query: string }): EmojiItem[] => { + const { emojis } = getExtensionStorage(editor, CORE_EXTENSIONS.EMOJI); + const { isSupported } = getExtensionStorage(editor, CORE_EXTENSIONS.EMOJI); + const filteredEmojis = emojis.filter((emoji) => { + const hasEmoji = !!emoji?.emoji; + const hasFallbackImage = !!emoji?.fallbackImage; + const renderFallbackImage = + (emoji.forceFallbackImages && !hasEmoji) || + (emoji.forceFallbackImages && hasFallbackImage) || + (emoji.forceFallbackImages && !isSupported(emoji) && hasFallbackImage) || + ((!isSupported(emoji) || !hasEmoji) && hasFallbackImage); + return !renderFallbackImage; + }); + + if (query.trim() === "") { + const defaultEmojis = DEFAULT_EMOJIS.map((name) => + filteredEmojis.find((emoji: EmojiItem) => emoji.shortcodes.includes(name) || emoji.name === name) + ) + .filter(Boolean) + .slice(0, 5); + return defaultEmojis as EmojiItem[]; + } + return filteredEmojis + .filter(({ shortcodes, tags }) => { + const lowerQuery = query.toLowerCase(); + return ( + shortcodes.find((shortcode: string) => shortcode.startsWith(lowerQuery)) || + tags.find((tag: string) => tag.startsWith(lowerQuery)) + ); + }) + .slice(0, 5) as EmojiItem[]; + }, + + allowSpaces: false, + + render: () => { + let component: ReactRenderer; + let editor: Editor; + + return { + onStart: (props: SuggestionProps): void => { + if (!props.clientRect) return; + + editor = props.editor; + + // Track active dropdown + getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY).activeDropbarExtensions.push(CORE_EXTENSIONS.EMOJI); + + component = new ReactRenderer(EmojiList, { + props: { + items: props.items, + command: props.command, + editor: props.editor, + query: props.query, + }, + editor: props.editor, + }); + + // Append to editor container + const targetElement = + (props.editor.options.element as HTMLElement) || props.editor.view.dom.parentElement || document.body; + targetElement.appendChild(component.element); + }, + + onUpdate: (props: SuggestionProps): void => { + if (!component) return; + + component.updateProps({ + items: props.items, + command: props.command, + editor: props.editor, + query: props.query, + }); + }, + + onKeyDown: (props: SuggestionKeyDownProps): boolean => { + if (props.event.key === "Escape") { + if (component) { + component.destroy(); + } + return true; + } + + // Delegate to EmojiList + return component?.ref?.onKeyDown(props) || false; + }, + + onExit: (): void => { + // Remove from active dropdowns + if (editor) { + const utilityStorage = getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY); + const index = utilityStorage.activeDropbarExtensions.indexOf(CORE_EXTENSIONS.EMOJI); + if (index > -1) { + utilityStorage.activeDropbarExtensions.splice(index, 1); + } + } + + // Cleanup + if (component) { + component.destroy(); + } + }, + }; + }, +}; + +export default emojiSuggestion; diff --git a/packages/editor/src/core/extensions/enter-key.ts b/packages/editor/src/core/extensions/enter-key.ts index 65119425f..e36adde3c 100644 --- a/packages/editor/src/core/extensions/enter-key.ts +++ b/packages/editor/src/core/extensions/enter-key.ts @@ -11,11 +11,13 @@ export const EnterKeyExtension = (onEnterKeyPress?: () => void) => addKeyboardShortcuts(this) { return { Enter: () => { - const isMentionOpen = getExtensionStorage(this.editor, CORE_EXTENSIONS.MENTION)?.mentionsOpen; - if (!isMentionOpen) { + const { activeDropbarExtensions } = getExtensionStorage(this.editor, CORE_EXTENSIONS.UTILITY); + + if (activeDropbarExtensions.length === 0) { onEnterKeyPress?.(); return true; } + return false; }, "Shift-Enter": ({ editor }) => diff --git a/packages/editor/src/core/extensions/extensions.ts b/packages/editor/src/core/extensions/extensions.ts index cc8882005..bcf8fbbe8 100644 --- a/packages/editor/src/core/extensions/extensions.ts +++ b/packages/editor/src/core/extensions/extensions.ts @@ -1,14 +1,10 @@ import { Extensions } from "@tiptap/core"; import CharacterCount from "@tiptap/extension-character-count"; -import Placeholder from "@tiptap/extension-placeholder"; import TaskItem from "@tiptap/extension-task-item"; import TaskList from "@tiptap/extension-task-list"; import TextStyle from "@tiptap/extension-text-style"; import TiptapUnderline from "@tiptap/extension-underline"; -import StarterKit from "@tiptap/starter-kit"; import { Markdown } from "tiptap-markdown"; -// constants -import { CORE_EXTENSIONS } from "@/constants/extension"; // extensions import { CustomCalloutExtension, @@ -30,15 +26,15 @@ import { TableRow, UtilityExtension, } from "@/extensions"; -// helpers -import { isValidHttpUrl } from "@/helpers/common"; -import { getExtensionStorage } from "@/helpers/get-extension-storage"; // plane editor extensions import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions"; // types import type { IEditorProps } from "@/types"; // local imports import { CustomImageExtension } from "./custom-image/extension"; +import { EmojiExtension } from "./emoji/extension"; +import { CustomPlaceholderExtension } from "./placeholder"; +import { CustomStarterKitExtension } from "./starter-kit"; type TArguments = Pick< IEditorProps, @@ -61,61 +57,15 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { } = args; const extensions = [ - StarterKit.configure({ - bulletList: { - HTMLAttributes: { - class: "list-disc pl-7 space-y-[--list-spacing-y]", - }, - }, - orderedList: { - HTMLAttributes: { - class: "list-decimal pl-7 space-y-[--list-spacing-y]", - }, - }, - listItem: { - HTMLAttributes: { - class: "not-prose space-y-2", - }, - }, - code: false, - codeBlock: false, - horizontalRule: false, - blockquote: false, - paragraph: { - HTMLAttributes: { - class: "editor-paragraph-block", - }, - }, - heading: { - HTMLAttributes: { - class: "editor-heading-block", - }, - }, - dropcursor: { - class: - "text-custom-text-300 transition-all motion-reduce:transition-none motion-reduce:hover:transform-none duration-200 ease-[cubic-bezier(0.165, 0.84, 0.44, 1)]", - }, - ...(enableHistory ? {} : { history: false }), + CustomStarterKitExtension({ + enableHistory, }), + EmojiExtension, CustomQuoteExtension, - CustomHorizontalRule.configure({ - HTMLAttributes: { - class: "py-4 border-custom-border-400", - }, - }), + CustomHorizontalRule, CustomKeymap, ListKeymap({ tabIndex }), - CustomLinkExtension.configure({ - openOnClick: true, - autolink: true, - linkOnPaste: true, - protocols: ["http", "https"], - validate: (url: string) => isValidHttpUrl(url).isValid, - HTMLAttributes: { - class: - "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", - }, - }), + CustomLinkExtension, CustomTypographyExtension, TiptapUnderline, TextStyle, @@ -130,11 +80,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { }, nested: true, }), - CustomCodeBlockExtension.configure({ - HTMLAttributes: { - class: "", - }, - }), + CustomCodeBlockExtension, CustomCodeInlineExtension, Markdown.configure({ html: true, @@ -147,34 +93,9 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { TableCell, TableRow, CustomMentionExtension(mentionHandler), - Placeholder.configure({ - placeholder: ({ editor, node }) => { - if (!editor.isEditable) return ""; - - if (node.type.name === CORE_EXTENSIONS.HEADING) return `Heading ${node.attrs.level}`; - - const isUploadInProgress = getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY)?.uploadInProgress; - - if (isUploadInProgress) return ""; - - const shouldHidePlaceholder = - editor.isActive(CORE_EXTENSIONS.TABLE) || - editor.isActive(CORE_EXTENSIONS.CODE_BLOCK) || - editor.isActive(CORE_EXTENSIONS.IMAGE) || - editor.isActive(CORE_EXTENSIONS.CUSTOM_IMAGE); - - if (shouldHidePlaceholder) return ""; - - if (placeholder) { - if (typeof placeholder === "string") return placeholder; - else return placeholder(editor.isFocused, editor.getHTML()); - } - - return "Press '/' for commands..."; - }, - includeChildren: true, - }), + CustomPlaceholderExtension({ placeholder }), CharacterCount, + CustomColorExtension, CustomTextAlignExtension, CustomCalloutExtension, UtilityExtension({ @@ -182,7 +103,6 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { fileHandler, isEditable: editable, }), - CustomColorExtension, ...CoreEditorAdditionalExtensions({ disabledExtensions, flaggedExtensions, @@ -202,6 +122,5 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { ); } - // @ts-expect-error tiptap types are incorrect return extensions; }; diff --git a/packages/editor/src/core/extensions/horizontal-rule.ts b/packages/editor/src/core/extensions/horizontal-rule.ts index 99a5dacc3..4ffbcbb00 100644 --- a/packages/editor/src/core/extensions/horizontal-rule.ts +++ b/packages/editor/src/core/extensions/horizontal-rule.ts @@ -20,15 +20,16 @@ declare module "@tiptap/core" { export const CustomHorizontalRule = Node.create({ name: CORE_EXTENSIONS.HORIZONTAL_RULE, + group: "block", addOptions() { return { - HTMLAttributes: {}, + HTMLAttributes: { + class: "py-4 border-custom-border-400", + }, }; }, - group: "block", - parseHTML() { return [ { diff --git a/packages/editor/src/core/extensions/image/extension-config.tsx b/packages/editor/src/core/extensions/image/extension-config.tsx index 6dbad2d24..7456e3dfb 100644 --- a/packages/editor/src/core/extensions/image/extension-config.tsx +++ b/packages/editor/src/core/extensions/image/extension-config.tsx @@ -19,6 +19,9 @@ export const ImageExtensionConfig = BaseImageExtension.extend< aspectRatio: { default: null, }, + alignment: { + default: "left", + }, }; }, }); diff --git a/packages/editor/src/core/extensions/image/extension.tsx b/packages/editor/src/core/extensions/image/extension.tsx index 80cf7c182..3cee3b10f 100644 --- a/packages/editor/src/core/extensions/image/extension.tsx +++ b/packages/editor/src/core/extensions/image/extension.tsx @@ -4,7 +4,7 @@ import { insertEmptyParagraphAtNodeBoundaries } from "@/helpers/insert-empty-par // types import type { TFileHandler, TReadOnlyFileHandler } from "@/types"; // local imports -import { CustomImageNodeView } from "../custom-image/components/node-view"; +import { CustomImageNodeView, CustomImageNodeViewProps } from "../custom-image/components/node-view"; import { ImageExtensionConfig } from "./extension-config"; export type ImageExtensionStorage = { @@ -47,7 +47,9 @@ export const ImageExtension = (props: Props) => { // render custom image node addNodeView() { - return ReactNodeViewRenderer(CustomImageNodeView); + return ReactNodeViewRenderer((props) => ( + + )); }, }); }; diff --git a/packages/editor/src/core/extensions/keymap.ts b/packages/editor/src/core/extensions/keymap.ts index a4961bb96..a95344691 100644 --- a/packages/editor/src/core/extensions/keymap.ts +++ b/packages/editor/src/core/extensions/keymap.ts @@ -117,11 +117,15 @@ export const CustomKeymap = Extension.create({ const endNodePos = tr.selection.$to.end(); const isCurrentTextSelectionNotExtendedToNodeBoundaries = startSelectionPos > startNodePos || endSelectionPos < endNodePos; + if (isCurrentTextSelectionNotExtendedToNodeBoundaries) { + // First press: select text within node boundaries editor.chain().selectTextWithinNodeBoundaries().run(); return true; + } else { + editor.commands.selectAll(); + return true; } - return false; }, }; }, diff --git a/packages/editor/src/core/extensions/mentions/extension-config.ts b/packages/editor/src/core/extensions/mentions/extension-config.ts index e75fc9156..e7b6dbe2a 100644 --- a/packages/editor/src/core/extensions/mentions/extension-config.ts +++ b/packages/editor/src/core/extensions/mentions/extension-config.ts @@ -12,11 +12,7 @@ export type TMentionExtensionOptions = MentionOptions & { getMentionedEntityDetails: TMentionHandler["getMentionedEntityDetails"]; }; -export type MentionExtensionStorage = { - mentionsOpen: boolean; -}; - -export const CustomMentionExtensionConfig = Mention.extend({ +export const CustomMentionExtensionConfig = Mention.extend({ addAttributes() { return { [EMentionComponentAttributeNames.ID]: { @@ -54,7 +50,6 @@ export const CustomMentionExtensionConfig = Mention.extend { }, addNodeView() { - return ReactNodeViewRenderer(MentionNodeView); + return ReactNodeViewRenderer((props) => ( + + )); }, }).configure({ suggestion: { diff --git a/packages/editor/src/core/extensions/mentions/mention-node-view.tsx b/packages/editor/src/core/extensions/mentions/mention-node-view.tsx index aac00de88..939093fa3 100644 --- a/packages/editor/src/core/extensions/mentions/mention-node-view.tsx +++ b/packages/editor/src/core/extensions/mentions/mention-node-view.tsx @@ -4,17 +4,18 @@ import { TMentionExtensionOptions } from "./extension-config"; // extension types import { EMentionComponentAttributeNames, TMentionComponentAttributes } from "./types"; -type Props = NodeViewProps & { +export type MentionNodeViewProps = NodeViewProps & { node: NodeViewProps["node"] & { attrs: TMentionComponentAttributes; }; }; -export const MentionNodeView = (props: Props) => { +export const MentionNodeView: React.FC = (props) => { const { extension, node: { attrs }, } = props; + return ( {(extension.options as TMentionExtensionOptions).renderComponent({ diff --git a/packages/editor/src/core/extensions/mentions/utils.ts b/packages/editor/src/core/extensions/mentions/utils.ts index 5a7550c83..5fa356059 100644 --- a/packages/editor/src/core/extensions/mentions/utils.ts +++ b/packages/editor/src/core/extensions/mentions/utils.ts @@ -8,6 +8,8 @@ import { CommandListInstance } from "@/helpers/tippy"; import { TMentionHandler } from "@/types"; // local components import { MentionsListDropdown, MentionsListDropdownProps } from "./mentions-list-dropdown"; +import { getExtensionStorage } from "@/helpers/get-extension-storage"; +import { CORE_EXTENSIONS } from "@/constants/extension"; export const renderMentionsDropdown = (props: Pick): SuggestionOptions["render"] => @@ -28,7 +30,9 @@ export const renderMentionsDropdown = }, editor: props.editor, }); - props.editor.storage.mentionsOpen = true; + getExtensionStorage(props.editor, CORE_EXTENSIONS.UTILITY).activeDropbarExtensions.push( + CORE_EXTENSIONS.MENTION + ); // @ts-expect-error - Tippy types are incorrect popup = tippy("body", { getReferenceClientRect: props.clientRect, @@ -64,7 +68,11 @@ export const renderMentionsDropdown = return false; }, onExit: (props: { editor: Editor; event: KeyboardEvent }) => { - props.editor.storage.mentionsOpen = false; + const utilityStorage = getExtensionStorage(props.editor, CORE_EXTENSIONS.UTILITY); + const index = utilityStorage.activeDropbarExtensions.indexOf(CORE_EXTENSIONS.MENTION); + if (index > -1) { + utilityStorage.activeDropbarExtensions.splice(index, 1); + } popup?.[0]?.destroy(); component?.destroy(); }, diff --git a/packages/editor/src/core/extensions/placeholder.ts b/packages/editor/src/core/extensions/placeholder.ts new file mode 100644 index 000000000..9e23792a2 --- /dev/null +++ b/packages/editor/src/core/extensions/placeholder.ts @@ -0,0 +1,43 @@ +import Placeholder from "@tiptap/extension-placeholder"; +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +// helpers +import { getExtensionStorage } from "@/helpers/get-extension-storage"; +// types +import type { IEditorProps } from "@/types"; + +type TArgs = { + placeholder: IEditorProps["placeholder"]; +}; + +export const CustomPlaceholderExtension = (args: TArgs) => { + const { placeholder } = args; + + return Placeholder.configure({ + placeholder: ({ editor, node }) => { + if (!editor.isEditable) return ""; + + if (node.type.name === CORE_EXTENSIONS.HEADING) return `Heading ${node.attrs.level}`; + + const isUploadInProgress = getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY)?.uploadInProgress; + + if (isUploadInProgress) return ""; + + const shouldHidePlaceholder = + editor.isActive(CORE_EXTENSIONS.TABLE) || + editor.isActive(CORE_EXTENSIONS.CODE_BLOCK) || + editor.isActive(CORE_EXTENSIONS.IMAGE) || + editor.isActive(CORE_EXTENSIONS.CUSTOM_IMAGE); + + if (shouldHidePlaceholder) return ""; + + if (placeholder) { + if (typeof placeholder === "string") return placeholder; + else return placeholder(editor.isFocused, editor.getHTML()); + } + + return "Press '/' for commands..."; + }, + includeChildren: true, + }); +}; diff --git a/packages/editor/src/core/extensions/read-only-extensions.ts b/packages/editor/src/core/extensions/read-only-extensions.ts index c99b02312..3099fa885 100644 --- a/packages/editor/src/core/extensions/read-only-extensions.ts +++ b/packages/editor/src/core/extensions/read-only-extensions.ts @@ -4,7 +4,6 @@ import TaskItem from "@tiptap/extension-task-item"; import TaskList from "@tiptap/extension-task-list"; import TextStyle from "@tiptap/extension-text-style"; import TiptapUnderline from "@tiptap/extension-underline"; -import StarterKit from "@tiptap/starter-kit"; import { Markdown } from "tiptap-markdown"; // extensions import { @@ -25,14 +24,14 @@ import { UtilityExtension, ImageExtension, } from "@/extensions"; -// helpers -import { isValidHttpUrl } from "@/helpers/common"; // plane editor extensions import { CoreReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extensions"; // types import type { IReadOnlyEditorProps } from "@/types"; // local imports import { CustomImageExtension } from "./custom-image/extension"; +import { EmojiExtension } from "./emoji/extension"; +import { CustomStarterKitExtension } from "./starter-kit"; type Props = Pick; @@ -40,56 +39,13 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler } = props; const extensions = [ - StarterKit.configure({ - bulletList: { - HTMLAttributes: { - class: "list-disc pl-7 space-y-[--list-spacing-y]", - }, - }, - orderedList: { - HTMLAttributes: { - class: "list-decimal pl-7 space-y-[--list-spacing-y]", - }, - }, - listItem: { - HTMLAttributes: { - class: "not-prose space-y-2", - }, - }, - code: false, - codeBlock: false, - horizontalRule: false, - blockquote: false, - paragraph: { - HTMLAttributes: { - class: "editor-paragraph-block", - }, - }, - heading: { - HTMLAttributes: { - class: "editor-heading-block", - }, - }, - dropcursor: false, - gapcursor: false, + CustomStarterKitExtension({ + enableHistory: false, }), + EmojiExtension, CustomQuoteExtension, - CustomHorizontalRule.configure({ - HTMLAttributes: { - class: "py-4 border-custom-border-400", - }, - }), - CustomLinkExtension.configure({ - openOnClick: true, - autolink: true, - linkOnPaste: true, - protocols: ["http", "https"], - validate: (url: string) => isValidHttpUrl(url).isValid, - HTMLAttributes: { - class: - "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", - }, - }), + CustomHorizontalRule, + CustomLinkExtension, CustomTypographyExtension, TiptapUnderline, TextStyle, @@ -104,11 +60,7 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { }, nested: true, }), - CustomCodeBlockExtension.configure({ - HTMLAttributes: { - class: "", - }, - }), + CustomCodeBlockExtension, CustomCodeInlineExtension, Markdown.configure({ html: true, @@ -146,6 +98,5 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { ); } - // @ts-expect-error tiptap types are incorrect return extensions; }; diff --git a/packages/editor/src/core/extensions/side-menu.ts b/packages/editor/src/core/extensions/side-menu.ts index 34e3c45e5..ca139f723 100644 --- a/packages/editor/src/core/extensions/side-menu.ts +++ b/packages/editor/src/core/extensions/side-menu.ts @@ -131,7 +131,7 @@ const SideMenu = (options: SideMenuPluginProps) => { } } - if (node.matches(".table-wrapper")) { + if (node.matches("table")) { rect.top += 8; rect.left -= 8; } diff --git a/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx b/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx index d3ca4856e..54d717de3 100644 --- a/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx +++ b/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx @@ -14,6 +14,7 @@ import { ListTodo, MessageSquareText, MinusSquare, + Smile, Table, TextQuote, } from "lucide-react"; @@ -189,6 +190,17 @@ export const getSlashCommandFilteredSections = icon: , command: ({ editor, range }) => editor.chain().focus().deleteRange(range).setHorizontalRule().run(), }, + { + commandKey: "emoji", + key: "emoji", + title: "Emoji", + description: "Insert an emoji", + searchTerms: ["emoji", "icons", "reaction", "emoticon", "emotags"], + icon: , + command: ({ editor, range }) => { + editor.chain().focus().insertContentAt(range, "

    :

    ").run(); + }, + }, ], }, { diff --git a/packages/editor/src/core/extensions/slash-commands/root.tsx b/packages/editor/src/core/extensions/slash-commands/root.tsx index 3a29e932c..43d7cf612 100644 --- a/packages/editor/src/core/extensions/slash-commands/root.tsx +++ b/packages/editor/src/core/extensions/slash-commands/root.tsx @@ -40,10 +40,6 @@ const Command = Extension.create({ return false; } - if (editor.isActive(CORE_EXTENSIONS.TABLE)) { - return false; - } - return true; }, }, diff --git a/packages/editor/src/core/extensions/starter-kit.ts b/packages/editor/src/core/extensions/starter-kit.ts new file mode 100644 index 000000000..e6a4c968d --- /dev/null +++ b/packages/editor/src/core/extensions/starter-kit.ts @@ -0,0 +1,46 @@ +import StarterKit from "@tiptap/starter-kit"; + +type TArgs = { + enableHistory: boolean; +}; + +export const CustomStarterKitExtension = (args: TArgs) => { + const { enableHistory } = args; + + return StarterKit.configure({ + bulletList: { + HTMLAttributes: { + class: "list-disc pl-7 space-y-[--list-spacing-y]", + }, + }, + orderedList: { + HTMLAttributes: { + class: "list-decimal pl-7 space-y-[--list-spacing-y]", + }, + }, + listItem: { + HTMLAttributes: { + class: "not-prose space-y-2", + }, + }, + code: false, + codeBlock: false, + horizontalRule: false, + blockquote: false, + paragraph: { + HTMLAttributes: { + class: "editor-paragraph-block", + }, + }, + heading: { + HTMLAttributes: { + class: "editor-heading-block", + }, + }, + dropcursor: { + class: + "text-custom-text-300 transition-all motion-reduce:transition-none motion-reduce:hover:transform-none duration-200 ease-[cubic-bezier(0.165, 0.84, 0.44, 1)]", + }, + ...(enableHistory ? {} : { history: false }), + }); +}; diff --git a/packages/editor/src/core/extensions/table/plugins/insert-handlers/plugin.ts b/packages/editor/src/core/extensions/table/plugins/insert-handlers/plugin.ts new file mode 100644 index 000000000..97cd2d09f --- /dev/null +++ b/packages/editor/src/core/extensions/table/plugins/insert-handlers/plugin.ts @@ -0,0 +1,87 @@ +import { type Editor } from "@tiptap/core"; +import { Plugin, PluginKey } from "@tiptap/pm/state"; +// local imports +import { createColumnInsertButton, createRowInsertButton, findAllTables, TableInfo } from "./utils"; + +const TABLE_INSERT_PLUGIN_KEY = new PluginKey("table-insert"); + +export const TableInsertPlugin = (editor: Editor): Plugin => { + const tableMap = new Map(); + + const setupTable = (tableInfo: TableInfo) => { + const { tableElement } = tableInfo; + + // Create and add column button if it doesn't exist + if (!tableInfo.columnButtonElement) { + const columnButton = createColumnInsertButton(editor, tableInfo); + tableElement.appendChild(columnButton); + tableInfo.columnButtonElement = columnButton; + } + + // Create and add row button if it doesn't exist + if (!tableInfo.rowButtonElement) { + const rowButton = createRowInsertButton(editor, tableInfo); + tableElement.appendChild(rowButton); + tableInfo.rowButtonElement = rowButton; + } + + tableMap.set(tableElement, tableInfo); + }; + + const cleanupTable = (tableElement: HTMLElement) => { + const tableInfo = tableMap.get(tableElement); + tableInfo?.columnButtonElement?.remove(); + tableInfo?.rowButtonElement?.remove(); + tableMap.delete(tableElement); + }; + + const updateAllTables = () => { + if (!editor.isEditable) { + // Clean up all tables if editor is not editable + tableMap.forEach((_, tableElement) => { + cleanupTable(tableElement); + }); + return; + } + + const currentTables = findAllTables(editor); + const currentTableElements = new Set(currentTables.map((t) => t.tableElement)); + + // Remove buttons from tables that no longer exist + tableMap.forEach((_, tableElement) => { + if (!currentTableElements.has(tableElement)) { + cleanupTable(tableElement); + } + }); + + // Add buttons to new tables + currentTables.forEach((tableInfo) => { + if (!tableMap.has(tableInfo.tableElement)) { + setupTable(tableInfo); + } + }); + }; + + return new Plugin({ + key: TABLE_INSERT_PLUGIN_KEY, + view() { + setTimeout(updateAllTables, 0); + + return { + update(view, prevState) { + // Update when document changes + if (!prevState.doc.eq(view.state.doc)) { + updateAllTables(); + } + }, + destroy() { + // Clean up all tables + tableMap.forEach((_, tableElement) => { + cleanupTable(tableElement); + }); + tableMap.clear(); + }, + }; + }, + }); +}; diff --git a/packages/editor/src/core/extensions/table/plugins/insert-handlers/utils.ts b/packages/editor/src/core/extensions/table/plugins/insert-handlers/utils.ts new file mode 100644 index 000000000..c8dc5f479 --- /dev/null +++ b/packages/editor/src/core/extensions/table/plugins/insert-handlers/utils.ts @@ -0,0 +1,411 @@ +import type { Editor } from "@tiptap/core"; +import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; +import { addColumn, removeColumn, addRow, removeRow, TableMap } from "@tiptap/pm/tables"; +// local imports +import { isCellEmpty } from "../../table/utilities/helpers"; + +const addSvg = ` + +`; + +export type TableInfo = { + tableElement: HTMLElement; + tableNode: ProseMirrorNode; + tablePos: number; + columnButtonElement?: HTMLElement; + rowButtonElement?: HTMLElement; +}; + +export const createColumnInsertButton = (editor: Editor, tableInfo: TableInfo): HTMLElement => { + const button = document.createElement("button"); + button.type = "button"; + button.className = "table-column-insert-button"; + button.title = "Insert columns"; + button.ariaLabel = "Insert columns"; + + const icon = document.createElement("span"); + icon.innerHTML = addSvg; + button.appendChild(icon); + + let mouseDownX = 0; + let isDragging = false; + let dragStarted = false; + let lastActionX = 0; + const DRAG_THRESHOLD = 5; // pixels to start drag + const ACTION_THRESHOLD = 150; // pixels total distance to trigger action + + const onMouseDown = (e: MouseEvent) => { + if (e.button !== 0) return; // Only left mouse button + + e.preventDefault(); + e.stopPropagation(); + + mouseDownX = e.clientX; + lastActionX = e.clientX; + isDragging = false; + dragStarted = false; + + document.addEventListener("mousemove", onMouseMove); + document.addEventListener("mouseup", onMouseUp); + }; + + const onMouseMove = (e: MouseEvent) => { + const deltaX = e.clientX - mouseDownX; + const distance = Math.abs(deltaX); + + // Start dragging if moved more than threshold + if (!isDragging && distance > DRAG_THRESHOLD) { + isDragging = true; + dragStarted = true; + + // Visual feedback + button.classList.add("dragging"); + document.body.style.userSelect = "none"; + } + + if (isDragging) { + const totalDistance = Math.abs(e.clientX - lastActionX); + + // Only trigger action when total distance reaches threshold + if (totalDistance >= ACTION_THRESHOLD) { + // Determine direction based on current movement relative to last action point + const directionFromLastAction = e.clientX - lastActionX; + + // Right direction - add columns + if (directionFromLastAction > 0) { + insertColumnAfterLast(editor, tableInfo); + lastActionX = e.clientX; // Reset action point + } + // Left direction - delete empty columns + else if (directionFromLastAction < 0) { + const deleted = removeLastColumn(editor, tableInfo); + if (deleted) { + lastActionX = e.clientX; // Reset action point + } + } + } + } + }; + + const onMouseUp = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + + if (isDragging) { + // Clean up drag state + button.classList.remove("dragging"); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + } else if (!dragStarted) { + // Handle as click if no dragging occurred + insertColumnAfterLast(editor, tableInfo); + } + + isDragging = false; + dragStarted = false; + }; + + button.addEventListener("mousedown", onMouseDown); + + // Prevent context menu and text selection + button.addEventListener("contextmenu", (e) => e.preventDefault()); + button.addEventListener("selectstart", (e) => e.preventDefault()); + + return button; +}; + +export const createRowInsertButton = (editor: Editor, tableInfo: TableInfo): HTMLElement => { + const button = document.createElement("button"); + button.type = "button"; + button.className = "table-row-insert-button"; + button.title = "Insert rows"; + button.ariaLabel = "Insert rows"; + + const icon = document.createElement("span"); + icon.innerHTML = addSvg; + button.appendChild(icon); + + let mouseDownY = 0; + let isDragging = false; + let dragStarted = false; + let lastActionY = 0; + const DRAG_THRESHOLD = 5; // pixels to start drag + const ACTION_THRESHOLD = 40; // pixels total distance to trigger action + + const onMouseDown = (e: MouseEvent) => { + if (e.button !== 0) return; // Only left mouse button + + e.preventDefault(); + e.stopPropagation(); + + mouseDownY = e.clientY; + lastActionY = e.clientY; + isDragging = false; + dragStarted = false; + + document.addEventListener("mousemove", onMouseMove); + document.addEventListener("mouseup", onMouseUp); + }; + + const onMouseMove = (e: MouseEvent) => { + const deltaY = e.clientY - mouseDownY; + const distance = Math.abs(deltaY); + + // Start dragging if moved more than threshold + if (!isDragging && distance > DRAG_THRESHOLD) { + isDragging = true; + dragStarted = true; + + // Visual feedback + button.classList.add("dragging"); + document.body.style.userSelect = "none"; + } + + if (isDragging) { + const totalDistance = Math.abs(e.clientY - lastActionY); + + // Only trigger action when total distance reaches threshold + if (totalDistance >= ACTION_THRESHOLD) { + // Determine direction based on current movement relative to last action point + const directionFromLastAction = e.clientY - lastActionY; + + // Down direction - add rows + if (directionFromLastAction > 0) { + insertRowAfterLast(editor, tableInfo); + lastActionY = e.clientY; // Reset action point + } + // Up direction - delete empty rows + else if (directionFromLastAction < 0) { + const deleted = removeLastRow(editor, tableInfo); + if (deleted) { + lastActionY = e.clientY; // Reset action point + } + } + } + } + }; + + const onMouseUp = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + + if (isDragging) { + // Clean up drag state + button.classList.remove("dragging"); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + } else if (!dragStarted) { + // Handle as click if no dragging occurred + insertRowAfterLast(editor, tableInfo); + } + + isDragging = false; + dragStarted = false; + }; + + button.addEventListener("mousedown", onMouseDown); + + // Prevent context menu and text selection + button.addEventListener("contextmenu", (e) => e.preventDefault()); + button.addEventListener("selectstart", (e) => e.preventDefault()); + + return button; +}; + +export const findAllTables = (editor: Editor): TableInfo[] => { + const tables: TableInfo[] = []; + const tableElements = editor.view.dom.querySelectorAll("table"); + + tableElements.forEach((tableElement) => { + // Find the table's ProseMirror position + let tablePos = -1; + let tableNode: ProseMirrorNode | null = null; + + // Walk through the document to find matching table nodes + editor.state.doc.descendants((node, pos) => { + if (node.type.spec.tableRole === "table") { + const domAtPos = editor.view.domAtPos(pos + 1); + let domTable = domAtPos.node; + + // Navigate to find the table element + while (domTable && domTable.parentNode && domTable.nodeType !== Node.ELEMENT_NODE) { + domTable = domTable.parentNode; + } + + while (domTable && domTable.parentNode && (domTable as HTMLElement).tagName !== "TABLE") { + domTable = domTable.parentNode; + } + + if (domTable === tableElement) { + tablePos = pos; + tableNode = node; + return false; // Stop iteration + } + } + }); + + if (tablePos !== -1 && tableNode) { + tables.push({ + tableElement, + tableNode, + tablePos, + }); + } + }); + + return tables; +}; + +const getCurrentTableInfo = (editor: Editor, tableInfo: TableInfo): TableInfo => { + // Refresh table info to get latest state + const tables = findAllTables(editor); + const updated = tables.find((t) => t.tableElement === tableInfo.tableElement); + return updated || tableInfo; +}; + +// Column functions +const insertColumnAfterLast = (editor: Editor, tableInfo: TableInfo) => { + const currentTableInfo = getCurrentTableInfo(editor, tableInfo); + const { tableNode, tablePos } = currentTableInfo; + const tableMapData = TableMap.get(tableNode); + const lastColumnIndex = tableMapData.width; + + const tr = editor.state.tr; + const rect = { + map: tableMapData, + tableStart: tablePos, + table: tableNode, + top: 0, + left: 0, + bottom: tableMapData.height - 1, + right: tableMapData.width - 1, + }; + + const newTr = addColumn(tr, rect, lastColumnIndex); + editor.view.dispatch(newTr); +}; + +const removeLastColumn = (editor: Editor, tableInfo: TableInfo): boolean => { + const currentTableInfo = getCurrentTableInfo(editor, tableInfo); + const { tableNode, tablePos } = currentTableInfo; + const tableMapData = TableMap.get(tableNode); + + // Don't delete if only one column left + if (tableMapData.width <= 1) { + return false; + } + + const lastColumnIndex = tableMapData.width - 1; + + // Check if last column is empty + if (!isColumnEmpty(currentTableInfo, lastColumnIndex)) { + return false; + } + + const tr = editor.state.tr; + const rect = { + map: tableMapData, + tableStart: tablePos, + table: tableNode, + top: 0, + left: 0, + bottom: tableMapData.height - 1, + right: tableMapData.width - 1, + }; + + removeColumn(tr, rect, lastColumnIndex); + editor.view.dispatch(tr); + return true; +}; + +const isColumnEmpty = (tableInfo: TableInfo, columnIndex: number): boolean => { + const { tableNode } = tableInfo; + const tableMapData = TableMap.get(tableNode); + + // Check each cell in the column + for (let row = 0; row < tableMapData.height; row++) { + const cellIndex = row * tableMapData.width + columnIndex; + const cellPos = tableMapData.map[cellIndex]; + const cell = tableNode.nodeAt(cellPos); + + if (!isCellEmpty(cell)) { + return false; + } + } + return true; +}; + +// Row functions +const insertRowAfterLast = (editor: Editor, tableInfo: TableInfo) => { + const currentTableInfo = getCurrentTableInfo(editor, tableInfo); + const { tableNode, tablePos } = currentTableInfo; + const tableMapData = TableMap.get(tableNode); + const lastRowIndex = tableMapData.height; + + const tr = editor.state.tr; + const rect = { + map: tableMapData, + tableStart: tablePos, + table: tableNode, + top: 0, + left: 0, + bottom: tableMapData.height - 1, + right: tableMapData.width - 1, + }; + + const newTr = addRow(tr, rect, lastRowIndex); + editor.view.dispatch(newTr); +}; + +const removeLastRow = (editor: Editor, tableInfo: TableInfo): boolean => { + const currentTableInfo = getCurrentTableInfo(editor, tableInfo); + const { tableNode, tablePos } = currentTableInfo; + const tableMapData = TableMap.get(tableNode); + + // Don't delete if only one row left + if (tableMapData.height <= 1) { + return false; + } + + const lastRowIndex = tableMapData.height - 1; + + // Check if last row is empty + if (!isRowEmpty(currentTableInfo, lastRowIndex)) { + return false; + } + + const tr = editor.state.tr; + const rect = { + map: tableMapData, + tableStart: tablePos, + table: tableNode, + top: 0, + left: 0, + bottom: tableMapData.height - 1, + right: tableMapData.width - 1, + }; + + removeRow(tr, rect, lastRowIndex); + editor.view.dispatch(tr); + return true; +}; + +const isRowEmpty = (tableInfo: TableInfo, rowIndex: number): boolean => { + const { tableNode } = tableInfo; + const tableMapData = TableMap.get(tableNode); + + // Check each cell in the row + for (let col = 0; col < tableMapData.width; col++) { + const cellIndex = rowIndex * tableMapData.width + col; + const cellPos = tableMapData.map[cellIndex]; + const cell = tableNode.nodeAt(cellPos); + + if (!isCellEmpty(cell)) { + return false; + } + } + return true; +}; diff --git a/packages/editor/src/core/extensions/table/plugins/selection-outline/plugin.ts b/packages/editor/src/core/extensions/table/plugins/selection-outline/plugin.ts new file mode 100644 index 000000000..834ea3e44 --- /dev/null +++ b/packages/editor/src/core/extensions/table/plugins/selection-outline/plugin.ts @@ -0,0 +1,59 @@ +import { findParentNode, type Editor } from "@tiptap/core"; +import { Plugin, PluginKey } from "@tiptap/pm/state"; +import { TableMap } from "@tiptap/pm/tables"; +import { Decoration, DecorationSet } from "@tiptap/pm/view"; +// local imports +import { isCellSelection } from "../../table/utilities/helpers"; +import { getCellBorderClasses } from "./utils"; + +type TableCellSelectionOutlinePluginState = { + decorations?: DecorationSet; +}; + +const TABLE_SELECTION_OUTLINE_PLUGIN_KEY = new PluginKey("table-cell-selection-outline"); + +export const TableCellSelectionOutlinePlugin = (editor: Editor): Plugin => + new Plugin({ + key: TABLE_SELECTION_OUTLINE_PLUGIN_KEY, + state: { + init: () => ({}), + apply(tr, prev, oldState, newState) { + if (!editor.isEditable) return {}; + const table = findParentNode((node) => node.type.spec.tableRole === "table")(newState.selection); + const hasDocChanged = tr.docChanged || !newState.selection.eq(oldState.selection); + if (!table || !hasDocChanged) { + return table === undefined ? {} : prev; + } + + const { selection } = newState; + if (!isCellSelection(selection)) return {}; + + const decorations: Decoration[] = []; + const tableMap = TableMap.get(table.node); + const selectedCells: number[] = []; + + // First, collect all selected cell positions + selection.forEachCell((_node, pos) => { + const start = pos - table.pos - 1; + selectedCells.push(start); + }); + + // Then, add decorations with appropriate border classes + selection.forEachCell((node, pos) => { + const start = pos - table.pos - 1; + const classes = getCellBorderClasses(start, selectedCells, tableMap); + + decorations.push(Decoration.node(pos, pos + node.nodeSize, { class: classes.join(" ") })); + }); + + return { + decorations: DecorationSet.create(newState.doc, decorations), + }; + }, + }, + props: { + decorations(state) { + return TABLE_SELECTION_OUTLINE_PLUGIN_KEY.getState(state).decorations; + }, + }, + }); diff --git a/packages/editor/src/core/extensions/table/plugins/selection-outline/utils.ts b/packages/editor/src/core/extensions/table/plugins/selection-outline/utils.ts new file mode 100644 index 000000000..f4c43e77e --- /dev/null +++ b/packages/editor/src/core/extensions/table/plugins/selection-outline/utils.ts @@ -0,0 +1,75 @@ +import type { TableMap } from "@tiptap/pm/tables"; + +/** + * Calculates the positions of cells adjacent to a given cell in a table + * @param cellStart - The start position of the current cell in the document + * @param tableMap - ProseMirror's table mapping structure containing cell positions and dimensions + * @returns Object with positions of adjacent cells (undefined if cell doesn't exist at table edge) + */ +const getAdjacentCellPositions = ( + cellStart: number, + tableMap: TableMap +): { top?: number; bottom?: number; left?: number; right?: number } => { + // Extract table dimensions + // width -> number of columns in the table + // height -> number of rows in the table + const { width, height } = tableMap; + + // Find the index of our cell in the flat tableMap.map array + // tableMap.map contains start positions of all cells in row-by-row order + const cellIndex = tableMap.map.indexOf(cellStart); + + // Safety check: if cell position not found in table map, return empty object + if (cellIndex === -1) return {}; + + // Convert flat array index to 2D grid coordinates + // row = which row the cell is in (0-based from top) + // col = which column the cell is in (0-based from left) + const row = Math.floor(cellIndex / width); // Integer division gives row number + const col = cellIndex % width; // Remainder gives column number + + return { + // Top cell: same column, one row up + // Check if we're not in the first row (row > 0) before calculating + top: row > 0 ? tableMap.map[(row - 1) * width + col] : undefined, + + // Bottom cell: same column, one row down + // Check if we're not in the last row (row < height - 1) before calculating + bottom: row < height - 1 ? tableMap.map[(row + 1) * width + col] : undefined, + + // Left cell: same row, one column left + // Check if we're not in the first column (col > 0) before calculating + left: col > 0 ? tableMap.map[row * width + (col - 1)] : undefined, + + // Right cell: same row, one column right + // Check if we're not in the last column (col < width - 1) before calculating + right: col < width - 1 ? tableMap.map[row * width + (col + 1)] : undefined, + }; +}; + +export const getCellBorderClasses = (cellStart: number, selectedCells: number[], tableMap: TableMap): string[] => { + const adjacent = getAdjacentCellPositions(cellStart, tableMap); + const classes: string[] = []; + + // Add border-right if right cell is not selected or doesn't exist + if (adjacent.right === undefined || !selectedCells.includes(adjacent.right)) { + classes.push("selectedCell-border-right"); + } + + // Add border-left if left cell is not selected or doesn't exist + if (adjacent.left === undefined || !selectedCells.includes(adjacent.left)) { + classes.push("selectedCell-border-left"); + } + + // Add border-top if top cell is not selected or doesn't exist + if (adjacent.top === undefined || !selectedCells.includes(adjacent.top)) { + classes.push("selectedCell-border-top"); + } + + // Add border-bottom if bottom cell is not selected or doesn't exist + if (adjacent.bottom === undefined || !selectedCells.includes(adjacent.bottom)) { + classes.push("selectedCell-border-bottom"); + } + + return classes; +}; diff --git a/packages/editor/src/core/extensions/table/table-cell.ts b/packages/editor/src/core/extensions/table/table-cell.ts index 2ba06845a..42fd3c7df 100644 --- a/packages/editor/src/core/extensions/table/table-cell.ts +++ b/packages/editor/src/core/extensions/table/table-cell.ts @@ -1,6 +1,14 @@ import { mergeAttributes, Node } from "@tiptap/core"; +import { TableMap } from "@tiptap/pm/tables"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +// helpers +import { findParentNodeOfType } from "@/helpers/common"; +// local imports +import { TableCellSelectionOutlinePlugin } from "./plugins/selection-outline/plugin"; +import { DEFAULT_COLUMN_WIDTH } from "./table"; +import { isCellSelection } from "./table/utilities/helpers"; + export interface TableCellOptions { HTMLAttributes: Record; } @@ -25,7 +33,7 @@ export const TableCell = Node.create({ default: 1, }, colwidth: { - default: null, + default: [DEFAULT_COLUMN_WIDTH], parseHTML: (element) => { const colwidth = element.getAttribute("colwidth"); const value = colwidth ? [parseInt(colwidth, 10)] : null; @@ -46,6 +54,51 @@ export const TableCell = Node.create({ isolating: true, + addProseMirrorPlugins() { + return [TableCellSelectionOutlinePlugin(this.editor)]; + }, + + addKeyboardShortcuts() { + return { + Backspace: ({ editor }) => { + const { state } = editor.view; + const { selection } = state; + + if (isCellSelection(selection)) return false; + + // Check if we're at the start of the cell + if (selection.from !== selection.to || selection.$head.parentOffset !== 0) return false; + + // Find table and current cell + const tableNode = findParentNodeOfType(selection, [CORE_EXTENSIONS.TABLE])?.node; + const currentCellInfo = findParentNodeOfType(selection, [ + CORE_EXTENSIONS.TABLE_CELL, + CORE_EXTENSIONS.TABLE_HEADER, + ]); + const currentCellNode = currentCellInfo?.node; + const cellPos = currentCellInfo?.pos; + const cellDepth = currentCellInfo?.depth; + + if (!tableNode || !currentCellNode || cellPos === null || cellDepth === null) return false; + + // Check if this is the only cell in the TableMap (1 row, 1 column) + const tableMap = TableMap.get(tableNode); + const isOnlyCell = tableMap.width === 1 && tableMap.height === 1; + if (!isOnlyCell) return false; + + // Cell has content, select the entire cell + // Use the position that points to the cell node itself, not its content + const cellNodePos = selection.$head.before(cellDepth); + + editor.commands.setCellSelection({ + anchorCell: cellNodePos, + headCell: cellNodePos, + }); + return true; + }, + }; + }, + parseHTML() { return [{ tag: "td" }]; }, diff --git a/packages/editor/src/core/extensions/table/table-header.ts b/packages/editor/src/core/extensions/table/table-header.ts index 491889eef..315ada5ec 100644 --- a/packages/editor/src/core/extensions/table/table-header.ts +++ b/packages/editor/src/core/extensions/table/table-header.ts @@ -1,6 +1,9 @@ import { mergeAttributes, Node } from "@tiptap/core"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +// local imports +import { DEFAULT_COLUMN_WIDTH } from "./table"; + export interface TableHeaderOptions { HTMLAttributes: Record; } @@ -25,7 +28,7 @@ export const TableHeader = Node.create({ default: 1, }, colwidth: { - default: null, + default: [DEFAULT_COLUMN_WIDTH], parseHTML: (element) => { const colwidth = element.getAttribute("colwidth"); const value = colwidth ? [parseInt(colwidth, 10)] : null; diff --git a/packages/editor/src/core/extensions/table/table/index.ts b/packages/editor/src/core/extensions/table/table/index.ts index 8efc43120..328422b73 100644 --- a/packages/editor/src/core/extensions/table/table/index.ts +++ b/packages/editor/src/core/extensions/table/table/index.ts @@ -1 +1,3 @@ export { Table } from "./table"; + +export const DEFAULT_COLUMN_WIDTH = 150; diff --git a/packages/editor/src/core/extensions/table/table/table-view.tsx b/packages/editor/src/core/extensions/table/table/table-view.tsx index f78d964ed..2ccdc3c6d 100644 --- a/packages/editor/src/core/extensions/table/table/table-view.tsx +++ b/packages/editor/src/core/extensions/table/table/table-view.tsx @@ -7,6 +7,8 @@ import { icons } from "src/core/extensions/table/table/icons"; import tippy, { Instance, Props } from "tippy.js"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +// local imports +import { isCellSelection } from "./utilities/helpers"; type ToolboxItem = { label: string; @@ -95,7 +97,7 @@ function setCellsBackgroundColor(editor: Editor, color: { backgroundColor: strin function setTableRowBackgroundColor(editor: Editor, color: { backgroundColor: string; textColor: string }) { const { state, dispatch } = editor.view; const { selection } = state; - if (!(selection instanceof CellSelection)) { + if (!isCellSelection(selection)) { return false; } @@ -387,7 +389,7 @@ export class TableView implements NodeView { this.root = h( "div", { - className: "table-wrapper horizontal-scrollbar scrollbar-md controls--disabled", + className: "table-wrapper editor-full-width-block horizontal-scrollbar scrollbar-sm controls--disabled", }, this.controls, this.table diff --git a/packages/editor/src/core/extensions/table/table/table.ts b/packages/editor/src/core/extensions/table/table/table.ts index 4810706b3..0bdc4e8d1 100644 --- a/packages/editor/src/core/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -7,8 +7,6 @@ import { addRowBefore, CellSelection, columnResizing, - deleteColumn, - deleteRow, deleteTable, fixTables, goToNextCell, @@ -23,12 +21,16 @@ import { Decoration } from "@tiptap/pm/view"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; // local imports +import { TableInsertPlugin } from "../plugins/insert-handlers/plugin"; import { tableControls } from "./table-controls"; import { TableView } from "./table-view"; import { createTable } from "./utilities/create-table"; -import { deleteTableWhenAllCellsSelected } from "./utilities/delete-table-when-all-cells-selected"; +import { deleteColumnOrTable } from "./utilities/delete-column"; +import { handleDeleteKeyOnTable } from "./utilities/delete-key-shortcut"; +import { deleteRowOrTable } from "./utilities/delete-row"; import { insertLineAboveTableAction } from "./utilities/insert-line-above-table-action"; import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action"; +import { DEFAULT_COLUMN_WIDTH } from "."; export interface TableOptions { HTMLAttributes: Record; @@ -42,12 +44,7 @@ export interface TableOptions { declare module "@tiptap/core" { interface Commands { [CORE_EXTENSIONS.TABLE]: { - insertTable: (options?: { - rows?: number; - cols?: number; - withHeaderRow?: boolean; - columnWidth?: number; - }) => ReturnType; + insertTable: (options?: { rows?: number; cols?: number; withHeaderRow?: boolean }) => ReturnType; addColumnBefore: () => ReturnType; addColumnAfter: () => ReturnType; deleteColumn: () => ReturnType; @@ -81,7 +78,7 @@ declare module "@tiptap/core" { } } -export const Table = Node.create({ +export const Table = Node.create({ name: CORE_EXTENSIONS.TABLE, addOptions() { @@ -116,9 +113,15 @@ export const Table = Node.create({ addCommands() { return { insertTable: - ({ rows = 3, cols = 3, withHeaderRow = false, columnWidth = 150 } = {}) => + ({ rows = 3, cols = 3, withHeaderRow = false } = {}) => ({ tr, dispatch, editor }) => { - const node = createTable(editor.schema, rows, cols, withHeaderRow, undefined, columnWidth); + const node = createTable({ + schema: editor.schema, + rowsCount: rows, + colsCount: cols, + withHeaderRow, + columnWidth: DEFAULT_COLUMN_WIDTH, + }); if (dispatch) { const offset = tr.selection.anchor + 1; @@ -137,10 +140,7 @@ export const Table = Node.create({ () => ({ state, dispatch }) => addColumnAfter(state, dispatch), - deleteColumn: - () => - ({ state, dispatch }) => - deleteColumn(state, dispatch), + deleteColumn: deleteColumnOrTable, addRowBefore: () => ({ state, dispatch }) => @@ -149,10 +149,7 @@ export const Table = Node.create({ () => ({ state, dispatch }) => addRowAfter(state, dispatch), - deleteRow: - () => - ({ state, dispatch }) => - deleteRow(state, dispatch), + deleteRow: deleteRowOrTable, deleteTable: () => ({ state, dispatch }) => @@ -222,27 +219,35 @@ export const Table = Node.create({ addKeyboardShortcuts() { return { Tab: () => { - if (this.editor.isActive(CORE_EXTENSIONS.TABLE)) { - if (this.editor.isActive(CORE_EXTENSIONS.LIST_ITEM) || this.editor.isActive(CORE_EXTENSIONS.TASK_ITEM)) { - return false; - } - if (this.editor.commands.goToNextCell()) { - return true; - } + if (!this.editor.isActive(CORE_EXTENSIONS.TABLE)) return false; - if (!this.editor.can().addRowAfter()) { - return false; - } - - return this.editor.chain().addRowAfter().goToNextCell().run(); + if (this.editor.isActive(CORE_EXTENSIONS.LIST_ITEM) || this.editor.isActive(CORE_EXTENSIONS.TASK_ITEM)) { + return false; } - return false; + + if (this.editor.commands.goToNextCell()) { + return true; + } + + if (!this.editor.can().addRowAfter()) { + return false; + } + + return this.editor.chain().addRowAfter().goToNextCell().run(); }, - "Shift-Tab": () => this.editor.commands.goToPreviousCell(), - Backspace: deleteTableWhenAllCellsSelected, - "Mod-Backspace": deleteTableWhenAllCellsSelected, - Delete: deleteTableWhenAllCellsSelected, - "Mod-Delete": deleteTableWhenAllCellsSelected, + "Shift-Tab": () => { + if (!this.editor.isActive(CORE_EXTENSIONS.TABLE)) return false; + + if (this.editor.isActive(CORE_EXTENSIONS.LIST_ITEM) || this.editor.isActive(CORE_EXTENSIONS.TASK_ITEM)) { + return false; + } + + return this.editor.commands.goToPreviousCell(); + }, + Backspace: handleDeleteKeyOnTable, + "Mod-Backspace": handleDeleteKeyOnTable, + Delete: handleDeleteKeyOnTable, + "Mod-Delete": handleDeleteKeyOnTable, ArrowDown: insertLineBelowTableAction, ArrowUp: insertLineAboveTableAction, }; @@ -264,6 +269,7 @@ export const Table = Node.create({ allowTableNodeSelection: this.options.allowTableNodeSelection, }), tableControls(), + TableInsertPlugin(this.editor), ]; if (isResizable) { diff --git a/packages/editor/src/core/extensions/table/table/utilities/create-table.ts b/packages/editor/src/core/extensions/table/table/utilities/create-table.ts index 5e9c4ba24..0ba2757db 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/create-table.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/create-table.ts @@ -3,14 +3,18 @@ import { Fragment, Node as ProsemirrorNode, Schema } from "@tiptap/pm/model"; import { createCell } from "@/extensions/table/table/utilities/create-cell"; import { getTableNodeTypes } from "@/extensions/table/table/utilities/get-table-node-types"; -export function createTable( - schema: Schema, - rowsCount: number, - colsCount: number, - withHeaderRow: boolean, - cellContent?: Fragment | ProsemirrorNode | Array, - columnWidth: number = 100 -): ProsemirrorNode { +type Props = { + schema: Schema; + rowsCount: number; + colsCount: number; + withHeaderRow: boolean; + cellContent?: Fragment | ProsemirrorNode | Array; + columnWidth: number; +}; + +export const createTable = (props: Props): ProsemirrorNode => { + const { schema, rowsCount, colsCount, withHeaderRow, cellContent, columnWidth } = props; + const types = getTableNodeTypes(schema); const headerCells: ProsemirrorNode[] = []; const cells: ProsemirrorNode[] = []; @@ -38,4 +42,4 @@ export function createTable( } return types.table.createChecked(null, rows); -} +}; diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts new file mode 100644 index 000000000..9cbcdd0a3 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-column.ts @@ -0,0 +1,39 @@ +import type { Command } from "@tiptap/core"; +import { deleteColumn, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; + +export const deleteColumnOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a table and have a cell selection + if (!isCellSelection(selection)) { + return false; + } + + // Get the ProseMirrorTable and calculate total columns + const tableStart = selection.$anchorCell.start(-1); + const selectedTable = state.doc.nodeAt(tableStart - 1); + + if (!selectedTable) return false; + + // Count total columns by examining the first row + const firstRow = selectedTable.firstChild; + if (!firstRow) return false; + + let totalColumns = 0; + for (let i = 0; i < firstRow.childCount; i++) { + const cell = firstRow.child(i); + totalColumns += cell.attrs.colspan || 1; + } + + // If only one column exists, delete the entire ProseMirrorTable + if (totalColumns === 1) { + return deleteTable(state, dispatch); + } + + // Otherwise, proceed with normal column deletion + return deleteColumn(state, dispatch); + }; diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-key-shortcut.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-key-shortcut.ts new file mode 100644 index 000000000..99f343651 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-key-shortcut.ts @@ -0,0 +1,201 @@ +import { Editor, findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/core"; +import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; +import { CellSelection, TableMap } from "@tiptap/pm/tables"; +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +// extensions +import { isCellEmpty, isCellSelection } from "@/extensions/table/table/utilities/helpers"; + +interface CellCoord { + row: number; + col: number; +} + +interface TableInfo { + node: ProseMirrorNode; + pos: number; + map: TableMap; + totalColumns: number; + totalRows: number; +} + +export const handleDeleteKeyOnTable: KeyboardShortcutCommand = (props) => { + const { editor } = props; + const { selection } = editor.state; + + try { + if (!isCellSelection(selection)) return false; + + const tableInfo = getTableInfo(editor); + if (!tableInfo) return false; + + const selectedCellCoords = getSelectedCellCoords(selection, tableInfo); + if (selectedCellCoords.length === 0) return false; + + const hasContent = checkCellsHaveContent(selection); + if (hasContent) return false; + + const selectionBounds = calculateSelectionBounds(selectedCellCoords); + const { totalColumnsInSelection, totalRowsInSelection, minRow, minCol } = selectionBounds; + + // Check if entire rows are selected + if (totalColumnsInSelection === tableInfo.totalColumns) { + return deleteMultipleRows(editor, totalRowsInSelection, minRow, tableInfo); + } + + // Check if entire columns are selected + if (totalRowsInSelection === tableInfo.totalRows) { + return deleteMultipleColumns(editor, totalColumnsInSelection, minCol, tableInfo); + } + + return false; + } catch (error) { + console.error("Error in handleDeleteKeyOnTable", error); + return false; + } +}; + +const getTableInfo = (editor: Editor): TableInfo | null => { + const table = findParentNodeClosestToPos( + editor.state.selection.ranges[0].$from, + (node) => node.type.name === CORE_EXTENSIONS.TABLE + ); + + if (!table) return null; + + const tableMap = TableMap.get(table.node); + return { + node: table.node, + pos: table.pos, + map: tableMap, + totalColumns: tableMap.width, + totalRows: tableMap.height, + }; +}; + +const getSelectedCellCoords = (selection: CellSelection, tableInfo: TableInfo): CellCoord[] => { + const selectedCellCoords: CellCoord[] = []; + + selection.forEachCell((_node, pos) => { + const cellStart = pos - tableInfo.pos - 1; + const coord = findCellCoordinate(cellStart, tableInfo); + + if (coord) { + selectedCellCoords.push(coord); + } + }); + + return selectedCellCoords; +}; + +const findCellCoordinate = (cellStart: number, tableInfo: TableInfo): CellCoord | null => { + // Primary method: use indexOf + const cellIndex = tableInfo.map.map.indexOf(cellStart); + + if (cellIndex !== -1) { + return { + row: Math.floor(cellIndex / tableInfo.totalColumns), + col: cellIndex % tableInfo.totalColumns, + }; + } + + // Fallback: manual search + for (let i = 0; i < tableInfo.map.map.length; i++) { + if (tableInfo.map.map[i] === cellStart) { + return { + row: Math.floor(i / tableInfo.totalColumns), + col: i % tableInfo.totalColumns, + }; + } + } + + return null; +}; + +const checkCellsHaveContent = (selection: CellSelection): boolean => { + let hasContent = false; + + selection.forEachCell((node) => { + if (node && !isCellEmpty(node)) { + hasContent = true; + } + }); + + return hasContent; +}; + +const calculateSelectionBounds = (selectedCellCoords: CellCoord[]) => { + const minRow = Math.min(...selectedCellCoords.map((c) => c.row)); + const maxRow = Math.max(...selectedCellCoords.map((c) => c.row)); + const minCol = Math.min(...selectedCellCoords.map((c) => c.col)); + const maxCol = Math.max(...selectedCellCoords.map((c) => c.col)); + + return { + minRow, + maxRow, + minCol, + maxCol, + totalColumnsInSelection: maxCol - minCol + 1, + totalRowsInSelection: maxRow - minRow + 1, + }; +}; + +const deleteMultipleRows = ( + editor: Editor, + totalRowsInSelection: number, + minRow: number, + initialTableInfo: TableInfo +): boolean => { + // Position cursor at the first selected row + setCursorAtPosition(editor, initialTableInfo, minRow, 0); + + // Delete rows one by one + for (let i = 0; i < totalRowsInSelection; i++) { + editor.commands.deleteRow(); + + // Reposition cursor if there are more rows to delete + if (i < totalRowsInSelection - 1) { + const updatedTableInfo = getTableInfo(editor); + if (updatedTableInfo) { + setCursorAtPosition(editor, updatedTableInfo, minRow, 0); + } + } + } + + return true; +}; + +const deleteMultipleColumns = ( + editor: Editor, + totalColumnsInSelection: number, + minCol: number, + initialTableInfo: TableInfo +): boolean => { + // Position cursor at the first selected column + setCursorAtPosition(editor, initialTableInfo, 0, minCol); + + // Delete columns one by one + for (let i = 0; i < totalColumnsInSelection; i++) { + editor.commands.deleteColumn(); + + // Reposition cursor if there are more columns to delete + if (i < totalColumnsInSelection - 1) { + const updatedTableInfo = getTableInfo(editor); + if (updatedTableInfo) { + setCursorAtPosition(editor, updatedTableInfo, 0, minCol); + } + } + } + + return true; +}; + +const setCursorAtPosition = (editor: Editor, tableInfo: TableInfo, row: number, col: number): void => { + const cellIndex = row * tableInfo.totalColumns + col; + const cellPos = tableInfo.pos + tableInfo.map.map[cellIndex] + 1; + + editor.commands.setCellSelection({ + anchorCell: cellPos, + headCell: cellPos, + }); +}; diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts new file mode 100644 index 000000000..4a7d161d1 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-row.ts @@ -0,0 +1,32 @@ +import type { Command } from "@tiptap/core"; +import { deleteRow, deleteTable } from "@tiptap/pm/tables"; +// local imports +import { isCellSelection } from "./helpers"; + +export const deleteRowOrTable: () => Command = + () => + ({ state, dispatch }) => { + const { selection } = state; + + // Check if we're in a ProseMirrorTable and have a cell selection + if (!isCellSelection(selection)) { + return false; + } + + // Get the ProseMirrorTable and calculate total rows + const tableStart = selection.$anchorCell.start(-1); + const selectedTable = state.doc.nodeAt(tableStart - 1); + + if (!selectedTable) return false; + + // Count total rows by examining the table's children + const totalRows = selectedTable.childCount; + + // If only one row exists, delete the entire ProseMirrorTable + if (totalRows === 1) { + return deleteTable(state, dispatch); + } + + // Otherwise, proceed with normal row deletion + return deleteRow(state, dispatch); + }; diff --git a/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts deleted file mode 100644 index 5c84b8617..000000000 --- a/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/core"; -// constants -import { CORE_EXTENSIONS } from "@/constants/extension"; -// extensions -import { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; - -export const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => { - const { selection } = editor.state; - - if (!isCellSelection(selection)) { - return false; - } - - let cellCount = 0; - const table = findParentNodeClosestToPos( - selection.ranges[0].$from, - (node) => node.type.name === CORE_EXTENSIONS.TABLE - ); - - table?.node.descendants((node) => { - if (node.type.name === CORE_EXTENSIONS.TABLE) { - return false; - } - - if ([CORE_EXTENSIONS.TABLE_CELL, CORE_EXTENSIONS.TABLE_HEADER].includes(node.type.name as CORE_EXTENSIONS)) { - cellCount += 1; - } - }); - - const allCellsSelected = cellCount === selection.ranges.length; - - if (!allCellsSelected) { - return false; - } - - editor.commands.deleteTable(); - - return true; -}; diff --git a/packages/editor/src/core/extensions/table/table/utilities/helpers.ts b/packages/editor/src/core/extensions/table/table/utilities/helpers.ts new file mode 100644 index 000000000..4d7218060 --- /dev/null +++ b/packages/editor/src/core/extensions/table/table/utilities/helpers.ts @@ -0,0 +1,35 @@ +import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; +import type { Selection } from "@tiptap/pm/state"; +import { CellSelection } from "@tiptap/pm/tables"; + +/** + * @description Check if the selection is a cell selection + * @param {Selection} selection - The selection to check + * @returns {boolean} True if the selection is a cell selection, false otherwise + */ +export const isCellSelection = (selection: Selection): selection is CellSelection => selection instanceof CellSelection; + +/** + * @description Check if a cell is empty + * @param {ProseMirrorNode | null} cell - The cell to check + * @returns {boolean} True if the cell is empty, false otherwise + */ +export const isCellEmpty = (cell: ProseMirrorNode | null): boolean => { + if (!cell || cell.content.size === 0) { + return true; + } + + // Check if cell has any non-empty content + let hasContent = false; + cell.content.forEach((node) => { + if (node.type.name === "paragraph") { + if (node.content.size > 0) { + hasContent = true; + } + } else if (node.content.size > 0 || node.isText) { + hasContent = true; + } + }); + + return !hasContent; +}; diff --git a/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts b/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts index 35c2ee3c7..9a50a839c 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts @@ -13,7 +13,7 @@ export const insertLineAboveTableAction: KeyboardShortcutCommand = ({ editor }) const { selection } = editor.state; // Find the table node and its position - const tableNode = findParentNodeOfType(selection, CORE_EXTENSIONS.TABLE); + const tableNode = findParentNodeOfType(selection, [CORE_EXTENSIONS.TABLE]); if (!tableNode) return false; const tablePos = tableNode.pos; diff --git a/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts b/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts index 6c26e22a2..b30b8ae4d 100644 --- a/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts @@ -13,7 +13,7 @@ export const insertLineBelowTableAction: KeyboardShortcutCommand = ({ editor }) const { selection } = editor.state; // Find the table node and its position - const tableNode = findParentNodeOfType(selection, CORE_EXTENSIONS.TABLE); + const tableNode = findParentNodeOfType(selection, [CORE_EXTENSIONS.TABLE]); if (!tableNode) return false; const tablePos = tableNode.pos; diff --git a/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts b/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts deleted file mode 100644 index 42ea5759c..000000000 --- a/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CellSelection } from "@tiptap/pm/tables"; - -export function isCellSelection(value: unknown): value is CellSelection { - return value instanceof CellSelection; -} diff --git a/packages/editor/src/core/extensions/utility.ts b/packages/editor/src/core/extensions/utility.ts index 758c74241..a1b138a6d 100644 --- a/packages/editor/src/core/extensions/utility.ts +++ b/packages/editor/src/core/extensions/utility.ts @@ -1,26 +1,40 @@ import { Extension } from "@tiptap/core"; -// prosemirror plugins import codemark from "prosemirror-codemark"; // helpers +import { CORE_EXTENSIONS } from "@/constants/extension"; import { restorePublicImages } from "@/helpers/image-helpers"; // plugins +import { TAdditionalActiveDropbarExtensions } from "@/plane-editor/types/utils"; import { DropHandlerPlugin } from "@/plugins/drop"; import { FilePlugins } from "@/plugins/file/root"; import { MarkdownClipboardPlugin } from "@/plugins/markdown-clipboard"; // types -import type { IEditorProps, TFileHandler, TReadOnlyFileHandler } from "@/types"; + +import type { IEditorProps, TEditorAsset, TFileHandler, TReadOnlyFileHandler } from "@/types"; +type TActiveDropbarExtensions = CORE_EXTENSIONS.MENTION | CORE_EXTENSIONS.EMOJI | TAdditionalActiveDropbarExtensions; declare module "@tiptap/core" { interface Commands { utility: { updateAssetsUploadStatus: (updatedStatus: TFileHandler["assetsUploadStatus"]) => () => void; + updateAssetsList: ( + args: + | { + asset: TEditorAsset; + } + | { + idToRemove: string; + } + ) => () => void; }; } } export interface UtilityExtensionStorage { + assetsList: TEditorAsset[]; assetsUploadStatus: TFileHandler["assetsUploadStatus"]; uploadInProgress: boolean; + activeDropbarExtensions: TActiveDropbarExtensions[]; } type Props = Pick & { @@ -58,8 +72,10 @@ export const UtilityExtension = (props: Props) => { addStorage() { return { + assetsList: [], assetsUploadStatus: isEditable && "assetsUploadStatus" in fileHandler ? fileHandler.assetsUploadStatus : {}, uploadInProgress: false, + activeDropbarExtensions: [], }; }, @@ -68,6 +84,21 @@ export const UtilityExtension = (props: Props) => { updateAssetsUploadStatus: (updatedStatus) => () => { this.storage.assetsUploadStatus = updatedStatus; }, + updateAssetsList: (args) => () => { + const uniqueAssets = new Set(this.storage.assetsList); + if ("asset" in args) { + const alreadyExists = this.storage.assetsList.find((asset) => asset.id === args.asset.id); + if (!alreadyExists) { + uniqueAssets.add(args.asset); + } + } else if ("idToRemove" in args) { + const asset = this.storage.assetsList.find((asset) => asset.id === args.idToRemove); + if (asset) { + uniqueAssets.delete(asset); + } + } + this.storage.assetsList = Array.from(uniqueAssets); + }, }; }, }); diff --git a/packages/editor/src/core/helpers/assets.ts b/packages/editor/src/core/helpers/assets.ts new file mode 100644 index 000000000..74179f6c4 --- /dev/null +++ b/packages/editor/src/core/helpers/assets.ts @@ -0,0 +1,37 @@ +import { Node as ProseMirrorNode } from "@tiptap/pm/model"; +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +// extensions +import { getImageBlockId } from "@/extensions/custom-image/utils"; +// plane editor imports +import { ADDITIONAL_ASSETS_META_DATA_RECORD } from "@/plane-editor/constants/assets"; +// types +import { TEditorAsset } from "@/types"; + +export type TAssetMetaDataRecord = (attrs: ProseMirrorNode["attrs"]) => TEditorAsset | undefined; + +export const CORE_ASSETS_META_DATA_RECORD: Partial> = { + [CORE_EXTENSIONS.IMAGE]: (attrs) => { + if (!attrs?.src) return; + return { + href: `#${getImageBlockId(attrs?.id ?? "")}`, + id: attrs?.id, + name: `image-${attrs?.id}`, + size: 0, + src: attrs?.src, + type: CORE_EXTENSIONS.IMAGE, + }; + }, + [CORE_EXTENSIONS.CUSTOM_IMAGE]: (attrs) => { + if (!attrs?.src) return; + return { + href: `#${getImageBlockId(attrs?.id ?? "")}`, + id: attrs?.id, + name: `image-${attrs?.id}`, + size: 0, + src: attrs?.src, + type: CORE_EXTENSIONS.CUSTOM_IMAGE, + }; + }, + ...ADDITIONAL_ASSETS_META_DATA_RECORD, +}; diff --git a/packages/editor/src/core/helpers/common.ts b/packages/editor/src/core/helpers/common.ts index e694e1e85..301d81917 100644 --- a/packages/editor/src/core/helpers/common.ts +++ b/packages/editor/src/core/helpers/common.ts @@ -1,3 +1,4 @@ +import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; import { EditorState, Selection } from "@tiptap/pm/state"; // plane imports import { cn } from "@plane/utils"; @@ -21,17 +22,28 @@ export const getEditorClassNames = ({ noBorder, borderOnFocus, containerClassNam ); // Helper function to find the parent node of a specific type -export function findParentNodeOfType(selection: Selection, typeName: string) { +export const findParentNodeOfType = ( + selection: Selection, + typeName: string[] +): { + node: ProseMirrorNode; + pos: number; + depth: number; +} | null => { let depth = selection.$anchor.depth; while (depth > 0) { const node = selection.$anchor.node(depth); - if (node.type.name === typeName) { - return { node, pos: selection.$anchor.start(depth) - 1 }; + if (typeName.includes(node.type.name)) { + return { + node, + pos: selection.$anchor.start(depth) - 1, + depth, + }; } depth--; } return null; -} +}; export const findTableAncestor = (node: Node | null): HTMLTableElement | null => { while (node !== null && node.nodeName !== "TABLE") { diff --git a/packages/editor/src/core/helpers/editor-commands.ts b/packages/editor/src/core/helpers/editor-commands.ts index 415a42bb3..fabce3691 100644 --- a/packages/editor/src/core/helpers/editor-commands.ts +++ b/packages/editor/src/core/helpers/editor-commands.ts @@ -1,4 +1,4 @@ -import { Editor, Range } from "@tiptap/core"; +import type { Editor, Range } from "@tiptap/core"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; // extensions @@ -14,21 +14,16 @@ export const setText = (editor: Editor, range?: Range) => { export const toggleHeading = (editor: Editor, level: 1 | 2 | 3 | 4 | 5 | 6, range?: Range) => { if (range) editor.chain().focus().deleteRange(range).setNode(CORE_EXTENSIONS.HEADING, { level }).run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleHeading({ level }).run(); }; export const toggleBold = (editor: Editor, range?: Range) => { - // @ts-expect-error tiptap types are incorrect if (range) editor.chain().focus().deleteRange(range).toggleBold().run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleBold().run(); }; export const toggleItalic = (editor: Editor, range?: Range) => { - // @ts-expect-error tiptap types are incorrect if (range) editor.chain().focus().deleteRange(range).toggleItalic().run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleItalic().run(); }; @@ -67,16 +62,12 @@ export const toggleCodeBlock = (editor: Editor, range?: Range) => { }; export const toggleOrderedList = (editor: Editor, range?: Range) => { - // @ts-expect-error tiptap types are incorrect if (range) editor.chain().focus().deleteRange(range).toggleOrderedList().run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleOrderedList().run(); }; export const toggleBulletList = (editor: Editor, range?: Range) => { - // @ts-expect-error tiptap types are incorrect if (range) editor.chain().focus().deleteRange(range).toggleBulletList().run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleBulletList().run(); }; @@ -86,9 +77,7 @@ export const toggleTaskList = (editor: Editor, range?: Range) => { }; export const toggleStrike = (editor: Editor, range?: Range) => { - // @ts-expect-error tiptap types are incorrect if (range) editor.chain().focus().deleteRange(range).toggleStrike().run(); - // @ts-expect-error tiptap types are incorrect else editor.chain().focus().toggleStrike().run(); }; @@ -109,9 +98,8 @@ export const insertTableCommand = (editor: Editor, range?: Range) => { } } } - if (range) - editor.chain().focus().deleteRange(range).clearNodes().insertTable({ rows: 3, cols: 3, columnWidth: 150 }).run(); - else editor.chain().focus().clearNodes().insertTable({ rows: 3, cols: 3, columnWidth: 150 }).run(); + if (range) editor.chain().focus().deleteRange(range).clearNodes().insertTable({ rows: 3, cols: 3 }).run(); + else editor.chain().focus().clearNodes().insertTable({ rows: 3, cols: 3 }).run(); }; export const insertImage = ({ diff --git a/packages/editor/src/core/helpers/editor-ref.ts b/packages/editor/src/core/helpers/editor-ref.ts new file mode 100644 index 000000000..1b9843df9 --- /dev/null +++ b/packages/editor/src/core/helpers/editor-ref.ts @@ -0,0 +1,55 @@ +import { HocuspocusProvider } from "@hocuspocus/provider"; +import { Editor } from "@tiptap/core"; +import * as Y from "yjs"; +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +import { CORE_EDITOR_META } from "@/constants/meta"; +// types +import { EditorReadOnlyRefApi } from "@/types"; +// local imports +import { getParagraphCount } from "./common"; +import { getExtensionStorage } from "./get-extension-storage"; +import { scrollSummary } from "./scroll-to-node"; + +type TArgs = { + editor: Editor | null; + provider: HocuspocusProvider | undefined; +}; + +export const getEditorRefHelpers = (args: TArgs): EditorReadOnlyRefApi => { + const { editor, provider } = args; + + return { + clearEditor: (emitUpdate = false) => { + editor?.chain().setMeta(CORE_EDITOR_META.SKIP_FILE_DELETION, true).clearContent(emitUpdate).run(); + }, + getDocument: () => { + const documentBinary = provider?.document ? Y.encodeStateAsUpdate(provider?.document) : null; + const documentHTML = editor?.getHTML() ?? "

    "; + const documentJSON = editor?.getJSON() ?? null; + + return { + binary: documentBinary, + html: documentHTML, + json: documentJSON, + }; + }, + getDocumentInfo: () => ({ + characters: editor ? getExtensionStorage(editor, CORE_EXTENSIONS.CHARACTER_COUNT)?.characters?.() : 0, + paragraphs: getParagraphCount(editor?.state), + words: editor ? getExtensionStorage(editor, CORE_EXTENSIONS.CHARACTER_COUNT)?.words?.() : 0, + }), + getHeadings: () => (editor ? getExtensionStorage(editor, CORE_EXTENSIONS.HEADINGS_LIST)?.headings : []), + getMarkDown: () => { + const markdownOutput = editor?.storage?.markdown?.getMarkdown?.(); + return markdownOutput; + }, + scrollSummary: (marking) => { + if (!editor) return; + scrollSummary(editor, marking); + }, + setEditorValue: (content, emitUpdate = false) => { + editor?.commands.setContent(content, emitUpdate, { preserveWhitespace: true }); + }, + }; +}; diff --git a/packages/editor/src/core/helpers/find-suggestion-match.ts b/packages/editor/src/core/helpers/find-suggestion-match.ts new file mode 100644 index 000000000..5db2f9474 --- /dev/null +++ b/packages/editor/src/core/helpers/find-suggestion-match.ts @@ -0,0 +1,73 @@ +import { escapeForRegEx } from "@tiptap/core"; +import { Trigger, SuggestionMatch } from "@tiptap/suggestion"; + +export function customFindSuggestionMatch(config: Trigger): SuggestionMatch | null { + const { char, allowSpaces: allowSpacesOption, allowToIncludeChar, allowedPrefixes, startOfLine, $position } = config; + + const allowSpaces = allowSpacesOption && !allowToIncludeChar; + + const escapedChar = escapeForRegEx(char); + const suffix = new RegExp(`\\s${escapedChar}$`); + const prefix = startOfLine ? "^" : ""; + const finalEscapedChar = allowToIncludeChar ? "" : escapedChar; + const regexp = allowSpaces + ? new RegExp(`${prefix}${escapedChar}.*?(?=\\s${finalEscapedChar}|$)`, "gm") + : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\s${finalEscapedChar}]*`, "gm"); + + // Instead of just looking at nodeBefore.text, we need to extract text from the current paragraph + // to properly handle text with decorators like bold, italic, etc. + const currentParagraph = $position.parent; + if (!currentParagraph.isTextblock) { + return null; + } + + // Get the start position of the current paragraph + const paragraphStart = $position.start(); + // Extract text content using textBetween which handles text across different nodes/marks + const text = $position.doc.textBetween(paragraphStart, $position.pos, "\0", "\0"); + + if (!text) { + return null; + } + + const textFrom = paragraphStart; + const match = Array.from(text.matchAll(regexp)).pop(); + + if (!match || match.input === undefined || match.index === undefined) { + return null; + } + + // JavaScript doesn't have lookbehinds. This hacks a check that first character + // is a space or the start of the line + const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index); + const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join("")}]?$`).test(matchPrefix); + + if (allowedPrefixes && allowedPrefixes.length > 0 && !matchPrefixIsAllowed) { + return null; + } + + // The absolute position of the match in the document + const from = textFrom + match.index; + let to = from + match[0].length; + + // Edge case handling; if spaces are allowed and we're directly in between + // two triggers + if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) { + match[0] += " "; + to += 1; + } + + // If the $position is located within the matched substring, return that range + if (from < $position.pos && to >= $position.pos) { + return { + range: { + from, + to, + }, + query: match[0].slice(char.length), + text: match[0], + }; + } + + return null; +} diff --git a/packages/editor/src/core/helpers/parser.ts b/packages/editor/src/core/helpers/parser.ts index 13b105323..bf84b2fdb 100644 --- a/packages/editor/src/core/helpers/parser.ts +++ b/packages/editor/src/core/helpers/parser.ts @@ -1,6 +1,5 @@ // plane imports -import { TDocumentPayload, TDuplicateAssetData, TDuplicateAssetResponse } from "@plane/types"; -import { TEditorAssetType } from "@plane/types/src/enums"; +import { TDocumentPayload, TDuplicateAssetData, TDuplicateAssetResponse, TEditorAssetType } from "@plane/types"; // plane web imports import { extractAdditionalAssetsFromHTMLContent, diff --git a/packages/editor/src/core/helpers/scroll-to-node.ts b/packages/editor/src/core/helpers/scroll-to-node.ts index 973f3cf14..7e5aa0979 100644 --- a/packages/editor/src/core/helpers/scroll-to-node.ts +++ b/packages/editor/src/core/helpers/scroll-to-node.ts @@ -32,6 +32,7 @@ function scrollToNode(editor: Editor, pos: number): void { } } +// eslint-disable-next-line no-undef export function scrollToNodeViaDOMCoordinates(editor: Editor, pos: number, behavior?: ScrollBehavior): void { const view = editor.view; diff --git a/packages/editor/src/core/helpers/yjs-utils.ts b/packages/editor/src/core/helpers/yjs-utils.ts index d61711127..92240bbb4 100644 --- a/packages/editor/src/core/helpers/yjs-utils.ts +++ b/packages/editor/src/core/helpers/yjs-utils.ts @@ -13,9 +13,7 @@ import { const RICH_TEXT_EDITOR_EXTENSIONS = CoreEditorExtensionsWithoutProps; const DOCUMENT_EDITOR_EXTENSIONS = [...CoreEditorExtensionsWithoutProps, ...DocumentEditorExtensionsWithoutProps]; // editor schemas -// @ts-expect-error tiptap types are incorrect const richTextEditorSchema = getSchema(RICH_TEXT_EDITOR_EXTENSIONS); -// @ts-expect-error tiptap types are incorrect const documentEditorSchema = getSchema(DOCUMENT_EDITOR_EXTENSIONS); /** @@ -57,7 +55,6 @@ export const convertBase64StringToBinaryData = (document: string): ArrayBuffer = */ export const getBinaryDataFromRichTextEditorHTMLString = (descriptionHTML: string): Uint8Array => { // convert HTML to JSON - // @ts-expect-error tiptap types are incorrect const contentJSON = generateJSON(descriptionHTML ?? "

    ", RICH_TEXT_EDITOR_EXTENSIONS); // convert JSON to Y.Doc format const transformedData = prosemirrorJSONToYDoc(richTextEditorSchema, contentJSON, "default"); @@ -73,7 +70,6 @@ export const getBinaryDataFromRichTextEditorHTMLString = (descriptionHTML: strin */ export const getBinaryDataFromDocumentEditorHTMLString = (descriptionHTML: string): Uint8Array => { // convert HTML to JSON - // @ts-expect-error tiptap types are incorrect const contentJSON = generateJSON(descriptionHTML ?? "

    ", DOCUMENT_EDITOR_EXTENSIONS); // convert JSON to Y.Doc format const transformedData = prosemirrorJSONToYDoc(documentEditorSchema, contentJSON, "default"); @@ -102,7 +98,6 @@ export const getAllDocumentFormatsFromRichTextEditorBinaryData = ( const type = yDoc.getXmlFragment("default"); const contentJSON = yXmlFragmentToProseMirrorRootNode(type, richTextEditorSchema).toJSON(); // convert to HTML - // @ts-expect-error tiptap types are incorrect const contentHTML = generateHTML(contentJSON, RICH_TEXT_EDITOR_EXTENSIONS); return { @@ -132,7 +127,6 @@ export const getAllDocumentFormatsFromDocumentEditorBinaryData = ( const type = yDoc.getXmlFragment("default"); const contentJSON = yXmlFragmentToProseMirrorRootNode(type, documentEditorSchema).toJSON(); // convert to HTML - // @ts-expect-error tiptap types are incorrect const contentHTML = generateHTML(contentJSON, DOCUMENT_EDITOR_EXTENSIONS); return { diff --git a/packages/editor/src/core/hooks/use-collaborative-editor.ts b/packages/editor/src/core/hooks/use-collaborative-editor.ts index 9c436dff2..3b4b333e6 100644 --- a/packages/editor/src/core/hooks/use-collaborative-editor.ts +++ b/packages/editor/src/core/hooks/use-collaborative-editor.ts @@ -13,6 +13,7 @@ import { TCollaborativeEditorHookProps } from "@/types"; export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) => { const { + onAssetChange, onChange, onTransaction, disabledExtensions, @@ -106,6 +107,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) => forwardedRef, handleEditorReady, mentionHandler, + onAssetChange, onChange, onTransaction, placeholder, diff --git a/packages/editor/src/core/hooks/use-editor.ts b/packages/editor/src/core/hooks/use-editor.ts index 4c1b93d84..1979d46b1 100644 --- a/packages/editor/src/core/hooks/use-editor.ts +++ b/packages/editor/src/core/hooks/use-editor.ts @@ -1,23 +1,23 @@ import { DOMSerializer } from "@tiptap/pm/model"; -import { useEditor as useTiptapEditor } from "@tiptap/react"; +import { useEditorState, useEditor as useTiptapEditor } from "@tiptap/react"; import { useImperativeHandle, useEffect } from "react"; import * as Y from "yjs"; // components import { getEditorMenuItems } from "@/components/menus"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; -import { CORE_EDITOR_META } from "@/constants/meta"; // extensions import { CoreEditorExtensions } from "@/extensions"; // helpers import { getParagraphCount } from "@/helpers/common"; +import { getEditorRefHelpers } from "@/helpers/editor-ref"; import { getExtensionStorage } from "@/helpers/get-extension-storage"; import { insertContentAtSavedSelection } from "@/helpers/insert-content-at-cursor-position"; -import { IMarking, scrollSummary, scrollToNodeViaDOMCoordinates } from "@/helpers/scroll-to-node"; +import { scrollToNodeViaDOMCoordinates } from "@/helpers/scroll-to-node"; // props import { CoreEditorProps } from "@/props"; // types -import type { TDocumentEventsServer, TEditorCommands, TEditorHookProps } from "@/types"; +import type { TEditorCommands, TEditorHookProps } from "@/types"; export const useEditor = (props: TEditorHookProps) => { const { @@ -35,6 +35,7 @@ export const useEditor = (props: TEditorHookProps) => { id = "", initialValue, mentionHandler, + onAssetChange, onChange, onTransaction, placeholder, @@ -109,27 +110,26 @@ export const useEditor = (props: TEditorHookProps) => { editor.commands.updateAssetsUploadStatus?.(assetsUploadStatus); }, [editor, fileHandler.assetsUploadStatus]); + // subscribe to assets list changes + const assetsList = useEditorState({ + editor, + selector: ({ editor }) => ({ + assets: editor ? getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY)?.assetsList : [], + }), + }); + // trigger callback when assets list changes + useEffect(() => { + const assets = assetsList?.assets; + if (!assets || !onAssetChange) return; + onAssetChange(assets); + }, [assetsList?.assets, onAssetChange]); + useImperativeHandle( forwardedRef, () => ({ + ...getEditorRefHelpers({ editor, provider }), blur: () => editor?.commands.blur(), - scrollToNodeViaDOMCoordinates(behavior?: ScrollBehavior, pos?: number) { - const resolvedPos = pos ?? editor?.state.selection.from; - if (!editor || !resolvedPos) return; - scrollToNodeViaDOMCoordinates(editor, resolvedPos, behavior); - }, - getCurrentCursorPosition: () => editor?.state.selection.from, - clearEditor: (emitUpdate = false) => { - editor?.chain().setMeta(CORE_EDITOR_META.SKIP_FILE_DELETION, true).clearContent(emitUpdate).run(); - }, - setEditorValue: (content: string, emitUpdate = false) => { - editor?.commands.setContent(content, emitUpdate, { preserveWhitespace: true }); - }, - setEditorValueAtCursorPosition: (content: string) => { - if (editor?.state.selection) { - insertContentAtSavedSelection(editor, content); - } - }, + emitRealTimeUpdate: (message) => provider?.sendStateless(message), executeMenuItemCommand: (props) => { const { itemKey } = props; const editorItems = getEditorMenuItems(editor); @@ -143,83 +143,7 @@ export const useEditor = (props: TEditorHookProps) => { console.warn(`No command found for item: ${itemKey}`); } }, - isMenuItemActive: (props) => { - const { itemKey } = props; - const editorItems = getEditorMenuItems(editor); - - const getEditorMenuItem = (itemKey: TEditorCommands) => editorItems.find((item) => item.key === itemKey); - const item = getEditorMenuItem(itemKey); - if (!item) return false; - - return item.isActive(props); - }, - onHeadingChange: (callback: (headings: IMarking[]) => void) => { - // Subscribe to update event emitted from headers extension - editor?.on("update", () => { - const headings = getExtensionStorage(editor, CORE_EXTENSIONS.HEADINGS_LIST)?.headings; - if (headings) { - callback(headings); - } - }); - // Return a function to unsubscribe to the continuous transactions of - // the editor on unmounting the component that has subscribed to this - // method - return () => { - editor?.off("update"); - }; - }, - getHeadings: () => (editor ? getExtensionStorage(editor, CORE_EXTENSIONS.HEADINGS_LIST)?.headings : []), - onStateChange: (callback: () => void) => { - // Subscribe to editor state changes - editor?.on("transaction", () => { - callback(); - }); - - // Return a function to unsubscribe to the continuous transactions of - // the editor on unmounting the component that has subscribed to this - // method - return () => { - editor?.off("transaction"); - }; - }, - getMarkDown: (): string => { - const markdownOutput = editor?.storage.markdown.getMarkdown(); - return markdownOutput; - }, - getDocument: () => { - const documentBinary = provider?.document ? Y.encodeStateAsUpdate(provider?.document) : null; - const documentHTML = editor?.getHTML() ?? "

    "; - const documentJSON = editor?.getJSON() ?? null; - - return { - binary: documentBinary, - html: documentHTML, - json: documentJSON, - }; - }, - scrollSummary: (marking: IMarking): void => { - if (!editor) return; - scrollSummary(editor, marking); - }, - isEditorReadyToDiscard: () => - !!editor && getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY)?.uploadInProgress === false, - setFocusAtPosition: (position: number) => { - if (!editor || editor.isDestroyed) { - console.error("Editor reference is not available or has been destroyed."); - return; - } - try { - const docSize = editor.state.doc.content.size; - const safePosition = Math.max(0, Math.min(position, docSize)); - editor - .chain() - .insertContentAt(safePosition, [{ type: CORE_EXTENSIONS.PARAGRAPH }]) - .focus() - .run(); - } catch (error) { - console.error("An error occurred while setting focus at position:", error); - } - }, + getCurrentCursorPosition: () => editor?.state.selection.from, getSelectedText: () => { if (!editor) return null; @@ -253,18 +177,99 @@ export const useEditor = (props: TEditorHookProps) => { editor.chain().focus().deleteRange({ from, to }).insertContent(contentHTML).run(); } }, - getDocumentInfo: () => ({ - characters: editor?.storage?.characterCount?.characters?.() ?? 0, - paragraphs: getParagraphCount(editor?.state), - words: editor?.storage?.characterCount?.words?.() ?? 0, - }), + isEditorReadyToDiscard: () => + !!editor && getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY)?.uploadInProgress === false, + isMenuItemActive: (props) => { + const { itemKey } = props; + const editorItems = getEditorMenuItems(editor); + + const getEditorMenuItem = (itemKey: TEditorCommands) => editorItems.find((item) => item.key === itemKey); + const item = getEditorMenuItem(itemKey); + if (!item) return false; + + return item.isActive(props); + }, + listenToRealTimeUpdate: () => provider && { on: provider.on.bind(provider), off: provider.off.bind(provider) }, + onDocumentInfoChange: (callback) => { + const handleDocumentInfoChange = () => { + if (!editor) return; + callback({ + characters: editor ? getExtensionStorage(editor, CORE_EXTENSIONS.CHARACTER_COUNT)?.characters?.() : 0, + paragraphs: getParagraphCount(editor?.state), + words: editor ? getExtensionStorage(editor, CORE_EXTENSIONS.CHARACTER_COUNT)?.words?.() : 0, + }); + }; + + // Subscribe to update event emitted from character count extension + editor?.on("update", handleDocumentInfoChange); + // Return a function to unsubscribe to the continuous transactions of + // the editor on unmounting the component that has subscribed to this + // method + return () => { + editor?.off("update", handleDocumentInfoChange); + }; + }, + onHeadingChange: (callback) => { + const handleHeadingChange = () => { + if (!editor) return; + const headings = getExtensionStorage(editor, CORE_EXTENSIONS.HEADINGS_LIST)?.headings; + if (headings) { + callback(headings); + } + }; + + // Subscribe to update event emitted from headers extension + editor?.on("update", handleHeadingChange); + // Return a function to unsubscribe to the continuous transactions of + // the editor on unmounting the component that has subscribed to this + // method + return () => { + editor?.off("update", handleHeadingChange); + }; + }, + onStateChange: (callback) => { + // Subscribe to editor state changes + editor?.on("transaction", callback); + + // Return a function to unsubscribe to the continuous transactions of + // the editor on unmounting the component that has subscribed to this + // method + return () => { + editor?.off("transaction", callback); + }; + }, + scrollToNodeViaDOMCoordinates(behavior, pos) { + const resolvedPos = pos ?? editor?.state.selection.from; + if (!editor || !resolvedPos) return; + scrollToNodeViaDOMCoordinates(editor, resolvedPos, behavior); + }, + setEditorValueAtCursorPosition: (content) => { + if (editor?.state.selection) { + insertContentAtSavedSelection(editor, content); + } + }, + setFocusAtPosition: (position) => { + if (!editor || editor.isDestroyed) { + console.error("Editor reference is not available or has been destroyed."); + return; + } + try { + const docSize = editor.state.doc.content.size; + const safePosition = Math.max(0, Math.min(position, docSize)); + editor + .chain() + .insertContentAt(safePosition, [{ type: CORE_EXTENSIONS.PARAGRAPH }]) + .focus() + .run(); + } catch (error) { + console.error("An error occurred while setting focus at position:", error); + } + }, setProviderDocument: (value) => { const document = provider?.document; if (!document) return; Y.applyUpdate(document, value); }, - emitRealTimeUpdate: (message: TDocumentEventsServer) => provider?.sendStateless(message), - listenToRealTimeUpdate: () => provider && { on: provider.on.bind(provider), off: provider.off.bind(provider) }, }), [editor] ); diff --git a/packages/editor/src/core/hooks/use-read-only-editor.ts b/packages/editor/src/core/hooks/use-read-only-editor.ts index d259470ac..43e9c9581 100644 --- a/packages/editor/src/core/hooks/use-read-only-editor.ts +++ b/packages/editor/src/core/hooks/use-read-only-editor.ts @@ -1,13 +1,9 @@ import { useEditor as useTiptapEditor } from "@tiptap/react"; import { useImperativeHandle, useEffect } from "react"; -import * as Y from "yjs"; -// constants -import { CORE_EDITOR_META } from "@/constants/meta"; // extensions import { CoreReadOnlyEditorExtensions } from "@/extensions"; // helpers -import { getParagraphCount } from "@/helpers/common"; -import { IMarking, scrollSummary } from "@/helpers/scroll-to-node"; +import { getEditorRefHelpers } from "@/helpers/editor-ref"; // props import { CoreReadOnlyEditorProps } from "@/props"; // types @@ -30,7 +26,7 @@ export const useReadOnlyEditor = (props: TReadOnlyEditorHookProps) => { const editor = useTiptapEditor({ editable: false, - immediatelyRender: true, + immediatelyRender: false, shouldRerenderOnTransaction: false, content: typeof initialValue === "string" && initialValue.trim() !== "" ? initialValue : "

    ", parseOptions: { preserveWhitespace: true }, @@ -63,38 +59,7 @@ export const useReadOnlyEditor = (props: TReadOnlyEditorHookProps) => { if (editor && !editor.isDestroyed) editor?.commands.setContent(initialValue, false, { preserveWhitespace: true }); }, [editor, initialValue]); - useImperativeHandle(forwardedRef, () => ({ - clearEditor: (emitUpdate = false) => { - editor?.chain().setMeta(CORE_EDITOR_META.SKIP_FILE_DELETION, true).clearContent(emitUpdate).run(); - }, - setEditorValue: (content: string, emitUpdate = false) => { - editor?.commands.setContent(content, emitUpdate, { preserveWhitespace: true }); - }, - getMarkDown: (): string => { - const markdownOutput = editor?.storage.markdown.getMarkdown(); - return markdownOutput; - }, - getDocument: () => { - const documentBinary = provider?.document ? Y.encodeStateAsUpdate(provider?.document) : null; - const documentHTML = editor?.getHTML() ?? "

    "; - const documentJSON = editor?.getJSON() ?? null; - - return { - binary: documentBinary, - html: documentHTML, - json: documentJSON, - }; - }, - scrollSummary: (marking: IMarking): void => { - if (!editor) return; - scrollSummary(editor, marking); - }, - getDocumentInfo: () => ({ - characters: editor.storage?.characterCount?.characters?.() ?? 0, - paragraphs: getParagraphCount(editor.state), - words: editor.storage?.characterCount?.words?.() ?? 0, - }), - })); + useImperativeHandle(forwardedRef, () => getEditorRefHelpers({ editor, provider })); if (!editor) { return null; diff --git a/packages/editor/src/core/plugins/drag-handle.ts b/packages/editor/src/core/plugins/drag-handle.ts index 4a534bc4c..607837e4e 100644 --- a/packages/editor/src/core/plugins/drag-handle.ts +++ b/packages/editor/src/core/plugins/drag-handle.ts @@ -16,7 +16,7 @@ const generalSelectors = [ "blockquote", "h1.editor-heading-block, h2.editor-heading-block, h3.editor-heading-block, h4.editor-heading-block, h5.editor-heading-block, h6.editor-heading-block", "[data-type=horizontalRule]", - ".table-wrapper", + "table", ".issue-embed", ".image-component", ".image-upload-component", @@ -65,7 +65,9 @@ const isScrollable = (node: HTMLElement | SVGElement) => { }); }; -const getScrollParent = (node: HTMLElement | SVGElement) => { +const getScrollParent = (node: HTMLElement | SVGElement | null): Element | null => { + if (!node) return null; + if (scrollParentCache.has(node)) { return scrollParentCache.get(node); } @@ -90,7 +92,7 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => { for (const elem of elements) { // Check for table wrapper first - if (elem.matches(".table-wrapper")) { + if (elem.matches("table")) { return elem; } @@ -99,7 +101,7 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => { } // Skip table cells - if (elem.closest(".table-wrapper")) { + if (elem.closest("table")) { continue; } @@ -137,32 +139,7 @@ export const DragHandlePlugin = (options: SideMenuPluginProps): SideMenuHandleOp let isDraggedOutsideWindow: "top" | "bottom" | boolean = false; let isMouseInsideWhileDragging = false; let currentScrollSpeed = 0; - - const handleClick = (event: MouseEvent, view: EditorView) => { - handleNodeSelection(event, view, false, options); - }; - - const handleDragStart = (event: DragEvent, view: EditorView) => { - const { listType: listTypeFromDragStart } = handleNodeSelection(event, view, true, options) ?? {}; - if (listTypeFromDragStart) { - listType = listTypeFromDragStart; - } - isDragging = true; - lastClientY = event.clientY; - scroll(); - }; - - const handleDragEnd = (event: TEvent, view?: EditorView) => { - event.preventDefault(); - isDragging = false; - isMouseInsideWhileDragging = false; - if (scrollAnimationFrame) { - cancelAnimationFrame(scrollAnimationFrame); - scrollAnimationFrame = null; - } - - view?.dom.classList.remove("dragging"); - }; + let dragHandleElement: HTMLElement | null = null; function scroll() { if (!isDragging) { @@ -170,7 +147,7 @@ export const DragHandlePlugin = (options: SideMenuPluginProps): SideMenuHandleOp return; } - const scrollableParent = getScrollParent(dragHandleElement); + const scrollableParent = getScrollParent(dragHandleElement!); if (!scrollableParent) return; const scrollRegionUp = options.scrollThreshold.up; @@ -199,7 +176,32 @@ export const DragHandlePlugin = (options: SideMenuPluginProps): SideMenuHandleOp scrollAnimationFrame = requestAnimationFrame(scroll); } - let dragHandleElement: HTMLElement | null = null; + const handleClick = (event: MouseEvent, view: EditorView) => { + handleNodeSelection(event, view, false, options); + }; + + const handleDragStart = (event: DragEvent, view: EditorView) => { + const { listType: listTypeFromDragStart } = handleNodeSelection(event, view, true, options) ?? {}; + if (listTypeFromDragStart) { + listType = listTypeFromDragStart; + } + isDragging = true; + lastClientY = event.clientY; + scroll(); + }; + + const handleDragEnd = (event: TEvent, view?: EditorView) => { + event.preventDefault(); + isDragging = false; + isMouseInsideWhileDragging = false; + if (scrollAnimationFrame) { + cancelAnimationFrame(scrollAnimationFrame); + scrollAnimationFrame = null; + } + + view?.dom.classList.remove("dragging"); + }; + // drag handle view actions const showDragHandle = () => dragHandleElement?.classList.remove("drag-handle-hidden"); const hideDragHandle = () => { diff --git a/packages/editor/src/core/plugins/file/delete.ts b/packages/editor/src/core/plugins/file/delete.ts index ac69b1819..427b100b7 100644 --- a/packages/editor/src/core/plugins/file/delete.ts +++ b/packages/editor/src/core/plugins/file/delete.ts @@ -57,6 +57,10 @@ export const TrackFileDeletionPlugin = (editor: Editor, deleteHandler: TFileHand if (!nodeFileSetDetails || !src) return; try { editor.storage[nodeType][nodeFileSetDetails.fileSetName]?.set(src, true); + // update assets list storage value + editor.commands.updateAssetsList?.({ + idToRemove: node.attrs.id, + }); await deleteHandler(src); } catch (error) { console.error("Error deleting file via delete utility plugin:", error); diff --git a/packages/editor/src/core/plugins/file/restore.ts b/packages/editor/src/core/plugins/file/restore.ts index 04a4c295c..bb4eb2afb 100644 --- a/packages/editor/src/core/plugins/file/restore.ts +++ b/packages/editor/src/core/plugins/file/restore.ts @@ -2,6 +2,8 @@ import { Editor } from "@tiptap/core"; import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +// helpers +import { CORE_ASSETS_META_DATA_RECORD } from "@/helpers/assets"; // plane editor imports import { NODE_FILE_MAP } from "@/plane-editor/constants/utility"; // types @@ -42,6 +44,13 @@ export const TrackFileRestorationPlugin = (editor: Editor, restoreHandler: TFile if (!isAValidNode) return; if (pos < 0 || pos > newState.doc.content.size) return; if (oldFileSources[nodeType]?.has(node.attrs.src)) return; + // update assets list storage value + const assetMetaData = CORE_ASSETS_META_DATA_RECORD[nodeType]?.(node.attrs); + if (assetMetaData) { + editor.commands.updateAssetsList?.({ + asset: assetMetaData, + }); + } // if the src is just a id (private bucket), then we don't need to handle restore from here but // only while it fails to load if (nodeType === CORE_EXTENSIONS.CUSTOM_IMAGE && !node.attrs.src?.startsWith("http")) return; diff --git a/packages/editor/src/core/types/asset.ts b/packages/editor/src/core/types/asset.ts new file mode 100644 index 000000000..5760da157 --- /dev/null +++ b/packages/editor/src/core/types/asset.ts @@ -0,0 +1,14 @@ +// constants +import { CORE_EXTENSIONS } from "@/constants/extension"; +// plane editor imports +import { TAdditionalEditorAsset } from "@/plane-editor/types/asset"; + +export type TEditorImageAsset = { + href: string; + id: string; + name: string; + src: string; + type: CORE_EXTENSIONS.IMAGE | CORE_EXTENSIONS.CUSTOM_IMAGE; +}; + +export type TEditorAsset = TEditorImageAsset | TAdditionalEditorAsset; diff --git a/packages/editor/src/core/types/config.ts b/packages/editor/src/core/types/config.ts index 60ccfa841..7ef685ad0 100644 --- a/packages/editor/src/core/types/config.ts +++ b/packages/editor/src/core/types/config.ts @@ -3,6 +3,7 @@ import { TWebhookConnectionQueryParams } from "@plane/types"; export type TReadOnlyFileHandler = { checkIfAssetExists: (assetId: string) => Promise; + getAssetDownloadSrc: (path: string) => Promise; getAssetSrc: (path: string) => Promise; restore: (assetSrc: string) => Promise; }; diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index cf3d7d2c7..b91d5fdee 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -1,5 +1,5 @@ -import type { Extensions, JSONContent } from "@tiptap/core"; -import type { Selection } from "@tiptap/pm/state"; +import { Extensions, JSONContent } from "@tiptap/core"; +import { Selection } from "@tiptap/pm/state"; // extension types import type { TTextAlign } from "@/extensions"; // helpers @@ -10,6 +10,7 @@ import type { TDisplayConfig, TDocumentEventEmitter, TDocumentEventsServer, + TEditorAsset, TEmbedConfig, TExtensions, TFileHandler, @@ -46,7 +47,8 @@ export type TEditorCommands = | "background-color" | "text-align" | "callout" - | "attachment"; + | "attachment" + | "emoji"; export type TCommandExtraProps = { image: { @@ -75,41 +77,45 @@ type TCommandWithPropsWithItemKey = T extends keyof T ? { itemKey: T } & TCommandExtraProps[T] : { itemKey: T }; +export type TDocumentInfo = { + characters: number; + paragraphs: number; + words: number; +}; + // editor refs export type EditorReadOnlyRefApi = { - getMarkDown: () => string; + clearEditor: (emitUpdate?: boolean) => void; getDocument: () => { binary: Uint8Array | null; html: string; json: JSONContent | null; }; - clearEditor: (emitUpdate?: boolean) => void; - setEditorValue: (content: string, emitUpdate?: boolean) => void; + getDocumentInfo: () => TDocumentInfo; + getHeadings: () => IMarking[]; + getMarkDown: () => string; scrollSummary: (marking: IMarking) => void; - getDocumentInfo: () => { - characters: number; - paragraphs: number; - words: number; - }; + setEditorValue: (content: string, emitUpdate?: boolean) => void; }; export interface EditorRefApi extends EditorReadOnlyRefApi { blur: () => void; - scrollToNodeViaDOMCoordinates: (behavior?: ScrollBehavior, position?: number) => void; - getCurrentCursorPosition: () => number | undefined; - setEditorValueAtCursorPosition: (content: string) => void; + emitRealTimeUpdate: (action: TDocumentEventsServer) => void; executeMenuItemCommand: (props: TCommandWithPropsWithItemKey) => void; - isMenuItemActive: (props: TCommandWithPropsWithItemKey) => boolean; - onStateChange: (callback: () => void) => () => void; - setFocusAtPosition: (position: number) => void; - isEditorReadyToDiscard: () => boolean; + getCurrentCursorPosition: () => number | undefined; getSelectedText: () => string | null; insertText: (contentHTML: string, insertOnNextLine?: boolean) => void; - setProviderDocument: (value: Uint8Array) => void; - onHeadingChange: (callback: (headings: IMarking[]) => void) => () => void; - getHeadings: () => IMarking[]; - emitRealTimeUpdate: (action: TDocumentEventsServer) => void; + isEditorReadyToDiscard: () => boolean; + isMenuItemActive: (props: TCommandWithPropsWithItemKey) => boolean; listenToRealTimeUpdate: () => TDocumentEventEmitter | undefined; + onDocumentInfoChange: (callback: (documentInfo: TDocumentInfo) => void) => () => void; + onHeadingChange: (callback: (headings: IMarking[]) => void) => () => void; + onStateChange: (callback: () => void) => () => void; + // eslint-disable-next-line no-undef + scrollToNodeViaDOMCoordinates: (behavior?: ScrollBehavior, position?: number) => void; + setEditorValueAtCursorPosition: (content: string) => void; + setFocusAtPosition: (position: number) => void; + setProviderDocument: (value: Uint8Array) => void; } // editor props @@ -128,6 +134,7 @@ export interface IEditorProps { id: string; initialValue: string; mentionHandler: TMentionHandler; + onAssetChange?: (assets: TEditorAsset[]) => void; onChange?: (json: object, html: string) => void; onEnterKeyPress?: (e?: any) => void; onTransaction?: () => void; @@ -137,9 +144,11 @@ export interface IEditorProps { } export type ILiteTextEditorProps = IEditorProps; -export interface IRichTextEditorProps extends IEditorProps { + +export type IRichTextEditorProps = IEditorProps & { dragDropEnabled?: boolean; -} + editable: boolean; +}; export interface ICollaborativeDocumentEditorProps extends Omit { @@ -172,8 +181,6 @@ export interface IReadOnlyEditorProps export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps; -export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps; - export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps { embedHandler: TEmbedConfig; } diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts index 2224935ca..40974981b 100644 --- a/packages/editor/src/core/types/hook.ts +++ b/packages/editor/src/core/types/hook.ts @@ -18,6 +18,7 @@ export type TEditorHookProps = TCoreHookProps & | "forwardedRef" | "id" | "mentionHandler" + | "onAssetChange" | "onChange" | "onTransaction" | "placeholder" @@ -38,6 +39,7 @@ export type TCollaborativeEditorHookProps = TCoreHookProps & | "forwardedRef" | "id" | "mentionHandler" + | "onAssetChange" | "onChange" | "onTransaction" | "placeholder" diff --git a/packages/editor/src/core/types/index.ts b/packages/editor/src/core/types/index.ts index 619fa0c78..cfa67ba97 100644 --- a/packages/editor/src/core/types/index.ts +++ b/packages/editor/src/core/types/index.ts @@ -1,4 +1,5 @@ export * from "./ai"; +export * from "./asset"; export * from "./collaboration"; export * from "./config"; export * from "./editor"; diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index fec933f91..9cb374dce 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -13,10 +13,9 @@ export { LiteTextEditorWithRef, LiteTextReadOnlyEditorWithRef, RichTextEditorWithRef, - RichTextReadOnlyEditorWithRef, } from "@/components/editors"; -export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; +export { isCellSelection } from "@/extensions/table/table/utilities/helpers"; // constants export * from "@/constants/common"; @@ -35,5 +34,8 @@ export { useEditor } from "@/hooks/use-editor"; export { type IMarking, useEditorMarkings } from "@/hooks/use-editor-markings"; export { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; +export { CORE_EXTENSIONS } from "@/constants/extension"; +export { ADDITIONAL_EXTENSIONS } from "@/plane-editor/constants/extensions"; + // types export * from "@/types"; diff --git a/packages/editor/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css index 7db6ed875..7b9577cc4 100644 --- a/packages/editor/src/styles/drag-drop.css +++ b/packages/editor/src/styles/drag-drop.css @@ -35,7 +35,7 @@ } /* end ai handle */ -.ProseMirror:not(.dragging) .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image) { +.ProseMirror:not(.dragging) .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image):not(.table-wrapper) { position: relative; cursor: grab; outline: none !important; @@ -61,7 +61,8 @@ } &.node-imageComponent, - &.node-image { + &.node-image, + &.table-wrapper { --horizontal-offset: 0px; &::after { diff --git a/packages/editor/src/styles/editor.css b/packages/editor/src/styles/editor.css index ba910d144..e4aabde9e 100644 --- a/packages/editor/src/styles/editor.css +++ b/packages/editor/src/styles/editor.css @@ -490,3 +490,13 @@ p.editor-paragraph-block + p.editor-paragraph-block { background-color: var(--editor-colors-purple-background); } /* end background colors */ + +/* emoji styles */ +span[data-name][data-type="emoji"] img { + display: inline !important; + vertical-align: middle; + margin: 0; + padding: 0; + max-width: 1.25em; + max-height: 1.25em; +} diff --git a/packages/editor/src/styles/table.css b/packages/editor/src/styles/table.css index b4a1ab820..ba5834abb 100644 --- a/packages/editor/src/styles/table.css +++ b/packages/editor/src/styles/table.css @@ -1,115 +1,149 @@ .table-wrapper { overflow-x: auto; - width: fit-content; - max-width: 100%; -} + padding-bottom: 26px; -.table-wrapper table { - border-collapse: collapse; - table-layout: fixed; - margin: 0.5rem 0 1rem 0; - border: 1px solid rgba(var(--color-border-200)); - width: 100%; -} + table { + position: relative; + border-collapse: collapse; + table-layout: fixed; + margin: 0.5rem 0 0 0; + border: 1px solid rgba(var(--color-border-200)); + width: 100%; -.table-wrapper table td, -.table-wrapper table th { - min-width: 1em; - border: 1px solid rgba(var(--color-border-200)); - padding: 7px 10px; - vertical-align: top; - box-sizing: border-box; - position: relative; - transition: background-color 0.3s ease; - - > * { - margin-bottom: 0; - } -} - -.table-wrapper table { - th { - font-weight: 500; - text-align: left; - } - - tr[background="none"], - tr:not([background]) { + td, th { - background-color: rgba(var(--color-background-90)); + min-width: 1em; + border: 1px solid rgba(var(--color-border-300)); + padding: 7px 10px; + vertical-align: top; + box-sizing: border-box; + position: relative; + transition: background-color 0.3s ease; + + > * { + margin-bottom: 0; + } + + /* Selected cell outline */ + &.selectedCell { + user-select: none; + + &::after { + position: absolute; + content: ""; + top: -1px; + left: -1px; + height: calc(100% + 2px); + width: calc(100% + 2px); + } + + &.selectedCell-border-top::after { + border-top: 2px solid rgba(var(--color-primary-100)); + } + + &.selectedCell-border-left::after { + border-left: 2px solid rgba(var(--color-primary-100)); + } + + &.selectedCell-border-bottom::after { + border-bottom: 2px solid rgba(var(--color-primary-100)); + } + + &.selectedCell-border-right::after { + border-right: 2px solid rgba(var(--color-primary-100)); + } + } + /* End selected cell outline */ + } + + th { + font-weight: 500; + text-align: left; + } + + tr[background="none"], + tr:not([background]) { + th { + background-color: rgba(var(--color-background-90)); + } } } + + /* Selected status */ + &.ProseMirror-selectednode { + table { + background-color: rgba(var(--color-primary-100), 0.2); + } + } + /* End selected status */ } -.table-wrapper table .selectedCell { - outline: 0.5px solid rgba(var(--color-primary-100)); -} - -/* table dropdown */ +/* Column resizer */ .table-wrapper table .column-resize-handle { position: absolute; - right: 0; - top: 0; + right: -1px; + top: -1px; width: 2px; - height: 100%; + height: calc(100% + 2px); z-index: 5; background-color: rgba(var(--color-primary-100)); pointer-events: none; } +/* End column resizer */ .table-wrapper .table-controls { position: absolute; -} -.table-wrapper .table-controls .columns-control, -.table-wrapper .table-controls .rows-control { - transition: opacity ease-in 100ms; - position: absolute; - z-index: 5; - display: flex; - justify-content: center; - align-items: center; -} + .columns-control, + .rows-control { + transition: opacity ease-in 100ms; + position: absolute; + z-index: 5; + display: flex; + justify-content: center; + align-items: center; + } -.table-wrapper .table-controls .columns-control { - height: 20px; - transform: translateY(-50%); -} + .columns-control { + height: 20px; + transform: translateY(-50%); -.table-wrapper .table-controls .columns-control .columns-control-div { - color: white; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath fill='%238F95B2' d='M4.5 10.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S6 12.825 6 12s-.675-1.5-1.5-1.5zm15 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S21 12.825 21 12s-.675-1.5-1.5-1.5zm-7.5 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z'/%3E%3C/svg%3E"); - width: 30px; - height: 15px; -} + .columns-control-div { + color: white; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath fill='%238F95B2' d='M4.5 10.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S6 12.825 6 12s-.675-1.5-1.5-1.5zm15 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5S21 12.825 21 12s-.675-1.5-1.5-1.5zm-7.5 0c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z'/%3E%3C/svg%3E"); + width: 30px; + height: 15px; + } + } -.table-wrapper .table-controls .rows-control { - width: 20px; - transform: translateX(-50%); - left: -8px; -} + .rows-control { + width: 20px; + transform: translateX(-50%); + left: -8px; -.table-wrapper .table-controls .rows-control .rows-control-div { - color: white; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath fill='%238F95B2' d='M12 3c-.825 0-1.5.675-1.5 1.5S11.175 6 12 6s1.5-.675 1.5-1.5S12.825 3 12 3zm0 15c-.825 0-1.5.675-1.5 1.5S11.175 21 12 21s1.5-.675 1.5-1.5S12.825 18 12 18zm0-7.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z'/%3E%3C/svg%3E"); - height: 30px; - width: 15px; -} + .rows-control-div { + color: white; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath fill='%238F95B2' d='M12 3c-.825 0-1.5.675-1.5 1.5S11.175 6 12 6s1.5-.675 1.5-1.5S12.825 3 12 3zm0 15c-.825 0-1.5.675-1.5 1.5S11.175 21 12 21s1.5-.675 1.5-1.5S12.825 18 12 18zm0-7.5c-.825 0-1.5.675-1.5 1.5s.675 1.5 1.5 1.5 1.5-.675 1.5-1.5-.675-1.5-1.5-1.5z'/%3E%3C/svg%3E"); + height: 30px; + width: 15px; + } + } -.table-wrapper .table-controls .rows-control-div, -.table-wrapper .table-controls .columns-control-div { - background-color: rgba(var(--color-background-80)); - border: 0.5px solid rgba(var(--color-border-200)); - border-radius: 4px; - background-size: 1.25rem; - background-repeat: no-repeat; - background-position: center; - transition: - transform ease-out 100ms, - background-color ease-out 100ms; - outline: none; - box-shadow: rgba(var(--color-shadow-2xs)); - cursor: pointer; + .columns-control-div, + .rows-control-div { + background-color: rgba(var(--color-background-80)); + border: 0.5px solid rgba(var(--color-border-200)); + border-radius: 4px; + background-size: 1.25rem; + background-repeat: no-repeat; + background-position: center; + transition: + transform ease-out 100ms, + background-color ease-out 100ms; + outline: none; + box-shadow: rgba(var(--color-shadow-2xs)); + cursor: pointer; + } } .resize-cursor .table-wrapper .table-controls .rows-control, @@ -119,3 +153,67 @@ opacity: 0; pointer-events: none; } + +/* Insert buttons */ +.table-wrapper { + .table-column-insert-button, + .table-row-insert-button { + position: absolute; + background-color: rgba(var(--color-background-90)); + color: rgba(var(--color-text-300)); + border: 1px solid rgba(var(--color-border-200)); + border-radius: 4px; + display: grid; + place-items: center; + opacity: 0; + pointer-events: none; + outline: none; + z-index: 10; + transition: all 0.2s ease; + + &:hover { + background-color: rgba(var(--color-background-80)); + color: rgba(var(--color-text-100)); + } + + &.dragging { + opacity: 1; + pointer-events: auto; + background-color: rgba(var(--color-primary-100), 0.2); + color: rgba(var(--color-text-100)); + } + + svg { + width: 12px; + height: 12px; + } + } + + .table-column-insert-button { + top: 0; + right: -16px; + width: 16px; + height: 100%; + transform: translateX(50%); + cursor: col-resize; + } + + .table-row-insert-button { + bottom: -16px; + left: 0; + width: 100%; + height: 16px; + transform: translateY(50%); + cursor: row-resize; + } + + /* Show buttons on table hover */ + &:hover { + .table-column-insert-button, + .table-row-insert-button { + opacity: 1; + pointer-events: auto; + } + } +} +/* End insert buttons */ diff --git a/packages/editor/src/styles/variables.css b/packages/editor/src/styles/variables.css index 6d6e2d9b6..f03808c1a 100644 --- a/packages/editor/src/styles/variables.css +++ b/packages/editor/src/styles/variables.css @@ -169,19 +169,35 @@ #page-content-container { container-name: page-content-container; container-type: inline-size; -} -.editor-container.document-editor { - --editor-content-width: var(--normal-content-width); + .frame-renderer { + --editor-content-width: var(--normal-content-width); - &.wide-layout { - --editor-content-width: var(--wide-content-width); - } + &.wide-layout { + --editor-content-width: var(--wide-content-width); + } - .ProseMirror { - max-width: var(--editor-content-width); - margin: 0 auto; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + .editor-container.page-title-editor .ProseMirror, + .document-editor-loader { + max-width: var(--editor-content-width); + margin: 0 auto; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + } + + .editor-container.document-editor .ProseMirror { + & > *:not(.editor-full-width-block) { + max-width: var(--editor-content-width); + margin-left: auto !important; + margin-right: auto !important; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + } + + & > .editor-full-width-block { + max-width: 100%; + padding-inline-start: calc((100% - var(--editor-content-width)) / 2); + padding-inline-end: var(--wide-content-margin); + } + } } } @@ -210,7 +226,8 @@ /* keep a static padding of 96px for wide layouts for container width >912px and <1344px */ @container page-content-container (min-width: 912px) and (max-width: 1344px) { - .editor-container.wide-layout, + #page-content-container .frame-renderer.wide-layout .editor-container, + #page-content-container .frame-renderer.wide-layout .document-editor-loader, .page-header-container { padding-left: var(--wide-content-margin); padding-right: var(--wide-content-margin); @@ -219,7 +236,8 @@ /* keep a static padding of 20px for wide layouts for container width <912px */ @container page-content-container (max-width: 912px) { - .editor-container.wide-layout, + #page-content-container .frame-renderer.wide-layout .editor-container, + #page-content-container .frame-renderer.wide-layout .document-editor-loader, .page-header-container { padding-left: var(--normal-content-margin); padding-right: var(--normal-content-margin); @@ -228,7 +246,8 @@ /* keep a static padding of 20px for normal layouts for container width <760px */ @container page-content-container (max-width: 760px) { - .editor-container:not(.wide-layout), + #page-content-container .frame-renderer:not(.wide-layout) .editor-container, + #page-content-container .frame-renderer:not(.wide-layout) .document-editor-loader, .page-header-container { padding-left: var(--normal-content-margin); padding-right: var(--normal-content-margin); diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index 58b8640e6..3bf34d969 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -1,16 +1,19 @@ { "compilerOptions": { "jsx": "react-jsx", - "lib": ["ES2015", "DOM"], + "lib": ["ES2022", "DOM"], "module": "ESNext", - "moduleResolution": "Node", - "target": "ES6", + "moduleResolution": "bundler", + "noEmit": true, + "skipLibCheck": true, "sourceMap": true, + "target": "ESNext", + "types": ["node"], "baseUrl": ".", "paths": { - "@/*": ["src/core/*"], - "@/styles/*": ["src/styles/*"], - "@/plane-editor/*": ["src/ce/*"] + "@/*": ["./src/core/*"], + "@/styles/*": ["./src/styles/*"], + "@/plane-editor/*": ["./src/ce/*"] }, "strictNullChecks": true, "allowSyntheticDefaultImports": true diff --git a/packages/editor/tsup.config.ts b/packages/editor/tsup.config.ts index c378c0b2b..1089c00b1 100644 --- a/packages/editor/tsup.config.ts +++ b/packages/editor/tsup.config.ts @@ -1,11 +1,14 @@ -import { defineConfig, Options } from "tsup"; +import { defineConfig } from "tsup"; -export default defineConfig((options: Options) => ({ +export default defineConfig({ entry: ["src/index.ts", "src/lib.ts"], - format: ["cjs", "esm"], + outDir: "dist", + format: ["esm", "cjs"], dts: true, - clean: false, - external: ["react"], + clean: true, + external: ["react", "react-dom"], injectStyle: true, - ...options, -})); + splitting: true, + treeshake: true, + minify: true, +}); diff --git a/packages/eslint-config/next.js b/packages/eslint-config/next.js index 543cd131a..a2da66010 100644 --- a/packages/eslint-config/next.js +++ b/packages/eslint-config/next.js @@ -52,7 +52,7 @@ module.exports = { }, ], "import/order": [ - "error", + "warn", { groups: ["builtin", "external", "internal", "parent", "sibling"], pathGroups: [ @@ -80,6 +80,11 @@ module.exports = { pattern: "@/**", group: "internal", }, + { + pattern: "public/**", + group: "internal", + position: "after", + }, ], pathGroupsExcludedImportTypes: ["builtin", "internal", "react"], alphabetize: { diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 98a831bbc..29683df8e 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,7 +1,7 @@ { "name": "@plane/eslint-config", "private": true, - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "files": [ "library.js", diff --git a/packages/hooks/.eslintrc.js b/packages/hooks/.eslintrc.js index 558b8f76e..b11b7bb6d 100644 --- a/packages/hooks/.eslintrc.js +++ b/packages/hooks/.eslintrc.js @@ -3,7 +3,4 @@ module.exports = { root: true, extends: ["@plane/eslint-config/library.js"], parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, }; diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 52b57de7e..ddaefb9c8 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@plane/hooks", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "React hooks that are shared across multiple apps internally", "private": true, @@ -11,9 +11,14 @@ "dist/**" ], "scripts": { - "build": "tsup ./src/index.ts --format esm,cjs --dts --external react --minify", - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "build": "tsup --minify", + "dev": "tsup --watch", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "dependencies": { "react": "^18.3.1" diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 11c33cfa4..a71e06bf5 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -1,3 +1,4 @@ +export * from "./use-hash-scroll"; export * from "./use-local-storage"; export * from "./use-outside-click-detector"; export * from "./use-platform-os"; diff --git a/packages/hooks/src/use-hash-scroll.ts b/packages/hooks/src/use-hash-scroll.ts new file mode 100644 index 000000000..8265b86d9 --- /dev/null +++ b/packages/hooks/src/use-hash-scroll.ts @@ -0,0 +1,128 @@ +import { useCallback, useEffect, useState } from "react"; + +type TArgs = { + elementId: string; + pathname: string; + scrollDelay?: number; +}; + +type TReturnType = { + isHashMatch: boolean; + hashIds: string[]; + scrollToElement: () => boolean; +}; + +/** + * Custom hook for handling hash-based scrolling to a specific element + * Supports multiple IDs in URL hash (comma-separated, space-separated, or other delimiters) + * + * @param {TArgs} args - The ID of the element to scroll to + * @returns {TReturnType} Object containing hash match status and scroll function + */ +export const useHashScroll = (args: TArgs): TReturnType => { + const { elementId, pathname, scrollDelay = 200 } = args; + // State to track if the current hash contains the provided element ID + const [isHashMatch, setIsHashMatch] = useState(false); + // State to track all IDs found in the hash + const [hashIds, setHashIds] = useState([]); + + /** + * Scrolls to the element with the provided ID + * @returns {boolean} - Whether the scroll was successful + */ + const scrollToElement = useCallback((): boolean => { + try { + const element = document.getElementById(elementId); + + if (element) { + setTimeout(() => { + element.scrollIntoView({ + behavior: "smooth", + block: "nearest", + }); + }, scrollDelay); + + return true; + } + + return false; + } catch (error) { + console.warn("Hash scroll error:", error); + return false; + } + }, [elementId, scrollDelay]); + + /** + * Extracts multiple IDs from hash string + * Supports various delimiters: comma, space, pipe, semicolon + * @param {string} hashString - The hash part of the URL + * @returns {string[]} - Array of clean ID strings + */ + const extractIdsFromHash = (hashString: string | null): string[] => { + if (!hashString) return []; + + // Split by common delimiters and clean up + return hashString + .split(/[,\s|;]+/) // Split by comma, space, pipe, or semicolon + .map((id) => id.trim()) // Remove whitespace + .filter((id) => id.length > 0); // Remove empty strings + }; + + /** + * Get current hash from window.location + * @returns {string | null} - Current hash without the # symbol + */ + const getCurrentHash = (): string | null => { + if (typeof window === "undefined") return null; + const hash = window.location.hash; + return hash ? hash.slice(1) : null; // Remove the # symbol + }; + + // Effect to handle hash changes and initial load + useEffect(() => { + if (!elementId) { + setIsHashMatch(false); + setHashIds([]); + return; + } + + const handleHashChange = () => { + const hash = getCurrentHash(); + + // Extract all IDs from the hash + const idsInHash = extractIdsFromHash(hash); + setHashIds(idsInHash); + + // Check if provided element ID is present in the hash + const hashMatches = idsInHash.includes(elementId); + setIsHashMatch(hashMatches); + + // If hash matches, attempt to scroll to the element + if (hashMatches) { + scrollToElement(); + } + }; + + // Handle initial load + handleHashChange(); + + // Listen for hash changes + window.addEventListener("hashchange", handleHashChange); + + return () => { + window.removeEventListener("hashchange", handleHashChange); + }; + }, [elementId, pathname, scrollToElement]); // Include pathname to handle route changes + + // Return object with hash match status and utility functions + return { + // Whether the current URL hash contains the provided element ID + isHashMatch, + + // Array of all IDs found in the current hash + hashIds, + + // Manually trigger scroll to the element + scrollToElement, + }; +}; diff --git a/packages/hooks/src/use-local-storage.tsx b/packages/hooks/src/use-local-storage.tsx index f04e0e71b..0aa8bfcc5 100644 --- a/packages/hooks/src/use-local-storage.tsx +++ b/packages/hooks/src/use-local-storage.tsx @@ -1,8 +1,7 @@ import { useState, useEffect, useCallback } from "react"; export const getValueFromLocalStorage = (key: string, defaultValue: any) => { - if (typeof window === undefined || typeof window === "undefined") - return defaultValue; + if (typeof window === undefined || typeof window === "undefined") return defaultValue; try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : defaultValue; @@ -13,8 +12,7 @@ export const getValueFromLocalStorage = (key: string, defaultValue: any) => { }; export const setValueIntoLocalStorage = (key: string, value: any) => { - if (typeof window === undefined || typeof window === "undefined") - return false; + if (typeof window === undefined || typeof window === "undefined") return false; try { window.localStorage.setItem(key, JSON.stringify(value)); return true; @@ -24,9 +22,7 @@ export const setValueIntoLocalStorage = (key: string, value: any) => { }; export const useLocalStorage = (key: string, initialValue: T) => { - const [storedValue, setStoredValue] = useState(() => - getValueFromLocalStorage(key, initialValue) - ); + const [storedValue, setStoredValue] = useState(() => getValueFromLocalStorage(key, initialValue)); const setValue = useCallback( (value: T) => { diff --git a/packages/hooks/tsup.config.ts b/packages/hooks/tsup.config.ts new file mode 100644 index 000000000..6566c82ef --- /dev/null +++ b/packages/hooks/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + format: ["esm", "cjs"], + dts: true, + clean: true, + minify: true, + splitting: true, + treeshake: true, + external: ["react"], +}); diff --git a/packages/i18n/package.json b/packages/i18n/package.json index ce07c6c86..a0ce5e594 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,14 +1,18 @@ { "name": "@plane/i18n", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "I18n shared across multiple apps internally", "private": true, "main": "./src/index.ts", "types": "./src/index.ts", "scripts": { - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "dependencies": { "@plane/utils": "*", diff --git a/packages/i18n/src/locales/cs/translations.json b/packages/i18n/src/locales/cs/translations.json index 95c964ca8..307289bb1 100644 --- a/packages/i18n/src/locales/cs/translations.json +++ b/packages/i18n/src/locales/cs/translations.json @@ -1042,6 +1042,10 @@ }, "upload": { "error": "Nahrání přílohy se nezdařilo. Zkuste to prosím později." + }, + "copy_link": { + "success": "Odkaz na komentář byl zkopírován do schránky", + "error": "Chyba při kopírování odkazu na komentář. Zkuste to prosím později." } }, "empty_state": { @@ -2481,5 +2485,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane se nespustil. To může být způsobeno tím, že se jeden nebo více služeb Plane nepodařilo spustit.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logů, abyste si byli jisti." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Osnova", + "empty_state": { + "title": "Chybí nadpisy", + "description": "Přidejte na tuto stránku nějaké nadpisy, aby se zde zobrazily." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Slova", + "characters": "Znaky", + "paragraphs": "Odstavce", + "read_time": "Doba čtení" + }, + "actors_info": { + "edited_by": "Upravil", + "created_by": "Vytvořil" + }, + "version_history": { + "label": "Historie verzí", + "current_version": "Aktuální verze" + } + }, + "assets": { + "label": "Přílohy", + "download_button": "Stáhnout", + "empty_state": { + "title": "Chybí obrázky", + "description": "Přidejte obrázky, aby se zde zobrazily." + } + } + }, + "open_button": "Otevřít navigační panel", + "close_button": "Zavřít navigační panel", + "outline_floating_button": "Otevřít osnovu" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/de/translations.json b/packages/i18n/src/locales/de/translations.json index 8f68455f8..3c086c8cf 100644 --- a/packages/i18n/src/locales/de/translations.json +++ b/packages/i18n/src/locales/de/translations.json @@ -1042,6 +1042,10 @@ }, "upload": { "error": "Anhang konnte nicht hochgeladen werden. Bitte versuchen Sie es später erneut." + }, + "copy_link": { + "success": "Kommentar-Link in die Zwischenablage kopiert", + "error": "Fehler beim Kopieren des Kommentar-Links. Bitte versuchen Sie es später erneut." } }, "empty_state": { @@ -2480,5 +2484,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane ist nicht gestartet. Dies könnte daran liegen, dass einer oder mehrere Plane-Services nicht starten konnten.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wählen Sie View Logs aus setup.sh und Docker-Logs, um sicherzugehen." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Gliederung", + "empty_state": { + "title": "Fehlende Überschriften", + "description": "Fügen Sie einige Überschriften zu dieser Seite hinzu, um sie hier zu sehen." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Wörter", + "characters": "Zeichen", + "paragraphs": "Absätze", + "read_time": "Lesezeit" + }, + "actors_info": { + "edited_by": "Bearbeitet von", + "created_by": "Erstellt von" + }, + "version_history": { + "label": "Versionsverlauf", + "current_version": "Aktuelle Version" + } + }, + "assets": { + "label": "Assets", + "download_button": "Herunterladen", + "empty_state": { + "title": "Fehlende Bilder", + "description": "Fügen Sie Bilder hinzu, um sie hier zu sehen." + } + } + }, + "open_button": "Navigationsbereich öffnen", + "close_button": "Navigationsbereich schließen", + "outline_floating_button": "Gliederung öffnen" } } diff --git a/packages/i18n/src/locales/en/translations.json b/packages/i18n/src/locales/en/translations.json index a1fd1774b..6d77eb341 100644 --- a/packages/i18n/src/locales/en/translations.json +++ b/packages/i18n/src/locales/en/translations.json @@ -885,6 +885,10 @@ }, "upload": { "error": "Asset upload failed. Please try again later." + }, + "copy_link": { + "success": "Comment link copied to clipboard", + "error": "Error copying comment link. Please try again later." } }, "empty_state": { @@ -2357,5 +2361,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane didn't start up. This could be because one or more Plane services failed to start.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choose View Logs from setup.sh and Docker logs to be sure." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Outline", + "empty_state": { + "title": "Missing headings", + "description": "Let's put some headings in this page to see them here." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Words", + "characters": "Characters", + "paragraphs": "Paragraphs", + "read_time": "Read time" + }, + "actors_info": { + "edited_by": "Edited by", + "created_by": "Created by" + }, + "version_history": { + "label": "Version history", + "current_version": "Current version" + } + }, + "assets": { + "label": "Assets", + "download_button": "Download", + "empty_state": { + "title": "Missing images", + "description": "Add images to see them here." + } + } + }, + "open_button": "Open navigation pane", + "close_button": "Close navigation pane", + "outline_floating_button": "Open outline" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/es/translations.json b/packages/i18n/src/locales/es/translations.json index c133c600b..0f17e8f8a 100644 --- a/packages/i18n/src/locales/es/translations.json +++ b/packages/i18n/src/locales/es/translations.json @@ -1045,6 +1045,10 @@ }, "upload": { "error": "Error al subir el archivo. Por favor, inténtalo más tarde." + }, + "copy_link": { + "success": "Enlace del comentario copiado al portapapeles", + "error": "Error al copiar el enlace del comentario. Inténtelo de nuevo más tarde." } }, "empty_state": { @@ -2483,5 +2487,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane no se inició. Esto podría deberse a que uno o más servicios de Plane fallaron al iniciar.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Selecciona View Logs desde setup.sh y los logs de Docker para estar seguro." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Esquema", + "empty_state": { + "title": "Faltan encabezados", + "description": "Añade algunos encabezados a esta página para verlos aquí." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Palabras", + "characters": "Caracteres", + "paragraphs": "Párrafos", + "read_time": "Tiempo de lectura" + }, + "actors_info": { + "edited_by": "Editado por", + "created_by": "Creado por" + }, + "version_history": { + "label": "Historial de versiones", + "current_version": "Versión actual" + } + }, + "assets": { + "label": "Recursos", + "download_button": "Descargar", + "empty_state": { + "title": "Faltan imágenes", + "description": "Añade imágenes para verlas aquí." + } + } + }, + "open_button": "Abrir panel de navegación", + "close_button": "Cerrar panel de navegación", + "outline_floating_button": "Abrir esquema" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/fr/translations.json b/packages/i18n/src/locales/fr/translations.json index 36e027dae..a078526fe 100644 --- a/packages/i18n/src/locales/fr/translations.json +++ b/packages/i18n/src/locales/fr/translations.json @@ -1043,6 +1043,10 @@ }, "upload": { "error": "Échec du téléchargement du fichier. Veuillez réessayer plus tard." + }, + "copy_link": { + "success": "Lien du commentaire copié dans le presse-papiers", + "error": "Erreur lors de la copie du lien du commentaire. Veuillez réessayer plus tard." } }, "empty_state": { @@ -2481,5 +2485,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane n'a pas démarré. Cela pourrait être dû au fait qu'un ou plusieurs services Plane ont échoué à démarrer.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choisissez View Logs depuis setup.sh et les logs Docker pour en être sûr." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Plan", + "empty_state": { + "title": "Titres manquants", + "description": "Ajoutons quelques titres à cette page pour les voir ici." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Mots", + "characters": "Caractères", + "paragraphs": "Paragraphes", + "read_time": "Temps de lecture" + }, + "actors_info": { + "edited_by": "Modifié par", + "created_by": "Créé par" + }, + "version_history": { + "label": "Historique des versions", + "current_version": "Version actuelle" + } + }, + "assets": { + "label": "Ressources", + "download_button": "Télécharger", + "empty_state": { + "title": "Images manquantes", + "description": "Ajoutez des images pour les voir ici." + } + } + }, + "open_button": "Ouvrir le panneau de navigation", + "close_button": "Fermer le panneau de navigation", + "outline_floating_button": "Ouvrir le plan" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/id/translations.json b/packages/i18n/src/locales/id/translations.json index e90efe694..01f6d1424 100644 --- a/packages/i18n/src/locales/id/translations.json +++ b/packages/i18n/src/locales/id/translations.json @@ -1042,6 +1042,10 @@ }, "upload": { "error": "Gagal mengunggah aset. Silakan coba lagi nanti." + }, + "copy_link": { + "success": "Tautan komentar berhasil disalin ke clipboard", + "error": "Gagal menyalin tautan komentar. Silakan coba lagi nanti." } }, "empty_state": { @@ -2476,5 +2480,45 @@ "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane tidak berhasil dimulai. Ini bisa karena satu atau lebih layanan Plane gagal untuk dimulai.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Pilih View Logs dari setup.sh dan log Docker untuk memastikan." }, - "no_of": "Jumlah {entity}" -} \ No newline at end of file + "no_of": "Jumlah {entity}", + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Garis Besar", + "empty_state": { + "title": "Judul hilang", + "description": "Mari tambahkan beberapa judul di halaman ini untuk melihatnya di sini." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Kata", + "characters": "Karakter", + "paragraphs": "Paragraf", + "read_time": "Waktu baca" + }, + "actors_info": { + "edited_by": "Disunting oleh", + "created_by": "Dibuat oleh" + }, + "version_history": { + "label": "Riwayat versi", + "current_version": "Versi saat ini" + } + }, + "assets": { + "label": "Aset", + "download_button": "Unduh", + "empty_state": { + "title": "Gambar hilang", + "description": "Tambahkan gambar untuk melihatnya di sini." + } + } + }, + "open_button": "Buka panel navigasi", + "close_button": "Tutup panel navigasi", + "outline_floating_button": "Buka garis besar" + } +} diff --git a/packages/i18n/src/locales/it/translations.json b/packages/i18n/src/locales/it/translations.json index ec7fb5efa..fc457eeb0 100644 --- a/packages/i18n/src/locales/it/translations.json +++ b/packages/i18n/src/locales/it/translations.json @@ -1041,6 +1041,10 @@ }, "upload": { "error": "Caricamento dell'asset fallito. Per favore, riprova più tardi." + }, + "copy_link": { + "success": "Link del commento copiato negli appunti", + "error": "Errore durante la copia del link del commento. Riprova più tardi." } }, "empty_state": { @@ -2480,5 +2484,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane non si è avviato. Questo potrebbe essere dovuto al fatto che uno o più servizi Plane non sono riusciti ad avviarsi.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Scegli View Logs da setup.sh e dai log Docker per essere sicuro." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Schema", + "empty_state": { + "title": "Intestazioni mancanti", + "description": "Aggiungiamo alcune intestazioni a questa pagina per vederle qui." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Parole", + "characters": "Caratteri", + "paragraphs": "Paragrafi", + "read_time": "Tempo di lettura" + }, + "actors_info": { + "edited_by": "Modificato da", + "created_by": "Creato da" + }, + "version_history": { + "label": "Cronologia versioni", + "current_version": "Versione corrente" + } + }, + "assets": { + "label": "Risorse", + "download_button": "Scarica", + "empty_state": { + "title": "Immagini mancanti", + "description": "Aggiungi immagini per vederle qui." + } + } + }, + "open_button": "Apri pannello di navigazione", + "close_button": "Chiudi pannello di navigazione", + "outline_floating_button": "Apri schema" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/ja/translations.json b/packages/i18n/src/locales/ja/translations.json index 79d7fa554..e92e0a182 100644 --- a/packages/i18n/src/locales/ja/translations.json +++ b/packages/i18n/src/locales/ja/translations.json @@ -1043,6 +1043,10 @@ }, "upload": { "error": "アセットのアップロードに失敗しました。後でもう一度お試しください。" + }, + "copy_link": { + "success": "コメントリンクがクリップボードにコピーされました", + "error": "コメントリンクのコピーに失敗しました。後でもう一度お試しください。" } }, "empty_state": { @@ -2481,5 +2485,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Planeが起動しませんでした。これは1つまたは複数のPlaneサービスの起動に失敗したことが原因である可能性があります。", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "setup.shとDockerログからView Logsを選択して確認してください。" + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "アウトライン", + "empty_state": { + "title": "見出しがありません", + "description": "このページに見出しを追加してここで確認しましょう。" + } + }, + "info": { + "label": "情報", + "document_info": { + "words": "単語数", + "characters": "文字数", + "paragraphs": "段落数", + "read_time": "読了時間" + }, + "actors_info": { + "edited_by": "編集者", + "created_by": "作成者" + }, + "version_history": { + "label": "バージョン履歴", + "current_version": "現在のバージョン" + } + }, + "assets": { + "label": "アセット", + "download_button": "ダウンロード", + "empty_state": { + "title": "画像がありません", + "description": "画像を追加してここで確認してください。" + } + } + }, + "open_button": "ナビゲーションパネルを開く", + "close_button": "ナビゲーションパネルを閉じる", + "outline_floating_button": "アウトラインを開く" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/ko/translations.json b/packages/i18n/src/locales/ko/translations.json index 1fbb2aac4..3f253931b 100644 --- a/packages/i18n/src/locales/ko/translations.json +++ b/packages/i18n/src/locales/ko/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "자산 업로드 실패. 나중에 다시 시도해주세요." + }, + "copy_link": { + "success": "댓글 링크가 클립보드에 복사되었습니다", + "error": "댓글 링크 복사 중 오류가 발생했습니다. 나중에 다시 시도해 주세요." } }, "empty_state": { @@ -2483,5 +2487,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane이 시작되지 않았습니다. 이는 하나 이상의 Plane 서비스가 시작에 실패했기 때문일 수 있습니다.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "확실히 하려면 setup.sh와 Docker 로그에서 View Logs를 선택하세요." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "개요", + "empty_state": { + "title": "제목이 없습니다", + "description": "이 페이지에 제목을 추가하여 여기에서 확인해보세요." + } + }, + "info": { + "label": "정보", + "document_info": { + "words": "단어", + "characters": "문자", + "paragraphs": "단락", + "read_time": "읽기 시간" + }, + "actors_info": { + "edited_by": "편집자", + "created_by": "작성자" + }, + "version_history": { + "label": "버전 기록", + "current_version": "현재 버전" + } + }, + "assets": { + "label": "자산", + "download_button": "다운로드", + "empty_state": { + "title": "이미지가 없습니다", + "description": "이미지를 추가하여 여기에서 확인하세요." + } + } + }, + "open_button": "네비게이션 패널 열기", + "close_button": "네비게이션 패널 닫기", + "outline_floating_button": "개요 열기" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/pl/translations.json b/packages/i18n/src/locales/pl/translations.json index ecb82a75a..fdb2d0958 100644 --- a/packages/i18n/src/locales/pl/translations.json +++ b/packages/i18n/src/locales/pl/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "Nie udało się przesłać załącznika. Spróbuj później." + }, + "copy_link": { + "success": "Link do komentarza skopiowany do schowka", + "error": "Błąd podczas kopiowania linka do komentarza. Spróbuj ponownie później." } }, "empty_state": { @@ -2482,5 +2486,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nie uruchomił się. Może to być spowodowane tym, że jedna lub więcej usług Plane nie mogła się uruchomić.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wybierz View Logs z setup.sh i logów Docker, aby mieć pewność." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Konspekt", + "empty_state": { + "title": "Brakuje nagłówków", + "description": "Dodajmy kilka nagłówków na tej stronie, aby je tutaj zobaczyć." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Słowa", + "characters": "Znaki", + "paragraphs": "Akapity", + "read_time": "Czas czytania" + }, + "actors_info": { + "edited_by": "Edytowane przez", + "created_by": "Utworzone przez" + }, + "version_history": { + "label": "Historia wersji", + "current_version": "Bieżąca wersja" + } + }, + "assets": { + "label": "Zasoby", + "download_button": "Pobierz", + "empty_state": { + "title": "Brakuje obrazów", + "description": "Dodaj obrazy, aby je tutaj zobaczyć." + } + } + }, + "open_button": "Otwórz panel nawigacji", + "close_button": "Zamknij panel nawigacji", + "outline_floating_button": "Otwórz konspekt" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/pt-BR/translations.json b/packages/i18n/src/locales/pt-BR/translations.json index fa0e57eb5..d12918556 100644 --- a/packages/i18n/src/locales/pt-BR/translations.json +++ b/packages/i18n/src/locales/pt-BR/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "Falha ao carregar o recurso. Por favor, tente novamente mais tarde." + }, + "copy_link": { + "success": "Link do comentário copiado para a área de transferência", + "error": "Erro ao copiar o link do comentário. Tente novamente mais tarde." } }, "empty_state": { @@ -2477,5 +2481,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "O Plane não inicializou. Isso pode ser porque um ou mais serviços do Plane falharam ao iniciar.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Escolha View Logs do setup.sh e logs do Docker para ter certeza." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Estrutura", + "empty_state": { + "title": "Cabeçalhos ausentes", + "description": "Vamos adicionar alguns cabeçalhos nesta página para vê-los aqui." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Palavras", + "characters": "Caracteres", + "paragraphs": "Parágrafos", + "read_time": "Tempo de leitura" + }, + "actors_info": { + "edited_by": "Editado por", + "created_by": "Criado por" + }, + "version_history": { + "label": "Histórico de versões", + "current_version": "Versão atual" + } + }, + "assets": { + "label": "Recursos", + "download_button": "Baixar", + "empty_state": { + "title": "Imagens ausentes", + "description": "Adicione imagens para vê-las aqui." + } + } + }, + "open_button": "Abrir painel de navegação", + "close_button": "Fechar painel de navegação", + "outline_floating_button": "Abrir estrutura" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/ro/translations.json b/packages/i18n/src/locales/ro/translations.json index e22dd33d2..caa1178d1 100644 --- a/packages/i18n/src/locales/ro/translations.json +++ b/packages/i18n/src/locales/ro/translations.json @@ -1042,6 +1042,10 @@ }, "upload": { "error": "Încărcarea fișierului a eșuat. Te rugăm să încerci mai târziu." + }, + "copy_link": { + "success": "Linkul comentariului a fost copiat în clipboard", + "error": "Eroare la copierea linkului comentariului. Încercați din nou mai târziu." } }, "empty_state": { @@ -2475,5 +2479,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nu a pornit. Aceasta ar putea fi din cauza că unul sau mai multe servicii Plane au eșuat să pornească.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Alegeți View Logs din setup.sh și logurile Docker pentru a fi siguri." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Contur", + "empty_state": { + "title": "Titluri lipsă", + "description": "Să punem câteva titluri în această pagină pentru a le vedea aici." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Cuvinte", + "characters": "Caractere", + "paragraphs": "Paragrafe", + "read_time": "Timp de citire" + }, + "actors_info": { + "edited_by": "Editat de", + "created_by": "Creat de" + }, + "version_history": { + "label": "Istoricul versiunilor", + "current_version": "Versiunea curentă" + } + }, + "assets": { + "label": "Resurse", + "download_button": "Descarcă", + "empty_state": { + "title": "Imagini lipsă", + "description": "Adăugați imagini pentru a le vedea aici." + } + } + }, + "open_button": "Deschide panoul de navigare", + "close_button": "Închide panoul de navigare", + "outline_floating_button": "Deschide conturul" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/ru/translations.json b/packages/i18n/src/locales/ru/translations.json index 24e939a66..8481b596c 100644 --- a/packages/i18n/src/locales/ru/translations.json +++ b/packages/i18n/src/locales/ru/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "Ошибка загрузки файла. Попробуйте позже." + }, + "copy_link": { + "success": "Ссылка на комментарий скопирована в буфер обмена", + "error": "Ошибка при копировании ссылки на комментарий. Попробуйте позже." } }, "empty_state": { @@ -2484,5 +2488,45 @@ "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустился. Это может быть из-за того, что один или несколько сервисов Plane не смогли запуститься.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Выберите View Logs из setup.sh и логов Docker, чтобы убедиться." }, - "no_of": "Количество {entity}" -} \ No newline at end of file + "no_of": "Количество {entity}", + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Структура", + "empty_state": { + "title": "Отсутствуют заголовки", + "description": "Давайте добавим несколько заголовков на эту страницу, чтобы увидеть их здесь." + } + }, + "info": { + "label": "Информация", + "document_info": { + "words": "Слова", + "characters": "Символы", + "paragraphs": "Абзацы", + "read_time": "Время чтения" + }, + "actors_info": { + "edited_by": "Отредактировано", + "created_by": "Создано" + }, + "version_history": { + "label": "История версий", + "current_version": "Текущая версия" + } + }, + "assets": { + "label": "Ресурсы", + "download_button": "Скачать", + "empty_state": { + "title": "Отсутствуют изображения", + "description": "Добавьте изображения, чтобы увидеть их здесь." + } + } + }, + "open_button": "Открыть панель навигации", + "close_button": "Закрыть панель навигации", + "outline_floating_button": "Открыть структуру" + } +} diff --git a/packages/i18n/src/locales/sk/translations.json b/packages/i18n/src/locales/sk/translations.json index 80128508b..7c89fc131 100644 --- a/packages/i18n/src/locales/sk/translations.json +++ b/packages/i18n/src/locales/sk/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "Nahratie prílohy zlyhalo. Skúste to prosím neskôr." + }, + "copy_link": { + "success": "Odkaz na komentár bol skopírovaný do schránky", + "error": "Chyba pri kopírovaní odkazu na komentár. Skúste to prosím neskôr." } }, "empty_state": { @@ -2482,5 +2486,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane sa nespustil. Toto môže byť spôsobené tým, že sa jedna alebo viac služieb Plane nepodarilo spustiť.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logov, aby ste si boli istí." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Osnova", + "empty_state": { + "title": "Chýbajú nadpisy", + "description": "Pridajme na túto stránku nejaké nadpisy, aby sa tu zobrazili." + } + }, + "info": { + "label": "Info", + "document_info": { + "words": "Slová", + "characters": "Znaky", + "paragraphs": "Odseky", + "read_time": "Čas čítania" + }, + "actors_info": { + "edited_by": "Upravil", + "created_by": "Vytvoril" + }, + "version_history": { + "label": "História verzií", + "current_version": "Aktuálna verzia" + } + }, + "assets": { + "label": "Prílohy", + "download_button": "Stiahnuť", + "empty_state": { + "title": "Chýbajú obrázky", + "description": "Pridajte obrázky, aby sa tu zobrazili." + } + } + }, + "open_button": "Otvoriť navigačný panel", + "close_button": "Zavrieť navigačný panel", + "outline_floating_button": "Otvoriť osnovu" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/tr-TR/translations.json b/packages/i18n/src/locales/tr-TR/translations.json index 607d441d5..65c830abf 100644 --- a/packages/i18n/src/locales/tr-TR/translations.json +++ b/packages/i18n/src/locales/tr-TR/translations.json @@ -1045,6 +1045,10 @@ }, "upload": { "error": "Dosya yüklenemedi. Lütfen daha sonra tekrar deneyin." + }, + "copy_link": { + "success": "Yorum bağlantısı panoya kopyalandı", + "error": "Yorum bağlantısı kopyalanırken hata oluştu. Lütfen daha sonra tekrar deneyin." } }, "empty_state": { @@ -2461,5 +2465,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane başlatılamadı. Bu, bir veya daha fazla Plane servisinin başlatılamaması nedeniyle olabilir.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Emin olmak için setup.sh ve Docker loglarından View Logs'u seçin." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Ana Hat", + "empty_state": { + "title": "Eksik başlıklar", + "description": "Bu sayfaya bazı başlıklar ekleyelim ki burada görebilelim." + } + }, + "info": { + "label": "Bilgi", + "document_info": { + "words": "Kelimeler", + "characters": "Karakterler", + "paragraphs": "Paragraflar", + "read_time": "Okuma süresi" + }, + "actors_info": { + "edited_by": "Düzenleyen", + "created_by": "Oluşturan" + }, + "version_history": { + "label": "Sürüm geçmişi", + "current_version": "Mevcut sürüm" + } + }, + "assets": { + "label": "Varlıklar", + "download_button": "İndir", + "empty_state": { + "title": "Eksik görseller", + "description": "Burada görmek için görseller ekleyin." + } + } + }, + "open_button": "Navigasyon panelini aç", + "close_button": "Navigasyon panelini kapat", + "outline_floating_button": "Ana hatları aç" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/ua/translations.json b/packages/i18n/src/locales/ua/translations.json index 9563fa288..1a3ab64f9 100644 --- a/packages/i18n/src/locales/ua/translations.json +++ b/packages/i18n/src/locales/ua/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "Не вдалося завантажити вкладення. Спробуйте пізніше." + }, + "copy_link": { + "success": "Посилання на коментар скопійовано в буфер обміну", + "error": "Помилка при копіюванні посилання на коментар. Спробуйте пізніше." } }, "empty_state": { @@ -2482,5 +2486,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустився. Це може бути через те, що один або декілька сервісів Plane не змогли запуститися.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Виберіть View Logs з setup.sh та логів Docker, щоб переконатися." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Структура", + "empty_state": { + "title": "Відсутні заголовки", + "description": "Давайте додамо кілька заголовків на цю сторінку, щоб побачити їх тут." + } + }, + "info": { + "label": "Інформація", + "document_info": { + "words": "Слова", + "characters": "Символи", + "paragraphs": "Абзаци", + "read_time": "Час читання" + }, + "actors_info": { + "edited_by": "Відредаговано", + "created_by": "Створено" + }, + "version_history": { + "label": "Історія версій", + "current_version": "Поточна версія" + } + }, + "assets": { + "label": "Ресурси", + "download_button": "Завантажити", + "empty_state": { + "title": "Відсутні зображення", + "description": "Додайте зображення, щоб побачити їх тут." + } + } + }, + "open_button": "Відкрити панель навігації", + "close_button": "Закрити панель навігації", + "outline_floating_button": "Відкрити структуру" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/vi-VN/translations.json b/packages/i18n/src/locales/vi-VN/translations.json index bd2f0df4b..947f10b16 100644 --- a/packages/i18n/src/locales/vi-VN/translations.json +++ b/packages/i18n/src/locales/vi-VN/translations.json @@ -1043,6 +1043,10 @@ }, "upload": { "error": "Không thể tải lên tài nguyên. Vui lòng thử lại sau." + }, + "copy_link": { + "success": "Liên kết bình luận đã được sao chép vào clipboard", + "error": "Lỗi khi sao chép liên kết bình luận. Vui lòng thử lại sau." } }, "empty_state": { @@ -2480,5 +2484,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane không khởi động được. Điều này có thể do một hoặc nhiều dịch vụ Plane không khởi động được.", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Chọn View Logs từ setup.sh và log Docker để chắc chắn." + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "Phác thảo", + "empty_state": { + "title": "Thiếu tiêu đề", + "description": "Hãy thêm một số tiêu đề vào trang này để xem chúng ở đây." + } + }, + "info": { + "label": "Thông tin", + "document_info": { + "words": "Từ", + "characters": "Ký tự", + "paragraphs": "Đoạn văn", + "read_time": "Thời gian đọc" + }, + "actors_info": { + "edited_by": "Được chỉnh sửa bởi", + "created_by": "Được tạo bởi" + }, + "version_history": { + "label": "Lịch sử phiên bản", + "current_version": "Phiên bản hiện tại" + } + }, + "assets": { + "label": "Tài sản", + "download_button": "Tải xuống", + "empty_state": { + "title": "Thiếu hình ảnh", + "description": "Thêm hình ảnh để xem chúng ở đây." + } + } + }, + "open_button": "Mở bảng điều hướng", + "close_button": "Đóng bảng điều hướng", + "outline_floating_button": "Mở phác thảo" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/zh-CN/translations.json b/packages/i18n/src/locales/zh-CN/translations.json index b1ca43f1f..444936c50 100644 --- a/packages/i18n/src/locales/zh-CN/translations.json +++ b/packages/i18n/src/locales/zh-CN/translations.json @@ -1043,6 +1043,10 @@ }, "upload": { "error": "资源上传失败。请稍后重试。" + }, + "copy_link": { + "success": "评论链接已复制到剪贴板", + "error": "复制评论链接时出错。请稍后再试。" } }, "empty_state": { @@ -2462,5 +2466,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能启动。这可能是因为一个或多个 Plane 服务启动失败。", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "请选择“查看日志”来查看 setup.sh 和 Docker 日志,以确认问题。" + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "大纲", + "empty_state": { + "title": "缺少标题", + "description": "让我们在这个页面添加一些标题来在这里查看它们。" + } + }, + "info": { + "label": "信息", + "document_info": { + "words": "字数", + "characters": "字符数", + "paragraphs": "段落数", + "read_time": "阅读时间" + }, + "actors_info": { + "edited_by": "编辑者", + "created_by": "创建者" + }, + "version_history": { + "label": "版本历史", + "current_version": "当前版本" + } + }, + "assets": { + "label": "资源", + "download_button": "下载", + "empty_state": { + "title": "缺少图片", + "description": "添加图片以在这里查看它们。" + } + } + }, + "open_button": "打开导航面板", + "close_button": "关闭导航面板", + "outline_floating_button": "打开大纲" } -} \ No newline at end of file +} diff --git a/packages/i18n/src/locales/zh-TW/translations.json b/packages/i18n/src/locales/zh-TW/translations.json index 0cd86f3aa..724c434db 100644 --- a/packages/i18n/src/locales/zh-TW/translations.json +++ b/packages/i18n/src/locales/zh-TW/translations.json @@ -1044,6 +1044,10 @@ }, "upload": { "error": "資產上傳失敗。請稍後再試。" + }, + "copy_link": { + "success": "評論連結已複製到剪貼簿", + "error": "複製評論連結時出錯。請稍後再試。" } }, "empty_state": { @@ -2483,5 +2487,45 @@ "self_hosted_maintenance_message": { "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能啟動。這可能是因為一個或多個 Plane 服務啟動失敗。", "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "從 setup.sh 和 Docker 日誌中選擇 View Logs 來確認。" + }, + + "page_navigation_pane": { + "tabs": { + "outline": { + "label": "大綱", + "empty_state": { + "title": "缺少標題", + "description": "讓我們在這個頁面添加一些標題來在這裡查看它們。" + } + }, + "info": { + "label": "資訊", + "document_info": { + "words": "字數", + "characters": "字元數", + "paragraphs": "段落數", + "read_time": "閱讀時間" + }, + "actors_info": { + "edited_by": "編輯者", + "created_by": "建立者" + }, + "version_history": { + "label": "版本歷史", + "current_version": "目前版本" + } + }, + "assets": { + "label": "資源", + "download_button": "下載", + "empty_state": { + "title": "缺少圖片", + "description": "添加圖片以在這裡查看它們。" + } + } + }, + "open_button": "打開導航面板", + "close_button": "關閉導航面板", + "outline_floating_button": "打開大綱" } -} \ No newline at end of file +} diff --git a/packages/logger/README.md b/packages/logger/README.md index 6b83eb52b..4391b898a 100644 --- a/packages/logger/README.md +++ b/packages/logger/README.md @@ -3,6 +3,7 @@ This package provides a logger and a request logger utility built using [Winston](https://github.com/winstonjs/winston). It offers customizable log levels using env and supports structured logging for general application logs and HTTP requests. ## Features. + - Dynamic log level configuration using env. - Pre-configured winston logger for general usage (`logger`). - Request logger middleware that logs incoming request @@ -10,7 +11,9 @@ This package provides a logger and a request logger utility built using [Winston ## Usage ### Adding as a package + Add this package as a dependency in package.json + ```typescript dependency: { ... @@ -20,11 +23,15 @@ dependency: { ``` ### Importing the Logger + ```typescript -import { logger, requestLogger } from '@plane/logger' +import { logger, requestLogger } from "@plane/logger"; ``` + ### Usage + ### `logger`: General Logger + Use this for general application logs. ```typescript @@ -34,14 +41,16 @@ logger.error("This is an error"); ``` ### `requestLogger`: Request Logger Middleware + Use this as a middleware for incoming requests ```typescript -const app = express() -app.use(requestLogger) +const app = express(); +app.use(requestLogger); ``` ## Available Log Levels + - `error` - `warn` - `info` (default) @@ -51,9 +60,11 @@ app.use(requestLogger) - `silly` ## Log file -- Log files are stored in logs folder of current working directory. Error logs are stored in files with format `error-%DATE%.log` and combined logs are stored with format `combined-%DATE%.log`. + +- Log files are stored in logs folder of current working directory. Error logs are stored in files with format `error-%DATE%.log` and combined logs are stored with format `combined-%DATE%.log`. - Log files have a 7 day rotation period defined. ## Configuration -- By default, the log level is set to `info`. -- You can specify a log level by adding a LOG_LEVEL in .env. \ No newline at end of file + +- By default, the log level is set to `info`. +- You can specify a log level by adding a LOG_LEVEL in .env. diff --git a/packages/logger/package.json b/packages/logger/package.json index 001fa07c4..96452f8fb 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@plane/logger", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "Logger shared across multiple apps internally", "private": true, @@ -11,18 +11,24 @@ "dist/**" ], "scripts": { - "build": "tsup", + "build": "tsup --minify", "dev": "tsup --watch", - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "dependencies": { + "@types/express": "^4.17.21", + "express": "^4.21.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" }, "devDependencies": { "@plane/eslint-config": "*", + "@plane/typescript-config": "*", "@types/node": "^22.5.4", "tsup": "8.4.0", "typescript": "5.8.3" diff --git a/packages/logger/tsup.config.ts b/packages/logger/tsup.config.ts index 85bf72fce..01d63fe27 100644 --- a/packages/logger/tsup.config.ts +++ b/packages/logger/tsup.config.ts @@ -2,11 +2,12 @@ import { defineConfig } from "tsup"; export default defineConfig({ entry: ["src/index.ts"], + outDir: "dist", format: ["esm", "cjs"], dts: true, - splitting: false, - sourcemap: true, clean: true, - external: ["winston", "winston-daily-rotate-file"], + minify: true, + splitting: true, treeshake: true, + external: ["winston", "winston-daily-rotate-file"], }); diff --git a/packages/propel/package.json b/packages/propel/package.json index 2a683a1e5..a39395fdd 100644 --- a/packages/propel/package.json +++ b/packages/propel/package.json @@ -1,11 +1,15 @@ { "name": "@plane/propel", - "version": "0.27.1", + "version": "0.28.0", "private": true, "license": "AGPL-3.0", "scripts": { - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "exports": { "./ui/*": "./src/ui/*.tsx", diff --git a/packages/propel/src/charts/components/legend.tsx b/packages/propel/src/charts/components/legend.tsx index 3c4558120..94ca2a2bf 100644 --- a/packages/propel/src/charts/components/legend.tsx +++ b/packages/propel/src/charts/components/legend.tsx @@ -15,16 +15,16 @@ export const getLegendProps = (args: TChartLegend): LegendProps => { overflow: "hidden", ...(layout === "vertical" ? { - top: 0, - alignItems: "center", - height: "100%", - } + top: 0, + alignItems: "center", + height: "100%", + } : { - left: 0, - bottom: 0, - width: "100%", - justifyContent: "center", - }), + left: 0, + bottom: 0, + width: "100%", + justifyContent: "center", + }), ...args.wrapperStyles, }, content: , @@ -34,8 +34,8 @@ export const getLegendProps = (args: TChartLegend): LegendProps => { const CustomLegend = React.forwardRef< HTMLDivElement, React.ComponentProps<"div"> & - Pick & - TChartLegend + Pick & + TChartLegend >((props, ref) => { const { formatter, layout, onClick, onMouseEnter, onMouseLeave, payload } = props; diff --git a/packages/propel/src/charts/components/tick.tsx b/packages/propel/src/charts/components/tick.tsx index 4b64e8373..1a79ca334 100644 --- a/packages/propel/src/charts/components/tick.tsx +++ b/packages/propel/src/charts/components/tick.tsx @@ -23,25 +23,23 @@ export const CustomYAxisTick = React.memo(({ x, y, payload }: any) => ( CustomYAxisTick.displayName = "CustomYAxisTick"; -export const CustomRadarAxisTick = React.memo( - ({ x, y, payload, getLabel, cx, cy, offset = 16 }: any) => { - // Calculate direction vector from center to tick - const dx = x - cx; - const dy = y - cy; - // Normalize and apply offset - const length = Math.sqrt(dx * dx + dy * dy); - const normX = dx / length; - const normY = dy / length; - const labelX = x + normX * offset; - const labelY = y + normY * offset; +export const CustomRadarAxisTick = React.memo(({ x, y, payload, getLabel, cx, cy, offset = 16 }: any) => { + // Calculate direction vector from center to tick + const dx = x - cx; + const dy = y - cy; + // Normalize and apply offset + const length = Math.sqrt(dx * dx + dy * dy); + const normX = dx / length; + const normY = dy / length; + const labelX = x + normX * offset; + const labelY = y + normY * offset; - return ( - - - {getLabel ? getLabel(payload.value) : payload.value} - - - ); - } -); + return ( + + + {getLabel ? getLabel(payload.value) : payload.value} + + + ); +}); CustomRadarAxisTick.displayName = "CustomRadarAxisTick"; diff --git a/packages/propel/src/charts/radar-chart/index.ts b/packages/propel/src/charts/radar-chart/index.ts index 50a9c47c0..1efe34c51 100644 --- a/packages/propel/src/charts/radar-chart/index.ts +++ b/packages/propel/src/charts/radar-chart/index.ts @@ -1 +1 @@ -export * from "./root"; \ No newline at end of file +export * from "./root"; diff --git a/packages/propel/src/charts/scatter-chart/index.ts b/packages/propel/src/charts/scatter-chart/index.ts index 50a9c47c0..1efe34c51 100644 --- a/packages/propel/src/charts/scatter-chart/index.ts +++ b/packages/propel/src/charts/scatter-chart/index.ts @@ -1 +1 @@ -export * from "./root"; \ No newline at end of file +export * from "./root"; diff --git a/packages/propel/src/charts/scatter-chart/root.tsx b/packages/propel/src/charts/scatter-chart/root.tsx index 5187d131b..25d7b84b4 100644 --- a/packages/propel/src/charts/scatter-chart/root.tsx +++ b/packages/propel/src/charts/scatter-chart/root.tsx @@ -156,4 +156,4 @@ export const ScatterChart = React.memo((prop
    ); }); -ScatterChart.displayName = "ScatterChart"; \ No newline at end of file +ScatterChart.displayName = "ScatterChart"; diff --git a/packages/propel/src/charts/tree-map/map-content.tsx b/packages/propel/src/charts/tree-map/map-content.tsx index f3b062cb0..0e4a6e2f3 100644 --- a/packages/propel/src/charts/tree-map/map-content.tsx +++ b/packages/propel/src/charts/tree-map/map-content.tsx @@ -252,8 +252,8 @@ export const CustomTreeMapContent: React.FC = ({ {bottom.labelTruncated ? truncateText( label, - availableTextWidth - calculateContentWidth(value, LAYOUT.TEXT.FONT_SIZES.SM) - 4, - LAYOUT.TEXT.FONT_SIZES.SM + availableTextWidth - calculateContentWidth(value, LAYOUT.TEXT.FONT_SIZES.SM) - 4, + LAYOUT.TEXT.FONT_SIZES.SM ) : label} diff --git a/packages/propel/src/table/index.ts b/packages/propel/src/table/index.ts index 8b83d73fe..8d119dee8 100644 --- a/packages/propel/src/table/index.ts +++ b/packages/propel/src/table/index.ts @@ -1 +1 @@ -export * from "./core"; \ No newline at end of file +export * from "./core"; diff --git a/packages/services/.eslintrc.js b/packages/services/.eslintrc.js index 558b8f76e..b11b7bb6d 100644 --- a/packages/services/.eslintrc.js +++ b/packages/services/.eslintrc.js @@ -3,7 +3,4 @@ module.exports = { root: true, extends: ["@plane/eslint-config/library.js"], parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, }; diff --git a/packages/services/package.json b/packages/services/package.json index 43c44dc95..25c47386f 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -1,15 +1,27 @@ { "name": "@plane/services", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "private": true, "main": "./src/index.ts", "scripts": { - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "build": "tsc --noEmit && tsup --minify", + "dev": "tsup --watch", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "dependencies": { "@plane/constants": "*", - "axios": "^1.8.3" + "axios": "1.11.0" + }, + "devDependencies": { + "@plane/eslint-config": "*", + "@plane/typescript-config": "*", + "tsup": "8.4.0", + "typescript": "5.8.3" } } diff --git a/packages/services/src/api.service.ts b/packages/services/src/api.service.ts index 619a0d4ec..e2b74993e 100644 --- a/packages/services/src/api.service.ts +++ b/packages/services/src/api.service.ts @@ -1,6 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ import axios, { AxiosInstance, AxiosRequestConfig } from "axios"; -import { IndexedDBService } from "./indexedDB.service"; /** * Abstract base class for making HTTP requests using axios @@ -20,38 +18,6 @@ export abstract class APIService { baseURL, withCredentials: true, }); - - this.setupInterceptors(); - } - - /** - * Sets up axios interceptors for handling responses - * Currently handles 401 unauthorized responses by redirecting to login - * @private - */ - private setupInterceptors() { - this.axiosInstance.interceptors.response.use( - (response) => response, - (error) => { - if (error.response && error.response.status === 401) { - const currentPath = window.location.pathname; - let prefix = "/"; - let updatedPath = currentPath; - - // Check for special path prefixes - if (currentPath.startsWith("/god-mode")) { - prefix = "/god-mode"; - updatedPath = currentPath.replace("/god-mode", ""); - } else if (currentPath.startsWith("/spaces")) { - prefix = "/spaces"; - updatedPath = currentPath.replace("/spaces", ""); - } - - window.location.replace(`${prefix}${updatedPath ? `?next_path=${updatedPath}` : ""}`); - } - return Promise.reject(error); - } - ); } /** diff --git a/packages/services/src/file/file-upload.service.ts b/packages/services/src/file/file-upload.service.ts index a2e5ce5e6..6613cf1d5 100644 --- a/packages/services/src/file/file-upload.service.ts +++ b/packages/services/src/file/file-upload.service.ts @@ -21,10 +21,7 @@ export class FileUploadService extends APIService { * @returns {Promise} Promise resolving to void * @throws {Error} If the request fails */ - async uploadFile( - url: string, - data: FormData, - ): Promise { + async uploadFile(url: string, data: FormData): Promise { this.cancelSource = axios.CancelToken.source(); return this.post(url, data, { headers: { @@ -49,4 +46,4 @@ export class FileUploadService extends APIService { cancelUpload() { this.cancelSource.cancel("Upload canceled"); } -} \ No newline at end of file +} diff --git a/packages/services/src/instance/instance.service.ts b/packages/services/src/instance/instance.service.ts index 637c81cad..6af821d9b 100644 --- a/packages/services/src/instance/instance.service.ts +++ b/packages/services/src/instance/instance.service.ts @@ -122,4 +122,17 @@ export class InstanceService extends APIService { throw error?.response?.data; }); } + + /** + * Disables the email configuration + * @returns {Promise} Promise resolving to void + * @throws {Error} If the API request fails + */ + async disableEmail(): Promise { + return this.delete("/api/instances/configurations/disable-email-feature/") + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } } diff --git a/packages/services/src/user/user.service.ts b/packages/services/src/user/user.service.ts index c302b1d4f..c177b1ffd 100644 --- a/packages/services/src/user/user.service.ts +++ b/packages/services/src/user/user.service.ts @@ -20,14 +20,13 @@ export class UserService extends APIService { /** * Retrieves the current user details - * @returns {Promise} Promise resolving to the current user details\ - * @remarks This method uses the validateStatus: null option to bypass interceptors for unauthorized errors. + * @returns {Promise} Promise resolving to the current user details */ async me(): Promise { - return this.get("/api/users/me/", { validateStatus: null }) + return this.get("/api/users/me/") .then((response) => response?.data) .catch((error) => { - throw error?.response; + throw error; }); } @@ -76,10 +75,9 @@ export class UserService extends APIService { * Retrieves the current instance admin details * @returns {Promise} Promise resolving to the current instance admin details * @throws {Error} If the API request fails - * @remarks This method uses the validateStatus: null option to bypass interceptors for unauthorized errors. */ async adminDetails(): Promise { - return this.get("/api/instances/admins/me/", { validateStatus: null }) + return this.get("/api/instances/admins/me/") .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/packages/services/tsconfig.json b/packages/services/tsconfig.json index efce2a9fe..e8af9092a 100644 --- a/packages/services/tsconfig.json +++ b/packages/services/tsconfig.json @@ -2,7 +2,7 @@ "extends": "@plane/typescript-config/react-library.json", "compilerOptions": { "jsx": "react", - "lib": ["esnext", "dom"], + "lib": ["esnext", "dom"] }, "include": ["./src"], "exclude": ["dist", "build", "node_modules"] diff --git a/packages/services/tsup.config.ts b/packages/services/tsup.config.ts new file mode 100644 index 000000000..cb6ac8b2a --- /dev/null +++ b/packages/services/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + format: ["esm", "cjs"], + dts: true, + clean: true, + minify: true, + splitting: true, + treeshake: true, + external: ["axios"], +}); diff --git a/packages/shared-state/package.json b/packages/shared-state/package.json index a68adb403..9e1068119 100644 --- a/packages/shared-state/package.json +++ b/packages/shared-state/package.json @@ -1,14 +1,18 @@ { "name": "@plane/shared-state", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "Shared state shared across multiple apps internally", "private": true, "main": "./src/index.ts", "types": "./src/index.ts", "scripts": { - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "dependencies": { "zod": "^3.22.2" diff --git a/packages/tailwind-config/package.json b/packages/tailwind-config/package.json index 524062c5e..ad7d92442 100644 --- a/packages/tailwind-config/package.json +++ b/packages/tailwind-config/package.json @@ -1,6 +1,6 @@ { "name": "@plane/tailwind-config", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "description": "common tailwind configuration across monorepo", "main": "tailwind.config.js", diff --git a/packages/tailwind-config/tailwind.config.js b/packages/tailwind-config/tailwind.config.js index 168c54e62..42e98e0a5 100644 --- a/packages/tailwind-config/tailwind.config.js +++ b/packages/tailwind-config/tailwind.config.js @@ -18,10 +18,10 @@ module.exports = { "./pages/**/*.tsx", "./app/**/*.tsx", "./ui/**/*.tsx", - "../packages/ui/src/**/*.{js,ts,jsx,tsx}", - "../packages/propel/src/**/*.{js,ts,jsx,tsx}", - "../packages/editor/src/**/*.{js,ts,jsx,tsx}", - "!../packages/ui/**/*.stories{js,ts,jsx,tsx}", + "../../packages/ui/src/**/*.{js,ts,jsx,tsx}", + "../../packages/propel/src/**/*.{js,ts,jsx,tsx}", + "../../packages/editor/src/**/*.{js,ts,jsx,tsx}", + "!../../packages/ui/**/*.stories{js,ts,jsx,tsx}", ], }, theme: { @@ -396,6 +396,9 @@ module.exports = { 80: "18rem", 96: "21.6rem", }, + height: { + header: "3.25rem", + }, space: { 0: "0", 0.5: "0.1125rem", @@ -484,6 +487,14 @@ module.exports = { paddingRight: "1.35rem", }, }, + // Hide scrollbar but keep functionality + ".scrollbar-hide": { + "-ms-overflow-style": "none" /* IE and Edge */, + "scrollbar-width": "none" /* Firefox */, + "&::-webkit-scrollbar": { + display: "none" /* Chrome, Safari and Opera */, + }, + }, }; addUtilities(newUtilities, ["responsive"]); diff --git a/packages/types/.eslintrc.js b/packages/types/.eslintrc.js new file mode 100644 index 000000000..c9472ec20 --- /dev/null +++ b/packages/types/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + root: true, + extends: ["@plane/eslint-config/library.js"], + parser: "@typescript-eslint/parser", +}; diff --git a/packages/types/package.json b/packages/types/package.json index 2a5f55062..7d501bc9a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,8 +1,35 @@ { "name": "@plane/types", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "private": true, - "types": "./src/index.d.ts", - "main": "./src/index.d.ts" + "files": [ + "dist" + ], + "types": "./dist/index.d.ts", + "main": "./dist/index.js", + "module": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "require": "./dist/index.js", + "import": "./dist/index.js" + } + }, + "scripts": { + "dev": "tsup --watch", + "build": "tsc --noEmit && tsup --minify", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" + }, + "devDependencies": { + "@plane/eslint-config": "*", + "@plane/typescript-config": "*", + "tsup": "8.4.0", + "typescript": "5.8.3" + } } diff --git a/packages/types/src/activity.d.ts b/packages/types/src/activity.ts similarity index 57% rename from packages/types/src/activity.d.ts rename to packages/types/src/activity.ts index 98d54dabc..957a2028d 100644 --- a/packages/types/src/activity.d.ts +++ b/packages/types/src/activity.ts @@ -1,7 +1,4 @@ -export type TBaseActivity< - TFieldKey extends string = string, - TVerbKey extends string = string, -> = { +export type TBaseActivity = { id: string; field: TFieldKey | undefined; epoch: number; @@ -19,17 +16,14 @@ export type TBaseActivity< updated_at: string; }; -export type TWorkspaceBaseActivity< - K extends string = string, - V extends string = string, -> = TBaseActivity & { +export type TWorkspaceBaseActivity = TBaseActivity & { workspace: string; }; -export type TProjectBaseActivity< - K extends string = string, - V extends string = string, -> = TWorkspaceBaseActivity & { +export type TProjectBaseActivity = TWorkspaceBaseActivity< + K, + V +> & { project: string; }; diff --git a/packages/types/src/ai.d.ts b/packages/types/src/ai.ts similarity index 65% rename from packages/types/src/ai.d.ts rename to packages/types/src/ai.ts index ce8bcbadb..d1c2d2441 100644 --- a/packages/types/src/ai.d.ts +++ b/packages/types/src/ai.ts @@ -1,4 +1,5 @@ -import { IProjectLite, IWorkspaceLite } from "@plane/types"; +import { IProjectLite } from "./project"; +import { IWorkspaceLite } from "./workspace"; export interface IGptResponse { response: string; diff --git a/packages/types/src/analytics.d.ts b/packages/types/src/analytics.ts similarity index 58% rename from packages/types/src/analytics.d.ts rename to packages/types/src/analytics.ts index 80c773fa2..e66794f7c 100644 --- a/packages/types/src/analytics.d.ts +++ b/packages/types/src/analytics.ts @@ -1,6 +1,34 @@ -import { ChartXAxisProperty, ChartYAxisMetric } from "@plane/constants"; import { TChartData } from "./charts"; -import { Row } from "@tanstack/react-table"; + +export enum ChartXAxisProperty { + STATES = "STATES", + STATE_GROUPS = "STATE_GROUPS", + LABELS = "LABELS", + ASSIGNEES = "ASSIGNEES", + ESTIMATE_POINTS = "ESTIMATE_POINTS", + CYCLES = "CYCLES", + MODULES = "MODULES", + PRIORITY = "PRIORITY", + START_DATE = "START_DATE", + TARGET_DATE = "TARGET_DATE", + CREATED_AT = "CREATED_AT", + COMPLETED_AT = "COMPLETED_AT", + CREATED_BY = "CREATED_BY", + WORK_ITEM_TYPES = "WORK_ITEM_TYPES", + PROJECTS = "PROJECTS", + EPICS = "EPICS", +} + +export enum ChartYAxisMetric { + WORK_ITEM_COUNT = "WORK_ITEM_COUNT", + ESTIMATE_POINT_COUNT = "ESTIMATE_POINT_COUNT", + PENDING_WORK_ITEM_COUNT = "PENDING_WORK_ITEM_COUNT", + COMPLETED_WORK_ITEM_COUNT = "COMPLETED_WORK_ITEM_COUNT", + IN_PROGRESS_WORK_ITEM_COUNT = "IN_PROGRESS_WORK_ITEM_COUNT", + WORK_ITEM_DUE_THIS_WEEK_COUNT = "WORK_ITEM_DUE_THIS_WEEK_COUNT", + WORK_ITEM_DUE_TODAY_COUNT = "WORK_ITEM_DUE_TODAY_COUNT", + BLOCKED_WORK_ITEM_COUNT = "BLOCKED_WORK_ITEM_COUNT", +} export type TAnalyticsTabsBase = "overview" | "work-items"; export type TAnalyticsGraphsBase = "projects" | "work-items" | "custom-work-items"; @@ -59,9 +87,3 @@ export interface IAnalyticsParams { y_axis: ChartYAxisMetric; group_by?: ChartXAxisProperty; } - -export type ExportConfig = { - key: string; - value: (row: Row) => string | number; - label?: string; -}; diff --git a/packages/types/src/api_token.d.ts b/packages/types/src/api_token.ts similarity index 100% rename from packages/types/src/api_token.d.ts rename to packages/types/src/api_token.ts diff --git a/packages/types/src/auth.d.ts b/packages/types/src/auth.ts similarity index 100% rename from packages/types/src/auth.d.ts rename to packages/types/src/auth.ts diff --git a/packages/types/src/calendar.d.ts b/packages/types/src/calendar.ts similarity index 100% rename from packages/types/src/calendar.d.ts rename to packages/types/src/calendar.ts diff --git a/packages/types/src/charts/common.d.ts b/packages/types/src/charts/common.ts similarity index 98% rename from packages/types/src/charts/common.d.ts rename to packages/types/src/charts/common.ts index 85034c2fe..082702138 100644 --- a/packages/types/src/charts/common.d.ts +++ b/packages/types/src/charts/common.ts @@ -1,5 +1,3 @@ - - export type TChartColorScheme = "modern" | "horizon" | "earthen"; export type TChartDatum = { @@ -12,5 +10,3 @@ export type TChart = { data: TChartDatum[]; schema: Record; }; - - diff --git a/packages/types/src/charts/index.d.ts b/packages/types/src/charts/index.ts similarity index 98% rename from packages/types/src/charts/index.d.ts rename to packages/types/src/charts/index.ts index 685aed214..fb49c7172 100644 --- a/packages/types/src/charts/index.d.ts +++ b/packages/types/src/charts/index.ts @@ -21,7 +21,7 @@ export type TChartData = { [key in K]: string | number; } & Record; -type TChartProps = { +export type TChartProps = { data: TChartData[]; xAxis: { key: keyof TChartData; diff --git a/packages/types/src/command-palette.d.ts b/packages/types/src/command-palette.ts similarity index 65% rename from packages/types/src/command-palette.d.ts rename to packages/types/src/command-palette.ts index 6e072ab8f..c773c2d36 100644 --- a/packages/types/src/command-palette.d.ts +++ b/packages/types/src/command-palette.ts @@ -1,7 +1,4 @@ -export type TCommandPaletteActionList = Record< - string, - { title: string; description: string; action: () => void } ->; +export type TCommandPaletteActionList = Record void }>; export type TCommandPaletteShortcutList = { key: string; diff --git a/packages/types/src/common.d.ts b/packages/types/src/common.ts similarity index 100% rename from packages/types/src/common.d.ts rename to packages/types/src/common.ts diff --git a/packages/types/src/current-user/profile.d.ts b/packages/types/src/current-user/profile.ts similarity index 100% rename from packages/types/src/current-user/profile.d.ts rename to packages/types/src/current-user/profile.ts diff --git a/packages/types/src/cycle/cycle.d.ts b/packages/types/src/cycle/cycle.ts similarity index 97% rename from packages/types/src/cycle/cycle.d.ts rename to packages/types/src/cycle/cycle.ts index 218219914..4bb66ff9b 100644 --- a/packages/types/src/cycle/cycle.d.ts +++ b/packages/types/src/cycle/cycle.ts @@ -1,4 +1,5 @@ -import type { TIssue, IIssueFilterOptions } from "@plane/types"; +import type { TIssue } from "../issues/issue"; +import type { IIssueFilterOptions } from "../view-props"; export type TCycleGroups = "current" | "upcoming" | "completed" | "draft"; diff --git a/packages/types/src/cycle/cycle_filters.d.ts b/packages/types/src/cycle/cycle_filters.ts similarity index 100% rename from packages/types/src/cycle/cycle_filters.d.ts rename to packages/types/src/cycle/cycle_filters.ts diff --git a/packages/types/src/cycle/index.d.ts b/packages/types/src/cycle/index.ts similarity index 100% rename from packages/types/src/cycle/index.d.ts rename to packages/types/src/cycle/index.ts diff --git a/packages/types/src/dashboard.d.ts b/packages/types/src/dashboard.ts similarity index 96% rename from packages/types/src/dashboard.d.ts rename to packages/types/src/dashboard.ts index 96efea007..ac2339d1c 100644 --- a/packages/types/src/dashboard.d.ts +++ b/packages/types/src/dashboard.ts @@ -2,7 +2,7 @@ import { EDurationFilters } from "./enums"; import { IIssueActivity, TIssuePriorities } from "./issues"; import { TIssue } from "./issues/issue"; import { TStateGroups } from "./state"; -import { TIssueRelationTypes } from "@/plane-web/types"; +import { TIssueRelationTypes } from "./issues/issue_relation"; export type TWidgetKeys = | "overview_stats" @@ -161,7 +161,7 @@ export type TWidgetStatsResponse = | TRecentCollaboratorsWidgetResponse[]; // dashboard -export type TDashboard = { +export type TDeprecatedDashboard = { created_at: string; created_by: string | null; description_html: string; @@ -176,6 +176,6 @@ export type TDashboard = { }; export type THomeDashboardResponse = { - dashboard: TDashboard; + dashboard: TDeprecatedDashboard; widgets: TWidget[]; }; diff --git a/packages/types/src/de-dupe.d.ts b/packages/types/src/de-dupe.ts similarity index 100% rename from packages/types/src/de-dupe.d.ts rename to packages/types/src/de-dupe.ts diff --git a/packages/types/src/description_version.d.ts b/packages/types/src/description_version.ts similarity index 100% rename from packages/types/src/description_version.d.ts rename to packages/types/src/description_version.ts diff --git a/packages/types/src/epics.d.ts b/packages/types/src/epics.ts similarity index 100% rename from packages/types/src/epics.d.ts rename to packages/types/src/epics.ts diff --git a/packages/types/src/estimate.d.ts b/packages/types/src/estimate.ts similarity index 100% rename from packages/types/src/estimate.d.ts rename to packages/types/src/estimate.ts diff --git a/packages/types/src/favorite/favorite.d.ts b/packages/types/src/favorite/favorite.ts similarity index 100% rename from packages/types/src/favorite/favorite.d.ts rename to packages/types/src/favorite/favorite.ts diff --git a/packages/types/src/favorite/index.d.ts b/packages/types/src/favorite/index.ts similarity index 100% rename from packages/types/src/favorite/index.d.ts rename to packages/types/src/favorite/index.ts diff --git a/packages/types/src/file.d.ts b/packages/types/src/file.ts similarity index 100% rename from packages/types/src/file.d.ts rename to packages/types/src/file.ts diff --git a/packages/types/src/home.d.ts b/packages/types/src/home.ts similarity index 100% rename from packages/types/src/home.d.ts rename to packages/types/src/home.ts diff --git a/packages/types/src/importer/github-importer.d.ts b/packages/types/src/importer/github-importer.ts similarity index 100% rename from packages/types/src/importer/github-importer.d.ts rename to packages/types/src/importer/github-importer.ts diff --git a/packages/types/src/importer/index.d.ts b/packages/types/src/importer/index.ts similarity index 100% rename from packages/types/src/importer/index.d.ts rename to packages/types/src/importer/index.ts diff --git a/packages/types/src/importer/jira-importer.d.ts b/packages/types/src/importer/jira-importer.ts similarity index 96% rename from packages/types/src/importer/jira-importer.d.ts rename to packages/types/src/importer/jira-importer.ts index cd9e31ad2..e9f4218fa 100644 --- a/packages/types/src/importer/jira-importer.d.ts +++ b/packages/types/src/importer/jira-importer.ts @@ -44,7 +44,7 @@ export interface IJiraResponseUser { accountId: string; accountType: string; emailAddress: string; - avatarUrls: AvatarUrls; + avatarUrls: IJiraResponseAvatarUrls; displayName: string; active: boolean; locale: string; diff --git a/packages/types/src/inbox.d.ts b/packages/types/src/inbox.ts similarity index 74% rename from packages/types/src/inbox.d.ts rename to packages/types/src/inbox.ts index e7065c6d0..d439f333a 100644 --- a/packages/types/src/inbox.d.ts +++ b/packages/types/src/inbox.ts @@ -1,8 +1,40 @@ -// plane constants -import { TInboxIssue, TInboxIssueStatus } from "@plane/constants"; // plane types import { TPaginationInfo } from "./common"; import { TIssuePriorities } from "./issues"; +import { TIssue } from "./issues/issue"; + +export enum EInboxIssueCurrentTab { + OPEN = "open", + CLOSED = "closed", +} + +export type TInboxIssueCurrentTab = EInboxIssueCurrentTab; + +export enum EInboxIssueStatus { + PENDING = -2, + DECLINED = -1, + SNOOZED = 0, + ACCEPTED = 1, + DUPLICATE = 2, +} + +export enum EInboxIssueSource { + IN_APP = "IN_APP", + FORMS = "FORMS", + EMAIL = "EMAIL", +} + +export type TInboxIssueStatus = EInboxIssueStatus; +export type TInboxIssue = { + id: string; + status: TInboxIssueStatus; + snoozed_till: Date | null; + duplicate_to: string | undefined; + source: EInboxIssueSource | undefined; + issue: TIssue; + created_by: string; + duplicate_issue_detail: TInboxDuplicateIssueDetails | undefined; +}; // filters export type TInboxIssueFilterMemberKeys = "assignees" | "created_by"; diff --git a/packages/types/src/index.d.ts b/packages/types/src/index.ts similarity index 98% rename from packages/types/src/index.d.ts rename to packages/types/src/index.ts index ba70ec5c7..ae35062e5 100644 --- a/packages/types/src/index.d.ts +++ b/packages/types/src/index.ts @@ -4,6 +4,7 @@ export * from "./cycle"; export * from "./dashboard"; export * from "./de-dupe"; export * from "./description_version"; +export * from "./enums"; export * from "./project"; export * from "./state"; export * from "./issues"; diff --git a/packages/types/src/instance/ai.d.ts b/packages/types/src/instance/ai.ts similarity index 100% rename from packages/types/src/instance/ai.d.ts rename to packages/types/src/instance/ai.ts diff --git a/packages/types/src/instance/auth.d.ts b/packages/types/src/instance/auth.ts similarity index 77% rename from packages/types/src/instance/auth.d.ts rename to packages/types/src/instance/auth.ts index 31d3a2582..274c5a29c 100644 --- a/packages/types/src/instance/auth.d.ts +++ b/packages/types/src/instance/auth.ts @@ -15,9 +15,7 @@ export type TInstanceAuthenticationMethodKeys = | "IS_GITHUB_ENABLED" | "IS_GITLAB_ENABLED"; -export type TInstanceGoogleAuthenticationConfigurationKeys = - | "GOOGLE_CLIENT_ID" - | "GOOGLE_CLIENT_SECRET"; +export type TInstanceGoogleAuthenticationConfigurationKeys = "GOOGLE_CLIENT_ID" | "GOOGLE_CLIENT_SECRET"; export type TInstanceGithubAuthenticationConfigurationKeys = | "GITHUB_CLIENT_ID" @@ -29,14 +27,12 @@ export type TInstanceGitlabAuthenticationConfigurationKeys = | "GITLAB_CLIENT_ID" | "GITLAB_CLIENT_SECRET"; -type TInstanceAuthenticationConfigurationKeys = +export type TInstanceAuthenticationConfigurationKeys = | TInstanceGoogleAuthenticationConfigurationKeys | TInstanceGithubAuthenticationConfigurationKeys | TInstanceGitlabAuthenticationConfigurationKeys; -export type TInstanceAuthenticationKeys = - | TInstanceAuthenticationMethodKeys - | TInstanceAuthenticationConfigurationKeys; +export type TInstanceAuthenticationKeys = TInstanceAuthenticationMethodKeys | TInstanceAuthenticationConfigurationKeys; export type TGetBaseAuthenticationModeProps = { disabled: boolean; diff --git a/packages/types/src/instance/base.d.ts b/packages/types/src/instance/base.ts similarity index 100% rename from packages/types/src/instance/base.d.ts rename to packages/types/src/instance/base.ts diff --git a/packages/types/src/instance/email.d.ts b/packages/types/src/instance/email.ts similarity index 82% rename from packages/types/src/instance/email.d.ts rename to packages/types/src/instance/email.ts index d7fe8be3d..0c15cd230 100644 --- a/packages/types/src/instance/email.d.ts +++ b/packages/types/src/instance/email.ts @@ -5,4 +5,5 @@ export type TInstanceEmailConfigurationKeys = | "EMAIL_HOST_PASSWORD" | "EMAIL_USE_TLS" | "EMAIL_USE_SSL" - | "EMAIL_FROM"; + | "EMAIL_FROM" + | "ENABLE_SMTP"; diff --git a/packages/types/src/instance/image.d.ts b/packages/types/src/instance/image.ts similarity index 92% rename from packages/types/src/instance/image.d.ts rename to packages/types/src/instance/image.ts index 7eee3bf91..9660a8559 100644 --- a/packages/types/src/instance/image.d.ts +++ b/packages/types/src/instance/image.ts @@ -1 +1 @@ -export type TInstanceImageConfigurationKeys = "UNSPLASH_ACCESS_KEY"; \ No newline at end of file +export type TInstanceImageConfigurationKeys = "UNSPLASH_ACCESS_KEY"; diff --git a/packages/types/src/instance/index.d.ts b/packages/types/src/instance/index.ts similarity index 100% rename from packages/types/src/instance/index.d.ts rename to packages/types/src/instance/index.ts diff --git a/packages/types/src/instance/workspace.d.ts b/packages/types/src/instance/workspace.ts similarity index 100% rename from packages/types/src/instance/workspace.d.ts rename to packages/types/src/instance/workspace.ts diff --git a/packages/types/src/integration.d.ts b/packages/types/src/integration.ts similarity index 97% rename from packages/types/src/integration.d.ts rename to packages/types/src/integration.ts index e2561bd18..a02dc7255 100644 --- a/packages/types/src/integration.d.ts +++ b/packages/types/src/integration.ts @@ -26,7 +26,7 @@ export interface IWorkspaceIntegration { created_by: string; id: string; integration: string; - integration_detail: IIntegrations; + integration_detail: IAppIntegration; metadata: any; updated_at: string; updated_by: string; diff --git a/packages/types/src/issues.d.ts b/packages/types/src/issues.ts similarity index 82% rename from packages/types/src/issues.d.ts rename to packages/types/src/issues.ts index fc7c14ed8..de64c3923 100644 --- a/packages/types/src/issues.d.ts +++ b/packages/types/src/issues.ts @@ -1,22 +1,18 @@ -import { ReactElement } from "react"; -import { KeyedMutator } from "swr"; -import type { - ICycle, - IModule, - IUserLite, - IProjectLite, - IWorkspaceLite, - IStateLite, - Properties, - IIssueDisplayFilterOptions, - TIssue, - IIssueFilterOptions, +import { ICycle } from "./cycle"; +import { TIssue } from "./issues/issue"; +import { IModule } from "./module"; +import { IProjectLite } from "./project"; +import { IStateLite } from "./state"; +import { IUserLite } from "./users"; +import { IIssueDisplayProperties, - TIssueGroupByOptions, - TIssueOrderByOptions, - TIssueGroupingFilters, + IIssueFilterOptions, TIssueExtraOptions, -} from "@plane/types"; + TIssueGroupByOptions, + TIssueGroupingFilters, + TIssueOrderByOptions, +} from "./view-props"; +import { IWorkspaceLite, Properties } from "./workspace"; export interface IIssueCycle { id: string; @@ -70,17 +66,6 @@ export interface ILinkDetails { url: string; } -export type IssueRelationType = "duplicate" | "relates_to" | "blocked_by"; - -export interface IssueRelation { - id: string; - issue: string; - issue_detail: BlockeIssueDetail; - relation_type: IssueRelationType; - related_issue: string; - relation: "blocking" | null; -} - export interface ISubIssuesState { backlog: number; unstarted: number; @@ -186,20 +171,6 @@ export interface IIssueAttachment { workspace: string; } -export interface IIssueViewProps { - groupedIssues: { [key: string]: TIssue[] } | undefined; - displayFilters: IIssueDisplayFilterOptions | undefined; - isEmpty: boolean; - mutateIssues: KeyedMutator< - | TIssue[] - | { - [key: string]: TIssue[]; - } - >; - params: any; - properties: Properties; -} - export type TIssuePriorities = "urgent" | "high" | "medium" | "low" | "none"; export interface ViewFlags { @@ -220,7 +191,7 @@ export type GroupByColumnTypes = | "created_by" | "team_project"; -type TGetColumns = { +export type TGetColumns = { isWorkspaceLevel?: boolean; projectId?: string; }; @@ -228,7 +199,7 @@ type TGetColumns = { export interface IGroupByColumn { id: string; name: string; - icon?: ReactElement | undefined; + icon?: React.ReactElement | undefined; payload: Partial; isDropDisabled?: boolean; dropErrorMessage?: string; @@ -243,7 +214,7 @@ export interface IIssueListRow { groupId: string; type: "HEADER" | "NO_ISSUES" | "QUICK_ADD" | "ISSUE"; name?: string; - icon?: ReactElement | undefined; + icon?: React.ReactElement | undefined; payload?: Partial; } diff --git a/packages/types/src/issues/activity/base.d.ts b/packages/types/src/issues/activity/base.ts similarity index 96% rename from packages/types/src/issues/activity/base.d.ts rename to packages/types/src/issues/activity/base.ts index 7b5653aed..7b6493349 100644 --- a/packages/types/src/issues/activity/base.d.ts +++ b/packages/types/src/issues/activity/base.ts @@ -2,7 +2,7 @@ export * from "./issue_activity"; export * from "./issue_comment"; export * from "./issue_comment_reaction"; -import { TIssuePriorities } from "../issues"; +import { TIssuePriorities } from "../../issues"; // root types export type TIssueActivityWorkspaceDetail = { diff --git a/packages/types/src/issues/activity/issue_activity.d.ts b/packages/types/src/issues/activity/issue_activity.ts similarity index 94% rename from packages/types/src/issues/activity/issue_activity.d.ts rename to packages/types/src/issues/activity/issue_activity.ts index 7ed0c35d6..15a37a4a7 100644 --- a/packages/types/src/issues/activity/issue_activity.d.ts +++ b/packages/types/src/issues/activity/issue_activity.ts @@ -1,5 +1,3 @@ -// plane imports -import { EInboxIssueSource } from "@plane/constants"; // local imports import { TIssueActivityWorkspaceDetail, @@ -7,6 +5,7 @@ import { TIssueActivityIssueDetail, TIssueActivityUserDetail, } from "./base"; +import { EInboxIssueSource } from "../../inbox"; export type TIssueActivity = { id: string; diff --git a/packages/types/src/issues/activity/issue_comment.d.ts b/packages/types/src/issues/activity/issue_comment.ts similarity index 73% rename from packages/types/src/issues/activity/issue_comment.d.ts rename to packages/types/src/issues/activity/issue_comment.ts index e61b35585..1a4b557b5 100644 --- a/packages/types/src/issues/activity/issue_comment.d.ts +++ b/packages/types/src/issues/activity/issue_comment.ts @@ -7,6 +7,7 @@ import { import { EIssueCommentAccessSpecifier } from "../../enums"; import { TFileSignedURLResponse } from "../../file"; import { IUserLite } from "../../users"; +import { IWorkspaceLite } from "../../workspace"; export type TCommentReaction = { id: string; @@ -40,12 +41,13 @@ export type TIssueComment = { }; export type TCommentsOperations = { + copyCommentLink: (commentId: string) => void; createComment: (data: Partial) => Promise | undefined>; updateComment: (commentId: string, data: Partial) => Promise; removeComment: (commentId: string) => Promise; uploadCommentAsset: (blockId: string, file: File, commentId?: string) => Promise; addCommentReaction: (commentId: string, reactionEmoji: string) => Promise; - deleteCommentReaction: (commentId: string, reactionEmoji: string, userReactions: TCommentReaction[]) => Promise; + deleteCommentReaction: (commentId: string, reactionEmoji: string) => Promise; react: (commentId: string, reactionEmoji: string, userReactions: string[]) => Promise; reactionIds: (commentId: string) => | { @@ -64,6 +66,57 @@ export type TIssueCommentIdMap = { [issue_id: string]: string[]; }; +export interface ActorDetail { + avatar_url?: string; + display_name?: string; + first_name?: string; + is_bot?: boolean; + id?: string; + last_name?: string; +} + +export interface IssueDetail { + id: string; + name: string; + description: Description; + description_html: string; + priority: string; + start_date: null; + target_date: null; + sequence_id: number; + sort_order: number; +} + +export interface Description { + type: string; + content: DescriptionContent[]; +} + +export interface DescriptionContent { + type: string; + attrs?: Attrs; + content: ContentContent[]; +} + +export interface Attrs { + level: number; +} + +export interface ContentContent { + text: string; + type: string; +} + +export interface ProjectDetail { + id: string; + identifier: string; + name: string; + cover_image: string; + icon_prop: null; + emoji: string; + description: string; +} + export type TIssuePublicComment = { actor_detail: ActorDetail; access: string; diff --git a/packages/types/src/issues/activity/issue_comment_reaction.d.ts b/packages/types/src/issues/activity/issue_comment_reaction.ts similarity index 100% rename from packages/types/src/issues/activity/issue_comment_reaction.d.ts rename to packages/types/src/issues/activity/issue_comment_reaction.ts diff --git a/packages/types/src/issues/base.d.ts b/packages/types/src/issues/base.ts similarity index 79% rename from packages/types/src/issues/base.d.ts rename to packages/types/src/issues/base.ts index 05f679cce..26054bf13 100644 --- a/packages/types/src/issues/base.d.ts +++ b/packages/types/src/issues/base.ts @@ -1,6 +1,3 @@ -import { StateGroup } from "components/states"; -import { TIssuePriorities } from "../issues"; - // issues export * from "./issue"; export * from "./issue_reaction"; @@ -10,13 +7,7 @@ export * from "./issue_relation"; export * from "./issue_sub_issues"; export * from "./activity/base"; - -export type TLoader = - | "init-loader" - | "mutation" - | "pagination" - | "loaded" - | undefined; +export type TLoader = "init-loader" | "mutation" | "pagination" | "loaded" | undefined; export type TGroupedIssues = { [group_id: string]: string[]; diff --git a/packages/types/src/issues/issue.d.ts b/packages/types/src/issues/issue.ts similarity index 84% rename from packages/types/src/issues/issue.d.ts rename to packages/types/src/issues/issue.ts index 01c0b2f3a..695b3ebc8 100644 --- a/packages/types/src/issues/issue.d.ts +++ b/packages/types/src/issues/issue.ts @@ -1,11 +1,39 @@ -import { EIssueServiceType, EIssuesStoreType } from "@plane/constants"; import { TIssuePriorities } from "../issues"; import { TIssueAttachment } from "./issue_attachment"; import { TIssueLink } from "./issue_link"; import { TIssueReaction, IIssuePublicReaction, IPublicVote } from "./issue_reaction"; -import { TIssueRelationTypes, TIssuePublicComment } from "@/plane-web/types"; +import { TIssueRelationTypes } from "./issue_relation"; +import { TIssuePublicComment } from "./activity/issue_comment"; -// new issue structure types +export enum EIssueLayoutTypes { + LIST = "list", + KANBAN = "kanban", + CALENDAR = "calendar", + GANTT = "gantt_chart", + SPREADSHEET = "spreadsheet", +} + +export enum EIssueServiceType { + ISSUES = "issues", + EPICS = "epics", + WORK_ITEMS = "work-items", +} + +export enum EIssuesStoreType { + GLOBAL = "GLOBAL", + PROFILE = "PROFILE", + TEAM = "TEAM", + PROJECT = "PROJECT", + CYCLE = "CYCLE", + MODULE = "MODULE", + TEAM_VIEW = "TEAM_VIEW", + PROJECT_VIEW = "PROJECT_VIEW", + ARCHIVED = "ARCHIVED", + DRAFT = "DRAFT", + DEFAULT = "DEFAULT", + WORKSPACE_DRAFT = "WORKSPACE_DRAFT", + EPIC = "EPIC", +} export type TBaseIssue = { id: string; @@ -71,7 +99,7 @@ export type TIssueMap = { [issue_id: string]: TIssue; }; -type TIssueResponseResults = +export type TIssueResponseResults = | TBaseIssue[] | { [key: string]: { @@ -153,7 +181,7 @@ export interface IPublicIssue vote_items: IPublicVote[]; } -type TPublicIssueResponseResults = +export type TPublicIssueResponseResults = | IPublicIssue[] | { [key: string]: { @@ -187,4 +215,4 @@ export interface IWorkItemPeekOverview { embedRemoveCurrentNotification?: () => void; is_draft?: boolean; storeType?: EIssuesStoreType; -} \ No newline at end of file +} diff --git a/packages/types/src/issues/issue_attachment.d.ts b/packages/types/src/issues/issue_attachment.ts similarity index 94% rename from packages/types/src/issues/issue_attachment.d.ts rename to packages/types/src/issues/issue_attachment.ts index f7503b9d2..d118568af 100644 --- a/packages/types/src/issues/issue_attachment.d.ts +++ b/packages/types/src/issues/issue_attachment.ts @@ -15,7 +15,7 @@ export type TIssueAttachment = { }; export type TIssueAttachmentUploadResponse = TFileSignedURLResponse & { - attachment: TIssueAttachment + attachment: TIssueAttachment; }; export type TIssueAttachmentMap = { diff --git a/packages/types/src/issues/issue_link.d.ts b/packages/types/src/issues/issue_link.ts similarity index 100% rename from packages/types/src/issues/issue_link.d.ts rename to packages/types/src/issues/issue_link.ts diff --git a/packages/types/src/issues/issue_reaction.d.ts b/packages/types/src/issues/issue_reaction.ts similarity index 100% rename from packages/types/src/issues/issue_reaction.d.ts rename to packages/types/src/issues/issue_reaction.ts diff --git a/packages/types/src/issues/issue_relation.d.ts b/packages/types/src/issues/issue_relation.ts similarity index 65% rename from packages/types/src/issues/issue_relation.d.ts rename to packages/types/src/issues/issue_relation.ts index 378470a58..53dc178f4 100644 --- a/packages/types/src/issues/issue_relation.d.ts +++ b/packages/types/src/issues/issue_relation.ts @@ -1,5 +1,4 @@ -import { TIssueRelationTypes } from "@/plane-web/types"; -import { TIssue } from "./issues"; +import { TIssue } from "./issue"; export type TIssueRelation = Record; @@ -8,3 +7,5 @@ export type TIssueRelationMap = { }; export type TIssueRelationIdMap = Record; + +export type TIssueRelationTypes = "blocking" | "blocked_by" | "duplicate" | "relates_to"; diff --git a/packages/types/src/issues/issue_sub_issues.d.ts b/packages/types/src/issues/issue_sub_issues.ts similarity index 100% rename from packages/types/src/issues/issue_sub_issues.d.ts rename to packages/types/src/issues/issue_sub_issues.ts diff --git a/packages/types/src/issues/issue_subscription.ts b/packages/types/src/issues/issue_subscription.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/types/src/layout/gantt.d.ts b/packages/types/src/layout/gantt.ts similarity index 84% rename from packages/types/src/layout/gantt.d.ts rename to packages/types/src/layout/gantt.ts index 990ae3fc3..0fb54615c 100644 --- a/packages/types/src/layout/gantt.d.ts +++ b/packages/types/src/layout/gantt.ts @@ -1,3 +1,8 @@ +export enum EGanttBlockType { + EPIC = "epic", + PROJECT = "project", + ISSUE = "issue", +} export interface IGanttBlock { data: any; id: string; @@ -9,7 +14,7 @@ export interface IGanttBlock { sort_order: number | undefined; start_date: string | undefined; target_date: string | undefined; - project_id: string | undefined; + meta?: Record; } export interface IBlockUpdateData { @@ -20,13 +25,14 @@ export interface IBlockUpdateData { }; start_date?: string; target_date?: string; + meta?: Record; } export interface IBlockUpdateDependencyData { id: string; start_date?: string; target_date?: string; - project_id?: string; + meta?: Record; } export type TGanttViews = "week" | "month" | "quarter"; diff --git a/packages/types/src/module/index.d.ts b/packages/types/src/module/index.ts similarity index 100% rename from packages/types/src/module/index.d.ts rename to packages/types/src/module/index.ts diff --git a/packages/types/src/module/module_filters.d.ts b/packages/types/src/module/module_filters.ts similarity index 100% rename from packages/types/src/module/module_filters.d.ts rename to packages/types/src/module/module_filters.ts diff --git a/packages/types/src/module/modules.d.ts b/packages/types/src/module/modules.ts similarity index 88% rename from packages/types/src/module/modules.d.ts rename to packages/types/src/module/modules.ts index ce845e60d..50e9e8af0 100644 --- a/packages/types/src/module/modules.d.ts +++ b/packages/types/src/module/modules.ts @@ -1,12 +1,8 @@ -import type { TIssue, IIssueFilterOptions, ILinkDetails } from "@plane/types"; +import type { TIssue } from "../issues/issue"; +import type { IIssueFilterOptions } from "../view-props"; +import type { ILinkDetails } from "../issues"; -export type TModuleStatus = - | "backlog" - | "planned" - | "in-progress" - | "paused" - | "completed" - | "cancelled"; +export type TModuleStatus = "backlog" | "planned" | "in-progress" | "paused" | "completed" | "cancelled"; export type TModuleCompletionChartDistribution = { [key: string]: number | null; @@ -112,9 +108,7 @@ export type ModuleLink = { url: string; }; -export type SelectModuleType = - | (IModule & { actionType: "edit" | "delete" | "create-issue" }) - | undefined; +export type SelectModuleType = (IModule & { actionType: "edit" | "delete" | "create-issue" }) | undefined; export type TModulePlotType = "burndown" | "points"; diff --git a/packages/types/src/page/core.d.ts b/packages/types/src/page/core.ts similarity index 100% rename from packages/types/src/page/core.d.ts rename to packages/types/src/page/core.ts diff --git a/packages/types/src/page/extended.d.ts b/packages/types/src/page/extended.ts similarity index 100% rename from packages/types/src/page/extended.d.ts rename to packages/types/src/page/extended.ts diff --git a/packages/types/src/page/index.d.ts b/packages/types/src/page/index.ts similarity index 100% rename from packages/types/src/page/index.d.ts rename to packages/types/src/page/index.ts diff --git a/packages/types/src/payment.d.ts b/packages/types/src/payment.ts similarity index 84% rename from packages/types/src/payment.d.ts rename to packages/types/src/payment.ts index bdbab7f32..21e22e631 100644 --- a/packages/types/src/payment.d.ts +++ b/packages/types/src/payment.ts @@ -1,4 +1,10 @@ -import { EProductSubscriptionEnum } from "@plane/constants"; +export enum EProductSubscriptionEnum { + FREE = "FREE", + ONE = "ONE", + PRO = "PRO", + BUSINESS = "BUSINESS", + ENTERPRISE = "ENTERPRISE", +} export type TBillingFrequency = "month" | "year"; diff --git a/packages/types/src/pragmatic.d.ts b/packages/types/src/pragmatic.ts similarity index 83% rename from packages/types/src/pragmatic.d.ts rename to packages/types/src/pragmatic.ts index 439e2b54f..bd0969ce2 100644 --- a/packages/types/src/pragmatic.d.ts +++ b/packages/types/src/pragmatic.ts @@ -26,9 +26,4 @@ export interface IPragmaticDropPayload { self: TDropTarget & TDropTargetMiscellaneousData; } -export type InstructionType = - | "reparent" - | "reorder-above" - | "reorder-below" - | "make-child" - | "instruction-blocked"; \ No newline at end of file +export type InstructionType = "reparent" | "reorder-above" | "reorder-below" | "make-child" | "instruction-blocked"; diff --git a/packages/types/src/project/project_filters.d.ts b/packages/types/src/project/project_filters.ts similarity index 86% rename from packages/types/src/project/project_filters.d.ts rename to packages/types/src/project/project_filters.ts index 77da7365f..4c21488ab 100644 --- a/packages/types/src/project/project_filters.d.ts +++ b/packages/types/src/project/project_filters.ts @@ -13,9 +13,7 @@ export type TProjectDisplayFilters = { order_by?: TProjectOrderByOptions; }; -export type TProjectAppliedDisplayFilterKeys = - | "my_projects" - | "archived_projects"; +export type TProjectAppliedDisplayFilterKeys = "my_projects" | "archived_projects"; export type TProjectFilters = { access?: string[] | null; diff --git a/packages/types/src/project/project_link.d.ts b/packages/types/src/project/project_link.ts similarity index 100% rename from packages/types/src/project/project_link.d.ts rename to packages/types/src/project/project_link.ts diff --git a/packages/types/src/project/projects.d.ts b/packages/types/src/project/projects.ts similarity index 89% rename from packages/types/src/project/projects.d.ts rename to packages/types/src/project/projects.ts index 9d6b03ab1..692768875 100644 --- a/packages/types/src/project/projects.d.ts +++ b/packages/types/src/project/projects.ts @@ -1,6 +1,14 @@ -import { EUserProjectRoles } from "@plane/constants"; -import type { IUser, IUserLite, IWorkspace, TLogoProps, TStateGroups } from ".."; +import { TLogoProps } from "../common"; import { TUserPermissions } from "../enums"; +import { TStateGroups } from "../state"; +import type { IUser, IUserLite } from "../users"; +import type { IWorkspace } from "../workspace"; + +export enum EUserProjectRoles { + ADMIN = 20, + MEMBER = 15, + GUEST = 5, +} export interface IPartialProject { id: string; @@ -65,7 +73,7 @@ export interface IProjectLite { logo_props: TLogoProps; } -type ProjectPreferences = { +export type ProjectPreferences = { pages: { block_display: boolean; }; @@ -144,4 +152,4 @@ export interface ISearchIssueResponse { export type TPartialProject = IPartialProject; -export type TProject = TPartialProject & IProject; +export type TProject = TPartialProject & IProject; diff --git a/packages/types/src/publish.d.ts b/packages/types/src/publish.ts similarity index 72% rename from packages/types/src/publish.d.ts rename to packages/types/src/publish.ts index 83d21d90b..358d6e5da 100644 --- a/packages/types/src/publish.d.ts +++ b/packages/types/src/publish.ts @@ -1,13 +1,9 @@ -import { IProject, IProjectLite, IWorkspaceLite } from "@plane/types"; +import { IProject, IProjectLite } from "./project"; +import { IWorkspaceLite } from "./workspace"; export type TPublishEntityType = "project" | "page"; -export type TProjectPublishLayouts = - | "calendar" - | "gantt" - | "kanban" - | "list" - | "spreadsheet"; +export type TProjectPublishLayouts = "calendar" | "gantt" | "kanban" | "list" | "spreadsheet"; export type TProjectPublishViewProps = { calendar?: boolean; @@ -17,10 +13,9 @@ export type TProjectPublishViewProps = { spreadsheet?: boolean; }; -export type TProjectDetails = IProjectLite & - Pick; +export type TProjectDetails = IProjectLite & Pick; -type TPublishSettings = { +export type TPublishSettings = { anchor: string | undefined; created_at: string | undefined; created_by: string | undefined; diff --git a/packages/types/src/reaction.d.ts b/packages/types/src/reaction.ts similarity index 100% rename from packages/types/src/reaction.d.ts rename to packages/types/src/reaction.ts diff --git a/packages/types/src/search.d.ts b/packages/types/src/search.ts similarity index 100% rename from packages/types/src/search.d.ts rename to packages/types/src/search.ts diff --git a/packages/types/src/state.d.ts b/packages/types/src/state.ts similarity index 92% rename from packages/types/src/state.d.ts rename to packages/types/src/state.ts index 38d0abe12..7392606e2 100644 --- a/packages/types/src/state.d.ts +++ b/packages/types/src/state.ts @@ -1,5 +1,3 @@ -import { IProject, IProjectLite, IWorkspaceLite } from "@plane/types"; - export type TStateGroups = "backlog" | "unstarted" | "started" | "completed" | "cancelled"; export interface IState { diff --git a/packages/types/src/stickies.d copy.ts b/packages/types/src/stickies.d copy.ts deleted file mode 100644 index 55f8b23c5..000000000 --- a/packages/types/src/stickies.d copy.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type TSticky = { - id: string; - name?: string; - description_html?: string; - color?: string; - createdAt?: Date; - updatedAt?: Date; -}; diff --git a/packages/types/src/stickies.d.ts b/packages/types/src/stickies.ts similarity index 100% rename from packages/types/src/stickies.d.ts rename to packages/types/src/stickies.ts diff --git a/packages/types/src/timezone.d.ts b/packages/types/src/timezone.ts similarity index 100% rename from packages/types/src/timezone.d.ts rename to packages/types/src/timezone.ts diff --git a/packages/types/src/users.d.ts b/packages/types/src/users.ts similarity index 94% rename from packages/types/src/users.d.ts rename to packages/types/src/users.ts index 7694c2406..3258d14dc 100644 --- a/packages/types/src/users.d.ts +++ b/packages/types/src/users.ts @@ -1,8 +1,21 @@ -import { EStartOfTheWeek } from "@plane/constants"; import { IIssueActivity, TIssuePriorities, TStateGroups } from "."; import { TUserPermissions } from "./enums"; -type TLoginMediums = "email" | "magic-code" | "github" | "gitlab" | "google"; +/** + * @description The start of the week for the user + * @enum {number} + */ +export enum EStartOfTheWeek { + SUNDAY = 0, + MONDAY = 1, + TUESDAY = 2, + WEDNESDAY = 3, + THURSDAY = 4, + FRIDAY = 5, + SATURDAY = 6, +} + +export type TLoginMediums = "email" | "magic-code" | "github" | "gitlab" | "google"; export interface IUserLite { avatar_url: string; @@ -19,7 +32,7 @@ export interface IUser extends IUserLite { cover_image_asset?: string | null; cover_image?: string | null; // only for rendering the cover image - cover_image_url: readonly (string | null); + cover_image_url: string | null; date_joined: string; email: string; is_active: boolean; diff --git a/packages/types/src/utils.d.ts b/packages/types/src/utils.ts similarity index 100% rename from packages/types/src/utils.d.ts rename to packages/types/src/utils.ts diff --git a/packages/types/src/view-props.d.ts b/packages/types/src/view-props.ts similarity index 92% rename from packages/types/src/view-props.d.ts rename to packages/types/src/view-props.ts index 509ee5495..2a6b9f22b 100644 --- a/packages/types/src/view-props.d.ts +++ b/packages/types/src/view-props.ts @@ -160,13 +160,6 @@ export interface IWorkspaceIssueFilterOptions { project?: string[] | null; } -export interface IWorkspaceGlobalViewDisplayFilterOptions { - order_by?: string | undefined; - type?: "active" | "backlog" | null; - sub_issue?: boolean; - layout?: TIssueViewOptions; -} - export interface IWorkspaceViewIssuesParams { assignees?: string | undefined; created_by?: string | undefined; @@ -193,11 +186,6 @@ export interface IWorkspaceViewProps { display_filters: IIssueDisplayFilterOptions | undefined; display_properties: IIssueDisplayProperties; } -export interface IWorkspaceGlobalViewProps { - filters: IWorkspaceIssueFilterOptions; - display_filters: IWorkspaceIssueDisplayFilterOptions | undefined; - display_properties: IIssueDisplayProperties; -} export interface IssuePaginationOptions { canGroup: boolean; diff --git a/packages/types/src/views.d.ts b/packages/types/src/views.ts similarity index 88% rename from packages/types/src/views.d.ts rename to packages/types/src/views.ts index 32b5889ca..79af8b739 100644 --- a/packages/types/src/views.d.ts +++ b/packages/types/src/views.ts @@ -1,10 +1,10 @@ -import { EViewAccess } from "@plane/constants"; import { TLogoProps } from "./common"; -import { - IIssueDisplayFilterOptions, - IIssueDisplayProperties, - IIssueFilterOptions, -} from "./view-props"; +import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "./view-props"; + +export enum EViewAccess { + PRIVATE, + PUBLIC, +} export interface IProjectView { id: string; diff --git a/packages/types/src/waitlist.d.ts b/packages/types/src/waitlist.ts similarity index 100% rename from packages/types/src/waitlist.d.ts rename to packages/types/src/waitlist.ts diff --git a/packages/types/src/webhook.d.ts b/packages/types/src/webhook.ts similarity index 100% rename from packages/types/src/webhook.d.ts rename to packages/types/src/webhook.ts diff --git a/packages/types/src/workspace-draft-issues/base.d.ts b/packages/types/src/workspace-draft-issues/base.ts similarity index 100% rename from packages/types/src/workspace-draft-issues/base.d.ts rename to packages/types/src/workspace-draft-issues/base.ts diff --git a/packages/types/src/workspace-notifications.d.ts b/packages/types/src/workspace-notifications.ts similarity index 100% rename from packages/types/src/workspace-notifications.d.ts rename to packages/types/src/workspace-notifications.ts diff --git a/packages/types/src/workspace-views.d.ts b/packages/types/src/workspace-views.ts similarity index 78% rename from packages/types/src/workspace-views.d.ts rename to packages/types/src/workspace-views.ts index eb207128d..00c07aec5 100644 --- a/packages/types/src/workspace-views.d.ts +++ b/packages/types/src/workspace-views.ts @@ -1,10 +1,10 @@ -import { EViewAccess } from "@plane/constants"; import { IWorkspaceViewProps, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, } from "./view-props"; +import { EViewAccess } from "./views"; export interface IWorkspaceView { id: string; @@ -16,7 +16,7 @@ export interface IWorkspaceView { updated_by: string; name: string; description: string; - filters: IIssueIIFilterOptions; + filters: IIssueFilterOptions; display_filters: IIssueDisplayFilterOptions; display_properties: IIssueDisplayProperties; query: any; @@ -32,8 +32,4 @@ export interface IWorkspaceView { }; } -export type TStaticViewTypes = - | "all-issues" - | "assigned" - | "created" - | "subscribed"; +export type TStaticViewTypes = "all-issues" | "assigned" | "created" | "subscribed"; diff --git a/packages/types/src/workspace.d.ts b/packages/types/src/workspace.ts similarity index 93% rename from packages/types/src/workspace.d.ts rename to packages/types/src/workspace.ts index 0b81e3b91..4b5c3df61 100644 --- a/packages/types/src/workspace.d.ts +++ b/packages/types/src/workspace.ts @@ -1,6 +1,15 @@ -import type { ICycle, TProjectMembership, IUser, IUserLite, IWorkspaceViewProps, TPaginationInfo } from "@plane/types"; -import { EUserWorkspaceRoles } from "@plane/constants"; // TODO: check if importing this over here causes circular dependency +import type { TPaginationInfo } from "./common"; +import type { ICycle } from "./cycle"; import { TUserPermissions } from "./enums"; +import { TProjectMembership } from "./project"; +import type { IUser, IUserLite } from "./users"; +import type { IWorkspaceViewProps } from "./view-props"; + +export enum EUserWorkspaceRoles { + ADMIN = 20, + MEMBER = 15, + GUEST = 5, +} export interface IWorkspace { readonly id: string; @@ -74,6 +83,7 @@ export interface IWorkspaceMember { joining_date?: string; display_name?: string; last_login_medium?: string; + is_active?: boolean; } export interface IWorkspaceMemberMe { diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 000000000..9a94573fb --- /dev/null +++ b/packages/types/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@plane/typescript-config/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "allowSyntheticDefaultImports": true, + "strictNullChecks": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/types/tsup.config.ts b/packages/types/tsup.config.ts new file mode 100644 index 000000000..04ad41425 --- /dev/null +++ b/packages/types/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + format: ["esm", "cjs"], + dts: true, + clean: true, + minify: true, +}); diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 58fe486eb..3099818a3 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@plane/typescript-config", - "version": "0.27.1", + "version": "0.28.0", "license": "AGPL-3.0", "private": true, "files": [ diff --git a/packages/ui/.eslintrc.js b/packages/ui/.eslintrc.js index 1b79b55f3..b11b7bb6d 100644 --- a/packages/ui/.eslintrc.js +++ b/packages/ui/.eslintrc.js @@ -3,8 +3,4 @@ module.exports = { root: true, extends: ["@plane/eslint-config/library.js"], parser: "@typescript-eslint/parser", - parserOptions: { - project: "./tsconfig.json", - tsconfigRootDir: __dirname, - }, }; diff --git a/packages/ui/.storybook/main.ts b/packages/ui/.storybook/main.ts index 06442d65f..4fe51da88 100644 --- a/packages/ui/.storybook/main.ts +++ b/packages/ui/.storybook/main.ts @@ -18,7 +18,7 @@ const config: StorybookConfig = { getAbsolutePath("@storybook/addon-essentials"), getAbsolutePath("@chromatic-com/storybook"), getAbsolutePath("@storybook/addon-interactions"), - "@storybook/addon-styling-webpack" + "@storybook/addon-styling-webpack", ], framework: { name: getAbsolutePath("@storybook/react-webpack5"), diff --git a/packages/ui/package.json b/packages/ui/package.json index dad98d38d..3ef9667ad 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -2,24 +2,27 @@ "name": "@plane/ui", "description": "UI components shared across multiple apps internally", "private": true, - "version": "0.27.1", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", + "version": "0.28.0", "sideEffects": false, "license": "AGPL-3.0", "files": [ - "dist/**" + "dist" ], + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", "scripts": { - "build": "tsup src/index.ts --format esm,cjs --dts --external react --minify", - "dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "build": "tsup --minify", + "dev": "tsup --watch", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", "postcss": "postcss styles/globals.css -o styles/output.css --watch", - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist" }, "peerDependencies": { "react": "^18.3.1", @@ -31,6 +34,7 @@ "@blueprintjs/core": "^4.16.3", "@blueprintjs/popover2": "^1.13.3", "@headlessui/react": "^1.7.3", + "@plane/constants": "*", "@plane/hooks": "*", "@plane/utils": "*", "@popperjs/core": "^2.11.8", @@ -67,7 +71,6 @@ "@types/react-color": "^3.0.9", "@types/react-dom": "^18.2.18", "autoprefixer": "^10.4.19", - "classnames": "^2.3.2", "postcss-cli": "^11.0.0", "postcss-nested": "^6.0.1", "storybook": "^8.1.1", diff --git a/web/ce/components/common/index.ts b/packages/ui/src/billing/index.ts similarity index 100% rename from web/ce/components/common/index.ts rename to packages/ui/src/billing/index.ts diff --git a/web/core/components/workspace/billing/subscription.ts b/packages/ui/src/billing/subscription.ts similarity index 97% rename from web/core/components/workspace/billing/subscription.ts rename to packages/ui/src/billing/subscription.ts index e895d7c98..98c03d337 100644 --- a/web/core/components/workspace/billing/subscription.ts +++ b/packages/ui/src/billing/subscription.ts @@ -1,11 +1,7 @@ // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; +import { EProductSubscriptionEnum } from "@plane/types"; import { cn } from "@plane/utils"; -// --------------- NOTE ---------------- -// This has to be in web application as tailwind won't be able to resolve the colors -// ------------------------------------ - export const getSubscriptionTextColor = ( planVariant: EProductSubscriptionEnum, shade: "200" | "400" = "200" diff --git a/packages/ui/src/breadcrumbs/navigation-dropdown.tsx b/packages/ui/src/breadcrumbs/navigation-dropdown.tsx index 503e13eb2..c07513e4a 100644 --- a/packages/ui/src/breadcrumbs/navigation-dropdown.tsx +++ b/packages/ui/src/breadcrumbs/navigation-dropdown.tsx @@ -45,8 +45,11 @@ export const BreadcrumbNavigationDropdown = (props: TBreadcrumbNavigationDropdow } )} > - {selectedItemIcon && {selectedItemIcon}} - {selectedItem.title} +
    ...
    +
    + {selectedItemIcon && {selectedItemIcon}} + {selectedItem.title} +
    ); diff --git a/packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx b/packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx index 0439d1d33..75cfff35a 100644 --- a/packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx +++ b/packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx @@ -16,6 +16,7 @@ type TBreadcrumbNavigationSearchDropdownProps = { isLast?: boolean; handleOnClick?: () => void; disableRootHover?: boolean; + shouldTruncate?: boolean; }; export const BreadcrumbNavigationSearchDropdown: React.FC = (props) => { @@ -28,6 +29,7 @@ export const BreadcrumbNavigationSearchDropdown: React.FC - {icon && {icon}} - {title} + {shouldTruncate &&
    ...
    } +
    + {icon && {icon}} + {title} +
    void; - Callback function for handling value changes. - options: TDropdownOption[] | undefined; - Array of options. @@ -14,6 +15,7 @@ Below is a detailed list of the props included: --- ### Button Props + - buttonContent?: (isOpen: boolean) => React.ReactNode; - Function to render the content of the button based on the open state. - buttonContainerClassName?: string; - Class name for the button container. - buttonClassName?: string; - Class name for the button itself. @@ -21,6 +23,7 @@ Below is a detailed list of the props included: --- ### Input Props + - disableSearch?: boolean; - Disables the search input if set to true. - inputPlaceholder?: string; - Placeholder text for the search input. - inputClassName?: string; - Class name for the search input. @@ -30,6 +33,7 @@ Below is a detailed list of the props included: --- ### Options Props + - keyExtractor: (option: TDropdownOption) => string; - Function to extract the key from each option. - optionsContainerClassName?: string; - Class name for the options container. - queryArray: string[]; - Array of strings to be used for querying the options. @@ -41,4 +45,4 @@ Below is a detailed list of the props included: --- -These properties offer extensive control over the dropdown's behavior and presentation, making it a highly versatile component suitable for various scenarios. \ No newline at end of file +These properties offer extensive control over the dropdown's behavior and presentation, making it a highly versatile component suitable for various scenarios. diff --git a/packages/ui/src/dropdowns/custom-menu.tsx b/packages/ui/src/dropdowns/custom-menu.tsx index d043ced70..103bd20e1 100644 --- a/packages/ui/src/dropdowns/custom-menu.tsx +++ b/packages/ui/src/dropdowns/custom-menu.tsx @@ -186,7 +186,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => { = (props) => { style={styles.popper} {...attributes.popper} className={cn( - "fixed z-[20] min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 p-1 text-xs shadow-custom-shadow-lg", + "fixed z-30 min-w-[12rem] overflow-hidden rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 p-1 text-xs shadow-custom-shadow-lg", "ring-1 ring-black ring-opacity-5", // Additional styling to make it stand out contentClassName )} diff --git a/packages/ui/src/dropdowns/custom-search-select.tsx b/packages/ui/src/dropdowns/custom-search-select.tsx index d26163e69..68fb90cb5 100644 --- a/packages/ui/src/dropdowns/custom-search-select.tsx +++ b/packages/ui/src/dropdowns/custom-search-select.tsx @@ -138,7 +138,7 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
    ((props, ref) strokeLinecap="round" strokeLinejoin="round" > - +
    ); diff --git a/packages/ui/src/form-fields/input-color-picker.tsx b/packages/ui/src/form-fields/input-color-picker.tsx index d71a15005..eb7b83977 100644 --- a/packages/ui/src/form-fields/input-color-picker.tsx +++ b/packages/ui/src/form-fields/input-color-picker.tsx @@ -1,12 +1,12 @@ -import * as React from "react"; import { Popover, Transition } from "@headlessui/react"; +import * as React from "react"; import { ColorResult, SketchPicker } from "react-color"; -// components -import { Input } from "./input"; import { usePopper } from "react-popper"; -import { Button } from "../button"; // helpers import { cn } from "../../helpers"; +// components +import { Button } from "../button"; +import { Input } from "./input"; export interface InputColorPickerProps { hasError: boolean; @@ -71,9 +71,9 @@ export const InputColorPicker: React.FC = (props) => { viewBox="0 0 24 24" fill="none" stroke="currentColor" - stroke-width="2" - stroke-linecap="round" - stroke-linejoin="round" + strokeWidth="2" + strokeLinecap="round" + strokeLinejoin="round" className="lucide lucide-palette" > diff --git a/packages/ui/src/header/helper.tsx b/packages/ui/src/header/helper.tsx index 13fee8b47..a2d21cd37 100644 --- a/packages/ui/src/header/helper.tsx +++ b/packages/ui/src/header/helper.tsx @@ -24,5 +24,5 @@ export const minHeights: IHeaderProperties = { export const getHeaderStyle = (variant: THeaderVariant, setMinHeight: boolean, showOnMobile: boolean) => { const height = setMinHeight ? minHeights[variant] : ""; const display = variant === EHeaderVariant.SECONDARY ? (showOnMobile ? "flex" : "hidden md:flex") : ""; - return " " + headerStyle[variant] + " " + height + " " + display; + return " @container " + headerStyle[variant] + " " + height + " " + display; }; diff --git a/packages/ui/src/icons/activity-icon.tsx b/packages/ui/src/icons/activity-icon.tsx index 2ac482836..14f3b1d42 100644 --- a/packages/ui/src/icons/activity-icon.tsx +++ b/packages/ui/src/icons/activity-icon.tsx @@ -3,14 +3,22 @@ import * as React from "react"; import { ISvgIcons } from "./type"; export const ActivityIcon: React.FC = ({ className = "text-current", ...rest }) => ( - - + + diff --git a/packages/ui/src/icons/ai-icon.tsx b/packages/ui/src/icons/ai-icon.tsx new file mode 100644 index 000000000..149d9db39 --- /dev/null +++ b/packages/ui/src/icons/ai-icon.tsx @@ -0,0 +1,30 @@ +import * as React from "react"; + +import { ISvgIcons } from "./type"; + +export const AiIcon: React.FC = ({ width = "16", height = "16", className, color = "currentColor" }) => ( + + + + + + + + + + + +); diff --git a/packages/ui/src/icons/at-risk-icon.tsx b/packages/ui/src/icons/at-risk-icon.tsx index 65e5ae63d..748307b3c 100644 --- a/packages/ui/src/icons/at-risk-icon.tsx +++ b/packages/ui/src/icons/at-risk-icon.tsx @@ -4,10 +4,10 @@ import { ISvgIcons } from "./type"; export const AtRiskIcon: React.FC = ({ width = "16", height = "16" }) => ( - + diff --git a/packages/ui/src/icons/center-panel-icon.tsx b/packages/ui/src/icons/center-panel-icon.tsx index de01e2e2d..4704dbf0a 100644 --- a/packages/ui/src/icons/center-panel-icon.tsx +++ b/packages/ui/src/icons/center-panel-icon.tsx @@ -14,17 +14,17 @@ export const CenterPanelIcon: React.FC = ({ className = "text-current ); diff --git a/packages/ui/src/icons/cycle/circle-dot-full-icon.tsx b/packages/ui/src/icons/cycle/circle-dot-full-icon.tsx index f8b528a61..d6cf059ef 100644 --- a/packages/ui/src/icons/cycle/circle-dot-full-icon.tsx +++ b/packages/ui/src/icons/cycle/circle-dot-full-icon.tsx @@ -4,7 +4,7 @@ import { ISvgIcons } from "../type"; export const CircleDotFullIcon: React.FC = ({ className = "text-current", ...rest }) => ( - - + + ); diff --git a/packages/ui/src/icons/discord-icon.tsx b/packages/ui/src/icons/discord-icon.tsx index 6a2e0083a..89f441045 100644 --- a/packages/ui/src/icons/discord-icon.tsx +++ b/packages/ui/src/icons/discord-icon.tsx @@ -11,7 +11,7 @@ export const DiscordIcon: React.FC = ({ width = "24", height = "24", fill="currentColor" xmlns="http://www.w3.org/2000/svg" > - + diff --git a/packages/ui/src/icons/done-icon.tsx b/packages/ui/src/icons/done-icon.tsx index f8f65aa5f..82783ea1d 100644 --- a/packages/ui/src/icons/done-icon.tsx +++ b/packages/ui/src/icons/done-icon.tsx @@ -11,10 +11,10 @@ export const DoneState: React.FC = ({ width = "10", height = "11", cl xmlns="http://www.w3.org/2000/svg" className={className} > - + diff --git a/packages/ui/src/icons/favorite-folder-icon.tsx b/packages/ui/src/icons/favorite-folder-icon.tsx index 03ebba71b..2f464e815 100644 --- a/packages/ui/src/icons/favorite-folder-icon.tsx +++ b/packages/ui/src/icons/favorite-folder-icon.tsx @@ -15,17 +15,15 @@ export const FavoriteFolderIcon: React.FC = ({ className = "text-curr > diff --git a/packages/ui/src/icons/in-progress-icon.tsx b/packages/ui/src/icons/in-progress-icon.tsx index 085f9d74d..f85b7b26e 100644 --- a/packages/ui/src/icons/in-progress-icon.tsx +++ b/packages/ui/src/icons/in-progress-icon.tsx @@ -11,7 +11,7 @@ export const InProgressState: React.FC = ({ width = "10", height = "1 xmlns="http://www.w3.org/2000/svg" className={className} > - - + + ); diff --git a/packages/ui/src/icons/index.ts b/packages/ui/src/icons/index.ts index 143c3d79a..500925e3c 100644 --- a/packages/ui/src/icons/index.ts +++ b/packages/ui/src/icons/index.ts @@ -52,3 +52,6 @@ export * from "./sticky-note-icon"; export * from "./bar-icon"; export * from "./tree-map-icon"; export * from "./display-properties"; +export * from "./ai-icon"; +export * from "./plane-icon"; +export * from "./wiki-icon"; diff --git a/packages/ui/src/icons/info-icon.tsx b/packages/ui/src/icons/info-icon.tsx index 5dbc7f756..b71337539 100644 --- a/packages/ui/src/icons/info-icon.tsx +++ b/packages/ui/src/icons/info-icon.tsx @@ -8,9 +8,9 @@ export const InfoIcon: React.FC = ({ className = "text-current", ...r className={`${className} stroke-2`} stroke="currentColor" fill="none" - stroke-width="2" - stroke-linecap="round" - stroke-linejoin="round" + strokeWidth="2" + strokeLinecap="round" + strokeLinejoin="round" xmlns="http://www.w3.org/2000/svg" {...rest} > diff --git a/packages/ui/src/icons/lead-icon.tsx b/packages/ui/src/icons/lead-icon.tsx index 75575d35e..5bb9d4b81 100644 --- a/packages/ui/src/icons/lead-icon.tsx +++ b/packages/ui/src/icons/lead-icon.tsx @@ -8,11 +8,11 @@ export const LeadIcon: React.FC = ({ className = "text-current", ...r d="M0.571533 9C0.571533 4.02944 4.60097 0 9.57153 0C14.5421 0 18.5715 4.02944 18.5715 9C18.5715 13.9706 14.5421 18 9.57153 18C4.60097 18 0.571533 13.9706 0.571533 9Z" fill="#3372FF" /> - + diff --git a/packages/ui/src/icons/multiple-sticky.tsx b/packages/ui/src/icons/multiple-sticky.tsx index 9c33205e9..60f2eaf9b 100644 --- a/packages/ui/src/icons/multiple-sticky.tsx +++ b/packages/ui/src/icons/multiple-sticky.tsx @@ -13,14 +13,14 @@ export const RecentStickyIcon: React.FC = ({ className = "text-curren {...rest} > diff --git a/packages/ui/src/icons/off-track-icon.tsx b/packages/ui/src/icons/off-track-icon.tsx index cbb8ba1f8..1069d36f9 100644 --- a/packages/ui/src/icons/off-track-icon.tsx +++ b/packages/ui/src/icons/off-track-icon.tsx @@ -4,10 +4,10 @@ import { ISvgIcons } from "./type"; export const OffTrackIcon: React.FC = ({ width = "16", height = "16" }) => ( - + diff --git a/packages/ui/src/icons/on-track-icon.tsx b/packages/ui/src/icons/on-track-icon.tsx index 5dcabcec9..55abe8b34 100644 --- a/packages/ui/src/icons/on-track-icon.tsx +++ b/packages/ui/src/icons/on-track-icon.tsx @@ -4,28 +4,28 @@ import { ISvgIcons } from "./type"; export const OnTrackIcon: React.FC = ({ width = "16", height = "16" }) => ( - + diff --git a/packages/ui/src/icons/pending-icon.tsx b/packages/ui/src/icons/pending-icon.tsx index 5269a22e2..217edaf83 100644 --- a/packages/ui/src/icons/pending-icon.tsx +++ b/packages/ui/src/icons/pending-icon.tsx @@ -12,14 +12,14 @@ export const PendingState: React.FC = ({ width = "10", height = "11", className={className} > diff --git a/packages/ui/src/icons/plane-icon.tsx b/packages/ui/src/icons/plane-icon.tsx new file mode 100644 index 000000000..113d2dfd0 --- /dev/null +++ b/packages/ui/src/icons/plane-icon.tsx @@ -0,0 +1,35 @@ +import * as React from "react"; + +import { ISvgIcons } from "./type"; + +export const PlaneNewIcon: React.FC = ({ + width = "16", + height = "16", + className, + color = "currentColor", +}) => ( + + + + + + + + + + + +); diff --git a/packages/ui/src/icons/planned-icon.tsx b/packages/ui/src/icons/planned-icon.tsx index 88aa6bbe3..eefc7da30 100644 --- a/packages/ui/src/icons/planned-icon.tsx +++ b/packages/ui/src/icons/planned-icon.tsx @@ -11,22 +11,22 @@ export const PlannedState: React.FC = ({ width = "10", height = "11", xmlns="http://www.w3.org/2000/svg" className={className} > - + diff --git a/packages/ui/src/icons/sticky-note-icon.tsx b/packages/ui/src/icons/sticky-note-icon.tsx index 871950289..fd1652dad 100644 --- a/packages/ui/src/icons/sticky-note-icon.tsx +++ b/packages/ui/src/icons/sticky-note-icon.tsx @@ -23,8 +23,8 @@ export const StickyNoteIcon: React.FC = ({ width = "17", height = "17 fill="currentColor" /> diff --git a/packages/ui/src/icons/updates-icon.tsx b/packages/ui/src/icons/updates-icon.tsx index 978eb5f05..1b480f618 100644 --- a/packages/ui/src/icons/updates-icon.tsx +++ b/packages/ui/src/icons/updates-icon.tsx @@ -5,8 +5,8 @@ import { ISvgIcons } from "./type"; export const UpdatesIcon: React.FC = ({ className = "text-current", ...rest }) => ( diff --git a/packages/ui/src/icons/wiki-icon.tsx b/packages/ui/src/icons/wiki-icon.tsx new file mode 100644 index 000000000..5a3b992c7 --- /dev/null +++ b/packages/ui/src/icons/wiki-icon.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; + +import { ISvgIcons } from "./type"; + +export const WikiIcon: React.FC = ({ width = "16", height = "16", className, color = "currentColor" }) => ( + + + + + + + + + + +); diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index a21979fa1..365d63ed2 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -35,3 +35,4 @@ export * from "./toast"; export * from "./tooltip"; export * from "./typography"; export * from "./utils"; +export * from "./billing"; diff --git a/packages/ui/src/modals/modal-core.tsx b/packages/ui/src/modals/modal-core.tsx index 534cb27ce..798917481 100644 --- a/packages/ui/src/modals/modal-core.tsx +++ b/packages/ui/src/modals/modal-core.tsx @@ -25,7 +25,7 @@ export const ModalCore: React.FC = (props) => { return ( - handleClose && handleClose()}> + handleClose && handleClose()}> = (props) => {
    -
    +
    ({ +export default defineConfig({ entry: ["src/index.ts"], - format: ["cjs", "esm"], + outDir: "dist", + format: ["esm", "cjs"], dts: true, - clean: false, - external: ["react"], + clean: true, + minify: true, + splitting: true, + treeshake: true, + external: ["react", "@plane/types"], injectStyle: true, - ...options, -})); +}); diff --git a/packages/utils/.eslintrc.js b/packages/utils/.eslintrc.js index 558b8f76e..b11b7bb6d 100644 --- a/packages/utils/.eslintrc.js +++ b/packages/utils/.eslintrc.js @@ -3,7 +3,4 @@ module.exports = { root: true, extends: ["@plane/eslint-config/library.js"], parser: "@typescript-eslint/parser", - parserOptions: { - project: true, - }, }; diff --git a/packages/utils/package.json b/packages/utils/package.json index d0ee2d822..1fe2462b8 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@plane/utils", - "version": "0.27.1", + "version": "0.28.0", "description": "Helper functions shared across multiple apps internally", "license": "AGPL-3.0", "private": true, @@ -8,26 +8,36 @@ "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "files": [ - "dist/**" + "dist" ], "scripts": { - "build": "tsup ./src/index.ts --format esm,cjs --dts --external react --minify", - "lint": "eslint src --ext .ts,.tsx", - "lint:errors": "eslint src --ext .ts,.tsx --quiet" + "build": "tsc --noEmit && tsup --minify", + "dev": "tsup --watch", + "check:lint": "eslint . --max-warnings 0", + "check:types": "tsc --noEmit", + "check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"", + "fix:lint": "eslint . --fix", + "fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" }, "dependencies": { + "@plane/constants": "*", + "@plane/types": "*", "clsx": "^2.1.1", "date-fns": "^4.1.0", "isomorphic-dompurify": "^2.16.0", "lodash": "^4.17.21", "react": "^18.3.1", "tailwind-merge": "^2.5.5", + "uuid": "^10.0.0", "zxcvbn": "^4.4.2" }, "devDependencies": { "@plane/eslint-config": "*", + "@plane/typescript-config": "*", "@types/node": "^22.5.4", "@types/react": "^18.3.11", + "@types/uuid": "^9.0.8", "@types/zxcvbn": "^4.4.5", "tsup": "8.4.0", "typescript": "5.8.3" diff --git a/packages/utils/src/array.ts b/packages/utils/src/array.ts index 12727d3a0..5d1791c72 100644 --- a/packages/utils/src/array.ts +++ b/packages/utils/src/array.ts @@ -96,7 +96,6 @@ export const checkIfArraysHaveSameElements = (arr1: any[] | null, arr2: any[] | return arr1.length === arr2.length && arr1.every((e) => arr2.includes(e)); }; - type GroupedItems = { [key: string]: T[] }; /** diff --git a/packages/utils/src/calendar.ts b/packages/utils/src/calendar.ts index f4217ea41..a8038ec5e 100644 --- a/packages/utils/src/calendar.ts +++ b/packages/utils/src/calendar.ts @@ -1,8 +1,7 @@ // plane imports -import { EStartOfTheWeek } from "@plane/constants"; -import { ICalendarDate, ICalendarPayload } from "@plane/types"; +import { EStartOfTheWeek, ICalendarDate, ICalendarPayload } from "@plane/types"; // local imports -import { getWeekNumberOfDate, renderFormattedPayloadDate } from "./datetime"; +import { getWeekNumberOfDate, renderFormattedPayloadDate } from "./datetime"; /** * @returns {ICalendarPayload} calendar payload to render the calendar @@ -67,8 +66,9 @@ export const getOrderedDays = ( items: T[], getDayIndex: (item: T) => number, startOfWeek: EStartOfTheWeek = EStartOfTheWeek.SUNDAY -): T[] => [...items].sort((a, b) => { +): T[] => + [...items].sort((a, b) => { const dayA = (7 + getDayIndex(a) - startOfWeek) % 7; const dayB = (7 + getDayIndex(b) - startOfWeek) % 7; return dayA - dayB; - }) + }); diff --git a/packages/utils/src/cycle.ts b/packages/utils/src/cycle.ts index 66002c740..133db1595 100644 --- a/packages/utils/src/cycle.ts +++ b/packages/utils/src/cycle.ts @@ -6,8 +6,8 @@ import uniqBy from "lodash/uniqBy"; // plane imports import { ICycle, TCycleFilters } from "@plane/types"; // local imports -import { findTotalDaysInRange, generateDateArray, getDate } from "./datetime"; -import { satisfiesDateFilter } from "./filter"; +import { findTotalDaysInRange, generateDateArray, getDate } from "./datetime"; +import { satisfiesDateFilter } from "./filter"; /** * Orders cycles based on their status diff --git a/packages/utils/src/distribution-update.ts b/packages/utils/src/distribution-update.ts index d085aabdb..de9e254cc 100644 --- a/packages/utils/src/distribution-update.ts +++ b/packages/utils/src/distribution-update.ts @@ -4,7 +4,7 @@ import { format } from "date-fns"; import get from "lodash/get"; import set from "lodash/set"; // plane imports -import { STATE_GROUPS, COMPLETED_STATE_GROUPS } from "@plane/constants"; +import { COMPLETED_STATE_GROUPS, STATE_DISTRIBUTION } from "@plane/constants"; import { ICycle, IEstimatePoint, IModule, IState, TIssue } from "@plane/types"; // helper import { getDate } from "./datetime"; @@ -33,34 +33,6 @@ export type DistributionUpdates = { labelUpdates: DistributionObjectUpdate[]; }; -const STATE_DISTRIBUTION = { - [STATE_GROUPS.backlog.key]: { - key: STATE_GROUPS.backlog.key, - issues: "backlog_issues", - points: "backlog_estimate_points", - }, - [STATE_GROUPS.unstarted.key]: { - key: STATE_GROUPS.unstarted.key, - issues: "unstarted_issues", - points: "unstarted_estimate_points", - }, - [STATE_GROUPS.started.key]: { - key: STATE_GROUPS.started.key, - issues: "started_issues", - points: "started_estimate_points", - }, - [STATE_GROUPS.completed.key]: { - key: STATE_GROUPS.completed.key, - issues: "completed_issues", - points: "completed_estimate_points", - }, - [STATE_GROUPS.cancelled.key]: { - key: STATE_GROUPS.cancelled.key, - issues: "cancelled_issues", - points: "cancelled_estimate_points", - }, -}; - /** * Get Distribution updates with the help of previous and next issue states * @param prevIssueState diff --git a/packages/utils/src/editor.ts b/packages/utils/src/editor.ts index 1bdf3a504..fb15edd07 100644 --- a/packages/utils/src/editor.ts +++ b/packages/utils/src/editor.ts @@ -22,6 +22,21 @@ export const getEditorAssetSrc = (args: TEditorSrcArgs): string | undefined => { return url; }; +/** + * @description generate the file source using assetId + * @param {TEditorSrcArgs} args + */ +export const getEditorAssetDownloadSrc = (args: TEditorSrcArgs): string | undefined => { + const { assetId, projectId, workspaceSlug } = args; + let url: string | undefined = ""; + if (projectId) { + url = getFileURL(`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/download/${assetId}/`); + } else { + url = getFileURL(`/api/assets/v2/workspaces/${workspaceSlug}/download/${assetId}/`); + } + return url; +}; + export const getTextContent = (jsx: JSX.Element | React.ReactNode | null | undefined): string => { if (!jsx) return ""; diff --git a/packages/utils/src/module.ts b/packages/utils/src/module.ts index b1e9f314d..37108b930 100644 --- a/packages/utils/src/module.ts +++ b/packages/utils/src/module.ts @@ -2,8 +2,8 @@ import sortBy from "lodash/sortBy"; // plane imports import { IModule, TModuleDisplayFilters, TModuleFilters, TModuleOrderByOptions } from "@plane/types"; // local imports -import { getDate } from "./datetime"; -import { satisfiesDateFilter } from "./filter"; +import { getDate } from "./datetime"; +import { satisfiesDateFilter } from "./filter"; /** * @description orders modules based on their status diff --git a/packages/utils/src/page.ts b/packages/utils/src/page.ts index 2501bc522..c2afc8a92 100644 --- a/packages/utils/src/page.ts +++ b/packages/utils/src/page.ts @@ -2,8 +2,8 @@ import sortBy from "lodash/sortBy"; // plane imports import { TPage, TPageFilterProps, TPageFiltersSortBy, TPageFiltersSortKey, TPageNavigationTabs } from "@plane/types"; // local imports -import { getDate } from "./datetime"; -import { satisfiesDateFilter } from "./filter"; +import { getDate } from "./datetime"; +import { satisfiesDateFilter } from "./filter"; /** * @description filters pages based on the page type @@ -61,7 +61,7 @@ export const shouldFilterPage = (page: TPage, filters: TPageFilterProps | undefi Object.keys(filters ?? {}).forEach((key) => { const filterKey = key as keyof TPageFilterProps; if (filterKey === "created_by" && filters?.created_by && filters.created_by.length > 0) - fallsInFilters = fallsInFilters && filters.created_by.includes(`${page.created_by}`); + fallsInFilters = fallsInFilters && filters.created_by.includes(`${page.owned_by}`); if (filterKey === "created_at" && filters?.created_at && filters.created_at.length > 0) { const createdDate = getDate(page.created_at); filters?.created_at.forEach((dateFilter) => { @@ -84,4 +84,3 @@ export const getPageName = (name: string | undefined) => { if (!name || name.trim() === "") return "Untitled"; return name; }; - diff --git a/packages/utils/src/permission/role.ts b/packages/utils/src/permission/role.ts index 5e6bf02e1..3b6f73cf4 100644 --- a/packages/utils/src/permission/role.ts +++ b/packages/utils/src/permission/role.ts @@ -1,5 +1,6 @@ // plane imports -import { EUserProjectRoles, EUserWorkspaceRoles, EUserPermissions } from "@plane/constants"; +import { EUserPermissions } from "@plane/constants"; +import { EUserProjectRoles, EUserWorkspaceRoles } from "@plane/types"; export const getUserRole = (role: EUserPermissions | EUserWorkspaceRoles | EUserProjectRoles) => { switch (role) { diff --git a/packages/utils/src/project-views.ts b/packages/utils/src/project-views.ts index 5263d7098..aa11f4de0 100644 --- a/packages/utils/src/project-views.ts +++ b/packages/utils/src/project-views.ts @@ -4,7 +4,7 @@ import orderBy from "lodash/orderBy"; import { SPACE_BASE_PATH, SPACE_BASE_URL } from "@plane/constants"; import { IProjectView, TViewFilterProps, TViewFiltersSortBy, TViewFiltersSortKey } from "@plane/types"; // local imports -import { getDate } from "./datetime"; +import { getDate } from "./datetime"; import { satisfiesDateFilter } from "./filter"; /** diff --git a/packages/utils/src/string.ts b/packages/utils/src/string.ts index 58822e1e9..7bcaa9db4 100644 --- a/packages/utils/src/string.ts +++ b/packages/utils/src/string.ts @@ -319,7 +319,6 @@ export const copyTextToClipboard = async (text: string): Promise => { await navigator.clipboard.writeText(text); }; - /** * @description Joins URL path segments properly, removing duplicate slashes using URL encoding * @param {...string} segments - URL path segments to join @@ -338,21 +337,17 @@ export const joinUrlPath = (...segments: string[]): string => { if (validSegments.length === 0) return ""; // Process segments to normalize slashes - const processedSegments = validSegments.map((segment, index) => { + const processedSegments = validSegments.map((segment) => { let processed = segment; // Remove leading slashes from all segments except the first - if (index > 0) { - while (processed.startsWith("/")) { - processed = processed.substring(1); - } + while (processed.startsWith("/")) { + processed = processed.substring(1); } // Remove trailing slashes from all segments except the last - if (index < validSegments.length - 1) { - while (processed.endsWith("/")) { - processed = processed.substring(0, processed.length - 1); - } + while (processed.endsWith("/")) { + processed = processed.substring(0, processed.length - 1); } return processed; @@ -371,4 +366,4 @@ export const joinUrlPath = (...segments: string[]): string => { const pathParts = joined.split("/").filter((part) => part !== ""); return pathParts.length > 0 ? `/${pathParts.join("/")}` : ""; } -}; \ No newline at end of file +}; diff --git a/packages/utils/src/subscription.ts b/packages/utils/src/subscription.ts index 207f387b7..a03dbc292 100644 --- a/packages/utils/src/subscription.ts +++ b/packages/utils/src/subscription.ts @@ -1,7 +1,6 @@ import orderBy from "lodash/orderBy"; // plane imports -import { EProductSubscriptionEnum } from "@plane/constants"; -import { IPaymentProduct, TProductSubscriptionType, TSubscriptionPrice } from "@plane/types"; +import { EProductSubscriptionEnum, IPaymentProduct, TProductSubscriptionType, TSubscriptionPrice } from "@plane/types"; /** * Calculates the yearly discount percentage when switching from monthly to yearly billing diff --git a/packages/utils/src/work-item/base.ts b/packages/utils/src/work-item/base.ts index 7ebca1ffd..6cef74175 100644 --- a/packages/utils/src/work-item/base.ts +++ b/packages/utils/src/work-item/base.ts @@ -3,7 +3,6 @@ import isEmpty from "lodash/isEmpty"; import { v4 as uuidv4 } from "uuid"; // plane imports import { - EIssueLayoutTypes, ISSUE_DISPLAY_FILTERS_BY_PAGE, STATE_GROUPS, TIssuePriorities, @@ -22,6 +21,7 @@ import { TStateGroups, TSubGroupedIssues, TUnGroupedIssues, + EIssueLayoutTypes, } from "@plane/types"; // local imports import { orderArrayBy } from "../array"; @@ -190,7 +190,9 @@ export const getIssueBlocksStructure = (block: TIssue): IGanttBlock => ({ sort_order: block?.sort_order, start_date: block?.start_date ?? undefined, target_date: block?.target_date ?? undefined, - project_id: block?.project_id ?? undefined, + meta: { + project_id: block?.project_id ?? undefined, + }, }); export const formatTextList = (TextArray: string[]): string => { diff --git a/packages/utils/src/work-item/modal.ts b/packages/utils/src/work-item/modal.ts index 74bb1063b..f39f87eda 100644 --- a/packages/utils/src/work-item/modal.ts +++ b/packages/utils/src/work-item/modal.ts @@ -33,7 +33,6 @@ export const convertWorkItemDataToSearchResponse = ( workspace__slug: workspaceSlug, }); - export function getChangedIssuefields(formData: Partial, dirtyFields: { [key: string]: boolean | undefined }) { const changedFields = {}; diff --git a/packages/utils/tsup.config.ts b/packages/utils/tsup.config.ts new file mode 100644 index 000000000..6566c82ef --- /dev/null +++ b/packages/utils/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + format: ["esm", "cjs"], + dts: true, + clean: true, + minify: true, + splitting: true, + treeshake: true, + external: ["react"], +}); diff --git a/setup.sh b/setup.sh index c19a29abf..986a42616 100755 --- a/setup.sh +++ b/setup.sh @@ -44,20 +44,23 @@ export LC_CTYPE=C echo -e "${YELLOW}Setting up environment files...${NC}" # Copy all environment example files -services=("" "web" "apiserver" "space" "admin" "live") +services=("" "web" "api" "space" "admin" "live") success=true for service in "${services[@]}"; do - prefix="./" - if [ "$service" != "" ]; then - prefix="./$service/" + if [ "$service" == "" ]; then + # Handle root .env file + prefix="./" + else + # Handle service .env files in apps folder + prefix="./apps/$service/" fi copy_env_file "${prefix}.env.example" "${prefix}.env" || success=false done # Generate SECRET_KEY for Django -if [ -f "./apiserver/.env" ]; then +if [ -f "./apps/api/.env" ]; then echo -e "\n${YELLOW}Generating Django SECRET_KEY...${NC}" SECRET_KEY=$(tr -dc 'a-z0-9' < /dev/urandom | head -c50) @@ -66,11 +69,11 @@ if [ -f "./apiserver/.env" ]; then echo -e "${RED}Ensure 'tr' and 'head' commands are available on your system.${NC}" success=false else - echo -e "SECRET_KEY=\"$SECRET_KEY\"" >> ./apiserver/.env - echo -e "${GREEN}✓${NC} Added SECRET_KEY to apiserver/.env" + echo -e "SECRET_KEY=\"$SECRET_KEY\"" >> ./apps/api/.env + echo -e "${GREEN}✓${NC} Added SECRET_KEY to apps/api/.env" fi else - echo -e "${RED}✗${NC} apiserver/.env not found. SECRET_KEY not added." + echo -e "${RED}✗${NC} apps/api/.env not found. SECRET_KEY not added." success=false fi diff --git a/space/core/components/editor/rich-text-read-only-editor.tsx b/space/core/components/editor/rich-text-read-only-editor.tsx deleted file mode 100644 index dd9d37190..000000000 --- a/space/core/components/editor/rich-text-read-only-editor.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from "react"; -// plane imports -import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor"; -import { MakeOptional } from "@plane/types"; -import { cn } from "@plane/utils"; -// components -import { EditorMentionsRoot } from "@/components/editor"; -// helpers -import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; -// store hooks -import { useMember } from "@/hooks/store"; - -type RichTextReadOnlyEditorWrapperProps = MakeOptional< - Omit, - "disabledExtensions" | "flaggedExtensions" -> & { - anchor: string; - workspaceId: string; -}; - -export const RichTextReadOnlyEditor = React.forwardRef( - ({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => { - const { getMemberById } = useMember(); - - return ( - , - getMentionedEntityDetails: (id: string) => ({ - display_name: getMemberById(id)?.member__display_name ?? "", - }), - }} - {...props} - // overriding the customClassName to add relative class passed - containerClassName={cn("relative p-0 border-none", props.containerClassName)} - /> - ); - } -); - -RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor"; diff --git a/start.sh b/start.sh deleted file mode 100644 index 2685c3826..000000000 --- a/start.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -set -x - -echo "Starting Plane Frontend.." -node $1 diff --git a/turbo.json b/turbo.json index 36e95edbd..09f2a42ad 100644 --- a/turbo.json +++ b/turbo.json @@ -24,23 +24,39 @@ "dependsOn": ["^build"], "outputs": [".next/**", "dist/**"] }, - "develop": { - "cache": false, - "persistent": true, - "dependsOn": ["^build"] - }, "dev": { + "dependsOn": ["^build"], "cache": false, - "persistent": true, - "dependsOn": ["^build"] + "persistent": true + }, + "check:types": { + "dependsOn": ["^build"], + "cache": false + }, + "check:lint": { + "cache": false + }, + "check:format": { + "cache": false + }, + "check": { + "dependsOn": ["check:format", "check:lint", "check:types"], + "cache": false + }, + "fix:lint": { + "cache": false + }, + "fix:format": { + "cache": false + }, + "fix": { + "dependsOn": ["fix:format", "fix:lint"], + "cache": false }, "test": { "dependsOn": ["^build"], "outputs": [] }, - "lint": { - "outputs": [] - }, "start": { "cache": false }, diff --git a/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx b/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx deleted file mode 100644 index 340ec57d0..000000000 --- a/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -"use client"; - -import { CommandPalette } from "@/components/command-palette"; -import { AuthenticationWrapper } from "@/lib/wrappers"; -// plane web components -import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper"; -import { AppSidebar } from "./sidebar"; - -export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { - return ( - - - -
    - -
    - {children} -
    -
    -
    -
    - ); -} diff --git a/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx b/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx deleted file mode 100644 index 39d6313ba..000000000 --- a/web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { FC, useEffect, useRef } from "react"; -import isEmpty from "lodash/isEmpty"; -import { observer } from "mobx-react"; -// plane helpers -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; -import { useOutsideClickDetector } from "@plane/hooks"; -// components -import { cn } from "@plane/utils"; -import { SidebarDropdown, SidebarHelpSection, SidebarProjectsList, SidebarQuickActions } from "@/components/workspace"; -import { SidebarFavoritesMenu } from "@/components/workspace/sidebar/favorites/favorites-menu"; -import { SidebarMenuItems } from "@/components/workspace/sidebar/sidebar-menu-items"; -// helpers -// hooks -import { useAppTheme, useUserPermissions } from "@/hooks/store"; -import { useFavorite } from "@/hooks/store/use-favorite"; -import useSize from "@/hooks/use-window-size"; -// plane web components -import { SidebarAppSwitcher } from "@/plane-web/components/sidebar"; -import { SidebarTeamsList } from "@/plane-web/components/workspace/sidebar/teams-sidebar-list"; -import { ExtendedProjectSidebar } from "./extended-project-sidebar"; -import { ExtendedAppSidebar } from "./extended-sidebar"; - -export const AppSidebar: FC = observer(() => { - // store hooks - const { allowPermissions } = useUserPermissions(); - const { toggleSidebar, sidebarCollapsed } = useAppTheme(); - const { groupedFavorites } = useFavorite(); - const windowSize = useSize(); - // refs - const ref = useRef(null); - - // derived values - const canPerformWorkspaceMemberActions = allowPermissions( - [EUserPermissions.ADMIN, EUserPermissions.MEMBER], - EUserPermissionsLevel.WORKSPACE - ); - - useOutsideClickDetector(ref, () => { - if (sidebarCollapsed === false) { - if (window.innerWidth < 768) { - toggleSidebar(); - } - } - }); - - useEffect(() => { - if (windowSize[0] < 768 && !sidebarCollapsed) toggleSidebar(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [windowSize]); - - const isFavoriteEmpty = isEmpty(groupedFavorites); - - return ( - <> -
    -
    -
    - {/* Workspace switcher and settings */} - -
    - {/* App switcher */} - {canPerformWorkspaceMemberActions && } - {/* Quick actions */} - -
    -
    -
    - - {sidebarCollapsed && ( -
    - )} - {/* Favorites Menu */} - {canPerformWorkspaceMemberActions && !isFavoriteEmpty && } - {/* Teams List */} - - {/* Projects List */} - -
    - {/* Help Section */} - -
    -
    - - - - ); -}); diff --git a/web/ce/components/common/subscription/index.ts b/web/ce/components/common/subscription/index.ts deleted file mode 100644 index beb26e1d9..000000000 --- a/web/ce/components/common/subscription/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./subscription-pill"; \ No newline at end of file diff --git a/web/ce/components/issues/bulk-operations/index.ts b/web/ce/components/issues/bulk-operations/index.ts deleted file mode 100644 index 50a9c47c0..000000000 --- a/web/ce/components/issues/bulk-operations/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./root"; \ No newline at end of file diff --git a/web/ce/components/issues/issue-modal/additional-properties.tsx b/web/ce/components/issues/issue-modal/additional-properties.tsx deleted file mode 100644 index 99ddc8830..000000000 --- a/web/ce/components/issues/issue-modal/additional-properties.tsx +++ /dev/null @@ -1,9 +0,0 @@ -type TIssueAdditionalPropertiesProps = { - issueId: string | undefined; - issueTypeId: string | null; - projectId: string; - workspaceSlug: string; - isDraft?: boolean; -}; - -export const IssueAdditionalProperties: React.FC = () => <>; diff --git a/web/ce/store/event-tracker.store.ts b/web/ce/store/event-tracker.store.ts deleted file mode 100644 index 4f5074dd9..000000000 --- a/web/ce/store/event-tracker.store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { RootStore } from "@/plane-web/store/root.store"; -import { CoreEventTrackerStore, ICoreEventTrackerStore } from "@/store/event-tracker.store"; - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface IEventTrackerStore extends ICoreEventTrackerStore {} - -export class EventTrackerStore extends CoreEventTrackerStore implements IEventTrackerStore { - constructor(_rootStore: RootStore) { - super(_rootStore); - } -} diff --git a/web/core/components/analytics/work-items/modal/index.tsx b/web/core/components/analytics/work-items/modal/index.tsx deleted file mode 100644 index 292dc1be5..000000000 --- a/web/core/components/analytics/work-items/modal/index.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { observer } from "mobx-react"; -import { Dialog, Transition } from "@headlessui/react"; -// plane package imports -import { ICycle, IModule, IProject } from "@plane/types"; -import { useAnalytics } from "@/hooks/store"; -// plane web components -import { WorkItemsModalMainContent } from "./content"; -import { WorkItemsModalHeader } from "./header"; - -type Props = { - isOpen: boolean; - onClose: () => void; - projectDetails?: IProject | undefined; - cycleDetails?: ICycle | undefined; - moduleDetails?: IModule | undefined; - isEpic?: boolean; -}; - -export const WorkItemsModal: React.FC = observer((props) => { - const { isOpen, onClose, projectDetails, moduleDetails, cycleDetails, isEpic } = props; - const { updateIsEpic } = useAnalytics(); - const [fullScreen, setFullScreen] = useState(false); - - const handleClose = () => { - onClose(); - }; - - useEffect(() => { - updateIsEpic(isEpic ?? false); - }, [isEpic, updateIsEpic]); - - return ( - - - -
    - -
    -
    - - -
    -
    -
    -
    -
    -
    -
    - ); -}); diff --git a/web/core/components/comments/comment-card.tsx b/web/core/components/comments/comment-card.tsx deleted file mode 100644 index 66dd75427..000000000 --- a/web/core/components/comments/comment-card.tsx +++ /dev/null @@ -1,224 +0,0 @@ -"use client"; - -import { FC, useEffect, useRef, useState } from "react"; -import { observer } from "mobx-react"; -import { useForm } from "react-hook-form"; -import { Check, Globe2, Lock, Pencil, Trash2, X } from "lucide-react"; -// PLane -import { EIssueCommentAccessSpecifier } from "@plane/constants"; -import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; -import { useTranslation } from "@plane/i18n"; -import { TIssueComment, TCommentsOperations } from "@plane/types"; -import { CustomMenu } from "@plane/ui"; -// components -import { isCommentEmpty } from "@plane/utils"; -import { LiteTextEditor, LiteTextReadOnlyEditor } from "@/components/editor"; -// helpers -// hooks -import { useUser } from "@/hooks/store"; -// -import { CommentBlock } from "@/plane-web/components/comments"; -import { CommentReactions } from "./comment-reaction"; - -type TCommentCard = { - workspaceSlug: string; - comment: TIssueComment | undefined; - activityOperations: TCommentsOperations; - ends: "top" | "bottom" | undefined; - showAccessSpecifier?: boolean; - disabled?: boolean; - projectId?: string; -}; - -export const CommentCard: FC = observer((props) => { - const { - workspaceSlug, - comment, - activityOperations, - ends, - showAccessSpecifier = false, - disabled = false, - projectId, - } = props; - const { t } = useTranslation(); - // refs - const editorRef = useRef(null); - const showEditorRef = useRef(null); - // state - const [isEditing, setIsEditing] = useState(false); - // store hooks - const { data: currentUser } = useUser(); - // form info - const { - formState: { isSubmitting }, - handleSubmit, - setFocus, - watch, - setValue, - } = useForm>({ - defaultValues: { comment_html: comment?.comment_html }, - }); - // derived values - const workspaceId = comment?.workspace; - const commentHTML = watch("comment_html"); - const isEmpty = isCommentEmpty(commentHTML ?? undefined); - const isEditorReadyToDiscard = editorRef.current?.isEditorReadyToDiscard(); - const isSubmitButtonDisabled = isSubmitting || !isEditorReadyToDiscard; - const isDisabled = isSubmitting || isEmpty || isSubmitButtonDisabled; - - // helpers - const onEnter = async (formData: Partial) => { - if (isSubmitting || !comment) return; - - setIsEditing(false); - - await activityOperations.updateComment(comment.id, formData); - - editorRef.current?.setEditorValue(formData?.comment_html ?? "

    "); - showEditorRef.current?.setEditorValue(formData?.comment_html ?? "

    "); - }; - - useEffect(() => { - if (isEditing) { - setFocus("comment_html"); - } - }, [isEditing, setFocus]); - - if (!comment || !currentUser || !workspaceId) return <>; - - return ( - - {!disabled && currentUser?.id === comment.actor && ( - - setIsEditing(true)} className="flex items-center gap-1"> - - {t("common.actions.edit")} - - {showAccessSpecifier && ( - <> - {comment.access === "INTERNAL" ? ( - - activityOperations.updateComment(comment.id, { access: EIssueCommentAccessSpecifier.EXTERNAL }) - } - className="flex items-center gap-1" - > - - {t("issue.comments.switch.public")} - - ) : ( - - activityOperations.updateComment(comment.id, { access: EIssueCommentAccessSpecifier.INTERNAL }) - } - className="flex items-center gap-1" - > - - {t("issue.comments.switch.private")} - - )} - - )} - activityOperations.removeComment(comment.id)} - className="flex items-center gap-1" - > - - {t("common.actions.delete")} - - - )} - - } - ends={ends} - > - <> - -
    { - if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty) handleSubmit(onEnter)(e); - }} - > - setValue("comment_html", comment_html)} - onEnterKeyPress={(e) => { - if (!isEmpty && !isSubmitting) { - handleSubmit(onEnter)(e); - } - }} - showSubmitButton={false} - uploadFile={async (blockId, file) => { - const { asset_id } = await activityOperations.uploadCommentAsset(blockId, file, comment.id); - return asset_id; - }} - projectId={projectId?.toString() ?? ""} - parentClassName="p-2" - displayConfig={{ - fontSize: "small-font", - }} - /> -
    -
    - {!isEmpty && ( - - )} - -
    - -
    - {showAccessSpecifier && ( -
    - {comment.access === EIssueCommentAccessSpecifier.INTERNAL ? ( - - ) : ( - - )} -
    - )} - - -
    - -
    - ); -}); diff --git a/web/core/components/core/app-header.tsx b/web/core/components/core/app-header.tsx deleted file mode 100644 index 6b943044e..000000000 --- a/web/core/components/core/app-header.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client"; - -import { ReactNode } from "react"; -// components -import { Row } from "@plane/ui"; -import { SidebarHamburgerToggle } from "@/components/core"; - -export interface AppHeaderProps { - header: ReactNode; - mobileHeader?: ReactNode; -} - -export const AppHeader = (props: AppHeaderProps) => { - const { header, mobileHeader } = props; - - return ( -
    - -
    - -
    -
    {header}
    -
    - {mobileHeader && mobileHeader} -
    - ); -}; diff --git a/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx b/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx deleted file mode 100644 index 7dc398812..000000000 --- a/web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx +++ /dev/null @@ -1,20 +0,0 @@ -"use client"; - -import { observer } from "mobx-react"; -import { Menu } from "lucide-react"; -import { useAppTheme } from "@/hooks/store"; - -export const SidebarHamburgerToggle = observer(() => { - // store hooks - const { toggleSidebar } = useAppTheme(); - - return ( - - ); -}); diff --git a/web/core/components/editor/rich-text-editor/index.ts b/web/core/components/editor/rich-text-editor/index.ts deleted file mode 100644 index f185d0054..000000000 --- a/web/core/components/editor/rich-text-editor/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./rich-text-editor"; -export * from "./rich-text-read-only-editor"; diff --git a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx deleted file mode 100644 index b89804e01..000000000 --- a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx +++ /dev/null @@ -1,59 +0,0 @@ -"use client"; - -import React from "react"; -// plane imports -import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor"; -import { MakeOptional } from "@plane/types"; -// components -import { cn } from "@plane/utils"; -import { EditorMentionsRoot } from "@/components/editor"; -// helpers -// hooks -import { useEditorConfig } from "@/hooks/editor"; -// store hooks -import { useMember } from "@/hooks/store"; -// plane web hooks -import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; - -type RichTextReadOnlyEditorWrapperProps = MakeOptional< - Omit, - "disabledExtensions" | "flaggedExtensions" -> & { - workspaceId: string; - workspaceSlug: string; - projectId?: string; -}; - -export const RichTextReadOnlyEditor = React.forwardRef( - ({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => { - // store hooks - const { getUserDetails } = useMember(); - - // editor flaggings - const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString()); - // editor config - const { getReadOnlyEditorFileHandlers } = useEditorConfig(); - - return ( - , - getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), - }} - {...props} - // overriding the containerClassName to add relative class passed - containerClassName={cn(props.containerClassName, "relative pl-3")} - /> - ); - } -); - -RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor"; diff --git a/web/core/components/gantt-chart/blocks/index.ts b/web/core/components/gantt-chart/blocks/index.ts deleted file mode 100644 index c99f8af32..000000000 --- a/web/core/components/gantt-chart/blocks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./blocks-list"; diff --git a/web/core/components/global/product-updates/footer.tsx b/web/core/components/global/product-updates/footer.tsx deleted file mode 100644 index 84966e637..000000000 --- a/web/core/components/global/product-updates/footer.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import Image from "next/image"; -import { useTranslation } from "@plane/i18n"; -// ui -import { getButtonStyling } from "@plane/ui"; -// helpers -import { cn } from "@plane/utils"; -// assets -import PlaneLogo from "@/public/plane-logos/blue-without-text.png"; - -export const ProductUpdatesFooter = () => { - const { t } = useTranslation(); - return ( - - ); -}; diff --git a/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx b/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx deleted file mode 100644 index 4be7686c2..000000000 --- a/web/core/components/issues/issue-detail/issue-detail-quick-actions.tsx +++ /dev/null @@ -1,277 +0,0 @@ -"use client"; - -import React, { FC, useState } from "react"; -import { observer } from "mobx-react"; -import { usePathname } from "next/navigation"; -import { ArchiveIcon, ArchiveRestoreIcon, LinkIcon, Trash2 } from "lucide-react"; -import { - ARCHIVABLE_STATE_GROUPS, - EIssuesStoreType, - EUserPermissions, - EUserPermissionsLevel, - WORK_ITEM_TRACKER_EVENTS, -} from "@plane/constants"; -import { useTranslation } from "@plane/i18n"; -import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; -import { cn, generateWorkItemLink, copyTextToClipboard } from "@plane/utils"; -// components -import { ArchiveIssueModal, DeleteIssueModal, IssueSubscription } from "@/components/issues"; -// helpers -// hooks -import { - useEventTracker, - useIssueDetail, - useIssues, - useProject, - useProjectState, - useUser, - useUserPermissions, -} from "@/hooks/store"; -import { useAppRouter } from "@/hooks/use-app-router"; -import { usePlatformOS } from "@/hooks/use-platform-os"; - -type Props = { - workspaceSlug: string; - projectId: string; - issueId: string; -}; - -export const IssueDetailQuickActions: FC = observer((props) => { - const { workspaceSlug, projectId, issueId } = props; - const { t } = useTranslation(); - // states - const [deleteIssueModal, setDeleteIssueModal] = useState(false); - const [archiveIssueModal, setArchiveIssueModal] = useState(false); - const [isRestoring, setIsRestoring] = useState(false); - - // router - const router = useAppRouter(); - - // hooks - const { data: currentUser } = useUser(); - const { allowPermissions } = useUserPermissions(); - const { isMobile } = usePlatformOS(); - const { getStateById } = useProjectState(); - const { getProjectIdentifierById } = useProject(); - const { - issue: { getIssueById }, - removeIssue, - archiveIssue, - } = useIssueDetail(); - const { - issues: { restoreIssue }, - } = useIssues(EIssuesStoreType.ARCHIVED); - const { - issues: { removeIssue: removeArchivedIssue }, - } = useIssues(EIssuesStoreType.ARCHIVED); - const { captureIssueEvent } = useEventTracker(); - const pathname = usePathname(); - - // derived values - const issue = getIssueById(issueId); - if (!issue) return <>; - - const stateDetails = getStateById(issue.state_id); - const projectIdentifier = getProjectIdentifierById(projectId); - - const workItemLink = generateWorkItemLink({ - workspaceSlug: workspaceSlug, - projectId, - issueId, - projectIdentifier, - sequenceId: issue?.sequence_id, - }); - - // handlers - const handleCopyText = () => { - const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; - copyTextToClipboard(`${originURL}${workItemLink}`).then(() => { - setToast({ - type: TOAST_TYPE.SUCCESS, - title: t("common.link_copied"), - message: t("common.copied_to_clipboard"), - }); - }); - }; - - const handleDeleteIssue = async () => { - try { - const deleteIssue = issue?.archived_at ? removeArchivedIssue : removeIssue; - const redirectionPath = issue?.archived_at - ? `/${workspaceSlug}/projects/${projectId}/archives/issues` - : `/${workspaceSlug}/projects/${projectId}/issues`; - - return deleteIssue(workspaceSlug, projectId, issueId).then(() => { - router.push(redirectionPath); - captureIssueEvent({ - eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "SUCCESS", element: "Work item detail page" }, - path: pathname, - }); - }); - } catch { - setToast({ - title: t("toast.error "), - type: TOAST_TYPE.ERROR, - message: t("entity.delete.failed", { entity: t("issue.label", { count: 1 }) }), - }); - captureIssueEvent({ - eventName: WORK_ITEM_TRACKER_EVENTS.delete, - payload: { id: issueId, state: "FAILED", element: "Work item detail page" }, - path: pathname, - }); - } - }; - - const handleArchiveIssue = async () => { - try { - await archiveIssue(workspaceSlug, projectId, issueId).then(() => { - router.push(`/${workspaceSlug}/projects/${projectId}/archives/issues/${issue.id}`); - }); - captureIssueEvent({ - eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "SUCCESS", element: "Issue details page" }, - path: pathname, - }); - } catch { - captureIssueEvent({ - eventName: WORK_ITEM_TRACKER_EVENTS.archive, - payload: { id: issueId, state: "FAILED", element: "Issue details page" }, - path: pathname, - }); - } - }; - - const handleRestore = async () => { - if (!workspaceSlug || !projectId || !issueId) return; - - setIsRestoring(true); - - await restoreIssue(workspaceSlug.toString(), projectId.toString(), issueId.toString()) - .then(() => { - setToast({ - type: TOAST_TYPE.SUCCESS, - title: t("issue.restore.success.title"), - message: t("issue.restore.success.message"), - }); - router.push(workItemLink); - }) - .catch(() => { - setToast({ - type: TOAST_TYPE.ERROR, - title: t("toast.error"), - message: t("issue.restore.failed.message"), - }); - }) - .finally(() => setIsRestoring(false)); - }; - - // auth - const isEditable = allowPermissions( - [EUserPermissions.ADMIN, EUserPermissions.MEMBER], - EUserPermissionsLevel.PROJECT, - workspaceSlug, - projectId - ); - const canRestoreIssue = allowPermissions( - [EUserPermissions.ADMIN, EUserPermissions.MEMBER], - EUserPermissionsLevel.PROJECT, - workspaceSlug, - projectId - ); - const isArchivingAllowed = !issue?.archived_at && isEditable; - const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group); - - return ( - <> - setDeleteIssueModal(false)} - isOpen={deleteIssueModal} - data={issue} - onSubmit={handleDeleteIssue} - /> - setArchiveIssueModal(false)} - data={issue} - onSubmit={handleArchiveIssue} - /> -
    -
    - {currentUser && !issue?.archived_at && ( - - )} -
    - - - - {issue?.archived_at && canRestoreIssue ? ( - <> - - - - - ) : ( - <> - {isArchivingAllowed && ( - - - - )} - - )} - - {isEditable && ( - - - - )} -
    -
    -
    - - ); -}); diff --git a/web/core/components/issues/peek-overview/view.tsx b/web/core/components/issues/peek-overview/view.tsx deleted file mode 100644 index bcdf61d67..000000000 --- a/web/core/components/issues/peek-overview/view.tsx +++ /dev/null @@ -1,278 +0,0 @@ -import { FC, useRef, useState } from "react"; -import { observer } from "mobx-react"; -// constants -import { EIssueServiceType } from "@plane/constants"; -// types -import { TNameDescriptionLoader } from "@plane/types"; -// components -import { cn } from "@plane/utils"; -import { - DeleteIssueModal, - IssuePeekOverviewHeader, - TPeekModes, - PeekOverviewIssueDetails, - PeekOverviewProperties, - TIssueOperations, - ArchiveIssueModal, - IssuePeekOverviewLoader, - IssuePeekOverviewError, - IssueDetailWidgets, -} from "@/components/issues"; -// helpers -// hooks -import { useIssueDetail } from "@/hooks/store"; -import useKeypress from "@/hooks/use-keypress"; -import usePeekOverviewOutsideClickDetector from "@/hooks/use-peek-overview-outside-click"; -// store hooks -import { IssueActivity } from "../issue-detail/issue-activity"; - -interface IIssueView { - workspaceSlug: string; - projectId: string; - issueId: string; - isLoading?: boolean; - isError?: boolean; - is_archived: boolean; - disabled?: boolean; - embedIssue?: boolean; - embedRemoveCurrentNotification?: () => void; - issueOperations: TIssueOperations; -} - -export const IssueView: FC = observer((props) => { - const { - workspaceSlug, - projectId, - issueId, - isLoading, - isError, - is_archived, - disabled = false, - embedIssue = false, - embedRemoveCurrentNotification, - issueOperations, - } = props; - // states - const [peekMode, setPeekMode] = useState("side-peek"); - const [isSubmitting, setIsSubmitting] = useState("saved"); - // ref - const issuePeekOverviewRef = useRef(null); - // store hooks - const { - setPeekIssue, - isAnyModalOpen, - isDeleteIssueModalOpen, - isArchiveIssueModalOpen, - toggleDeleteIssueModal, - toggleArchiveIssueModal, - issue: { getIssueById, getIsLocalDBIssueDescription }, - } = useIssueDetail(); - const { isAnyModalOpen: isAnyEpicModalOpen } = useIssueDetail(EIssueServiceType.EPICS); - const issue = getIssueById(issueId); - // remove peek id - const removeRoutePeekId = () => { - setPeekIssue(undefined); - if (embedIssue && embedRemoveCurrentNotification) embedRemoveCurrentNotification(); - }; - - const isLocalDBIssueDescription = getIsLocalDBIssueDescription(issueId); - - usePeekOverviewOutsideClickDetector( - issuePeekOverviewRef, - () => { - if (!embedIssue) { - if (!isAnyModalOpen && !isAnyEpicModalOpen) { - removeRoutePeekId(); - } - } - }, - issueId - ); - - const handleKeyDown = () => { - const slashCommandDropdownElement = document.querySelector("#slash-command"); - const editorImageFullScreenModalElement = document.querySelector(".editor-image-full-screen-modal"); - const dropdownElement = document.activeElement?.tagName === "INPUT"; - if (!isAnyModalOpen && !slashCommandDropdownElement && !dropdownElement && !editorImageFullScreenModalElement) { - removeRoutePeekId(); - const issueElement = document.getElementById(`issue-${issueId}`); - if (issueElement) issueElement?.focus(); - } - }; - - useKeypress("Escape", () => !embedIssue && handleKeyDown()); - - const handleRestore = async () => { - if (!issueOperations.restore) return; - await issueOperations.restore(workspaceSlug, projectId, issueId); - removeRoutePeekId(); - }; - - const peekOverviewIssueClassName = cn( - !embedIssue - ? "fixed z-20 flex flex-col overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 transition-all duration-300" - : `w-full h-full`, - !embedIssue && { - "bottom-0 right-0 top-0 w-full md:w-[50%] border-0 border-l": peekMode === "side-peek", - "size-5/6 top-[8.33%] left-[8.33%]": peekMode === "modal", - "inset-0 m-4": peekMode === "full-screen", - } - ); - - return ( - <> - {issue && !is_archived && ( - toggleArchiveIssueModal(null)} - data={issue} - onSubmit={async () => { - if (issueOperations.archive) await issueOperations.archive(workspaceSlug, projectId, issueId); - removeRoutePeekId(); - }} - /> - )} - - {issue && isDeleteIssueModalOpen === issue.id && ( - { - toggleDeleteIssueModal(null); - }} - data={issue} - onSubmit={async () => issueOperations.remove(workspaceSlug, projectId, issueId)} - /> - )} - -
    - {issueId && ( -
    - {isError ? ( -
    - -
    - ) : ( - isLoading && - )} - {!isLoading && !isError && issue && ( - <> - {/* header */} - setPeekMode(value)} - removeRoutePeekId={removeRoutePeekId} - toggleDeleteIssueModal={toggleDeleteIssueModal} - toggleArchiveIssueModal={toggleArchiveIssueModal} - handleRestoreIssue={handleRestore} - isArchived={is_archived} - issueId={issueId} - workspaceSlug={workspaceSlug} - projectId={projectId} - isSubmitting={isSubmitting} - disabled={disabled} - embedIssue={embedIssue} - /> - {/* content */} -
    - {["side-peek", "modal"].includes(peekMode) ? ( -
    - setIsSubmitting(value)} - /> - -
    - -
    - - - - -
    - ) : ( -
    -
    -
    - setIsSubmitting(value)} - /> - -
    - -
    - - -
    -
    -
    - -
    -
    - )} -
    - - )} -
    - )} -
    - - ); -}); diff --git a/web/core/components/issues/select/index.ts b/web/core/components/issues/select/index.ts deleted file mode 100644 index c8a3baf31..000000000 --- a/web/core/components/issues/select/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./label"; diff --git a/web/core/components/pages/editor/toolbar/info-popover.tsx b/web/core/components/pages/editor/toolbar/info-popover.tsx deleted file mode 100644 index 49ad06b9b..000000000 --- a/web/core/components/pages/editor/toolbar/info-popover.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { useState } from "react"; -import { observer } from "mobx-react"; -import Link from "next/link"; -import { useParams } from "next/navigation"; -import { usePopper } from "react-popper"; -import { Info } from "lucide-react"; -// plane imports -import { Avatar } from "@plane/ui"; -import { calculateTimeAgoShort, getFileURL, getReadTimeFromWordsCount, renderFormattedDate } from "@plane/utils"; -// hooks -import { useMember } from "@/hooks/store"; -// store -import { TPageInstance } from "@/store/pages/base-page"; - -type Props = { - page: TPageInstance; -}; - -export const PageInfoPopover: React.FC = observer((props) => { - const { page } = props; - // states - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - // refs - const [referenceElement, setReferenceElement] = useState(null); - const [popperElement, setPopperElement] = useState(null); - // router - const { workspaceSlug } = useParams(); - // popper-js - const { styles: infoPopoverStyles, attributes: infoPopoverAttributes } = usePopper(referenceElement, popperElement, { - placement: "bottom-start", - }); - // store hooks - const { getUserDetails } = useMember(); - // derived values - const editorInformation = page.updated_by ? getUserDetails(page.updated_by) : undefined; - const creatorInformation = page.created_by ? getUserDetails(page.created_by) : undefined; - - const documentsInfo = page.editorRef?.getDocumentInfo() || { words: 0, characters: 0, paragraphs: 0 }; - - const secondsToReadableTime = () => { - const wordsCount = documentsInfo.words; - const readTimeInSeconds = Number(getReadTimeFromWordsCount(wordsCount).toFixed(0)); - return readTimeInSeconds < 60 ? `${readTimeInSeconds}s` : `${Math.ceil(readTimeInSeconds / 60)}m`; - }; - - const documentInfoCards = [ - { - key: "words-count", - title: "Words", - info: documentsInfo.words, - }, - { - key: "characters-count", - title: "Characters", - info: documentsInfo.characters, - }, - { - key: "paragraphs-count", - title: "Paragraphs", - info: documentsInfo.paragraphs, - }, - { - key: "read-time", - title: "Read time", - info: secondsToReadableTime(), - }, - ]; - - return ( -
    setIsPopoverOpen(true)} - onMouseLeave={() => setIsPopoverOpen(false)} - > - - {isPopoverOpen && ( -
    -
    - {documentInfoCards.map((card) => ( -
    -
    {card.info}
    -

    {card.title}

    -
    - ))} -
    -
    -
    -

    Edited by

    - - - - {editorInformation?.display_name}{" "} - {calculateTimeAgoShort(page.updated_at ?? "")} ago - - -
    -
    -

    Created by

    - - - - {creatorInformation?.display_name}{" "} - {renderFormattedDate(page.created_at)} - - -
    -
    -
    - )} -
    - ); -}); diff --git a/web/core/components/pages/editor/toolbar/root.tsx b/web/core/components/pages/editor/toolbar/root.tsx deleted file mode 100644 index 72c9da3d4..000000000 --- a/web/core/components/pages/editor/toolbar/root.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { observer } from "mobx-react"; -// components -import { cn } from "@plane/utils"; -import { PageToolbar } from "@/components/pages"; -// helpers -// hooks -import { usePageFilters } from "@/hooks/use-page-filters"; -// plane web components -import { PageCollaboratorsList } from "@/plane-web/components/pages/header/collaborators-list"; -// store -import { TPageInstance } from "@/store/pages/base-page"; - -type Props = { - page: TPageInstance; -}; - -export const PageEditorToolbarRoot: React.FC = observer((props) => { - const { page } = props; - // derived values - const { isContentEditable, editorRef } = page; - // page filters - const { isFullWidth, isStickyToolbarEnabled } = usePageFilters(); - // derived values - const shouldHideToolbar = !isStickyToolbarEnabled || !isContentEditable; - - return ( -
    -
    -
    - {editorRef && } - -
    -
    -
    - ); -}); diff --git a/web/core/components/pages/version/index.ts b/web/core/components/pages/version/index.ts deleted file mode 100644 index 8e04e4de9..000000000 --- a/web/core/components/pages/version/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from "./editor"; -export * from "./main-content"; -export * from "./root"; -export * from "./sidebar-list-item"; -export * from "./sidebar-list"; -export * from "./sidebar-root"; diff --git a/web/core/components/pages/version/root.tsx b/web/core/components/pages/version/root.tsx deleted file mode 100644 index f1dd0248b..000000000 --- a/web/core/components/pages/version/root.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { observer } from "mobx-react"; -// plane types -import { TPageVersion } from "@plane/types"; -// components -import { cn } from "@plane/utils"; -import { PageVersionsMainContent, PageVersionsSidebarRoot, TVersionEditorProps } from "@/components/pages"; -// helpers - -type Props = { - activeVersion: string | null; - currentVersionDescription: string | null; - editorComponent: React.FC; - fetchAllVersions: (pageId: string) => Promise; - fetchVersionDetails: (pageId: string, versionId: string) => Promise; - handleRestore: (descriptionHTML: string) => Promise; - isOpen: boolean; - onClose: () => void; - pageId: string; - restoreEnabled: boolean; -}; - -export const PageVersionsOverlay: React.FC = observer((props) => { - const { - activeVersion, - currentVersionDescription, - editorComponent, - fetchAllVersions, - fetchVersionDetails, - handleRestore, - isOpen, - onClose, - pageId, - restoreEnabled, - } = props; - - const handleClose = () => { - onClose(); - }; - - return ( -
    - - -
    - ); -}); diff --git a/web/core/components/pages/version/sidebar-list-item.tsx b/web/core/components/pages/version/sidebar-list-item.tsx deleted file mode 100644 index c5df2c0d2..000000000 --- a/web/core/components/pages/version/sidebar-list-item.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { observer } from "mobx-react"; -import Link from "next/link"; -// plane imports -import { useTranslation } from "@plane/i18n"; -import { TPageVersion } from "@plane/types"; -import { Avatar } from "@plane/ui"; -import { cn, renderFormattedDate, renderFormattedTime, getFileURL } from "@plane/utils"; -// helpers -// hooks -import { useMember } from "@/hooks/store"; - -type Props = { - href: string; - isActive: boolean; - version: TPageVersion; -}; - -export const PlaneVersionsSidebarListItem: React.FC = observer((props) => { - const { href, isActive, version } = props; - // store hooks - const { getUserDetails } = useMember(); - // derived values - const ownerDetails = getUserDetails(version.owned_by); - // translation - const { t } = useTranslation(); - - return ( - -

    - {renderFormattedDate(version.last_saved_at)} {renderFormattedTime(version.last_saved_at)} -

    -

    - - {ownerDetails?.display_name ?? t("common.deactivated_user")} -

    - - ); -}); diff --git a/web/core/components/pages/version/sidebar-list.tsx b/web/core/components/pages/version/sidebar-list.tsx deleted file mode 100644 index bff9c3698..000000000 --- a/web/core/components/pages/version/sidebar-list.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useState } from "react"; -import Link from "next/link"; -import useSWR from "swr"; -import { TriangleAlert } from "lucide-react"; -// plane types -import { TPageVersion } from "@plane/types"; -// plane ui -import { Button, Loader } from "@plane/ui"; -// components -import { cn } from "@plane/utils"; -import { PlaneVersionsSidebarListItem } from "@/components/pages"; -// helpers -// hooks -import { useQueryParams } from "@/hooks/use-query-params"; - -type Props = { - activeVersion: string | null; - fetchAllVersions: (pageId: string) => Promise; - isOpen: boolean; - pageId: string; -}; - -export const PageVersionsSidebarList: React.FC = (props) => { - const { activeVersion, fetchAllVersions, isOpen, pageId } = props; - // states - const [isRetrying, setIsRetrying] = useState(false); - // update query params - const { updateQueryParams } = useQueryParams(); - - const { - data: versionsList, - error: versionsListError, - mutate: mutateVersionsList, - } = useSWR( - pageId && isOpen ? `PAGE_VERSIONS_LIST_${pageId}` : null, - pageId && isOpen ? () => fetchAllVersions(pageId) : null - ); - - const handleRetry = async () => { - setIsRetrying(true); - await mutateVersionsList(); - setIsRetrying(false); - }; - - const getVersionLink = (versionID: string) => - updateQueryParams({ - paramsToAdd: { version: versionID }, - }); - - return ( -
    - -

    Current version

    - - {versionsListError ? ( -
    -
    - - - -
    -
    Something went wrong!
    -

    - There was a problem while loading previous -
    - versions, please try again. -

    -
    - -
    -
    - ) : versionsList ? ( - versionsList.map((version) => ( - - )) - ) : ( - - - - - - - - )} -
    - ); -}; diff --git a/web/core/components/pages/version/sidebar-root.tsx b/web/core/components/pages/version/sidebar-root.tsx deleted file mode 100644 index 793d7fed9..000000000 --- a/web/core/components/pages/version/sidebar-root.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { X } from "lucide-react"; -// plane types -import { TPageVersion } from "@plane/types"; -// components -import { PageVersionsSidebarList } from "@/components/pages"; - -type Props = { - activeVersion: string | null; - fetchAllVersions: (pageId: string) => Promise; - handleClose: () => void; - isOpen: boolean; - pageId: string; -}; - -export const PageVersionsSidebarRoot: React.FC = (props) => { - const { activeVersion, fetchAllVersions, handleClose, isOpen, pageId } = props; - - return ( -
    -
    -
    Version history
    - -
    - -
    - ); -}; diff --git a/web/core/components/sidebar/index.ts b/web/core/components/sidebar/index.ts deleted file mode 100644 index b2e6f7602..000000000 --- a/web/core/components/sidebar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./sidebar-navigation"; \ No newline at end of file diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx b/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx deleted file mode 100644 index 847c45f7a..000000000 --- a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx +++ /dev/null @@ -1,39 +0,0 @@ -"use client"; -import React, { FC } from "react"; -import { observer } from "mobx-react"; -import Link from "next/link"; -import { Tooltip } from "@plane/ui"; -import { cn } from "@plane/utils"; -import { useAppTheme } from "@/hooks/store"; -import { usePlatformOS } from "@/hooks/use-platform-os"; - -type Props = { - href: string; - title: string; - icon: JSX.Element; - isSidebarCollapsed: boolean; -}; - -export const FavoriteItemTitle: FC = observer((props) => { - const { href, title, icon, isSidebarCollapsed } = props; - // store hooks - const { toggleSidebar } = useAppTheme(); - const { isMobile } = usePlatformOS(); - - const linkClass = "flex items-center gap-1.5 truncate w-full"; - const collapsedClass = - "group/project-item cursor-pointer relative group w-full flex items-center justify-center gap-1.5 rounded px-2 py-1 outline-none text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-90 active:bg-custom-sidebar-background-90 truncate p-0 size-8 aspect-square mx-auto"; - - const handleOnClick = () => { - if (isMobile) toggleSidebar(); - }; - - return ( - - - {icon} - {!isSidebarCollapsed && {title}} - - - ); -}); diff --git a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx b/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx deleted file mode 100644 index 9c3c64b8d..000000000 --- a/web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; -import React, { FC } from "react"; -// helpers -import { cn } from "@plane/utils"; - -type Props = { - children: React.ReactNode; - elementRef: React.RefObject; - isMenuActive?: boolean; - sidebarCollapsed?: boolean; -}; - -export const FavoriteItemWrapper: FC = (props) => { - const { children, elementRef, isMenuActive = false, sidebarCollapsed = false } = props; - return ( - <> - {sidebarCollapsed ? ( -
    {children}
    - ) : ( -
    - {children} -
    - )} - - ); -}; diff --git a/web/core/components/workspace/sidebar/sidebar-menu-items.tsx b/web/core/components/workspace/sidebar/sidebar-menu-items.tsx deleted file mode 100644 index 89c0f150e..000000000 --- a/web/core/components/workspace/sidebar/sidebar-menu-items.tsx +++ /dev/null @@ -1,75 +0,0 @@ -"use client"; -import React, { useMemo } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "next/navigation"; -import { Ellipsis } from "lucide-react"; -// plane imports -import { - WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS, - WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS, -} from "@plane/constants"; -import { useTranslation } from "@plane/i18n"; -import { cn } from "@plane/utils"; -// components -import { SidebarNavItem } from "@/components/sidebar"; -// store hooks -import { useAppTheme, useWorkspace } from "@/hooks/store"; -// plane-web imports -import { SidebarItem } from "@/plane-web/components/workspace/sidebar"; - -export const SidebarMenuItems = observer(() => { - // routers - const { workspaceSlug } = useParams(); - // store hooks - const { sidebarCollapsed, extendedSidebarCollapsed, toggleExtendedSidebar } = useAppTheme(); - const { getNavigationPreferences } = useWorkspace(); - // translation - const { t } = useTranslation(); - // derived values - const currentWorkspaceNavigationPreferences = getNavigationPreferences(workspaceSlug.toString()); - - const sortedNavigationItems = useMemo( - () => - WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS.map((item) => { - const preference = currentWorkspaceNavigationPreferences?.[item.key]; - return { - ...item, - sort_order: preference ? preference.sort_order : 0, - }; - }).sort((a, b) => a.sort_order - b.sort_order), - [currentWorkspaceNavigationPreferences] - ); - - return ( -
    - {WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS.map((item, _index) => ( - - ))} - {sortedNavigationItems.map((item, _index) => ( - - ))} - - - -
    - ); -}); diff --git a/web/core/hooks/store/use-event-tracker.ts b/web/core/hooks/store/use-event-tracker.ts deleted file mode 100644 index 0f92aaced..000000000 --- a/web/core/hooks/store/use-event-tracker.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useContext } from "react"; -// mobx store -import { StoreContext } from "@/lib/store-context"; -// types -import { IEventTrackerStore } from "@/plane-web/store/event-tracker.store"; - -export const useEventTracker = (): IEventTrackerStore => { - const context = useContext(StoreContext); - if (context === undefined) throw new Error("useEventTracker must be used within StoreProvider"); - return context.eventTracker; -}; diff --git a/web/core/hooks/use-query-params.ts b/web/core/hooks/use-query-params.ts deleted file mode 100644 index 8b689f0cb..000000000 --- a/web/core/hooks/use-query-params.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useSearchParams, usePathname } from "next/navigation"; - -type TParamsToAdd = { - [key: string]: string; -}; - -export const useQueryParams = () => { - // next navigation - const searchParams = useSearchParams(); - const pathname = usePathname(); - - const updateQueryParams = ({ - paramsToAdd = {}, - paramsToRemove = [], - }: { - paramsToAdd?: TParamsToAdd; - paramsToRemove?: string[]; - }) => { - const currentParams = new URLSearchParams(searchParams.toString()); - - // add or update query parameters - Object.keys(paramsToAdd).forEach((key) => { - currentParams.set(key, paramsToAdd[key]); - }); - - // remove specified query parameters - paramsToRemove.forEach((key) => { - currentParams.delete(key); - }); - - // construct the new route with the updated query parameters - const newRoute = `${pathname}?${currentParams.toString()}`; - return newRoute; - }; - - return { - updateQueryParams, - }; -}; diff --git a/web/core/lib/n-progress/utils/sameURL.ts b/web/core/lib/n-progress/utils/sameURL.ts deleted file mode 100644 index 14c689f75..000000000 --- a/web/core/lib/n-progress/utils/sameURL.ts +++ /dev/null @@ -1,16 +0,0 @@ -export function isSameURL(target: URL, current: URL) { - const cleanTarget = - target.protocol + '//' + target.host + target.pathname + target.search; - const cleanCurrent = - current.protocol + '//' + current.host + current.pathname + current.search; - - return cleanTarget === cleanCurrent; -} - -export function isSameURLWithoutSearch(target: URL, current: URL) { - const cleanTarget = target.protocol + '//' + target.host + target.pathname; - const cleanCurrent = - current.protocol + '//' + current.host + current.pathname; - - return cleanTarget === cleanCurrent; -} diff --git a/web/core/store/event-tracker.store.ts b/web/core/store/event-tracker.store.ts deleted file mode 100644 index 8116eaaf0..000000000 --- a/web/core/store/event-tracker.store.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { action, computed, makeObservable, observable } from "mobx"; -import posthog from "posthog-js"; -// store -import { - GROUP_WORKSPACE_TRACKER_EVENT, - EventProps, - IssueEventProps, - getCycleEventPayload, - getIssueEventPayload, - getModuleEventPayload, - getProjectEventPayload, - getProjectStateEventPayload, - getWorkspaceEventPayload, - getPageEventPayload, - WORKSPACE_TRACKER_EVENTS, -} from "@plane/constants"; -import { CoreRootStore } from "./root.store"; - -export interface ICoreEventTrackerStore { - // properties - trackElement: string | undefined; - // computed - getRequiredProperties: any; - // actions - resetSession: () => void; - setTrackElement: (element: string) => void; - captureEvent: (eventName: string, payload?: any) => void; - joinWorkspaceMetricGroup: (workspaceId?: string) => void; - captureWorkspaceEvent: (props: EventProps) => void; - captureProjectEvent: (props: EventProps) => void; - captureCycleEvent: (props: EventProps) => void; - captureModuleEvent: (props: EventProps) => void; - capturePageEvent: (props: EventProps) => void; - captureIssueEvent: (props: IssueEventProps) => void; - captureProjectStateEvent: (props: EventProps) => void; -} - -export abstract class CoreEventTrackerStore implements ICoreEventTrackerStore { - trackElement: string | undefined = undefined; - rootStore; - constructor(_rootStore: CoreRootStore) { - makeObservable(this, { - // properties - trackElement: observable, - // computed - getRequiredProperties: computed, - // actions - resetSession: action, - setTrackElement: action, - captureEvent: action, - captureProjectEvent: action, - captureCycleEvent: action, - }); - // store - this.rootStore = _rootStore; - } - - /** - * @description: Returns the necessary property for the event tracking - */ - get getRequiredProperties() { - const currentWorkspaceDetails = this.rootStore.workspaceRoot.currentWorkspace; - const currentProjectDetails = this.rootStore.projectRoot.project.currentProjectDetails; - return { - workspace_id: currentWorkspaceDetails?.id, - project_id: currentProjectDetails?.id, - }; - } - - /** - * @description: Set the trigger point of event. - * @param {string} element - */ - setTrackElement = (element?: string) => { - this.trackElement = element; - }; - - /** - * @description: Reset the session. - */ - resetSession = () => { - posthog?.reset(); - }; - - /** - * @description: Creates the workspace metric group. - * @param {string} userEmail - * @param {string} workspaceId - */ - joinWorkspaceMetricGroup = (workspaceId?: string) => { - if (!workspaceId) return; - posthog?.group(GROUP_WORKSPACE_TRACKER_EVENT, workspaceId, { - date: new Date().toDateString(), - workspace_id: workspaceId, - }); - }; - - /** - * @description: Captures the event. - * @param {string} eventName - * @param {any} payload - */ - captureEvent = (eventName: string, payload?: any) => { - posthog?.capture(eventName, { - ...this.getRequiredProperties, - ...payload, - element: payload?.element ?? this.trackElement, - }); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the workspace crud related events. - * @param {EventProps} props - */ - captureWorkspaceEvent = (props: EventProps) => { - const { eventName, payload } = props; - if (eventName === WORKSPACE_TRACKER_EVENTS.create && payload.state == "SUCCESS") { - this.joinWorkspaceMetricGroup(payload.id); - } - const eventPayload: any = getWorkspaceEventPayload({ - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the project related events. - * @param {EventProps} props - */ - captureProjectEvent = (props: EventProps) => { - const { eventName, payload } = props; - const eventPayload: any = getProjectEventPayload({ - ...this.getRequiredProperties, - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the cycle related events. - * @param {EventProps} props - */ - captureCycleEvent = (props: EventProps) => { - const { eventName, payload } = props; - const eventPayload: any = getCycleEventPayload({ - ...this.getRequiredProperties, - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the module related events. - * @param {EventProps} props - */ - captureModuleEvent = (props: EventProps) => { - const { eventName, payload } = props; - const eventPayload: any = getModuleEventPayload({ - ...this.getRequiredProperties, - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the project pages related events. - * @param {EventProps} props - */ - capturePageEvent = (props: EventProps) => { - const { eventName, payload } = props; - const eventPayload: any = getPageEventPayload({ - ...this.getRequiredProperties, - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the issue related events. - * @param {IssueEventProps} props - */ - captureIssueEvent = (props: IssueEventProps) => { - const { eventName, payload } = props; - const eventPayload: any = { - ...getIssueEventPayload(props), - ...this.getRequiredProperties, - state_group: this.rootStore.state.getStateById(payload.state_id)?.group ?? "", - element: payload.element ?? this.trackElement, - }; - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; - - /** - * @description: Captures the issue related events. - * @param {IssueEventProps} props - */ - captureProjectStateEvent = (props: EventProps) => { - const { eventName, payload } = props; - const eventPayload: any = getProjectStateEventPayload({ - ...this.getRequiredProperties, - ...payload, - element: payload.element ?? this.trackElement, - }); - posthog?.capture(eventName, eventPayload); - this.setTrackElement(undefined); - }; -} diff --git a/web/ee/components/breadcrumbs/index.ts b/web/ee/components/breadcrumbs/index.ts deleted file mode 100644 index ae95faf6b..000000000 --- a/web/ee/components/breadcrumbs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/breadcrumbs"; \ No newline at end of file diff --git a/web/ee/components/issues/bulk-operations/index.ts b/web/ee/components/issues/bulk-operations/index.ts deleted file mode 100644 index 5470941b5..000000000 --- a/web/ee/components/issues/bulk-operations/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/issues/bulk-operations/index"; \ No newline at end of file diff --git a/web/ee/components/issues/issue-modal/additional-properties.tsx b/web/ee/components/issues/issue-modal/additional-properties.tsx deleted file mode 100644 index 388efd523..000000000 --- a/web/ee/components/issues/issue-modal/additional-properties.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/issues/issue-modal/additional-properties"; diff --git a/web/ee/components/sidebar/index.ts b/web/ee/components/sidebar/index.ts deleted file mode 100644 index ffc5f14cf..000000000 --- a/web/ee/components/sidebar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/sidebar"; \ No newline at end of file diff --git a/web/ee/components/workspace/billing/index.ts b/web/ee/components/workspace/billing/index.ts deleted file mode 100644 index 50a9c47c0..000000000 --- a/web/ee/components/workspace/billing/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./root"; \ No newline at end of file diff --git a/web/ee/components/workspace/upgrade-badge.tsx b/web/ee/components/workspace/upgrade-badge.tsx deleted file mode 100644 index 1c7fcfb64..000000000 --- a/web/ee/components/workspace/upgrade-badge.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/workspace/upgrade-badge"; diff --git a/web/ee/store/event-tracker.store.ts b/web/ee/store/event-tracker.store.ts deleted file mode 100644 index 68f6a3a74..000000000 --- a/web/ee/store/event-tracker.store.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/store/event-tracker.store"; diff --git a/web/public/animated-icons/uploading.json b/web/public/animated-icons/uploading.json deleted file mode 100644 index 1560fd40e..000000000 --- a/web/public/animated-icons/uploading.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"5.3.4","fr":60,"ip":0,"op":84,"w":678,"h":896,"nm":"share","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Слой 18","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.347,"y":1},"o":{"x":0.333,"y":0},"n":"0p347_1_0p333_0","t":64,"s":[338,1288,0],"e":[338,492,0],"to":[0,-132.66667175293,0],"ti":[0,132.66667175293,0]},{"t":76}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.354,"y":1},"o":{"x":0.333,"y":0},"n":"0p354_1_0p333_0","t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.125,-433.461],[0.223,-433.488],[0,-433.488],[0.229,-433.33],[0,-433.488],[0.25,-433.262]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[177,-256.711],[0.223,-433.488],[0,-433.488],[-176.777,-256.711],[0,-433.488],[0,169.488]],"c":false}]},{"t":79}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":84,"st":63,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Слой 15","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.393,"y":1},"o":{"x":0.333,"y":0},"n":"0p393_1_0p333_0","t":5,"s":[338,492,0],"e":[338,482,0],"to":[0,-1.66666662693024,0],"ti":[0,-22.1666660308838,0]},{"i":{"x":0.418,"y":1},"o":{"x":0.333,"y":0},"n":"0p418_1_0p333_0","t":15,"s":[338,482,0],"e":[338,625,0],"to":[0,22.1666660308838,0],"ti":[0,-1.66666662693024,0]},{"i":{"x":0.362,"y":1},"o":{"x":0.333,"y":0},"n":"0p362_1_0p333_0","t":26,"s":[338,625,0],"e":[338,492,0],"to":[0,1.66666662693024,0],"ti":[0,22.1666660308838,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.338,"y":1},"o":{"x":0.333,"y":0},"n":"0p338_1_0p333_0","t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[177,-256.711],[0.223,-433.488],[0,-433.488],[-176.777,-256.711],[0,-433.488],[0,169.488]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[169,-252.711],[0.223,-433.488],[0,-433.488],[-168.777,-252.711],[0,-433.488],[0,169.488]],"c":false}]},{"i":{"x":0.368,"y":1},"o":{"x":0.333,"y":0},"n":"0p368_1_0p333_0","t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[169,-252.711],[0.223,-433.488],[0,-433.488],[-168.777,-252.711],[0,-433.488],[0,169.488]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[189,-181.274],[0.223,-273],[0,-273],[-198.777,-181.274],[0,-273],[0,169.488]],"c":false}]},{"i":{"x":0.301,"y":1},"o":{"x":0.333,"y":0},"n":"0p301_1_0p333_0","t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[189,-181.274],[0.223,-273],[0,-273],[-198.777,-181.274],[0,-273],[0,169.488]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[177,-256.711],[0.223,-433.488],[0,-433.488],[-176.777,-256.711],[0,-433.488],[0,169.488]],"c":false}]},{"i":{"x":0.338,"y":1},"o":{"x":0.333,"y":0},"n":"0p338_1_0p333_0","t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[177,-256.711],[0.223,-433.488],[0,-433.488],[-176.777,-256.711],[0,-433.488],[0,169.488]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[55,-331.686],[0.223,-433.488],[0,-433.488],[-52.777,-331.843],[0,-433.488],[0,-78.512]],"c":false}]},{"i":{"x":0.301,"y":1},"o":{"x":0.333,"y":0},"n":"0p301_1_0p333_0","t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[55,-331.686],[0.223,-433.488],[0,-433.488],[-52.777,-331.843],[0,-433.488],[0,-78.512]],"c":false}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.25,-432.593],[0.223,-433.488],[0,-433.488],[-0.027,-433.093],[0,-433.488],[0,-432.512]],"c":false}]},{"t":42}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":39,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Слой 17","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[338,492,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[48,-30.133],[32.954,0],[0,0],[25.447,15.225],[0,61.848],[0,0]],"o":[[0,0],[0,60.546],[-26.126,16.401],[0,0],[-31.652,0],[-49.724,-29.75],[0,0],[0,0]],"v":[[301.777,0],[301.777,196],[221.699,340.096],[131.777,366],[-131.777,366],[-218.579,342.008],[-301.777,196],[-301.777,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":2,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.473],"y":[-0.005]},"n":["0p833_1_0p473_-0p005"],"t":8,"s":[0],"e":[10]},{"i":{"x":[0.411],"y":[0.948]},"o":{"x":[0.167],"y":[0]},"n":["0p411_0p948_0p167_0"],"t":19,"s":[10],"e":[0]},{"t":40}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.473],"y":[0.005]},"n":["0p833_1_0p473_0p005"],"t":8,"s":[100],"e":[90]},{"i":{"x":[0.411],"y":[1.052]},"o":{"x":[0.167],"y":[0]},"n":["0p411_1p052_0p167_0"],"t":19,"s":[90],"e":[100]},{"t":40}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":84,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e8fcdc11c..eaab6478c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,919 +3,215 @@ "@adobe/css-tools@^4.4.0": - version "4.4.1" - resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" - integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== + version "4.4.3" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.3.tgz#beebbefb0264fdeb32d3052acae0e0d94315a9a2" + integrity sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA== "@alloc/quick-lru@^5.2.0": version "5.2.0" - resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== "@ampproject/remapping@^2.2.0": version "2.3.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@asamuzakjp/css-color@^2.8.2": - version "2.8.3" - resolved "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz#665f0f5e8edb95d8f543847529e30fe5cc437ef7" - integrity sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw== +"@asamuzakjp/css-color@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-3.2.0.tgz#cc42f5b85c593f79f1fa4f25d2b9b321e61d1794" + integrity sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw== dependencies: - "@csstools/css-calc" "^2.1.1" - "@csstools/css-color-parser" "^3.0.7" + "@csstools/css-calc" "^2.1.3" + "@csstools/css-color-parser" "^3.0.9" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" lru-cache "^10.4.3" "@atlaskit/pragmatic-drag-and-drop-auto-scroll@^1.3.0": version "1.4.0" - resolved "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop-auto-scroll/-/pragmatic-drag-and-drop-auto-scroll-1.4.0.tgz#99be18a428c93996b2cde3b97e88db85753aa5a5" + resolved "https://registry.yarnpkg.com/@atlaskit/pragmatic-drag-and-drop-auto-scroll/-/pragmatic-drag-and-drop-auto-scroll-1.4.0.tgz#99be18a428c93996b2cde3b97e88db85753aa5a5" integrity sha512-5GoikoTSW13UX76F9TDeWB8x3jbbGlp/Y+3aRkHe1MOBMkrWkwNpJ42MIVhhX/6NSeaZiPumP0KbGJVs2tOWSQ== dependencies: "@atlaskit/pragmatic-drag-and-drop" "^1.2.0" "@babel/runtime" "^7.0.0" "@atlaskit/pragmatic-drag-and-drop-hitbox@^1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop-hitbox/-/pragmatic-drag-and-drop-hitbox-1.0.3.tgz#fcce42f5e2c5a26007f4422397acad29608d3784" - integrity sha512-/Sbu/HqN2VGLYBhnsG7SbRNg98XKkbF6L7XDdBi+izRybfaK1FeMfodPpm/xnBHPJzwYMdkE0qtLyv6afhgMUA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@atlaskit/pragmatic-drag-and-drop-hitbox/-/pragmatic-drag-and-drop-hitbox-1.1.0.tgz#3a031ac295513a394eff116f9b75869e64d3e559" + integrity sha512-JWt6eVp6Br2FPHRM8s0dUIHQk/jFInGP1f3ti5CdtM1Ji5/pt8Akm44wDC063Gv2i5RGseixtbW0z/t6RYtbdg== dependencies: - "@atlaskit/pragmatic-drag-and-drop" "^1.1.0" + "@atlaskit/pragmatic-drag-and-drop" "^1.6.0" "@babel/runtime" "^7.0.0" -"@atlaskit/pragmatic-drag-and-drop@^1.1.0", "@atlaskit/pragmatic-drag-and-drop@^1.1.10", "@atlaskit/pragmatic-drag-and-drop@^1.1.3", "@atlaskit/pragmatic-drag-and-drop@^1.2.0": - version "1.5.0" - resolved "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.5.0.tgz#d49979bfac99030b43196d05223989eee0c0030c" - integrity sha512-VnHcgOBALm+mbL9CoJPI6wBNQeB0is+CkejdfAlaP8RfBoELe+0sQtE8j4Z4fPRqDzo11OEqUYKHkmx4Ttzozg== +"@atlaskit/pragmatic-drag-and-drop@^1.1.10", "@atlaskit/pragmatic-drag-and-drop@^1.1.3", "@atlaskit/pragmatic-drag-and-drop@^1.2.0", "@atlaskit/pragmatic-drag-and-drop@^1.6.0": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.7.4.tgz#d90f833c036e62119fb2acf7fd84c851b6af2a52" + integrity sha512-lZHnO9BJdHPKnwB0uvVUCyDnIhL+WAHzXQ2EXX0qacogOsnvIUiCgY0BLKhBqTCWln3/f/Ox5jU54MKO6ayh9A== dependencies: "@babel/runtime" "^7.0.0" bind-event-listener "^3.0.0" raf-schd "^4.0.3" -"@babel/cli@^7.25.6": - version "7.26.4" - resolved "https://registry.npmjs.org/@babel/cli/-/cli-7.26.4.tgz#4101ff8ee5de8447a6c395397a97921056411d20" - integrity sha512-+mORf3ezU3p3qr+82WvJSnQNE1GAYeoCfEv4fik6B5/2cvKZ75AX8oawWQdXtM9MmndooQj15Jr9kelRFWsuRw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@jridgewell/trace-mapping" "^0.3.25" - commander "^6.2.0" - convert-source-map "^2.0.0" - fs-readdir-recursive "^1.1.0" - glob "^7.2.0" - make-dir "^2.1.0" - slash "^2.0.0" - optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" - chokidar "^3.6.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" - picocolors "^1.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" - integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.27.2": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.0.tgz#9fc6fd58c2a6a15243cd13983224968392070790" + integrity sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw== -"@babel/core@^7.18.9", "@babel/core@^7.25.2": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz#7742f11c75acea6b08a8e24c5c0c8c89e89bf53e" - integrity sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ== +"@babel/core@^7.18.9": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.0.tgz#55dad808d5bf3445a108eefc88ea3fdf034749a4" + integrity sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.8" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helpers" "^7.26.7" - "@babel/parser" "^7.26.8" - "@babel/template" "^7.26.8" - "@babel/traverse" "^7.26.8" - "@babel/types" "^7.26.8" - "@types/gensync" "^1.0.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.27.3" + "@babel/helpers" "^7.27.6" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.0" + "@babel/types" "^7.28.0" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.8.tgz#f9c5e770309e12e3099ad8271e52f6caa15442ab" - integrity sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA== +"@babel/generator@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" + integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== dependencies: - "@babel/parser" "^7.26.8" - "@babel/types" "^7.26.8" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@babel/parser" "^7.28.0" + "@babel/types" "^7.28.0" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" - integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== +"@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" - integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== - dependencies: - "@babel/compat-data" "^7.26.5" - "@babel/helper-validator-option" "^7.25.9" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" - integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ== +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/traverse" "^7.25.9" - semver "^6.3.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": - version "7.26.3" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0" - integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong== +"@babel/helper-module-transforms@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" + integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - regexpu-core "^6.2.0" - semver "^6.3.1" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.3" -"@babel/helper-define-polyfill-provider@^0.6.3": - version "0.6.3" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" - integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-member-expression-to-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" - integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-optimise-call-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" - integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== - dependencies: - "@babel/types" "^7.25.9" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5": - version "7.26.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" - integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== - -"@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-wrap-function" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-replace-supers@^7.25.9": - version "7.26.5" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" - integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.25.9" - "@babel/helper-optimise-call-expression" "^7.25.9" - "@babel/traverse" "^7.26.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" - integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== - -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== - dependencies: - "@babel/template" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helpers@7.26.10", "@babel/helpers@^7.26.7": +"@babel/helpers@7.26.10", "@babel/helpers@^7.27.6": version "7.26.10" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384" integrity sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g== dependencies: "@babel/template" "^7.26.9" "@babel/types" "^7.26.10" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.26.8": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.8.tgz#deca2b4d99e5e1b1553843b99823f118da6107c2" - integrity sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw== +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.27.2", "@babel/parser@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" + integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== dependencies: - "@babel/types" "^7.26.8" + "@babel/types" "^7.28.0" -"@babel/parser@^7.26.9": +"@babel/runtime@7.26.10", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": version "7.26.10" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749" - integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA== - dependencies: - "@babel/types" "^7.26.10" - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" - integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" - integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" - integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" - integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" - integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - version "7.21.0-placeholder-for-preset-env.2" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" - integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== - -"@babel/plugin-syntax-import-assertions@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" - integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-import-attributes@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" - integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-jsx@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" - integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-typescript@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" - integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" - integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-transform-arrow-functions@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" - integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-async-generator-functions@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" - integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-remap-async-to-generator" "^7.25.9" - "@babel/traverse" "^7.26.8" - -"@babel/plugin-transform-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" - integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-remap-async-to-generator" "^7.25.9" - -"@babel/plugin-transform-block-scoped-functions@^7.26.5": - version "7.26.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" - integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-block-scoping@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" - integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-class-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" - integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-class-static-block@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" - integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-classes@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" - integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - "@babel/traverse" "^7.25.9" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" - integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/template" "^7.25.9" - -"@babel/plugin-transform-destructuring@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" - integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-dotall-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" - integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-duplicate-keys@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" - integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" - integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-dynamic-import@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" - integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-exponentiation-operator@^7.26.3": - version "7.26.3" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" - integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-export-namespace-from@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" - integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-for-of@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz#4bdc7d42a213397905d89f02350c5267866d5755" - integrity sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-function-name@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" - integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== - dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-transform-json-strings@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" - integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" - integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-logical-assignment-operators@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" - integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-member-expression-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" - integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-amd@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" - integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3": - version "7.26.3" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" - integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== - dependencies: - "@babel/helper-module-transforms" "^7.26.0" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-modules-systemjs@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" - integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/plugin-transform-modules-umd@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" - integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== - dependencies: - "@babel/helper-module-transforms" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" - integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-new-target@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" - integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": - version "7.26.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" - integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-numeric-separator@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" - integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-object-rest-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" - integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== - dependencies: - "@babel/helper-compilation-targets" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" - -"@babel/plugin-transform-object-super@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" - integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-replace-supers" "^7.25.9" - -"@babel/plugin-transform-optional-catch-binding@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" - integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-optional-chaining@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" - integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-parameters@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" - integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-methods@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" - integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-private-property-in-object@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" - integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-property-literals@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" - integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-regenerator@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" - integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - regenerator-transform "^0.15.2" - -"@babel/plugin-transform-regexp-modifiers@^7.26.0": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" - integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-reserved-words@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" - integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-shorthand-properties@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" - integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-spread@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" - integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - -"@babel/plugin-transform-sticky-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" - integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-template-literals@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" - integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-typeof-symbol@^7.26.7": - version "7.26.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz#d0e33acd9223744c1e857dbd6fa17bd0a3786937" - integrity sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw== - dependencies: - "@babel/helper-plugin-utils" "^7.26.5" - -"@babel/plugin-transform-typescript@^7.25.9": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" - integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.25.9" - "@babel/helper-create-class-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" - "@babel/plugin-syntax-typescript" "^7.25.9" - -"@babel/plugin-transform-unicode-escapes@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" - integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-property-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" - integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" - integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/plugin-transform-unicode-sets-regex@^7.25.9": - version "7.25.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" - integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.25.9" - "@babel/helper-plugin-utils" "^7.25.9" - -"@babel/preset-env@^7.25.4": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.8.tgz#7af0090829b606d2046db99679004731e1dc364d" - integrity sha512-um7Sy+2THd697S4zJEfv/U5MHGJzkN2xhtsR3T/SWRbVSic62nbISh51VVfU9JiO/L/Z97QczHTaFVkOU8IzNg== - dependencies: - "@babel/compat-data" "^7.26.8" - "@babel/helper-compilation-targets" "^7.26.5" - "@babel/helper-plugin-utils" "^7.26.5" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.9" - "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.9" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.9" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.25.9" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.9" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-import-assertions" "^7.26.0" - "@babel/plugin-syntax-import-attributes" "^7.26.0" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.25.9" - "@babel/plugin-transform-async-generator-functions" "^7.26.8" - "@babel/plugin-transform-async-to-generator" "^7.25.9" - "@babel/plugin-transform-block-scoped-functions" "^7.26.5" - "@babel/plugin-transform-block-scoping" "^7.25.9" - "@babel/plugin-transform-class-properties" "^7.25.9" - "@babel/plugin-transform-class-static-block" "^7.26.0" - "@babel/plugin-transform-classes" "^7.25.9" - "@babel/plugin-transform-computed-properties" "^7.25.9" - "@babel/plugin-transform-destructuring" "^7.25.9" - "@babel/plugin-transform-dotall-regex" "^7.25.9" - "@babel/plugin-transform-duplicate-keys" "^7.25.9" - "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.9" - "@babel/plugin-transform-dynamic-import" "^7.25.9" - "@babel/plugin-transform-exponentiation-operator" "^7.26.3" - "@babel/plugin-transform-export-namespace-from" "^7.25.9" - "@babel/plugin-transform-for-of" "^7.25.9" - "@babel/plugin-transform-function-name" "^7.25.9" - "@babel/plugin-transform-json-strings" "^7.25.9" - "@babel/plugin-transform-literals" "^7.25.9" - "@babel/plugin-transform-logical-assignment-operators" "^7.25.9" - "@babel/plugin-transform-member-expression-literals" "^7.25.9" - "@babel/plugin-transform-modules-amd" "^7.25.9" - "@babel/plugin-transform-modules-commonjs" "^7.26.3" - "@babel/plugin-transform-modules-systemjs" "^7.25.9" - "@babel/plugin-transform-modules-umd" "^7.25.9" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.25.9" - "@babel/plugin-transform-new-target" "^7.25.9" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.26.6" - "@babel/plugin-transform-numeric-separator" "^7.25.9" - "@babel/plugin-transform-object-rest-spread" "^7.25.9" - "@babel/plugin-transform-object-super" "^7.25.9" - "@babel/plugin-transform-optional-catch-binding" "^7.25.9" - "@babel/plugin-transform-optional-chaining" "^7.25.9" - "@babel/plugin-transform-parameters" "^7.25.9" - "@babel/plugin-transform-private-methods" "^7.25.9" - "@babel/plugin-transform-private-property-in-object" "^7.25.9" - "@babel/plugin-transform-property-literals" "^7.25.9" - "@babel/plugin-transform-regenerator" "^7.25.9" - "@babel/plugin-transform-regexp-modifiers" "^7.26.0" - "@babel/plugin-transform-reserved-words" "^7.25.9" - "@babel/plugin-transform-shorthand-properties" "^7.25.9" - "@babel/plugin-transform-spread" "^7.25.9" - "@babel/plugin-transform-sticky-regex" "^7.25.9" - "@babel/plugin-transform-template-literals" "^7.26.8" - "@babel/plugin-transform-typeof-symbol" "^7.26.7" - "@babel/plugin-transform-unicode-escapes" "^7.25.9" - "@babel/plugin-transform-unicode-property-regex" "^7.25.9" - "@babel/plugin-transform-unicode-regex" "^7.25.9" - "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.11.0" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.40.0" - semver "^6.3.1" - -"@babel/preset-modules@0.1.6-no-external-plugins": - version "0.1.6-no-external-plugins" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" - integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-typescript@^7.24.7": - version "7.26.0" - resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" - integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== - dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/helper-validator-option" "^7.25.9" - "@babel/plugin-syntax-jsx" "^7.25.9" - "@babel/plugin-transform-modules-commonjs" "^7.25.9" - "@babel/plugin-transform-typescript" "^7.25.9" - -"@babel/runtime@7.26.10", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.26.10" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2" integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.25.9", "@babel/template@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz#db3898f47a17bab2f4c78ec1d0de38527c2ffe19" - integrity sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q== +"@babel/template@^7.26.9", "@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.26.8" - "@babel/types" "^7.26.8" + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" -"@babel/template@^7.26.9": - version "7.26.9" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" - integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== +"@babel/traverse@^7.18.9", "@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" + integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" - -"@babel/traverse@^7.18.9", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8": - version "7.26.8" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz#0a8a9c2b7cc9519eed14275f4fd2278ad46e8cc9" - integrity sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.8" - "@babel/parser" "^7.26.8" - "@babel/template" "^7.26.8" - "@babel/types" "^7.26.8" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.0" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.0" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.0" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.18.9", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.8", "@babel/types@^7.4.4": - version "7.26.8" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.8.tgz#97dcdc190fab45be7f3dc073e3c11160d677c127" - integrity sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA== +"@babel/types@^7.0.0", "@babel/types@^7.18.9", "@babel/types@^7.20.7", "@babel/types@^7.26.10", "@babel/types@^7.27.1", "@babel/types@^7.28.0": + version "7.28.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" + integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - -"@babel/types@^7.26.10", "@babel/types@^7.26.9": - version "7.26.10" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259" - integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" "@blueprintjs/colors@^4.2.1": version "4.2.1" - resolved "https://registry.npmjs.org/@blueprintjs/colors/-/colors-4.2.1.tgz#603b2512caee84feddcb3dbd536534c140b9a1f3" + resolved "https://registry.yarnpkg.com/@blueprintjs/colors/-/colors-4.2.1.tgz#603b2512caee84feddcb3dbd536534c140b9a1f3" integrity sha512-Cx7J2YnUuxn+fi+y5XtXnBB7+cFHN4xBrRkaAetp78i3VTCXjUk+d1omrOr8TqbRucUXTdrhbZOUHpzRLFcJpQ== dependencies: tslib "~2.5.0" "@blueprintjs/core@^4.16.3", "@blueprintjs/core@^4.20.2": version "4.20.2" - resolved "https://registry.npmjs.org/@blueprintjs/core/-/core-4.20.2.tgz#ae1bbaf13bd1bf887b506760c478cc940f6d6e20" + resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-4.20.2.tgz#ae1bbaf13bd1bf887b506760c478cc940f6d6e20" integrity sha512-5v4Nr0jozfAjiOkjY4zvt1XSpt4ldnrSaxtwo506S2cxJYfwFeMTmDshXNPFcc8L1fjZMxi0IWI2WABXzZXS6w== dependencies: "@blueprintjs/colors" "^4.2.1" @@ -932,7 +228,7 @@ "@blueprintjs/icons@^4.16.0": version "4.16.0" - resolved "https://registry.npmjs.org/@blueprintjs/icons/-/icons-4.16.0.tgz#47f9e8abe64d84fc18721080b8f191d8aac075d8" + resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-4.16.0.tgz#47f9e8abe64d84fc18721080b8f191d8aac075d8" integrity sha512-cyfgjUZcZCtQrXWUV8FwqYTFEzduV4a0N7yhOU38jY+cBRCLu/sDrD0Osvfk4DGRvNe4YjY7pohVLFSxpg68Uw== dependencies: change-case "^4.1.2" @@ -941,7 +237,7 @@ "@blueprintjs/popover2@^1.13.3": version "1.14.11" - resolved "https://registry.npmjs.org/@blueprintjs/popover2/-/popover2-1.14.11.tgz#0698fdeaf6710460cef0b71bed592ca37f40d1f9" + resolved "https://registry.yarnpkg.com/@blueprintjs/popover2/-/popover2-1.14.11.tgz#0698fdeaf6710460cef0b71bed592ca37f40d1f9" integrity sha512-5XAjeb2mlWjYXC0pqrNDLzHSsX85Zaiv8jixxUN9abarMUUFKGATgGF8MRsWTLAW94Gli6CB1lzVkrYkRHHf6Q== dependencies: "@blueprintjs/core" "^4.20.2" @@ -954,7 +250,7 @@ "@chromatic-com/storybook@^1.4.0": version "1.9.0" - resolved "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.9.0.tgz#d95eb3474783bcc17a830a7627c3f099c1f75ba5" + resolved "https://registry.yarnpkg.com/@chromatic-com/storybook/-/storybook-1.9.0.tgz#d95eb3474783bcc17a830a7627c3f099c1f75ba5" integrity sha512-vYQ+TcfktEE3GHnLZXHCzXF/sN9dw+KivH8a5cmPyd9YtQs7fZtHrEgsIjWpYycXiweKMo1Lm1RZsjxk8DH3rA== dependencies: chromatic "^11.4.0" @@ -965,47 +261,47 @@ "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" - resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@csstools/color-helpers@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz#829f1c76f5800b79c51c709e2f36821b728e0e10" - integrity sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA== +"@csstools/color-helpers@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.2.tgz#82592c9a7c2b83c293d9161894e2a6471feb97b8" + integrity sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA== -"@csstools/css-calc@^2.1.1": - version "2.1.1" - resolved "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz#a7dbc66627f5cf458d42aed14bda0d3860562383" - integrity sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag== +"@csstools/css-calc@^2.1.3", "@csstools/css-calc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.4.tgz#8473f63e2fcd6e459838dd412401d5948f224c65" + integrity sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ== -"@csstools/css-color-parser@^3.0.7": - version "3.0.7" - resolved "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz#442d61d58e54ad258d52c309a787fceb33906484" - integrity sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA== +"@csstools/css-color-parser@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz#79fc68864dd43c3b6782d2b3828bc0fa9d085c10" + integrity sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg== dependencies: - "@csstools/color-helpers" "^5.0.1" - "@csstools/css-calc" "^2.1.1" + "@csstools/color-helpers" "^5.0.2" + "@csstools/css-calc" "^2.1.4" "@csstools/css-parser-algorithms@^3.0.4": - version "3.0.4" - resolved "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz#74426e93bd1c4dcab3e441f5cc7ba4fb35d94356" - integrity sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A== + version "3.0.5" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076" + integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== "@csstools/css-tokenizer@^3.0.3": - version "3.0.3" - resolved "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz#a5502c8539265fecbd873c1e395a890339f119c2" - integrity sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" + integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== "@dabh/diagnostics@^2.0.2": version "2.0.3" - resolved "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== dependencies: colorspace "1.1.x" @@ -1017,9 +313,31 @@ resolved "https://registry.yarnpkg.com/@date-fns/tz/-/tz-1.2.0.tgz#81cb3211693830babaf3b96aff51607e143030a6" integrity sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg== +"@emnapi/core@^1.4.3": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.5.tgz#bfbb0cbbbb9f96ec4e2c4fd917b7bbe5495ceccb" + integrity sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q== + dependencies: + "@emnapi/wasi-threads" "1.0.4" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.5.tgz#c67710d0661070f38418b6474584f159de38aba9" + integrity sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz#703fc094d969e273b1b71c292523b2f792862bf4" + integrity sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g== + dependencies: + tslib "^2.4.0" + "@emotion/babel-plugin@^11.13.5": version "11.13.5" - resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz#eab8d65dbded74e0ecfd28dc218e75607c4e7bc0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz#eab8d65dbded74e0ecfd28dc218e75607c4e7bc0" integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== dependencies: "@babel/helper-module-imports" "^7.16.7" @@ -1036,7 +354,7 @@ "@emotion/cache@^11.13.5", "@emotion/cache@^11.14.0": version "11.14.0" - resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz#ee44b26986eeb93c8be82bb92f1f7a9b21b2ed76" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.14.0.tgz#ee44b26986eeb93c8be82bb92f1f7a9b21b2ed76" integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== dependencies: "@emotion/memoize" "^0.9.0" @@ -1047,24 +365,24 @@ "@emotion/hash@^0.9.2": version "0.9.2" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== "@emotion/is-prop-valid@^1.3.0": version "1.3.1" - resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240" integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw== dependencies: "@emotion/memoize" "^0.9.0" "@emotion/memoize@^0.9.0": version "0.9.0" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== "@emotion/react@^11.11.1": version "11.14.0" - resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz#cfaae35ebc67dd9ef4ea2e9acc6cd29e157dd05d" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.14.0.tgz#cfaae35ebc67dd9ef4ea2e9acc6cd29e157dd05d" integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== dependencies: "@babel/runtime" "^7.18.3" @@ -1078,7 +396,7 @@ "@emotion/serialize@^1.3.3": version "1.3.3" - resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8" integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== dependencies: "@emotion/hash" "^0.9.2" @@ -1089,13 +407,13 @@ "@emotion/sheet@^1.4.0": version "1.4.0" - resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== "@emotion/styled@^11.11.0": - version "11.14.0" - resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz#f47ca7219b1a295186d7661583376fcea95f0ff3" - integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA== + version "11.14.1" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.14.1.tgz#8c34bed2948e83e1980370305614c20955aacd1c" + integrity sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw== dependencies: "@babel/runtime" "^7.18.3" "@emotion/babel-plugin" "^11.13.5" @@ -1106,22 +424,22 @@ "@emotion/unitless@^0.10.0": version "0.10.0" - resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== "@emotion/use-insertion-effect-with-fallbacks@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz#8a8cb77b590e09affb960f4ff1e9a89e532738bf" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz#8a8cb77b590e09affb960f4ff1e9a89e532738bf" integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg== "@emotion/utils@^1.4.2": version "1.4.2" - resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52" integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== "@emotion/weak-memoize@^0.4.0": version "0.4.0" - resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== "@esbuild/aix-ppc64@0.25.0": @@ -1249,21 +567,21 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ== -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.1" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" - integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== dependencies: eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": version "4.12.1" - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/eslintrc@^2.1.4": version "2.1.4" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" @@ -1278,121 +596,121 @@ "@eslint/js@8.57.1": version "8.57.1" - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== -"@floating-ui/core@^1.6.0": - version "1.6.9" - resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" - integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== +"@floating-ui/core@^1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.2.tgz#3d1c35263950b314b6d5a72c8bfb9e3c1551aefd" + integrity sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw== dependencies: - "@floating-ui/utils" "^0.2.9" + "@floating-ui/utils" "^0.2.10" -"@floating-ui/dom@^1.0.0": - version "1.6.13" - resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" - integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== +"@floating-ui/dom@^1.7.1", "@floating-ui/dom@^1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.2.tgz#3540b051cf5ce0d4f4db5fb2507a76e8ea5b4a45" + integrity sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA== dependencies: - "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.9" + "@floating-ui/core" "^1.7.2" + "@floating-ui/utils" "^0.2.10" "@floating-ui/react-dom@^2.1.2": - version "2.1.2" - resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" - integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + version "2.1.4" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.4.tgz#a0689be8978352fff2be2dfdd718cf668c488ec3" + integrity sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw== dependencies: - "@floating-ui/dom" "^1.0.0" + "@floating-ui/dom" "^1.7.2" "@floating-ui/react@^0.26.4": version "0.26.28" - resolved "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== dependencies: "@floating-ui/react-dom" "^2.1.2" "@floating-ui/utils" "^0.2.8" tabbable "^6.0.0" -"@floating-ui/utils@^0.2.8", "@floating-ui/utils@^0.2.9": - version "0.2.9" - resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" - integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== +"@floating-ui/utils@^0.2.10", "@floating-ui/utils@^0.2.8": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" + integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== -"@formatjs/ecma402-abstract@2.3.3": - version "2.3.3" - resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.3.tgz#fbc7555c9e4fdd104cd5e23129fa3735be3ad0ba" - integrity sha512-pJT1OkhplSmvvr6i3CWTPvC/FGC06MbN5TNBfRO6Ox62AEz90eMq+dVvtX9Bl3jxCEkS0tATzDarRZuOLw7oFg== +"@formatjs/ecma402-abstract@2.3.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz#e90c5a846ba2b33d92bc400fdd709da588280fbc" + integrity sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA== dependencies: - "@formatjs/fast-memoize" "2.2.6" - "@formatjs/intl-localematcher" "0.6.0" - decimal.js "10" - tslib "2" + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/intl-localematcher" "0.6.1" + decimal.js "^10.4.3" + tslib "^2.8.0" -"@formatjs/fast-memoize@2.2.6": - version "2.2.6" - resolved "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz#fac0a84207a1396be1f1aa4ee2805b179e9343d1" - integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw== +"@formatjs/fast-memoize@2.2.7": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz#707f9ddaeb522a32f6715bb7950b0831f4cc7b15" + integrity sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ== dependencies: - tslib "2" + tslib "^2.8.0" -"@formatjs/icu-messageformat-parser@2.11.1": - version "2.11.1" - resolved "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.1.tgz#59d69124b9cf3186800a576c0228947d10594347" - integrity sha512-o0AhSNaOfKoic0Sn1GkFCK4MxdRsw7mPJ5/rBpIqdvcC7MIuyUSW8WChUEvrK78HhNpYOgqCQbINxCTumJLzZA== +"@formatjs/icu-messageformat-parser@2.11.2": + version "2.11.2" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz#85aea211bea40aa81ee1d44ac7accc3cf5500a73" + integrity sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA== dependencies: - "@formatjs/ecma402-abstract" "2.3.3" - "@formatjs/icu-skeleton-parser" "1.8.13" - tslib "2" + "@formatjs/ecma402-abstract" "2.3.4" + "@formatjs/icu-skeleton-parser" "1.8.14" + tslib "^2.8.0" -"@formatjs/icu-skeleton-parser@1.8.13": - version "1.8.13" - resolved "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.13.tgz#5e8b1e1bb467c937735fecb4cb4b345932151a44" - integrity sha512-N/LIdTvVc1TpJmMt2jVg0Fr1F7Q1qJPdZSCs19unMskCmVQ/sa0H9L8PWt13vq+gLdLg1+pPsvBLydL1Apahjg== +"@formatjs/icu-skeleton-parser@1.8.14": + version "1.8.14" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz#b9581d00363908efb29817fdffc32b79f41dabe5" + integrity sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ== dependencies: - "@formatjs/ecma402-abstract" "2.3.3" - tslib "2" + "@formatjs/ecma402-abstract" "2.3.4" + tslib "^2.8.0" -"@formatjs/intl-localematcher@0.6.0": - version "0.6.0" - resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.0.tgz#33cf0d33279572c990e02ab75a93122569878082" - integrity sha512-4rB4g+3hESy1bHSBG3tDFaMY2CH67iT7yne1e+0CLTsGLDcmoEWWpJjjpWVaYgYfYuohIRuo0E+N536gd2ZHZA== +"@formatjs/intl-localematcher@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz#25dc30675320bf65a9d7f73876fc1e4064c0e299" + integrity sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg== dependencies: - tslib "2" + tslib "^2.8.0" "@headlessui/react@^1.7.13", "@headlessui/react@^1.7.19", "@headlessui/react@^1.7.3": version "1.7.19" - resolved "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40" integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw== dependencies: "@tanstack/react-virtual" "^3.0.0-beta.60" client-only "^0.0.1" -"@hocuspocus/common@^2.15.2": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/common/-/common-2.15.2.tgz#dec1869f41716bd80a454e4cefb789fcbad543a0" - integrity sha512-wU1wxXNnQQMXyeL3mdSDYiQsm/r/QyJVjjQhF7sUBrLnjdsN7bA1cvfcSvJBr1ymrMSeYRmUL3UlQmEHEOaP7w== +"@hocuspocus/common@^2.15.3": + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/common/-/common-2.15.3.tgz#c5e6a326141b2ceaf49d555fd35917211340ceee" + integrity sha512-Rzh1HF0a2o/tf90A3w2XNdXd9Ym3aQzMDfD3lAUONCX9B9QOdqdyiORrj6M25QEaJrEIbXFy8LtAFcL0wRdWzA== dependencies: lib0 "^0.2.87" "@hocuspocus/extension-database@^2.15.0": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/extension-database/-/extension-database-2.15.2.tgz#d17be8061525c308038f973bc9878732a3423fb7" - integrity sha512-BkYDfKA99udx7AEkqWReBS61kvGMC9SqoPJs3v8xNgpaj2GGyMJQlUdQRMhPyZTn2osV+pqhk8Hn7xUJCW1RJg== + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/extension-database/-/extension-database-2.15.3.tgz#6cb606248d2161e01c391b910392274f738b6e34" + integrity sha512-+PVlPwfdVyOase68WEBb105ZwglhCLVeGpyNa3uwnmH+Ers7OKGLma2SDMKn3Vcb5oHzTzEGx7jNt+32KTEKXA== dependencies: - "@hocuspocus/server" "^2.15.2" + "@hocuspocus/server" "^2.15.3" "@hocuspocus/extension-logger@^2.15.0": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/extension-logger/-/extension-logger-2.15.2.tgz#f13fe713311d832dabefc03dc412657c184232da" - integrity sha512-nqSnSFI+xO7dBTsgzSANKvx09ptq8J4Doz3AdLgxfaweYC85qFao7mAx1ZCtWoVHseVwBYua6S3dTwQq5IsWEg== + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/extension-logger/-/extension-logger-2.15.3.tgz#13ea3f9d6eb68b1a41c628c93dc272e4ae80338f" + integrity sha512-NufsjXldlVX1c2B98Hyg8Vq9GblPmnIvw9QGdsBK6SNEgWzDwfVrjljrigMAVGuQ4pbBVz8TaY5DcsmOCi5jqA== dependencies: - "@hocuspocus/server" "^2.15.2" + "@hocuspocus/server" "^2.15.3" "@hocuspocus/extension-redis@^2.15.0": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/extension-redis/-/extension-redis-2.15.2.tgz#0982f65d7588235d039b80313e77103dc605285c" - integrity sha512-2BNBLnDEQq2v3uQSidBSdUOIbHhH383SGxn+hmy6tDQfrt2hLE4MwilgDdcCO0FKOCYaJrV7HyKu6/WyzLbAOg== + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/extension-redis/-/extension-redis-2.15.3.tgz#87ee7526da94914d9c776099855546156b7fa816" + integrity sha512-gKeiiuQcAoRYb+QK9vyIczRrjNy8NW6ky+oyVv7raMcaizfFxeWP3TaAHPyC2pjGKfXsqN2m3YM0GbBGZfMiCg== dependencies: - "@hocuspocus/server" "^2.15.2" + "@hocuspocus/server" "^2.15.3" ioredis "^4.28.2" kleur "^4.1.4" lodash.debounce "^4.0.8" @@ -1400,21 +718,21 @@ uuid "^11.0.3" "@hocuspocus/provider@^2.15.0": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/provider/-/provider-2.15.2.tgz#ce534b90e161cd32fd02928d7296bb38f424c319" - integrity sha512-mdBurviyaUd7bQx4vMIE39WqRJDTpfFelHOVXr7w/jA8G1E7K7lxQ9/DacSrbg+9o8s+1z1+SerZiUjaToaBJg== + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/provider/-/provider-2.15.3.tgz#d3a7ec469c5b0d9d079430710e9869bb09fedec5" + integrity sha512-oadN05m+KL4ylNKVo5YspNG4MXkT2Y+FUFzrgigpQeTjQibkPUwCNmUnkUxMgrGRgxb+O0lJCfirFIJMxedctA== dependencies: - "@hocuspocus/common" "^2.15.2" + "@hocuspocus/common" "^2.15.3" "@lifeomic/attempt" "^3.0.2" lib0 "^0.2.87" ws "^8.17.1" -"@hocuspocus/server@^2.15.0", "@hocuspocus/server@^2.15.2": - version "2.15.2" - resolved "https://registry.npmjs.org/@hocuspocus/server/-/server-2.15.2.tgz#77be1e2540843bec313141dad7f39ea65a4221dd" - integrity sha512-+fLRVswg+bkgfHqJ+wFgywivw3H08WMOtVvJF7dJzWT2ZR/Sc3nDMFh2KqMF6Ygh4z6mt23xr7SKIm3eP1zoLA== +"@hocuspocus/server@^2.15.0", "@hocuspocus/server@^2.15.3": + version "2.15.3" + resolved "https://registry.yarnpkg.com/@hocuspocus/server/-/server-2.15.3.tgz#96beed4786b2733ccbe5d29c2b70f5f94dd35069" + integrity sha512-Ju4ty4/7JtmvivcP7gKReOLf8KrFwN7Yx/5VhXYh4TRULy4kSo2fsDVUaluPp0neZa6PbVhizJuzlOim73IEbQ== dependencies: - "@hocuspocus/common" "^2.15.2" + "@hocuspocus/common" "^2.15.3" async-lock "^1.3.1" kleur "^4.1.4" lib0 "^0.2.47" @@ -1423,7 +741,7 @@ "@humanwhocodes/config-array@^0.13.0": version "0.13.0" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== dependencies: "@humanwhocodes/object-schema" "^2.0.3" @@ -1432,17 +750,17 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^2.0.3": version "2.0.3" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@hypnosphi/create-react-context@^0.3.1": version "0.3.1" - resolved "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz#f8bfebdc7665f5d426cba3753e0e9c7d3154d7c6" + resolved "https://registry.yarnpkg.com/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz#f8bfebdc7665f5d426cba3753e0e9c7d3154d7c6" integrity sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A== dependencies: gud "^1.0.0" @@ -1450,22 +768,22 @@ "@icons/material@^0.2.4": version "0.2.4" - resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" + resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== "@intercom/messenger-js-sdk@^0.0.12": version "0.0.12" - resolved "https://registry.npmjs.org/@intercom/messenger-js-sdk/-/messenger-js-sdk-0.0.12.tgz#1b80acf6b2a59ef9ce4010e0920522d579a590fa" + resolved "https://registry.yarnpkg.com/@intercom/messenger-js-sdk/-/messenger-js-sdk-0.0.12.tgz#1b80acf6b2a59ef9ce4010e0920522d579a590fa" integrity sha512-xoUGlKLD8nIcZaH7AesR/LfwXH4QQUdPZMV4sApK/zvVFBgAY/A9IWp1ey/jUcp+776ejtZeEqreJZxG4LdEuw== -"@ioredis/commands@^1.1.1": +"@ioredis/commands@^1.0.2", "@ioredis/commands@^1.1.1": version "1.2.0" - resolved "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== "@isaacs/cliui@^8.0.2": version "8.0.2" - resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== dependencies: string-width "^5.1.2" @@ -1475,86 +793,80 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.12" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz#2234ce26c62889f03db3d7fea43c1932ab3e927b" + integrity sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg== dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/sourcemap-codec" "^1.5.0" "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - "@jridgewell/source-map@^0.3.3": - version "0.3.6" - resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" - integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + version "0.3.10" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.10.tgz#a35714446a2e84503ff9bfe66f1d1d4846f2075b" + integrity sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q== dependencies: "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.0" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7" + integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz#a58d31eaadaf92c6695680b2e1d464a9b8fbf7fc" + integrity sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" "@juggle/resize-observer@^3.4.0": version "3.4.0" - resolved "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" + resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== "@lifeomic/attempt@^3.0.2": version "3.1.0" - resolved "https://registry.npmjs.org/@lifeomic/attempt/-/attempt-3.1.0.tgz#7fc703559177b81a008b9d263e3d9a001d11d08a" + resolved "https://registry.yarnpkg.com/@lifeomic/attempt/-/attempt-3.1.0.tgz#7fc703559177b81a008b9d263e3d9a001d11d08a" integrity sha512-QZqem4QuAnAyzfz+Gj5/+SLxqwCAw2qmt7732ZXodr6VDWGeYLG6w1i/vYLa55JQM9wRuBKLmXmiZ2P0LtE5rw== "@mdx-js/react@^3.0.0": version "3.1.0" - resolved "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz#c4522e335b3897b9a845db1dbdd2f966ae8fb0ed" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.0.tgz#c4522e335b3897b9a845db1dbdd2f966ae8fb0ed" integrity sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ== dependencies: "@types/mdx" "^2.0.0" -"@mui/core-downloads-tracker@^5.16.14": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.14.tgz#e6536f1b6caa873f7915fbf9703fdc840a5a98d9" - integrity sha512-sbjXW+BBSvmzn61XyTMun899E7nGPTXwqD9drm1jBUAvWEhJpPFIRxwQQiATWZnd9rvdxtnhhdsDxEGWI0jxqA== +"@mui/core-downloads-tracker@^5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.18.0.tgz#85019a8704b0f63305fc5600635ee663810f2b66" + integrity sha512-jbhwoQ1AY200PSSOrNXmrFCaSDSJWP7qk6urkTmIirvRXDROkqe+QwcLlUiw/PrREwsIF/vm3/dAXvjlMHF0RA== "@mui/material@^5.14.1": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/material/-/material-5.16.14.tgz#da8a75822f039d8c1b0ab7fb4146d767c2f9248a" - integrity sha512-eSXQVCMKU2xc7EcTxe/X/rC9QsV2jUe8eLM3MUCPYbo6V52eCE436akRIvELq/AqZpxx2bwkq7HC0cRhLB+yaw== + version "5.18.0" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.18.0.tgz#71e72d52338252edc6f8d9461e04fdf0d61905cd" + integrity sha512-bbH/HaJZpFtXGvWg3TsBWG4eyt3gah3E7nCNU8GLyRjVoWcA91Vm/T+sjHfUcwgJSw9iLtucfHBoq+qW/T30aA== dependencies: "@babel/runtime" "^7.23.9" - "@mui/core-downloads-tracker" "^5.16.14" - "@mui/system" "^5.16.14" - "@mui/types" "^7.2.15" - "@mui/utils" "^5.16.14" + "@mui/core-downloads-tracker" "^5.18.0" + "@mui/system" "^5.18.0" + "@mui/types" "~7.2.15" + "@mui/utils" "^5.17.1" "@popperjs/core" "^2.11.8" "@types/react-transition-group" "^4.4.10" clsx "^2.1.0" @@ -1563,65 +875,75 @@ react-is "^19.0.0" react-transition-group "^4.4.5" -"@mui/private-theming@^5.16.14": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.14.tgz#7ad2b8a8fe0417f9fdfd05011806b9cb33c1a20a" - integrity sha512-12t7NKzvYi819IO5IapW2BcR33wP/KAVrU8d7gLhGHoAmhDxyXlRoKiRij3TOD8+uzk0B6R9wHUNKi4baJcRNg== +"@mui/private-theming@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.17.1.tgz#b4b6fbece27830754ef78186e3f1307dca42f295" + integrity sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ== dependencies: "@babel/runtime" "^7.23.9" - "@mui/utils" "^5.16.14" + "@mui/utils" "^5.17.1" prop-types "^15.8.1" -"@mui/styled-engine@^5.16.14": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.14.tgz#f90fef5b4f8ebf11d48e1b1df8854a45bb31a9f5" - integrity sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw== +"@mui/styled-engine@^5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.18.0.tgz#914cca1385bb33ce0cde31721f529c8bd7fa301c" + integrity sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg== dependencies: "@babel/runtime" "^7.23.9" "@emotion/cache" "^11.13.5" + "@emotion/serialize" "^1.3.3" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^5.16.14": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/system/-/system-5.16.14.tgz#92765ba01a3d1f8ee4967248cb00077d7aed225b" - integrity sha512-KBxMwCb8mSIABnKvoGbvM33XHyT+sN0BzEBG+rsSc0lLQGzs7127KWkCA6/H8h6LZ00XpBEME5MAj8mZLiQ1tw== +"@mui/system@^5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.18.0.tgz#e55331203a40584b26c5a855a07949ac8973bfb6" + integrity sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw== dependencies: "@babel/runtime" "^7.23.9" - "@mui/private-theming" "^5.16.14" - "@mui/styled-engine" "^5.16.14" - "@mui/types" "^7.2.15" - "@mui/utils" "^5.16.14" + "@mui/private-theming" "^5.17.1" + "@mui/styled-engine" "^5.18.0" + "@mui/types" "~7.2.15" + "@mui/utils" "^5.17.1" clsx "^2.1.0" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/types@^7.2.15": - version "7.2.21" - resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz#63f50874eda8e4a021a69aaa8ba9597369befda2" - integrity sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww== +"@mui/types@~7.2.15": + version "7.2.24" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.24.tgz#5eff63129d9c29d80bbf2d2e561bd0690314dec2" + integrity sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw== -"@mui/utils@^5.16.14": - version "5.16.14" - resolved "https://registry.npmjs.org/@mui/utils/-/utils-5.16.14.tgz#7217e876a5092cd04c184b34bca348e0befaef8c" - integrity sha512-wn1QZkRzSmeXD1IguBVvJJHV3s6rxJrfb6YuC9Kk6Noh9f8Fb54nUs5JRkKm+BOerRhj5fLg05Dhx/H3Ofb8Mg== +"@mui/utils@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.17.1.tgz#72ba4ffa79f7bdf69d67458139390f18484b6e6b" + integrity sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg== dependencies: "@babel/runtime" "^7.23.9" - "@mui/types" "^7.2.15" + "@mui/types" "~7.2.15" "@types/prop-types" "^15.7.12" clsx "^2.1.1" prop-types "^15.8.1" react-is "^19.0.0" +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + "@next/env@14.2.30": version "14.2.30" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.30.tgz#f955b57975751584722b6b0a2a8cf2bdcc4ffae3" integrity sha512-KBiBKrDY6kxTQWGzKjQB7QirL3PiiOkV7KW98leHFjtVRKtft76Ra5qSA/SL75xT44dp6hOcqiiJ6iievLOYug== -"@next/eslint-plugin-next@14.2.24": - version "14.2.24" - resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.24.tgz#2bd0857c31d510610386ecb7a4cc9c2ca452a4ee" - integrity sha512-FDL3qs+5DML0AJz56DCVr+KnFYivxeAX73En8QbPw9GjJZ6zbfvqDy+HrarHFzbsIASn7y8y5ySJ/lllSruNVQ== +"@next/eslint-plugin-next@14.2.30": + version "14.2.30" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.30.tgz#852651bc31a7a01d84a54d95903f48cde6c8bc01" + integrity sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA== dependencies: glob "10.3.10" @@ -1670,14 +992,9 @@ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.30.tgz#94d3ddcc1e97572a0514a6180c8e3bb415e1dc98" integrity sha512-4KCo8hMZXMjpTzs3HOqOGYYwAXymXIy7PEPAXNEcEOyKqkjiDlECumrWziy+JEF0Oi4ILHGxzgQ3YiMGG2t/Lg== -"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": - version "2.1.8-no-fsevents.3" - resolved "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" - integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -1685,12 +1002,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -1698,175 +1015,188 @@ "@nolyfill/is-core-module@1.0.39": version "1.0.39" - resolved "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== "@pkgjs/parseargs@^0.11.0": version "0.11.0" - resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@popperjs/core@^2.11.7", "@popperjs/core@^2.11.8", "@popperjs/core@^2.9.0": version "2.11.8" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== -"@radix-ui/number@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" - integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== - -"@radix-ui/primitive@1.1.1": +"@radix-ui/number@1.1.1": version "1.1.1" - resolved "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" - integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.1.tgz#7b2c9225fbf1b126539551f5985769d0048d9090" + integrity sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g== -"@radix-ui/react-compose-refs@1.1.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" - integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== +"@radix-ui/primitive@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.2.tgz#83f415c4425f21e3d27914c12b3272a32e3dae65" + integrity sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA== -"@radix-ui/react-context@1.1.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" - integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== +"@radix-ui/react-compose-refs@1.1.2", "@radix-ui/react-compose-refs@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz#a2c4c47af6337048ee78ff6dc0d090b390d2bb30" + integrity sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg== -"@radix-ui/react-dialog@^1.1.2": - version "1.1.6" - resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz#65b4465e99ad900f28a98eed9a94bb21ec644bf7" - integrity sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw== +"@radix-ui/react-context@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36" + integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA== + +"@radix-ui/react-dialog@^1.1.6": + version "1.1.14" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz#4c69c80c258bc6561398cfce055202ea11075107" + integrity sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw== dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.5" - "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-focus-scope" "1.1.2" - "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-portal" "1.1.4" - "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-slot" "1.1.2" - "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/primitive" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-context" "1.1.2" + "@radix-ui/react-dismissable-layer" "1.1.10" + "@radix-ui/react-focus-guards" "1.1.2" + "@radix-ui/react-focus-scope" "1.1.7" + "@radix-ui/react-id" "1.1.1" + "@radix-ui/react-portal" "1.1.9" + "@radix-ui/react-presence" "1.1.4" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-slot" "1.2.3" + "@radix-ui/react-use-controllable-state" "1.2.2" aria-hidden "^1.2.4" react-remove-scroll "^2.6.3" -"@radix-ui/react-direction@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" - integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== - -"@radix-ui/react-dismissable-layer@1.1.5": - version "1.1.5" - resolved "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" - integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-escape-keydown" "1.1.0" - -"@radix-ui/react-focus-guards@1.1.1": +"@radix-ui/react-direction@1.1.1": version "1.1.1" - resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" - integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14" + integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw== -"@radix-ui/react-focus-scope@1.1.2": +"@radix-ui/react-dismissable-layer@1.1.10": + version "1.1.10" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz#429b9bada3672c6895a5d6a642aca6ecaf4f18c3" + integrity sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ== + dependencies: + "@radix-ui/primitive" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-callback-ref" "1.1.1" + "@radix-ui/react-use-escape-keydown" "1.1.1" + +"@radix-ui/react-focus-guards@1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" - integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== - dependencies: - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-use-callback-ref" "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz#4ec9a7e50925f7fb661394460045b46212a33bed" + integrity sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA== -"@radix-ui/react-id@1.1.0", "@radix-ui/react-id@^1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" - integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== +"@radix-ui/react-focus-scope@1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz#dfe76fc103537d80bf42723a183773fd07bfb58d" + integrity sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw== dependencies: - "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-callback-ref" "1.1.1" -"@radix-ui/react-portal@1.1.4": +"@radix-ui/react-id@1.1.1", "@radix-ui/react-id@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7" + integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-portal@1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.9.tgz#14c3649fe48ec474ac51ed9f2b9f5da4d91c4472" + integrity sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ== + dependencies: + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-presence@1.1.4": version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" - integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA== + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.4.tgz#253ac0ad4946c5b4a9c66878335f5cf07c967ced" + integrity sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA== dependencies: - "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-use-layout-effect" "1.1.1" -"@radix-ui/react-presence@1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" - integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== +"@radix-ui/react-primitive@2.1.3", "@radix-ui/react-primitive@^2.0.2": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz#db9b8bcff49e01be510ad79893fb0e4cda50f1bc" + integrity sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ== dependencies: - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-layout-effect" "1.1.0" - -"@radix-ui/react-primitive@2.0.2", "@radix-ui/react-primitive@^2.0.0": - version "2.0.2" - resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef" - integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w== - dependencies: - "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-slot" "1.2.3" "@radix-ui/react-scroll-area@^1.2.3": + version "1.2.9" + resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz#90c49bd3231d7f0796d5d12dabc065afa829cf07" + integrity sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A== + dependencies: + "@radix-ui/number" "1.1.1" + "@radix-ui/primitive" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-context" "1.1.2" + "@radix-ui/react-direction" "1.1.1" + "@radix-ui/react-presence" "1.1.4" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-callback-ref" "1.1.1" + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-slot@1.2.3", "@radix-ui/react-slot@^1.1.1": version "1.2.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.3.tgz#6a9a7897add739ce84b517796ee345d495893d3f" - integrity sha512-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ== + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.3.tgz#502d6e354fc847d4169c3bc5f189de777f68cfe1" + integrity sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A== dependencies: - "@radix-ui/number" "1.1.0" - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-direction" "1.1.0" - "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-primitive" "2.0.2" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.2" -"@radix-ui/react-slot@1.1.2", "@radix-ui/react-slot@^1.1.1": - version "1.1.2" - resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" - integrity sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ== +"@radix-ui/react-use-callback-ref@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz#62a4dba8b3255fdc5cc7787faeac1c6e4cc58d40" + integrity sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg== + +"@radix-ui/react-use-controllable-state@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz#905793405de57d61a439f4afebbb17d0645f3190" + integrity sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg== dependencies: - "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-use-effect-event" "0.0.2" + "@radix-ui/react-use-layout-effect" "1.1.1" -"@radix-ui/react-use-callback-ref@1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" - integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== - -"@radix-ui/react-use-controllable-state@1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" - integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== +"@radix-ui/react-use-effect-event@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz#090cf30d00a4c7632a15548512e9152217593907" + integrity sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA== dependencies: - "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.1" -"@radix-ui/react-use-escape-keydown@1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" - integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== +"@radix-ui/react-use-escape-keydown@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz#b3fed9bbea366a118f40427ac40500aa1423cc29" + integrity sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g== dependencies: - "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.1" -"@radix-ui/react-use-layout-effect@1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" - integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== +"@radix-ui/react-use-layout-effect@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz#0c4230a9eed49d4589c967e2d9c0d9d60a23971e" + integrity sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ== "@react-pdf/fns@2.2.1": version "2.2.1" - resolved "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.2.1.tgz#04fe664a6f70214569c9c27e249e3395836f37d5" + resolved "https://registry.yarnpkg.com/@react-pdf/fns/-/fns-2.2.1.tgz#04fe664a6f70214569c9c27e249e3395836f37d5" integrity sha512-s78aDg0vDYaijU5lLOCsUD+qinQbfOvcNeaoX9AiE7+kZzzCo6B/nX+l48cmt9OosJmvZvE9DWR9cLhrhOi2pA== dependencies: "@babel/runtime" "^7.20.13" +"@react-pdf/fns@3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-pdf/fns/-/fns-3.1.2.tgz#9ce7351d9fdf1cdb6e9c6ffd6801bc65f29f991c" + integrity sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g== + "@react-pdf/font@^2.5.2": version "2.5.2" - resolved "https://registry.npmjs.org/@react-pdf/font/-/font-2.5.2.tgz#4a2fcaac3b55470a2727387ec28937b54cba0d77" + resolved "https://registry.yarnpkg.com/@react-pdf/font/-/font-2.5.2.tgz#4a2fcaac3b55470a2727387ec28937b54cba0d77" integrity sha512-Ud0EfZ2FwrbvwAWx8nz+KKLmiqACCH9a/N/xNDOja0e/YgSnqTpuyHegFBgIMKjuBtO5dNvkb4dXkxAhGe/ayw== dependencies: "@babel/runtime" "^7.20.13" @@ -1875,9 +1205,19 @@ fontkit "^2.0.2" is-url "^1.2.4" +"@react-pdf/font@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@react-pdf/font/-/font-4.0.2.tgz#58ede51937bb57025dcf221b107e248d0ea9d60b" + integrity sha512-/dAWu7Y2RD1RxarDZ9SkYPHgBYOhmcDnet4W/qN/m8k+A2Hr3ja54GymSR7GGxWBtxjKtNauVKrTa9LS1n8WUw== + dependencies: + "@react-pdf/pdfkit" "^4.0.3" + "@react-pdf/types" "^2.9.0" + fontkit "^2.0.2" + is-url "^1.2.4" + "@react-pdf/image@^2.3.6": version "2.3.6" - resolved "https://registry.npmjs.org/@react-pdf/image/-/image-2.3.6.tgz#72444842517f8b0c08bbf4c216d8b41110498d16" + resolved "https://registry.yarnpkg.com/@react-pdf/image/-/image-2.3.6.tgz#72444842517f8b0c08bbf4c216d8b41110498d16" integrity sha512-7iZDYZrZlJqNzS6huNl2XdMcLFUo68e6mOdzQeJ63d5eApdthhSHBnkGzHfLhH5t8DCpZNtClmklzuLL63ADfw== dependencies: "@babel/runtime" "^7.20.13" @@ -1887,7 +1227,7 @@ "@react-pdf/layout@^3.13.0": version "3.13.0" - resolved "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.13.0.tgz#2ef1423f32e891b5ec24f2d9d5c2daad4da01c66" + resolved "https://registry.yarnpkg.com/@react-pdf/layout/-/layout-3.13.0.tgz#2ef1423f32e891b5ec24f2d9d5c2daad4da01c66" integrity sha512-lpPj/EJYHFOc0ALiJwLP09H28B4ADyvTjxOf67xTF+qkWd+dq1vg7dw3wnYESPnWk5T9NN+HlUenJqdYEY9AvA== dependencies: "@babel/runtime" "^7.20.13" @@ -1905,7 +1245,7 @@ "@react-pdf/pdfkit@^3.2.0": version "3.2.0" - resolved "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.2.0.tgz#d4a088b8cc61c35512dc885e67ff2c6058518bea" + resolved "https://registry.yarnpkg.com/@react-pdf/pdfkit/-/pdfkit-3.2.0.tgz#d4a088b8cc61c35512dc885e67ff2c6058518bea" integrity sha512-OBfCcnTC6RpD9uv9L2woF60Zj1uQxhLFzTBXTdcYE9URzPE/zqXIyzpXEA4Vf3TFbvBCgFE2RzJ2ZUS0asq7yA== dependencies: "@babel/runtime" "^7.20.13" @@ -1916,21 +1256,47 @@ jay-peg "^1.0.2" vite-compatible-readable-stream "^3.6.1" +"@react-pdf/pdfkit@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@react-pdf/pdfkit/-/pdfkit-4.0.3.tgz#8b8a0e7e2aadbbada738a1c164f06ffff2947c8b" + integrity sha512-k+Lsuq8vTwWsCqTp+CCB4+2N+sOTFrzwGA7aw3H9ix/PDWR9QksbmNg0YkzGbLAPI6CeawmiLHcf4trZ5ecLPQ== + dependencies: + "@babel/runtime" "^7.20.13" + "@react-pdf/png-js" "^3.0.0" + browserify-zlib "^0.2.0" + crypto-js "^4.2.0" + fontkit "^2.0.2" + jay-peg "^1.1.1" + linebreak "^1.1.0" + vite-compatible-readable-stream "^3.6.1" + "@react-pdf/png-js@^2.3.1": version "2.3.1" - resolved "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.3.1.tgz#5381d5443ac1134e98fc446fa1debb45950665bc" + resolved "https://registry.yarnpkg.com/@react-pdf/png-js/-/png-js-2.3.1.tgz#5381d5443ac1134e98fc446fa1debb45950665bc" integrity sha512-pEZ18I4t1vAUS4lmhvXPmXYP4PHeblpWP/pAlMMRkEyP7tdAeHUN7taQl9sf9OPq7YITMY3lWpYpJU6t4CZgZg== dependencies: browserify-zlib "^0.2.0" +"@react-pdf/png-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@react-pdf/png-js/-/png-js-3.0.0.tgz#c0b7dc7c77e36f0830e9b7bccca7ddd64ada1c5e" + integrity sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA== + dependencies: + browserify-zlib "^0.2.0" + "@react-pdf/primitives@^3.1.1": version "3.1.1" - resolved "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.1.1.tgz#45a3253806fa61046f3821b8553bfee3cd848d14" + resolved "https://registry.yarnpkg.com/@react-pdf/primitives/-/primitives-3.1.1.tgz#45a3253806fa61046f3821b8553bfee3cd848d14" integrity sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w== +"@react-pdf/primitives@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@react-pdf/primitives/-/primitives-4.1.1.tgz#c7bfb7e83173661b6ec50ada4aba8dc9e94d0563" + integrity sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ== + "@react-pdf/render@^3.5.0": version "3.5.0" - resolved "https://registry.npmjs.org/@react-pdf/render/-/render-3.5.0.tgz#1be1f7ca280473680ce4f11e90b697e2c635ad16" + resolved "https://registry.yarnpkg.com/@react-pdf/render/-/render-3.5.0.tgz#1be1f7ca280473680ce4f11e90b697e2c635ad16" integrity sha512-gFOpnyqCgJ6l7VzfJz6rG1i2S7iVSD8bUHDjPW9Mze8TmyksHzN2zBH3y7NbsQOw1wU6hN4NhRmslrsn+BRDPA== dependencies: "@babel/runtime" "^7.20.13" @@ -1946,7 +1312,7 @@ "@react-pdf/renderer@^3.4.5": version "3.4.5" - resolved "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.4.5.tgz#e369149d12815b53934183353fcfcee2386fb862" + resolved "https://registry.yarnpkg.com/@react-pdf/renderer/-/renderer-3.4.5.tgz#e369149d12815b53934183353fcfcee2386fb862" integrity sha512-O1N8q45bTs7YuC+x9afJSKQWDYQy2RjoCxlxEGdbCwP+WD5G6dWRUWXlc8F0TtzU3uFglYMmDab2YhXTmnVN9g== dependencies: "@babel/runtime" "^7.20.13" @@ -1964,7 +1330,7 @@ "@react-pdf/stylesheet@^4.3.0": version "4.3.0" - resolved "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.3.0.tgz#3b0ad11e8d304347c8de5caacaa708f16d4a0473" + resolved "https://registry.yarnpkg.com/@react-pdf/stylesheet/-/stylesheet-4.3.0.tgz#3b0ad11e8d304347c8de5caacaa708f16d4a0473" integrity sha512-x7IVZOqRrUum9quuDeFXBveXwBht+z/6B0M+z4a4XjfSg1vZVvzoTl07Oa1yvQ/4yIC5yIkG2TSMWeKnDB+hrw== dependencies: "@babel/runtime" "^7.20.13" @@ -1975,9 +1341,21 @@ media-engine "^1.0.3" postcss-value-parser "^4.1.0" +"@react-pdf/stylesheet@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@react-pdf/stylesheet/-/stylesheet-6.1.0.tgz#ca6b5b0f7cc749b36379379d943f648f8527d71a" + integrity sha512-BGZ2sYNUp38VJUegjva/jsri3iiRGnVNjWI+G9dTwAvLNOmwFvSJzqaCsEnqQ/DW5mrTBk/577FhDY7pv6AidA== + dependencies: + "@react-pdf/fns" "3.1.2" + "@react-pdf/types" "^2.9.0" + color-string "^1.9.1" + hsl-to-hex "^1.0.0" + media-engine "^1.0.3" + postcss-value-parser "^4.1.0" + "@react-pdf/textkit@^4.4.1": version "4.4.1" - resolved "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.4.1.tgz#b4e4181ea7d4269c54a1794d4022b55c5135f0e7" + resolved "https://registry.yarnpkg.com/@react-pdf/textkit/-/textkit-4.4.1.tgz#b4e4181ea7d4269c54a1794d4022b55c5135f0e7" integrity sha512-Jl9wdTqIvJ5pX+vAGz0EOhP7ut5Two9H6CzTKo/YYPeD79cM2yTXF3JzTERBC28y7LR0Waq9D2LHQjI+b/EYUQ== dependencies: "@babel/runtime" "^7.20.13" @@ -1986,135 +1364,134 @@ hyphen "^1.6.4" unicode-properties "^1.4.1" -"@react-pdf/types@^2.6.0": - version "2.7.1" - resolved "https://registry.npmjs.org/@react-pdf/types/-/types-2.7.1.tgz#eb9f70be66b42c47f60c5afcc0af044ac48b98bf" - integrity sha512-MyjR1u+6SclQ/Tx6NP3/yoYZw7reXgC4OHFOrdMh/zeZ+ezfdGyovB+jdmVQuMe7Fsh64v7PUkO5tnsXHyCFWQ== +"@react-pdf/types@^2.6.0", "@react-pdf/types@^2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@react-pdf/types/-/types-2.9.0.tgz#a2721a847cb1ace2c31ca29b0303c7b51a2241c2" + integrity sha512-ckj80vZLlvl9oYrQ4tovEaqKWP3O06Eb1D48/jQWbdwz1Yh7Y9v1cEmwlP8ET+a1Whp8xfdM0xduMexkuPANCQ== + dependencies: + "@react-pdf/font" "^4.0.2" + "@react-pdf/primitives" "^4.1.1" + "@react-pdf/stylesheet" "^6.1.0" "@remirror/core-constants@3.0.0": version "3.0.0" - resolved "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz#96fdb89d25c62e7b6a5d08caf0ce5114370e3b8f" + resolved "https://registry.yarnpkg.com/@remirror/core-constants/-/core-constants-3.0.0.tgz#96fdb89d25c62e7b6a5d08caf0ce5114370e3b8f" integrity sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg== -"@rollup/rollup-android-arm-eabi@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz#f39f09f60d4a562de727c960d7b202a2cf797424" - integrity sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw== +"@rollup/rollup-android-arm-eabi@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz#8560592f0dcf43b8cb0949af9f1d916205148d12" + integrity sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA== -"@rollup/rollup-android-arm64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz#d19af7e23760717f1d879d4ca3d2cd247742dff2" - integrity sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA== +"@rollup/rollup-android-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz#6bfb777bbce998691b6fd3e916b05cd46392d020" + integrity sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ== -"@rollup/rollup-darwin-arm64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz#1c3a2fbf205d80641728e05f4a56c909e95218b7" - integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w== +"@rollup/rollup-darwin-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz#7efce10220293a22e7b7b595d05d8b8400a7bcf3" + integrity sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA== -"@rollup/rollup-darwin-x64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz#aa66d2ba1a25e609500e13bef06dc0e71cc0c0d4" - integrity sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg== +"@rollup/rollup-darwin-x64@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz#c617a8ece21050bfbea299c126767d2e70cfa79a" + integrity sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og== -"@rollup/rollup-freebsd-arm64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz#df10a7b6316a0ef1028c6ca71a081124c537e30d" - integrity sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg== +"@rollup/rollup-freebsd-arm64@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz#5a6af0a9acf82162d2910933649ae24fc0ea3ecb" + integrity sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g== -"@rollup/rollup-freebsd-x64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz#a3fdce8a05e95b068cbcb46e4df5185e407d0c35" - integrity sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA== +"@rollup/rollup-freebsd-x64@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz#ae9709463560196fc275bd0da598668a2e341023" + integrity sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A== -"@rollup/rollup-linux-arm-gnueabihf@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz#49f766c55383bd0498014a9d76924348c2f3890c" - integrity sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg== +"@rollup/rollup-linux-arm-gnueabihf@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz#6ec52661764dbd54c19d6520a403aa385a5c0fbf" + integrity sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q== -"@rollup/rollup-linux-arm-musleabihf@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz#1d4d7d32fc557e17d52e1857817381ea365e2959" - integrity sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA== +"@rollup/rollup-linux-arm-musleabihf@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz#fd33ba4a43ef8419e96811236493d19436271923" + integrity sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q== -"@rollup/rollup-linux-arm64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz#f4fc317268441e9589edad3be8f62b6c03009bc1" - integrity sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA== +"@rollup/rollup-linux-arm64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz#933b3d99b73c9d7bf4506cab0d5d313c7e74fd2d" + integrity sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw== -"@rollup/rollup-linux-arm64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz#63a1f1b0671cb17822dabae827fef0e443aebeb7" - integrity sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg== +"@rollup/rollup-linux-arm64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz#dbe9ae24ee9e97b75662fddcb69eb7f23c89280a" + integrity sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog== -"@rollup/rollup-linux-loongarch64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz#c659b01cc6c0730b547571fc3973e1e955369f98" - integrity sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw== +"@rollup/rollup-linux-loongarch64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz#818c5a071eec744436dbcdd76fe9c3c869dc9a8d" + integrity sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg== -"@rollup/rollup-linux-powerpc64le-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz#612e746f9ad7e58480f964d65e0d6c3f4aae69a8" - integrity sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A== +"@rollup/rollup-linux-powerpc64le-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz#6b8591def27d886fa147fb0340126c7d6682a7e4" + integrity sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg== -"@rollup/rollup-linux-riscv64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz#4610dbd1dcfbbae32fbc10c20ae7387acb31110c" - integrity sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw== +"@rollup/rollup-linux-riscv64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz#f1861ac4ee8da64e0b0d23853ff26fe2baa876cf" + integrity sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw== -"@rollup/rollup-linux-riscv64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz#054911fab40dc83fafc21e470193c058108f19d8" - integrity sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw== +"@rollup/rollup-linux-riscv64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz#320c961401a923b374e358664527b188e374e1ae" + integrity sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA== -"@rollup/rollup-linux-s390x-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz#98896eca8012547c7f04bd07eaa6896825f9e1a5" - integrity sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g== +"@rollup/rollup-linux-s390x-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz#1763eed3362b50b6164d3f0947486c03cc7e616d" + integrity sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw== -"@rollup/rollup-linux-x64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz#01cf56844a1e636ee80dfb364e72c2b7142ad896" - integrity sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A== +"@rollup/rollup-linux-x64-gnu@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz#0d4c8d0b8f801902f0844a40a9d981a0179f4971" + integrity sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw== -"@rollup/rollup-linux-x64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz#e67c7531df6dff0b4c241101d4096617fbca87c3" - integrity sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ== +"@rollup/rollup-linux-x64-musl@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz#ec30bb48b5fe22a3aaba98072f2d5b7139e1a8eb" + integrity sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw== -"@rollup/rollup-win32-arm64-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz#7eeada98444e580674de6989284e4baacd48ea65" - integrity sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ== +"@rollup/rollup-win32-arm64-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz#27a6e48d1502e8e4bed96bedfb533738655874f2" + integrity sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg== -"@rollup/rollup-win32-ia32-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz#516c4b54f80587b4a390aaf4940b40870271d35d" - integrity sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg== +"@rollup/rollup-win32-ia32-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz#a2fbad3bec20ff879f3fd51720adf33692ca8f3d" + integrity sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw== -"@rollup/rollup-win32-x64-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz#848f99b0d9936d92221bb6070baeff4db6947a30" - integrity sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw== +"@rollup/rollup-win32-x64-msvc@4.45.1": + version "4.45.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz#e5085c6d13da15b4c5133cd2a6bb11f25b6bb77a" + integrity sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA== "@rtsao/scc@^1.1.0": version "1.1.0" - resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== "@rushstack/eslint-patch@^1.3.3": - version "1.10.5" - resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz#3a1c12c959010a55c17d46b395ed3047b545c246" - integrity sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A== + version "1.12.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz#326a7b46f6d4cfa54ae25bb888551697873069b4" + integrity sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw== -"@sindresorhus/merge-streams@^2.1.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958" - integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg== - -"@storybook/addon-actions@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.5.4.tgz#8d1cd697a96d85d0e4d235b094753b3ac5610871" - integrity sha512-b7dwmVWaiJJmPdNrCCuy5wPD1HsPNGHCH+O9XJDrQpZ4EFREAcoWurIztldy5PV7DOOeLlW5rXxtwEEN41emQg== +"@storybook/addon-actions@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.6.14.tgz#e6bc8f5afc67853e6ce3e03fb0bdcfa67c0dec16" + integrity sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ== dependencies: "@storybook/global" "^5.0.0" "@types/uuid" "^9.0.1" @@ -2122,143 +1499,141 @@ polished "^4.2.2" uuid "^9.0.0" -"@storybook/addon-backgrounds@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.5.4.tgz#2021295f44f8ce02ac05724c12a335fc9ab134a2" - integrity sha512-PldWAiNGZ2gjwHSYpqCgkMAQ9kt6yZSZ6BMvQMEMZ5uUhTlQ65g/aSAVN8a3baM79idPA3yetnMm2ybXbUxKOQ== +"@storybook/addon-backgrounds@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-8.6.14.tgz#3840ce28339c3c16d001f751fd5f3125c0643ed7" + integrity sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg== dependencies: "@storybook/global" "^5.0.0" memoizerific "^1.11.3" ts-dedent "^2.0.0" -"@storybook/addon-controls@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.5.4.tgz#2d2b54e3fe3ec7afe51ea816d36d114e4c181ab6" - integrity sha512-6rI+IIYdTpR7RrZQfE1ixPINm+a4DOggs82PX8q8gLGErHQo1TSfLaUeNpysb9DTZev0PhTdajdiW4AVakMgyg== +"@storybook/addon-controls@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-8.6.14.tgz#4aafdd25276a0b86a8b744ef8344998f458cb5a5" + integrity sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw== dependencies: "@storybook/global" "^5.0.0" dequal "^2.0.2" ts-dedent "^2.0.0" -"@storybook/addon-docs@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.5.4.tgz#aa12e4adbdce1104f9befb70043c3f1e1c92202f" - integrity sha512-dLDM1oycm50a2wJVtuPwoNLIBmy8Z9r7e0F9InsPu9iTZAZLb6C5lYDNXG7GkFrRU/Q2yqSb9q7upoV7UiPGWA== +"@storybook/addon-docs@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-8.6.14.tgz#71fcf4cf06dae91cecd5668915a8c234b82748e9" + integrity sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ== dependencies: "@mdx-js/react" "^3.0.0" - "@storybook/blocks" "8.5.4" - "@storybook/csf-plugin" "8.5.4" - "@storybook/react-dom-shim" "8.5.4" + "@storybook/blocks" "8.6.14" + "@storybook/csf-plugin" "8.6.14" + "@storybook/react-dom-shim" "8.6.14" react "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" react-dom "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" ts-dedent "^2.0.0" "@storybook/addon-essentials@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.5.4.tgz#978fc8357ea8075158396749bd7596a4c65c4e3c" - integrity sha512-syocWJaOI+JpV6aRhw1+QKFjJ0LEt1L/qDDz+UWyH2ryppXUkKQtc8nJVkLogkWODIZ/Q4cjIVD0kdrDSmtu0g== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-8.6.14.tgz#228f6ebeafba1d3368e8d900508dbdc86640ad34" + integrity sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA== dependencies: - "@storybook/addon-actions" "8.5.4" - "@storybook/addon-backgrounds" "8.5.4" - "@storybook/addon-controls" "8.5.4" - "@storybook/addon-docs" "8.5.4" - "@storybook/addon-highlight" "8.5.4" - "@storybook/addon-measure" "8.5.4" - "@storybook/addon-outline" "8.5.4" - "@storybook/addon-toolbars" "8.5.4" - "@storybook/addon-viewport" "8.5.4" + "@storybook/addon-actions" "8.6.14" + "@storybook/addon-backgrounds" "8.6.14" + "@storybook/addon-controls" "8.6.14" + "@storybook/addon-docs" "8.6.14" + "@storybook/addon-highlight" "8.6.14" + "@storybook/addon-measure" "8.6.14" + "@storybook/addon-outline" "8.6.14" + "@storybook/addon-toolbars" "8.6.14" + "@storybook/addon-viewport" "8.6.14" ts-dedent "^2.0.0" -"@storybook/addon-highlight@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.5.4.tgz#62d63e946059fe3249ee093aad57812794f20964" - integrity sha512-llrxTpzJs+F61nU9ZPaVhw8iHE3hVSc5bVRuEFSRRroJC/wSNGBHz9nLBfmZ7w+06dXK4S5DRHbYehBLRRzj3Q== +"@storybook/addon-highlight@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-8.6.14.tgz#f5fb86bfae8b485cd49e8e2732eb05e049cd60cb" + integrity sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ== dependencies: "@storybook/global" "^5.0.0" "@storybook/addon-interactions@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.5.4.tgz#9a2a9c8c0de341df8bb92544e67296de98086ff5" - integrity sha512-9xhz7goOKV13WIAcrCZs4kP7pMutLqyMygjCt+oNHCiDx7Sj8q+heVT46uSR1xkgZU1C7uKpUeQWkb+kfkB54Q== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-interactions/-/addon-interactions-8.6.14.tgz#f836fed81b4fb5a5ef09afaeb15902cdb933624e" + integrity sha512-8VmElhm2XOjh22l/dO4UmXxNOolGhNiSpBcls2pqWSraVh4a670EyYBZsHpkXqfNHo2YgKyZN3C91+9zfH79qQ== dependencies: "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.5.4" - "@storybook/test" "8.5.4" + "@storybook/instrumenter" "8.6.14" + "@storybook/test" "8.6.14" polished "^4.2.2" ts-dedent "^2.2.0" "@storybook/addon-links@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.5.4.tgz#ab0dcc30275b03c8cce2b92f822596dfad9f9dbb" - integrity sha512-t28NJXhtTGa4RbzGOWNoL0T9liqhdlVbq3wkhbpUgXI4ay5BA2bVsVUuO7vKDp26oNeaZDsSyWv78Gg7FoeVmQ== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-8.6.14.tgz#d7d30b5f96dd6b5b93046dec5a37d2e9b0ae44d0" + integrity sha512-DRlXHIyZzOruAZkxmXfVgTF+4d6K27pFcH4cUsm3KT1AXuZbr23lb5iZHpUZoG6lmU85Sru4xCEgewSTXBIe1w== dependencies: - "@storybook/csf" "0.1.12" "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-measure@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.5.4.tgz#711d01ee33d5df726eb771be135780928d80e672" - integrity sha512-VmKvXGm7s++BUrnmT8GHw2A3x+nDTk+8PtP4cBVaqMqyiYOd7ycWDrCTrLl/sm+WcYo3NY9/iXYNgluN4rKQ5Q== +"@storybook/addon-measure@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-8.6.14.tgz#cafe8742616f0df6f82eadc0ee268bbca6ac4843" + integrity sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw== dependencies: "@storybook/global" "^5.0.0" tiny-invariant "^1.3.1" "@storybook/addon-onboarding@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.5.4.tgz#49ad7197e3222ddc574a168e8055f5b572fd1f2b" - integrity sha512-QCj1HY2G+Rs60i0bhWEl1675MZ/iBLBofFyubmP2G8cdgYMLUrOtbrd0cQBp11TSGVNzkT8sCDHYW+JEtsb0tQ== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-onboarding/-/addon-onboarding-8.6.14.tgz#82453d71595572818bf3a72899e6d506806475c3" + integrity sha512-bHdHiGJFigVcSzMIsNLHY5IODZHr+nKwyz5/QOZLMkLcGH2IaUbOJfm4RyGOaTTPsUtAKbdsVXNEG3Otf+qO9A== -"@storybook/addon-outline@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.5.4.tgz#edc388fb0eb508391d35050f195b5503ce027cd0" - integrity sha512-DSrTzQpCObZ9Af3djJPWVkBxvUfkBtMMeXKaGazOZem90vk2r1Q2PRaX8J/xhWxMhZtvjQuYexAyn5O7JxdaWA== +"@storybook/addon-outline@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-8.6.14.tgz#8a779cd6cdaf935964fe6d6c30ebf929218e23d5" + integrity sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w== dependencies: "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" "@storybook/addon-styling-webpack@^1.0.0": version "1.0.1" - resolved "https://registry.npmjs.org/@storybook/addon-styling-webpack/-/addon-styling-webpack-1.0.1.tgz#660ee002ec249f6e32dd2784abfa50f59ef97951" + resolved "https://registry.yarnpkg.com/@storybook/addon-styling-webpack/-/addon-styling-webpack-1.0.1.tgz#660ee002ec249f6e32dd2784abfa50f59ef97951" integrity sha512-5n+SXPfMTc4m7sWaJWPWjoHYWc6/B111M2Ia55toQ3GV4ON4vVlTgH9FX+EgCkDticElj99HLTMDJkHRj2yvkg== dependencies: "@storybook/node-logger" "^8.0.0-alpha.10" -"@storybook/addon-toolbars@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.5.4.tgz#6c79ed56cdc732301b41cfcc0b31f64e88e14f86" - integrity sha512-aszYJ8VJjaQV6RcZhD27NMSHpPHygt130l3VnRg1EqKN/r2QdNU1hVC8n2EPASYOJfOQH4Q9eySIplbQYSt0+g== +"@storybook/addon-toolbars@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-8.6.14.tgz#6d53ba81ee7179621798fe0302d453e47ecfaeba" + integrity sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ== -"@storybook/addon-viewport@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.5.4.tgz#2e4d90071302d9c50d5788403c8669ae406c6e8d" - integrity sha512-CweXFUXmdG9d4uRVspGzhtrzwyLYQMKLIpjz1N5jDHiT234+xWKYtlqYbpmm5x56M/w9kzxqIWgyMgB/i2mPIA== +"@storybook/addon-viewport@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-8.6.14.tgz#d948fcb0a91dadd7f4735913c8eee6c376d49baa" + integrity sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA== dependencies: memoizerific "^1.11.3" "@storybook/addon-webpack5-compiler-swc@^1.0.2": version "1.0.6" - resolved "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.6.tgz#6fe1d3af421e3efc935c866a719e02b62f2ab6ea" + resolved "https://registry.yarnpkg.com/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.6.tgz#6fe1d3af421e3efc935c866a719e02b62f2ab6ea" integrity sha512-QiZheKKYsUCAtPn9phwtmOBAWBNxnxyfu5E+HUSQIbX94pTwc3ROufJ3g1R/RMQZcklOYXpSI0V8FS1m6aUVkg== dependencies: "@swc/core" "^1.7.3" swc-loader "^0.2.3" -"@storybook/blocks@8.5.4", "@storybook/blocks@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.5.4.tgz#cf91a257ab8e756d53393126251708149cfa8d26" - integrity sha512-QLfQ5KX6m2FAsz1zjB+mUp9jEA+LCzIHo3BxLr/tWN3pIwSURoHs2wrHDXT2r+wu5CBesGvTKI4KUWlsxsOF9g== +"@storybook/blocks@8.6.14", "@storybook/blocks@^8.1.1": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-8.6.14.tgz#9d39e64f4fd0a446d96f1f5d6b220d4812fc05fa" + integrity sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ== dependencies: - "@storybook/csf" "0.1.12" "@storybook/icons" "^1.2.12" ts-dedent "^2.0.0" -"@storybook/builder-webpack5@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.5.4.tgz#d5f5f0c97c6b8dace63f0abe4b314a50d7e17c30" - integrity sha512-bOcq7qrcW31Oy1RcR7utgr3SEYBvSj5wiQYHmRMgvAbcmWP80mP6scTHFdauvc/kzKE11Yri9CT/KG9GgoEm4g== +"@storybook/builder-webpack5@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-8.6.14.tgz#18e9f0d34b989ad1e4ed5b79a71c82b2bc727fd4" + integrity sha512-YZYAqc6NBKoMTKZpjxnkMch6zDtMkBZdS/yaji1+wJX2QPFBwTbSh7SpeBxDp1S11gXSAJ4f1btUWeqSqo8nJA== dependencies: - "@storybook/core-webpack" "8.5.4" + "@storybook/core-webpack" "8.6.14" "@types/semver" "^7.3.4" browser-assert "^1.2.1" case-sensitive-paths-webpack-plugin "^2.4.0" @@ -2283,27 +1658,27 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.6.0" -"@storybook/components@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/components/-/components-8.5.4.tgz#f1eab3e26c687a225e21a0e8af5f257f6326601e" - integrity sha512-z4lWN4W1cUqlhOFQ3Kg33Yu4uuoOvECQtxJqNHUPFsHNOtIbYIdUMCLwiJFUxrzdJXUnOqn5QTcsFerWX6Roag== +"@storybook/components@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-8.6.14.tgz#3cfc5e120f3dc38990fc37b34a22eff1e3f4bdfb" + integrity sha512-HNR2mC5I4Z5ek8kTrVZlIY/B8gJGs5b3XdZPBPBopTIN6U/YHXiDyOjY3JlaS4fSG1fVhp/Qp1TpMn1w/9m1pw== -"@storybook/core-webpack@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.5.4.tgz#430ebf12a063efb03859fa105bb09c32feaddd79" - integrity sha512-YOlzywqG4pVFYMzkmYuMrueI4swofOaoKvQjlVIE/8fP7vSu7HhhBbtlxowd0i08UjP/wSVq0zvxl9RGxHWq5Q== +"@storybook/core-webpack@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/core-webpack/-/core-webpack-8.6.14.tgz#2d2d3aca9cff01bcb33d1b6067d5dd69727998f1" + integrity sha512-iG7r8osNKabSGBbuJuSeMWKbU+ilt5PvzTYkClcYaagla/DliXkXvfywA6jOugVk/Cpx+c6tVKlPfjLcaQHwmw== dependencies: ts-dedent "^2.0.0" -"@storybook/core@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/core/-/core-8.5.4.tgz#7dfdd3496620f607253bd23bb004d602e17114ee" - integrity sha512-x7SoqdDAi6+x7hFRF7SIcxKKNdj8E1pK0B9k6uf+cop16/mxNWazqQFJRpKRE66h/ImYqopMnpX3ASaa3Khm4w== +"@storybook/core@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-8.6.14.tgz#335b067709fd649512b6553b31ad48c8c56f7ed9" + integrity sha512-1P/w4FSNRqP8j3JQBOi3yGt8PVOgSRbP66Ok520T78eJBeqx9ukCfl912PQZ7SPbW3TIunBwLXMZOjZwBB/JmA== dependencies: - "@storybook/csf" "0.1.12" + "@storybook/theming" "8.6.14" better-opn "^3.0.2" browser-assert "^1.2.1" - esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0" + esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0" esbuild-register "^3.5.0" jsdoc-type-pratt-parser "^4.0.0" process "^0.11.10" @@ -2312,55 +1687,48 @@ util "^0.12.5" ws "^8.2.3" -"@storybook/csf-plugin@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.5.4.tgz#e8638a45f07fd3e9d080c29c3cf7f2737438e6af" - integrity sha512-W368wMblH861QlW5gfZEwF/LYrWQ2NheXgikBfYv73se1WxvQCo8IMLXCNpgmYhse81GsvXRddKULGsqDSH37A== +"@storybook/csf-plugin@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-8.6.14.tgz#c7fc0361204a34693e8d62ebe5922d77dfec06c0" + integrity sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ== dependencies: unplugin "^1.3.1" -"@storybook/csf@0.1.12": - version "0.1.12" - resolved "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.12.tgz#1dcfa0f398a69b834c563884b5f747db3d5a81df" - integrity sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw== - dependencies: - type-fest "^2.19.0" - "@storybook/global@^5.0.0": version "5.0.0" - resolved "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed" + resolved "https://registry.yarnpkg.com/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed" integrity sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ== "@storybook/icons@^1.2.12": - version "1.3.2" - resolved "https://registry.npmjs.org/@storybook/icons/-/icons-1.3.2.tgz#e9b92c35ca789ff79f9d0b3848829dd6490ca628" - integrity sha512-t3xcbCKkPvqyef8urBM0j/nP6sKtnlRkVgC+8JTbTAZQjaTmOjes3byEgzs89p4B/K6cJsg9wLW2k3SknLtYJw== + version "1.4.0" + resolved "https://registry.yarnpkg.com/@storybook/icons/-/icons-1.4.0.tgz#7cf7ab3dfb41943930954c4ef493a73798d8b31d" + integrity sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA== -"@storybook/instrumenter@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.5.4.tgz#002e79b6d1d618c6249cfa82a1adf79e298535ad" - integrity sha512-6Y2d6SNZslZl2UhkfH8Ml6SzKX5b2x/QRBwkLAAXc/xZcFdK5luAOPk/fW1BU7jEAPAjtn493V3oo2nGA5D22A== +"@storybook/instrumenter@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-8.6.14.tgz#85bf47e34348f17dfbb99080312eefb2f535bd65" + integrity sha512-iG4MlWCcz1L7Yu8AwgsnfVAmMbvyRSk700Mfy2g4c8y5O+Cv1ejshE1LBBsCwHgkuqU0H4R0qu4g23+6UnUemQ== dependencies: "@storybook/global" "^5.0.0" "@vitest/utils" "^2.1.1" -"@storybook/manager-api@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.5.4.tgz#3d198104264af3ffac27b0a6c3700b822484af16" - integrity sha512-kFK5DM+4YPob0qdiXN5DJh33fDyQvNJb7IAobDS/rPo2L+t6M+DAgqEsXLQXT9nUbnUD9IcCjwEnjKa+EHU2RA== +"@storybook/manager-api@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-8.6.14.tgz#1e0740193fbfd4a66e9ff5f75c7f976e16028752" + integrity sha512-ez0Zihuy17udLbfHZQXkGqwtep0mSGgHcNzGN7iZrMP1m+VmNo+7aGCJJdvXi7+iU3yq8weXSQFWg5DqWgLS7g== "@storybook/node-logger@^8.0.0-alpha.10": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-8.5.4.tgz#0805ba35a71ece96b29458fd76dee71900310901" - integrity sha512-76vc3gkwOO6gnh/l4uRbYQ4AFNcWoklOED0Ck6yP2OsuH5lRb8sayeE9sluRCathXHBiI2nW1c85P8OeYCP55w== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-8.6.14.tgz#f5f6971a88e21c20855506ab54be22ab43673946" + integrity sha512-/H67NMvc9hDOaNgVragsHaeXQ5JzwAQfyx1QeL4vlx2SPGoWXmxpoRXZTpOJRaNOhKlYh6sDj/3Lx2xOH5IxnQ== -"@storybook/preset-react-webpack@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.5.4.tgz#916e54cebd4e0f8fe6f2c11f4ba0471883921cae" - integrity sha512-4T9wzY+G0TtyzAqlqFwOujffxxjxrJGY2vLtHVWNP5kTjqIdmmqes7LFz+69Pmily1qKJg+bIPkelu/MUBECRA== +"@storybook/preset-react-webpack@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/preset-react-webpack/-/preset-react-webpack-8.6.14.tgz#c8a402afe857dbe1d04f2ebee492521adaff1ae7" + integrity sha512-M7Q6ErNx7N2hQorTz0OLa3YV8nc8OcvkDlCxqqnkHPGQNEIWEpeDvq3wn2OvZlrHDpchyuiquGXZ8aztVtBP2g== dependencies: - "@storybook/core-webpack" "8.5.4" - "@storybook/react" "8.5.4" + "@storybook/core-webpack" "8.6.14" + "@storybook/react" "8.6.14" "@storybook/react-docgen-typescript-plugin" "1.0.6--canary.9.0c3f3b7.0" "@types/semver" "^7.3.4" find-up "^5.0.0" @@ -2371,14 +1739,14 @@ tsconfig-paths "^4.2.0" webpack "5" -"@storybook/preview-api@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.5.4.tgz#ea3f05bfbbc2924c1112fd25befdc8be28101ee0" - integrity sha512-V9cTl5uWRmWAA4hCmz97PxgP0QYq2DpJUpeSxt/+Hhhm1OYTxAYJWt6Y3pIfqEFhOFjQzZwTprzGYzVjk4S3DA== +"@storybook/preview-api@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-8.6.14.tgz#b4a1eda7ecf17c4d3a07aa9a42ed1251de121f74" + integrity sha512-2GhcCd4dNMrnD7eooEfvbfL4I83qAqEyO0CO7JQAmIO6Rxb9BsOLLI/GD5HkvQB73ArTJ+PT50rfaO820IExOQ== "@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0": version "1.0.6--canary.9.0c3f3b7.0" - resolved "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz#7f10f3c641f32e4513a8b6ffb5036933e7059534" + resolved "https://registry.yarnpkg.com/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz#7f10f3c641f32e4513a8b6ffb5036933e7059534" integrity sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q== dependencies: debug "^4.1.1" @@ -2389,144 +1757,143 @@ react-docgen-typescript "^2.2.2" tslib "^2.0.0" -"@storybook/react-dom-shim@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.5.4.tgz#32f2d82b0a7478f5ad39013fba5d0a093b4e7a01" - integrity sha512-m6soTAZFlOH5L2CW3V3g1eJ9Z06Gzgv8urOrnqeBmyCTcpuzxs4GRf9whvu5x/ULZAuvAL77H53d9W1/UYI4sQ== +"@storybook/react-dom-shim@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-8.6.14.tgz#02fc8aeab701040744d93b6ef46b9e5727123370" + integrity sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw== "@storybook/react-webpack5@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.5.4.tgz#57f2f37e044c0f2ce1e0ef2b33eb7a650d3a7962" - integrity sha512-rXdvr2Ls22chU8BoiCFicaERKo3vZarrHeS4y++pL5ef+RIU0bnZitxGyhusolL6s2q36ZS6u+i1BXr//c0Ynw== + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/react-webpack5/-/react-webpack5-8.6.14.tgz#2a3d23787153e31a2943078904648b188669a777" + integrity sha512-ka0q9tQBLruhO38sybP/MkZzejqAltce7HJTJ2KKbUYUlbvuG7m56tBX7DVC5JaImbsO3b8fqOrKH7gRt4KYrQ== dependencies: - "@storybook/builder-webpack5" "8.5.4" - "@storybook/preset-react-webpack" "8.5.4" - "@storybook/react" "8.5.4" + "@storybook/builder-webpack5" "8.6.14" + "@storybook/preset-react-webpack" "8.6.14" + "@storybook/react" "8.6.14" -"@storybook/react@8.5.4", "@storybook/react@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/react/-/react-8.5.4.tgz#cbf286803bf8dc6477dab582b82f010e2c3b6bfc" - integrity sha512-4OipHaxH+IYqrYrX25kjrXTC3gj0NhpksYG/cfZ38MgLY+odFHGI7hNMgx9YMoaL/pnQRtnVjWaz2nIahsUXSA== +"@storybook/react@8.6.14", "@storybook/react@^8.1.1": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-8.6.14.tgz#80136abcbc6e96ef5f747aef5c4e6afc40b3dce4" + integrity sha512-BOepx5bBFwl/CPI+F+LnmMmsG1wQYmrX/UQXgUbHQUU9Tj7E2ndTnNbpIuSLc8IrM03ru+DfwSg1Co3cxWtT+g== dependencies: - "@storybook/components" "8.5.4" + "@storybook/components" "8.6.14" "@storybook/global" "^5.0.0" - "@storybook/manager-api" "8.5.4" - "@storybook/preview-api" "8.5.4" - "@storybook/react-dom-shim" "8.5.4" - "@storybook/theming" "8.5.4" + "@storybook/manager-api" "8.6.14" + "@storybook/preview-api" "8.6.14" + "@storybook/react-dom-shim" "8.6.14" + "@storybook/theming" "8.6.14" -"@storybook/test@8.5.4", "@storybook/test@^8.1.1": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/test/-/test-8.5.4.tgz#700d9fdd08c3ce76dc0f3d98fd35a7c68b9a8b1e" - integrity sha512-H7zV39GLiUSz/M7fJtv/NWOF1J99CTAqqXMaETwJU5wEpkj1Q3jzmWss+UFtl5x7f/OZC4niP9s9A3G8rZHpKw== +"@storybook/test@8.6.14", "@storybook/test@^8.1.1": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.6.14.tgz#7b90708f13adabdac0fe8d08889d763608f6a481" + integrity sha512-GkPNBbbZmz+XRdrhMtkxPotCLOQ1BaGNp/gFZYdGDk2KmUWBKmvc5JxxOhtoXM2703IzNFlQHSSNnhrDZYuLlw== dependencies: - "@storybook/csf" "0.1.12" "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.5.4" + "@storybook/instrumenter" "8.6.14" "@testing-library/dom" "10.4.0" "@testing-library/jest-dom" "6.5.0" "@testing-library/user-event" "14.5.2" "@vitest/expect" "2.0.5" "@vitest/spy" "2.0.5" -"@storybook/theming@8.5.4": - version "8.5.4" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-8.5.4.tgz#9e50d3c16e0c3885de5ed02925de1e0cbf0e7dfa" - integrity sha512-mgMQDe6rF0fS3cDGx55KSzv0URA9Eefo89uoh2oKUmv5+M30067axNK62A9Ys03fSVcB11Iccen0cyu3SHeiyw== +"@storybook/theming@8.6.14": + version "8.6.14" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-8.6.14.tgz#78c6dc878f705de70c67f2b2d08b8313b985d81a" + integrity sha512-r4y+LsiB37V5hzpQo+BM10PaCsp7YlZ0YcZzQP1OCkPlYXmUAFy2VvDKaFRpD8IeNPKug2u4iFm/laDEbs03dg== -"@swc/core-darwin-arm64@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.15.tgz#1703ee8e98ea859965bfc7a912db4c452dc4ca36" - integrity sha512-zFdZ6/yHqMCPk7OhLFqHy/MQ1EqJhcZMpNHd1gXYT7VRU3FaqvvKETrUlG3VYl65McPC7AhMRfXPyJ0JO/jARQ== +"@swc/core-darwin-arm64@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.1.tgz#a66e5bc1186f8b7402855560adc7448612b159af" + integrity sha512-zO6SW/jSMTUORPm6dUZFPUwf+EFWZsaXWMGXadRG6akCofYpoQb8pcY2QZkVr43z8TMka6BtXpyoD/DJ0iOPHQ== -"@swc/core-darwin-x64@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.15.tgz#e8d60fc04ca56b1e5644b25f0032093a5bef70a0" - integrity sha512-8g4yiQwbr8fxOOjKXdot0dEkE5zgE8uNZudLy/ZyAhiwiZ8pbJ8/wVrDOu6dqbX7FBXAoDnvZ7fwN1jk4C8jdA== +"@swc/core-darwin-x64@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.13.1.tgz#9c56b3d25df950bdeb080b287f2a9d8331eb08a3" + integrity sha512-8RjaTZYxrlYKE5PgzZYWSOT4mAsyhIuh30Nu4dnn/2r0Ef68iNCbvX4ynGnFMhOIhqunjQbJf+mJKpwTwdHXhw== -"@swc/core-linux-arm-gnueabihf@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.15.tgz#1ec6d2caf1a8a099e13dcd459f45be2fb4febde8" - integrity sha512-rl+eVOltl2+7WXOnvmWBpMgh6aO13G5x0U0g8hjwlmD6ku3Y9iRcThpOhm7IytMEarUp5pQxItNoPq+VUGjVHg== +"@swc/core-linux-arm-gnueabihf@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.1.tgz#cb4b6f7b793d0047c3936c1e57308d5e5a6a7533" + integrity sha512-jEqK6pECs2m4BpL2JA/4CCkq04p6iFOEtVNXTisO+lJ3zwmxlnIEm9UfJZG6VSu8GS9MHRKGB0ieZ1tEdN1qDA== -"@swc/core-linux-arm64-gnu@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.15.tgz#dfcf6a63e9d6cb75779411e637c86ff7a04d352b" - integrity sha512-qxWEQeyAJMWJqjaN4hi58WMpPdt3Tn0biSK9CYRegQtvZWCbewr6v2agtSu5AZ2rudeH6OfCWAMDQQeSgn6PJQ== +"@swc/core-linux-arm64-gnu@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.1.tgz#d208622b6fdff92595d23b4aba36d73be31fffe6" + integrity sha512-PbkuIOYXO/gQbWQ7NnYIwm59ygNqmUcF8LBeoKvxhx1VtOwE+9KiTfoplOikkPLhMiTzKsd8qentTslbITIg+Q== -"@swc/core-linux-arm64-musl@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.15.tgz#a629b47066f83730b757743145e2c8354a42164f" - integrity sha512-QcELd9/+HjZx0WCxRrKcyKGWTiQ0485kFb5w8waxcSNd0d9Lgk4EFfWWVyvIb5gIHpDQmhrgzI/yRaWQX4YSZQ== +"@swc/core-linux-arm64-musl@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.1.tgz#dd306f08f277a3e3a0c223f1a22ef25be791a8dd" + integrity sha512-JaqFdBCarIBKiMu5bbAp+kWPMNGg97ej+7KzbKOzWP5pRptqKi86kCDZT3WmjPe8hNG6dvBwbm7Y8JNry5LebQ== -"@swc/core-linux-x64-gnu@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.15.tgz#2a5ec7ed21b38d6f07524ec6af6ae90c10ad3f63" - integrity sha512-S1+ZEEn3+a/MiMeQqQypbwTGoBG8/sPoCvpNbk+uValyygT+jSn3U0xVr45FbukpmMB+NhBMqfedMLqKA0QnJA== +"@swc/core-linux-x64-gnu@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.1.tgz#c2a41b8065c7d9cb165cc3df5317897426091823" + integrity sha512-t4cLkku10YECDaakWUH0452WJHIZtrLPRwezt6BdoMntVMwNjvXRX7C8bGuYcKC3YxRW7enZKFpozLhQIQ37oA== -"@swc/core-linux-x64-musl@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.15.tgz#64bf2a9d4b3858a002a4879833245c25e742149b" - integrity sha512-qW+H9g/2zTJ4jP7NDw4VAALY0ZlNEKzYsEoSj/HKi7k3tYEHjMzsxjfsY9I8WZCft23bBdV3RTCPoxCshaj1CQ== +"@swc/core-linux-x64-musl@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.1.tgz#6691322d5a2cfe5187d43370c07c7ceaaac045ed" + integrity sha512-fSMwZOaG+3ukUucbEbzz9GhzGhUhXoCPqHe9qW0/Vc2IZRp538xalygKyZynYweH5d9EHux1aj3+IO8/xBaoiA== -"@swc/core-win32-arm64-msvc@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.15.tgz#1c703c90873991b37a49df056af0f71bd632db5b" - integrity sha512-AhRB11aA6LxjIqut+mg7qsu/7soQDmbK6MKR9nP3hgBszpqtXbRba58lr24xIbBCMr+dpo6kgEapWt+t5Po6Zg== +"@swc/core-win32-arm64-msvc@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.1.tgz#451eff0efdb79804d6983dc6f533a046a90e82a0" + integrity sha512-tweCXK/79vAwj1NhAsYgICy8T1z2QEairmN2BFEBYFBFNMEB1iI1YlXwBkBtuihRvgZrTh1ORusKa4jLYzLCZA== -"@swc/core-win32-ia32-msvc@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.15.tgz#09f86d172b08913aaf0b96aa1596505cd95447af" - integrity sha512-UGdh430TQwbDn6KjgvRTg1fO022sbQ4yCCHUev0+5B8uoBwi9a89qAz3emy2m56C8TXxUoihW9Y9OMfaRwPXUw== +"@swc/core-win32-ia32-msvc@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.1.tgz#3b5ed14186017a1e181f48f48d5b26147c0b857e" + integrity sha512-zi7hO9D+2R2yQN9D7T10/CAI9KhuXkNkz8tcJOW6+dVPtAk/gsIC5NoGPELjgrAlLL9CS38ZQpLDslLfpP15ng== -"@swc/core-win32-x64-msvc@1.10.15": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.15.tgz#70bcf83837d331e5cebaf2195a1e696549fdfef3" - integrity sha512-XJzBCqO1m929qbJsOG7FZXQWX26TnEoMctS3QjuCoyBmkHxxQmZsy78KjMes1aomTcKHCyFYgrRGWgVmk7tT4Q== +"@swc/core-win32-x64-msvc@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.1.tgz#bd35da282344ad73a86cd32a7edc0b03a457d9f7" + integrity sha512-KubYjzqs/nz3H69ncX/XHKsC8c1xqc7UvonQAj26BhbL22HBsqdAaVutZ+Obho6RMpd3F5qQ95ldavUTWskRrw== "@swc/core@^1.7.3": - version "1.10.15" - resolved "https://registry.npmjs.org/@swc/core/-/core-1.10.15.tgz#41568ec332765d2798f56753fd56d7aeece48510" - integrity sha512-/iFeQuNaGdK7mfJbQcObhAhsMqLT7qgMYl7jX2GEIO+VDTejESpzAyKwaMeYXExN8D6e5BRHBCe7M5YlsuzjDA== + version "1.13.1" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.13.1.tgz#36cb623f0b0282240ec007678a515fdb7c72997f" + integrity sha512-jEKKErLC6uwSqA+p6bmZR08usZM5Fpc+HdEu5CAzvye0q43yf1si1kjhHEa9XMkz0A2SAaal3eKCg/YYmtOsCA== dependencies: "@swc/counter" "^0.1.3" - "@swc/types" "^0.1.17" + "@swc/types" "^0.1.23" optionalDependencies: - "@swc/core-darwin-arm64" "1.10.15" - "@swc/core-darwin-x64" "1.10.15" - "@swc/core-linux-arm-gnueabihf" "1.10.15" - "@swc/core-linux-arm64-gnu" "1.10.15" - "@swc/core-linux-arm64-musl" "1.10.15" - "@swc/core-linux-x64-gnu" "1.10.15" - "@swc/core-linux-x64-musl" "1.10.15" - "@swc/core-win32-arm64-msvc" "1.10.15" - "@swc/core-win32-ia32-msvc" "1.10.15" - "@swc/core-win32-x64-msvc" "1.10.15" + "@swc/core-darwin-arm64" "1.13.1" + "@swc/core-darwin-x64" "1.13.1" + "@swc/core-linux-arm-gnueabihf" "1.13.1" + "@swc/core-linux-arm64-gnu" "1.13.1" + "@swc/core-linux-arm64-musl" "1.13.1" + "@swc/core-linux-x64-gnu" "1.13.1" + "@swc/core-linux-x64-musl" "1.13.1" + "@swc/core-win32-arm64-msvc" "1.13.1" + "@swc/core-win32-ia32-msvc" "1.13.1" + "@swc/core-win32-x64-msvc" "1.13.1" "@swc/counter@^0.1.3": version "0.1.3" - resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== "@swc/helpers@0.5.5": version "0.5.5" - resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== dependencies: "@swc/counter" "^0.1.3" tslib "^2.4.0" "@swc/helpers@^0.5.12": - version "0.5.15" - resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7" - integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== dependencies: tslib "^2.8.0" -"@swc/types@^0.1.17": - version "0.1.17" - resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz#bd1d94e73497f27341bf141abdf4c85230d41e7c" - integrity sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ== +"@swc/types@^0.1.23": + version "0.1.23" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.23.tgz#7eabf88b9cfd929253859c562ae95982ee04b4e8" + integrity sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw== dependencies: "@swc/counter" "^0.1.3" @@ -2537,7 +1904,7 @@ "@tailwindcss/typography@^0.5.9": version "0.5.16" - resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz#a926c8f44d5c439b2915e231cad80058850047c6" + resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.16.tgz#a926c8f44d5c439b2915e231cad80058850047c6" integrity sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA== dependencies: lodash.castarray "^4.4.0" @@ -2553,25 +1920,25 @@ "@tanstack/table-core" "8.21.3" "@tanstack/react-virtual@^3.0.0-beta.60": - version "3.13.0" - resolved "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.0.tgz#f50bccdfbb792cb11fdc0342fd3ec6945c730389" - integrity sha512-CchF0NlLIowiM2GxtsoKBkXA4uqSnY2KvnXo+kyUFD4a4ll6+J0qzoRsUPMwXV/H26lRsxgJIr/YmjYum2oEjg== + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz#d372dc2783739cc04ec1a728ca8203937687a819" + integrity sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA== dependencies: - "@tanstack/virtual-core" "3.13.0" + "@tanstack/virtual-core" "3.13.12" "@tanstack/table-core@8.21.3": version "8.21.3" resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.21.3.tgz#2977727d8fc8dfa079112d9f4d4c019110f1732c" integrity sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg== -"@tanstack/virtual-core@3.13.0": - version "3.13.0" - resolved "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.0.tgz#8db0ccc9d6c32b6393551a6d19c87dbb259a8828" - integrity sha512-NBKJP3OIdmZY3COJdWkSonr50FMVIi+aj5ZJ7hI/DTpEKg2RMfo/KvP8A3B/zOSpMgIe52B5E2yn7rryULzA6g== +"@tanstack/virtual-core@3.13.12": + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz#1dff176df9cc8f93c78c5e46bcea11079b397578" + integrity sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA== "@testing-library/dom@10.4.0": version "10.4.0" - resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== dependencies: "@babel/code-frame" "^7.10.4" @@ -2585,7 +1952,7 @@ "@testing-library/jest-dom@6.5.0": version "6.5.0" - resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz#50484da3f80fb222a853479f618a9ce5c47bfe54" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz#50484da3f80fb222a853479f618a9ce5c47bfe54" integrity sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA== dependencies: "@adobe/css-tools" "^4.4.0" @@ -2598,201 +1965,190 @@ "@testing-library/user-event@14.5.2": version "14.5.2" - resolved "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ== -"@tiptap/core@2.10.4": - version "2.10.4" - resolved "https://registry.npmjs.org/@tiptap/core/-/core-2.10.4.tgz#0b3ad822d71f5834b281590809f430e6fd41523c" - integrity sha512-fExFRTRgb6MSpg2VvR5qO2dPTQAZWuUoU4UsBCurIVcPWcyVv4FG1YzgMyoLDKy44rebFtwUGJbfU9NzX7Q/bA== +"@tiptap/core@^2.22.3", "@tiptap/core@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.26.1.tgz#8f97c223629972221d4175e4779f6ee955c41a37" + integrity sha512-fymyd/XZvYiHjBoLt1gxs024xP/LY26d43R1vluYq7AHBL/7DE3ywzy+1GEsGyAv5Je2L0KBhNIR/izbq3Kaqg== -"@tiptap/core@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/core/-/core-2.11.5.tgz#2bf1b08c4ca2467778d0a109634c45ab475522f4" - integrity sha512-jb0KTdUJaJY53JaN7ooY3XAxHQNoMYti/H6ANo707PsLXVeEqJ9o8+eBup1JU5CuwzrgnDc2dECt2WIGX9f8Jw== +"@tiptap/extension-blockquote@^2.22.3", "@tiptap/extension-blockquote@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.26.1.tgz#8ad2b3c119ff22430432ef46c852c135c156d63b" + integrity sha512-viQ6AHRhjCYYipKK6ZepBzwZpkuMvO9yhRHeUZDvlSOAh8rvsUTSre0y74nu8QRYUt4a44lJJ6BpphJK7bEgYA== -"@tiptap/extension-blockquote@2.10.4": - version "2.10.4" - resolved "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.10.4.tgz#0f9a26740009fc7430fabc423077c369feaebb42" - integrity sha512-4JSwAM3B92YWvGzu/Vd5rovPrCGwLSaSLD5rxcLyfxLSrTDQd3n7lp78pzVgGhunVECzaGF5A0ByWWpEyS0a3w== +"@tiptap/extension-bold@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.26.1.tgz#1218b847d360d69b6fc9e30596991bc53bc8fb98" + integrity sha512-zCce9PRuTNhadFir71luLo99HERDpGJ0EEflGm7RN8I1SnNi9gD5ooK42BOIQtejGCJqg3hTPZiYDJC2hXvckQ== -"@tiptap/extension-blockquote@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.11.5.tgz#d43ae78f5eba7de1b9138820502e950bae83c31c" - integrity sha512-MZfcRIzKRD8/J1hkt/eYv49060GTL6qGR3NY/oTDuw2wYzbQXXLEbjk8hxAtjwNn7G+pWQv3L+PKFzZDxibLuA== - -"@tiptap/extension-bold@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.11.5.tgz#7fc13d835067fbee4ff2be83a694f5200ba50e41" - integrity sha512-OAq03MHEbl7MtYCUzGuwb0VpOPnM0k5ekMbEaRILFU5ZC7cEAQ36XmPIw1dQayrcuE8GZL35BKub2qtRxyC9iA== - -"@tiptap/extension-bubble-menu@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.11.5.tgz#75da9bcea2a6579cd3ad41cf82f7bc7369c1816d" - integrity sha512-rx+rMd7EEdht5EHLWldpkzJ56SWYA9799b33ustePqhXd6linnokJCzBqY13AfZ9+xp3RsR6C0ZHI9GGea0tIA== +"@tiptap/extension-bubble-menu@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.26.1.tgz#7d78abb95bfc96468b40819ec00e2770ddcf63ad" + integrity sha512-oHevUcZbTMFOTpdCEo4YEDe044MB4P1ZrWyML8CGe5tnnKdlI9BN03AXpI1mEEa5CA3H1/eEckXx8EiCgYwQ3Q== dependencies: tippy.js "^6.3.7" -"@tiptap/extension-bullet-list@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.11.5.tgz#84c6bf623c5dffcd73dd24d012c9636191031d43" - integrity sha512-VXwHlX6A/T6FAspnyjbKDO0TQ+oetXuat6RY1/JxbXphH42nLuBaGWJ6pgy6xMl6XY8/9oPkTNrfJw/8/eeRwA== +"@tiptap/extension-bullet-list@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.26.1.tgz#b92170ca5d0b3404599799277fd73a124e81d093" + integrity sha512-HHakuV4ckYCDOnBbne088FvCEP4YICw+wgPBz/V2dfpiFYQ4WzT0LPK9s7OFMCN+ROraoug+1ryN1Z1KdIgujQ== -"@tiptap/extension-character-count@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-character-count/-/extension-character-count-2.11.0.tgz#7d3992ceba72f1eeb2db3a1fc997c50dddd7cf8c" - integrity sha512-WbqVr1QY62vxpmDJP5k3bwyzoHha1sZTs0xj3L+4s1j/SB2A7tAlFdcNPPwfbPOINHQgomSAyClfTyd4Gor7HA== +"@tiptap/extension-character-count@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-character-count/-/extension-character-count-2.26.1.tgz#f053ba6c0ac82dd02ffe3fddcb645da4d49fa9ea" + integrity sha512-F7LP1a9GF28thbApowWT2I41baqX74HMUTrV9LGrNXaOkW2gxZz+CDOzfHsbHyfuwfIxIjv07Qf/HKA6Cc1qbA== -"@tiptap/extension-code-block@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.11.5.tgz#b90cea403884630f3f86c7629815250e8a266802" - integrity sha512-ksxMMvqLDlC+ftcQLynqZMdlJT1iHYZorXsXw/n+wuRd7YElkRkd6YWUX/Pq/njFY6lDjKiqFLEXBJB8nrzzBA== +"@tiptap/extension-code-block@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.26.1.tgz#dd6f9ec59440844f8e0ab0b33a75ff8ab6b6669f" + integrity sha512-/TDDOwONl0qEUc4+B6V9NnWtSjz95eg7/8uCb8Y8iRbGvI9vT4/znRKofFxstvKmW4URu/H74/g0ywV57h0B+A== -"@tiptap/extension-code@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.11.5.tgz#a550c544804e65507ab66dc8ab89a1e2f7d9228d" - integrity sha512-xOvHevNIQIcCCVn9tpvXa1wBp0wHN/2umbAZGTVzS+AQtM7BTo0tz8IyzwxkcZJaImONcUVYLOLzt2AgW1LltA== +"@tiptap/extension-code@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.26.1.tgz#ed289955423da20faa6ef4c81472835ac5fe1574" + integrity sha512-GU9deB1A/Tr4FMPu71CvlcjGKwRhGYz60wQ8m4aM+ELZcVIcZRa1ebR8bExRIEWnvRztQuyRiCQzw2N0xQJ1QQ== -"@tiptap/extension-collaboration@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-2.11.0.tgz#21ac1c8bc2ca6d8ba2a838e63457528627294888" - integrity sha512-pS3E//ODD80PwVXp7zOqek0q9z5AtZ6sMSK5nPneNioe7dSvCeQzToOD9V6EevK4KChUIN9wEryK8mkQs57ioA== +"@tiptap/extension-collaboration@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-collaboration/-/extension-collaboration-2.26.1.tgz#7dccd127e5356d72337dad8d71be11c3265e2d27" + integrity sha512-ozCrGW5IAzi/18Ngdi0v/Q175D7J3ZGoTffDDyPxnTK/oksfROajoe+ZIEgoDGXPeI/I7TTlTONuqQ6LZT5r7Q== -"@tiptap/extension-document@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.11.5.tgz#1d650d232df46cf07b83e0a5cc64db1c70057f37" - integrity sha512-7I4BRTpIux2a0O2qS3BDmyZ5LGp3pszKbix32CmeVh7lN9dV7W5reDqtJJ9FCZEEF+pZ6e1/DQA362dflwZw2g== +"@tiptap/extension-document@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.26.1.tgz#3e65e4833fee138e5afaed4be586d75db10cb8b6" + integrity sha512-2P2IZp1NRAE+21mRuFBiP3X2WKfZ6kUC23NJKpn8bcOamY3obYqCt0ltGPhE4eR8n8QAl2fI/3jIgjR07dC8ow== -"@tiptap/extension-dropcursor@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.11.5.tgz#a1d6fad3379551449534bdb8135da2577a8ec8fb" - integrity sha512-uIN7L3FU0904ec7FFFbndO7RQE/yiON4VzAMhNn587LFMyWO8US139HXIL4O8dpZeYwYL3d1FnDTflZl6CwLlg== +"@tiptap/extension-dropcursor@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.26.1.tgz#2eff232f3ab50816ba7182275f84f475a88b4443" + integrity sha512-JkDQU2ZYFOuT5mNYb8OiWGwD1HcjbtmX8tLNugQbToECmz9WvVPqJmn7V/q8VGpP81iEECz/IsyRmuf2kSD4uA== -"@tiptap/extension-floating-menu@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.11.5.tgz#97868901bae46e1826b9d2cfe5a4a33a446adfc1" - integrity sha512-HsMI0hV5Lwzm530Z5tBeyNCBNG38eJ3qjfdV2OHlfSf3+KOEfn6a5AUdoNaZO02LF79/8+7BaYU2drafag9cxQ== +"@tiptap/extension-emoji@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-emoji/-/extension-emoji-2.26.1.tgz#b91e913996e9967939079cb94a70a25ab80aaa8c" + integrity sha512-CtK10GF80Qr4lgJ7P6W6tVThOjpq1lh8oyoBospZ+CjD4GYcY73bdl+FP0uxhZdJsMHzaqzMP5wWQ54zHsIaIg== + dependencies: + emoji-regex "^10.4.0" + emojibase-data "^15" + is-emoji-supported "^0.0.5" + +"@tiptap/extension-floating-menu@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.26.1.tgz#4be572fa98f356d44b1817cff5cd0db819f45c01" + integrity sha512-OJF+H6qhQogVTMedAGSWuoL1RPe3LZYXONuFCVyzHnvvMpK+BP1vm180E2zDNFnn/DVA+FOrzNGpZW7YjoFH1w== dependencies: tippy.js "^6.3.7" -"@tiptap/extension-gapcursor@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.11.5.tgz#6771e387d90ef85ee834f4572627d76e303e1297" - integrity sha512-kcWa+Xq9cb6lBdiICvLReuDtz/rLjFKHWpW3jTTF3FiP3wx4H8Rs6bzVtty7uOVTfwupxZRiKICAMEU6iT0xrQ== +"@tiptap/extension-gapcursor@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.26.1.tgz#7a5ebd84d4495aa8403ececd1ace51d3ba9ab139" + integrity sha512-KOiMZc3PwJS3hR0nSq5d0TJi2jkNZkLZElcT6pCEnhRHzPH6dRMu9GM5Jj798ZRUy0T9UFcKJalFZaDxnmRnpg== -"@tiptap/extension-hard-break@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.11.5.tgz#cf9610846cb7ab0f3a8d8dc37fd1fcee6a39d72f" - integrity sha512-q9doeN+Yg9F5QNTG8pZGYfNye3tmntOwch683v0CCVCI4ldKaLZ0jG3NbBTq+mosHYdgOH2rNbIORlRRsQ+iYQ== +"@tiptap/extension-hard-break@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.26.1.tgz#70226e2b63e2252a74f6e59b5c001a4c02e0c1e5" + integrity sha512-d6uStdNKi8kjPlHAyO59M6KGWATNwhLCD7dng0NXfwGndc22fthzIk/6j9F6ltQx30huy5qQram6j3JXwNACoA== -"@tiptap/extension-heading@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.11.5.tgz#e9a54e4cbb5c9c7fc95a24cc894a16751ecd185f" - integrity sha512-x/MV53psJ9baRcZ4k4WjnCUBMt8zCX7mPlKVT+9C/o+DEs/j/qxPLs95nHeQv70chZpSwCQCt93xMmuF0kPoAg== +"@tiptap/extension-heading@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.26.1.tgz#49d1e8f2d10eb1c06bf348d7cb9d131097d65f78" + integrity sha512-KSzL8WZV3pjJG9ke4RaU70+B5UlYR2S6olNt5UCAawM+fi11mobVztiBoC19xtpSVqIXC1AmXOqUgnuSvmE4ZA== -"@tiptap/extension-history@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.11.5.tgz#c636c8da784ad25886eb617cff6b4752ac9586d1" - integrity sha512-b+wOS33Dz1azw6F1i9LFTEIJ/gUui0Jwz5ZvmVDpL2ZHBhq1Ui0/spTT+tuZOXq7Y/uCbKL8Liu4WoedIvhboQ== +"@tiptap/extension-history@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.26.1.tgz#de8e8a5ebf08cbbccb6dec11291128843a2d24e6" + integrity sha512-m6YR1gkkauIDo3PRl0gP+7Oc4n5OqDzcjVh6LvWREmZP8nmi94hfseYbqOXUb6RPHIc0JKF02eiRifT4MSd2nw== -"@tiptap/extension-horizontal-rule@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.11.5.tgz#b876f606386c51bc2ff45d4bd26267f5b104a850" - integrity sha512-3up2r1Du8/5/4ZYzTC0DjTwhgPI3dn8jhOCLu73m5F3OGvK/9whcXoeWoX103hYMnGDxBlfOje71yQuN35FL4A== +"@tiptap/extension-horizontal-rule@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.26.1.tgz#5c0c635d4444f38cb70e721d06fbe2d47a79982c" + integrity sha512-mT6baqOhs/NakgrAeDeed194E/ZJFGL692H0C7f1N7WDRaWxUu2oR0LrnRqSH5OyPjELkzu6nQnNy0+0tFGHHg== -"@tiptap/extension-image@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-2.11.0.tgz#e9611a6a032804279f9b12a483a7afe696358a3f" - integrity sha512-R+JkK5ocX35ag1c42aAw6rcb9QlLUBB0ju8A7b+8qZXN5yWKE0yO/oixYFmnZN7WSnBYtzuCVDX8cvRG+BPbgA== +"@tiptap/extension-image@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.26.1.tgz#1b71633f31a7c53c4570f94e1068ceb46fe93224" + integrity sha512-96+MaYBJebQlR/ik5W72GLUfXdEoxFs+6jsoERxbM5qEdhb7TEnodBFtWZOwgDO27kFd6rSNZuW9r5KJNtljEg== -"@tiptap/extension-italic@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.11.5.tgz#63b09c7fb41ab64681983df7be8cf6bc330c0ede" - integrity sha512-9VGfb2/LfPhQ6TjzDwuYLRvw0A6VGbaIp3F+5Mql8XVdTBHb2+rhELbyhNGiGVR78CaB/EiKb6dO9xu/tBWSYA== +"@tiptap/extension-italic@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.26.1.tgz#cd798d5e410d112f70aaea2c7eb30716f4a483c6" + integrity sha512-pOs6oU4LyGO89IrYE4jbE8ZYsPwMMIiKkYfXcfeD9NtpGNBnjeVXXF5I9ndY2ANrCAgC8k58C3/powDRf0T2yA== -"@tiptap/extension-list-item@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.11.0.tgz#15889fd8217b998bfef78cd9079c8405b5a9abcd" - integrity sha512-Jikcg0fccpM13a3hAFLtguMcpVg4eMWI8NnC0aUULD9rFhvWZQYQYQuoK3fO6vQrAQpNhsV4oa0dfSq1btu9kg== +"@tiptap/extension-list-item@^2.22.3", "@tiptap/extension-list-item@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.26.1.tgz#932e041245d3a696c943e9d4a32cdf59cb386e88" + integrity sha512-quOXckC73Luc3x+Dcm88YAEBW+Crh3x5uvtQOQtn2GEG91AshrvbnhGRiYnfvEN7UhWIS+FYI5liHFcRKSUKrQ== -"@tiptap/extension-list-item@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.11.5.tgz#6ada38dd4e6db889288242542bc0490b0908d190" - integrity sha512-Mp5RD/pbkfW1vdc6xMVxXYcta73FOwLmblQlFNn/l/E5/X1DUSA4iGhgDDH4EWO3swbs03x2f7Zka/Xoj3+WLg== +"@tiptap/extension-mention@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-mention/-/extension-mention-2.26.1.tgz#f61a77f8b3dd99b12b9aac0a9ee8041f098b3986" + integrity sha512-sBrlJ9nWjFx7oWCtt0hV192FgCBXva1zwImWbgXTCGPAjv0d5EoPymIfRgoeanAmuQjOHoKzzZnJ6bELTZhkGw== -"@tiptap/extension-mention@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.11.0.tgz#515f831975188ce33e3c0951f94a34396a3f35cd" - integrity sha512-5/Yk2rTpsoIZaNyo4f+CgsCCkQkSiNAp24HOvvCm9Dp9w1gIFm6y6dSj5RYqzEucGjOkoaBbfMcm1QxKWIj6/A== +"@tiptap/extension-ordered-list@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.26.1.tgz#81e60f4b679533b736ef0fbad4263a11e1c8465e" + integrity sha512-UHKNRxq6TBnXMGFSq91knD6QaHsyyOwLOsXMzupmKM5Su0s+CRXEjfav3qKlbb9e4m7D7S/a0aPm8nC9KIXNhQ== -"@tiptap/extension-ordered-list@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.11.5.tgz#c81e33b5bc885450d412e9ea644cc666407e0c13" - integrity sha512-Cu8KwruBNWAaEfshRQR0yOSaUKAeEwxW7UgbvF9cN/zZuKgK5uZosPCPTehIFCcRe+TBpRtZQh+06f/gNYpYYg== +"@tiptap/extension-paragraph@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.26.1.tgz#2e25f9e72fd5b4b34ca8e9e3c355303d86eae055" + integrity sha512-UezvM9VDRAVJlX1tykgHWSD1g3MKfVMWWZ+Tg+PE4+kizOwoYkRWznVPgCAxjmyHajxpCKRXgqTZkOxjJ9Kjzg== -"@tiptap/extension-paragraph@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.11.5.tgz#05575f0264a435837483831eebffc5e3af279cb1" - integrity sha512-YFBWeg7xu/sBnsDIF/+nh9Arf7R0h07VZMd0id5Ydd2Qe3c1uIZwXxeINVtH0SZozuPIQFAT8ICe9M0RxmE+TA== +"@tiptap/extension-placeholder@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.26.1.tgz#a44280063978dfa86aad71dee6cad36c3a7862a0" + integrity sha512-MBlqbkd+63btY7Qu+SqrXvWjPwooGZDsLTtl7jp52BczBl61cq9yygglt9XpM11TFMBdySgdLHBrLtQ0B7fBlw== -"@tiptap/extension-placeholder@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.11.0.tgz#a330df0bc791df82b3a84490031a8db9a68f4061" - integrity sha512-ee8vz51pW6H+1rEDMFg2FnBs2Tj5rUHlJ1JgD7Dcp3+89SVHGB3UILGfbNpAnHZvhmsTY3NcfPAcZZ80QfQFMQ== +"@tiptap/extension-strike@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.26.1.tgz#d703acfa78455021082ccbac72b41ee9ab3f8c9b" + integrity sha512-CkoRH+pAi6MgdCh7K0cVZl4N2uR4pZdabXAnFSoLZRSg6imLvEUmWHfSi1dl3Z7JOvd3a4yZ4NxerQn5MWbJ7g== -"@tiptap/extension-strike@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.11.5.tgz#94e214dcede09f6c5f99d0c58290a1d3f5db61eb" - integrity sha512-PVfUiCqrjvsLpbIoVlegSY8RlkR64F1Rr2RYmiybQfGbg+AkSZXDeO0eIrc03//4gua7D9DfIozHmAKv1KN3ow== +"@tiptap/extension-task-item@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.26.1.tgz#060535e2c0f910fca1eb7bb0aa764ca2bd4d6584" + integrity sha512-b7JNeOsBqEd1p2oQ5N6Msz9fr2o73WR1WsYDC0WhECg07Goud2gQEkwWkQaLsvfcwuS746eMJK/nrT2pVEngYA== -"@tiptap/extension-task-item@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-2.11.0.tgz#ff97f10bf39d6c27fd3f3f1ee3987d7015304c11" - integrity sha512-qu6VuRc8qF80Bwr82CItFcrKtC67LJkwpxESLEIi42zWZ5sXF/3DJEPPS/4Kk+nAc9UCBoEMFAULibPq7rRl/w== +"@tiptap/extension-task-list@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.26.1.tgz#5cb01a50368a2d38aa7b1ecc90b75b74b6fd3be4" + integrity sha512-xR4LMpMPZ6bpkZNmFvIojmNGtdGKNlKFbpvyIOgs4qhlWskbFQQVevglHjV1R8xJLic5c+byJQaAmQdQudqGng== -"@tiptap/extension-task-list@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-2.11.0.tgz#2f197a70aafc0c23163ed70aa314cc0300534cf6" - integrity sha512-+dZRjeXLXxyliFt3J7uQADxfOwi6ntyepVM+ri1rnmIaqVZUHJbUFodOc0LivI+Z5iZZ10u3TId8gehqWJHD+w== +"@tiptap/extension-text-align@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-text-align/-/extension-text-align-2.26.1.tgz#79add5084d2b9ff1c347686834f924613d6c98cb" + integrity sha512-x6mpNGELy2QtSPBoQqNgiXO9PjZoB+O2EAfXA9YRiBDSIRNOrw+7vOVpi+IgzswFmhMNgIYUVfQRud4FHUCNew== -"@tiptap/extension-text-align@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-2.11.0.tgz#b90b86ee3f6e14c9abf186cb8ab6ced20c0df14d" - integrity sha512-VRXBqO17po6ddqhoWLBa2aCX/tqHdzdKPLfjnBy1fF8hjQKbidzjMWhb4CMm31ApvJjKK/DTkM3EnyYS/XDhng== +"@tiptap/extension-text-style@^2.22.3", "@tiptap/extension-text-style@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-text-style/-/extension-text-style-2.26.1.tgz#a6be329ff881df9da37d9a8c353b2b2e7b8508b3" + integrity sha512-t9Nc/UkrbCfnSHEUi1gvUQ2ZPzvfdYFT5TExoV2DTiUCkhG6+mecT5bTVFGW3QkPmbToL+nFhGn4ZRMDD0SP3Q== -"@tiptap/extension-text-style@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.11.0.tgz#2acb6207fe6acdb5479384682846980be15caa80" - integrity sha512-vuA16wMZ6J3fboL7FObwV2f5uN9Vg0WYmqU7971vxzJyaRj9VE1eeH8Kh5fq4RgwDzc13MZGvZZV4HcE1R8o8A== +"@tiptap/extension-text@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.26.1.tgz#a51a11aa446d32b136851ce5173c89ad5ff0f57a" + integrity sha512-p2n8WVMd/2vckdJlol24acaTDIZAhI7qle5cM75bn01sOEZoFlSw6SwINOULrUCzNJsYb43qrLEibZb4j2LeQw== -"@tiptap/extension-text-style@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.11.5.tgz#f1b3882de489328203187e6256e6ee130477cfad" - integrity sha512-YUmYl0gILSd/u/ZkOmNxjNXVw+mu8fpC2f8G4I4tLODm0zCx09j9DDEJXSrM5XX72nxJQqtSQsCpNKnL0hfeEQ== +"@tiptap/extension-underline@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/extension-underline/-/extension-underline-2.26.1.tgz#79f2eced758b5432e7b2dd764bd0d4e53e8c1721" + integrity sha512-/fufv41WDMdf0a4xmFAxONoAz08TonJXX6NEoSJmuGKO59M/Y0Pz8DTK1g32Wk44kn7dyScDiPlvvndl+UOv0A== -"@tiptap/extension-text@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.11.5.tgz#10cc6ec519aac71a6841ec9bd914ded747f6ec3f" - integrity sha512-Gq1WwyhFpCbEDrLPIHt5A8aLSlf8bfz4jm417c8F/JyU0J5dtYdmx0RAxjnLw1i7ZHE7LRyqqAoS0sl7JHDNSQ== - -"@tiptap/extension-underline@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.11.0.tgz#473025d3ed01953fb2c23f8060ea90be4c231faa" - integrity sha512-DE1piq441y1+9Aj1pvvuq1dcc5B2HZ2d1SPtO4DTMjCxrhok12biTkMxxq0q1dzA5/BouLlUW6WTPpinhmrUWA== - -"@tiptap/html@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/html/-/html-2.11.0.tgz#dd0b4195a07bbdca27aa13325b8ebac41480a6a0" - integrity sha512-9+8eSeey3gm6vMtbt+uKZfkvtwsWr577lhtTeGUsoThim9zyBnbhzHc1dQw2m1RefOoPcODrnnQPvi5nvA84Cw== +"@tiptap/html@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/html/-/html-2.26.1.tgz#61c2929d3bd5f91d22b3f43448a5e6dc369f6988" + integrity sha512-93keIjciRdjgQabxntXBjW6NTrAoM+uC/u3dwoM5CJFs40cpJC+/CEPYG7SJ5Cyv8srv/OqzyjCjoz7PQGvXyA== dependencies: zeed-dom "^0.15.1" -"@tiptap/pm@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.0.tgz#c2ccb0c9b99fd5915d9390e90d3ab9e5fb408cd8" - integrity sha512-4RU6bpODkMY+ZshzdRFcuUc5jWlMW82LWXR6UOsHK/X/Mav41ZFS0Cyf+hQM6gxxTB09YFIICmGpEpULb+/CuA== +"@tiptap/pm@^2.22.3", "@tiptap/pm@^2.26.1": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/pm/-/pm-2.26.1.tgz#5e4bd79e60fe698fa12770b2845e5133b3333d06" + integrity sha512-8aF+mY/vSHbGFqyG663ds84b+vca5Lge3tHdTMTKazxCnhXR9dn2oQJMnZ78YZvdRbkPkMJJHti9h3K7u2UQvw== dependencies: - prosemirror-changeset "^2.2.1" + prosemirror-changeset "^2.3.0" prosemirror-collab "^1.3.1" prosemirror-commands "^1.6.2" prosemirror-dropcursor "^1.8.1" @@ -2806,106 +2162,89 @@ prosemirror-schema-basic "^1.2.3" prosemirror-schema-list "^1.4.1" prosemirror-state "^1.4.3" - prosemirror-tables "^1.6.1" + prosemirror-tables "^1.6.4" prosemirror-trailing-node "^3.0.0" prosemirror-transform "^1.10.2" prosemirror-view "^1.37.0" -"@tiptap/pm@^2.11.0": - version "2.11.5" - resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.5.tgz#6577e277e5a991c605a3dfcebde7c0b794d8def4" - integrity sha512-z9JFtqc5ZOsdQLd9vRnXfTCQ8v5ADAfRt9Nm7SqP6FUHII8E1hs38ACzf5xursmth/VonJYb5+73Pqxk1hGIPw== +"@tiptap/react@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-2.26.1.tgz#793d035a1decd6655f40195f58a6fd873ee65c83" + integrity sha512-Zxlwzi1iML7aELa+PyysFD2ncVo2mEcjTkhoDok9iTbMGpm1oU8hgR1i6iHrcSNQLfaRiW6M7HNhZZQPKIC9yw== dependencies: - prosemirror-changeset "^2.2.1" - prosemirror-collab "^1.3.1" - prosemirror-commands "^1.6.2" - prosemirror-dropcursor "^1.8.1" - prosemirror-gapcursor "^1.3.2" - prosemirror-history "^1.4.1" - prosemirror-inputrules "^1.4.0" - prosemirror-keymap "^1.2.2" - prosemirror-markdown "^1.13.1" - prosemirror-menu "^1.2.4" - prosemirror-model "^1.23.0" - prosemirror-schema-basic "^1.2.3" - prosemirror-schema-list "^1.4.1" - prosemirror-state "^1.4.3" - prosemirror-tables "^1.6.3" - prosemirror-trailing-node "^3.0.0" - prosemirror-transform "^1.10.2" - prosemirror-view "^1.37.0" - -"@tiptap/react@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/react/-/react-2.11.0.tgz#28b9ca64bdeb6302eaca1941ef792e3acea2e40e" - integrity sha512-AALzHbqNq/gerJpkbXmN2OXFmHAs2bQENH7rXbnH70bpxVdIfQVtvjK4dIb+cQQvAuTWZvhsISnTrFY2BesT3Q== - dependencies: - "@tiptap/extension-bubble-menu" "^2.11.0" - "@tiptap/extension-floating-menu" "^2.11.0" + "@tiptap/extension-bubble-menu" "^2.26.1" + "@tiptap/extension-floating-menu" "^2.26.1" "@types/use-sync-external-store" "^0.0.6" fast-deep-equal "^3" use-sync-external-store "^1" -"@tiptap/starter-kit@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.11.0.tgz#3b4a9ca9daaffed3abd030d4cd72e8d9d3eb0649" - integrity sha512-lrYmkeaAFiuUjN5nGnCowdjponrsR7eRmeTf/15/5oZsNrMN7t/fvPb014AqhG/anNasa0ism4CKZns3D+4pKQ== +"@tiptap/starter-kit@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.26.1.tgz#00a19c05491a51423aabe511f624567942bd2baa" + integrity sha512-oziMGCds8SVQ3s5dRpBxVdEKZAmO/O//BjZ69mhA3q4vJdR0rnfLb5fTxSeQvHiqB878HBNn76kNaJrHrV35GA== dependencies: - "@tiptap/core" "^2.11.0" - "@tiptap/extension-blockquote" "^2.11.0" - "@tiptap/extension-bold" "^2.11.0" - "@tiptap/extension-bullet-list" "^2.11.0" - "@tiptap/extension-code" "^2.11.0" - "@tiptap/extension-code-block" "^2.11.0" - "@tiptap/extension-document" "^2.11.0" - "@tiptap/extension-dropcursor" "^2.11.0" - "@tiptap/extension-gapcursor" "^2.11.0" - "@tiptap/extension-hard-break" "^2.11.0" - "@tiptap/extension-heading" "^2.11.0" - "@tiptap/extension-history" "^2.11.0" - "@tiptap/extension-horizontal-rule" "^2.11.0" - "@tiptap/extension-italic" "^2.11.0" - "@tiptap/extension-list-item" "^2.11.0" - "@tiptap/extension-ordered-list" "^2.11.0" - "@tiptap/extension-paragraph" "^2.11.0" - "@tiptap/extension-strike" "^2.11.0" - "@tiptap/extension-text" "^2.11.0" - "@tiptap/extension-text-style" "^2.11.0" - "@tiptap/pm" "^2.11.0" + "@tiptap/core" "^2.26.1" + "@tiptap/extension-blockquote" "^2.26.1" + "@tiptap/extension-bold" "^2.26.1" + "@tiptap/extension-bullet-list" "^2.26.1" + "@tiptap/extension-code" "^2.26.1" + "@tiptap/extension-code-block" "^2.26.1" + "@tiptap/extension-document" "^2.26.1" + "@tiptap/extension-dropcursor" "^2.26.1" + "@tiptap/extension-gapcursor" "^2.26.1" + "@tiptap/extension-hard-break" "^2.26.1" + "@tiptap/extension-heading" "^2.26.1" + "@tiptap/extension-history" "^2.26.1" + "@tiptap/extension-horizontal-rule" "^2.26.1" + "@tiptap/extension-italic" "^2.26.1" + "@tiptap/extension-list-item" "^2.26.1" + "@tiptap/extension-ordered-list" "^2.26.1" + "@tiptap/extension-paragraph" "^2.26.1" + "@tiptap/extension-strike" "^2.26.1" + "@tiptap/extension-text" "^2.26.1" + "@tiptap/extension-text-style" "^2.26.1" + "@tiptap/pm" "^2.26.1" -"@tiptap/suggestion@2.11.0": - version "2.11.0" - resolved "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.11.0.tgz#826140c6f1a76af2d91713dafb4b142c803eabef" - integrity sha512-f+KcczhzEEy2f7/0N/RSID+Z6NjxCX6ab26NLfWZxdaEm/J+vQ2Pqh/e5Z59vMfKiC0DJXVcO0rdv2LBh23qDw== +"@tiptap/suggestion@^2.22.3": + version "2.26.1" + resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.26.1.tgz#64b567443668ff9afb5533737f877e3604ab53ae" + integrity sha512-iNWJdQN7h01keNoVwyCsdI7ZX11YkrexZjCnutWK17Dd72s3NYVTmQXu7saftwddT4nDdlczNxAFosrt0zMhcg== "@tsconfig/node10@^1.0.7": version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== "@tsconfig/node12@^1.0.7": version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": version "1.0.3" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": version "1.0.4" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@tybys/wasm-util@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369" + integrity sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ== + dependencies: + tslib "^2.4.0" + "@types/aria-query@^5.0.1": version "5.0.4" - resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== "@types/babel__core@^7.18.0": version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: "@babel/parser" "^7.20.7" @@ -2915,141 +2254,142 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.4" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.18.0": - version "7.20.6" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + version "7.20.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" + integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== dependencies: "@babel/types" "^7.20.7" "@types/body-parser@*": - version "1.19.5" - resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + version "1.19.6" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.6.tgz#1859bebb8fd7dac9918a45d54c1971ab8b5af474" + integrity sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g== dependencies: "@types/connect" "*" "@types/node" "*" -"@types/compression@^1.7.5": - version "1.7.5" - resolved "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz#0f80efef6eb031be57b12221c4ba6bc3577808f7" - integrity sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg== +"@types/compression@1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@types/compression/-/compression-1.8.1.tgz#57cd1a5c0c585aca56124ab4daef1d254d6f5a7d" + integrity sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q== dependencies: "@types/express" "*" + "@types/node" "*" "@types/connect@*": version "3.4.38" - resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" "@types/cors@^2.8.17": - version "2.8.17" - resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" + integrity sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg== dependencies: "@types/node" "*" "@types/d3-array@^3.0.3": version "3.2.1" - resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== "@types/d3-color@*": version "3.1.3" - resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== "@types/d3-ease@^3.0.0": version "3.0.2" - resolved "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== "@types/d3-interpolate@^3.0.1": version "3.0.4" - resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== dependencies: "@types/d3-color" "*" "@types/d3-path@*": version "3.1.1" - resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz#f632b380c3aca1dba8e34aa049bcd6a4af23df8a" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.1.tgz#f632b380c3aca1dba8e34aa049bcd6a4af23df8a" integrity sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg== "@types/d3-scale@^4.0.2": version "4.0.9" - resolved "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== dependencies: "@types/d3-time" "*" "@types/d3-shape@^3.1.0": version "3.1.7" - resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555" integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg== dependencies: "@types/d3-path" "*" "@types/d3-time@*", "@types/d3-time@^3.0.0": version "3.0.4" - resolved "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== "@types/d3-timer@^3.0.0": version "3.0.2" - resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== "@types/debug@^4.0.0": version "4.1.12" - resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" "@types/doctrine@^0.0.9": version "0.0.9" - resolved "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" + resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA== "@types/dom4@^2.0.2": version "2.0.4" - resolved "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.4.tgz#427a4ce8590727aed5ce0fe39a64f175a57fdc1c" + resolved "https://registry.yarnpkg.com/@types/dom4/-/dom4-2.0.4.tgz#427a4ce8590727aed5ce0fe39a64f175a57fdc1c" integrity sha512-PD+wqNhrjWFjAlSVd18jvChZvOXB2SOwAILBmuYev5zswBats5qmzs/QFoooLKd2omj9BT05a8MeSeRmXLGY+Q== "@types/dompurify@^3.0.5": version "3.2.0" - resolved "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.2.0.tgz#56610bf3e4250df57744d61fbd95422e07dfb840" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.2.0.tgz#56610bf3e4250df57744d61fbd95422e07dfb840" integrity sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg== dependencies: dompurify "*" "@types/dotenv@^8.2.0": version "8.2.3" - resolved "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.3.tgz#c97b3c5b2e97ff3873793a000999e86cd66ff354" + resolved "https://registry.yarnpkg.com/@types/dotenv/-/dotenv-8.2.3.tgz#c97b3c5b2e97ff3873793a000999e86cd66ff354" integrity sha512-g2FXjlDX/cYuc5CiQvyU/6kkbP1JtmGzh0obW50zD7OKeILVL0NSpPWLXVfqoAGQjom2/SLLx9zHq0KXvD6mbw== dependencies: dotenv "*" "@types/eslint-scope@^3.7.7": version "3.7.7" - resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" @@ -3057,26 +2397,21 @@ "@types/eslint@*": version "9.6.1" - resolved "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6": - version "1.0.6" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== - -"@types/estree@1.0.7": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" - integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== +"@types/estree@*", "@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^5.0.0": - version "5.0.6" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz#41fec4ea20e9c7b22f024ab88a95c6bb288f51b8" - integrity sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA== + version "5.0.7" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" + integrity sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ== dependencies: "@types/node" "*" "@types/qs" "*" @@ -3085,7 +2420,7 @@ "@types/express-serve-static-core@^4.17.33": version "4.19.6" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== dependencies: "@types/node" "*" @@ -3095,7 +2430,7 @@ "@types/express-ws@^3.0.4": version "3.0.5" - resolved "https://registry.npmjs.org/@types/express-ws/-/express-ws-3.0.5.tgz#5abf3dda3acb0a339351f089c31aca708f234c7c" + resolved "https://registry.yarnpkg.com/@types/express-ws/-/express-ws-3.0.5.tgz#5abf3dda3acb0a339351f089c31aca708f234c7c" integrity sha512-lbWMjoHrm/v85j81UCmb/GNZFO3genxRYBW1Ob7rjRI+zxUBR+4tcFuOpKKsYQ1LYTYiy3356epLeYi/5zxUwA== dependencies: "@types/express" "*" @@ -3103,82 +2438,76 @@ "@types/ws" "*" "@types/express@*": - version "5.0.0" - resolved "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz#13a7d1f75295e90d19ed6e74cab3678488eaa96c" - integrity sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ== + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.3.tgz#6c4bc6acddc2e2a587142e1d8be0bce20757e956" + integrity sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^5.0.0" - "@types/qs" "*" "@types/serve-static" "*" "@types/express@^4.17.21": - version "4.17.21" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + version "4.17.23" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.23.tgz#35af3193c640bfd4d7fe77191cd0ed411a433bef" + integrity sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" "@types/qs" "*" "@types/serve-static" "*" -"@types/gensync@^1.0.0": - version "1.0.4" - resolved "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz#7122d8f0cd3bf437f9725cc95b180197190cf50b" - integrity sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA== - "@types/hast@^2.0.0": version "2.3.10" - resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== dependencies: "@types/unist" "^2" "@types/hast@^3.0.0": version "3.0.4" - resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== dependencies: "@types/unist" "*" "@types/html-minifier-terser@^6.0.0": version "6.1.0" - resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== "@types/http-errors@*": - version "2.0.4" - resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.5.tgz#5b749ab2b16ba113423feb1a64a95dcd30398472" + integrity sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg== -"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" - resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/linkify-it@^3": version "3.0.5" - resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== "@types/linkify-it@^5": version "5.0.0" - resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q== "@types/lodash@^4.14.202", "@types/lodash@^4.17.0", "@types/lodash@^4.17.1", "@types/lodash@^4.17.6": - version "4.17.15" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz#12d4af0ed17cc7600ce1f9980cec48fc17ad1e89" - integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw== + version "4.17.20" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93" + integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA== "@types/markdown-it@^13.0.7": version "13.0.9" - resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.9.tgz#df79221eae698df5b4e982c7e91128dd8e525743" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-13.0.9.tgz#df79221eae698df5b4e982c7e91128dd8e525743" integrity sha512-1XPwR0+MgXLWfTn9gCsZ55AHOKW1WN+P9vr0PaQh5aerR9LLQXUbjfEAFhjmEmyoYFWAyuN2Mqkn40MZ4ukjBw== dependencies: "@types/linkify-it" "^3" @@ -3186,7 +2515,7 @@ "@types/markdown-it@^14.0.0": version "14.1.2" - resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== dependencies: "@types/linkify-it" "^5" @@ -3194,120 +2523,157 @@ "@types/mdast@^3.0.0": version "3.0.15" - resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== dependencies: "@types/unist" "^2" "@types/mdurl@^1": version "1.0.5" - resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" integrity sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== "@types/mdurl@^2": version "2.0.0" - resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== "@types/mdx@^2.0.0": version "2.0.13" - resolved "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.13.tgz#68f6877043d377092890ff5b298152b0a21671bd" integrity sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw== "@types/mime@^1": version "1.3.5" - resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== "@types/ms@*": version "2.1.0" - resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node@*", "@types/node@^22.5.4": - version "22.13.1" - resolved "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz#a2a3fefbdeb7ba6b89f40371842162fac0934f33" - integrity sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew== +"@types/node@*": + version "24.0.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.15.tgz#f34fbc973e7d64217106e0c59ed8761e6b51381e" + integrity sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA== dependencies: - undici-types "~6.20.0" + undici-types "~7.8.0" "@types/node@18.14.1": version "18.14.1" - resolved "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz#90dad8476f1e42797c49d6f8b69aaf9f876fc69f" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.1.tgz#90dad8476f1e42797c49d6f8b69aaf9f876fc69f" integrity sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ== "@types/node@18.15.3": version "18.15.3" - resolved "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== "@types/node@18.16.1": version "18.16.1" - resolved "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz#5db121e9c5352925bb1f1b892c4ae620e3526799" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.1.tgz#5db121e9c5352925bb1f1b892c4ae620e3526799" integrity sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA== "@types/node@^20.14.9", "@types/node@^20.5.2": - version "20.17.17" - resolved "https://registry.npmjs.org/@types/node/-/node-20.17.17.tgz#5cea2af2e271313742c14f418eaf5dcfa8ae2e3a" - integrity sha512-/WndGO4kIfMicEQLTi/mDANUu/iVUhT7KboZPdEqqHQ4aTS+3qT3U5gIqWDFV+XouorjfgGqvKILJeHhuQgFYg== + version "20.19.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.9.tgz#ca9a58193fec361cc6e859d88b52261853f1f0d3" + integrity sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw== dependencies: - undici-types "~6.19.2" + undici-types "~6.21.0" + +"@types/node@^22.5.4": + version "22.16.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.16.5.tgz#cc46ac3994cd957000d0c11095a0b1dae2ea2368" + integrity sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ== + dependencies: + undici-types "~6.21.0" "@types/nprogress@^0.2.0": version "0.2.3" - resolved "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.3.tgz#b2150b054a13622fabcba12cf6f0b54c48b14287" + resolved "https://registry.yarnpkg.com/@types/nprogress/-/nprogress-0.2.3.tgz#b2150b054a13622fabcba12cf6f0b54c48b14287" integrity sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA== "@types/parse-json@^4.0.0": version "4.0.2" - resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== +"@types/pino-http@^5.8.4": + version "5.8.4" + resolved "https://registry.yarnpkg.com/@types/pino-http/-/pino-http-5.8.4.tgz#c775d527fccdde3c055f9c3ac55c0975284c70f0" + integrity sha512-UTYBQ2acmJ2eK0w58vVtgZ9RAicFFndfrnWC1w5cBTf8zwn/HEy8O+H7psc03UZgTzHmlcuX8VkPRnRDEj+FUQ== + dependencies: + "@types/pino" "6.3" + +"@types/pino-pretty@*": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/pino-pretty/-/pino-pretty-5.0.0.tgz#aa7a61cfd553b051764acfa0a49872f7a09a1722" + integrity sha512-N1uzqSzioqz8R3AkDbSJwcfDWeI3YMPNapSQQhnB2ISU4NYgUIcAh+hYT5ygqBM+klX4htpEhXMmoJv3J7GrdA== + dependencies: + pino-pretty "*" + +"@types/pino-std-serializers@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1e28b80b554c8222858e99a4e0fc77fd070e10e8" + integrity sha512-gXfUZx2xIBbFYozGms53fT0nvkacx/+62c8iTxrEqH5PkIGAQvDbXg2774VWOycMPbqn5YJBQ3BMsg4Li3dWbg== + dependencies: + pino-std-serializers "*" + +"@types/pino@6.3": + version "6.3.12" + resolved "https://registry.yarnpkg.com/@types/pino/-/pino-6.3.12.tgz#4425db6ced806109c3df957100cba9dfcd73c228" + integrity sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw== + dependencies: + "@types/node" "*" + "@types/pino-pretty" "*" + "@types/pino-std-serializers" "*" + sonic-boom "^2.1.0" + "@types/prop-types@*", "@types/prop-types@^15.0.0", "@types/prop-types@^15.7.12": - version "15.7.14" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" - integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== + version "15.7.15" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.15.tgz#e6e5a86d602beaca71ce5163fadf5f95d70931c7" + integrity sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw== "@types/qs@*": - version "6.9.18" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2" - integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA== + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== "@types/range-parser@*": version "1.2.7" - resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/react-color@^3.0.6", "@types/react-color@^3.0.9": version "3.0.13" - resolved "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.13.tgz#0f86a14ac948428bd811689706c328817661dc13" + resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.13.tgz#0f86a14ac948428bd811689706c328817661dc13" integrity sha512-2c/9FZ4ixC5T3JzN0LP5Cke2Mf0MKOP2Eh0NPDPWmuVH3NjPyhEjqNMQpN1Phr5m74egAy+p2lYNAFrX1z9Yrg== dependencies: "@types/reactcss" "*" "@types/react-dom@18.3.0": version "18.3.0" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== dependencies: "@types/react" "*" "@types/react-dom@^18.2.18": - version "18.3.5" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz#45f9f87398c5dcea085b715c58ddcf1faf65f716" - integrity sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q== + version "18.3.7" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f" + integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ== "@types/react-transition-group@^4.4.10": version "4.4.12" - resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz#b5d76568485b02a307238270bfe96cb51ee2a044" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz#b5d76568485b02a307238270bfe96cb51ee2a044" integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== -"@types/react@*", "@types/react@^18.3.11": - version "18.3.18" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" - integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== +"@types/react@*": + version "19.1.8" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.8.tgz#ff8395f2afb764597265ced15f8dddb0720ae1c3" + integrity sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g== dependencies: - "@types/prop-types" "*" csstype "^3.0.2" "@types/react@18.3.1": @@ -3318,9 +2684,17 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/react@^18.3.11": + version "18.3.23" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.23.tgz#86ae6f6b95a48c418fecdaccc8069e0fbb63696a" + integrity sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/reactcss@*": version "1.2.13" - resolved "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.13.tgz#11c7468cc96b5353f7af998a5664deae21c7af08" + resolved "https://registry.yarnpkg.com/@types/reactcss/-/reactcss-1.2.13.tgz#11c7468cc96b5353f7af998a5664deae21c7af08" integrity sha512-gi3S+aUi6kpkF5vdhUsnkwbiSEIU/BEJyD7kBy2SudWBUuKmJk8AQKE0OVcQQeEy40Azh0lV6uynxlikYIJuwg== "@types/reflect-metadata@^0.1.0": @@ -3332,26 +2706,26 @@ "@types/resolve@^1.20.2": version "1.20.6" - resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz#e6e60dad29c2c8c206c026e6dd8d6d1bdda850b8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.6.tgz#e6e60dad29c2c8c206c026e6dd8d6d1bdda850b8" integrity sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ== "@types/semver@^7.3.12", "@types/semver@^7.3.4": - version "7.5.8" - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + version "7.7.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.0.tgz#64c441bdae033b378b6eef7d0c3d77c329b9378e" + integrity sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA== "@types/send@*": - version "0.17.4" - resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + version "0.17.5" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.5.tgz#d991d4f2b16f2b1ef497131f00a9114290791e74" + integrity sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w== dependencies: "@types/mime" "^1" "@types/node" "*" "@types/serve-static@*": - version "1.15.7" - resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + version "1.15.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.8.tgz#8180c3fbe4a70e8f00b9f70b9ba7f08f35987877" + integrity sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg== dependencies: "@types/http-errors" "*" "@types/node" "*" @@ -3359,76 +2733,69 @@ "@types/triple-beam@^1.3.2": version "1.3.5" - resolved "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== "@types/trusted-types@^2.0.7": version "2.0.7" - resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== "@types/unist@*": version "3.0.3" - resolved "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== "@types/unist@^2", "@types/unist@^2.0.0": version "2.0.11" - resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== "@types/use-sync-external-store@^0.0.6": version "0.0.6" - resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" + resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== "@types/uuid@^8.3.4": version "8.3.4" - resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== "@types/uuid@^9.0.1", "@types/uuid@^9.0.8": version "9.0.8" - resolved "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== -"@types/ws@*": - version "8.5.14" - resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz#93d44b268c9127d96026cf44353725dd9b6c3c21" - integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== - dependencies: - "@types/node" "*" - -"@types/ws@^8.5.10": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.0.tgz#8a2ec491d6f0685ceaab9a9b7ff44146236993b5" - integrity sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw== +"@types/ws@*", "@types/ws@^8.5.10": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== dependencies: "@types/node" "*" "@types/zxcvbn@^4.4.4", "@types/zxcvbn@^4.4.5": version "4.4.5" - resolved "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.5.tgz#8ce8623ed7a36e3a76d1c0b539708dfb2e859bc0" + resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.5.tgz#8ce8623ed7a36e3a76d1c0b539708dfb2e859bc0" integrity sha512-FZJgC5Bxuqg7Rhsm/bx6gAruHHhDQ55r+s0JhDh8CQ16fD7NsJJ+p8YMMQDhSQoIrSmjpqqYWA96oQVMNkjRyA== "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/eslint-plugin@^8.6.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz#574a95d67660a1e4544ae131d672867a5b40abb3" - integrity sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ== + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz#332392883f936137cd6252c8eb236d298e514e70" + integrity sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.24.0" - "@typescript-eslint/type-utils" "8.24.0" - "@typescript-eslint/utils" "8.24.0" - "@typescript-eslint/visitor-keys" "8.24.0" + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/type-utils" "8.37.0" + "@typescript-eslint/utils" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" graphemer "^1.4.0" - ignore "^5.3.1" + ignore "^7.0.0" natural-compare "^1.4.0" - ts-api-utils "^2.0.1" + ts-api-utils "^2.1.0" "@typescript-eslint/eslint-plugin@^5.48.2": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: "@eslint-community/regexpp" "^4.4.0" @@ -3443,35 +2810,49 @@ tsutils "^3.21.0" "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.6.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.0.tgz#bba837f9ee125b78f459ad947ff9b61be8139085" - integrity sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA== + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.37.0.tgz#b87f6b61e25ad5cc5bbf8baf809b8da889c89804" + integrity sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA== dependencies: - "@typescript-eslint/scope-manager" "8.24.0" - "@typescript-eslint/types" "8.24.0" - "@typescript-eslint/typescript-estree" "8.24.0" - "@typescript-eslint/visitor-keys" "8.24.0" + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.37.0.tgz#0594352e32a4ac9258591b88af77b5653800cdfe" + integrity sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.37.0" + "@typescript-eslint/types" "^8.37.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz#2e34b3eb2ce768f2ffb109474174ced5417002b1" - integrity sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw== +"@typescript-eslint/scope-manager@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz#a31a3c80ca2ef4ed58de13742debb692e7d4c0a4" + integrity sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA== dependencies: - "@typescript-eslint/types" "8.24.0" - "@typescript-eslint/visitor-keys" "8.24.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" + +"@typescript-eslint/tsconfig-utils@8.37.0", "@typescript-eslint/tsconfig-utils@^8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz#47a2760d265c6125f8e7864bc5c8537cad2bd053" + integrity sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg== "@typescript-eslint/type-utils@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: "@typescript-eslint/typescript-estree" "5.62.0" @@ -3479,29 +2860,30 @@ debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/type-utils@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz#6ee3ec4db06f9e5e7b01ca6c2b5dd5843a9fd1e8" - integrity sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA== +"@typescript-eslint/type-utils@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz#2a682e4c6ff5886712dad57e9787b5e417124507" + integrity sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow== dependencies: - "@typescript-eslint/typescript-estree" "8.24.0" - "@typescript-eslint/utils" "8.24.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" + "@typescript-eslint/utils" "8.37.0" debug "^4.3.4" - ts-api-utils "^2.0.1" + ts-api-utils "^2.1.0" "@typescript-eslint/types@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.0.tgz#694e7fb18d70506c317b816de9521300b0f72c8e" - integrity sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw== +"@typescript-eslint/types@8.37.0", "@typescript-eslint/types@^8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.37.0.tgz#09517aa9625eb3c68941dde3ac8835740587b6ff" + integrity sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: "@typescript-eslint/types" "5.62.0" @@ -3512,23 +2894,25 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz#0487349be174097bb329a58273100a9629e03c6c" - integrity sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ== +"@typescript-eslint/typescript-estree@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz#a07e4574d8e6e4355a558f61323730c987f5fcbc" + integrity sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg== dependencies: - "@typescript-eslint/types" "8.24.0" - "@typescript-eslint/visitor-keys" "8.24.0" + "@typescript-eslint/project-service" "8.37.0" + "@typescript-eslint/tsconfig-utils" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" minimatch "^9.0.4" semver "^7.6.0" - ts-api-utils "^2.0.1" + ts-api-utils "^2.1.0" "@typescript-eslint/utils@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -3540,40 +2924,137 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.0.tgz#21cb1195ae79230af825bfeed59574f5cb70a749" - integrity sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ== +"@typescript-eslint/utils@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.37.0.tgz#189ea59b2709f5d898614611f091a776751ee335" + integrity sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A== dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.24.0" - "@typescript-eslint/types" "8.24.0" - "@typescript-eslint/typescript-estree" "8.24.0" + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@8.24.0": - version "8.24.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz#36ecf0b9b1d819ad88a3bd4157ab7d594cb797c9" - integrity sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg== +"@typescript-eslint/visitor-keys@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz#cdb6a6bd3e8d6dd69bd70c1bdda36e2d18737455" + integrity sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w== dependencies: - "@typescript-eslint/types" "8.24.0" - eslint-visitor-keys "^4.2.0" + "@typescript-eslint/types" "8.37.0" + eslint-visitor-keys "^4.2.1" "@ungap/structured-clone@^1.2.0": version "1.3.0" - resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + "@vitest/expect@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" integrity sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA== dependencies: "@vitest/spy" "2.0.5" @@ -3583,28 +3064,28 @@ "@vitest/pretty-format@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" integrity sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ== dependencies: tinyrainbow "^1.2.0" "@vitest/pretty-format@2.1.9": version "2.1.9" - resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz#434ff2f7611689f9ce70cd7d567eceb883653fdf" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.9.tgz#434ff2f7611689f9ce70cd7d567eceb883653fdf" integrity sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ== dependencies: tinyrainbow "^1.2.0" "@vitest/spy@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" integrity sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA== dependencies: tinyspy "^3.0.0" "@vitest/utils@2.0.5": version "2.0.5" - resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz#6f8307a4b6bc6ceb9270007f73c67c915944e926" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.0.5.tgz#6f8307a4b6bc6ceb9270007f73c67c915944e926" integrity sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ== dependencies: "@vitest/pretty-format" "2.0.5" @@ -3614,7 +3095,7 @@ "@vitest/utils@^2.1.1": version "2.1.9" - resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz#4f2486de8a54acf7ecbf2c5c24ad7994a680a6c1" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.9.tgz#4f2486de8a54acf7ecbf2c5c24ad7994a680a6c1" integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ== dependencies: "@vitest/pretty-format" "2.1.9" @@ -3623,7 +3104,7 @@ "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== dependencies: "@webassemblyjs/helper-numbers" "1.13.2" @@ -3631,22 +3112,22 @@ "@webassemblyjs/floating-point-hex-parser@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== "@webassemblyjs/helper-api-error@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== "@webassemblyjs/helper-buffer@1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== "@webassemblyjs/helper-numbers@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== dependencies: "@webassemblyjs/floating-point-hex-parser" "1.13.2" @@ -3655,12 +3136,12 @@ "@webassemblyjs/helper-wasm-bytecode@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== "@webassemblyjs/helper-wasm-section@1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3670,26 +3151,26 @@ "@webassemblyjs/ieee754@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.13.2": version "1.13.2" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== "@webassemblyjs/wasm-edit@^1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3703,7 +3184,7 @@ "@webassemblyjs/wasm-gen@1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3714,7 +3195,7 @@ "@webassemblyjs/wasm-opt@1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3724,7 +3205,7 @@ "@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3736,7 +3217,7 @@ "@webassemblyjs/wast-printer@1.14.1": version "1.14.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== dependencies: "@webassemblyjs/ast" "1.14.1" @@ -3744,78 +3225,83 @@ "@xtuc/ieee754@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" - resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== abort-controller@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== dependencies: event-target-shim "^5.0.0" abs-svg-path@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf" + resolved "https://registry.yarnpkg.com/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf" integrity sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA== accepts@~1.3.8: version "1.3.8" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: mime-types "~2.1.34" negotiator "0.6.3" +acorn-import-phases@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz#16eb850ba99a056cb7cbfe872ffb8972e18c8bd7" + integrity sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ== + acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: version "8.3.4" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.2, acorn@^8.9.0: - version "8.14.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.11.0, acorn@^8.14.0, acorn@^8.15.0, acorn@^8.4.1, acorn@^8.9.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.3" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" - integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== ajv-formats@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv-keywords@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== dependencies: fast-deep-equal "^3.1.3" ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -3825,7 +3311,7 @@ ajv@^6.12.4, ajv@^6.12.5: ajv@^8.0.0, ajv@^8.9.0: version "8.17.1" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: fast-deep-equal "^3.1.3" @@ -3835,44 +3321,44 @@ ajv@^8.0.0, ajv@^8.9.0: ansi-html-community@0.0.8: version "0.0.8" - resolved "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" ansi-styles@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== ansi-styles@^6.1.0: version "6.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== any-promise@^1.0.0: version "1.3.0" - resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -3880,41 +3366,41 @@ anymatch@~3.1.2: arg@^4.1.0: version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== arg@^5.0.2: version "5.0.2" - resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" - integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + version "1.2.6" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.6.tgz#73051c9b088114c795b1ea414e9c0fff874ffc1a" + integrity sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA== dependencies: tslib "^2.0.0" aria-query@5.3.0: version "5.3.0" - resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== dependencies: dequal "^2.0.3" aria-query@^5.0.0, aria-query@^5.3.2: version "5.3.2" - resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== dependencies: call-bound "^1.0.3" @@ -3922,29 +3408,31 @@ array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-includes@^3.1.6, array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== +array-includes@^3.1.6, array-includes@^3.1.8, array-includes@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.9.tgz#1f0ccaa08e90cdbc3eb433210f903ad0f17c3f3a" + integrity sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" + es-abstract "^1.24.0" + es-object-atoms "^1.1.1" + get-intrinsic "^1.3.0" + is-string "^1.1.1" + math-intrinsics "^1.1.0" array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array.prototype.findlast@^1.2.5: version "1.2.5" - resolved "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== dependencies: call-bind "^1.0.7" @@ -3954,21 +3442,22 @@ array.prototype.findlast@^1.2.5: es-object-atoms "^1.0.0" es-shim-unscopables "^1.0.2" -array.prototype.findlastindex@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== +array.prototype.findlastindex@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz#cfa1065c81dcb64e34557c9b81d012f6a421c564" + integrity sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" define-properties "^1.2.1" - es-abstract "^1.23.2" + es-abstract "^1.23.9" es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" + es-object-atoms "^1.1.1" + es-shim-unscopables "^1.1.0" -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== dependencies: call-bind "^1.0.8" @@ -3978,7 +3467,7 @@ array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== dependencies: call-bind "^1.0.8" @@ -3988,7 +3477,7 @@ array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: array.prototype.tosorted@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== dependencies: call-bind "^1.0.7" @@ -3999,7 +3488,7 @@ array.prototype.tosorted@^1.1.4: arraybuffer.prototype.slice@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: array-buffer-byte-length "^1.0.1" @@ -4012,54 +3501,54 @@ arraybuffer.prototype.slice@^1.0.4: assertion-error@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== ast-types-flow@^0.0.8: version "0.0.8" - resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== ast-types@^0.16.1: version "0.16.1" - resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz#7a9da1617c9081bc121faafe91711b4c8bb81da2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.16.1.tgz#7a9da1617c9081bc121faafe91711b4c8bb81da2" integrity sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg== dependencies: tslib "^2.0.1" async-function@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== async-lock@^1.3.1: version "1.4.1" - resolved "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" + resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== async@^3.2.3: version "3.2.6" - resolved "https://registry.npmjs.org/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== atomic-sleep@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== attr-accept@^2.2.4: version "2.2.5" - resolved "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" + resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== autoprefixer@10.4.14: version "10.4.14" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== dependencies: browserslist "^4.21.5" @@ -4070,184 +3559,154 @@ autoprefixer@10.4.14: postcss-value-parser "^4.2.0" autoprefixer@^10.4.14, autoprefixer@^10.4.19: - version "10.4.20" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" - integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== + version "10.4.21" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d" + integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ== dependencies: - browserslist "^4.23.3" - caniuse-lite "^1.0.30001646" + browserslist "^4.24.4" + caniuse-lite "^1.0.30001702" fraction.js "^4.3.7" normalize-range "^0.1.2" - picocolors "^1.0.1" + picocolors "^1.1.1" postcss-value-parser "^4.2.0" available-typed-arrays@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== dependencies: possible-typed-array-names "^1.0.0" axe-core@^4.10.0: - version "4.10.2" - resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" - integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== + version "4.10.3" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.3.tgz#04145965ac7894faddbac30861e5d8f11bfd14fc" + integrity sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg== -axios@^1.8.3: - version "1.8.3" - resolved "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz#9ebccd71c98651d547162a018a1a95a4b4ed4de8" - integrity sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A== +axios@1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.11.0.tgz#c2ec219e35e414c025b2095e8b8280278478fdb6" + integrity sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA== dependencies: follow-redirects "^1.15.6" - form-data "^4.0.0" + form-data "^4.0.4" proxy-from-env "^1.1.0" axobject-query@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== b4a@^1.6.4: version "1.6.7" - resolved "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4" integrity sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg== babel-plugin-macros@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== dependencies: "@babel/runtime" "^7.12.5" cosmiconfig "^7.0.0" resolve "^1.19.0" -babel-plugin-module-resolver@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz#cdeac5d4aaa3b08dd1ac23ddbf516660ed2d293e" - integrity sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg== - dependencies: - find-babel-config "^2.1.1" - glob "^9.3.3" - pkg-up "^3.1.0" - reselect "^4.1.7" - resolve "^1.22.8" - -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.12" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" - integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.3" - semver "^6.3.1" - -babel-plugin-polyfill-corejs3@^0.11.0: - version "0.11.1" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz#4e4e182f1bb37c7ba62e2af81d8dd09df31344f6" - integrity sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.3" - core-js-compat "^3.40.0" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.3" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" - integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.3" - bail@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bare-events@^2.0.0, bare-events@^2.2.0: - version "2.5.4" - resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz#16143d435e1ed9eafd1ab85f12b89b3357a41745" - integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA== +bare-events@^2.2.0, bare-events@^2.5.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.6.0.tgz#11d9506da109e363a2f3af050fbb005ccdb3ee8f" + integrity sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg== bare-fs@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.1.tgz#85844f34da819c76754d545323a8b23ed3617c76" - integrity sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg== + version "4.1.6" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.1.6.tgz#0925521e7310f65cb1f154cab264f0b647a7cdef" + integrity sha512-25RsLF33BqooOEFNdMcEhMpJy8EoR88zSMrnOQOaM3USnOK2VmaJ1uaQEwPA6AQjrv1lXChScosN6CzbwbO9OQ== dependencies: - bare-events "^2.0.0" + bare-events "^2.5.4" bare-path "^3.0.0" - bare-stream "^2.0.0" + bare-stream "^2.6.4" bare-os@^3.0.1: - version "3.4.0" - resolved "https://registry.npmjs.org/bare-os/-/bare-os-3.4.0.tgz#97be31503f3095beb232a6871f0118859832eb0c" - integrity sha512-9Ous7UlnKbe3fMi7Y+qh0DwAup6A1JkYgPnjvMDNOlmnxNRQvQ/7Nst+OnUQKzk0iAT0m9BisbDVp9gCv8+ETA== + version "3.6.1" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.1.tgz#9921f6f59edbe81afa9f56910658422c0f4858d4" + integrity sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g== bare-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== dependencies: bare-os "^3.0.1" -bare-stream@^2.0.0: +bare-stream@^2.6.4: version "2.6.5" - resolved "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz#bba8e879674c4c27f7e27805df005c15d7a2ca07" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.6.5.tgz#bba8e879674c4c27f7e27805df005c15d7a2ca07" integrity sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA== dependencies: streamx "^2.21.0" +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw== + base64-js@^1.1.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== basic-auth@~2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== dependencies: safe-buffer "5.1.2" batch-processor@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" + resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" integrity sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA== better-opn@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" + resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ== dependencies: open "^8.0.4" bidi-js@^1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" + resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== dependencies: require-from-string "^2.0.2" binary-extensions@^2.0.0: version "2.3.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== bind-event-listener@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-3.0.0.tgz#c90f9a7fcb65cac21045f810c20ef7e647a74921" + resolved "https://registry.yarnpkg.com/bind-event-listener/-/bind-event-listener-3.0.0.tgz#c90f9a7fcb65cac21045f810c20ef7e647a74921" integrity sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q== bluebird@^3.7.2: version "3.7.2" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== body-parser@1.20.3: version "1.20.3" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" @@ -4265,7 +3724,7 @@ body-parser@1.20.3: boolbase@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== brace-expansion@2.0.2, brace-expansion@^1.1.7, brace-expansion@^2.0.1: @@ -4277,48 +3736,48 @@ brace-expansion@2.0.2, brace-expansion@^1.1.7, brace-expansion@^2.0.1: braces@^3.0.3, braces@~3.0.2: version "3.0.3" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" brotli@^1.3.2: version "1.3.3" - resolved "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz#7365d8cc00f12cf765d2b2c898716bcf4b604d48" + resolved "https://registry.yarnpkg.com/brotli/-/brotli-1.3.3.tgz#7365d8cc00f12cf765d2b2c898716bcf4b604d48" integrity sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg== dependencies: base64-js "^1.1.2" browser-assert@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz#9aaa5a2a8c74685c2ae05bfe46efd606f068c200" + resolved "https://registry.yarnpkg.com/browser-assert/-/browser-assert-1.2.1.tgz#9aaa5a2a8c74685c2ae05bfe46efd606f068c200" integrity sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ== browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserslist@^4.21.5, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: - version "4.24.4" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" - integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== +browserslist@^4.21.5, browserslist@^4.24.0, browserslist@^4.24.4: + version "4.25.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111" + integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw== dependencies: - caniuse-lite "^1.0.30001688" - electron-to-chromium "^1.5.73" + caniuse-lite "^1.0.30001726" + electron-to-chromium "^1.5.173" node-releases "^2.0.19" - update-browserslist-db "^1.1.1" + update-browserslist-db "^1.1.3" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer@^6.0.3: version "6.0.3" - resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== dependencies: base64-js "^1.3.1" @@ -4333,14 +3792,14 @@ bundle-require@^5.1.0: busboy@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== dependencies: streamsearch "^1.1.0" bytes@3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cac@^6.7.14: @@ -4348,17 +3807,17 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" - integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== dependencies: es-errors "^1.3.0" function-bind "^1.1.2" call-bind@^1.0.7, call-bind@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== dependencies: call-bind-apply-helpers "^1.0.0" @@ -4366,22 +3825,22 @@ call-bind@^1.0.7, call-bind@^1.0.8: get-intrinsic "^1.2.4" set-function-length "^1.2.2" -call-bound@^1.0.2, call-bound@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" - integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== dependencies: - call-bind-apply-helpers "^1.0.1" - get-intrinsic "^1.2.6" + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camel-case@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== dependencies: pascal-case "^3.1.2" @@ -4389,17 +3848,17 @@ camel-case@^4.1.2: camelcase-css@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: - version "1.0.30001699" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz#a102cf330d153bf8c92bfb5be3cd44c0a89c8c12" - integrity sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w== +caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001726: + version "1.0.30001727" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" + integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== capital-case@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" + resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== dependencies: no-case "^3.0.4" @@ -4408,13 +3867,13 @@ capital-case@^1.0.4: case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== chai@^5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" - integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw== + version "5.2.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.1.tgz#a9502462bdc79cf90b4a0953537a9908aa638b47" + integrity sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A== dependencies: assertion-error "^2.0.1" check-error "^2.1.1" @@ -4424,7 +3883,7 @@ chai@^5.1.1: chalk@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== dependencies: ansi-styles "^4.1.0" @@ -4432,7 +3891,7 @@ chalk@^3.0.0: chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -4440,7 +3899,7 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: change-case@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== dependencies: camel-case "^4.1.2" @@ -4458,12 +3917,12 @@ change-case@^4.1.2: character-entities@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== check-error@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== chokidar@3.6.0, chokidar@^3.3.0, chokidar@^3.5.2, chokidar@^3.5.3, chokidar@^3.6.0, chokidar@^4.0.3: @@ -4482,47 +3941,47 @@ chokidar@3.6.0, chokidar@^3.3.0, chokidar@^3.5.2, chokidar@^3.5.3, chokidar@^3.6 fsevents "~2.3.2" chromatic@^11.4.0: - version "11.25.2" - resolved "https://registry.npmjs.org/chromatic/-/chromatic-11.25.2.tgz#cb93dc1332d8f6b70d97a3ef126bc6d03429d396" - integrity sha512-/9eQWn6BU1iFsop86t8Au21IksTRxwXAl7if8YHD05L2AbuMjClLWZo5cZojqrJHGKDhTqfrC2X2xE4uSm0iKw== + version "11.29.0" + resolved "https://registry.yarnpkg.com/chromatic/-/chromatic-11.29.0.tgz#da556dbd3b043e8c6a3134d1afa3bb4ad7317410" + integrity sha512-yisBlntp9hHVj19lIQdpTlcYIXuU9H/DbFuu6tyWHmj6hWT2EtukCCcxYXL78XdQt1vm2GfIrtgtKpj/Rzmo4A== chrome-trace-event@^1.0.2: version "1.0.4" - resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== cjs-module-lexer@^1.2.3: version "1.4.3" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== -class-variance-authority@^0.7.0, class-variance-authority@^0.7.1: +class-variance-authority@^0.7.1: version "0.7.1" - resolved "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz#4008a798a0e4553a781a57ac5177c9fb5d043787" + resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.1.tgz#4008a798a0e4553a781a57ac5177c9fb5d043787" integrity sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg== dependencies: clsx "^2.1.1" -classnames@^2.3.1, classnames@^2.3.2: +classnames@^2.3.1: version "2.5.1" - resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== clean-css@^5.2.2: version "5.3.3" - resolved "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== dependencies: source-map "~0.6.0" client-only@0.0.1, client-only@^0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== cliui@^8.0.1: version "8.0.1" - resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -4531,56 +3990,56 @@ cliui@^8.0.1: clone@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== clsx@^2.0.0, clsx@^2.1.0, clsx@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== cluster-key-slot@^1.1.0: version "1.1.2" - resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== cmdk@^1.0.0: - version "1.0.4" - resolved "https://registry.npmjs.org/cmdk/-/cmdk-1.0.4.tgz#cbddef6f5ade2378f85c80a0b9ad9a8a712779b5" - integrity sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.1.1.tgz#b8524272699ccaa37aaf07f36850b376bf3d58e5" + integrity sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg== dependencies: - "@radix-ui/react-dialog" "^1.1.2" + "@radix-ui/react-compose-refs" "^1.1.1" + "@radix-ui/react-dialog" "^1.1.6" "@radix-ui/react-id" "^1.1.0" - "@radix-ui/react-primitive" "^2.0.0" - use-sync-external-store "^1.2.2" + "@radix-ui/react-primitive" "^2.0.2" color-convert@^1.9.3: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.6.0, color-string@^1.9.0, color-string@^1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" @@ -4588,7 +4047,7 @@ color-string@^1.6.0, color-string@^1.9.0, color-string@^1.9.1: color@^3.1.3: version "3.2.1" - resolved "https://registry.npmjs.org/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== dependencies: color-convert "^1.9.3" @@ -4596,7 +4055,7 @@ color@^3.1.3: color@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== dependencies: color-convert "^2.0.1" @@ -4604,12 +4063,12 @@ color@^4.2.3: colorette@^2.0.10, colorette@^2.0.7: version "2.0.20" - resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colorspace@1.1.x: version "1.1.4" - resolved "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== dependencies: color "^3.1.3" @@ -4617,75 +4076,70 @@ colorspace@1.1.x: combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" comlink@^4.4.1: version "4.4.2" - resolved "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz#cbbcd82742fbebc06489c28a183eedc5c60a2bca" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.2.tgz#cbbcd82742fbebc06489c28a183eedc5c60a2bca" integrity sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g== comma-separated-tokens@^2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== commander@^2.20.0: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commander@^4.0.0: version "4.1.1" - resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^6.2.0: - version "6.2.1" - resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" - integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== - commander@^8.3.0: version "8.3.0" - resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compressible@~2.0.18: version "2.0.18" - resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== dependencies: mime-db ">= 1.43.0 < 2" -compression@^1.7.4: - version "1.8.0" - resolved "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz#09420efc96e11a0f44f3a558de59e321364180f7" - integrity sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA== +compression@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79" + integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w== dependencies: bytes "3.1.2" compressible "~2.0.18" debug "2.6.9" negotiator "~0.6.4" - on-headers "~1.0.2" + on-headers "~1.1.0" safe-buffer "5.2.1" vary "~1.1.2" compute-scroll-into-view@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz#02c3386ec531fb6a9881967388e53e8564f3e9aa" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz#02c3386ec531fb6a9881967388e53e8564f3e9aa" integrity sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw== concurrently@^9.0.1: - version "9.1.2" - resolved "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz#22d9109296961eaee773e12bfb1ce9a66bc9836c" - integrity sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ== + version "9.2.0" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.2.0.tgz#233e3892ceb0b5db9fd49e9c8c739737a7b638b5" + integrity sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ== dependencies: chalk "^4.1.2" lodash "^4.17.21" @@ -4702,7 +4156,7 @@ consola@^3.4.0: constant-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== dependencies: no-case "^3.0.4" @@ -4711,56 +4165,49 @@ constant-case@^3.0.4: constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== convert-source-map@^1.5.0: version "1.9.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== cookie@0.7.1: version "0.7.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -core-js-compat@^3.40.0: - version "3.40.0" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" - integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== - dependencies: - browserslist "^4.24.3" - core-js@^3.38.1: - version "3.40.0" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" - integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== + version "3.44.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.44.0.tgz#db4fd4fa07933c1d6898c8b112a1119a9336e959" + integrity sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw== cors@^2.8.5: version "2.8.5" - resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" @@ -4768,7 +4215,7 @@ cors@^2.8.5: cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: version "7.1.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" @@ -4779,7 +4226,7 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: create-react-class@^15.6.2: version "15.7.0" - resolved "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng== dependencies: loose-envify "^1.3.1" @@ -4787,24 +4234,24 @@ create-react-class@^15.6.2: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== crelt@^1.0.0: version "1.0.6" - resolved "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== cross-fetch@^3.1.5: version "3.2.0" - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3" integrity sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q== dependencies: node-fetch "^2.7.0" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.2, cross-spawn@^7.0.6: version "7.0.6" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" @@ -4813,12 +4260,12 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: crypto-js@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== css-loader@^6.7.1: version "6.11.0" - resolved "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== dependencies: icss-utils "^5.1.0" @@ -4832,7 +4279,7 @@ css-loader@^6.7.1: css-select@^4.1.3: version "4.3.0" - resolved "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== dependencies: boolbase "^1.0.0" @@ -4842,9 +4289,9 @@ css-select@^4.1.3: nth-check "^2.0.1" css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + version "5.2.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" + integrity sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== dependencies: boolbase "^1.0.0" css-what "^6.1.0" @@ -4854,77 +4301,77 @@ css-select@^5.1.0: css-tree@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== dependencies: mdn-data "2.0.14" source-map "^0.6.1" css-what@^6.0.1, css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + version "6.2.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.2.2.tgz#cdcc8f9b6977719fdfbd1de7aec24abf756b9dea" + integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== css.escape@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssstyle@^4.2.1: - version "4.2.1" - resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz#5142782410fea95db66fb68147714a652a7c2381" - integrity sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw== + version "4.6.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.6.0.tgz#ea18007024e3167f4f105315f3ec2d982bf48ed9" + integrity sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg== dependencies: - "@asamuzakjp/css-color" "^2.8.2" + "@asamuzakjp/css-color" "^3.2.0" rrweb-cssom "^0.8.0" csstype@^3.0.2, csstype@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== "d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: version "3.2.4" - resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== dependencies: internmap "1 - 2" "d3-color@1 - 3": version "3.1.0" - resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== d3-ease@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== "d3-format@1 - 3": version "3.1.0" - resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== "d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== dependencies: d3-color "1 - 3" d3-path@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== d3-scale@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== dependencies: d3-array "2.10.0 - 3" @@ -4935,38 +4382,38 @@ d3-scale@^4.0.2: d3-shape@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== dependencies: d3-path "^3.1.0" "d3-time-format@2 - 4": version "4.1.0" - resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== dependencies: d3-time "1 - 3" "d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== dependencies: d3-array "2 - 3" d3-timer@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== damerau-levenshtein@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== data-urls@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== dependencies: whatwg-mimetype "^4.0.0" @@ -4974,7 +4421,7 @@ data-urls@^5.0.0: data-view-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== dependencies: call-bound "^1.0.3" @@ -4983,7 +4430,7 @@ data-view-buffer@^1.0.2: data-view-byte-length@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== dependencies: call-bound "^1.0.3" @@ -4992,7 +4439,7 @@ data-view-byte-length@^1.0.2: data-view-byte-offset@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== dependencies: call-bound "^1.0.2" @@ -5006,79 +4453,72 @@ date-fns-jalali@^4.1.0-0: date-fns@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== dateformat@^4.6.3: version "4.6.3" - resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== debug@2.6.9: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.4.0: +debug@4, debug@^4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: ms "^2.1.3" +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + decimal.js-light@^2.4.1: version "2.5.1" - resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== -decimal.js@10, decimal.js@^10.4.3: - version "10.5.0" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" - integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== +decimal.js@^10.4.3, decimal.js@^10.5.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== decode-named-character-reference@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" - integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz#25c32ae6dd5e21889549d40f676030e9514cc0ed" + integrity sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q== dependencies: character-entities "^2.0.0" decompress-response@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: mimic-response "^3.1.0" dedent@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== deep-eql@^5.0.1: version "5.0.2" - resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== deep-equal@^1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761" integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg== dependencies: is-arguments "^1.1.1" @@ -5090,22 +4530,22 @@ deep-equal@^1.1.1: deep-extend@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deepmerge@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: es-define-property "^1.0.0" @@ -5114,12 +4554,12 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: define-lazy-prop@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== define-properties@^1.1.3, define-properties@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: define-data-property "^1.0.1" @@ -5128,127 +4568,127 @@ define-properties@^1.1.3, define-properties@^1.2.1: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== denque@^1.1.0: version "1.5.1" - resolved "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== denque@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== depd@2.0.0, depd@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -dependency-graph@^0.11.0: - version "0.11.0" - resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" - integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== +dependency-graph@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-1.0.0.tgz#bb5e85aec1310bc13b22dbd76e3196c4ee4c10d2" + integrity sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg== dequal@^2.0.0, dequal@^2.0.2, dequal@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== desandro-matches-selector@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz#717beed4dc13e7d8f3762f707a6d58a6774218e1" + resolved "https://registry.yarnpkg.com/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz#717beed4dc13e7d8f3762f707a6d58a6774218e1" integrity sha512-+1q0nXhdzg1IpIJdMKalUwvvskeKnYyEe3shPRwedNcWtnhEKT3ZxvFjzywHDeGcKViIxTCAoOYQWP1qD7VNyg== destroy@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^2.0.0, detect-libc@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" - integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8" + integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA== detect-node-es@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== devlop@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== dependencies: dequal "^2.0.0" dfa@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz#96ac3204e2d29c49ea5b57af8d92c2ae12790657" + resolved "https://registry.yarnpkg.com/dfa/-/dfa-1.2.0.tgz#96ac3204e2d29c49ea5b57af8d92c2ae12790657" integrity sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q== didyoumean@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== diff@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== diff@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" dlv@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" dom-accessibility-api@^0.5.9: version "0.5.16" - resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== dom-accessibility-api@^0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== dom-converter@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== dependencies: utila "~0.4" dom-helpers@^5.0.1: version "5.2.1" - resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== dependencies: "@babel/runtime" "^7.8.7" @@ -5256,7 +4696,7 @@ dom-helpers@^5.0.1: dom-serializer@^1.0.1: version "1.4.1" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" @@ -5265,7 +4705,7 @@ dom-serializer@^1.0.1: dom-serializer@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== dependencies: domelementtype "^2.3.0" @@ -5274,38 +4714,38 @@ dom-serializer@^2.0.0: dom4@^2.1.5: version "2.1.6" - resolved "https://registry.npmjs.org/dom4/-/dom4-2.1.6.tgz#c90df07134aa0dbd81ed4d6ba1237b36fc164770" + resolved "https://registry.yarnpkg.com/dom4/-/dom4-2.1.6.tgz#c90df07134aa0dbd81ed4d6ba1237b36fc164770" integrity sha512-JkCVGnN4ofKGbjf5Uvc8mmxaATIErKQKSgACdBXpsQ3fY6DlIpAyWfiBSrGkttATssbDCp3psiAKWXk5gmjycA== domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: version "4.3.1" - resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" - resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== dependencies: domelementtype "^2.3.0" -dompurify@*, dompurify@^3.0.11, dompurify@^3.2.3: - version "3.2.4" - resolved "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz#af5a5a11407524431456cf18836c55d13441cd8e" - integrity sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg== +dompurify@*, dompurify@^3.0.11, dompurify@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.6.tgz#ca040a6ad2b88e2a92dc45f38c79f84a714a1cad" + integrity sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ== optionalDependencies: "@types/trusted-types" "^2.0.7" domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" - resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== dependencies: dom-serializer "^1.0.1" @@ -5314,7 +4754,7 @@ domutils@^2.5.2, domutils@^2.8.0: domutils@^3.0.1: version "3.2.2" - resolved "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== dependencies: dom-serializer "^2.0.0" @@ -5323,25 +4763,30 @@ domutils@^3.0.1: dot-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== dependencies: no-case "^3.0.4" tslib "^2.0.3" -dotenv@*, dotenv@^16.0.3, dotenv@^16.3.1, dotenv@^16.4.5: - version "16.4.7" - resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" - integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== +dotenv@*: + version "17.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.0.tgz#e19678fdabcf86d4bfdb6764a758d7d44efbb6a2" + integrity sha512-Q4sgBT60gzd0BB0lSyYD3xM4YxrXA9y4uBDof1JNYGzOXrQdQ6yX+7XIAqoFOGQFOTK1D3Hts5OllpxMDZFONQ== dotenv@16.0.3: version "16.0.3" - resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== +dotenv@^16.0.3, dotenv@^16.3.1, dotenv@^16.4.5: + version "16.6.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" + integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== + dunder-proto@^1.0.0, dunder-proto@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== dependencies: call-bind-apply-helpers "^1.0.1" @@ -5350,130 +4795,140 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1: eastasianwidth@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.73: - version "1.5.97" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.97.tgz#5c4a4744c79e7c85b187adf5160264ac130c776f" - integrity sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ== +electron-to-chromium@^1.5.173: + version "1.5.187" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz#8c58854e065962351dc87e95614dd78d50425966" + integrity sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA== element-resize-detector@^1.1.9: version "1.2.4" - resolved "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" + resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" integrity sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg== dependencies: batch-processor "1.0.0" emoji-picker-react@^4.5.16: - version "4.12.0" - resolved "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.12.0.tgz#4cc310ad4b8a39844a2d5edcc92967683d6b5138" - integrity sha512-q2c8UcZH0eRIMj41bj0k1akTjk69tsu+E7EzkW7giN66iltF6H9LQvQvw6ugscsxdC+1lmt3WZpQkkY65J95tg== + version "4.13.2" + resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-4.13.2.tgz#cf2a669ae902c982b9f0b4bddc78f7cdbe6ff384" + integrity sha512-azaJQLTshEOZVhksgU136izJWJyZ4Clx6xQ6Vctzk1gOdPPAUbTa/JYDwZJ8rh97QxnjpyeftXl99eRlYr3vNA== dependencies: flairup "1.0.0" -emoji-regex@^10.3.0: +emoji-regex@^10.3.0, emoji-regex@^10.4.0: version "10.4.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.2.2: version "9.2.2" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +emojibase-data@^15: + version "15.3.2" + resolved "https://registry.yarnpkg.com/emojibase-data/-/emojibase-data-15.3.2.tgz#2742246bfe14f16a7829b42ca156dec09934cf85" + integrity sha512-TpDyTDDTdqWIJixV5sTA6OQ0P0JfIIeK2tFRR3q56G9LK65ylAZ7z3KyBXokpvTTJ+mLUXQXbLNyVkjvnTLE+A== + enabled@2.0.x: version "2.0.0" - resolved "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== encodeurl@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== dependencies: once "^1.4.0" endent@^2.0.1: version "2.1.0" - resolved "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz#5aaba698fb569e5e18e69e1ff7a28ff35373cd88" + resolved "https://registry.yarnpkg.com/endent/-/endent-2.1.0.tgz#5aaba698fb569e5e18e69e1ff7a28ff35373cd88" integrity sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w== dependencies: dedent "^0.7.0" fast-json-parse "^1.0.3" objectorarray "^1.0.5" -enhanced-resolve@^5.15.0, enhanced-resolve@^5.17.1: - version "5.18.1" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf" - integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== +enhanced-resolve@^5.17.2: + version "5.18.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz#7903c5b32ffd4b2143eeb4b92472bd68effd5464" + integrity sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" entities@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: +entities@^4.2.0, entities@^4.4.0: version "4.5.0" - resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== entities@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/entities/-/entities-5.0.0.tgz#b2ab51fe40d995817979ec79dd621154c3c0f62b" + resolved "https://registry.yarnpkg.com/entities/-/entities-5.0.0.tgz#b2ab51fe40d995817979ec79dd621154c3c0f62b" integrity sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA== +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: - version "1.23.9" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" - integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" + integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== dependencies: array-buffer-byte-length "^1.0.2" arraybuffer.prototype.slice "^1.0.4" available-typed-arrays "^1.0.7" call-bind "^1.0.8" - call-bound "^1.0.3" + call-bound "^1.0.4" data-view-buffer "^1.0.2" data-view-byte-length "^1.0.2" data-view-byte-offset "^1.0.1" es-define-property "^1.0.1" es-errors "^1.3.0" - es-object-atoms "^1.0.0" + es-object-atoms "^1.1.1" es-set-tostringtag "^2.1.0" es-to-primitive "^1.3.0" function.prototype.name "^1.1.8" - get-intrinsic "^1.2.7" - get-proto "^1.0.0" + get-intrinsic "^1.3.0" + get-proto "^1.0.1" get-symbol-description "^1.1.0" globalthis "^1.0.4" gopd "^1.2.0" @@ -5485,21 +4940,24 @@ es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23 is-array-buffer "^3.0.5" is-callable "^1.2.7" is-data-view "^1.0.2" + is-negative-zero "^2.0.3" is-regex "^1.2.1" + is-set "^2.0.3" is-shared-array-buffer "^1.0.4" is-string "^1.1.1" is-typed-array "^1.1.15" - is-weakref "^1.1.0" + is-weakref "^1.1.1" math-intrinsics "^1.1.0" - object-inspect "^1.13.3" + object-inspect "^1.13.4" object-keys "^1.1.1" object.assign "^4.1.7" own-keys "^1.0.1" - regexp.prototype.flags "^1.5.3" + regexp.prototype.flags "^1.5.4" safe-array-concat "^1.1.3" safe-push-apply "^1.0.0" safe-regex-test "^1.1.0" set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" string.prototype.trim "^1.2.10" string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" @@ -5508,21 +4966,21 @@ es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23 typed-array-byte-offset "^1.0.4" typed-array-length "^1.0.7" unbox-primitive "^1.1.0" - which-typed-array "^1.1.18" + which-typed-array "^1.1.19" es-define-property@^1.0.0, es-define-property@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== es-errors@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== es-iterator-helpers@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== dependencies: call-bind "^1.0.8" @@ -5543,20 +5001,20 @@ es-iterator-helpers@^1.2.1: safe-array-concat "^1.1.3" es-module-lexer@^1.2.1, es-module-lexer@^1.5.0: - version "1.6.0" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21" - integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== -es-object-atoms@^1.0.0: +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== dependencies: es-errors "^1.3.0" es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== dependencies: es-errors "^1.3.0" @@ -5564,16 +5022,16 @@ es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: has-tostringtag "^1.0.2" hasown "^2.0.2" -es-shim-unscopables@^1.0.2: +es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== dependencies: hasown "^2.0.2" es-to-primitive@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: is-callable "^1.2.7" @@ -5582,14 +5040,14 @@ es-to-primitive@^1.3.0: esbuild-register@^3.5.0: version "3.6.0" - resolved "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz#cf270cfa677baebbc0010ac024b823cbf723a36d" + resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-3.6.0.tgz#cf270cfa677baebbc0010ac024b823cbf723a36d" integrity sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg== dependencies: debug "^4.3.4" -esbuild@0.25.0, "esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", esbuild@^0.25.0: +esbuild@0.25.0, "esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", esbuild@^0.25.0: version "0.25.0" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw== optionalDependencies: "@esbuild/aix-ppc64" "0.25.0" @@ -5620,25 +5078,25 @@ esbuild@0.25.0, "esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-config-next@^14.1.0: - version "14.2.24" - resolved "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.24.tgz#da232b0c7f768c0d5c11e1cab9df20351cf3f602" - integrity sha512-9r1ujK++Pgpfixr5+DQ6rXDIQmSzuDbBlAQYMkJRMz9KWqovX7ESUTC0EAyBfOCl3ubkoeplw+aoXDuih3A8fw== + version "14.2.30" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.30.tgz#3a2be44099c6fbda60ba5c97098dd5f534bb18c7" + integrity sha512-4pTMb3wfpI+piVeEz3TWG1spjuXJJBZaYabi2H08z2ZTk6/N304POEovHdFmK6EZb4QlKpETulBNaRIITA0+xg== dependencies: - "@next/eslint-plugin-next" "14.2.24" + "@next/eslint-plugin-next" "14.2.30" "@rushstack/eslint-patch" "^1.3.3" "@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" @@ -5650,20 +5108,20 @@ eslint-config-next@^14.1.0: eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" eslint-config-prettier@^9.1.0: - version "9.1.0" - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" - integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + version "9.1.2" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz#90deb4fa0259592df774b600dbd1d2249a78ce91" + integrity sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ== eslint-config-turbo@^1.12.4: version "1.13.4" - resolved "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-1.13.4.tgz#9c06f10c4e5d971d317baee8695fbdda24b92804" + resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-1.13.4.tgz#9c06f10c4e5d971d317baee8695fbdda24b92804" integrity sha512-+we4eWdZlmlEn7LnhXHCIPX/wtujbHCS7XjQM/TN09BHNEl2fZ8id4rHfdfUKIYTSKyy8U/nNyJ0DNoZj5Q8bw== dependencies: eslint-plugin-turbo "1.13.4" eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" - resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" @@ -5671,54 +5129,53 @@ eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: resolve "^1.22.4" eslint-import-resolver-typescript@^3.5.2: - version "3.7.0" - resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz#e69925936a771a9cb2de418ccebc4cdf6c0818aa" - integrity sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow== + version "3.10.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz#23dac32efa86a88e2b8232eb244ac499ad636db2" + integrity sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ== dependencies: "@nolyfill/is-core-module" "1.0.39" - debug "^4.3.7" - enhanced-resolve "^5.15.0" - fast-glob "^3.3.2" - get-tsconfig "^4.7.5" - is-bun-module "^1.0.2" - is-glob "^4.0.3" - stable-hash "^0.0.4" + debug "^4.4.0" + get-tsconfig "^4.10.0" + is-bun-module "^2.0.0" + stable-hash "^0.0.5" + tinyglobby "^0.2.13" + unrs-resolver "^1.6.2" -eslint-module-utils@^2.12.0: - version "2.12.0" - resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" - integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== +eslint-module-utils@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz#f76d3220bfb83c057651359295ab5854eaad75ff" + integrity sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw== dependencies: debug "^3.2.7" eslint-plugin-import@^2.28.1, eslint-plugin-import@^2.29.1: - version "2.31.0" - resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" - integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== + version "2.32.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz#602b55faa6e4caeaa5e970c198b5c00a37708980" + integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA== dependencies: "@rtsao/scc" "^1.1.0" - array-includes "^3.1.8" - array.prototype.findlastindex "^1.2.5" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" + array-includes "^3.1.9" + array.prototype.findlastindex "^1.2.6" + array.prototype.flat "^1.3.3" + array.prototype.flatmap "^1.3.3" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.12.0" + eslint-module-utils "^2.12.1" hasown "^2.0.2" - is-core-module "^2.15.1" + is-core-module "^2.16.1" is-glob "^4.0.3" minimatch "^3.1.2" object.fromentries "^2.0.8" object.groupby "^1.0.3" - object.values "^1.2.0" + object.values "^1.2.1" semver "^6.3.1" - string.prototype.trimend "^1.0.8" + string.prototype.trimend "^1.0.9" tsconfig-paths "^3.15.0" eslint-plugin-jsx-a11y@^6.7.1: version "6.10.2" - resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== dependencies: aria-query "^5.3.2" @@ -5739,7 +5196,7 @@ eslint-plugin-jsx-a11y@^6.7.1: "eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": version "5.0.0-canary-7118f5dd7-20230705" - resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz#4d55c50e186f1a2b0636433d2b0b2f592ddbccfd" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz#4d55c50e186f1a2b0636433d2b0b2f592ddbccfd" integrity sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw== eslint-plugin-react-hooks@^5.2.0: @@ -5748,9 +5205,9 @@ eslint-plugin-react-hooks@^5.2.0: integrity sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg== eslint-plugin-react@^7.33.2: - version "7.37.4" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz#1b6c80b6175b6ae4b26055ae4d55d04c414c7181" - integrity sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ== + version "7.37.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz#2975511472bdda1b272b34d779335c9b0e877065" + integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== dependencies: array-includes "^3.1.8" array.prototype.findlast "^1.2.5" @@ -5762,7 +5219,7 @@ eslint-plugin-react@^7.33.2: hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.8" + object.entries "^1.1.9" object.fromentries "^2.0.8" object.values "^1.2.1" prop-types "^15.8.1" @@ -5773,14 +5230,14 @@ eslint-plugin-react@^7.33.2: eslint-plugin-turbo@1.13.4: version "1.13.4" - resolved "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-1.13.4.tgz#d237d51a33ccdf54d3be8e300f8052342a16e85c" + resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-1.13.4.tgz#d237d51a33ccdf54d3be8e300f8052342a16e85c" integrity sha512-82GfMzrewI/DJB92Bbch239GWbGx4j1zvjk1lqb06lxIlMPnVwUHVwPbAnLfyLG3JuhLv9whxGkO/q1CL18JTg== dependencies: dotenv "16.0.3" eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -5788,7 +5245,7 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: eslint-scope@^7.2.2: version "7.2.2" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" @@ -5796,17 +5253,17 @@ eslint-scope@^7.2.2: eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" - integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== eslint@8.57.1: version "8.57.1" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -5850,7 +5307,7 @@ eslint@8.57.1: espree@^9.6.0, espree@^9.6.1: version "9.6.1" - resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: acorn "^8.9.0" @@ -5859,73 +5316,73 @@ espree@^9.6.0, espree@^9.6.1: esprima@~4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.2: version "1.6.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== estree-walker@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== dependencies: "@types/estree" "^1.0.0" esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== ev-emitter@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz#8f18b0ce5c76a5d18017f71c0a795c65b9138f2a" + resolved "https://registry.yarnpkg.com/ev-emitter/-/ev-emitter-1.1.1.tgz#8f18b0ce5c76a5d18017f71c0a795c65b9138f2a" integrity sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q== event-target-shim@^5.0.0: version "5.0.1" - resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== eventemitter3@^4.0.1: version "4.0.7" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.2.0, events@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== expand-template@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== export-to-csv@^1.4.0: @@ -5935,14 +5392,14 @@ export-to-csv@^1.4.0: express-ws@^5.0.2: version "5.0.2" - resolved "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz#5b02d41b937d05199c6c266d7cc931c823bda8eb" + resolved "https://registry.yarnpkg.com/express-ws/-/express-ws-5.0.2.tgz#5b02d41b937d05199c6c266d7cc931c823bda8eb" integrity sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ== dependencies: ws "^7.4.6" express@^4.21.2: version "4.21.2" - resolved "https://registry.npmjs.org/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== dependencies: accepts "~1.3.8" @@ -5979,32 +5436,32 @@ express@^4.21.2: extend@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== fast-copy@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== fast-deep-equal@^3, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-equals@^5.0.1: version "5.2.2" - resolved "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz#885d7bfb079fac0ce0e8450374bce29e9b742484" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.2.2.tgz#885d7bfb079fac0ce0e8450374bce29e9b742484" integrity sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw== fast-fifo@^1.2.0, fast-fifo@^1.3.2: version "1.3.2" - resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9, fast-glob@^3.3.2, fast-glob@^3.3.3: +fast-glob@^3.2.9, fast-glob@^3.3.2: version "3.3.3" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -6015,99 +5472,99 @@ fast-glob@^3.2.9, fast-glob@^3.3.2, fast-glob@^3.3.3: fast-json-parse@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-redact@^3.1.1: version "3.5.0" - resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== fast-safe-stringify@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fast-uri@^3.0.1: version "3.0.6" - resolved "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== fastq@^1.6.0: - version "1.19.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" - integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== dependencies: reusify "^1.0.4" fault@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" + resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c" integrity sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ== dependencies: format "^0.2.0" fdir@^6.4.4: - version "6.4.4" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" - integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== + version "6.4.6" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== fecha@^4.2.0: version "4.2.3" - resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== fflate@^0.4.8: version "0.4.8" - resolved "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" file-selector@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== dependencies: tslib "^2.7.0" file-stream-rotator@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz#007019e735b262bb6c6f0197e58e5c87cb96cec3" + resolved "https://registry.yarnpkg.com/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz#007019e735b262bb6c6f0197e58e5c87cb96cec3" integrity sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ== dependencies: moment "^2.29.1" filesize@^10.0.12: version "10.1.6" - resolved "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361" integrity sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w== fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" finalhandler@1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" @@ -6118,16 +5575,9 @@ finalhandler@1.3.1: statuses "2.0.1" unpipe "~1.0.0" -find-babel-config@^2.1.1: - version "2.1.2" - resolved "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.2.tgz#2841b1bfbbbcdb971e1e39df8cbc43dafa901716" - integrity sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg== - dependencies: - json5 "^2.2.3" - find-cache-dir@^3.3.1: version "3.3.2" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== dependencies: commondir "^1.0.1" @@ -6136,19 +5586,12 @@ find-cache-dir@^3.3.1: find-root@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -6156,7 +5599,7 @@ find-up@^4.0.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -6164,19 +5607,19 @@ find-up@^5.0.0: fizzy-ui-utils@^2.0.0: version "2.0.7" - resolved "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz#7df45dcc4eb374a08b65d39bb9a4beedf7330505" + resolved "https://registry.yarnpkg.com/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz#7df45dcc4eb374a08b65d39bb9a4beedf7330505" integrity sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg== dependencies: desandro-matches-selector "^2.0.0" flairup@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz#d3af0052ad02734c12d2446608a869498adb351b" + resolved "https://registry.yarnpkg.com/flairup/-/flairup-1.0.0.tgz#d3af0052ad02734c12d2446608a869498adb351b" integrity sha512-IKlE+pNvL2R+kVL1kEhUYqRxVqeFnjiIvHWDMLFXNaqyUdFXQM2wte44EfMYJNHkW16X991t2Zg8apKkhv7OBA== flat-cache@^3.0.4: version "3.2.0" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: flatted "^3.2.9" @@ -6184,28 +5627,28 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.2.9: - version "3.3.2" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" - integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== fn.name@1.x.x: version "1.1.0" - resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== follow-redirects@^1.15.6: version "1.15.9" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== fontfaceobserver@2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.1.0.tgz#e2705d293e2c585a6531c2a722905657317a2991" + resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.1.0.tgz#e2705d293e2c585a6531c2a722905657317a2991" integrity sha512-ReOsO2F66jUa0jmv2nlM/s1MiutJx/srhAe2+TE8dJCMi02ZZOcCTxTCQFr3Yet+uODUtnr4Mewg+tNQ+4V1Ng== fontkit@^2.0.2: version "2.0.4" - resolved "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz#4765d664c68b49b5d6feb6bd1051ee49d8ec5ab0" + resolved "https://registry.yarnpkg.com/fontkit/-/fontkit-2.0.4.tgz#4765d664c68b49b5d6feb6bd1051ee49d8ec5ab0" integrity sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g== dependencies: "@swc/helpers" "^0.5.12" @@ -6218,24 +5661,24 @@ fontkit@^2.0.2: unicode-properties "^1.4.0" unicode-trie "^2.0.0" -for-each@^0.3.3: +for-each@^0.3.3, for-each@^0.3.5: version "0.3.5" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== dependencies: is-callable "^1.2.7" foreground-child@^3.1.0: - version "3.3.0" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" - integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: - cross-spawn "^7.0.0" + cross-spawn "^7.0.6" signal-exit "^4.0.1" fork-ts-checker-webpack-plugin@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz#dae45dfe7298aa5d553e2580096ced79b6179504" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz#dae45dfe7298aa5d553e2580096ced79b6179504" integrity sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg== dependencies: "@babel/code-frame" "^7.16.7" @@ -6251,38 +5694,40 @@ fork-ts-checker-webpack-plugin@^8.0.0: semver "^7.3.5" tapable "^2.2.1" -form-data@^4.0.0, form-data@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== +form-data@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" + integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" mime-types "^2.1.12" format@^0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== forwarded@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fraction.js@^4.2.0, fraction.js@^4.3.7: version "4.3.7" - resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== fresh@0.5.2: version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-extra@^10.0.0: version "10.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" @@ -6291,7 +5736,7 @@ fs-extra@^10.0.0: fs-extra@^11.0.0: version "11.3.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== dependencies: graceful-fs "^4.2.0" @@ -6299,33 +5744,28 @@ fs-extra@^11.0.0: universalify "^2.0.0" fs-monkey@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" - integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== - -fs-readdir-recursive@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.1.0.tgz#632aa15a20e71828ed56b24303363fb1414e5997" + integrity sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: version "1.1.8" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: call-bind "^1.0.8" @@ -6337,30 +5777,30 @@ function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044" - integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== dependencies: - call-bind-apply-helpers "^1.0.1" + call-bind-apply-helpers "^1.0.2" es-define-property "^1.0.1" es-errors "^1.3.0" - es-object-atoms "^1.0.0" + es-object-atoms "^1.1.1" function-bind "^1.1.2" - get-proto "^1.0.0" + get-proto "^1.0.1" gopd "^1.2.0" has-symbols "^1.1.0" hasown "^2.0.2" @@ -6368,12 +5808,12 @@ get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@ get-nonce@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== get-proto@^1.0.0, get-proto@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== dependencies: dunder-proto "^1.0.1" @@ -6381,57 +5821,52 @@ get-proto@^1.0.0, get-proto@^1.0.1: get-size@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/get-size/-/get-size-2.0.3.tgz#54a1d0256b20ea7ac646516756202769941ad2ef" + resolved "https://registry.yarnpkg.com/get-size/-/get-size-2.0.3.tgz#54a1d0256b20ea7ac646516756202769941ad2ef" integrity sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q== -get-stdin@^9.0.0: - version "9.0.0" - resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" - integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA== - get-symbol-description@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== dependencies: call-bound "^1.0.3" es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-tsconfig@^4.7.5: - version "4.10.0" - resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz#403a682b373a823612475a4c2928c7326fc0f6bb" - integrity sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A== +get-tsconfig@^4.10.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" + integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== dependencies: resolve-pkg-maps "^1.0.0" github-from-package@0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob-to-regexp@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@10.3.10: version "10.3.10" - resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== dependencies: foreground-child "^3.1.0" @@ -6442,7 +5877,7 @@ glob@10.3.10: glob@^10.3.10: version "10.4.5" - resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" @@ -6452,9 +5887,9 @@ glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" -glob@^7.1.3, glob@^7.2.0: +glob@^7.1.3: version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -6464,31 +5899,16 @@ glob@^7.1.3, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^9.3.3: - version "9.3.5" - resolved "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" - integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== - dependencies: - fs.realpath "^1.0.0" - minimatch "^8.0.2" - minipass "^4.2.4" - path-scurry "^1.6.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.19.0: version "13.24.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" globalthis@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== dependencies: define-properties "^1.2.1" @@ -6496,7 +5916,7 @@ globalthis@^1.0.4: globby@^11.1.0: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -6506,99 +5926,87 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^14.0.0: - version "14.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz#138b78e77cf5a8d794e327b15dce80bf1fb0a73e" - integrity sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA== - dependencies: - "@sindresorhus/merge-streams" "^2.1.0" - fast-glob "^3.3.3" - ignore "^7.0.3" - path-type "^6.0.0" - slash "^5.1.0" - unicorn-magic "^0.3.0" - gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== gud@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== has-bigints@^1.0.2: version "1.1.0" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: es-define-property "^1.0.0" has-proto@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== dependencies: dunder-proto "^1.0.0" has-symbols@^1.0.3, has-symbols@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== has-tostringtag@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" hasown@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" hast-util-whitespace@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557" integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng== he@1.2.0, he@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== header-case@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== dependencies: capital-case "^1.0.4" @@ -6606,58 +6014,58 @@ header-case@^2.0.4: helmet@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz#8b2dcc425b4a46c88f6953481b40453cbe66b167" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.2.0.tgz#8b2dcc425b4a46c88f6953481b40453cbe66b167" integrity sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw== help-me@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== highlight.js@^11.8.0, highlight.js@~11.11.0: version "11.11.1" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz#fca06fa0e5aeecf6c4d437239135fabc15213585" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.11.1.tgz#fca06fa0e5aeecf6c4d437239135fabc15213585" integrity sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w== highlight.js@~11.8.0: version "11.8.0" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== hoist-non-react-statics@^3.3.1: version "3.3.2" - resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" hsl-to-hex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz#c58c826dc6d2f1e0a5ff1da5a7ecbf03faac1352" + resolved "https://registry.yarnpkg.com/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz#c58c826dc6d2f1e0a5ff1da5a7ecbf03faac1352" integrity sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA== dependencies: hsl-to-rgb-for-reals "^1.1.0" hsl-to-rgb-for-reals@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz#e1eb23f6b78016e3722431df68197e6dcdc016d9" + resolved "https://registry.yarnpkg.com/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz#e1eb23f6b78016e3722431df68197e6dcdc016d9" integrity sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg== html-encoding-sniffer@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== dependencies: whatwg-encoding "^3.1.1" html-entities@^2.1.0: - version "2.5.2" - resolved "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" - integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + version "2.6.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.6.0.tgz#7c64f1ea3b36818ccae3d3fb48b6974208e984f8" + integrity sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ== html-minifier-terser@^6.0.2: version "6.1.0" - resolved "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== dependencies: camel-case "^4.1.2" @@ -6670,7 +6078,7 @@ html-minifier-terser@^6.0.2: html-webpack-plugin@^5.5.0: version "5.6.3" - resolved "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz#a31145f0fee4184d53a794f9513147df1e653685" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz#a31145f0fee4184d53a794f9513147df1e653685" integrity sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg== dependencies: "@types/html-minifier-terser" "^6.0.0" @@ -6681,7 +6089,7 @@ html-webpack-plugin@^5.5.0: htmlparser2@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== dependencies: domelementtype "^2.0.1" @@ -6691,7 +6099,7 @@ htmlparser2@^6.1.0: http-errors@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -6702,7 +6110,7 @@ http-errors@2.0.0: http-proxy-agent@^7.0.2: version "7.0.2" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== dependencies: agent-base "^7.1.0" @@ -6710,7 +6118,7 @@ http-proxy-agent@^7.0.2: https-proxy-agent@^7.0.6: version "7.0.6" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== dependencies: agent-base "^7.1.2" @@ -6718,58 +6126,58 @@ https-proxy-agent@^7.0.6: hyphen@^1.6.4: version "1.10.6" - resolved "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz#0e779d280e696102b97d7e42f5ca5de2cc97e274" + resolved "https://registry.yarnpkg.com/hyphen/-/hyphen-1.10.6.tgz#0e779d280e696102b97d7e42f5ca5de2cc97e274" integrity sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw== iconv-lite@0.4.24: version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== ieee754@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore-by-default@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== -ignore@^5.2.0, ignore@^5.3.1: +ignore@^5.2.0: version "5.3.2" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -ignore@^7.0.3: - version "7.0.3" - resolved "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz#397ef9315dfe0595671eefe8b633fec6943ab733" - integrity sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA== +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== imagesloaded@^4.0.0: version "4.1.4" - resolved "https://registry.npmjs.org/imagesloaded/-/imagesloaded-4.1.4.tgz#1376efcd162bb768c34c3727ac89cc04051f3cc7" + resolved "https://registry.yarnpkg.com/imagesloaded/-/imagesloaded-4.1.4.tgz#1376efcd162bb768c34c3727ac89cc04051f3cc7" integrity sha512-ltiBVcYpc/TYTF5nolkMNsnREHW+ICvfQ3Yla2Sgr71YFwQ86bDwV9hgpFhFtrGPuwEx5+LqOHIrdXBdoWwwsA== dependencies: ev-emitter "^1.0.0" import-fresh@^3.2.1: version "3.3.1" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" @@ -6777,17 +6185,17 @@ import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -6795,22 +6203,22 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ini@~1.3.0: version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== inline-style-parser@0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== internal-slot@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== dependencies: es-errors "^1.3.0" @@ -6819,24 +6227,25 @@ internal-slot@^1.1.0: "internmap@1 - 2": version "2.0.3" - resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== intl-messageformat@^10.7.11: - version "10.7.15" - resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.15.tgz#5cdc62139ef39ece1b083db32dae4d1c9fa5b627" - integrity sha512-LRyExsEsefQSBjU2p47oAheoKz+EOJxSLDdjOaEjdriajfHsMXOmV/EhMvYSg9bAgCUHasuAC+mcUBe/95PfIg== + version "10.7.16" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.16.tgz#d909f9f9f4ab857fbe681d559b958dd4dd9f665a" + integrity sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug== dependencies: - "@formatjs/ecma402-abstract" "2.3.3" - "@formatjs/fast-memoize" "2.2.6" - "@formatjs/icu-messageformat-parser" "2.11.1" - tslib "2" + "@formatjs/ecma402-abstract" "2.3.4" + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/icu-messageformat-parser" "2.11.2" + tslib "^2.8.0" ioredis@^4.28.2: - version "4.28.5" - resolved "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f" - integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A== + version "4.30.0" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.30.0.tgz#023277fcbeddd2dba3c101ef45f26c3f1de98a92" + integrity sha512-P9F4Eo6zicYsIJbEy/mPJmSxKY0rVcmiy5H8oXPxPDotQRCvCBjBuI5QWoQQanVE9jdeocnum5iqYAHl4pHdLA== dependencies: + "@ioredis/commands" "^1.0.2" cluster-key-slot "^1.1.0" debug "^4.3.1" denque "^1.1.0" @@ -6844,15 +6253,14 @@ ioredis@^4.28.2: lodash.flatten "^4.4.0" lodash.isarguments "^3.1.0" p-map "^2.1.0" - redis-commands "1.7.0" redis-errors "^1.2.0" redis-parser "^3.0.0" standard-as-callback "^2.1.0" ioredis@^5.4.1: - version "5.5.0" - resolved "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz#ff2332e125ca2ac8e15472ddd14ecdffa6484a2a" - integrity sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw== + version "5.6.1" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.6.1.tgz#1ed7dc9131081e77342503425afceaf7357ae599" + integrity sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA== dependencies: "@ioredis/commands" "^1.1.1" cluster-key-slot "^1.1.0" @@ -6866,12 +6274,12 @@ ioredis@^5.4.1: ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== dependencies: call-bound "^1.0.2" @@ -6879,7 +6287,7 @@ is-arguments@^1.0.4, is-arguments@^1.1.1: is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: version "3.0.5" - resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: call-bind "^1.0.8" @@ -6888,17 +6296,17 @@ is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-arrayish@^0.3.1: version "0.3.2" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== is-async-function@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== dependencies: async-function "^1.0.0" @@ -6909,21 +6317,21 @@ is-async-function@^2.0.0: is-bigint@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== dependencies: has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.2.1: version "1.2.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== dependencies: call-bound "^1.0.3" @@ -6931,31 +6339,31 @@ is-boolean-object@^1.2.1: is-buffer@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-bun-module@^1.0.2: - version "1.3.0" - resolved "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz#ea4d24fdebfcecc98e81bcbcb506827fee288760" - integrity sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA== +is-bun-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-2.0.0.tgz#4d7859a87c0fcac950c95e666730e745eae8bddd" + integrity sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ== dependencies: - semver "^7.6.3" + semver "^7.7.1" is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.16.0: +is-core-module@^2.13.0, is-core-module@^2.16.0, is-core-module@^2.16.1: version "2.16.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: hasown "^2.0.2" is-data-view@^1.0.1, is-data-view@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== dependencies: call-bound "^1.0.2" @@ -6964,7 +6372,7 @@ is-data-view@^1.0.1, is-data-view@^1.0.2: is-date-object@^1.0.5, is-date-object@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== dependencies: call-bound "^1.0.2" @@ -6972,29 +6380,34 @@ is-date-object@^1.0.5, is-date-object@^1.1.0: is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" - resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-emoji-supported@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/is-emoji-supported/-/is-emoji-supported-0.0.5.tgz#f22301b22c63d6322935e829f39dfa59d03a7fe2" + integrity sha512-WOlXUhDDHxYqcSmFZis+xWhhqXiK2SU0iYiqmth5Ip0FHLZQAt9rKL5ahnilE8/86WH8tZ3bmNNNC+bTzamqlw== + is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finalizationregistry@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== dependencies: call-bound "^1.0.3" is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-function@^1.0.10, is-generator-function@^1.0.7: version "1.1.0" - resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== dependencies: call-bound "^1.0.3" @@ -7004,19 +6417,24 @@ is-generator-function@^1.0.10, is-generator-function@^1.0.7: is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-map@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + is-number-object@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: call-bound "^1.0.3" @@ -7024,27 +6442,27 @@ is-number-object@^1.1.1: is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-path-inside@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-plain-obj@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== is-regex@^1.1.4, is-regex@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== dependencies: call-bound "^1.0.2" @@ -7054,24 +6472,24 @@ is-regex@^1.1.4, is-regex@^1.2.1: is-set@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== is-shared-array-buffer@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.7, is-string@^1.1.1: +is-string@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: call-bound "^1.0.3" @@ -7079,7 +6497,7 @@ is-string@^1.0.7, is-string@^1.1.1: is-symbol@^1.0.4, is-symbol@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: call-bound "^1.0.2" @@ -7088,31 +6506,31 @@ is-symbol@^1.0.4, is-symbol@^1.1.1: is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15, is-typed-array@^1.1.3: version "1.1.15" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: which-typed-array "^1.1.16" is-url@^1.2.4: version "1.2.4" - resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== is-weakmap@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== -is-weakref@^1.0.2, is-weakref@^1.1.0: +is-weakref@^1.0.2, is-weakref@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== dependencies: call-bound "^1.0.3" is-weakset@^2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== dependencies: call-bound "^1.0.3" @@ -7120,37 +6538,37 @@ is-weakset@^2.0.3: is-wsl@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" isarray@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isomorphic-dompurify@^2.12.0, isomorphic-dompurify@^2.16.0: - version "2.21.0" - resolved "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-2.21.0.tgz#57369b409bd72a67c111d065eae412610725588b" - integrity sha512-IjBG/D6ApEiO6ciXvrzPqbE4xOLbjRTshSWRSeeycQVhvsxf1O9PhA7LoqwMYS0/2PKLNFJRugwsNV5UihtLxQ== + version "2.26.0" + resolved "https://registry.yarnpkg.com/isomorphic-dompurify/-/isomorphic-dompurify-2.26.0.tgz#ea6201953d38488445171443393855fa700ea906" + integrity sha512-nZmoK4wKdzPs5USq4JHBiimjdKSVAOm2T1KyDoadtMPNXYHxiENd19ou4iU/V4juFM6LVgYQnpxCYmxqNP4Obw== dependencies: - dompurify "^3.2.3" - jsdom "^26.0.0" + dompurify "^3.2.6" + jsdom "^26.1.0" isomorphic.js@^0.2.4: version "0.2.5" - resolved "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88" + resolved "https://registry.yarnpkg.com/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88" integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw== iterator.prototype@^1.1.4: version "1.1.5" - resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== dependencies: define-data-property "^1.1.4" @@ -7162,7 +6580,7 @@ iterator.prototype@^1.1.4: jackspeak@^2.3.5: version "2.3.6" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== dependencies: "@isaacs/cliui" "^8.0.2" @@ -7171,23 +6589,23 @@ jackspeak@^2.3.5: jackspeak@^3.1.2: version "3.4.3" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jay-peg@^1.0.2: +jay-peg@^1.0.2, jay-peg@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz#fdf410b89fa7a295bf74424ffe4c9083dbe7c363" + resolved "https://registry.yarnpkg.com/jay-peg/-/jay-peg-1.1.1.tgz#fdf410b89fa7a295bf74424ffe4c9083dbe7c363" integrity sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww== dependencies: restructure "^3.0.0" jest-worker@^27.4.5: version "27.5.1" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" @@ -7196,40 +6614,39 @@ jest-worker@^27.4.5: jiti@^1.21.6: version "1.21.7" - resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== joycon@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsdoc-type-pratt-parser@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz#ff6b4a3f339c34a6c188cbf50a16087858d22113" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz#ff6b4a3f339c34a6c188cbf50a16087858d22113" integrity sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg== -jsdom@^26.0.0: - version "26.0.0" - resolved "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz#446dd1ad8cfc50df7e714e58f1f972c1763b354c" - integrity sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw== +jsdom@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-26.1.0.tgz#ab5f1c1cafc04bd878725490974ea5e8bf0c72b3" + integrity sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg== dependencies: cssstyle "^4.2.1" data-urls "^5.0.0" - decimal.js "^10.4.3" - form-data "^4.0.1" + decimal.js "^10.5.0" html-encoding-sniffer "^4.0.0" http-proxy-agent "^7.0.2" https-proxy-agent "^7.0.6" @@ -7239,65 +6656,60 @@ jsdom@^26.0.0: rrweb-cssom "^0.8.0" saxes "^6.0.0" symbol-tree "^3.2.4" - tough-cookie "^5.0.0" + tough-cookie "^5.1.1" w3c-xmlserializer "^5.0.0" webidl-conversions "^7.0.0" whatwg-encoding "^3.1.1" whatwg-mimetype "^4.0.0" - whatwg-url "^14.1.0" + whatwg-url "^14.1.1" ws "^8.18.0" xml-name-validator "^5.0.0" jsesc@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== -jsesc@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" json5@^2.2.2, json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^6.0.1, jsonfile@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -7306,7 +6718,7 @@ jsonfile@^6.0.1, jsonfile@^6.1.0: "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: array-includes "^3.1.6" @@ -7316,162 +6728,162 @@ jsonfile@^6.0.1, jsonfile@^6.1.0: jsx-dom-cjs@^8.0.3: version "8.1.6" - resolved "https://registry.npmjs.org/jsx-dom-cjs/-/jsx-dom-cjs-8.1.6.tgz#37ac60189fd0a99b63d0c2bb99f57fc563992b25" + resolved "https://registry.yarnpkg.com/jsx-dom-cjs/-/jsx-dom-cjs-8.1.6.tgz#37ac60189fd0a99b63d0c2bb99f57fc563992b25" integrity sha512-aeGqlIZ3IBKF2+B0cKXZGh10OHxxABuHD9tlS10suXDXXG0c4wMkJios9xVslduflSNEQJVlicME3EBCYgxGvA== dependencies: csstype "^3.1.3" keyv@^4.5.3: version "4.5.4" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" kleur@^4.0.3, kleur@^4.1.4: version "4.1.5" - resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== kuler@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== language-subtag-registry@^0.3.20: version "0.3.23" - resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== language-tags@^1.0.9: version "1.0.9" - resolved "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== dependencies: language-subtag-registry "^0.3.20" levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" -lib0@^0.2.42, lib0@^0.2.47, lib0@^0.2.74, lib0@^0.2.85, lib0@^0.2.87, lib0@^0.2.99: - version "0.2.99" - resolved "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz#80d715dbd75496dabe0a1f5061fbb4ea162d2532" - integrity sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w== +lib0@^0.2.109, lib0@^0.2.47, lib0@^0.2.74, lib0@^0.2.85, lib0@^0.2.87, lib0@^0.2.99: + version "0.2.114" + resolved "https://registry.yarnpkg.com/lib0/-/lib0-0.2.114.tgz#0b0e55c3ffa8768fe3d9efca971059f465db4baf" + integrity sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ== dependencies: isomorphic.js "^0.2.4" lilconfig@^3.0.0, lilconfig@^3.1.1, lilconfig@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== +linebreak@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-1.1.0.tgz#831cf378d98bced381d8ab118f852bd50d81e46b" + integrity sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ== + dependencies: + base64-js "0.0.8" + unicode-trie "^2.0.0" + lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== linkify-it@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== dependencies: uc.micro "^2.0.0" linkifyjs@^4.1.3: - version "4.2.0" - resolved "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.2.0.tgz#9dd30222b9cbabec9c950e725ec00031c7fa3f08" - integrity sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw== + version "4.3.1" + resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.3.1.tgz#1f246ebf4be040002accd1f4535b6af7c7e37898" + integrity sha512-DRSlB9DKVW04c4SUdGvKK5FR6be45lTU9M76JnngqPeeGDqPwYc0zdUErtsNVMtxPXgUWV4HbXbnC4sNyBxkYg== load-tsconfig@^0.2.3: version "0.2.5" - resolved "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" + resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== loader-runner@^4.2.0: version "4.3.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash-es@^4.17.15: version "4.17.21" - resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== lodash.castarray@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" + resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q== lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.defaults@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.flatten@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== lodash.isarguments@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== lodash.isplainobject@^4.0.6: version "4.0.6" - resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash.sortby@^4.7.0: version "4.7.0" - resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== logform@^2.7.0: version "2.7.0" - resolved "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== dependencies: "@colors/colors" "1.6.0" @@ -7483,26 +6895,26 @@ logform@^2.7.0: loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" loupe@^3.1.0, loupe@^3.1.1, loupe@^3.1.2: - version "3.1.3" - resolved "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2" - integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== + version "3.1.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.4.tgz#784a0060545cb38778ffb19ccde44d7870d5fdd9" + integrity sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg== lower-case@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== dependencies: tslib "^2.0.3" lowlight@^2.9.0: version "2.9.0" - resolved "https://registry.npmjs.org/lowlight/-/lowlight-2.9.0.tgz#70da647a4319c7bfd8e97721a679b13ef5621496" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-2.9.0.tgz#70da647a4319c7bfd8e97721a679b13ef5621496" integrity sha512-OpcaUTCLmHuVuBcyNckKfH5B0oA4JUavb/M/8n9iAvanJYNQkrVm4pvyX0SUaqkBG4dnWHKt7p50B3ngAG2Rfw== dependencies: "@types/hast" "^2.0.0" @@ -7511,7 +6923,7 @@ lowlight@^2.9.0: lowlight@^3.0.0: version "3.3.0" - resolved "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz#007b8a5bfcfd27cc65b96246d2de3e9dd4e23c6c" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-3.3.0.tgz#007b8a5bfcfd27cc65b96246d2de3e9dd4e23c6c" integrity sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ== dependencies: "@types/hast" "^3.0.0" @@ -7520,66 +6932,58 @@ lowlight@^3.0.0: lru-cache@^10.2.0, lru-cache@^10.4.3: version "10.4.3" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lucide-react@^0.469.0: version "0.469.0" - resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz#f16936ca6521482fef754a7eabb310e6c68e1482" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.469.0.tgz#f16936ca6521482fef754a7eabb310e6c68e1482" integrity sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw== lz-string@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== magic-string@^0.30.5: version "0.30.17" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" -make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - make-dir@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" make-error@^1.1.1: version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== map-or-similar@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" + resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== markdown-it-task-lists@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz#f68f4d2ac2bad5a2c373ba93081a1a6848417088" + resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz#f68f4d2ac2bad5a2c373ba93081a1a6848417088" integrity sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA== markdown-it@^14.0.0, markdown-it@^14.1.0: version "14.1.0" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== dependencies: argparse "^2.0.1" @@ -7591,7 +6995,7 @@ markdown-it@^14.0.0, markdown-it@^14.1.0: masonry-layout@^4.2.0: version "4.2.2" - resolved "https://registry.npmjs.org/masonry-layout/-/masonry-layout-4.2.2.tgz#d57b44af13e601bfcdc423f1dd8348b5524de348" + resolved "https://registry.yarnpkg.com/masonry-layout/-/masonry-layout-4.2.2.tgz#d57b44af13e601bfcdc423f1dd8348b5524de348" integrity sha512-iGtAlrpHNyxaR19CvKC3npnEcAwszXoyJiI8ARV2ePi7fmYhIud25MHK8Zx4P0LCC4d3TNO9+rFa1KoK1OEOaA== dependencies: get-size "^2.0.2" @@ -7599,17 +7003,17 @@ masonry-layout@^4.2.0: material-colors@^1.2.1: version "1.2.6" - resolved "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" + resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== math-intrinsics@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== mdast-util-definitions@^5.0.0: version "5.1.2" - resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz#9910abb60ac5d7115d6819b57ae0bcef07a3f7a7" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz#9910abb60ac5d7115d6819b57ae0bcef07a3f7a7" integrity sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA== dependencies: "@types/mdast" "^3.0.0" @@ -7618,7 +7022,7 @@ mdast-util-definitions@^5.0.0: mdast-util-from-markdown@^1.0.0: version "1.3.1" - resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== dependencies: "@types/mdast" "^3.0.0" @@ -7636,7 +7040,7 @@ mdast-util-from-markdown@^1.0.0: mdast-util-to-hast@^12.1.0: version "12.3.0" - resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz#045d2825fb04374e59970f5b3f279b5700f6fb49" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz#045d2825fb04374e59970f5b3f279b5700f6fb49" integrity sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw== dependencies: "@types/hast" "^2.0.0" @@ -7650,68 +7054,68 @@ mdast-util-to-hast@^12.1.0: mdast-util-to-string@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== dependencies: "@types/mdast" "^3.0.0" mdn-data@2.0.14: version "2.0.14" - resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== mdurl@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== media-engine@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz#be3188f6cd243ea2a40804a35de5a5b032f58dad" + resolved "https://registry.yarnpkg.com/media-engine/-/media-engine-1.0.3.tgz#be3188f6cd243ea2a40804a35de5a5b032f58dad" integrity sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg== media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^3.4.1, memfs@^3.4.12: version "3.6.0" - resolved "https://registry.npmjs.org/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: fs-monkey "^1.0.4" memoizerific@^1.11.3: version "1.11.3" - resolved "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" + resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" integrity sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog== dependencies: map-or-similar "^1.5.0" merge-descriptors@1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== methods@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromark-core-commonmark@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== dependencies: decode-named-character-reference "^1.0.0" @@ -7733,7 +7137,7 @@ micromark-core-commonmark@^1.0.1: micromark-factory-destination@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== dependencies: micromark-util-character "^1.0.0" @@ -7742,7 +7146,7 @@ micromark-factory-destination@^1.0.0: micromark-factory-label@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== dependencies: micromark-util-character "^1.0.0" @@ -7752,7 +7156,7 @@ micromark-factory-label@^1.0.0: micromark-factory-space@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== dependencies: micromark-util-character "^1.0.0" @@ -7760,7 +7164,7 @@ micromark-factory-space@^1.0.0: micromark-factory-title@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== dependencies: micromark-factory-space "^1.0.0" @@ -7770,7 +7174,7 @@ micromark-factory-title@^1.0.0: micromark-factory-whitespace@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== dependencies: micromark-factory-space "^1.0.0" @@ -7780,7 +7184,7 @@ micromark-factory-whitespace@^1.0.0: micromark-util-character@^1.0.0: version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== dependencies: micromark-util-symbol "^1.0.0" @@ -7788,14 +7192,14 @@ micromark-util-character@^1.0.0: micromark-util-chunked@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== dependencies: micromark-util-symbol "^1.0.0" micromark-util-classify-character@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== dependencies: micromark-util-character "^1.0.0" @@ -7804,7 +7208,7 @@ micromark-util-classify-character@^1.0.0: micromark-util-combine-extensions@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== dependencies: micromark-util-chunked "^1.0.0" @@ -7812,14 +7216,14 @@ micromark-util-combine-extensions@^1.0.0: micromark-util-decode-numeric-character-reference@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== dependencies: micromark-util-symbol "^1.0.0" micromark-util-decode-string@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== dependencies: decode-named-character-reference "^1.0.0" @@ -7829,31 +7233,31 @@ micromark-util-decode-string@^1.0.0: micromark-util-encode@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== micromark-util-html-tag-name@^1.0.0: version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== micromark-util-normalize-identifier@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== dependencies: micromark-util-symbol "^1.0.0" micromark-util-resolve-all@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== dependencies: micromark-util-types "^1.0.0" micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== dependencies: micromark-util-character "^1.0.0" @@ -7862,7 +7266,7 @@ micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: micromark-util-subtokenize@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== dependencies: micromark-util-chunked "^1.0.0" @@ -7872,17 +7276,17 @@ micromark-util-subtokenize@^1.0.0: micromark-util-symbol@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== micromark@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== dependencies: "@types/debug" "^4.0.0" @@ -7905,7 +7309,7 @@ micromark@^3.0.0: micromatch@^4.0.2, micromatch@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" @@ -7913,179 +7317,172 @@ micromatch@^4.0.2, micromatch@^4.0.8: mime-db@1.52.0: version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== "mime-db@>= 1.43.0 < 2": - version "1.53.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" - integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mimic-response@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== min-indent@^1.0.0, min-indent@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^8.0.2: - version "8.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" - integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.1, minimatch@^9.0.4: version "9.0.5" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minipass@^4.2.4: - version "4.2.8" - resolved "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" - integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== - "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" - resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== mkdirp-classic@^0.5.3: version "0.5.3" - resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== mobx-react-lite@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-4.1.0.tgz#6a03ed2d94150848213cfebd7d172e123528a972" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-4.1.0.tgz#6a03ed2d94150848213cfebd7d172e123528a972" integrity sha512-QEP10dpHHBeQNv1pks3WnHRCem2Zp636lq54M2nKO2Sarr13pL4u6diQXf65yzXUn0mkk18SyIDCm9UOJYTi1w== dependencies: use-sync-external-store "^1.4.0" mobx-react@^9.1.1: version "9.2.0" - resolved "https://registry.npmjs.org/mobx-react/-/mobx-react-9.2.0.tgz#c1e4d1ed406f6664d9de0787c948bac3a7ed5893" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-9.2.0.tgz#c1e4d1ed406f6664d9de0787c948bac3a7ed5893" integrity sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw== dependencies: mobx-react-lite "^4.1.0" mobx-utils@^6.0.8: - version "6.1.0" - resolved "https://registry.npmjs.org/mobx-utils/-/mobx-utils-6.1.0.tgz#98f749b1ede18a9f40b89b9b296bcc625b085ddf" - integrity sha512-P3qUVDFp3Kv5HXD7EIGJn3zlgJJnN+/ZpFHWQ+u6YNN1xDxY53iMvsQ9fM8kauTVdDmt7ulDgDQtDrOxb1NS9Q== + version "6.1.1" + resolved "https://registry.yarnpkg.com/mobx-utils/-/mobx-utils-6.1.1.tgz#61c66563e7646fb75462c189f4110a76d2e35768" + integrity sha512-ZR4tOKucWAHOdMjqElRl2BEvrzK7duuDdKmsbEbt2kzgVpuLuoYLiDCjc3QwWQl8CmOlxPgaZQpZ7emwNqPkIg== mobx@^6.10.0, mobx@^6.12.0: - version "6.13.6" - resolved "https://registry.npmjs.org/mobx/-/mobx-6.13.6.tgz#3b80895c7c9df456efc86ae0b6983ccea1da6cc6" - integrity sha512-r19KNV0uBN4b+ER8Z0gA4y+MzDYIQ2SvOmn3fUrqPnWXdQfakd9yfbPBDBF/p5I+bd3N5Rk1fHONIvMay+bJGA== + version "6.13.7" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.13.7.tgz#70e5dda7a45da947f773b3cd3b065dfe7c8a75de" + integrity sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g== moment@^2.29.1: version "2.30.1" - resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== -morgan@^1.10.0: - version "1.10.0" - resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" - integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== +morgan@1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.1.tgz#4e02e6a4465a48e26af540191593955d17f61570" + integrity sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A== dependencies: basic-auth "~2.0.1" debug "2.6.9" depd "~2.0.0" on-finished "~2.3.0" - on-headers "~1.0.2" + on-headers "~1.1.0" mri@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mz@^2.7.0: version "2.7.0" - resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@3.3.8, nanoid@^3.3.6, nanoid@^3.3.8: +nanoid@3.3.8, nanoid@^3.3.11, nanoid@^3.3.6: version "3.3.8" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== napi-build-utils@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== +napi-postinstall@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.2.tgz#03c62080e88b311c4d7423b0f15f0c920bbcc626" + integrity sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw== + natural-compare-lite@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== negotiator@0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== negotiator@~0.6.4: version "0.6.4" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== next-themes@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45" integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A== next@14.2.30: @@ -8113,39 +7510,39 @@ next@14.2.30: no-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== dependencies: lower-case "^2.0.2" tslib "^2.0.3" node-abi@^3.3.0: - version "3.74.0" - resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz#5bfb4424264eaeb91432d2adb9da23c63a301ed0" - integrity sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w== + version "3.75.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.75.0.tgz#2f929a91a90a0d02b325c43731314802357ed764" + integrity sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg== dependencies: semver "^7.3.5" node-abort-controller@^3.0.1: version "3.1.1" - resolved "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== node-addon-api@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== node-fetch@^2.7.0: version "2.7.0" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" node-html-parser@^6.1.13: version "6.1.13" - resolved "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz#a1df799b83df5c6743fcd92740ba14682083b7e4" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.13.tgz#a1df799b83df5c6743fcd92740ba14682083b7e4" integrity sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg== dependencies: css-select "^5.1.0" @@ -8153,13 +7550,13 @@ node-html-parser@^6.1.13: node-releases@^2.0.19: version "2.0.19" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== nodemon@^3.1.7: - version "3.1.9" - resolved "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz#df502cdc3b120e1c3c0c6e4152349019efa7387b" - integrity sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg== + version "3.1.10" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1" + integrity sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw== dependencies: chokidar "^3.5.2" debug "^4" @@ -8174,61 +7571,61 @@ nodemon@^3.1.7: normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-range@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== normalize-svg-path@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg== dependencies: svg-arc-to-cubic-bezier "^3.0.0" normalize.css@^8.0.1: version "8.0.1" - resolved "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" + resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== nprogress@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== nth-check@^2.0.1: version "2.1.1" - resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== dependencies: boolbase "^1.0.0" nwsapi@^2.2.16: - version "2.2.16" - resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz#177760bba02c351df1d2644e220c31dfec8cdb43" - integrity sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ== + version "2.2.20" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.20.tgz#22e53253c61e7b0e7e93cef42c891154bcca11ef" + integrity sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA== object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-hash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.13.3: +object-inspect@^1.13.3, object-inspect@^1.13.4: version "1.13.4" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== object-is@^1.1.5: version "1.1.6" - resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: call-bind "^1.0.7" @@ -8236,12 +7633,12 @@ object-is@^1.1.5: object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.4, object.assign@^4.1.7: version "4.1.7" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: call-bind "^1.0.8" @@ -8251,18 +7648,19 @@ object.assign@^4.1.4, object.assign@^4.1.7: has-symbols "^1.1.0" object-keys "^1.1.1" -object.entries@^1.1.8: - version "1.1.8" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== +object.entries@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.9.tgz#e4770a6a1444afb61bd39f984018b5bede25f8b3" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" define-properties "^1.2.1" - es-object-atoms "^1.0.0" + es-object-atoms "^1.1.1" object.fromentries@^2.0.8: version "2.0.8" - resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== dependencies: call-bind "^1.0.7" @@ -8272,16 +7670,16 @@ object.fromentries@^2.0.8: object.groupby@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== dependencies: call-bind "^1.0.7" define-properties "^1.2.1" es-abstract "^1.23.2" -object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: +object.values@^1.1.6, object.values@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== dependencies: call-bind "^1.0.8" @@ -8291,50 +7689,50 @@ object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: objectorarray@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" + resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== on-exit-leak-free@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== on-finished@2.4.1: version "2.4.1" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== +on-headers@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" + integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" one-time@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== dependencies: fn.name "1.x.x" open@^8.0.4: version "8.4.2" - resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: define-lazy-prop "^2.0.0" @@ -8343,7 +7741,7 @@ open@^8.0.4: optionator@^0.9.3: version "0.9.4" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" @@ -8355,12 +7753,12 @@ optionator@^0.9.3: orderedmap@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2" + resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2" integrity sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g== outlayer@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/outlayer/-/outlayer-2.1.1.tgz#29863b6de10ea5dadfffcadfa0d728907387e9a2" + resolved "https://registry.yarnpkg.com/outlayer/-/outlayer-2.1.1.tgz#29863b6de10ea5dadfffcadfa0d728907387e9a2" integrity sha512-+GplXsCQ3VrbGujAeHEzP9SXsBmJxzn/YdDSQZL0xqBmAWBmortu2Y9Gwdp9J0bgDQ8/YNIPMoBM13nTwZfAhw== dependencies: ev-emitter "^1.0.0" @@ -8369,76 +7767,69 @@ outlayer@^2.1.0: own-keys@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== dependencies: get-intrinsic "^1.2.6" object-keys "^1.1.1" safe-push-apply "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.0: +p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-map@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-json-from-dist@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== pako@^0.2.5: version "0.2.9" - resolved "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== pako@~1.0.5: version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== param-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== dependencies: dot-case "^3.0.4" @@ -8446,14 +7837,14 @@ param-case@^3.0.4: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -8463,24 +7854,24 @@ parse-json@^5.0.0: parse-svg-path@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" + resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ== parse5@^7.2.1: - version "7.2.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" - integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== + version "7.3.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== dependencies: - entities "^4.5.0" + entities "^6.0.0" parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascal-case@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== dependencies: no-case "^3.0.4" @@ -8488,45 +7879,40 @@ pascal-case@^3.1.2: path-browserify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== path-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== dependencies: dot-case "^3.0.4" tslib "^2.0.3" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1, path-scurry@^1.11.1, path-scurry@^1.6.1: +path-scurry@^1.10.1, path-scurry@^1.11.1: version "1.11.1" - resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: lru-cache "^10.2.0" @@ -8534,69 +7920,78 @@ path-scurry@^1.10.1, path-scurry@^1.11.1, path-scurry@^1.6.1: path-to-regexp@0.1.12: version "0.1.12" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path-type@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz#2f1bb6791a91ce99194caede5d6c5920ed81eb51" - integrity sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ== - pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== -picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.1: +picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== pify@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - pino-abstract-transport@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== dependencies: split2 "^4.0.0" pino-http@^10.3.0: - version "10.4.0" - resolved "https://registry.npmjs.org/pino-http/-/pino-http-10.4.0.tgz#a97911138fd5170e6da92ae8882c2a6357e84115" - integrity sha512-vjQsKBE+VN1LVchjbfLE7B6nBeGASZNRNKsR68VS0DolTm5R3zo+47JX1wjm0O96dcbvA7vnqt8YqOWlG5nN0w== + version "10.5.0" + resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-10.5.0.tgz#6a4fd8df93a181fc89f7f89979b8a2146aad29f2" + integrity sha512-hD91XjgaKkSsdn8P7LaebrNzhGTdB086W3pyPihX0EzGPjq5uBJBXo4N5guqNaK6mUjg9aubMF7wDViYek9dRA== dependencies: get-caller-file "^2.0.5" pino "^9.0.0" pino-std-serializers "^7.0.0" - process-warning "^4.0.0" + process-warning "^5.0.0" + +pino-pretty@*: + version "13.0.0" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.0.0.tgz#21d57fe940e34f2e279905d7dba2d7e2c4f9bf17" + integrity sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.2" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pump "^3.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^4.0.1" + strip-json-comments "^3.1.1" pino-pretty@^11.2.2: version "11.3.0" - resolved "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz#390b3be044cf3d2e9192c7d19d44f6b690468f2e" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.3.0.tgz#390b3be044cf3d2e9192c7d19d44f6b690468f2e" integrity sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA== dependencies: colorette "^2.0.7" @@ -8614,22 +8009,22 @@ pino-pretty@^11.2.2: sonic-boom "^4.0.1" strip-json-comments "^3.1.1" -pino-std-serializers@^7.0.0: +pino-std-serializers@*, pino-std-serializers@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== pino@^9.0.0: - version "9.6.0" - resolved "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz#6bc628159ba0cc81806d286718903b7fc6b13169" - integrity sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg== + version "9.7.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.7.0.tgz#ff7cd86eb3103ee620204dbd5ca6ffda8b53f645" + integrity sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg== dependencies: atomic-sleep "^1.0.0" fast-redact "^3.1.1" on-exit-leak-free "^2.1.0" pino-abstract-transport "^2.0.0" pino-std-serializers "^7.0.0" - process-warning "^4.0.0" + process-warning "^5.0.0" quick-format-unescaped "^4.0.3" real-require "^0.2.0" safe-stable-stringify "^2.3.1" @@ -8637,62 +8032,54 @@ pino@^9.0.0: thread-stream "^3.0.0" pirates@^4.0.1: - version "4.0.6" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - polished@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz#5a00ae32715609f83d89f6f31d0f0261c6170548" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.3.1.tgz#5a00ae32715609f83d89f6f31d0f0261c6170548" integrity sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA== dependencies: "@babel/runtime" "^7.17.8" popper.js@^1.14.4, popper.js@^1.16.1: version "1.16.1" - resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== possible-typed-array-names@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== postcss-cli@^11.0.0: - version "11.0.0" - resolved "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz#649f4b9af447501feb6cbca7f7505a132f90442b" - integrity sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA== + version "11.0.1" + resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-11.0.1.tgz#341188ff7b26b19b206ca923ae2bd979751e7da7" + integrity sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g== dependencies: chokidar "^3.3.0" - dependency-graph "^0.11.0" + dependency-graph "^1.0.0" fs-extra "^11.0.0" - get-stdin "^9.0.0" - globby "^14.0.0" picocolors "^1.0.0" postcss-load-config "^5.0.0" postcss-reporter "^7.0.0" pretty-hrtime "^1.0.3" read-cache "^1.0.0" slash "^5.0.0" + tinyglobby "^0.2.12" yargs "^17.0.0" postcss-import@^15.1.0: version "15.1.0" - resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== dependencies: postcss-value-parser "^4.0.0" @@ -8701,14 +8088,14 @@ postcss-import@^15.1.0: postcss-js@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== dependencies: camelcase-css "^2.0.1" postcss-load-config@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== dependencies: lilconfig "^3.0.0" @@ -8716,7 +8103,7 @@ postcss-load-config@^4.0.2: postcss-load-config@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz#4ded23410da973e05edae9d41fa99bb5c1d5477f" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-5.1.0.tgz#4ded23410da973e05edae9d41fa99bb5c1d5477f" integrity sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA== dependencies: lilconfig "^3.1.1" @@ -8731,12 +8118,12 @@ postcss-load-config@^6.0.1: postcss-modules-extract-imports@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== postcss-modules-local-by-default@^4.0.5: version "4.2.0" - resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" integrity sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw== dependencies: icss-utils "^5.0.0" @@ -8745,28 +8132,28 @@ postcss-modules-local-by-default@^4.0.5: postcss-modules-scope@^3.2.0: version "3.2.1" - resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== dependencies: postcss-selector-parser "^7.0.0" postcss-modules-values@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== dependencies: icss-utils "^5.0.0" postcss-nested@^6.0.1, postcss-nested@^6.2.0: version "6.2.0" - resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== dependencies: postcss-selector-parser "^6.1.1" postcss-reporter@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz#5ec476d224e2fe25a054e3c66d9b2901d4fab422" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-7.1.0.tgz#5ec476d224e2fe25a054e3c66d9b2901d4fab422" integrity sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA== dependencies: picocolors "^1.0.0" @@ -8774,7 +8161,7 @@ postcss-reporter@^7.0.0: postcss-selector-parser@6.0.10: version "6.0.10" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== dependencies: cssesc "^3.0.0" @@ -8782,7 +8169,7 @@ postcss-selector-parser@6.0.10: postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: version "6.1.2" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== dependencies: cssesc "^3.0.0" @@ -8790,7 +8177,7 @@ postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: postcss-selector-parser@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== dependencies: cssesc "^3.0.0" @@ -8798,45 +8185,45 @@ postcss-selector-parser@^7.0.0: postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss@8.4.31: version "8.4.31" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.47: - version "8.5.2" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd" - integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA== +postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.47, postcss@^8.4.49: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== dependencies: - nanoid "^3.3.8" + nanoid "^3.3.11" picocolors "^1.1.1" source-map-js "^1.2.1" posthog-js@^1.131.3: - version "1.217.1" - resolved "https://registry.npmjs.org/posthog-js/-/posthog-js-1.217.1.tgz#f8919cc05ed4851896a47a5a0c949e7ae91731c4" - integrity sha512-qttaRWe3WW7VL/MIG1Usg65Dzohw9Ylf8IVWyX36oHH9k0kzriPUl4Nx08P+oV0esbWWaCsljRzIiww4p+HOMQ== + version "1.257.0" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.257.0.tgz#7adfffa024756b910ee87a978e0fc6c12a9fa730" + integrity sha512-Ujg9RGtWVCu+4tmlRpALSy2ZOZI6JtieSYXIDDdgMWm167KYKvTtbMPHdoBaPWcNu0Km+1hAIBnQFygyn30KhA== dependencies: core-js "^3.38.1" fflate "^0.4.8" preact "^10.19.3" - web-vitals "^4.2.0" + web-vitals "^4.2.4" preact@^10.19.3: - version "10.25.4" - resolved "https://registry.npmjs.org/preact/-/preact-10.25.4.tgz#c1d00bee9d7b9dcd06a2311d9951973b506ae8ac" - integrity sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA== + version "10.26.9" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.26.9.tgz#b3898d1b65140640799062ad73b89846c293b6a7" + integrity sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA== prebuild-install@^7.1.1: version "7.1.3" - resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== dependencies: detect-libc "^2.0.0" @@ -8854,32 +8241,32 @@ prebuild-install@^7.1.1: prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-plugin-tailwindcss@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz#8299b307c7f6467f52732265579ed9375be6c818" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz#8299b307c7f6467f52732265579ed9375be6c818" integrity sha512-009/Xqdy7UmkcTBpwlq7jsViDqXAYSOMLDrHAdTMlVZOrKfM2o9Ci7EMWTMZ7SkKBFTG04UM9F9iM2+4i6boDA== prettier-plugin-tailwindcss@^0.5.4: version "0.5.14" - resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz#4482eed357d5e22eac259541c70aca5a4c7b9d5c" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz#4482eed357d5e22eac259541c70aca5a4c7b9d5c" integrity sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q== prettier@^2.8.8: version "2.8.8" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== prettier@^3.2.5, prettier@latest: - version "3.5.0" - resolved "https://registry.npmjs.org/prettier/-/prettier-3.5.0.tgz#50325a28887c6dfdf2ca3f8eaba02b66a8429ca7" - integrity sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" + integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== pretty-error@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== dependencies: lodash "^4.17.20" @@ -8887,7 +8274,7 @@ pretty-error@^4.0.0: pretty-format@^27.0.2: version "27.5.1" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== dependencies: ansi-regex "^5.0.1" @@ -8896,22 +8283,22 @@ pretty-format@^27.0.2: pretty-hrtime@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== -process-warning@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb" - integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q== +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== process@^0.11.10: version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" @@ -8920,41 +8307,41 @@ prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, property-information@^6.0.0: version "6.5.0" - resolved "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== -prosemirror-changeset@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz#dae94b63aec618fac7bb9061648e6e2a79988383" - integrity sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ== +prosemirror-changeset@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz#eee3299cfabc7a027694e9abdc4e85505e9dd5e7" + integrity sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ== dependencies: prosemirror-transform "^1.0.0" prosemirror-codemark@^0.4.2: version "0.4.2" - resolved "https://registry.npmjs.org/prosemirror-codemark/-/prosemirror-codemark-0.4.2.tgz#b4d0a57c0f1f6c6667e2a1ae7cfb6ba031dfb2e5" + resolved "https://registry.yarnpkg.com/prosemirror-codemark/-/prosemirror-codemark-0.4.2.tgz#b4d0a57c0f1f6c6667e2a1ae7cfb6ba031dfb2e5" integrity sha512-4n+PnGQToa/vTjn0OiivUvE8/moLtguUAfry8UA4Q8p47MhqT2Qpf2zBLustX5Upi4mSp3z1ZYBqLLovZC6abA== prosemirror-collab@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz#0e8c91e76e009b53457eb3b3051fb68dad029a33" + resolved "https://registry.yarnpkg.com/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz#0e8c91e76e009b53457eb3b3051fb68dad029a33" integrity sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ== dependencies: prosemirror-state "^1.0.0" prosemirror-commands@^1.0.0, prosemirror-commands@^1.6.2: - version "1.6.2" - resolved "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.6.2.tgz#d9cf6654912442cff47daa1677eb43ebd0b1f117" - integrity sha512-0nDHH++qcf/BuPLYvmqZTUUsPJUCPBUXt0J1ErTcDIS369CTp773itzLGIgIXG4LJXOlwYCr44+Mh4ii6MP1QA== + version "1.7.1" + resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz#d101fef85618b1be53d5b99ea17bee5600781b38" + integrity sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w== dependencies: prosemirror-model "^1.0.0" prosemirror-state "^1.0.0" prosemirror-transform "^1.10.2" prosemirror-dropcursor@^1.8.1: - version "1.8.1" - resolved "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz#49b9fb2f583e0d0f4021ff87db825faa2be2832d" - integrity sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw== + version "1.8.2" + resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz#2ed30c4796109ddeb1cf7282372b3850528b7228" + integrity sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw== dependencies: prosemirror-state "^1.0.0" prosemirror-transform "^1.1.0" @@ -8962,7 +8349,7 @@ prosemirror-dropcursor@^1.8.1: prosemirror-gapcursor@^1.3.2: version "1.3.2" - resolved "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz#5fa336b83789c6199a7341c9493587e249215cb4" + resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz#5fa336b83789c6199a7341c9493587e249215cb4" integrity sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ== dependencies: prosemirror-keymap "^1.0.0" @@ -8972,7 +8359,7 @@ prosemirror-gapcursor@^1.3.2: prosemirror-history@^1.0.0, prosemirror-history@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz#cc370a46fb629e83a33946a0e12612e934ab8b98" + resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.4.1.tgz#cc370a46fb629e83a33946a0e12612e934ab8b98" integrity sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ== dependencies: prosemirror-state "^1.2.2" @@ -8981,58 +8368,58 @@ prosemirror-history@^1.0.0, prosemirror-history@^1.4.1: rope-sequence "^1.3.0" prosemirror-inputrules@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz#ef1519bb2cb0d1e0cec74bad1a97f1c1555068bb" - integrity sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz#e22bfaf1d6ea4fe240ad447c184af3d520d43c37" + integrity sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA== dependencies: prosemirror-state "^1.0.0" prosemirror-transform "^1.0.0" prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz#14a54763a29c7b2704f561088ccf3384d14eb77e" - integrity sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ== + version "1.2.3" + resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz#c0f6ab95f75c0b82c97e44eb6aaf29cbfc150472" + integrity sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw== dependencies: prosemirror-state "^1.0.0" w3c-keyname "^2.2.0" prosemirror-markdown@^1.11.1, prosemirror-markdown@^1.13.1: - version "1.13.1" - resolved "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.1.tgz#23feb6652dacb3dd78ffd8f131da37c20e4e4cf8" - integrity sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw== + version "1.13.2" + resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz#863eb3fd5f57a444e4378174622b562735b1c503" + integrity sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g== dependencies: "@types/markdown-it" "^14.0.0" markdown-it "^14.0.0" - prosemirror-model "^1.20.0" + prosemirror-model "^1.25.0" prosemirror-menu@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz#3cfdc7c06d10f9fbd1bce29082c498bd11a0a79a" - integrity sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA== + version "1.2.5" + resolved "https://registry.yarnpkg.com/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz#dea00e7b623cea89f4d76963bee22d2ac2343250" + integrity sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ== dependencies: crelt "^1.0.0" prosemirror-commands "^1.0.0" prosemirror-history "^1.0.0" prosemirror-state "^1.0.0" -prosemirror-model@^1.0.0, prosemirror-model@^1.19.0, prosemirror-model@^1.20.0, prosemirror-model@^1.21.0, prosemirror-model@^1.23.0, prosemirror-model@^1.24.1: - version "1.24.1" - resolved "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.24.1.tgz#b445e4f9b9cfc8c1a699215057b506842ebff1a9" - integrity sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg== +prosemirror-model@^1.0.0, prosemirror-model@^1.20.0, prosemirror-model@^1.21.0, prosemirror-model@^1.23.0, prosemirror-model@^1.25.0: + version "1.25.2" + resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.25.2.tgz#39ca862f76f354237efb94441dbc9f79e81cb247" + integrity sha512-BVypCAJ4SL6jOiTsDffP3Wp6wD69lRhI4zg/iT8JXjp3ccZFiq5WyguxvMKmdKFC3prhaig7wSr8dneDToHE1Q== dependencies: orderedmap "^2.0.0" prosemirror-schema-basic@^1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz#649c349bb21c61a56febf9deb71ac68fca4cedf2" - integrity sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA== + version "1.2.4" + resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz#389ce1ec09b8a30ea9bbb92c58569cb690c2d695" + integrity sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ== dependencies: - prosemirror-model "^1.19.0" + prosemirror-model "^1.25.0" prosemirror-schema-list@^1.4.1: - version "1.5.0" - resolved "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.0.tgz#f05ddbe2e71efc9157a0dbedf80761c08bda5192" - integrity sha512-gg1tAfH1sqpECdhIHOA/aLg2VH3ROKBWQ4m8Qp9mBKrOxQRW61zc+gMCI8nh22gnBzd1t2u1/NPLmO3nAa3ssg== + version "1.5.1" + resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz#5869c8f749e8745c394548bb11820b0feb1e32f5" + integrity sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q== dependencies: prosemirror-model "^1.0.0" prosemirror-state "^1.0.0" @@ -9040,48 +8427,43 @@ prosemirror-schema-list@^1.4.1: prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.4.3: version "1.4.3" - resolved "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz#94aecf3ffd54ec37e87aa7179d13508da181a080" + resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.4.3.tgz#94aecf3ffd54ec37e87aa7179d13508da181a080" integrity sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q== dependencies: prosemirror-model "^1.0.0" prosemirror-transform "^1.0.0" prosemirror-view "^1.27.0" -prosemirror-tables@^1.6.1, prosemirror-tables@^1.6.3: - version "1.6.4" - resolved "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.6.4.tgz#e36ebca70d9e398c4a3b99b122ba86bfc985293d" - integrity sha512-TkDY3Gw52gRFRfRn2f4wJv5WOgAOXLJA2CQJYIJ5+kdFbfj3acR4JUW6LX2e1hiEBiUwvEhzH5a3cZ5YSztpIA== +prosemirror-tables@^1.6.4: + version "1.7.1" + resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.7.1.tgz#df2507f285c6c7563097b4904cb7c4b9e0cd724b" + integrity sha512-eRQ97Bf+i9Eby99QbyAiyov43iOKgWa7QCGly+lrDt7efZ1v8NWolhXiB43hSDGIXT1UXgbs4KJN3a06FGpr1Q== dependencies: prosemirror-keymap "^1.2.2" - prosemirror-model "^1.24.1" + prosemirror-model "^1.25.0" prosemirror-state "^1.4.3" - prosemirror-transform "^1.10.2" - prosemirror-view "^1.37.2" + prosemirror-transform "^1.10.3" + prosemirror-view "^1.39.1" prosemirror-trailing-node@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz#5bc223d4fc1e8d9145e4079ec77a932b54e19e04" + resolved "https://registry.yarnpkg.com/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz#5bc223d4fc1e8d9145e4079ec77a932b54e19e04" integrity sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ== dependencies: "@remirror/core-constants" "3.0.0" escape-string-regexp "^4.0.0" -prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.10.2, prosemirror-transform@^1.7.3: - version "1.10.2" - resolved "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.2.tgz#8ebac4e305b586cd96595aa028118c9191bbf052" - integrity sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ== +prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.10.2, prosemirror-transform@^1.10.3, prosemirror-transform@^1.7.3: + version "1.10.4" + resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz#56419eac14f9f56612c806ae46f9238648f3f02e" + integrity sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw== dependencies: prosemirror-model "^1.21.0" -prosemirror-utils@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/prosemirror-utils/-/prosemirror-utils-1.2.2.tgz#21ff3777e7b9b22b9ec8d7ded7d15b9aeeb1d008" - integrity sha512-7a2MPf99oCW8/587rQYI1/snX71Ban40+apr1hLkY8TmU9YXd7JeR6QsmktcTisJURO3WRjxIia4lTMsYgZVOw== - -prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0, prosemirror-view@^1.37.0, prosemirror-view@^1.37.2: - version "1.37.2" - resolved "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.37.2.tgz#e16b92611c6d0f30695606724dc4a9575ce7ca6b" - integrity sha512-ApcyrfV/cRcaL65on7TQcfWElwLyOgIjnIynfAuV+fIdlpbSvSWRwfuPaH7T5mo4AbO/FID29qOtjiDIKGWyog== +prosemirror-view@1.40.0, prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0, prosemirror-view@^1.37.0, prosemirror-view@^1.39.1: + version "1.40.0" + resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.40.0.tgz#212e627a0c4f0198ac9823a1232e0099c9a92865" + integrity sha512-2G3svX0Cr1sJjkD/DYWSe3cfV5VPVTBOxI9XQEGWJDFEpsZb/gh4MV29ctv+OJx2RFX4BLt09i+6zaGM/ldkCw== dependencies: prosemirror-model "^1.20.0" prosemirror-state "^1.0.0" @@ -9089,7 +8471,7 @@ prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.27.0, pros proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -9097,88 +8479,88 @@ proxy-addr@~2.0.7: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== pstree.remy@^1.1.8: version "1.1.8" - resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== pump@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" - integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" punycode.js@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== punycode@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== qs@6.13.0: version "6.13.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: side-channel "^1.0.6" qs@^6.12.3: version "6.14.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== dependencies: side-channel "^1.1.0" queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== queue@^6.0.1: version "6.0.2" - resolved "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== dependencies: inherits "~2.0.3" quick-format-unescaped@^4.0.3: version "4.0.4" - resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== raf-schd@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.5.2: version "2.5.2" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" @@ -9188,7 +8570,7 @@ raw-body@2.5.2: rc@^1.2.7: version "1.2.8" - resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" @@ -9198,7 +8580,7 @@ rc@^1.2.7: react-color@^2.19.3: version "2.19.3" - resolved "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d" + resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d" integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA== dependencies: "@icons/material" "^0.2.4" @@ -9210,9 +8592,9 @@ react-color@^2.19.3: tinycolor2 "^1.4.1" react-confetti@^6.1.0: - version "6.2.2" - resolved "https://registry.npmjs.org/react-confetti/-/react-confetti-6.2.2.tgz#b72888889b10b6707a91adca919dd35c653f4bb2" - integrity sha512-K+kTyOPgX+ZujMZ+Rmb7pZdHBvg+DzinG/w4Eh52WOB8/pfO38efnnrtEZNJmjTvLxc16RBYO+tPM68Fg8viBA== + version "6.4.0" + resolved "https://registry.yarnpkg.com/react-confetti/-/react-confetti-6.4.0.tgz#e9416b5b3c8baf6f0bb1c5a8e1e3c89babd2c837" + integrity sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg== dependencies: tween-functions "^1.2.0" @@ -9226,13 +8608,13 @@ react-day-picker@9.5.0: date-fns-jalali "^4.1.0-0" react-docgen-typescript@^2.2.2: - version "2.2.2" - resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz#4611055e569edc071204aadb20e1c93e1ab1659c" - integrity sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg== + version "2.4.0" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.4.0.tgz#033428b4a6a639d050ac8baf2a5195c596521713" + integrity sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg== react-docgen@^7.0.0: version "7.1.1" - resolved "https://registry.npmjs.org/react-docgen/-/react-docgen-7.1.1.tgz#a7a8e6b923a945acf0b7325a889ddd74fec74a63" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-7.1.1.tgz#a7a8e6b923a945acf0b7325a889ddd74fec74a63" integrity sha512-hlSJDQ2synMPKFZOsKo9Hi8WWZTC7POR8EmWvTSjow+VDgKzkmjQvFm2fk0tmRw+f0vTOIYKlarR0iL4996pdg== dependencies: "@babel/core" "^7.18.9" @@ -9247,24 +8629,24 @@ react-docgen@^7.0.0: strip-indent "^4.0.0" "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": - version "19.0.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57" - integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623" + integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== dependencies: - scheduler "^0.25.0" + scheduler "^0.26.0" react-dom@^18.3.1: version "18.3.1" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" scheduler "^0.23.2" react-dropzone@^14.2.3: - version "14.3.5" - resolved "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.3.5.tgz#1a8bd312c8a353ec78ef402842ccb3589c225add" - integrity sha512-9nDUaEEpqZLOz5v5SUcFA0CjM4vq8YbqO0WRls+EYT7+DvxUdzDPKNCPLqGfj3YL9MsniCLCD4RFA6M95V6KMQ== + version "14.3.8" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.3.8.tgz#a7eab118f8a452fe3f8b162d64454e81ba830582" + integrity sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug== dependencies: attr-accept "^2.2.4" file-selector "^2.1.0" @@ -9272,37 +8654,37 @@ react-dropzone@^14.2.3: react-fast-compare@^3.0.1: version "3.2.2" - resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== react-hook-form@7.51.5: version "7.51.5" - resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz#4afbfb819312db9fea23e8237a3a0d097e128b43" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.51.5.tgz#4afbfb819312db9fea23e8237a3a0d097e128b43" integrity sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q== react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@^17.0.1: version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== react-is@^18.0.0, react-is@^18.3.1: version "18.3.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== react-is@^19.0.0: - version "19.0.0" - resolved "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz#d6669fd389ff022a9684f708cf6fa4962d1fea7a" - integrity sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g== + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.1.0.tgz#805bce321546b7e14c084989c77022351bbdd11b" + integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg== react-markdown@^8.0.7: version "8.0.7" - resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz#c8dbd1b9ba5f1c5e7e5f2a44de465a3caafdf89b" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.7.tgz#c8dbd1b9ba5f1c5e7e5f2a44de465a3caafdf89b" integrity sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ== dependencies: "@types/hast" "^2.0.0" @@ -9323,7 +8705,7 @@ react-markdown@^8.0.7: react-masonry-component@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/react-masonry-component/-/react-masonry-component-6.3.0.tgz#edd7593f9f0d4bfa29249ea1e4d2d07757eba65d" + resolved "https://registry.yarnpkg.com/react-masonry-component/-/react-masonry-component-6.3.0.tgz#edd7593f9f0d4bfa29249ea1e4d2d07757eba65d" integrity sha512-4ZI78nxMfCpU5yQiS6Rup07Ju++YzcOGAyvbMcl2GfpZTw8GRwT548lkKr0PJarNicRV1qE2D/NiT26UPg1T7A== dependencies: create-react-class "^15.6.2" @@ -9335,7 +8717,7 @@ react-masonry-component@^6.3.0: react-pdf-html@^2.1.2: version "2.1.3" - resolved "https://registry.npmjs.org/react-pdf-html/-/react-pdf-html-2.1.3.tgz#1e3d048e2a42b594cd65b7ecbd62088cfa26b2cd" + resolved "https://registry.yarnpkg.com/react-pdf-html/-/react-pdf-html-2.1.3.tgz#1e3d048e2a42b594cd65b7ecbd62088cfa26b2cd" integrity sha512-KTTbLUFnpus2Ed6zPGM+LD/evnDcQVz+uG7/kBW4d5qKI9/O6/Hwirh8ZvcbQT/0TeA5vzaqjUnuOs2MhhZjCw== dependencies: css-tree "^1.1.3" @@ -9343,7 +8725,7 @@ react-pdf-html@^2.1.2: react-popper@^1.3.11: version "1.3.11" - resolved "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" integrity sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg== dependencies: "@babel/runtime" "^7.1.2" @@ -9356,7 +8738,7 @@ react-popper@^1.3.11: react-popper@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q== dependencies: react-fast-compare "^3.0.1" @@ -9364,16 +8746,16 @@ react-popper@^2.3.0: react-remove-scroll-bar@^2.3.7: version "2.3.8" - resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== dependencies: react-style-singleton "^2.2.2" tslib "^2.0.0" react-remove-scroll@^2.6.3: - version "2.6.3" - resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" - integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== + version "2.7.1" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753" + integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA== dependencies: react-remove-scroll-bar "^2.3.7" react-style-singleton "^2.2.3" @@ -9383,7 +8765,7 @@ react-remove-scroll@^2.6.3: react-smooth@^4.0.4: version "4.0.4" - resolved "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz#a5875f8bb61963ca61b819cedc569dc2453894b4" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-4.0.4.tgz#a5875f8bb61963ca61b819cedc569dc2453894b4" integrity sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q== dependencies: fast-equals "^5.0.1" @@ -9392,7 +8774,7 @@ react-smooth@^4.0.4: react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== dependencies: get-nonce "^1.0.0" @@ -9400,7 +8782,7 @@ react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: react-transition-group@^4.4.5: version "4.4.5" - resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== dependencies: "@babel/runtime" "^7.5.5" @@ -9409,34 +8791,34 @@ react-transition-group@^4.4.5: prop-types "^15.6.2" "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": - version "19.0.0" - resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" - integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== + version "19.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75" + integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== react@^18.3.1: version "18.3.1" - resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" reactcss@^1.2.0: version "1.2.3" - resolved "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" + resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A== dependencies: lodash "^4.0.1" read-cache@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== dependencies: pify "^2.3.0" readable-stream@^3.4.0, readable-stream@^3.6.2: version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -9445,7 +8827,7 @@ readable-stream@^3.4.0, readable-stream@^3.6.2: readable-stream@^4.0.0: version "4.7.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== dependencies: abort-controller "^3.0.0" @@ -9456,20 +8838,20 @@ readable-stream@^4.0.0: readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" real-require@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== recast@^0.23.5: - version "0.23.9" - resolved "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz#587c5d3a77c2cfcb0c18ccce6da4361528c2587b" - integrity sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q== + version "0.23.11" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.11.tgz#8885570bb28cf773ba1dc600da7f502f7883f73f" + integrity sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA== dependencies: ast-types "^0.16.1" esprima "~4.0.0" @@ -9479,15 +8861,15 @@ recast@^0.23.5: recharts-scale@^0.4.4: version "0.4.5" - resolved "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" + resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" integrity sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w== dependencies: decimal.js-light "^2.4.1" recharts@^2.12.7, recharts@^2.15.1: - version "2.15.1" - resolved "https://registry.npmjs.org/recharts/-/recharts-2.15.1.tgz#0941adf0402528d54f6d81997eb15840c893aa3c" - integrity sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q== + version "2.15.4" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.15.4.tgz#0ed3e66c0843bcf2d9f9a172caf97b1d05127a5f" + integrity sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw== dependencies: clsx "^2.0.0" eventemitter3 "^4.0.1" @@ -9500,32 +8882,27 @@ recharts@^2.12.7, recharts@^2.15.1: redent@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== dependencies: indent-string "^4.0.0" strip-indent "^3.0.0" -redis-commands@1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" - integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== - redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== redis-parser@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== dependencies: redis-errors "^1.0.0" redlock@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/redlock/-/redlock-4.2.0.tgz#c26590768559afd5fff76aa1133c94b411ff4f5f" + resolved "https://registry.yarnpkg.com/redlock/-/redlock-4.2.0.tgz#c26590768559afd5fff76aa1133c94b411ff4f5f" integrity sha512-j+oQlG+dOwcetUt2WJWttu4CZVeRzUrcVcISFmEmfyuwCVSJ93rDT7YSgg7H7rnxwoRyk/jU46kycVka5tW7jA== dependencies: bluebird "^3.7.2" @@ -9537,7 +8914,7 @@ reflect-metadata@*, reflect-metadata@^0.2.2: reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: version "1.0.10" - resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== dependencies: call-bind "^1.0.8" @@ -9549,33 +8926,14 @@ reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: get-proto "^1.0.1" which-builtin-type "^1.2.1" -regenerate-unicode-properties@^10.2.0: - version "10.2.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" - integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - regenerator-runtime@^0.14.0: version "0.14.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== - dependencies: - "@babel/runtime" "^7.8.4" - -regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3: +regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: version "1.5.4" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== dependencies: call-bind "^1.0.8" @@ -9585,38 +8943,14 @@ regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3: gopd "^1.2.0" set-function-name "^2.0.2" -regexpu-core@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" - integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== - dependencies: - regenerate "^1.4.2" - regenerate-unicode-properties "^10.2.0" - regjsgen "^0.8.0" - regjsparser "^0.12.0" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -regjsgen@^0.8.0: - version "0.8.0" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" - integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== - -regjsparser@^0.12.0: - version "0.12.0" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" - integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== - dependencies: - jsesc "~3.0.2" - relateurl@^0.2.7: version "0.2.7" - resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== remark-parse@^10.0.0: version "10.0.2" - resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz#ca241fde8751c2158933f031a4e3efbaeb8bc262" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.2.tgz#ca241fde8751c2158933f031a4e3efbaeb8bc262" integrity sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw== dependencies: "@types/mdast" "^3.0.0" @@ -9625,7 +8959,7 @@ remark-parse@^10.0.0: remark-rehype@^10.0.0: version "10.1.0" - resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== dependencies: "@types/hast" "^2.0.0" @@ -9635,7 +8969,7 @@ remark-rehype@^10.0.0: renderkid@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== dependencies: css-select "^4.1.3" @@ -9646,37 +8980,32 @@ renderkid@^3.0.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -reselect@^4.1.7: - version "4.1.8" - resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-pkg-maps@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.8: +resolve@^1.1.7, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.8: version "1.22.10" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== dependencies: is-core-module "^2.16.0" @@ -9685,7 +9014,7 @@ resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22 resolve@^2.0.0-next.5: version "2.0.0-next.5" - resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: is-core-module "^2.13.0" @@ -9694,84 +9023,84 @@ resolve@^2.0.0-next.5: restructure@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz#e6b2fad214f78edee21797fa8160fef50eb9b49a" + resolved "https://registry.yarnpkg.com/restructure/-/restructure-3.0.2.tgz#e6b2fad214f78edee21797fa8160fef50eb9b49a" integrity sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw== reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" rollup@^4.34.8: - version "4.41.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.41.1.tgz#46ddc1b33cf1b0baa99320d3b0b4973dc2253b6a" - integrity sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw== + version "4.45.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.45.1.tgz#d0ef72a8d0a9210d832f9c3c5f3b6a2aa4b0ba64" + integrity sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw== dependencies: - "@types/estree" "1.0.7" + "@types/estree" "1.0.8" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.41.1" - "@rollup/rollup-android-arm64" "4.41.1" - "@rollup/rollup-darwin-arm64" "4.41.1" - "@rollup/rollup-darwin-x64" "4.41.1" - "@rollup/rollup-freebsd-arm64" "4.41.1" - "@rollup/rollup-freebsd-x64" "4.41.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.41.1" - "@rollup/rollup-linux-arm-musleabihf" "4.41.1" - "@rollup/rollup-linux-arm64-gnu" "4.41.1" - "@rollup/rollup-linux-arm64-musl" "4.41.1" - "@rollup/rollup-linux-loongarch64-gnu" "4.41.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.41.1" - "@rollup/rollup-linux-riscv64-gnu" "4.41.1" - "@rollup/rollup-linux-riscv64-musl" "4.41.1" - "@rollup/rollup-linux-s390x-gnu" "4.41.1" - "@rollup/rollup-linux-x64-gnu" "4.41.1" - "@rollup/rollup-linux-x64-musl" "4.41.1" - "@rollup/rollup-win32-arm64-msvc" "4.41.1" - "@rollup/rollup-win32-ia32-msvc" "4.41.1" - "@rollup/rollup-win32-x64-msvc" "4.41.1" + "@rollup/rollup-android-arm-eabi" "4.45.1" + "@rollup/rollup-android-arm64" "4.45.1" + "@rollup/rollup-darwin-arm64" "4.45.1" + "@rollup/rollup-darwin-x64" "4.45.1" + "@rollup/rollup-freebsd-arm64" "4.45.1" + "@rollup/rollup-freebsd-x64" "4.45.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.45.1" + "@rollup/rollup-linux-arm-musleabihf" "4.45.1" + "@rollup/rollup-linux-arm64-gnu" "4.45.1" + "@rollup/rollup-linux-arm64-musl" "4.45.1" + "@rollup/rollup-linux-loongarch64-gnu" "4.45.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.45.1" + "@rollup/rollup-linux-riscv64-gnu" "4.45.1" + "@rollup/rollup-linux-riscv64-musl" "4.45.1" + "@rollup/rollup-linux-s390x-gnu" "4.45.1" + "@rollup/rollup-linux-x64-gnu" "4.45.1" + "@rollup/rollup-linux-x64-musl" "4.45.1" + "@rollup/rollup-win32-arm64-msvc" "4.45.1" + "@rollup/rollup-win32-ia32-msvc" "4.45.1" + "@rollup/rollup-win32-x64-msvc" "4.45.1" fsevents "~2.3.2" rope-sequence@^1.3.0: version "1.3.4" - resolved "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz#df85711aaecd32f1e756f76e43a415171235d425" + resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.4.tgz#df85711aaecd32f1e756f76e43a415171235d425" integrity sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ== rrweb-cssom@^0.8.0: version "0.8.0" - resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw== run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" rxjs@^7.8.1: - version "7.8.1" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== dependencies: tslib "^2.1.0" sade@^1.7.3: version "1.8.1" - resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== dependencies: mri "^1.1.0" safe-array-concat@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: call-bind "^1.0.8" @@ -9782,17 +9111,17 @@ safe-array-concat@^1.1.3: safe-buffer@5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-push-apply@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== dependencies: es-errors "^1.3.0" @@ -9800,7 +9129,7 @@ safe-push-apply@^1.0.0: safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== dependencies: call-bound "^1.0.2" @@ -9809,24 +9138,24 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: safe-stable-stringify@^2.3.1: version "2.5.0" - resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== saxes@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== dependencies: xmlchars "^2.2.0" scheduler@^0.17.0: version "0.17.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== dependencies: loose-envify "^1.1.0" @@ -9834,29 +9163,29 @@ scheduler@^0.17.0: scheduler@^0.23.2: version "0.23.2" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" -scheduler@^0.25.0: - version "0.25.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" - integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== -schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.1.1: version "3.3.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0, schema-utils@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0" - integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g== +schema-utils@^4.0.0, schema-utils@^4.3.0, schema-utils@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.2.tgz#0c10878bf4a73fd2b1dfd14b9462b26788c806ae" + integrity sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ== dependencies: "@types/json-schema" "^7.0.9" ajv "^8.9.0" @@ -9865,34 +9194,29 @@ schema-utils@^4.0.0, schema-utils@^4.3.0: scroll-into-view-if-needed@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f" integrity sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ== dependencies: compute-scroll-into-view "^3.0.2" secure-json-parse@^2.4.0: version "2.7.0" - resolved "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== -semver@^5.6.0: - version "5.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - semver@^6.0.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3: - version "7.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== +semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.7.1: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== send@0.19.0: version "0.19.0" - resolved "https://registry.npmjs.org/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" @@ -9911,7 +9235,7 @@ send@0.19.0: sentence-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== dependencies: no-case "^3.0.4" @@ -9920,14 +9244,14 @@ sentence-case@^3.0.4: serialize-javascript@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" serve-static@1.16.2: version "1.16.2" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: encodeurl "~2.0.0" @@ -9937,7 +9261,7 @@ serve-static@1.16.2: set-function-length@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: define-data-property "^1.1.4" @@ -9949,7 +9273,7 @@ set-function-length@^1.2.2: set-function-name@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== dependencies: define-data-property "^1.1.4" @@ -9959,7 +9283,7 @@ set-function-name@^2.0.2: set-proto@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== dependencies: dunder-proto "^1.0.1" @@ -9968,12 +9292,12 @@ set-proto@^1.0.0: setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sharp@^0.32.1: version "0.32.6" - resolved "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz#6ad30c0b7cd910df65d5f355f774aa4fce45732a" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.6.tgz#6ad30c0b7cd910df65d5f355f774aa4fce45732a" integrity sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w== dependencies: color "^4.2.3" @@ -9987,24 +9311,24 @@ sharp@^0.32.1: shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.8.1: - version "1.8.2" - resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" - integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== + version "1.8.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b" + integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw== side-channel-list@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: es-errors "^1.3.0" @@ -10012,7 +9336,7 @@ side-channel-list@^1.0.0: side-channel-map@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== dependencies: call-bound "^1.0.2" @@ -10022,7 +9346,7 @@ side-channel-map@^1.0.1: side-channel-weakmap@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== dependencies: call-bound "^1.0.2" @@ -10033,7 +9357,7 @@ side-channel-weakmap@^1.0.2: side-channel@^1.0.6, side-channel@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== dependencies: es-errors "^1.3.0" @@ -10044,17 +9368,17 @@ side-channel@^1.0.6, side-channel@^1.1.0: signal-exit@^4.0.1: version "4.1.0" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-concat@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^4.0.0, simple-get@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== dependencies: decompress-response "^6.0.0" @@ -10063,68 +9387,70 @@ simple-get@^4.0.0, simple-get@^4.0.1: simple-swizzle@^0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" simple-update-notifier@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== dependencies: semver "^7.5.3" -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^5.0.0, slash@^5.1.0: +slash@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" + resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== smooth-scroll-into-view-if-needed@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-2.0.2.tgz#5bd4ebef668474d6618ce8704650082e93068371" + resolved "https://registry.yarnpkg.com/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-2.0.2.tgz#5bd4ebef668474d6618ce8704650082e93068371" integrity sha512-z54WzUSlM+xHHvJu3lMIsh+1d1kA4vaakcAtQvqzeGJ5Ffau7EKjpRrMHh1/OBo5zyU2h30ZYEt77vWmPHqg7Q== dependencies: scroll-into-view-if-needed "^3.1.0" snake-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== dependencies: dot-case "^3.0.4" tslib "^2.0.3" +sonic-boom@^2.1.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== + dependencies: + atomic-sleep "^1.0.0" + sonic-boom@^4.0.1: version "4.2.0" - resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== dependencies: atomic-sleep "^1.0.0" sonner@^1.4.41: version "1.7.4" - resolved "https://registry.npmjs.org/sonner/-/sonner-1.7.4.tgz#4c39820db86623800a17115c8970796aa862133a" + resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.7.4.tgz#4c39820db86623800a17115c8970796aa862133a" integrity sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw== source-map-js@^1.0.2, source-map-js@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -10132,67 +9458,75 @@ source-map-support@~0.5.20: source-map@0.8.0-beta.0: version "0.8.0-beta.0" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== dependencies: whatwg-url "^7.0.0" source-map@^0.5.7: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== space-separated-tokens@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== split2@^4.0.0: version "4.2.0" - resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== -stable-hash@^0.0.4: - version "0.0.4" - resolved "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz#55ae7dadc13e4b3faed13601587cec41859b42f7" - integrity sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g== +stable-hash@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.5.tgz#94e8837aaeac5b4d0f631d2972adef2924b40269" + integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA== stack-trace@0.0.x: version "0.0.10" - resolved "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== standard-as-callback@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== statuses@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -storybook@^8.1.1: - version "8.5.4" - resolved "https://registry.npmjs.org/storybook/-/storybook-8.5.4.tgz#097e6d39bba43db18c2fa951c8b820a2d445e61f" - integrity sha512-TMXXOprDjkt8GbTCgzZSi0sPYoKMfvN+9gGnU7gRa8s1C0QhqkE0lc6fq9pl8nahXPF5ala4gPOaxjQbuJUvNQ== +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== dependencies: - "@storybook/core" "8.5.4" + es-errors "^1.3.0" + internal-slot "^1.1.0" + +storybook@^8.1.1: + version "8.6.14" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.6.14.tgz#d205e73b6427eebf321bcfbe63bfbec3ade4d9db" + integrity sha512-sVKbCj/OTx67jhmauhxc2dcr1P+yOgz/x3h0krwjyMgdc5Oubvxyg4NYDZmzAw+ym36g/lzH8N0Ccp4dwtdfxw== + dependencies: + "@storybook/core" "8.6.14" streamsearch@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== streamx@^2.15.0, streamx@^2.21.0: - version "2.22.0" - resolved "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz#cd7b5e57c95aaef0ff9b2aef7905afa62ec6e4a7" - integrity sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw== + version "2.22.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.1.tgz#c97cbb0ce18da4f4db5a971dc9ab68ff5dc7f5a5" + integrity sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA== dependencies: fast-fifo "^1.3.2" text-decoder "^1.1.0" @@ -10201,7 +9535,7 @@ streamx@^2.15.0, streamx@^2.21.0: "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -10210,7 +9544,7 @@ streamx@^2.15.0, streamx@^2.21.0: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -10219,7 +9553,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: eastasianwidth "^0.2.0" @@ -10228,7 +9562,7 @@ string-width@^5.0.1, string-width@^5.1.2: string.prototype.includes@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== dependencies: call-bind "^1.0.7" @@ -10237,7 +9571,7 @@ string.prototype.includes@^2.0.1: string.prototype.matchall@^4.0.12: version "4.0.12" - resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== dependencies: call-bind "^1.0.8" @@ -10256,7 +9590,7 @@ string.prototype.matchall@^4.0.12: string.prototype.repeat@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== dependencies: define-properties "^1.1.3" @@ -10264,7 +9598,7 @@ string.prototype.repeat@^1.0.0: string.prototype.trim@^1.2.10: version "1.2.10" - resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== dependencies: call-bind "^1.0.8" @@ -10275,9 +9609,9 @@ string.prototype.trim@^1.2.10: es-object-atoms "^1.0.0" has-property-descriptors "^1.0.2" -string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: +string.prototype.trimend@^1.0.9: version "1.0.9" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== dependencies: call-bind "^1.0.8" @@ -10287,7 +9621,7 @@ string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: string.prototype.trimstart@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== dependencies: call-bind "^1.0.7" @@ -10296,88 +9630,88 @@ string.prototype.trimstart@^1.0.8: string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-indent@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== dependencies: min-indent "^1.0.0" strip-indent@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853" integrity sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA== dependencies: min-indent "^1.0.1" strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== style-loader@^3.3.1: version "3.3.4" - resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== style-to-object@^0.4.0: version "0.4.4" - resolved "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec" integrity sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg== dependencies: inline-style-parser "0.1.1" styled-jsx@5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== dependencies: client-only "0.0.1" stylis@4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== sucrase@^3.35.0: version "3.35.0" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== dependencies: "@jridgewell/gen-mapping" "^0.3.2" @@ -10390,73 +9724,73 @@ sucrase@^3.35.0: supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0, supports-color@^8.1.1: version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== svg-arc-to-cubic-bezier@^3.0.0, svg-arc-to-cubic-bezier@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" + resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g== swc-loader@^0.2.3: version "0.2.6" - resolved "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz#bf0cba8eeff34bb19620ead81d1277fefaec6bc8" + resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.2.6.tgz#bf0cba8eeff34bb19620ead81d1277fefaec6bc8" integrity sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg== dependencies: "@swc/counter" "^0.1.3" swr@^2.1.3, swr@^2.2.2, swr@^2.2.4: - version "2.3.2" - resolved "https://registry.npmjs.org/swr/-/swr-2.3.2.tgz#e7c4eb7115e7ff734e445ad0036e97812dd95191" - integrity sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA== + version "2.3.4" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.3.4.tgz#60bcb5b97cae157a6ef69eff0ed2beb9010eba69" + integrity sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg== dependencies: dequal "^2.0.3" use-sync-external-store "^1.4.0" symbol-tree@^3.2.4: version "3.2.4" - resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== tabbable@^6.0.0: version "6.2.0" - resolved "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== tailwind-merge@^2.0.0, tailwind-merge@^2.5.5: version "2.6.0" - resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz#ac5fb7e227910c038d458f396b7400d93a3142d5" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.6.0.tgz#ac5fb7e227910c038d458f396b7400d93a3142d5" integrity sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA== tailwindcss-animate@^1.0.6, tailwindcss-animate@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" + resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== tailwindcss@^3.4.17: version "3.4.17" - resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== dependencies: "@alloc/quick-lru" "^5.2.0" @@ -10483,13 +9817,13 @@ tailwindcss@^3.4.17: sucrase "^3.35.0" tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.2.tgz#ab4984340d30cb9989a490032f086dbb8b56d872" + integrity sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg== tar-fs@3.0.9, tar-fs@^2.0.0, tar-fs@^3.0.4: version "3.0.9" - resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz#d570793c6370d7078926c41fa422891566a0b617" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.9.tgz#d570793c6370d7078926c41fa422891566a0b617" integrity sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA== dependencies: pump "^3.0.0" @@ -10500,17 +9834,17 @@ tar-fs@3.0.9, tar-fs@^2.0.0, tar-fs@^3.0.4: tar-stream@^3.1.5: version "3.1.7" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== dependencies: b4a "^1.6.4" fast-fifo "^1.2.0" streamx "^2.15.0" -terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10: - version "5.3.11" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz#93c21f44ca86634257cac176f884f942b7ba3832" - integrity sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ== +terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.11: + version "5.3.14" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" + integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" @@ -10519,71 +9853,71 @@ terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10: terser "^5.31.1" terser@^5.10.0, terser@^5.31.1: - version "5.38.2" - resolved "https://registry.npmjs.org/terser/-/terser-5.38.2.tgz#24aef4ea48c900d46a4b13f6a53789980d59967f" - integrity sha512-w8CXxxbFA5zfNsR/i8HZq5bvn18AK0O9jj7hyo1YqkovLxEFa0uP0LCVGZRqiRaKRFxXhELBp8SteeAjEnfeJg== + version "5.43.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.43.1.tgz#88387f4f9794ff1a29e7ad61fb2932e25b4fdb6d" + integrity sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg== dependencies: "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" + acorn "^8.14.0" commander "^2.20.0" source-map-support "~0.5.20" text-decoder@^1.1.0: version "1.2.3" - resolved "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== dependencies: b4a "^1.6.4" text-hex@1.0.x: version "1.0.0" - resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== thenby@^1.3.4: version "1.3.4" - resolved "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz#81581f6e1bb324c6dedeae9bfc28e59b1a2201cc" + resolved "https://registry.yarnpkg.com/thenby/-/thenby-1.3.4.tgz#81581f6e1bb324c6dedeae9bfc28e59b1a2201cc" integrity sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ== thenify-all@^1.0.0: version "1.6.0" - resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.1" - resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" thread-stream@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== dependencies: real-require "^0.2.0" tiny-inflate@^1.0.0, tiny-inflate@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== tiny-invariant@^1.3.1, tiny-invariant@^1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== tinycolor2@^1.4.1: version "1.6.0" - resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== tinyexec@^0.3.2: @@ -10591,7 +9925,7 @@ tinyexec@^0.3.2: resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== -tinyglobby@^0.2.11: +tinyglobby@^0.2.11, tinyglobby@^0.2.12, tinyglobby@^0.2.13: version "0.2.14" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== @@ -10601,24 +9935,24 @@ tinyglobby@^0.2.11: tinyrainbow@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== tinyspy@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== tippy.js@^6.3.7: version "6.3.7" - resolved "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" + resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ== dependencies: "@popperjs/core" "^2.9.0" tiptap-markdown@^0.8.10: version "0.8.10" - resolved "https://registry.npmjs.org/tiptap-markdown/-/tiptap-markdown-0.8.10.tgz#864a54befc17b25e7f475ff6072de3d49814f09b" + resolved "https://registry.yarnpkg.com/tiptap-markdown/-/tiptap-markdown-0.8.10.tgz#864a54befc17b25e7f475ff6072de3d49814f09b" integrity sha512-iDVkR2BjAqkTDtFX0h94yVvE2AihCXlF0Q7RIXSJPRSR5I0PA1TMuAg6FHFpmqTn4tPxJ0by0CK7PUMlnFLGEQ== dependencies: "@types/markdown-it" "^13.0.7" @@ -10626,99 +9960,99 @@ tiptap-markdown@^0.8.10: markdown-it-task-lists "^2.1.1" prosemirror-markdown "^1.11.1" -tldts-core@^6.1.77: - version "6.1.77" - resolved "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.77.tgz#0fa4563163a7a61d72c4b05650fb66fc7e815500" - integrity sha512-bCaqm24FPk8OgBkM0u/SrEWJgHnhBWYqeBo6yUmcZJDCHt/IfyWBb+14CXdGi4RInMv4v7eUAin15W0DoA+Ytg== +tldts-core@^6.1.86: + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.86.tgz#a93e6ed9d505cb54c542ce43feb14c73913265d8" + integrity sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA== tldts@^6.1.32: - version "6.1.77" - resolved "https://registry.npmjs.org/tldts/-/tldts-6.1.77.tgz#714e3d1989e562886f2ed97b65e95a8e9f9e92d9" - integrity sha512-lBpoWgy+kYmuXWQ83+R7LlJCnsd9YW8DGpZSHhrMl4b8Ly/1vzOie3OdtmUJDkKxcgRGOehDu5btKkty+JEe+g== + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.86.tgz#087e0555b31b9725ee48ca7e77edc56115cd82f7" + integrity sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ== dependencies: - tldts-core "^6.1.77" + tldts-core "^6.1.86" to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== touch@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== -tough-cookie@^5.0.0: - version "5.1.1" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.1.tgz#4641c1fdbf024927e29c5532edb7b6e5377ea1f2" - integrity sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA== +tough-cookie@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" + integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== dependencies: tldts "^6.1.32" tr46@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== dependencies: punycode "^2.1.0" -tr46@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz#3b46d583613ec7283020d79019f1335723801cec" - integrity sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g== +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== dependencies: punycode "^2.3.1" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tree-kill@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== trim-lines@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== triple-beam@^1.3.0, triple-beam@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== trough@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== -ts-api-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" - integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== ts-dedent@^2.0.0, ts-dedent@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== ts-interface-checker@^0.1.9: version "0.1.13" - resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== ts-node@^10.9.2: version "10.9.2" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -10737,7 +10071,7 @@ ts-node@^10.9.2: tsconfig-paths@^3.15.0: version "3.15.0" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" @@ -10747,26 +10081,26 @@ tsconfig-paths@^3.15.0: tsconfig-paths@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0: - version "2.8.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tslib@^1.8.1: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@~2.5.0: version "2.5.3" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== tsup@8.4.0: @@ -10793,85 +10127,80 @@ tsup@8.4.0: tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" -turbo-darwin-64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.5.4.tgz#f03b3f071365c626d05e84d0d4b9db96348f2951" - integrity sha512-ah6YnH2dErojhFooxEzmvsoZQTMImaruZhFPfMKPBq8sb+hALRdvBNLqfc8NWlZq576FkfRZ/MSi4SHvVFT9PQ== +turbo-darwin-64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.5.5.tgz#96a9f4f0acd61e48685c5be1765fa3a0c9be120d" + integrity sha512-RYnTz49u4F5tDD2SUwwtlynABNBAfbyT2uU/brJcyh5k6lDLyNfYKdKmqd3K2ls4AaiALWrFKVSBsiVwhdFNzQ== -turbo-darwin-arm64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.5.4.tgz#614becf281da75af5a01094373f380ac2b48190a" - integrity sha512-2+Nx6LAyuXw2MdXb7pxqle3MYignLvS7OwtsP9SgtSBaMlnNlxl9BovzqdYAgkUW3AsYiQMJ/wBRb7d+xemM5A== +turbo-darwin-arm64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.5.5.tgz#2d8e47e1b04d2cb339455adb64fb52c94e587a44" + integrity sha512-Tk+ZeSNdBobZiMw9aFypQt0DlLsWSFWu1ymqsAdJLuPoAH05qCfYtRxE1pJuYHcJB5pqI+/HOxtJoQ40726Btw== -turbo-linux-64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.5.4.tgz#fc7425f35feb19a8373e7926eccdd4a3b2fb77a4" - integrity sha512-5May2kjWbc8w4XxswGAl74GZ5eM4Gr6IiroqdLhXeXyfvWEdm2mFYCSWOzz0/z5cAgqyGidF1jt1qzUR8hTmOA== +turbo-linux-64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.5.5.tgz#3f8512243d9fa0927d677235d720c07540bf66e8" + integrity sha512-2/XvMGykD7VgsvWesZZYIIVXMlgBcQy+ZAryjugoTcvJv8TZzSU/B1nShcA7IAjZ0q7OsZ45uP2cOb8EgKT30w== -turbo-linux-arm64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.5.4.tgz#ab5418a88089e4ec20b2c28c3d3c6b8a99b07a81" - integrity sha512-/2yqFaS3TbfxV3P5yG2JUI79P7OUQKOUvAnx4MV9Bdz6jqHsHwc9WZPpO4QseQm+NvmgY6ICORnoVPODxGUiJg== +turbo-linux-arm64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.5.5.tgz#705dc5fdaed6b2c8cc9cd35bbd154ed16e4a78d3" + integrity sha512-DW+8CjCjybu0d7TFm9dovTTVg1VRnlkZ1rceO4zqsaLrit3DgHnN4to4uwyuf9s2V/BwS3IYcRy+HG9BL596Iw== -turbo-windows-64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.5.4.tgz#fc78585d3950e5cd64bed8d6648f078e7f32f9a5" - integrity sha512-EQUO4SmaCDhO6zYohxIjJpOKRN3wlfU7jMAj3CgcyTPvQR/UFLEKAYHqJOnJtymbQmiiM/ihX6c6W6Uq0yC7mA== +turbo-windows-64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.5.5.tgz#70c7937e59d1a48391c4ed300b28d0e58ea22073" + integrity sha512-q5p1BOy8ChtSZfULuF1BhFMYIx6bevXu4fJ+TE/hyNfyHJIfjl90Z6jWdqAlyaFLmn99X/uw+7d6T/Y/dr5JwQ== -turbo-windows-arm64@2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.5.4.tgz#5134537cc9fa27f4647f2f899b7ba2dacfc6ad22" - integrity sha512-oQ8RrK1VS8lrxkLriotFq+PiF7iiGgkZtfLKF4DDKsmdbPo0O9R2mQxm7jHLuXraRCuIQDWMIw6dpcr7Iykf4A== +turbo-windows-arm64@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.5.5.tgz#0ab29d38fcc67ba38652f1cd273df49177cb55b8" + integrity sha512-AXbF1KmpHUq3PKQwddMGoKMYhHsy5t1YBQO8HZ04HLMR0rWv9adYlQ8kaeQJTko1Ay1anOBFTqaxfVOOsu7+1Q== turbo@^2.5.4: - version "2.5.4" - resolved "https://registry.npmjs.org/turbo/-/turbo-2.5.4.tgz#e46213a4560b94e56c014e0fd56d06605de16753" - integrity sha512-kc8ZibdRcuWUG1pbYSBFWqmIjynlD8Lp7IB6U3vIzvOv9VG+6Sp8bzyeBWE3Oi8XV5KsQrznyRTBPvrf99E4mA== + version "2.5.5" + resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.5.5.tgz#6057f87c1262acdfa30cf16d4cf74629623f36c9" + integrity sha512-eZ7wI6KjtT1eBqCnh2JPXWNUAxtoxxfi6VdBdZFvil0ychCOTxbm7YLRBi1JSt7U3c+u3CLxpoPxLdvr/Npr3A== optionalDependencies: - turbo-darwin-64 "2.5.4" - turbo-darwin-arm64 "2.5.4" - turbo-linux-64 "2.5.4" - turbo-linux-arm64 "2.5.4" - turbo-windows-64 "2.5.4" - turbo-windows-arm64 "2.5.4" + turbo-darwin-64 "2.5.5" + turbo-darwin-arm64 "2.5.5" + turbo-linux-64 "2.5.5" + turbo-linux-arm64 "2.5.5" + turbo-windows-64 "2.5.5" + turbo-windows-arm64 "2.5.5" tween-functions@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff" + resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff" integrity sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^2.19.0: - version "2.19.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" - integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== - type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -10879,7 +10208,7 @@ type-is@~1.6.18: typed-array-buffer@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: call-bound "^1.0.3" @@ -10888,7 +10217,7 @@ typed-array-buffer@^1.0.3: typed-array-byte-length@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: call-bind "^1.0.8" @@ -10899,7 +10228,7 @@ typed-array-byte-length@^1.0.3: typed-array-byte-offset@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== dependencies: available-typed-arrays "^1.0.7" @@ -10912,7 +10241,7 @@ typed-array-byte-offset@^1.0.4: typed-array-length@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" @@ -10924,7 +10253,7 @@ typed-array-length@^1.0.7: typed-styles@^0.0.7: version "0.0.7" - resolved "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" + resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== typescript@5.8.3: @@ -10934,12 +10263,12 @@ typescript@5.8.3: uc.micro@^2.0.0, uc.micro@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== unbox-primitive@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: call-bound "^1.0.3" @@ -10949,66 +10278,38 @@ unbox-primitive@^1.1.0: undefsafe@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" - integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.2.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" - integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== unicode-properties@^1.4.0, unicode-properties@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz#96a9cffb7e619a0dc7368c28da27e05fc8f9be5f" + resolved "https://registry.yarnpkg.com/unicode-properties/-/unicode-properties-1.4.1.tgz#96a9cffb7e619a0dc7368c28da27e05fc8f9be5f" integrity sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg== dependencies: base64-js "^1.3.0" unicode-trie "^2.0.0" -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - unicode-trie@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz#8fd8845696e2e14a8b67d78fa9e0dd2cad62fec8" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-2.0.0.tgz#8fd8845696e2e14a8b67d78fa9e0dd2cad62fec8" integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ== dependencies: pako "^0.2.5" tiny-inflate "^1.0.0" -unicorn-magic@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104" - integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== - unified@^10.0.0: version "10.1.2" - resolved "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== dependencies: "@types/unist" "^2.0.0" @@ -11021,33 +10322,33 @@ unified@^10.0.0: unist-util-generated@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae" integrity sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A== unist-util-is@^5.0.0: version "5.2.1" - resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== dependencies: "@types/unist" "^2.0.0" unist-util-position@^4.0.0: version "4.0.4" - resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz#93f6d8c7d6b373d9b825844645877c127455f037" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.4.tgz#93f6d8c7d6b373d9b825844645877c127455f037" integrity sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== dependencies: "@types/unist" "^2.0.0" unist-util-visit-parents@^5.1.1: version "5.1.3" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== dependencies: "@types/unist" "^2.0.0" @@ -11055,7 +10356,7 @@ unist-util-visit-parents@^5.1.1: unist-util-visit@^4.0.0: version "4.1.2" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== dependencies: "@types/unist" "^2.0.0" @@ -11064,54 +10365,81 @@ unist-util-visit@^4.0.0: universalify@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unplugin@^1.3.1: version "1.16.1" - resolved "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz#a844d2e3c3b14a4ac2945c42be80409321b61199" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.16.1.tgz#a844d2e3c3b14a4ac2945c42be80409321b61199" integrity sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w== dependencies: acorn "^8.14.0" webpack-virtual-modules "^0.6.2" -update-browserslist-db@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" - integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== +unrs-resolver@^1.6.2: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== dependencies: escalade "^3.2.0" picocolors "^1.1.1" upper-case-first@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== dependencies: tslib "^2.0.3" upper-case@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== dependencies: tslib "^2.0.3" uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" url@^0.11.0: version "0.11.4" - resolved "https://registry.npmjs.org/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== dependencies: punycode "^1.4.1" @@ -11119,39 +10447,39 @@ url@^0.11.0: use-callback-ref@^1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== dependencies: tslib "^2.0.0" use-font-face-observer@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/use-font-face-observer/-/use-font-face-observer-1.2.2.tgz#ed230d907589c6b17e8c8b896c9f5913968ac5ed" - integrity sha512-5C11YC9vPQn5TeIKDvHHiUg59FBzV1LDIOjYJ2PVgn1raVoKHcuWf3dxVDb7OiqQVg3M2S1jX3LxbLw16xo8gg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-font-face-observer/-/use-font-face-observer-1.3.0.tgz#12987ed66450fdb1f48749be7ef70a3542951f70" + integrity sha512-gS5UoSPcOoCF+JMbw2By1E3FtXl6ZPxgFo8MW4shpM15lf+MNyzEfjsLJFJ3T/mHLdGTBhQgZYSAXEzubr6v5Q== dependencies: fontfaceobserver "2.1.0" use-sidecar@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== dependencies: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1, use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" - integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== +use-sync-external-store@^1, use-sync-external-store@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.4, util@^0.12.5: version "0.12.5" - resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== dependencies: inherits "^2.0.3" @@ -11162,32 +10490,32 @@ util@^0.12.4, util@^0.12.5: utila@~0.4: version "0.4.0" - resolved "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^10.0.0: version "10.0.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== uuid@^11.0.3: - version "11.0.5" - resolved "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz#07b46bdfa6310c92c3fb3953a8720f170427fc62" - integrity sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA== + version "11.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== uuid@^9.0.0, uuid@^9.0.1: version "9.0.1" - resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== uvu@^0.5.0: version "0.5.6" - resolved "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== dependencies: dequal "^2.0.0" @@ -11197,17 +10525,17 @@ uvu@^0.5.0: v8-compile-cache-lib@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== vary@^1, vary@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vfile-message@^3.0.0: version "3.1.4" - resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz#15a50816ae7d7c2d1fa87090a7f9f96612b59dea" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.4.tgz#15a50816ae7d7c2d1fa87090a7f9f96612b59dea" integrity sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw== dependencies: "@types/unist" "^2.0.0" @@ -11215,7 +10543,7 @@ vfile-message@^3.0.0: vfile@^5.0.0: version "5.3.7" - resolved "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz#de0677e6683e3380fafc46544cfe603118826ab7" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.7.tgz#de0677e6683e3380fafc46544cfe603118826ab7" integrity sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g== dependencies: "@types/unist" "^2.0.0" @@ -11225,7 +10553,7 @@ vfile@^5.0.0: victory-vendor@^36.6.8: version "36.9.2" - resolved "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz#668b02a448fa4ea0f788dbf4228b7e64669ff801" + resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-36.9.2.tgz#668b02a448fa4ea0f788dbf4228b7e64669ff801" integrity sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ== dependencies: "@types/d3-array" "^3.0.3" @@ -11245,7 +10573,7 @@ victory-vendor@^36.6.8: vite-compatible-readable-stream@^3.6.1: version "3.6.1" - resolved "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz#27267aebbdc9893c0ddf65a421279cbb1e31d8cd" + resolved "https://registry.yarnpkg.com/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz#27267aebbdc9893c0ddf65a421279cbb1e31d8cd" integrity sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ== dependencies: inherits "^2.0.3" @@ -11254,54 +10582,54 @@ vite-compatible-readable-stream@^3.6.1: w3c-keyname@^2.2.0: version "2.2.8" - resolved "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== w3c-xmlserializer@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== dependencies: xml-name-validator "^5.0.0" warning@^4.0.2, warning@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== dependencies: loose-envify "^1.0.0" watchpack@^2.4.1: - version "2.4.2" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" - integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + version "2.4.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.4.tgz#473bda72f0850453da6425081ea46fc0d7602947" + integrity sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -web-vitals@^4.2.0: +web-vitals@^4.2.4: version "4.2.4" - resolved "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== webidl-conversions@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== webpack-dev-middleware@^6.1.2: version "6.1.3" - resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz#79f4103f8c898564c9e96c3a9c2422de50f249bc" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz#79f4103f8c898564c9e96c3a9c2422de50f249bc" integrity sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw== dependencies: colorette "^2.0.10" @@ -11312,37 +10640,39 @@ webpack-dev-middleware@^6.1.2: webpack-hot-middleware@^2.25.1: version "2.26.1" - resolved "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz#87214f1e3f9f3acab9271fef9e6ed7b637d719c0" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz#87214f1e3f9f3acab9271fef9e6ed7b637d719c0" integrity sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A== dependencies: ansi-html-community "0.0.8" html-entities "^2.1.0" strip-ansi "^6.0.0" -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== +webpack-sources@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.3.tgz#d4bf7f9909675d7a070ff14d0ef2a4f3c982c723" + integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg== webpack-virtual-modules@^0.6.0, webpack-virtual-modules@^0.6.2: version "0.6.2" - resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== webpack@5: - version "5.97.1" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz#972a8320a438b56ff0f1d94ade9e82eac155fa58" - integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg== + version "5.100.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.100.2.tgz#e2341facf9f7de1d702147c91bcb65b693adf9e8" + integrity sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw== dependencies: "@types/eslint-scope" "^3.7.7" - "@types/estree" "^1.0.6" + "@types/estree" "^1.0.8" + "@types/json-schema" "^7.0.15" "@webassemblyjs/ast" "^1.14.1" "@webassemblyjs/wasm-edit" "^1.14.1" "@webassemblyjs/wasm-parser" "^1.14.1" - acorn "^8.14.0" + acorn "^8.15.0" + acorn-import-phases "^1.0.3" browserslist "^4.24.0" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.1" + enhanced-resolve "^5.17.2" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" @@ -11352,35 +10682,35 @@ webpack@5: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.2.0" + schema-utils "^4.3.2" tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" + terser-webpack-plugin "^5.3.11" watchpack "^2.4.1" - webpack-sources "^3.2.3" + webpack-sources "^3.3.3" whatwg-encoding@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== dependencies: iconv-lite "0.6.3" whatwg-mimetype@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== -whatwg-url@^14.0.0, whatwg-url@^14.1.0: - version "14.1.1" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz#ce71e240c61541315833b5cdafd139a479e47058" - integrity sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ== +whatwg-url@^14.0.0, whatwg-url@^14.1.1: + version "14.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== dependencies: - tr46 "^5.0.0" + tr46 "^5.1.0" webidl-conversions "^7.0.0" whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -11388,7 +10718,7 @@ whatwg-url@^5.0.0: whatwg-url@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== dependencies: lodash.sortby "^4.7.0" @@ -11397,7 +10727,7 @@ whatwg-url@^7.0.0: which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== dependencies: is-bigint "^1.1.0" @@ -11408,7 +10738,7 @@ which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: which-builtin-type@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== dependencies: call-bound "^1.0.2" @@ -11427,7 +10757,7 @@ which-builtin-type@^1.2.1: which-collection@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: is-map "^2.0.3" @@ -11435,28 +10765,29 @@ which-collection@^1.0.2: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.16, which-typed-array@^1.1.18, which-typed-array@^1.1.2: - version "1.1.18" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad" - integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== +which-typed-array@^1.1.16, which-typed-array@^1.1.19, which-typed-array@^1.1.2: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== dependencies: available-typed-arrays "^1.0.7" call-bind "^1.0.8" - call-bound "^1.0.3" - for-each "^0.3.3" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" gopd "^1.2.0" has-tostringtag "^1.0.2" which@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" winston-daily-rotate-file@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-5.0.0.tgz#8cd94800025490e47c00ec892b655a5821f4266d" + resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-5.0.0.tgz#8cd94800025490e47c00ec892b655a5821f4266d" integrity sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw== dependencies: file-stream-rotator "^0.6.1" @@ -11466,7 +10797,7 @@ winston-daily-rotate-file@^5.0.0: winston-transport@^4.7.0, winston-transport@^4.9.0: version "4.9.0" - resolved "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== dependencies: logform "^2.7.0" @@ -11475,7 +10806,7 @@ winston-transport@^4.7.0, winston-transport@^4.9.0: winston@^3.17.0: version "3.17.0" - resolved "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== dependencies: "@colors/colors" "^1.6.0" @@ -11492,12 +10823,12 @@ winston@^3.17.0: word-wrap@^1.2.5: version "1.2.5" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -11506,7 +10837,7 @@ word-wrap@^1.2.5: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -11515,7 +10846,7 @@ wrap-ansi@^7.0.0: wrap-ansi@^8.1.0: version "8.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" @@ -11524,78 +10855,78 @@ wrap-ansi@^8.1.0: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@^7.4.6: version "7.5.10" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== ws@^8.17.1, ws@^8.18.0, ws@^8.2.3, ws@^8.5.0: - version "8.18.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" - integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== xml-name-validator@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== y-indexeddb@^9.0.12: version "9.0.12" - resolved "https://registry.npmjs.org/y-indexeddb/-/y-indexeddb-9.0.12.tgz#73657f31d52886d7532256610babf5cca4ad5e58" + resolved "https://registry.yarnpkg.com/y-indexeddb/-/y-indexeddb-9.0.12.tgz#73657f31d52886d7532256610babf5cca4ad5e58" integrity sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg== dependencies: lib0 "^0.2.74" y-prosemirror@^1.2.15: - version "1.2.15" - resolved "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-1.2.15.tgz#6062ce96efd7465a3404a5aa1a34fb36a2cf7994" - integrity sha512-XDdrytq2M5bIy3qusQvfRclLu2eWZYPA+BbGWAb9FFWEhOB5FCrnzez2vsA+gvAd0FJTAcr89mjJ5g45r0j7TQ== + version "1.3.7" + resolved "https://registry.yarnpkg.com/y-prosemirror/-/y-prosemirror-1.3.7.tgz#f88e553da4ea33278b114cf0b6a0ea978b154e84" + integrity sha512-NpM99WSdD4Fx4if5xOMDpPtU3oAmTSjlzh5U4353ABbRHl1HtAFUx6HlebLZfyFxXN9jzKMDkVbcRjqOZVkYQg== dependencies: - lib0 "^0.2.42" + lib0 "^0.2.109" y-protocols@^1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz#66dad8a95752623443e8e28c0e923682d2c0d495" + resolved "https://registry.yarnpkg.com/y-protocols/-/y-protocols-1.0.6.tgz#66dad8a95752623443e8e28c0e923682d2c0d495" integrity sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q== dependencies: lib0 "^0.2.85" y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yaml@^1.10.0: version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yaml@^2.3.4, yaml@^2.4.2: - version "2.7.0" - resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== + version "2.8.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.0.tgz#15f8c9866211bdc2d3781a0890e44d4fa1a5fff6" + integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ== yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.0.0, yargs@^17.7.2: version "17.7.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -11607,41 +10938,41 @@ yargs@^17.0.0, yargs@^17.7.2: yargs-parser "^21.1.1" yjs@^13.6.20: - version "13.6.23" - resolved "https://registry.npmjs.org/yjs/-/yjs-13.6.23.tgz#62358dfa52e92dc870b8a0bedcf0d4cbd4c5ffa8" - integrity sha512-ExtnT5WIOVpkL56bhLeisG/N5c4fmzKn4k0ROVfJa5TY2QHbH7F0Wu2T5ZhR7ErsFWQEFafyrnSI8TPKVF9Few== + version "13.6.27" + resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.6.27.tgz#8899be929d57da05a0aa112d044a5c204393ab7b" + integrity sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw== dependencies: lib0 "^0.2.99" yn@3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== yoga-layout@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/yoga-layout/-/yoga-layout-2.0.1.tgz#4bc686abe2464f977866650ddccc1dbcf9f0d03c" + resolved "https://registry.yarnpkg.com/yoga-layout/-/yoga-layout-2.0.1.tgz#4bc686abe2464f977866650ddccc1dbcf9f0d03c" integrity sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q== zeed-dom@^0.15.1: version "0.15.1" - resolved "https://registry.npmjs.org/zeed-dom/-/zeed-dom-0.15.1.tgz#dceb759d8a6e7aec042701ebe6684850baaf6193" + resolved "https://registry.yarnpkg.com/zeed-dom/-/zeed-dom-0.15.1.tgz#dceb759d8a6e7aec042701ebe6684850baaf6193" integrity sha512-dtZ0aQSFyZmoJS0m06/xBN1SazUBPL5HpzlAcs/KcRW0rzadYw12deQBjeMhGKMMeGEp7bA9vmikMLaO4exBcg== dependencies: css-what "^6.1.0" entities "^5.0.0" zod@^3.22.2: - version "3.24.2" - resolved "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3" - integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ== + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== zxcvbn@^4.4.2: version "4.4.2" - resolved "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30" + resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30" integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==