Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visualize 3D models locally without relying on sketchfab iframe #2091

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
56afecb
feat: able to render 3d models locally
luistoptal Nov 10, 2024
b65a3ab
feat: use jquery
luistoptal Nov 10, 2024
5d3bdd1
feat: scaffold model viewer refactor
luistoptal Nov 11, 2024
d16a28b
feat: able to visualize rendered models
luistoptal Nov 12, 2024
e572f03
feat: model looks similar to sketchfab
luistoptal Nov 12, 2024
7ced357
feat: adds multitud of small refactorings
luistoptal Nov 12, 2024
97bf32f
feat: load ply, obj and las models
luistoptal Nov 13, 2024
d76ca05
feat: responsive canvas and refactored ui code
luistoptal Nov 13, 2024
31d6c99
feat: improves help controls
luistoptal Nov 13, 2024
4c15ea4
feat: adds fullscreen btn
luistoptal Nov 13, 2024
ba975be
feat: refactors root ui script, colocates selectors, adds js docs
luistoptal Nov 13, 2024
33e4a05
feat: integrates model viewer into dataset page
luistoptal Nov 14, 2024
e83abd2
feat: improves a11y for model loading state
luistoptal Nov 14, 2024
5053b67
chore: remove debug logs
luistoptal Nov 14, 2024
f051629
chore: up log
luistoptal Nov 14, 2024
e858b73
chore: undoes ignored temp models folder
luistoptal Nov 14, 2024
e064ace
feat: adds jsdocs
luistoptal Nov 14, 2024
bd824ca
chore: Merge branch 'develop' into new-feature/2054-3d-image-viewer
luistoptal Nov 14, 2024
d3c9334
chore: update 3d models tab test
luistoptal Nov 20, 2024
6a8e1e7
feat: tests for model selector
luistoptal Nov 20, 2024
336b89a
fix: undoes bug introduced by trim func
luistoptal Nov 20, 2024
5bd9b1c
chore: add https://cdn.jsdelivr.net to nginx config
luistoptal Nov 20, 2024
bf0e900
feat: add 3d models to test db and tests
luistoptal Nov 21, 2024
d0e4167
chore: adds model source to nginx
luistoptal Nov 21, 2024
226be5f
chore: Merge branch 'develop' into new-feature/2054-3d-image-viewer
luistoptal Nov 21, 2024
3eb5306
chore: cleanup tests
luistoptal Nov 22, 2024
b004b38
fix: displays 3d models only in 3d models tab panel
luistoptal Nov 22, 2024
60ae2f7
fix: render model viewer only once
luistoptal Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@ php-conf/appconfig.ini
params-local.php

# release related artefacts
VERSION
VERSION
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased

