diff --git a/.github/workflows/desktop_build_linux.yml b/.github/workflows/desktop_build_linux.yml deleted file mode 100644 index 3efc03e760..0000000000 --- a/.github/workflows/desktop_build_linux.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Desktop build - Linux -on: - push: - tags: - - 'v*' - -jobs: - build: - name: Build Linux desktop app - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Install build deps - run: | - sudo apt install -y python3 make gcc libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev - - name: Build app - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - yarn build-electron:linux --publish always - working-directory: products/jbrowse-desktop diff --git a/.github/workflows/desktop_build_mac.yml b/.github/workflows/desktop_build_mac.yml deleted file mode 100644 index 9ce5790cb8..0000000000 --- a/.github/workflows/desktop_build_mac.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Desktop build - Mac -on: - push: - tags: - - 'v*' - -jobs: - build: - name: Build Mac desktop app - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install build deps - run: | - brew install pkg-config cairo pango libpng jpeg giflib librsvg - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Build app - env: - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} - APPLEID: ${{ secrets.APPLEID }} - APPLEIDPASS: ${{ secrets.APPLEIDPASS }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - yarn build-electron:mac --publish always - working-directory: products/jbrowse-desktop diff --git a/.github/workflows/desktop_build_win.yml b/.github/workflows/desktop_build_win.yml deleted file mode 100644 index d17d892328..0000000000 --- a/.github/workflows/desktop_build_win.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Desktop build - Win -on: - push: - tags: - - 'v*' - -jobs: - build: - name: Build Windows desktop app - runs-on: ubuntu-latest - container: - image: docker://node:20-bullseye - steps: - - uses: actions/checkout@v4 - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Install wine - # https://wiki.debian.org/Wine - run: | - dpkg --add-architecture i386 - apt update - apt install --yes wine wine32 wine64 libwine libwine:i386 fonts-wine - - name: Install build deps - run: | - apt install --yes python3 make gcc libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev - - name: Build app - env: - WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - chown --recursive root:root /github/home - yarn build-electron:win --publish always - working-directory: products/jbrowse-desktop diff --git a/.github/workflows/jbrowse-web.yml b/.github/workflows/jbrowse-web.yml deleted file mode 100644 index bca49123dd..0000000000 --- a/.github/workflows/jbrowse-web.yml +++ /dev/null @@ -1,50 +0,0 @@ -# Upload jbrowse-web release artifact to jbrowse-web tag -on: - push: - tags: - - 'v*' - -name: Upload jbrowse-web artifacts - -jobs: - build: - name: upload_web - runs-on: ubuntu-latest - steps: - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - # This allows us to manually edit the release body text before publishing - draft: true - prerelease: false - - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Set env - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - name: Install deps - run: yarn - - name: Build project - run: | - echo $RELEASE_VERSION - cd products/jbrowse-web/ - NODE_OPTIONS='--max-old-space-size=6500' yarn build - cd build - zip -r "jbrowse-web-${RELEASE_VERSION}.zip" . - - name: Upload jbrowse-web build - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./products/jbrowse-web/build/jbrowse-web-${{env.RELEASE_VERSION}}.zip - asset_name: jbrowse-web-${{env.RELEASE_VERSION}}.zip - asset_content_type: application/zip diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6905fad528..7252781089 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -3,24 +3,6 @@ name: Push on: push jobs: - test: - name: Test and typecheck - runs-on: ubuntu-latest - steps: - - run: sudo apt-get -y install tabix - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Test codebase - run: yarn test-ci - - name: Upload coverage - uses: codecov/codecov-action@v4 - - name: Typecheck codebase - run: yarn typecheck - buildwebsite: name: Build website runs-on: ubuntu-latest @@ -78,7 +60,7 @@ jobs: working-directory: component_tests/react-app buildjbrowseweb: - name: Build only jbrowse-web and upload to s3 + name: Deploy jbrowse-web and storybooks to S3 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -104,17 +86,9 @@ jobs: cd products/jbrowse-web/build && zip -r "jbrowse-web-$(echo ${{github.ref}} | cut -d '/' -f3-).zip" . && cd - cp products/jbrowse-web/build/test_data/config.json products/jbrowse-web/build/config.json aws s3 sync --delete products/jbrowse-web/build s3://jbrowse.org/code/jb2/$(echo ${{github.ref}} | cut -d "/" -f3-) - storybook_lgv: - name: Build and deploy static linear genome view Storybook site to AWS S3 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Build Storybook static site + aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/code/jb2/$(echo ${{github.ref}} | cut -d "/" -f3-)/*" + + - name: Build LGV run: | yarn storybook:build working-directory: products/jbrowse-react-linear-genome-view @@ -124,23 +98,15 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - - name: Deploy Storybook for branch to S3 + + - name: Deploy LGV run: | pwd aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/lgv/$(echo ${{github.ref}} | cut -d "/" -f3-) aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/lgv/$(echo ${{github.ref}} | cut -d "/" -f3-)/*" working-directory: products/jbrowse-react-linear-genome-view - storybook_app: - name: Build and deploy static react app Storybook site to AWS S3 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Build Storybook static site + + - name: Build React App run: | yarn storybook:build working-directory: products/jbrowse-react-app @@ -150,24 +116,14 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - - name: Deploy Storybook for branch to S3 + - name: Deploy React App run: | pwd aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/app/$(echo ${{github.ref}} | cut -d "/" -f3-) aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/app/$(echo ${{github.ref}} | cut -d "/" -f3-)/*" working-directory: products/jbrowse-react-app - storybook_cgv: - name: Build and deploy static circular genome view Storybook site to AWS S3 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps (with cache) - uses: bahmutov/npm-install@v1 - - name: Build Storybook static site + - name: Build CGV run: | yarn storybook:build working-directory: products/jbrowse-react-circular-genome-view @@ -177,29 +133,18 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - - name: Deploy Storybook for branch to S3 + - name: Deploy CGV run: | pwd aws s3 sync --delete storybook-static s3://jbrowse.org/storybook/cgv/$(echo ${{github.ref}} | cut -d "/" -f3-) aws cloudfront create-invalidation --distribution-id E13LGELJOT4GQO --paths "/storybook/cgv/$(echo ${{github.ref}} | cut -d "/" -f3-)/*" working-directory: products/jbrowse-react-circular-genome-view - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install deps and build (with cache) - uses: bahmutov/npm-install@v1 - - name: Lint codebase - run: yarn lint formatchecks: - name: Format/spellcheck/docs + name: Lint, typecheck, test runs-on: ubuntu-latest steps: + - run: sudo apt-get -y install tabix - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: @@ -212,3 +157,11 @@ jobs: run: yarn statedocs && yarn configdocs - name: Spellcheck uses: crate-ci/typos@master + - name: Lint codebase + run: yarn lint + - name: Test codebase + run: yarn test-ci + - name: Upload coverage + uses: codecov/codecov-action@v4 + - name: Typecheck codebase + run: yarn typecheck diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..db4dd1a497 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,122 @@ +name: Release +on: + push: + tags: + - 'v*' + +jobs: + createrelease: + name: Create release tag and JBrowse web release artifacts + runs-on: ubuntu-latest + steps: + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + # This allows us to manually edit the release body text before publishing + draft: true + prerelease: false + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Install deps + run: yarn + - name: Build project + run: | + echo $RELEASE_VERSION + cd products/jbrowse-web/ + NODE_OPTIONS='--max-old-space-size=6500' yarn build + cd build + zip -r "jbrowse-web-${RELEASE_VERSION}.zip" . + - name: Upload jbrowse-web build + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./products/jbrowse-web/build/jbrowse-web-${{env.RELEASE_VERSION}}.zip + asset_name: jbrowse-web-${{env.RELEASE_VERSION}}.zip + asset_content_type: application/zip + buildwindows: + needs: createrelease + name: Build Windows desktop app + runs-on: ubuntu-latest + container: + image: docker://node:20-bullseye + steps: + - uses: actions/checkout@v4 + - name: Install deps (with cache) + uses: bahmutov/npm-install@v1 + - name: Install wine + # https://wiki.debian.org/Wine + run: | + dpkg --add-architecture i386 + apt update + apt install --yes wine wine32 wine64 libwine libwine:i386 fonts-wine + - name: Install build deps + run: | + apt install --yes python3 make gcc libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev + - name: Build app + env: + WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }} + WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + chown --recursive root:root /github/home + yarn build-electron:win --publish always + working-directory: products/jbrowse-desktop + buildmac: + needs: createrelease + name: Build Mac desktop app + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install build deps + run: | + brew install pkg-config cairo pango libpng jpeg giflib librsvg + - name: Install deps (with cache) + uses: bahmutov/npm-install@v1 + - name: Build app + env: + CSC_LINK: ${{ secrets.CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + APPLEID: ${{ secrets.APPLEID }} + APPLEIDPASS: ${{ secrets.APPLEIDPASS }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + yarn build-electron:mac --publish always + working-directory: products/jbrowse-desktop + buildlinux: + needs: createrelease + name: Build Linux desktop app + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install deps (with cache) + uses: bahmutov/npm-install@v1 + - name: Install build deps + run: | + sudo apt install -y python3 make gcc libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev + - name: Build app + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + yarn build-electron:linux --publish always + working-directory: products/jbrowse-desktop diff --git a/.github/workflows/website.yml b/.github/workflows/update-docs.yml similarity index 100% rename from .github/workflows/website.yml rename to .github/workflows/update-docs.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8dd82557..0d70861d40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,49 @@ +yarn run v1.22.22 $ lerna-changelog --silent --silent --next-version 2.15.1 + +## 2.15.1 (2024-09-12) + +#### :rocket: Enhancement + +- `core`, `sv-core` + - [#4561](https://github.com/GMOD/jbrowse-components/pull/4561) Create notion + of launching a single-row breakpoint split view + ([@cmdcolin](https://github.com/cmdcolin)) +- Other + - [#4556](https://github.com/GMOD/jbrowse-components/pull/4556) Add dropdown + menu from bookmark label clicks ([@cmdcolin](https://github.com/cmdcolin)) +- `core` + - [#4554](https://github.com/GMOD/jbrowse-components/pull/4554) Fix the + ability to sort menu items by priority for CascadingMenu + ([@cmdcolin](https://github.com/cmdcolin)) + +#### :bug: Bug Fix + +- Other + - [#4560](https://github.com/GMOD/jbrowse-components/pull/4560) Fix coloring + on circular chord renderings ([@cmdcolin](https://github.com/cmdcolin)) +- `core` + - [#4553](https://github.com/GMOD/jbrowse-components/pull/4553) Fix + performance regression since v2.14.0 in assembly loading + ([@cmdcolin](https://github.com/cmdcolin)) + +#### :house: Internal + +- `core` + - [#4548](https://github.com/GMOD/jbrowse-components/pull/4548) Create + BaseTooltip component in @jbrowse/core/ui + ([@cmdcolin](https://github.com/cmdcolin)) +- Other + - [#4547](https://github.com/GMOD/jbrowse-components/pull/4547) Avoid stream + polyfill for GFF3/GTF parsing ([@cmdcolin](https://github.com/cmdcolin)) + +#### Committers: 1 + +- Colin Diesh ([@cmdcolin](https://github.com/cmdcolin)) Done in 1.16s. + +yarn run v1.22.22 $ lerna-changelog --silent --silent --next-version 2.15.0 + +Done in 1.26s. + yarn run v1.22.22 $ lerna-changelog --silent --silent --next-version 2.14.0 ## 2.14.0 (2024-08-28) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36f0907f66..140b205281 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -213,15 +213,3 @@ particular notes include subpaths like '@jbrowse/core/util' 2. The use of tsconfig.build.json to generate types in the final release 3. The use of referring to the src directory at development time - -## Notes about yarn - -Using `yarn upgrade` or `yarn upgrade-interactive --latest` can produce errors -with the latest version of yarn. This is commonly cited around the web, but -using npx to one-off run an older version of yarn can fix this issues - -Example: - -``` -npx yarn@1.19.1 upgrade-interactive --latest -``` diff --git a/component_tests/cgv/package.json b/component_tests/cgv/package.json index 2d7752e063..85e97b7f70 100644 --- a/component_tests/cgv/package.json +++ b/component_tests/cgv/package.json @@ -42,6 +42,7 @@ "@jbrowse/plugin-variants": "file:./packed/jbrowse-plugin-variants.tgz", "@jbrowse/plugin-wiggle": "file:./packed/jbrowse-plugin-wiggle.tgz", "@jbrowse/product-core": "file:./packed/jbrowse-product-core.tgz", + "@jbrowse/sv-core": "file:./packed/jbrowse-sv-core.tgz", "@jbrowse/embedded-core": "file:./packed/jbrowse-embedded-core.tgz", "@jbrowse/react-linear-genome-view": "file:./packed/jbrowse-react-linear-genome-view.tgz", "@jbrowse/react-circular-genome-view": "file:./packed/jbrowse-react-circular-genome-view.tgz" diff --git a/component_tests/lgv/package.json b/component_tests/lgv/package.json index ff28a82ed1..a0a7c3f5b5 100644 --- a/component_tests/lgv/package.json +++ b/component_tests/lgv/package.json @@ -42,6 +42,7 @@ "@jbrowse/plugin-variants": "file:./packed/jbrowse-plugin-variants.tgz", "@jbrowse/plugin-wiggle": "file:./packed/jbrowse-plugin-wiggle.tgz", "@jbrowse/product-core": "file:./packed/jbrowse-product-core.tgz", + "@jbrowse/sv-core": "file:./packed/jbrowse-sv-core.tgz", "@jbrowse/embedded-core": "file:./packed/jbrowse-embedded-core.tgz", "@jbrowse/react-linear-genome-view": "file:./packed/jbrowse-react-linear-genome-view.tgz" }, diff --git a/component_tests/react-app/package.json b/component_tests/react-app/package.json index 927b0bf7e1..c3f6ebef4f 100644 --- a/component_tests/react-app/package.json +++ b/component_tests/react-app/package.json @@ -55,6 +55,7 @@ "@jbrowse/plugin-spreadsheet-view": "file:./packed/jbrowse-plugin-spreadsheet-view.tgz", "@jbrowse/plugin-sv-inspector": "file:./packed/jbrowse-plugin-sv-inspector.tgz", "@jbrowse/app-core": "file:./packed/jbrowse-app-core.tgz", + "@jbrowse/sv-core": "file:./packed/jbrowse-sv-core.tgz", "@jbrowse/product-core": "file:./packed/jbrowse-product-core.tgz", "@jbrowse/web-core": "file:./packed/jbrowse-web-core.tgz" }, diff --git a/embedded_demos/clone_demos.sh b/embedded_demos/clone_demos.sh index e460de0407..4ec0aa45ab 100755 --- a/embedded_demos/clone_demos.sh +++ b/embedded_demos/clone_demos.sh @@ -5,6 +5,7 @@ git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-vanillajs-demo git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-cra5-demo git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-vite-demo git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-farm-demo +git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-rsbuild-demo git clone git@github.com:GMOD/jbrowse-react-linear-genome-view-nextjs-demo git clone git@github.com:GMOD/jbrowse-react-circular-genome-view-vanillajs-demo @@ -14,5 +15,6 @@ git clone git@github.com:GMOD/jbrowse-react-circular-genome-view-nextjs-demo git clone git@github.com:GMOD/jbrowse-react-app-nextjs-demo git clone git@github.com:GMOD/jbrowse-react-app-vite-demo git clone git@github.com:GMOD/jbrowse-react-app-farm-demo +git clone git@github.com:GMOD/jbrowse-react-app-rsbuild-demo git clone git@github.com:GMOD/jbrowse-react-app-cra5-demo cd - diff --git a/embedded_demos/copy_files.sh b/embedded_demos/copy_files.sh index d0990aaeac..77d1f234ca 100755 --- a/embedded_demos/copy_files.sh +++ b/embedded_demos/copy_files.sh @@ -5,18 +5,21 @@ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view/src/ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-cra5/src/ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-vite/src/ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-farm/src/ +cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-rsbuild/src/ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-nextjs/utils/ cp base/linear/assembly.ts $JB2TMP/jbrowse-react-linear-genome-view-vanillajs/assembly.js cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view/src/ cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-cra5/src/ cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-vite/src/ cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-farm/src/ +cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-rsbuild/src/ cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-nextjs/utils/ cp base/linear/tracks.ts $JB2TMP/jbrowse-react-linear-genome-view-vanillajs/tracks.js cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view/src/ cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-cra5/src/ cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-vite/src/ cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-farm/src/ +cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-rsbuild/src/ cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-nextjs/utils/ cp base/linear/defaultSession.ts $JB2TMP/jbrowse-react-linear-genome-view-vanillajs/defaultSession.js @@ -38,3 +41,4 @@ cp base/app/config.ts $JB2TMP/jbrowse-react-app-cra5/src/ cp base/app/config.ts $JB2TMP/jbrowse-react-app-vite/src/ cp base/app/config.ts $JB2TMP/jbrowse-react-app-farm/src/ cp base/app/config.ts $JB2TMP/jbrowse-react-app-nextjs/utils/ +cp base/app/config.ts $JB2TMP/jbrowse-react-app-rsbuild/utils/ diff --git a/embedded_demos/deploy_demos.sh b/embedded_demos/deploy_demos.sh index 7a14b3b7f5..9cd14a2eef 100755 --- a/embedded_demos/deploy_demos.sh +++ b/embedded_demos/deploy_demos.sh @@ -3,7 +3,9 @@ set -e; cd $JB2TMP for i in jbrowse-react*; do cd $i; + echo "DEPLOY $i"; yarn deploy; + echo "DONE DEPLOY $i" cd -; done; cd - diff --git a/embedded_demos/push_demos.sh b/embedded_demos/push_demos.sh index 9772b83423..669df43e9a 100755 --- a/embedded_demos/push_demos.sh +++ b/embedded_demos/push_demos.sh @@ -2,10 +2,11 @@ cd $JB2TMP for i in jbrowse-react*; do cd $i; - echo `pwd`; + echo "PUSH $i"; git add yarn.lock; git commit -m "Update yarn.lock" git push; + echo "DONE PUSH $i" cd -; done; cd - diff --git a/embedded_demos/update_demos.sh b/embedded_demos/update_demos.sh index c94e2c8fa3..c15cedc5a8 100755 --- a/embedded_demos/update_demos.sh +++ b/embedded_demos/update_demos.sh @@ -3,10 +3,12 @@ set -e; cd $JB2TMP for i in jbrowse-react*; do cd $i; + echo "UPDATE $i"; git stash; git pull; yarn; yarn upgrade; + echo "DONE UPDATE $i"; cd -; done; cd - diff --git a/eslint.config.mjs b/eslint.config.mjs index 6117e9abd0..e981a8e948 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -13,6 +13,7 @@ export default tseslint.config( '**/dist/**/*', '**/esm/**/*', '**/public/**/*', + '**/storybook-static/**', 'website/*', 'packages/core/util/nanoid.js', 'products/**/webpack.config.js', @@ -80,6 +81,7 @@ export default tseslint.config( 'react-refresh/only-export-components': 'warn', 'react/no-unescaped-entities': 'off', + 'react/no-is-mounted': 'off', 'react/prop-types': 'off', 'unicorn/prefer-structured-clone': 'off', diff --git a/lerna.json b/lerna.json index dd4f0d8150..c797e38c7d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.14.0", + "version": "2.15.1", "npmClient": "yarn", "$schema": "node_modules/lerna/schemas/lerna-schema.json" } diff --git a/package.json b/package.json index d6562d4f54..58fba0dcf5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@mui/system": "^6.0.0", "@mui/x-data-grid": "^7.0.0", "@node-oauth/express-oauth-server": "^4.0.0", - "@oclif/core": "^4.0.0", + "@oclif/core": "4.0.19", "@oclif/test": "^4.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", "@r2wc/react-to-web-component": "^2.0.3", @@ -56,7 +56,7 @@ "@types/cors": "^2.8.13", "@types/cross-spawn": "^6.0.2", "@types/crypto-js": "^4.0.1", - "@types/d3-scale": "^3.0.0", + "@types/d3-scale": "^4.0.8", "@types/decompress": "^4.2.4", "@types/deep-equal": "^1.0.1", "@types/detect-node": "^2.0.0", @@ -99,8 +99,8 @@ "dependency-graph": "^1.0.0", "dotenv": "^16.3.1", "dotenv-expand": "^11.0.3", - "electron": "32.0.1", - "electron-builder": "^24.9.0", + "electron": "32.1.0", + "electron-builder": "^25.0.5", "electron-mock-ipc": "^0.3.8", "eslint": "^9.0.0", "eslint-plugin-react": "^7.33.2", @@ -144,7 +144,7 @@ "tslib": "^2.0.1", "tss-react": "^4.0.0", "tsx": "^4.17.0", - "typescript": "^5.1.3", + "typescript": "^5.5.0", "typescript-eslint": "^8.0.1", "webpack": "^5.64.4", "webpack-cli": "^5.1.4", diff --git a/packages/app-core/package.json b/packages/app-core/package.json index e789ab0f7e..40deb110dc 100644 --- a/packages/app-core/package.json +++ b/packages/app-core/package.json @@ -1,6 +1,6 @@ { "name": "@jbrowse/app-core", - "version": "2.14.0", + "version": "2.15.1", "description": "JBrowse 2 code shared between the 'full featured' apps e.g. jbrowse-web and jbrowse-desktop", "keywords": [ "jbrowse", @@ -42,7 +42,7 @@ }, "dependencies": { "@babel/runtime": "^7.16.3", - "@jbrowse/product-core": "^2.14.0", + "@jbrowse/product-core": "^2.15.1", "@mui/icons-material": "^6.0.0", "@mui/material": "^6.0.0", "copy-to-clipboard": "^3.3.1", diff --git a/packages/core/BaseFeatureWidget/BaseFeatureDetail/util.ts b/packages/core/BaseFeatureWidget/BaseFeatureDetail/util.ts index 52bd881381..c02cca7915 100644 --- a/packages/core/BaseFeatureWidget/BaseFeatureDetail/util.ts +++ b/packages/core/BaseFeatureWidget/BaseFeatureDetail/util.ts @@ -7,7 +7,7 @@ export function isEmpty(obj: Record) { } export function generateTitle(name: unknown, id: unknown, type: unknown) { - return [ellipses(`${name}` || `${id}`), `${type}`] + return [ellipses(`${name || id || ''}`), `${type}`] .filter(f => !!f) .join(' - ') } diff --git a/packages/core/BaseFeatureWidget/__snapshots__/index.test.tsx.snap b/packages/core/BaseFeatureWidget/__snapshots__/index.test.tsx.snap index f0cf7b8cac..f7d07a66f5 100644 --- a/packages/core/BaseFeatureWidget/__snapshots__/index.test.tsx.snap +++ b/packages/core/BaseFeatureWidget/__snapshots__/index.test.tsx.snap @@ -3,31 +3,31 @@ exports[`open up a widget 1`] = `

Core details

@@ -92,10 +92,10 @@ exports[`open up a widget 1`] = `

Attributes

@@ -120,10 +120,10 @@ exports[`open up a widget 1`] = ` class="css-57ilie-container" >
+ + + + ) +}) + +export default BreakendMultiLevelOptionDialog diff --git a/packages/sv-core/src/BreakendSingleLevelOptionDialog.tsx b/packages/sv-core/src/BreakendSingleLevelOptionDialog.tsx new file mode 100644 index 0000000000..a1a17e2310 --- /dev/null +++ b/packages/sv-core/src/BreakendSingleLevelOptionDialog.tsx @@ -0,0 +1,167 @@ +import React, { useState } from 'react' +import { observer } from 'mobx-react' +import { Button, DialogActions, DialogContent, TextField } from '@mui/material' +import { getSnapshot } from 'mobx-state-tree' +import { Dialog } from '@jbrowse/core/ui' +import { + getSession, + Feature, + gatherOverlaps, + useLocalStorage, +} from '@jbrowse/core/util' +import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' +import type { Assembly } from '@jbrowse/core/assemblyManager/assembly' + +// locals +import Checkbox2 from './Checkbox2' + +interface Display { + id: string + [key: string]: unknown +} +interface Track { + id: string + displays: Display[] + [key: string]: unknown +} + +function stripIds(arr: Track[]) { + return arr.map(({ id, displays, ...rest }) => ({ + ...rest, + displays: displays.map(({ id, ...rest }) => rest), + })) +} + +const BreakendSingleLevelOptionDialog = observer(function ({ + model, + handleClose, + feature, + assemblyName, + viewType, + view, +}: { + model: unknown + handleClose: () => void + feature: Feature + view: LinearGenomeViewModel + assemblyName: string + viewType: { + getBreakendCoveringRegions: (arg: { + feature: Feature + assembly: Assembly + }) => { + pos: number + refName: string + mateRefName: string + matePos: number + } + } +}) { + const [copyTracks, setCopyTracks] = useState(true) + const [windowSize, setWindowSize] = useLocalStorage( + 'breakpointWindowSize', + '5000', + ) + + return ( + + + { + setCopyTracks(event.target.checked) + }} + /> + + { + setWindowSize(event.target.value) + }} + /> + + + + + + + ) +}) + +export default BreakendSingleLevelOptionDialog diff --git a/packages/sv-core/src/Checkbox2.tsx b/packages/sv-core/src/Checkbox2.tsx new file mode 100644 index 0000000000..3b9232e65c --- /dev/null +++ b/packages/sv-core/src/Checkbox2.tsx @@ -0,0 +1,31 @@ +import React from 'react' +import { Checkbox, FormControlLabel } from '@mui/material' +import { makeStyles } from 'tss-react/mui' + +const useStyles = makeStyles()({ + block: { + display: 'block', + }, +}) + +export default function Checkbox2({ + checked, + disabled, + label, + onChange, +}: { + checked: boolean + disabled?: boolean + label: string + onChange: (event: React.ChangeEvent) => void +}) { + const { classes } = useStyles() + return ( + } + label={label} + /> + ) +} diff --git a/packages/sv-core/src/index.ts b/packages/sv-core/src/index.ts new file mode 100644 index 0000000000..46ef2c579a --- /dev/null +++ b/packages/sv-core/src/index.ts @@ -0,0 +1,2 @@ +export { default as BreakendMultiLevelOptionDialog } from './BreakendMultiLevelOptionDialog' +export { default as BreakendSingleLevelOptionDialog } from './BreakendSingleLevelOptionDialog' diff --git a/packages/sv-core/tsconfig.build.commonjs.json b/packages/sv-core/tsconfig.build.commonjs.json new file mode 120000 index 0000000000..2625244379 --- /dev/null +++ b/packages/sv-core/tsconfig.build.commonjs.json @@ -0,0 +1 @@ +../tsconfig.build.commonjs.json \ No newline at end of file diff --git a/packages/sv-core/tsconfig.build.esm.json b/packages/sv-core/tsconfig.build.esm.json new file mode 120000 index 0000000000..bb016715b3 --- /dev/null +++ b/packages/sv-core/tsconfig.build.esm.json @@ -0,0 +1 @@ +../tsconfig.build.esm.json \ No newline at end of file diff --git a/packages/text-indexing/package.json b/packages/text-indexing/package.json index 0dd6ae0712..149121b4dc 100644 --- a/packages/text-indexing/package.json +++ b/packages/text-indexing/package.json @@ -1,6 +1,6 @@ { "name": "@jbrowse/text-indexing", - "version": "2.14.0", + "version": "2.15.1", "description": "JBrowse 2 text indexing for desktop", "keywords": [ "jbrowse", @@ -42,7 +42,7 @@ }, "dependencies": { "@babel/runtime": "^7.16.3", - "@jbrowse/core": "^2.14.0", + "@jbrowse/core": "^2.15.1", "ixixx": "^2.0.1", "node-fetch": "^2.6.0", "sanitize-filename": "^1.6.3" diff --git a/packages/web-core/package.json b/packages/web-core/package.json index 9dca10050b..c05bf51656 100644 --- a/packages/web-core/package.json +++ b/packages/web-core/package.json @@ -1,6 +1,6 @@ { "name": "@jbrowse/web-core", - "version": "2.14.0", + "version": "2.15.1", "description": "JBrowse 2 code shared between web-app type products", "keywords": [ "jbrowse", @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/runtime": "^7.16.3", - "@jbrowse/app-core": "^2.14.0", - "@jbrowse/product-core": "^2.14.0", + "@jbrowse/app-core": "^2.15.1", + "@jbrowse/product-core": "^2.15.1", "@mui/icons-material": "^6.0.0", "@mui/material": "^6.0.0", "clone": "^2.0.0", diff --git a/packages/web-core/src/BaseWebSession/index.ts b/packages/web-core/src/BaseWebSession/index.ts index 948d3bc05c..8ea0bafc5b 100644 --- a/packages/web-core/src/BaseWebSession/index.ts +++ b/packages/web-core/src/BaseWebSession/index.ts @@ -356,6 +356,7 @@ export function BaseWebSession({ return [ { label: 'About track', + priority: 1002, onClick: () => { self.queueDialog(handleClose => [ AboutDialog, @@ -366,6 +367,7 @@ export function BaseWebSession({ }, { label: 'Settings', + priority: 1001, disabled: !canEdit, onClick: () => { self.editTrackConfiguration(config) @@ -374,12 +376,14 @@ export function BaseWebSession({ }, { label: 'Delete track', + priority: 1000, disabled: !canEdit || isRefSeq, onClick: () => self.deleteTrackConf(config), icon: DeleteIcon, }, { label: 'Copy track', + priority: 999, disabled: isRefSeq, onClick: () => { interface Display { diff --git a/plugins/alignments/package.json b/plugins/alignments/package.json index 476e7ee9aa..1509e92047 100644 --- a/plugins/alignments/package.json +++ b/plugins/alignments/package.json @@ -1,6 +1,6 @@ { "name": "@jbrowse/plugin-alignments", - "version": "2.14.0", + "version": "2.15.1", "description": "JBrowse 2 alignments adapters, tracks, etc.", "keywords": [ "jbrowse", @@ -38,6 +38,7 @@ "dependencies": { "@gmod/bam": "^2.0.0", "@gmod/cram": "^3.0.3", + "@jbrowse/sv-core": "^2.15.1", "@mui/icons-material": "^6.0.0", "canvas2svg": "^1.0.16", "clone": "^2.1.2", diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/AlignmentsFeatureDetail.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/AlignmentsFeatureDetail.tsx index 92ebf4c4c5..b7150f2f6d 100644 --- a/plugins/alignments/src/AlignmentsFeatureDetail/AlignmentsFeatureDetail.tsx +++ b/plugins/alignments/src/AlignmentsFeatureDetail/AlignmentsFeatureDetail.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { lazy } from 'react' import { Paper } from '@mui/material' import { observer } from 'mobx-react' import clone from 'clone' @@ -10,11 +10,14 @@ import { tags } from './tagInfo' import { AlignmentFeatureWidgetModel } from './stateModelFactory' // local components -import SuppAlignments from './SuppAlignments' import Flags from './Flags' import PairLink from './PairLink' import Formatter from './Formatter' +// lazies +const SupplementaryAlignments = lazy(() => import('./SupplementaryAlignments')) +const LinkedPairedAlignments = lazy(() => import('./LinkedPairedAlignments')) + const omit = ['clipPos', 'flags'] const AlignmentsFeatureDetails = observer(function (props: { @@ -42,7 +45,10 @@ const AlignmentsFeatureDetails = observer(function (props: { } /> {SA !== undefined ? ( - + + ) : null} + {flags & 1 ? ( + ) : null} {flags !== undefined ? : null} diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/BreakendMultiLevelOptionDialog.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/BreakendMultiLevelOptionDialog.tsx new file mode 100644 index 0000000000..f2aedc807b --- /dev/null +++ b/plugins/alignments/src/AlignmentsFeatureDetail/BreakendMultiLevelOptionDialog.tsx @@ -0,0 +1,2 @@ +// re-exported for react lazy +export { BreakendMultiLevelOptionDialog as default } from '@jbrowse/sv-core' diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/BreakendOptionDialog.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/BreakendOptionDialog.tsx deleted file mode 100644 index 15e237f912..0000000000 --- a/plugins/alignments/src/AlignmentsFeatureDetail/BreakendOptionDialog.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import React, { useState } from 'react' -import { observer } from 'mobx-react' -import { - Button, - Checkbox, - DialogActions, - DialogContent, - FormControlLabel, -} from '@mui/material' -import { makeStyles } from 'tss-react/mui' -import { getSession } from '@jbrowse/core/util' -import { Dialog } from '@jbrowse/core/ui' -import { ViewType } from '@jbrowse/core/pluggableElementTypes' - -// locals -import { AlignmentFeatureWidgetModel } from './stateModelFactory' -import { getBreakpointSplitView } from './launchBreakpointSplitView' -import { getSnapshot } from 'mobx-state-tree' -import { ReducedFeature } from './getSAFeatures' - -const useStyles = makeStyles()({ - block: { - display: 'block', - }, -}) - -interface Track { - id: string - displays: { id: string; [key: string]: unknown }[] - [key: string]: unknown -} - -function stripIds(arr: Track[]) { - return arr.map(({ id, displays, ...rest }) => ({ - ...rest, - displays: displays.map(({ id, ...rest }) => rest), - })) -} - -function Checkbox2({ - checked, - label, - onChange, -}: { - checked: boolean - label: string - onChange: (event: React.ChangeEvent) => void -}) { - const { classes } = useStyles() - return ( - } - label={label} - /> - ) -} - -const BreakendOptionDialog = observer(function ({ - model, - handleClose, - f1, - f2, -}: { - model: AlignmentFeatureWidgetModel - handleClose: () => void - f1: ReducedFeature - f2: ReducedFeature - viewType: ViewType -}) { - const [copyTracks, setCopyTracks] = useState(true) - const [mirror, setMirror] = useState(true) - - return ( - - - { - setCopyTracks(event.target.checked) - }} - label="Copy tracks into the new view" - /> - { - setMirror(event.target.checked) - }} - label="Mirror tracks vertically in vertically stacked view" - /> - - - - - - - ) -}) - -export default BreakendOptionDialog diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/BreakendSingleLevelOptionDialog.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/BreakendSingleLevelOptionDialog.tsx new file mode 100644 index 0000000000..e7bdfdc631 --- /dev/null +++ b/plugins/alignments/src/AlignmentsFeatureDetail/BreakendSingleLevelOptionDialog.tsx @@ -0,0 +1,2 @@ +// re-exported for react lazy +export { BreakendSingleLevelOptionDialog as default } from '@jbrowse/sv-core' diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/LaunchBreakpointSplitViewPanel.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/LaunchBreakpointSplitViewPanel.tsx deleted file mode 100644 index 7887e036c9..0000000000 --- a/plugins/alignments/src/AlignmentsFeatureDetail/LaunchBreakpointSplitViewPanel.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React, { lazy, useEffect, useState } from 'react' -import { Typography, Link, Tooltip } from '@mui/material' -import { - SimpleFeature, - SimpleFeatureSerialized, - getSession, - toLocale, -} from '@jbrowse/core/util' -import { ErrorMessage } from '@jbrowse/core/ui' -import { ViewType } from '@jbrowse/core/pluggableElementTypes' - -// locals -import { AlignmentFeatureWidgetModel } from './stateModelFactory' -import { ReducedFeature, getSAFeatures } from './getSAFeatures' - -// lazies -const BreakendOptionDialog = lazy(() => import('./BreakendOptionDialog')) - -export default function LaunchBreakpointSplitViewPanel({ - model, - feature, - viewType, -}: { - model: AlignmentFeatureWidgetModel - feature: SimpleFeatureSerialized - viewType: ViewType -}) { - const session = getSession(model) - const { view } = model - const [res, setRes] = useState() - const [error, setError] = useState() - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - ;(async () => { - try { - const feats = await getSAFeatures({ - view, - feature: new SimpleFeature(feature), - }) - setRes(feats) - } catch (e) { - setError(e) - console.error(e) - } - })() - }, [feature, view]) - - const ret = [] as [ReducedFeature, ReducedFeature][] - if (res) { - for (let i = 0; i < res.length - 1; i++) { - ret.push([res[i]!, res[i + 1]!] as const) - } - } - return ret.length ? ( -
- - Launch split views with breakend source and target - - {error ? : null} -
    - {ret.map((arg, index) => { - const [f1, f2] = arg - return ( -
  • - - { - event.preventDefault() - session.queueDialog(handleClose => [ - BreakendOptionDialog, - { handleClose, f1, f2, model, viewType }, - ]) - }} - > - {f1.refName}:{toLocale(f1.strand === 1 ? f1.end : f1.start)}{' '} - -> {f2.refName}: - {toLocale(f2.strand === 1 ? f2.start : f2.end)} - - -
  • - ) - })} -