- Feat #2054: Visualize 3D models locally without relying on sketchfab iframe
- Fix #2094: Make Semgrep-based SAST analyzer available in tagged release
- Feat #701: Code refactoring to separate upload status transitions and notifications to prepare for upload status overhaul
- Security #1867: Update the gitlab static application security testing (SAST) job using the Semgrep-based analyzer
Expand Down
3 changes: 3 additions & 0 deletions data/dev/external_link.csv
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ id,dataset_id,url,external_link_type_id
36,144,https://github.com/ShashaankV/GD,1
1525,2342,https://scicrunch.org/resolver/RRID:SCR_021313,1
1526,2342,https://github.com/cihga39871/Atria,7
1527,8,https://s3.ap-northeast-1.wasabisys.com/gigadb-datasets/dev/tests/3d-models/100006/leaf_01.las,5
1528,8,https://s3.ap-northeast-1.wasabisys.com/gigadb-datasets/dev/tests/3d-models/100006/beet_03.stl,5
1529,8,https://s3.ap-northeast-1.wasabisys.com/gigadb-datasets/dev/tests/3d-models/100006/GeoB8502_865cm_Shell-4.obj,5
5 changes: 1 addition & 4 deletions features/bootstrap/DatasetViewContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,7 @@ public function iShouldNotSeeTabWithTable($arg1, TableNode $table)
*/
public function iHaveAddedLinkToDataset($arg1, $arg2, $arg3)
{
if ("3D Viewer" == $arg1 ) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kencho51 since I deleted the 3D Models test, I am also deleting this switch case

$this->gigadbWebsiteContext->loadUserData("3D_Viewer_${arg3}_test_data");
}
elseif ("Code Ocean" == $arg1 ) {
if ("Code Ocean" == $arg1 ) {
$this->gigadbWebsiteContext->loadUserData("Code_Ocean_${arg3}_test_data");
}
else {
Expand Down
7 changes: 0 additions & 7 deletions features/dataset-view.feature
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,6 @@ Feature: a user visit the dataset page
| Funding body | Awardee | Award ID | Comments |
| National Science Foundation | Matthew W. Hahn | DEB-1249633 | Matthew W Hahn |

@ok
Scenario: 3D Viewer
Given I am not logged in to Gigadb web site
And I have added "3D Viewer" link "https://sketchfab.com/models/ea49d0dd500647cbb4b61ad5ca9e659a" to dataset "101001"
When I go to "/dataset/101001"
Then I should see "3D Models" tab with text "3D Models:"

@ok
Scenario: Protocols.io
Given I am not logged in to Gigadb web site
Expand Down
3 changes: 2 additions & 1 deletion less/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@
@import "modules/team-grid.less";
@import "modules/map.less";
@import "modules/lists.less";
@import "modules/tooltip.less";
@import "modules/tooltip.less";
@import "modules/model-viewer.less";
10 changes: 10 additions & 0 deletions less/modules/datatables.less
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,13 @@ table.dataTable thead {
.tab-content {
overflow: hidden;
}

.dataset-tab-content {
overflow: visible;
[role="tabpanel"] {
overflow: hidden;
&.visible {
overflow: visible;
}
}
}
304 changes: 304 additions & 0 deletions less/modules/model-viewer.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
// stack order
@stack-order-controls-info: 1;
@stack-order-play-button: 2;
@stack-order-loading-overlay: 3;
@stack-order-error-display: 4;
@stack-order-help-modal: 5;
@stack-order-fullscreen: 9999;
@stack-order-fullscreen-controls: 10000;
@stack-order-fullscreen-help-modal: 10001;


.model-selector {
width: 450px;
margin-bottom: 20px;
}

.model-viewer-container {
position: relative;
width: 912px;
height: 512px;
background: transparent;
}

@media (max-width: 912px) {
.model-viewer-container {
width: 100%;
height: auto;
aspect-ratio: 1.78;
}
}

.canvas-container {
width: 100%;
height: 100%;
background-color: @color-light-gray;
display: block;
}

// controls info

.controls {
position: absolute;
background: transparent;
color: @color-true-white;
bottom: 0;
right: 0;
padding: 12px;
z-index: @stack-order-controls-info;
display: flex;
gap: 6px;
}

.controls .controls-btn {
text-decoration: none;
color: @color-warm-black;
background: transparent;
font-size: 18px;
opacity: 0.8;
transition: opacity 0.2s ease, background 0.2s ease;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;

&:hover {
opacity: 1;
color: @color-true-white;
text-decoration: none;
background: rgba(0, 0, 0, 0.5);
}
}

// help modal

.help-modal {
position: absolute;
inset: 0;
z-index: @stack-order-help-modal;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
color: @color-true-white;

.help-modal-content {
background: rgba(0, 0, 0, 0.9);
border-radius: 8px;
padding: 24px;
min-width: 300px;
max-width: 90%;
}

.help-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;

.help-modal-title {
margin: 0;
font-size: 18px;
font-weight: bold;
}

.help-modal-close {
background: transparent;
border: none;
color: @color-true-white;
font-size: 20px;
padding: 4px;
cursor: pointer;
opacity: 0.8;

&:hover {
opacity: 1;
}
}
}

.help-modal-body {
h3 {
font-size: 14px;
margin: 0 0 16px 0;
opacity: 0.8;
}

.help-control {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 16px;

i {
font-size: 24px;
width: 24px;
text-align: center;
}

.help-control-text {
div:first-child {
font-weight: bold;
margin-bottom: 4px;
}

.help-control-detail {
font-size: 14px;
opacity: 0.8;
}
}
}
}
}

.model-viewer-container.fullscreen {
.canvas-container {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: @stack-order-fullscreen;
}

.controls {
position: fixed;
bottom: 0;
right: 0;
z-index: @stack-order-fullscreen-controls;
}

.help-modal {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: @stack-order-fullscreen-help-modal;
}
}

// play button

.play-button-overlay {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: @stack-order-play-button;
background: rgba(0, 0, 0, 0.3);
}

.play-button {
width: 150px;
height: 150px;
background: rgba(0, 0, 0, 0.5);
color: @color-true-white;
border: none;
border-radius: 50%;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.2s ease-in-out, background 0.3s ease-in-out;
}

.play-button:hover {
transform: scale(1.1);
background: @color-gigadb-green;
box-shadow: 0 0 40px rgba(255, 255, 255, 0.5),
0 0 20px fade(@color-gigadb-green, 60%);
}

.play-button:focus {
outline: none;
box-shadow: 0 0 0 4px @color-true-white,
0 0 0 8px @color-gigadb-green,
0 0 0 12px fade(@color-gigadb-green, 30%);
}

.play-button-icon {
font-size: 70px;
position: relative;
/* make button look visually centered */
left: 6px;
}

@media (max-width: 768px) {
.play-button {
width: 120px;
height: 120px;
padding: 16px;

.play-button-icon {
font-size: 50px;
}
}
}

// loading overlay

.loading-overlay {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
z-index: @stack-order-loading-overlay;
background: rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
}

.loading-overlay.active {
display: flex;
}

.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid transparent;
border-top: 4px solid @color-gigadb-green;
border-radius: 50%;
animation: spin 0.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
margin-bottom: 8px;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}

100% {
transform: rotate(360deg);
}
}