-
- ) : null -} diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.tsx new file mode 100644 index 0000000000..4fecfe1121 --- /dev/null +++ b/plugins/alignments/src/AlignmentsFeatureDetail/LaunchPairedEndBreakpointSplitViewPanel.tsx @@ -0,0 +1,97 @@ +import React, { lazy } from 'react' +import { Typography, Link } from '@mui/material' +import { + SimpleFeature, + SimpleFeatureSerialized, + getSession, + toLocale, +} from '@jbrowse/core/util' +import { ViewType } from '@jbrowse/core/pluggableElementTypes' + +// locals +import { AlignmentFeatureWidgetModel } from './stateModelFactory' + +// lazies +const BreakendMultiLevelOptionDialog = lazy( + () => import('./BreakendMultiLevelOptionDialog'), +) +const BreakendSingleLevelOptionDialog = lazy( + () => import('./BreakendSingleLevelOptionDialog'), +) + +export default function LaunchPairedEndBreakpointSplitViewPanel({ + model, + feature, + viewType, +}: { + model: AlignmentFeatureWidgetModel + feature: SimpleFeatureSerialized + viewType: ViewType +}) { + const session = getSession(model) + const f1 = { + uniqueId: feature.uniqueId, + refName: feature.refName, + start: feature.start, + end: feature.end, + strand: feature.strand, + } + const f2 = { + uniqueId: `${feature.id}-mate`, + refName: feature.next_ref as string, + start: feature.next_pos as number, + end: (feature.next_pos as number) + 1, + strand: feature.strand as number, + } + return ( +
+ Launch split view +
    +
  • + {f1.refName}:{toLocale(f1.start)} -> {f2.refName}: + {toLocale(f2.start)}{' '} + { + event.preventDefault() + session.queueDialog(handleClose => [ + BreakendMultiLevelOptionDialog, + { + handleClose, + model, + feature: new SimpleFeature({ ...f1, mate: f2 }), + // @ts-expect-error + viewType, + view: model.view, + assemblyName: model.view.displayedRegions[0].assemblyName, + }, + ]) + }} + > + (top/bottom) + {' '} + { + event.preventDefault() + session.queueDialog(handleClose => [ + BreakendSingleLevelOptionDialog, + { + handleClose, + model, + feature: new SimpleFeature({ ...f1, mate: f2 }), + // @ts-expect-error + viewType, + view: model.view, + assemblyName: model.view.displayedRegions[0].assemblyName, + }, + ]) + }} + > + (single row) + +
  • +
+
+ ) +} diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.tsx new file mode 100644 index 0000000000..35d7e14d6c --- /dev/null +++ b/plugins/alignments/src/AlignmentsFeatureDetail/LaunchSupplementaryAlignmentBreakpointSplitViewPanel.tsx @@ -0,0 +1,116 @@ +import React, { lazy, useEffect, useState } from 'react' +import { Typography, Link } from '@mui/material' +import { + SimpleFeature, + SimpleFeatureSerialized, + getSession, + toLocale, +} from '@jbrowse/core/util' +import { ErrorMessage } from '@jbrowse/core/ui' +import { ViewType } from '@jbrowse/core/pluggableElementTypes' + +// locals +import { AlignmentFeatureWidgetModel } from './stateModelFactory' +import { ReducedFeature, getSAFeatures } from './getSAFeatures' + +// lazies +const BreakendMultiLevelOptionDialog = lazy( + () => import('./BreakendMultiLevelOptionDialog'), +) +const BreakendSingleLevelOptionDialog = lazy( + () => import('./BreakendSingleLevelOptionDialog'), +) + +export default function LaunchBreakpointSplitViewPanel({ + model, + feature, + viewType, +}: { + model: AlignmentFeatureWidgetModel + feature: SimpleFeatureSerialized + viewType: ViewType +}) { + const session = getSession(model) + const { view } = model + const [res, setRes] = useState() + const [error, setError] = useState() + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + try { + const feats = await getSAFeatures({ + view, + feature: new SimpleFeature(feature), + }) + setRes(feats) + } catch (e) { + setError(e) + console.error(e) + } + })() + }, [feature, view]) + + const ret = [] as [ReducedFeature, ReducedFeature][] + if (res) { + for (let i = 0; i < res.length - 1; i++) { + ret.push([res[i]!, res[i + 1]!] as const) + } + } + return ret.length ? ( +
+ Launch split view + {error ? : null} +
    + {ret.map((arg, index) => { + const [f1, f2] = arg + return ( +
  • + {f1.refName}:{toLocale(f1.strand === 1 ? f1.end : f1.start)} ->{' '} + {f2.refName}:{toLocale(f2.strand === 1 ? f2.start : f2.end)}{' '} + { + event.preventDefault() + session.queueDialog(handleClose => [ + BreakendMultiLevelOptionDialog, + { + handleClose, + model, + feature: new SimpleFeature({ ...f1, mate: f2 }), + // @ts-expect-error + viewType, + view: model.view, + assemblyName: model.view.displayedRegions[0].assemblyName, + }, + ]) + }} + > + (top/bottom) + {' '} + { + event.preventDefault() + session.queueDialog(handleClose => [ + BreakendSingleLevelOptionDialog, + { + handleClose, + model, + feature: new SimpleFeature({ ...f1, mate: f2 }), + // @ts-expect-error + viewType, + view: model.view, + assemblyName: model.view.displayedRegions[0].assemblyName, + }, + ]) + }} + > + (single row) + +
  • + ) + })} +
+
+ ) : null +} diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/LinkedPairedAlignments.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/LinkedPairedAlignments.tsx new file mode 100644 index 0000000000..2afcc7f1c1 --- /dev/null +++ b/plugins/alignments/src/AlignmentsFeatureDetail/LinkedPairedAlignments.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail' +import { SimpleFeatureSerialized, getEnv, getSession } from '@jbrowse/core/util' +import { ViewType } from '@jbrowse/core/pluggableElementTypes' + +// locals +import { AlignmentFeatureWidgetModel } from './stateModelFactory' +import LaunchPairedEndBreakpointSplitViewPanel from './LaunchPairedEndBreakpointSplitViewPanel' + +export default function SuppAlignments(props: { + model: AlignmentFeatureWidgetModel + feature: SimpleFeatureSerialized +}) { + const { model, feature } = props + const session = getSession(model) + const { pluginManager } = getEnv(session) + let viewType: ViewType | undefined + + try { + viewType = pluginManager.getViewType('BreakpointSplitView') + } catch (e) { + // ignore + } + + return ( + + {viewType ? ( + + ) : null} + + ) +} diff --git a/plugins/alignments/src/AlignmentsFeatureDetail/SuppAlignments.tsx b/plugins/alignments/src/AlignmentsFeatureDetail/SupplementaryAlignments.tsx similarity index 75% rename from plugins/alignments/src/AlignmentsFeatureDetail/SuppAlignments.tsx rename to plugins/alignments/src/AlignmentsFeatureDetail/SupplementaryAlignments.tsx index d8b1f128c0..948a88d726 100644 --- a/plugins/alignments/src/AlignmentsFeatureDetail/SuppAlignments.tsx +++ b/plugins/alignments/src/AlignmentsFeatureDetail/SupplementaryAlignments.tsx @@ -5,10 +5,10 @@ import { ViewType } from '@jbrowse/core/pluggableElementTypes' // locals import { AlignmentFeatureWidgetModel } from './stateModelFactory' -import SuppAlignmentsLocStrings from './SuppAlignmentsLocStrings' -import LaunchBreakpointSplitViewPanel from './LaunchBreakpointSplitViewPanel' +import SupplementaryAlignmentsLocStrings from './SupplementaryAlignmentsLocStrings' +import LaunchBreakpointSplitViewPanel from './LaunchSupplementaryAlignmentBreakpointSplitViewPanel' -export default function SuppAlignments(props: { +export default function SupplementaryAlignments(props: { tag: string model: AlignmentFeatureWidgetModel feature: SimpleFeatureSerialized @@ -26,7 +26,7 @@ export default function SuppAlignments(props: { return ( - + {viewType ? (

ctgA_3_555_0:0:0_2:0... - match

Core details

@@ -131,10 +131,10 @@ exports[`open up a widget 1`] = `

Attributes

@@ -289,10 +289,10 @@ exports[`open up a widget 1`] = ` class="css-57ilie-container" >

stringArrayTest

@@ -315,44 +315,44 @@ exports[`renders all the different types of built-in slots 1`] = ` />
key1

Values associated with entry key1

stringArrayMapTest

@@ -533,17 +533,17 @@ exports[`renders all the different types of built-in slots 1`] = ` />