.loading-text {
font-size: 18px;
color: @color-warm-black;
opacity: 1;
text-align: center;
margin-top: 5px;
font-weight: 500;
}

// error display

.error-display {
max-width: 100%;
position: absolute;
inset-inline: 12px;
bottom: 12px;
margin: 0;
z-index: @stack-order-error-display;
}

// model description
.model-description {
// avoid layout shift
height: 22px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ server {
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' http://gigadb.org http://penguin.genomics.cn https://www.rosaceae.org *.protocols.io https://sketchfab.com https://codeocean.com *.hypothes.is *.datatables.net *.cloudflare.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.matomo.cloud/gigadb.matomo.cloud/matomo.js *.hypothes.is *.datatables.net *.cloudflare.com *.google-analytics.com https://www.rosaceae.org https://www.protocols.io https://hypothes.is https://codeocean.com https://tumormap.ucsc.edu https://openlayers.org/en/v4.6.5/build/ol.js; frame-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu; child-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu; img-src blob: data: 'self' https://assets.gigadb-cdn.net *.tile.openstreetmap.org; report-uri https://gigadb.report-uri.com/r/d/csp/enforce;";
add_header Content-Security-Policy-Report-Only "default-src 'self' https://gigadb.org; script-src 'self' https://cdn.matomo.cloud/gigadb.matomo.cloud/matomo.js https://*.hypothes.is https://*.datatables.net https://*.cloudflare.com https://*.google-analytics.com https://www.rosaceae.org https://www.protocols.io https://hypothes.is https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn https://openlayers.org/en/v4.6.5/build/ol.js; frame-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn; child-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn; report-uri https://gigadb.report-uri.com/r/d/csp/reportOnly;";
add_header Content-Security-Policy "default-src https://s3.ap-northeast-1.wasabisys.com 'self' 'unsafe-inline' 'unsafe-eval' http://gigadb.org http://penguin.genomics.cn https://www.rosaceae.org *.protocols.io https://sketchfab.com https://codeocean.com *.hypothes.is *.datatables.net *.cloudflare.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.matomo.cloud/gigadb.matomo.cloud/matomo.js *.hypothes.is *.datatables.net *.cloudflare.com *.google-analytics.com https://www.rosaceae.org https://www.protocols.io https://hypothes.is https://codeocean.com https://tumormap.ucsc.edu https://openlayers.org/en/v4.6.5/build/ol.js https://cdn.jsdelivr.net; frame-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu; child-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu; img-src blob: data: 'self' https://assets.gigadb-cdn.net *.tile.openstreetmap.org; report-uri https://gigadb.report-uri.com/r/d/csp/enforce;";
add_header Content-Security-Policy-Report-Only "default-src https://s3.ap-northeast-1.wasabisys.com 'self' https://gigadb.org; script-src 'self' https://cdn.matomo.cloud/gigadb.matomo.cloud/matomo.js https://*.hypothes.is https://*.datatables.net https://*.cloudflare.com https://*.google-analytics.com https://www.rosaceae.org https://www.protocols.io https://hypothes.is https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn https://openlayers.org/en/v4.6.5/build/ol.js https://cdn.jsdelivr.net; frame-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn; child-src https://www.protocols.io https://hypothes.is https://www.rosaceae.org https://sketchfab.com https://codeocean.com https://tumormap.ucsc.edu http://penguin.genomics.cn; report-uri https://gigadb.report-uri.com/r/d/csp/reportOnly;";

# Cors headers
add_header Access-Control-Allow-Origin '*';
Expand Down Expand Up @@ -106,7 +106,7 @@ server {
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src 'self'; script-src https://*.matomo.cloud https://*.sentry.io https://sentry.io https://nominatim.openstreetmap.org 'self' 'unsafe-inline' 'unsafe-eval'; style-src https://fonts.googleapis.com 'self' 'unsafe-inline'; font-src https://fonts.gstatic.com https://fonts.googleapis.com 'self' data:; connect-src https://*.matomo.cloud 'self' ws://* wss://* https://*.sentry.io https://sentry.io https://*.googleapis.com; object-src 'self'; img-src https://*.google.com https://api.mapbox.com 'self' blob: data:; frame-src 'self' http://penguin.genomics.cn;";
add_header Content-Security-Policy "default-src https://s3.ap-northeast-1.wasabisys.com 'self'; script-src https://*.matomo.cloud https://*.sentry.io https://sentry.io https://nominatim.openstreetmap.org https://cdn.jsdelivr.net 'self' 'unsafe-inline' 'unsafe-eval'; style-src https://fonts.googleapis.com 'self' 'unsafe-inline'; font-src https://fonts.gstatic.com https://fonts.googleapis.com 'self' data:; connect-src https://*.matomo.cloud 'self' ws://* wss://* https://*.sentry.io https://sentry.io https://*.googleapis.com; object-src 'self'; img-src https://*.google.com https://api.mapbox.com 'self' blob: data:; frame-src 'self' http://penguin.genomics.cn;";

# Cors headers
add_header Access-Control-Allow-Origin '*';
Expand Down
Loading