├── qiimp ├── __init__.py ├── settings │ ├── readme_template.txt │ ├── packages │ │ ├── rat.xlsx │ │ ├── animal.xlsx │ │ ├── base.xlsx │ │ ├── fungus.xlsx │ │ ├── human.xlsx │ │ ├── mouse.xlsx │ │ ├── plant.xlsx │ │ ├── rat-gut.xlsx │ │ ├── base-other.xlsx │ │ ├── free-living.xlsx │ │ ├── human-blood.xlsx │ │ ├── human-gut.xlsx │ │ ├── human-other.xlsx │ │ ├── human-skin.xlsx │ │ ├── human-stool.xlsx │ │ ├── mouse-gut.xlsx │ │ ├── mouse-other.xlsx │ │ ├── mouse-skin.xlsx │ │ ├── mouse-stool.xlsx │ │ ├── rat-bowels.xlsx │ │ ├── rat-other.xlsx │ │ ├── rat-stool.xlsx │ │ ├── vertebrate.xlsx │ │ ├── human-ear-wax.xlsx │ │ ├── human-saliva.xlsx │ │ ├── human-tongue.xlsx │ │ ├── air-environment.xlsx │ │ ├── ebi-submittable.xlsx │ │ ├── free-living-air.xlsx │ │ ├── host-associated.xlsx │ │ ├── iacuc-eligible.xlsx │ │ ├── vertebrate-serum.xlsx │ │ ├── vertebrate-skin.xlsx │ │ ├── vertebrate-stool.xlsx │ │ ├── vertebrate-urine.xlsx │ │ ├── built-environment.xlsx │ │ ├── human-lung-tissue.xlsx │ │ ├── human-nasal-mucus.xlsx │ │ ├── mouse-colon-mucosa.xlsx │ │ ├── other-environment.xlsx │ │ ├── vertebrate-saliva.xlsx │ │ ├── vertebrate-sputum.xlsx │ │ ├── human-vaginal-mucus.xlsx │ │ ├── mouse-colon-content.xlsx │ │ ├── non-vertebrate-animal.xlsx │ │ ├── vertebrate-colon-mucosa.xlsx │ │ └── vertebrate-colon-content.xlsx │ ├── config.txt │ ├── server.csr │ ├── install.sh │ ├── default_locales.yaml │ ├── server.crt │ ├── server.key │ ├── sampletypes.yaml │ ├── environments.yaml │ ├── reserved_words.yaml │ └── regex_definitions.yaml ├── third-party │ ├── jQuery-File-Upload-9.19.2 │ │ ├── .gitignore │ │ ├── server │ │ │ ├── gae-go │ │ │ │ ├── static │ │ │ │ │ ├── robots.txt │ │ │ │ │ └── favicon.ico │ │ │ │ ├── app.yaml │ │ │ │ └── app │ │ │ │ │ └── main.go │ │ │ ├── php │ │ │ │ ├── files │ │ │ │ │ ├── .gitignore │ │ │ │ │ └── .htaccess │ │ │ │ ├── docker-compose.yml │ │ │ │ ├── index.php │ │ │ │ └── Dockerfile │ │ │ └── gae-python │ │ │ │ ├── static │ │ │ │ ├── robots.txt │ │ │ │ └── favicon.ico │ │ │ │ ├── app.yaml │ │ │ │ └── main.py │ │ ├── img │ │ │ ├── loading.gif │ │ │ └── progressbar.gif │ │ ├── css │ │ │ ├── style.css │ │ │ ├── jquery.fileupload-ui-noscript.css │ │ │ ├── jquery-ui-demo-ie8.css │ │ │ ├── jquery.fileupload-noscript.css │ │ │ ├── jquery.fileupload.css │ │ │ ├── jquery.fileupload-ui.css │ │ │ └── jquery-ui-demo.css │ │ ├── bower-version-update.js │ │ ├── cors │ │ │ ├── result.html │ │ │ └── postmessage.html │ │ ├── CONTRIBUTING.md │ │ ├── .npmignore │ │ ├── LICENSE.txt │ │ ├── bower.json │ │ ├── package.json │ │ ├── js │ │ │ ├── main.js │ │ │ ├── cors │ │ │ │ ├── jquery.xdr-transport.js │ │ │ │ └── jquery.postmessage-transport.js │ │ │ ├── app.js │ │ │ ├── jquery.fileupload-audio.js │ │ │ ├── jquery.fileupload-video.js │ │ │ ├── jquery.fileupload-validate.js │ │ │ ├── jquery.fileupload-jquery-ui.js │ │ │ └── jquery.fileupload-process.js │ │ ├── .jshintrc │ │ ├── basic.html │ │ ├── README.md │ │ ├── test │ │ │ └── index.html │ │ └── basic-plus.html │ ├── favicon.ico │ ├── jquery-ui-1.12.1 │ │ ├── images │ │ │ ├── ui-icons_444444_256x240.png │ │ │ ├── ui-icons_555555_256x240.png │ │ │ ├── ui-icons_777620_256x240.png │ │ │ ├── ui-icons_777777_256x240.png │ │ │ ├── ui-icons_cc0000_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ ├── LICENSE.txt │ │ └── package.json │ ├── bootstrap-3.3.7-dist │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ └── npm.js │ └── tmpl.min.js ├── ajax_loader_gray_small_line.gif ├── ajax_loader_gray_large_circle.gif ├── output │ └── placeholder.txt ├── templates │ ├── metadata_download_template.html │ └── metadata_error_template.html ├── xlsx_builder.py ├── tests │ └── test_xlsx_validation_builder.py ├── client_scripts │ └── packageWizard.js └── schema_builder.py ├── docs └── images │ ├── createdir.txt │ ├── text.png │ ├── manual.png │ ├── submit.png │ ├── table.png │ ├── text2.png │ ├── addfield.png │ ├── allerrors.png │ ├── boolean.png │ ├── boolean2.png │ ├── fieldtype.png │ ├── homepage.png │ ├── newwindow.png │ ├── notunique.png │ ├── package.png │ ├── categorical.png │ ├── continuous.png │ ├── continuous2.png │ ├── customfield.png │ ├── fieldselect.png │ ├── fieldtype2.png │ ├── newwindow2.png │ ├── tableerror.png │ ├── uploadfile.png │ ├── usewizard1.png │ ├── usewizard2.png │ ├── categorical2.png │ ├── fieldselect2.png │ ├── packagefields.png │ ├── fieldnamesadded.png │ ├── fieldnamesadded2.png │ ├── studydescription.png │ └── studydescriptionerror.png ├── MANIFEST.in ├── date_validation_formula.xlsx ├── README.md └── setup.py /qiimp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/images/createdir.txt: -------------------------------------------------------------------------------- 1 | sorry amanda 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | recursive-include metadata_wizard/client_scripts * -------------------------------------------------------------------------------- /docs/images/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/text.png -------------------------------------------------------------------------------- /docs/images/manual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/manual.png -------------------------------------------------------------------------------- /docs/images/submit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/submit.png -------------------------------------------------------------------------------- /docs/images/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/table.png -------------------------------------------------------------------------------- /docs/images/text2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/text2.png -------------------------------------------------------------------------------- /qiimp/settings/readme_template.txt: -------------------------------------------------------------------------------- 1 | This file was created by QIIMP VERSION at GENERATION_TIMESTAMP. -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | node_modules 4 | -------------------------------------------------------------------------------- /docs/images/addfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/addfield.png -------------------------------------------------------------------------------- /docs/images/allerrors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/allerrors.png -------------------------------------------------------------------------------- /docs/images/boolean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/boolean.png -------------------------------------------------------------------------------- /docs/images/boolean2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/boolean2.png -------------------------------------------------------------------------------- /docs/images/fieldtype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldtype.png -------------------------------------------------------------------------------- /docs/images/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/homepage.png -------------------------------------------------------------------------------- /docs/images/newwindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/newwindow.png -------------------------------------------------------------------------------- /docs/images/notunique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/notunique.png -------------------------------------------------------------------------------- /docs/images/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/package.png -------------------------------------------------------------------------------- /docs/images/categorical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/categorical.png -------------------------------------------------------------------------------- /docs/images/continuous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/continuous.png -------------------------------------------------------------------------------- /docs/images/continuous2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/continuous2.png -------------------------------------------------------------------------------- /docs/images/customfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/customfield.png -------------------------------------------------------------------------------- /docs/images/fieldselect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldselect.png -------------------------------------------------------------------------------- /docs/images/fieldtype2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldtype2.png -------------------------------------------------------------------------------- /docs/images/newwindow2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/newwindow2.png -------------------------------------------------------------------------------- /docs/images/tableerror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/tableerror.png -------------------------------------------------------------------------------- /docs/images/uploadfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/uploadfile.png -------------------------------------------------------------------------------- /docs/images/usewizard1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/usewizard1.png -------------------------------------------------------------------------------- /docs/images/usewizard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/usewizard2.png -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-go/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/php/files/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.htaccess 4 | -------------------------------------------------------------------------------- /date_validation_formula.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/date_validation_formula.xlsx -------------------------------------------------------------------------------- /docs/images/categorical2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/categorical2.png -------------------------------------------------------------------------------- /docs/images/fieldselect2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldselect2.png -------------------------------------------------------------------------------- /docs/images/packagefields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/packagefields.png -------------------------------------------------------------------------------- /qiimp/third-party/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/favicon.ico -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-python/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /docs/images/fieldnamesadded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldnamesadded.png -------------------------------------------------------------------------------- /docs/images/fieldnamesadded2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/fieldnamesadded2.png -------------------------------------------------------------------------------- /docs/images/studydescription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/studydescription.png -------------------------------------------------------------------------------- /qiimp/settings/packages/rat.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/rat.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/animal.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/animal.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/base.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/base.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/fungus.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/fungus.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/plant.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/plant.xlsx -------------------------------------------------------------------------------- /docs/images/studydescriptionerror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/docs/images/studydescriptionerror.png -------------------------------------------------------------------------------- /qiimp/ajax_loader_gray_small_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/ajax_loader_gray_small_line.gif -------------------------------------------------------------------------------- /qiimp/settings/packages/rat-gut.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/rat-gut.xlsx -------------------------------------------------------------------------------- /qiimp/ajax_loader_gray_large_circle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/ajax_loader_gray_large_circle.gif -------------------------------------------------------------------------------- /qiimp/settings/packages/base-other.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/base-other.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/free-living.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/free-living.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-blood.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-blood.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-gut.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-gut.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-other.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-other.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-skin.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-skin.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-stool.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-stool.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-gut.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-gut.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-other.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-other.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-skin.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-skin.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-stool.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-stool.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/rat-bowels.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/rat-bowels.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/rat-other.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/rat-other.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/rat-stool.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/rat-stool.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-ear-wax.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-ear-wax.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-saliva.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-saliva.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-tongue.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-tongue.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/air-environment.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/air-environment.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/ebi-submittable.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/ebi-submittable.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/free-living-air.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/free-living-air.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/host-associated.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/host-associated.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/iacuc-eligible.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/iacuc-eligible.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-serum.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-serum.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-skin.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-skin.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-stool.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-stool.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-urine.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-urine.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/built-environment.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/built-environment.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-lung-tissue.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-lung-tissue.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-nasal-mucus.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-nasal-mucus.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-colon-mucosa.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-colon-mucosa.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/other-environment.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/other-environment.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-saliva.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-saliva.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-sputum.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-sputum.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/human-vaginal-mucus.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/human-vaginal-mucus.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/mouse-colon-content.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/mouse-colon-content.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/non-vertebrate-animal.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/non-vertebrate-animal.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-colon-mucosa.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-colon-mucosa.xlsx -------------------------------------------------------------------------------- /qiimp/settings/packages/vertebrate-colon-content.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/settings/packages/vertebrate-colon-content.xlsx -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jQuery-File-Upload-9.19.2/img/loading.gif -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/img/progressbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jQuery-File-Upload-9.19.2/img/progressbar.gif -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/php/docker-compose.yml: -------------------------------------------------------------------------------- 1 | apache: 2 | build: ./ 3 | ports: 4 | - "80:80" 5 | volumes: 6 | - "../../:/var/www/html" 7 | -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_444444_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_444444_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_555555_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_555555_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_777620_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_777620_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_777777_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_777777_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_cc0000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_cc0000_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-go/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-go/static/favicon.ico -------------------------------------------------------------------------------- /qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/bootstrap-3.3.7-dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-python/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucsd-ccbb/qiimp/master/qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-python/static/favicon.ico -------------------------------------------------------------------------------- /qiimp/output/placeholder.txt: -------------------------------------------------------------------------------- 1 | This file is not necessary for the functioning of the application; its only purpose is to ensure that deployment from GitHub creates the necessary outputs folder, which would not be the case if no file checked into github were in the folder. -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-go/app.yaml: -------------------------------------------------------------------------------- 1 | application: jquery-file-upload 2 | version: 2 3 | runtime: go 4 | api_version: go1 5 | 6 | handlers: 7 | - url: /(favicon\.ico|robots\.txt) 8 | static_files: static/\1 9 | upload: static/(.*) 10 | expiration: '1d' 11 | - url: /.* 12 | script: _go_app 13 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/css/style.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * jQuery File Upload Plugin CSS Example 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | body { 14 | padding-top: 60px; 15 | } 16 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-python/app.yaml: -------------------------------------------------------------------------------- 1 | application: jquery-file-upload 2 | version: 1 3 | runtime: python27 4 | api_version: 1 5 | threadsafe: true 6 | 7 | libraries: 8 | - name: PIL 9 | version: latest 10 | 11 | handlers: 12 | - url: /(favicon\.ico|robots\.txt) 13 | static_files: static/\1 14 | upload: static/(.*) 15 | expiration: '1d' 16 | - url: /.* 17 | script: main.app 18 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/php/index.php: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | jQuery Iframe Transport Plugin Redirect Page 18 | 19 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please follow these pull request guidelines: 2 | 3 | 1. Update your fork to the latest upstream version. 4 | 5 | 2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout). 6 | 7 | 3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project. 8 | 9 | 4. Code changes must pass the QUnit tests defined in the `test` folder. 10 | 11 | 5. New features should be covered by accompanying QUnit tests. 12 | 13 | 6. Keep your commits as atomic as possible, i.e. create a new commit for every single bug fix or feature added. 14 | 15 | 7. Always add meaningful commit messages. 16 | -------------------------------------------------------------------------------- /qiimp/settings/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIBpjCCAQ8CAQAwZjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQH 3 | EwlTYW4gRGllZ28xDTALBgNVBAoTBFVDU0QxEzARBgNVBAsTCktuaWdodCBMYWIx 4 | EjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA 5 | q6ChN/5vk1fn45Ys5inttHe8IntBQtU31oKy+2IR+znTGBvG/iht0veG5sbjlkm+ 6 | Hn4auk5lR9EOmnTy+fl44LJ81rZuYmy3mjLSAHwmx7eeZTJ2lNjH/Blq5vC4VmPQ 7 | 3Ka7zMusOTZSBDw6k8r6bxbMgarXc+rQtDvQfv2QITsCAwEAAaAAMA0GCSqGSIb3 8 | DQEBBQUAA4GBAGR6kJFSMFDM8UpCmUFSs4cUW+myTPPNpbI+2egDlzeAEYT94+81 9 | A+Z5MLvwSCC7xH3BMlUBqUa75xpLpRmTOabTFvrckS+K+0bh3uB2DiX4mapvHlGT 10 | r34iGqQq7MufMU/IRyw4S9GZ8JDqbnwVaUClyJeKfJuzEB/UEKVJWGIP 11 | -----END CERTIFICATE REQUEST----- 12 | -------------------------------------------------------------------------------- /qiimp/settings/install.sh: -------------------------------------------------------------------------------- 1 | curl https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda_py3.sh 2 | bash miniconda_py3.sh -b -p $HOME/miniconda3 3 | echo "export PATH=\"$HOME/miniconda3/bin:\$PATH\"" >>$HOME/.bashrc 4 | source $HOME/.bashrc 5 | conda update conda -y 6 | conda install python=3.5 -y 7 | conda install pyyaml -y 8 | conda install tornado -y 9 | conda install xlsxwriter -y 10 | conda install openpyxl -y 11 | conda install pandas -y 12 | conda install git -y 13 | git clone https://github.com/ucsd-ccbb/qiimp.git 14 | cd qiimp 15 | # ensure URL/port in metadata_wizard_server.py main and in metadataWizard.js document.ready are set for instance 16 | python metadata_wizard_server.py 17 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !css/jquery.fileupload-noscript.css 3 | !css/jquery.fileupload-ui-noscript.css 4 | !css/jquery.fileupload-ui.css 5 | !css/jquery.fileupload.css 6 | !img/loading.gif 7 | !img/progressbar.gif 8 | !js/cors/jquery.postmessage-transport.js 9 | !js/cors/jquery.xdr-transport.js 10 | !js/vendor/jquery.ui.widget.js 11 | !js/jquery.fileupload-angular.js 12 | !js/jquery.fileupload-audio.js 13 | !js/jquery.fileupload-image.js 14 | !js/jquery.fileupload-jquery-ui.js 15 | !js/jquery.fileupload-process.js 16 | !js/jquery.fileupload-ui.js 17 | !js/jquery.fileupload-validate.js 18 | !js/jquery.fileupload-video.js 19 | !js/jquery.fileupload.js 20 | !js/jquery.iframe-transport.js 21 | -------------------------------------------------------------------------------- /qiimp/settings/default_locales.yaml: -------------------------------------------------------------------------------- 1 | # Note that this is a list rather than a dictionary because this data structure is 2 | # used, among other things, to populate the default locale select box in the interface 3 | # and I anticipate wanting to be able to explicitly control the order in which 4 | # items appear in that box. 5 | - None: {} 6 | - San Diego standard: 7 | elevation: {default: 193} 8 | geo_loc_name: {default: 'USA:CA: San Diego'} 9 | latitude: {default: 32.842} 10 | longitude: {default: -117.258} 11 | - San Diego phi-compliant: 12 | elevation: {default: 'restricted access'} 13 | geo_loc_name: {default: 'USA:CA'} 14 | latitude: {default: 'restricted access'} 15 | longitude: {default: 'restricted access'} 16 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/css/jquery.fileupload.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * jQuery File Upload Plugin CSS 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | .fileinput-button { 14 | position: relative; 15 | overflow: hidden; 16 | display: inline-block; 17 | } 18 | .fileinput-button input { 19 | position: absolute; 20 | top: 0; 21 | right: 0; 22 | margin: 0; 23 | opacity: 0; 24 | -ms-filter: 'alpha(opacity=0)'; 25 | font-size: 200px !important; 26 | direction: ltr; 27 | cursor: pointer; 28 | } 29 | 30 | /* Fixes for IE < 8 */ 31 | @media screen\9 { 32 | .fileinput-button input { 33 | filter: alpha(opacity=0); 34 | font-size: 100%; 35 | height: 100%; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /qiimp/settings/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICRTCCAa4CCQDPGmrQ4bra7TANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJV 3 | UzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVNhbiBEaWVnbzENMAsGA1UEChMEVUNT 4 | RDETMBEGA1UECxMKS25pZ2h0IExhYjESMBAGA1UEAxMJbG9jYWxob3N0MCAXDTE3 5 | MDExOTA4MTQ1NloYDzIxMTYxMjI2MDgxNDU2WjBmMQswCQYDVQQGEwJVUzELMAkG 6 | A1UECBMCQ0ExEjAQBgNVBAcTCVNhbiBEaWVnbzENMAsGA1UEChMEVUNTRDETMBEG 7 | A1UECxMKS25pZ2h0IExhYjESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3 8 | DQEBAQUAA4GNADCBiQKBgQCroKE3/m+TV+fjlizmKe20d7wie0FC1TfWgrL7YhH7 9 | OdMYG8b+KG3S94bmxuOWSb4efhq6TmVH0Q6adPL5+XjgsnzWtm5ibLeaMtIAfCbH 10 | t55lMnaU2Mf8GWrm8LhWY9DcprvMy6w5NlIEPDqTyvpvFsyBqtdz6tC0O9B+/ZAh 11 | OwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAGLau2DhrdnR5P2C2rGZuSaHLYCsVPJO 12 | nj3Q+v5md1UzTDitlzHwM3pX1QBLxfiTJ6e7/0QLkrDceYKOfU/eucLGM1KG1YjS 13 | nB39W2BNLKXu4QXWJUx4WC1Qxib9wbxxm4NyMb0ir2/PZTs+gKMtguBUyVHqETvs 14 | n1b0mapYTJ/Q 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /qiimp/settings/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQCroKE3/m+TV+fjlizmKe20d7wie0FC1TfWgrL7YhH7OdMYG8b+ 3 | KG3S94bmxuOWSb4efhq6TmVH0Q6adPL5+XjgsnzWtm5ibLeaMtIAfCbHt55lMnaU 4 | 2Mf8GWrm8LhWY9DcprvMy6w5NlIEPDqTyvpvFsyBqtdz6tC0O9B+/ZAhOwIDAQAB 5 | AoGBAJDbtBeBvoTbllKmR2FBFGvU/8sOwyd4tXdtu0moHcswpDZeA5gzYXbGC2uv 6 | hRotRbWQ9Fg5oQx7rFq7yPUqFlYW6nhn3eyKbEaqF90dJheIvIr5rjTK2Sfn1wDf 7 | 0RpXBsmk4h4QBtqPuU2CNCUd45TDQWSdnFDjemibcGSFLM/5AkEA2HrjMrZTRhAQ 8 | C8pQlHEHx/I5KJY3zZhQ89t6uGD47OvWqg1x+8x3ujBLqd+4tyA4juSy/j7SvkEU 9 | z6NEJJp6vQJBAMr1kwlvdj0s4w9dSoAFvNTjxR6EQjb2i7jsDLUao84u+ML5o6lL 10 | i3RZFcvsuIig5Eg5E4e4ZhWO7GuCnzx+R1cCQQCqYYYCOugtw6Stcu2a959VKnr8 11 | S8bd5R0J4VukVIZ3CmOo8e4dbV9qRmq25+NdFloNdUi/vLhnj5eOmQSf/onNAkBC 12 | sOVLAWxJ99j4sIANh1UgY2Pffjg/1U3eSvp1/DX9R2QItX044REG/0rxQmz0wGGi 13 | 9dZcD5TD2r4HKdnnR9trAkA4LJFB0hZX6Lc6MxCjGITL/f9OquvNrT/29z43M+6K 14 | gAstm0FuH4Z3lHdR2zv9AjdlE6qBVkl7Pt6BSl6lDWWi 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /qiimp/third-party/tmpl.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"use strict";var n=function(e,t){var r=/[^\w\-.:]/.test(e)?new Function(n.arg+",tmpl","var _e=tmpl.encode"+n.helper+",_s='"+e.replace(n.regexp,n.func)+"';return _s;"):n.cache[e]=n.cache[e]||n(n.load(e));return t?r(t,n):function(e){return r(e,n)}};n.cache={},n.load=function(e){return document.getElementById(e).innerHTML},n.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,n.func=function(e,n,t,r,c,u){return n?{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+r+")+'":"'+("+r+"==null?'':"+r+")+'":c?"';":u?"_s+='":void 0},n.encReg=/[<>&"'\x00]/g,n.encMap={"<":"<",">":">","&":"&",'"':""","'":"'"},n.encode=function(e){return(null==e?"":""+e).replace(n.encReg,function(e){return n.encMap[e]||""})},n.arg="o",n.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return n}):"object"==typeof module&&module.exports?module.exports=n:e.tmpl=n}(this); 2 | //# sourceMappingURL=tmpl.min.js.map -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/php/files/.htaccess: -------------------------------------------------------------------------------- 1 | # To enable the Headers module, execute the following command and reload Apache: 2 | # sudo a2enmod headers 3 | 4 | # The following directives prevent the execution of script files 5 | # in the context of the website. 6 | # They also force the content-type application/octet-stream and 7 | # force browsers to display a download dialog for non-image files. 8 | SetHandler default-handler 9 | ForceType application/octet-stream 10 | Header set Content-Disposition attachment 11 | 12 | # The following unsets the forced type and Content-Disposition headers 13 | # for known image files: 14 | 15 | ForceType none 16 | Header unset Content-Disposition 17 | 18 | 19 | # The following directive prevents browsers from MIME-sniffing the content-type. 20 | # This is an important complement to the ForceType directive above: 21 | Header set X-Content-Type-Options nosniff 22 | 23 | # Uncomment the following lines to prevent unauthorized download of files: 24 | #AuthName "Authorization required" 25 | #AuthType Basic 26 | #require valid-user 27 | -------------------------------------------------------------------------------- /qiimp/settings/sampletypes.yaml: -------------------------------------------------------------------------------- 1 | # Note that this is a list rather than a dictionary because I anticipate wanting 2 | # to explicitly control the order in which these are visible to the user. 3 | - {skin: Skin} 4 | - {colon_mucosa: Colon Mucosa} 5 | - {colon_content: Colon Content} 6 | - {stool: Stool} 7 | - {sputum: Sputum} 8 | - {urine: Urine} 9 | - {blood: Blood} 10 | - {serum: Serum} 11 | - {tongue: Tongue} 12 | - {saliva: Saliva} 13 | - {vaginal_mucus: Vaginal Mucus} 14 | - {lung_tissue: Lung Tissue} 15 | - {ear_wax: Ear Wax} 16 | - {nasal_mucus: Nasal Mucus} 17 | - {air: Air} 18 | - {anaerobic-digester-content: Anaerobic Digester Content} 19 | - {beer: Beer} 20 | - {cheese: Cheese} 21 | - {dust: Dust} 22 | - {fresh-water: Fresh Water} 23 | - {marine-sediment: Marine Sediment} 24 | - {sea-water: Sea Water} 25 | - {sediment: Sediment} 26 | - {soil: Soil} 27 | - {waste-water: Waste Water} 28 | - {fruit: Fruit} 29 | - {seed: Seed} 30 | - {leaf: Leaf} 31 | - {stem: Stem} 32 | - {root: Root} 33 | - {rhizome: Rhizome} 34 | - {sponge: Sponge} 35 | - {coral: Coral} 36 | - {biofilm: Biofilm} 37 | - {whole-gut: Whole Gut} 38 | - {insect: Insect} 39 | - {insect-gut: Insect Gut} 40 | - {other: Other} -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2010 Sebastian Tschan, https://blueimp.net 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.0-apache 2 | 3 | # Enable the Apache Headers module: 4 | RUN ln -s /etc/apache2/mods-available/headers.load \ 5 | /etc/apache2/mods-enabled/headers.load 6 | 7 | # Enable the Apache Rewrite module: 8 | RUN ln -s /etc/apache2/mods-available/rewrite.load \ 9 | /etc/apache2/mods-enabled/rewrite.load 10 | 11 | # Install GD, Imagick and ImageMagick as image conversion options: 12 | RUN DEBIAN_FRONTEND=noninteractive \ 13 | apt-get update && apt-get install -y --no-install-recommends \ 14 | libpng-dev \ 15 | libjpeg-dev \ 16 | libmagickwand-dev \ 17 | imagemagick \ 18 | && pecl install \ 19 | imagick \ 20 | && docker-php-ext-enable \ 21 | imagick \ 22 | && docker-php-ext-configure \ 23 | gd --with-jpeg-dir=/usr/include/ \ 24 | && docker-php-ext-install \ 25 | gd \ 26 | # Uninstall obsolete packages: 27 | && apt-get autoremove -y \ 28 | libpng-dev \ 29 | libjpeg-dev \ 30 | libmagickwand-dev \ 31 | # Remove obsolete files: 32 | && apt-get clean \ 33 | && rm -rf \ 34 | /tmp/* \ 35 | /usr/share/doc/* \ 36 | /var/cache/* \ 37 | /var/lib/apt/lists/* \ 38 | /var/tmp/* 39 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/css/jquery.fileupload-ui.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * jQuery File Upload UI Plugin CSS 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2010, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | .fileupload-buttonbar .btn, 14 | .fileupload-buttonbar .toggle { 15 | margin-bottom: 5px; 16 | } 17 | .progress-animated .progress-bar, 18 | .progress-animated .bar { 19 | background: url("../img/progressbar.gif") !important; 20 | filter: none; 21 | } 22 | .fileupload-process { 23 | float: right; 24 | display: none; 25 | } 26 | .fileupload-processing .fileupload-process, 27 | .files .processing .preview { 28 | display: block; 29 | width: 32px; 30 | height: 32px; 31 | background: url("../img/loading.gif") center no-repeat; 32 | background-size: contain; 33 | } 34 | .files audio, 35 | .files video { 36 | max-width: 300px; 37 | } 38 | 39 | @media (max-width: 767px) { 40 | .fileupload-buttonbar .toggle, 41 | .files .toggle, 42 | .files .btn span { 43 | display: none; 44 | } 45 | .files .name { 46 | width: 80px; 47 | word-wrap: break-word; 48 | } 49 | .files audio, 50 | .files video { 51 | max-width: 80px; 52 | } 53 | .files img, 54 | .files canvas { 55 | max-width: 100%; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/css/jquery-ui-demo.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* 3 | * jQuery File Upload Demo CSS 4 | * https://github.com/blueimp/jQuery-File-Upload 5 | * 6 | * Copyright 2013, Sebastian Tschan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | body { 14 | max-width: 750px; 15 | margin: 0 auto; 16 | padding: 1em; 17 | font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; 18 | font-size: 1em; 19 | line-height: 1.4em; 20 | background: #222; 21 | color: #fff; 22 | -webkit-text-size-adjust: 100%; 23 | -ms-text-size-adjust: 100%; 24 | } 25 | a { 26 | color: orange; 27 | text-decoration: none; 28 | } 29 | img { 30 | border: 0; 31 | vertical-align: middle; 32 | } 33 | h1 { 34 | line-height: 1em; 35 | } 36 | blockquote { 37 | padding: 0 0 0 15px; 38 | margin: 0 0 20px; 39 | border-left: 5px solid #eee; 40 | } 41 | table { 42 | width: 100%; 43 | margin: 10px 0; 44 | } 45 | 46 | .fileupload-progress { 47 | margin: 10px 0; 48 | } 49 | .fileupload-progress .progress-extended { 50 | margin-top: 5px; 51 | } 52 | .error { 53 | color: red; 54 | } 55 | 56 | @media (min-width: 481px) { 57 | .navigation { 58 | list-style: none; 59 | padding: 0; 60 | } 61 | .navigation li { 62 | display: inline-block; 63 | } 64 | .navigation li:not(:first-child):before { 65 | content: "| "; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blueimp-file-upload", 3 | "version": "9.19.2", 4 | "title": "jQuery File Upload", 5 | "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images.", 6 | "keywords": [ 7 | "jquery", 8 | "file", 9 | "upload", 10 | "widget", 11 | "multiple", 12 | "selection", 13 | "drag", 14 | "drop", 15 | "progress", 16 | "preview", 17 | "cross-domain", 18 | "cross-site", 19 | "chunk", 20 | "resume", 21 | "gae", 22 | "go", 23 | "python", 24 | "php", 25 | "bootstrap" 26 | ], 27 | "homepage": "https://github.com/blueimp/jQuery-File-Upload", 28 | "author": { 29 | "name": "Sebastian Tschan", 30 | "url": "https://blueimp.net" 31 | }, 32 | "maintainers": [ 33 | { 34 | "name": "Sebastian Tschan", 35 | "url": "https://blueimp.net" 36 | } 37 | ], 38 | "repository": { 39 | "type": "git", 40 | "url": "git://github.com/blueimp/jQuery-File-Upload.git" 41 | }, 42 | "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues", 43 | "license": "MIT", 44 | "dependencies": { 45 | "jquery": ">=1.6", 46 | "blueimp-tmpl": ">=2.5.4", 47 | "blueimp-load-image": ">=1.13.0", 48 | "blueimp-canvas-to-blob": ">=2.1.1" 49 | }, 50 | "main": [ 51 | "js/jquery.fileupload.js" 52 | ], 53 | "ignore": [ 54 | "/*.*", 55 | "/cors", 56 | "css/jquery-ui-demo-ie8.css", 57 | "css/jquery-ui-demo.css", 58 | "css/style.css", 59 | "js/app.js", 60 | "js/main.js", 61 | "server", 62 | "test" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /qiimp/templates/metadata_download_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QIIMP Metadata Template Download 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 |
19 |
20 |

QIIMP Metadata Template Download

21 |
22 |
23 |
24 |
25 | Download your customized metadata template spreadsheet now! 26 |
27 |
28 | {% raw wiz_state.TUTORIAL_BLURB %} 29 |
30 |
31 | To make another metadata template, click here. 32 |
33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blueimp-file-upload", 3 | "version": "9.19.2", 4 | "title": "jQuery File Upload", 5 | "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.", 6 | "keywords": [ 7 | "jquery", 8 | "file", 9 | "upload", 10 | "widget", 11 | "multiple", 12 | "selection", 13 | "drag", 14 | "drop", 15 | "progress", 16 | "preview", 17 | "cross-domain", 18 | "cross-site", 19 | "chunk", 20 | "resume", 21 | "gae", 22 | "go", 23 | "python", 24 | "php", 25 | "bootstrap" 26 | ], 27 | "homepage": "https://github.com/blueimp/jQuery-File-Upload", 28 | "author": { 29 | "name": "Sebastian Tschan", 30 | "url": "https://blueimp.net" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git://github.com/blueimp/jQuery-File-Upload.git" 35 | }, 36 | "license": "MIT", 37 | "optionalDependencies": { 38 | "blueimp-canvas-to-blob": "3.5.0", 39 | "blueimp-load-image": "2.12.2", 40 | "blueimp-tmpl": "3.6.0" 41 | }, 42 | "devDependencies": { 43 | "bower-json": "0.8.1", 44 | "jshint": "2.9.3" 45 | }, 46 | "scripts": { 47 | "bower-version-update": "./bower-version-update.js", 48 | "lint": "jshint *.js js/*.js js/cors/*.js", 49 | "test": "npm run lint", 50 | "preversion": "npm test", 51 | "version": "npm run bower-version-update && git add bower.json", 52 | "postversion": "git push --tags origin master && npm publish" 53 | }, 54 | "main": "js/jquery.fileupload.js" 55 | } 56 | -------------------------------------------------------------------------------- /qiimp/templates/metadata_error_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QIIMP Error 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 |
19 |
20 |

QIIMP Error

21 |
22 |
23 |
24 |
25 | QIIMP has encountered an error. Apologies for the inconvenience. 26 |

27 | Please take a moment to click here to email this error to the developer so we can get it fixed! 28 |

29 |

30 | Return to QIIMP. 31 |

32 |
33 |
34 |
35 |
36 |
37 | {{ error_trace }}
38 |                 
39 |
40 |
41 |
42 | 43 | -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery-ui 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | Copyright and related rights for sample code are waived via CC0. Sample 34 | code is defined as all source code contained within the demos directory. 35 | 36 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 37 | 38 | ==== 39 | 40 | All files located in the node_modules and external directories are 41 | externally maintained libraries used by this software which have their 42 | own licenses; we recommend you read them, as their terms may differ from 43 | the terms above. 44 | -------------------------------------------------------------------------------- /qiimp/third-party/jquery-ui-1.12.1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-ui", 3 | "title": "jQuery UI", 4 | "description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.", 5 | "version": "1.12.1", 6 | "homepage": "http://jqueryui.com", 7 | "author": { 8 | "name": "jQuery Foundation and other contributors", 9 | "url": "https://github.com/jquery/jquery-ui/blob/1.12.1/AUTHORS.txt" 10 | }, 11 | "main": "ui/widget.js", 12 | "maintainers": [ 13 | { 14 | "name": "Scott González", 15 | "email": "scott.gonzalez@gmail.com", 16 | "url": "http://scottgonzalez.com" 17 | }, 18 | { 19 | "name": "Jörn Zaefferer", 20 | "email": "joern.zaefferer@gmail.com", 21 | "url": "http://bassistance.de" 22 | }, 23 | { 24 | "name": "Mike Sherov", 25 | "email": "mike.sherov@gmail.com", 26 | "url": "http://mike.sherov.com" 27 | }, 28 | { 29 | "name": "TJ VanToll", 30 | "email": "tj.vantoll@gmail.com", 31 | "url": "http://tjvantoll.com" 32 | }, 33 | { 34 | "name": "Felix Nagel", 35 | "email": "info@felixnagel.com", 36 | "url": "http://www.felixnagel.com" 37 | }, 38 | { 39 | "name": "Alex Schmitz", 40 | "email": "arschmitz@gmail.com", 41 | "url": "https://github.com/arschmitz" 42 | } 43 | ], 44 | "repository": { 45 | "type": "git", 46 | "url": "git://github.com/jquery/jquery-ui.git" 47 | }, 48 | "bugs": "https://bugs.jqueryui.com/", 49 | "license": "MIT", 50 | "scripts": { 51 | "test": "grunt" 52 | }, 53 | "dependencies": {}, 54 | "devDependencies": { 55 | "commitplease": "2.3.0", 56 | "grunt": "0.4.5", 57 | "grunt-bowercopy": "1.2.4", 58 | "grunt-cli": "0.1.13", 59 | "grunt-compare-size": "0.4.0", 60 | "grunt-contrib-concat": "0.5.1", 61 | "grunt-contrib-csslint": "0.5.0", 62 | "grunt-contrib-jshint": "0.12.0", 63 | "grunt-contrib-qunit": "1.0.1", 64 | "grunt-contrib-requirejs": "0.4.4", 65 | "grunt-contrib-uglify": "0.11.1", 66 | "grunt-git-authors": "3.1.0", 67 | "grunt-html": "6.0.0", 68 | "grunt-jscs": "2.1.0", 69 | "load-grunt-tasks": "3.4.0", 70 | "rimraf": "2.5.1", 71 | "testswarm": "1.1.0" 72 | }, 73 | "keywords": [] 74 | } 75 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/cors/postmessage.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | jQuery File Upload Plugin postMessage API 18 | 19 | 20 | 21 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin JS Example 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2010, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global $, window */ 13 | 14 | $(function () { 15 | 'use strict'; 16 | 17 | // Initialize the jQuery File Upload widget: 18 | $('#fileupload').fileupload({ 19 | // Uncomment the following to send cross-domain cookies: 20 | //xhrFields: {withCredentials: true}, 21 | url: 'server/php/' 22 | }); 23 | 24 | // Enable iframe cross-domain access via redirect option: 25 | $('#fileupload').fileupload( 26 | 'option', 27 | 'redirect', 28 | window.location.href.replace( 29 | /\/[^\/]*$/, 30 | '/cors/result.html?%s' 31 | ) 32 | ); 33 | 34 | if (window.location.hostname === 'blueimp.github.io') { 35 | // Demo settings: 36 | $('#fileupload').fileupload('option', { 37 | url: '//jquery-file-upload.appspot.com/', 38 | // Enable image resizing, except for Android and Opera, 39 | // which actually support image resizing, but fail to 40 | // send Blob objects via XHR requests: 41 | disableImageResize: /Android(?!.*Chrome)|Opera/ 42 | .test(window.navigator.userAgent), 43 | maxFileSize: 999000, 44 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i 45 | }); 46 | // Upload server status check for browsers with CORS support: 47 | if ($.support.cors) { 48 | $.ajax({ 49 | url: '//jquery-file-upload.appspot.com/', 50 | type: 'HEAD' 51 | }).fail(function () { 52 | $('
') 53 | .text('Upload server currently unavailable - ' + 54 | new Date()) 55 | .appendTo('#fileupload'); 56 | }); 57 | } 58 | } else { 59 | // Load existing files: 60 | $('#fileupload').addClass('fileupload-processing'); 61 | $.ajax({ 62 | // Uncomment the following to send cross-domain cookies: 63 | //xhrFields: {withCredentials: true}, 64 | url: $('#fileupload').fileupload('option', 'url'), 65 | dataType: 'json', 66 | context: $('#fileupload')[0] 67 | }).always(function () { 68 | $(this).removeClass('fileupload-processing'); 69 | }).done(function (result) { 70 | $(this).fileupload('option', 'done') 71 | .call(this, $.Event('done'), {result: result}); 72 | }); 73 | } 74 | 75 | }); 76 | -------------------------------------------------------------------------------- /qiimp/settings/environments.yaml: -------------------------------------------------------------------------------- 1 | - human: 2 | display_name: Human 3 | filename: human.xlsx 4 | filename_by_sampletypes_list: 5 | - {tongue: human-tongue.xlsx} 6 | - {colon_content: human-gut.xlsx} 7 | - {colon_mucosa: human-gut.xlsx} 8 | - {saliva: human-saliva.xlsx} 9 | - {stool: human-gut.xlsx} 10 | - {skin: human-skin.xlsx} 11 | - {lung_tissue: human-lung-tissue.xlsx} 12 | - {ear_wax: human-ear-wax.xlsx} 13 | - {blood: human-blood.xlsx} 14 | - {vaginal mucus: human-vaginal-mucus.xlsx} 15 | - {nasal_mucus: human-nasal-mucus.xlsx} 16 | - {other: human-other.xlsx} 17 | parent: vertebrate 18 | - mouse: 19 | display_name: Mouse 20 | filename: mouse.xlsx 21 | filename_by_sampletypes_list: 22 | - {colon_content: mouse-gut.xlsx} 23 | - {colon_mucosa: mouse-gut.xlsx} 24 | - {other: mouse-other.xlsx} 25 | - {skin: mouse-skin.xlsx} 26 | - {stool: mouse-gut.xlsx} 27 | parent: iacuc-eligible 28 | - rat: 29 | display_name: Rat 30 | filename: rat.xlsx 31 | filename_by_sampletypes_list: 32 | - {colon_content: rat-gut.xlsx} 33 | - {colon_mucosa: rat-gut.xlsx} 34 | - {other: rat-other.xlsx} 35 | - {stool: rat-gut.xlsx} 36 | parent: iacuc-eligible 37 | - iacuc-eligible: 38 | display_name: null 39 | filename: iacuc-eligible.xlsx 40 | filename_by_sampletypes_list: [] 41 | parent: vertebrate 42 | - vertebrate: 43 | display_name: Other Vertebrate Host 44 | filename: vertebrate.xlsx 45 | filename_by_sampletypes_list: 46 | - {skin: vertebrate-skin.xlsx} 47 | - {saliva: vertebrate-saliva.xlsx} 48 | - {stool: vertebrate-stool.xlsx} 49 | - {colon_mucosa: vertebrate-colon-mucosa.xlsx} 50 | - {colon_content: vertebrate-colon-content.xlsx} 51 | - {sputum: vertebrate-sputum.xlsx} 52 | - {urine: vertebrate-urine.xlsx} 53 | - {serum: vertebrate-serum.xlsx} 54 | parent: animal 55 | - non-vertebrate: 56 | display_name: Non-Vertebrate Animal Host 57 | filename: non-vertebrate-animal.xlsx 58 | filename_by_sampletypes_list: [] 59 | parent: animal 60 | - animal: 61 | display_name: null 62 | filename: animal.xlsx 63 | filename_by_sampletypes_list: [] 64 | parent: host_associated 65 | - plant: 66 | display_name: Plant Host 67 | filename: plant.xlsx 68 | filename_by_sampletypes_list: [] 69 | parent: host_associated 70 | - fungus: 71 | display_name: Fungus Host 72 | filename: fungus.xlsx 73 | filename_by_sampletypes_list: [] 74 | parent: host_associated 75 | - host_associated: 76 | display_name: Other Non-Animal Host 77 | filename: host-associated.xlsx 78 | filename_by_sampletypes_list: [] 79 | parent: ebi_submittable 80 | - built_env: 81 | display_name: Built Environment 82 | filename: built-environment.xlsx 83 | filename_by_sampletypes_list: 84 | - {air: free-living-air.xlsx} 85 | parent: free-living 86 | - other_env: 87 | display_name: Other Free-Living Environment 88 | filename: other-environment.xlsx 89 | filename_by_sampletypes_list: 90 | - {air: free-living-air.xlsx} 91 | parent: free-living 92 | - free-living: 93 | display_name: null 94 | filename: free-living.xlsx 95 | filename_by_sampletypes_list: 96 | - {air: free-living-air.xlsx} 97 | parent: ebi_submittable 98 | - ebi_submittable: 99 | display_name: Other EBI-Submittable Environment 100 | filename: ebi-submittable.xlsx 101 | filename_by_sampletypes_list: 102 | - {other: base-other.xlsx} 103 | parent: base 104 | - base: 105 | display_name: null 106 | filename: base.xlsx 107 | filename_by_sampletypes_list: 108 | - {other: null} 109 | parent: null -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/cors/jquery.xdr-transport.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery XDomainRequest Transport Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | * 11 | * Based on Julian Aubourg's ajaxHooks xdr.js: 12 | * https://github.com/jaubourg/ajaxHooks/ 13 | */ 14 | 15 | /* global define, require, window, XDomainRequest */ 16 | 17 | ;(function (factory) { 18 | 'use strict'; 19 | if (typeof define === 'function' && define.amd) { 20 | // Register as an anonymous AMD module: 21 | define(['jquery'], factory); 22 | } else if (typeof exports === 'object') { 23 | // Node/CommonJS: 24 | factory(require('jquery')); 25 | } else { 26 | // Browser globals: 27 | factory(window.jQuery); 28 | } 29 | }(function ($) { 30 | 'use strict'; 31 | if (window.XDomainRequest && !$.support.cors) { 32 | $.ajaxTransport(function (s) { 33 | if (s.crossDomain && s.async) { 34 | if (s.timeout) { 35 | s.xdrTimeout = s.timeout; 36 | delete s.timeout; 37 | } 38 | var xdr; 39 | return { 40 | send: function (headers, completeCallback) { 41 | var addParamChar = /\?/.test(s.url) ? '&' : '?'; 42 | function callback(status, statusText, responses, responseHeaders) { 43 | xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; 44 | xdr = null; 45 | completeCallback(status, statusText, responses, responseHeaders); 46 | } 47 | xdr = new XDomainRequest(); 48 | // XDomainRequest only supports GET and POST: 49 | if (s.type === 'DELETE') { 50 | s.url = s.url + addParamChar + '_method=DELETE'; 51 | s.type = 'POST'; 52 | } else if (s.type === 'PUT') { 53 | s.url = s.url + addParamChar + '_method=PUT'; 54 | s.type = 'POST'; 55 | } else if (s.type === 'PATCH') { 56 | s.url = s.url + addParamChar + '_method=PATCH'; 57 | s.type = 'POST'; 58 | } 59 | xdr.open(s.type, s.url); 60 | xdr.onload = function () { 61 | callback( 62 | 200, 63 | 'OK', 64 | {text: xdr.responseText}, 65 | 'Content-Type: ' + xdr.contentType 66 | ); 67 | }; 68 | xdr.onerror = function () { 69 | callback(404, 'Not Found'); 70 | }; 71 | if (s.xdrTimeout) { 72 | xdr.ontimeout = function () { 73 | callback(0, 'timeout'); 74 | }; 75 | xdr.timeout = s.xdrTimeout; 76 | } 77 | xdr.send((s.hasContent && s.data) || null); 78 | }, 79 | abort: function () { 80 | if (xdr) { 81 | xdr.onerror = $.noop(); 82 | xdr.abort(); 83 | } 84 | } 85 | }; 86 | } 87 | }); 88 | } 89 | })); 90 | -------------------------------------------------------------------------------- /qiimp/settings/reserved_words.yaml: -------------------------------------------------------------------------------- 1 | - ABORT - ABSOLUTE - ACCESS - ACTION - ADD - ADMIN - AFTER - AGGREGATE - ALSO - ALTER - ALWAYS - ASSERTION - ASSIGNMENT - AT - ATTRIBUTE - BACKWARD - BEFORE - BEGIN - BY - CACHE - CALLED - CASCADE - CASCADED - CATALOG - CHAIN - CHARACTERISTICS - CHECKPOINT - CLASS - CLOSE - CLUSTER - COMMENT - COMMENTS - COMMIT - COMMITTED - CONFIGURATION - CONNECTION - CONSTRAINTS - CONTENT - CONTINUE - CONVERSION - COPY - COST - CSV - CURRENT - CURSOR - CYCLE - DATA - DATABASE - DAY - DEALLOCATE - DECLARE - DEFAULTS - DEFERRED - DEFINER - DELETE - DELIMITER - DELIMITERS - DICTIONARY - DISABLE - DISCARD - DOCUMENT - DOMAIN - DOUBLE - DROP - EACH - ENABLE - ENCODING - ENCRYPTED - ENUM - ESCAPE - EVENT - EXCLUDE - EXCLUDING - EXCLUSIVE - EXECUTE - EXPLAIN - EXTENSION - EXTERNAL - FAMILY - FIRST - FOLLOWING - FORCE - FORWARD - FUNCTION - FUNCTIONS - GLOBAL - GRANTED - HANDLER - HEADER - HOLD - HOUR - IDENTITY - IF - IMMEDIATE - IMMUTABLE - IMPLICIT - INCLUDING - INCREMENT - INDEX - INDEXES - INHERIT - INHERITS - INLINE - INPUT - INSENSITIVE - INSERT - INSTEAD - INVOKER - ISOLATION - KEY - LABEL - LANGUAGE - LARGE - LAST - LC_COLLATE - LC_CTYPE - LEAKPROOF - LEVEL - LISTEN - LOAD - LOCAL - LOCATION - LOCK - MAPPING - MATCH - MATERIALIZED - MAXVALUE - MINUTE - MINVALUE - MODE - MONTH - MOVE - NAME - NAMES - NEXT - NO - NOTHING - NOTIFY - NOWAIT - NULLS - OBJECT - OF - OFF - OIDS - OPERATOR - OPTION - OPTIONS - OWNED - OWNER - PARSER - PARTIAL - PARTITION - PASSING - PASSWORD - PLANS - PRECEDING - PREPARE - PREPARED - PRESERVE - PRIOR - PRIVILEGES - PROCEDURAL - PROCEDURE - PROGRAM - QUOTE - RANGE - READ - REASSIGN - RECHECK - RECURSIVE - REF - REFRESH - REINDEX - RELATIVE - RELEASE - RENAME - REPEATABLE - REPLACE - REPLICA - RESET - RESTART - RESTRICT - RETURNS - REVOKE - ROLE - ROLLBACK - ROWS - RULE - SAVEPOINT - SCHEMA - SCROLL - SEARCH - SECOND - SECURITY - SEQUENCE - SEQUENCES - SERIALIZABLE - SERVER - SESSION - SET - SHARE - SHOW - SIMPLE - SNAPSHOT - STABLE - STANDALONE - START - STATEMENT - STATISTICS - STDIN - STDOUT - STORAGE - STRICT - STRIP - SYSID - SYSTEM - TABLES - TABLESPACE - TEMP - TEMPLATE - TEMPORARY - TEXT - TRANSACTION - TRIGGER - TRUNCATE - TRUSTED - TYPE - TYPES - UNBOUNDED - UNCOMMITTED - UNENCRYPTED - UNKNOWN - UNLISTEN - UNLOGGED - UNTIL - UPDATE - VACUUM - VALID - VALIDATE - VALIDATOR - VALUE - VARYING - VERSION - VIEW - VOLATILE - WHITESPACE - WITHOUT - WORK - WRAPPER - WRITE - XML - YEAR - YES - ZONE - BETWEEN - BIGINT - BIT - BOOLEAN - CHAR - CHARACTER - COALESCE - DEC - DECIMAL - EXISTS - EXTRACT - FLOAT - GREATEST - INOUT - INT - INTEGER - INTERVAL - LEAST - NATIONAL - NCHAR - NONE - NULLIF - NUMERIC - OUT - OVERLAY - POSITION - PRECISION - REAL - ROW - SETOF - SMALLINT - SUBSTRING - TIME - TIMESTAMP - TREAT - TRIM - VALUES - VARCHAR - XMLATTRIBUTES - XMLCONCAT - XMLELEMENT - XMLEXISTS - XMLFOREST - XMLPARSE - XMLPI - XMLROOT - XMLSERIALIZE - ALL - ANALYSE - ANALYZE - AND - ANY - ARRAY - AS - ASC - ASYMMETRIC - BOTH - CASE - CAST - CHECK - COLLATE - COLUMN - CONSTRAINT - CREATE - CURRENT_CATALOG - CURRENT_DATE - CURRENT_ROLE - CURRENT_TIME - CURRENT_TIMESTAMP - CURRENT_USER - DEFAULT - DEFERRABLE - DESC - DISTINCT - DO - ELSE - END - EXCEPT - FETCH - FOR - FOREIGN - FROM - GRANT - GROUP - HAVING - IN - INITIALLY - INTERSECT - INTO - LATERAL - LEADING - LIMIT - LOCALTIME - LOCALTIMESTAMP - NOT - NULL - OFFSET - ON - ONLY - OR - ORDER - PLACING - PRIMARY - REFERENCES - RETURNING - SELECT - SESSION_USER - SOME - SYMMETRIC - TABLE - THEN - TO - TRAILING - UNION - UNIQUE - USER - USING - VARIADIC - WHEN - WHERE - WINDOW - WITH - FALSE - TRUE - AUTHORIZATION - BINARY - COLLATION - CONCURRENTLY - CROSS - CURRENT_SCHEMA - FREEZE - FULL - ILIKE - INNER - IS - ISNULL - JOIN - LEFT - LIKE - NATURAL - NOTNULL - OUTER - OVER - OVERLAPS - RIGHT - SIMILAR - VERBOSE - sample_id - id - sampleid - sample id - sample-id - featureid - feature id - feature-id - sample_name -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QIIMP 2 | *(Pronounced "chimp"!)* 3 | 4 | Web application to collect metadata specifications from an experimenter and produce metadata input files with appropriate constraints 5 | 6 | Note that this repository contains the full code necessary for QIIMP to function, which includes code that ccbb-ucsd did not write (contained in the "third-party" folder). 7 | 8 | ## Requirements 9 | 10 | * Hardware: A linux or OSX machine/instance with at least 1 GB of memory and at least 8 GB of storage 11 | * Software: An installation of the `conda` package manager (either `Anaconda` or `miniconda`) 12 | 13 | ## Installation 14 | 15 | 1. Create and source a `conda` environment for QIIMP 16 | 17 | conda create -n qiimp python=3 openpyxl tornado xlsxwriter PyYAML pandas git 18 | source activate qiimp 19 | 20 | 3. Install QIIMP from github.com 21 | 22 | pip install --upgrade git+git://github.com/ucsd-ccbb/qiimp.git 23 | 24 | 4. Find the `config.txt` file 25 | 26 | * Find the location of your `conda` install's `site-packages` folder by running 27 | 28 | pip show qiimp 29 | 30 | * Look for the line in the output that starts with `Location: ` and find the path it lists (for example, `/Users/Me/Applications/miniconda3/envs/qiimp/lib/python3.6/site-packages`). This will be referred to below as `sitepackagespath`. 31 | * The `config.txt` file will be at `sitepackagespath/qiimp/settings/config.txt` 32 | 33 | 6. Edit the `[DEPLOYED]` section of the `config.txt` file to set the appropriate values for your installation 34 | 35 | * Set the `main_url` variable to the public hostname of the machine/instance (e.g., `ec2-34-215-148-70.us-west-2.compute.amazonaws.com`). 36 | * If you want the port used to be something other than the default (e.g., 8183), 37 | * If you want the user to access this port directly, add it to the `main_url` (e.g., `ec2-34-215-148-70.us-west-2.compute.amazonaws.com:8183`) 38 | * Regardless of whether you want the user to access the port directly or be redirected to it internally, set the `listen_port` variable to the desired port. 39 | * **Be sure that public access to this port is enabled on your machine!** 40 | 7. Start the QIIMP server 41 | 42 | start_qiimp_server --deployed 43 | 44 | * If you are running QIIMP on your local host instead of on a publicly available host, run it *without* the `--deployed` switch. It will then use the settings in the `[LOCAL]` section of the config instead of the `[DEPLOYED]` section. 45 | * If you see `UserWarning`s like the examples below: 46 | 47 | /home/ec2-user/miniconda3/envs/qiimp/lib/python3.6/site-packages/qiimp/metadata_package_schema_builder.py:163: UserWarning: No filename specified for sample type 'sponge' in environment 'non-vertebrate'. 48 | warnings.warn("No filename specified for {0}.".format(context_description)) 49 | 50 | * ... this indicates that not all environments and/or sample types have schema files defined for them in the `settings/environments.yaml` file for the installation. 51 | * This is sometimes acceptable, specifically in cases in which the sample type or environment truly has no unique field definitions associated with it, such as the "other" sample type in the "base" environment. 52 | * However, it is more often an indication that not all expected configuration information for environment and sample type packages has been properly placed in the `settings/packages` directory. 53 | * Thus, each such warning should be checked to ensure that it is expected. 54 | 55 | * When the QIIMP server is accessible, a `server ready` message will be printed to `STDOUT` 56 | 57 | 8. Access QIIMP through a browser at the URL of your instance + the port number, e.g. `http://ec2-18-236-71-136.us-west-2.compute.amazonaws.com:8181/` 58 | 59 | 9. If desired (when done using it), stop the QIIMP server by typing `Ctrl+c` on the server command line 60 | 61 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin Angular JS Example 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* jshint nomen:false */ 13 | /* global window, angular */ 14 | 15 | ;(function () { 16 | 'use strict'; 17 | 18 | var isOnGitHub = window.location.hostname === 'blueimp.github.io', 19 | url = isOnGitHub ? '//jquery-file-upload.appspot.com/' : 'server/php/'; 20 | 21 | angular.module('demo', [ 22 | 'blueimp.fileupload' 23 | ]) 24 | .config([ 25 | '$httpProvider', 'fileUploadProvider', 26 | function ($httpProvider, fileUploadProvider) { 27 | delete $httpProvider.defaults.headers.common['X-Requested-With']; 28 | fileUploadProvider.defaults.redirect = window.location.href.replace( 29 | /\/[^\/]*$/, 30 | '/cors/result.html?%s' 31 | ); 32 | if (isOnGitHub) { 33 | // Demo settings: 34 | angular.extend(fileUploadProvider.defaults, { 35 | // Enable image resizing, except for Android and Opera, 36 | // which actually support image resizing, but fail to 37 | // send Blob objects via XHR requests: 38 | disableImageResize: /Android(?!.*Chrome)|Opera/ 39 | .test(window.navigator.userAgent), 40 | maxFileSize: 999000, 41 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i 42 | }); 43 | } 44 | } 45 | ]) 46 | 47 | .controller('DemoFileUploadController', [ 48 | '$scope', '$http', '$filter', '$window', 49 | function ($scope, $http) { 50 | $scope.options = { 51 | url: url 52 | }; 53 | if (!isOnGitHub) { 54 | $scope.loadingFiles = true; 55 | $http.get(url) 56 | .then( 57 | function (response) { 58 | $scope.loadingFiles = false; 59 | $scope.queue = response.data.files || []; 60 | }, 61 | function () { 62 | $scope.loadingFiles = false; 63 | } 64 | ); 65 | } 66 | } 67 | ]) 68 | 69 | .controller('FileDestroyController', [ 70 | '$scope', '$http', 71 | function ($scope, $http) { 72 | var file = $scope.file, 73 | state; 74 | if (file.url) { 75 | file.$state = function () { 76 | return state; 77 | }; 78 | file.$destroy = function () { 79 | state = 'pending'; 80 | return $http({ 81 | url: file.deleteUrl, 82 | method: file.deleteType 83 | }).then( 84 | function () { 85 | state = 'resolved'; 86 | $scope.clear(file); 87 | }, 88 | function () { 89 | state = 'rejected'; 90 | } 91 | ); 92 | }; 93 | } else if (!file.$cancel && !file._index) { 94 | file.$cancel = function () { 95 | $scope.clear(file); 96 | }; 97 | } 98 | } 99 | ]); 100 | 101 | }()); 102 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/jquery.fileupload-audio.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Audio Preview Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* jshint nomen:false */ 13 | /* global define, require, window, document */ 14 | 15 | ;(function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define([ 20 | 'jquery', 21 | 'load-image', 22 | './jquery.fileupload-process' 23 | ], factory); 24 | } else if (typeof exports === 'object') { 25 | // Node/CommonJS: 26 | factory( 27 | require('jquery'), 28 | require('blueimp-load-image/js/load-image'), 29 | require('./jquery.fileupload-process') 30 | ); 31 | } else { 32 | // Browser globals: 33 | factory( 34 | window.jQuery, 35 | window.loadImage 36 | ); 37 | } 38 | }(function ($, loadImage) { 39 | 'use strict'; 40 | 41 | // Prepend to the default processQueue: 42 | $.blueimp.fileupload.prototype.options.processQueue.unshift( 43 | { 44 | action: 'loadAudio', 45 | // Use the action as prefix for the "@" options: 46 | prefix: true, 47 | fileTypes: '@', 48 | maxFileSize: '@', 49 | disabled: '@disableAudioPreview' 50 | }, 51 | { 52 | action: 'setAudio', 53 | name: '@audioPreviewName', 54 | disabled: '@disableAudioPreview' 55 | } 56 | ); 57 | 58 | // The File Upload Audio Preview plugin extends the fileupload widget 59 | // with audio preview functionality: 60 | $.widget('blueimp.fileupload', $.blueimp.fileupload, { 61 | 62 | options: { 63 | // The regular expression for the types of audio files to load, 64 | // matched against the file type: 65 | loadAudioFileTypes: /^audio\/.*$/ 66 | }, 67 | 68 | _audioElement: document.createElement('audio'), 69 | 70 | processActions: { 71 | 72 | // Loads the audio file given via data.files and data.index 73 | // as audio element if the browser supports playing it. 74 | // Accepts the options fileTypes (regular expression) 75 | // and maxFileSize (integer) to limit the files to load: 76 | loadAudio: function (data, options) { 77 | if (options.disabled) { 78 | return data; 79 | } 80 | var file = data.files[data.index], 81 | url, 82 | audio; 83 | if (this._audioElement.canPlayType && 84 | this._audioElement.canPlayType(file.type) && 85 | ($.type(options.maxFileSize) !== 'number' || 86 | file.size <= options.maxFileSize) && 87 | (!options.fileTypes || 88 | options.fileTypes.test(file.type))) { 89 | url = loadImage.createObjectURL(file); 90 | if (url) { 91 | audio = this._audioElement.cloneNode(false); 92 | audio.src = url; 93 | audio.controls = true; 94 | data.audio = audio; 95 | return data; 96 | } 97 | } 98 | return data; 99 | }, 100 | 101 | // Sets the audio element as a property of the file object: 102 | setAudio: function (data, options) { 103 | if (data.audio && !options.disabled) { 104 | data.files[data.index][options.name || 'preview'] = data.audio; 105 | } 106 | return data; 107 | } 108 | 109 | } 110 | 111 | }); 112 | 113 | })); 114 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/jquery.fileupload-video.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Video Preview Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* jshint nomen:false */ 13 | /* global define, require, window, document */ 14 | 15 | ;(function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define([ 20 | 'jquery', 21 | 'load-image', 22 | './jquery.fileupload-process' 23 | ], factory); 24 | } else if (typeof exports === 'object') { 25 | // Node/CommonJS: 26 | factory( 27 | require('jquery'), 28 | require('blueimp-load-image/js/load-image'), 29 | require('./jquery.fileupload-process') 30 | ); 31 | } else { 32 | // Browser globals: 33 | factory( 34 | window.jQuery, 35 | window.loadImage 36 | ); 37 | } 38 | }(function ($, loadImage) { 39 | 'use strict'; 40 | 41 | // Prepend to the default processQueue: 42 | $.blueimp.fileupload.prototype.options.processQueue.unshift( 43 | { 44 | action: 'loadVideo', 45 | // Use the action as prefix for the "@" options: 46 | prefix: true, 47 | fileTypes: '@', 48 | maxFileSize: '@', 49 | disabled: '@disableVideoPreview' 50 | }, 51 | { 52 | action: 'setVideo', 53 | name: '@videoPreviewName', 54 | disabled: '@disableVideoPreview' 55 | } 56 | ); 57 | 58 | // The File Upload Video Preview plugin extends the fileupload widget 59 | // with video preview functionality: 60 | $.widget('blueimp.fileupload', $.blueimp.fileupload, { 61 | 62 | options: { 63 | // The regular expression for the types of video files to load, 64 | // matched against the file type: 65 | loadVideoFileTypes: /^video\/.*$/ 66 | }, 67 | 68 | _videoElement: document.createElement('video'), 69 | 70 | processActions: { 71 | 72 | // Loads the video file given via data.files and data.index 73 | // as video element if the browser supports playing it. 74 | // Accepts the options fileTypes (regular expression) 75 | // and maxFileSize (integer) to limit the files to load: 76 | loadVideo: function (data, options) { 77 | if (options.disabled) { 78 | return data; 79 | } 80 | var file = data.files[data.index], 81 | url, 82 | video; 83 | if (this._videoElement.canPlayType && 84 | this._videoElement.canPlayType(file.type) && 85 | ($.type(options.maxFileSize) !== 'number' || 86 | file.size <= options.maxFileSize) && 87 | (!options.fileTypes || 88 | options.fileTypes.test(file.type))) { 89 | url = loadImage.createObjectURL(file); 90 | if (url) { 91 | video = this._videoElement.cloneNode(false); 92 | video.src = url; 93 | video.controls = true; 94 | data.video = video; 95 | return data; 96 | } 97 | } 98 | return data; 99 | }, 100 | 101 | // Sets the video element as a property of the file object: 102 | setVideo: function (data, options) { 103 | if (data.video && !options.disabled) { 104 | data.files[data.index][options.name || 'preview'] = data.video; 105 | } 106 | return data; 107 | } 108 | 109 | } 110 | 111 | }); 112 | 113 | })); 114 | -------------------------------------------------------------------------------- /qiimp/settings/regex_definitions.yaml: -------------------------------------------------------------------------------- 1 | # formula modified from best answer at https://answers.yahoo.com/question/index?qid=20120113102337AAMpHOd 2 | sample_name: { 3 | regex: '^[a-zA-Z0-9\.]+$', 4 | formula: 'NOT(ISERROR(SUMPRODUCT(SEARCH(MID({cell},ROW(INDIRECT("1:"&LEN({cell}))), 1),"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ."))))', 5 | message: 'the value must contain only alphanumeric characters and/or periods' 6 | } 7 | # regex from http://www.regexlib.com/REDetails.aspx?regexp_id=1535 8 | latitude: { 9 | regex: '^-?([1-8]?[1-9]|[1-9]0)\.{1}\d{1,6}', 10 | formula: 'IF({cell}="",FALSE,ISNUMBER(VALUE({cell}))),{cell}>=-90,{cell}<=90)', 11 | message: 'the value must contain only decimal values of degrees between -90 and 90 inclusive' 12 | } 13 | # regex from http://www.regexlib.com/REDetails.aspx?regexp_id=1536 14 | longitude: { 15 | regex: '^-?([1]?[1-7][1-9]|[1]?[1-8][0]|[1-9]?[0-9])\.{1}\d{1,6}', 16 | formula: 'IF({cell}="",FALSE,ISNUMBER(VALUE({cell}))),{cell}>=-180,{cell}<=180)', 17 | message: 'the value must contain only decimal values of degrees between -180 and 180 inclusive' 18 | } 19 | geo_loc_name: { 20 | regex: '^[\w -]+(:[\w -]+)?(:[\w -]+)?$', 21 | formula: 'AND((LEN({cell})-LEN(SUBSTITUTE({cell},":","")))>=0,(LEN({cell})-LEN(SUBSTITUTE({cell},":","")))<=2,RIGHT({cell},1)<>":")', 22 | message: 'the value may contain only words, spaces, and hyphens, separated by zero to two colons' 23 | } 24 | # regex modified from https://stackoverflow.com/questions/1057716/ 25 | # regular-expression-to-validate-a-timestamp/1057739#1057739 26 | # Note that regex and formula don't do EXACTLY the same thing: for example, 27 | # formula will fail a day number of 32 but regex won't; same for hour number 28 | # of 24. Regex is less stringent (i.e., less correct). 29 | datetime: { 30 | regex: '^([0-9]{4})(?:-([0-1][0-2])(?:-([0-3][0-9])(?: ([0-2][0-9])(?::([0-5][0-9])(?::([0-5][0-9]))?)?)?)?)?$', 31 | formula: 'AND(AND(IFERROR(INT(LEFT({cell},4))>1900,FALSE),IFERROR(INT(LEFT({cell},4))<=YEAR(NOW()),FALSE)), OR(MID({cell},5,1)="", AND(AND(MID({cell},5,1)="-",IFERROR(INT(MID({cell},6,1))>=0,FALSE),IFERROR(INT(MID({cell},6,1))<=1,FALSE),NOT(MID({cell},7,1)=""),IFERROR(INT(MID({cell},6,2))>=1,FALSE),IFERROR(INT(MID({cell},6,2))<=12,FALSE)), OR(MID({cell},8,1)="", AND(AND(MID({cell},8,1)="-",IFERROR(INT(MID({cell},9,1))>=0,FALSE),IFERROR(INT(MID({cell},9,1))<=3,FALSE),NOT(MID({cell},10,1)=""),IFERROR(INT(MID({cell},9,2))>=1,FALSE),IFERROR(INT(MID({cell},9,2))<=31,FALSE)), OR(MID({cell},11,1)="", AND(AND(MID({cell},11,1)=" ",IFERROR(INT(MID({cell},12,1))>=0,FALSE),IFERROR(INT(MID({cell},12,1))<=2,FALSE),NOT(MID({cell},13,1)=""),IFERROR(INT(MID({cell},12,2))>=0,FALSE),IFERROR(INT(MID({cell},12,2))<=23,FALSE)), OR(MID({cell},14,1)="", AND(AND(MID({cell},14,1)=":",IFERROR(INT(MID({cell},15,1))>=0,FALSE),IFERROR(INT(MID({cell},15,1))<=5,FALSE),NOT(MID({cell},16,1)=""),IFERROR(INT(MID({cell},15,2))>=0,FALSE),IFERROR(INT(MID({cell},15,2))<=59,FALSE)), OR(MID({cell},17,1)="", AND(AND(MID({cell},17,1)=":",IFERROR(INT(MID({cell},18,1))>=0,FALSE),IFERROR(INT(MID({cell},18,1))<=5,FALSE),NOT(MID({cell},19,1)=""),IFERROR(INT(MID({cell},18,2))>=0,FALSE),IFERROR(INT(MID({cell},18,2))<=59,FALSE)), LEN({cell})<=19)))))))))))', 32 | message: 'the value must be a valid timestamp in one of these formats: YYYY or YYYY-MM or YYYY-MM-DD or YYYY-MM-DD hh or YYYY-MM-DD hh:mm or YYYY-MM-DD hh:mm:ss' 33 | } 34 | # regex modified from datetime above 35 | # Note that regex and formula don't do EXACTLY the same thing: for example, 36 | # formula will fail an hour number of 24 but regex won't. 37 | # Regex is less stringent (i.e., less correct). 38 | time: { 39 | regex: '^([0-2][0-9])(:([0-5][0-9])(?::([0-5][0-9]))?)$', 40 | formula: 'AND(AND(IFERROR(INT(LEFT({cell},1))>=0,FALSE),IFERROR(INT(LEFT({cell},1))<=2,FALSE),NOT(MID({cell},2,1)=""),IFERROR(INT(LEFT({cell},2))>=0,FALSE),IFERROR(INT(LEFT({cell},2))<=23,FALSE),MID({cell},3,1)=":",IFERROR(INT(MID({cell},4,1))>=0,FALSE),IFERROR(INT(MID({cell},4,1))<=5,FALSE),NOT(MID({cell},5,1)=""),IFERROR(INT(MID({cell},4,2))>=0,FALSE),IFERROR(INT(MID({cell},4,2))<=59,FALSE)),OR(MID({cell},6,1)="",AND(AND(MID({cell},6,1)=":",IFERROR(INT(MID({cell},7,1))>=0,FALSE),IFERROR(INT(MID({cell},7,1))<=5,FALSE),NOT(MID({cell},8,1)=""),IFERROR(INT(MID({cell},7,2))>=0,FALSE),IFERROR(INT(MID({cell},7,2))<=59,FALSE)),LEN({cell})<=8)))', 41 | message: 'the value must be a valid time in one of these formats: hh:mm or hh:mm:ss' 42 | } 43 | # TODO: add elevation -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/jquery.fileupload-validate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Validation Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, require, window */ 13 | 14 | ;(function (factory) { 15 | 'use strict'; 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define([ 19 | 'jquery', 20 | './jquery.fileupload-process' 21 | ], factory); 22 | } else if (typeof exports === 'object') { 23 | // Node/CommonJS: 24 | factory( 25 | require('jquery'), 26 | require('./jquery.fileupload-process') 27 | ); 28 | } else { 29 | // Browser globals: 30 | factory( 31 | window.jQuery 32 | ); 33 | } 34 | }(function ($) { 35 | 'use strict'; 36 | 37 | // Append to the default processQueue: 38 | $.blueimp.fileupload.prototype.options.processQueue.push( 39 | { 40 | action: 'validate', 41 | // Always trigger this action, 42 | // even if the previous action was rejected: 43 | always: true, 44 | // Options taken from the global options map: 45 | acceptFileTypes: '@', 46 | maxFileSize: '@', 47 | minFileSize: '@', 48 | maxNumberOfFiles: '@', 49 | disabled: '@disableValidation' 50 | } 51 | ); 52 | 53 | // The File Upload Validation plugin extends the fileupload widget 54 | // with file validation functionality: 55 | $.widget('blueimp.fileupload', $.blueimp.fileupload, { 56 | 57 | options: { 58 | /* 59 | // The regular expression for allowed file types, matches 60 | // against either file type or file name: 61 | acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, 62 | // The maximum allowed file size in bytes: 63 | maxFileSize: 10000000, // 10 MB 64 | // The minimum allowed file size in bytes: 65 | minFileSize: undefined, // No minimal file size 66 | // The limit of files to be uploaded: 67 | maxNumberOfFiles: 10, 68 | */ 69 | 70 | // Function returning the current number of files, 71 | // has to be overriden for maxNumberOfFiles validation: 72 | getNumberOfFiles: $.noop, 73 | 74 | // Error and info messages: 75 | messages: { 76 | maxNumberOfFiles: 'Maximum number of files exceeded', 77 | acceptFileTypes: 'File type not allowed', 78 | maxFileSize: 'File is too large', 79 | minFileSize: 'File is too small' 80 | } 81 | }, 82 | 83 | processActions: { 84 | 85 | validate: function (data, options) { 86 | if (options.disabled) { 87 | return data; 88 | } 89 | var dfd = $.Deferred(), 90 | settings = this.options, 91 | file = data.files[data.index], 92 | fileSize; 93 | if (options.minFileSize || options.maxFileSize) { 94 | fileSize = file.size; 95 | } 96 | if ($.type(options.maxNumberOfFiles) === 'number' && 97 | (settings.getNumberOfFiles() || 0) + data.files.length > 98 | options.maxNumberOfFiles) { 99 | file.error = settings.i18n('maxNumberOfFiles'); 100 | } else if (options.acceptFileTypes && 101 | !(options.acceptFileTypes.test(file.type) || 102 | options.acceptFileTypes.test(file.name))) { 103 | file.error = settings.i18n('acceptFileTypes'); 104 | } else if (fileSize > options.maxFileSize) { 105 | file.error = settings.i18n('maxFileSize'); 106 | } else if ($.type(fileSize) === 'number' && 107 | fileSize < options.minFileSize) { 108 | file.error = settings.i18n('minFileSize'); 109 | } else { 110 | delete file.error; 111 | } 112 | if (file.error || data.files.error) { 113 | data.files.error = true; 114 | dfd.rejectWith(this, [data]); 115 | } else { 116 | dfd.resolveWith(this, [data]); 117 | } 118 | return dfd.promise(); 119 | } 120 | 121 | } 122 | 123 | }); 124 | 125 | })); 126 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/cors/jquery.postmessage-transport.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery postMessage Transport Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, require, window, document */ 13 | 14 | ;(function (factory) { 15 | 'use strict'; 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['jquery'], factory); 19 | } else if (typeof exports === 'object') { 20 | // Node/CommonJS: 21 | factory(require('jquery')); 22 | } else { 23 | // Browser globals: 24 | factory(window.jQuery); 25 | } 26 | }(function ($) { 27 | 'use strict'; 28 | 29 | var counter = 0, 30 | names = [ 31 | 'accepts', 32 | 'cache', 33 | 'contents', 34 | 'contentType', 35 | 'crossDomain', 36 | 'data', 37 | 'dataType', 38 | 'headers', 39 | 'ifModified', 40 | 'mimeType', 41 | 'password', 42 | 'processData', 43 | 'timeout', 44 | 'traditional', 45 | 'type', 46 | 'url', 47 | 'username' 48 | ], 49 | convert = function (p) { 50 | return p; 51 | }; 52 | 53 | $.ajaxSetup({ 54 | converters: { 55 | 'postmessage text': convert, 56 | 'postmessage json': convert, 57 | 'postmessage html': convert 58 | } 59 | }); 60 | 61 | $.ajaxTransport('postmessage', function (options) { 62 | if (options.postMessage && window.postMessage) { 63 | var iframe, 64 | loc = $('').prop('href', options.postMessage)[0], 65 | target = loc.protocol + '//' + loc.host, 66 | xhrUpload = options.xhr().upload; 67 | // IE always includes the port for the host property of a link 68 | // element, but not in the location.host or origin property for the 69 | // default http port 80 and https port 443, so we strip it: 70 | if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) { 71 | target = target.replace(/:(80|443)$/, ''); 72 | } 73 | return { 74 | send: function (_, completeCallback) { 75 | counter += 1; 76 | var message = { 77 | id: 'postmessage-transport-' + counter 78 | }, 79 | eventName = 'message.' + message.id; 80 | iframe = $( 81 | '' 84 | ).bind('load', function () { 85 | $.each(names, function (i, name) { 86 | message[name] = options[name]; 87 | }); 88 | message.dataType = message.dataType.replace('postmessage ', ''); 89 | $(window).bind(eventName, function (e) { 90 | e = e.originalEvent; 91 | var data = e.data, 92 | ev; 93 | if (e.origin === target && data.id === message.id) { 94 | if (data.type === 'progress') { 95 | ev = document.createEvent('Event'); 96 | ev.initEvent(data.type, false, true); 97 | $.extend(ev, data); 98 | xhrUpload.dispatchEvent(ev); 99 | } else { 100 | completeCallback( 101 | data.status, 102 | data.statusText, 103 | {postmessage: data.result}, 104 | data.headers 105 | ); 106 | iframe.remove(); 107 | $(window).unbind(eventName); 108 | } 109 | } 110 | }); 111 | iframe[0].contentWindow.postMessage( 112 | message, 113 | target 114 | ); 115 | }).appendTo(document.body); 116 | }, 117 | abort: function () { 118 | if (iframe) { 119 | iframe.remove(); 120 | } 121 | } 122 | }; 123 | } 124 | }); 125 | 126 | })); 127 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Much of the content of this file is copied from the 2 | # setup.py of the (open-source) PyPA sample project at 3 | # https://github.com/pypa/sampleproject/blob/master/setup.py 4 | 5 | # Always prefer setuptools over distutils 6 | from setuptools import setup, find_packages 7 | 8 | # To use a consistent encoding 9 | from codecs import open 10 | from os import path 11 | 12 | here = path.abspath(path.dirname(__file__)) 13 | 14 | # Get the long description from the README file 15 | with open(path.join(here, 'README.md'), encoding='utf-8') as f: 16 | long_description = f.read() 17 | 18 | setup( 19 | name='qiimp', 20 | 21 | # Versions should comply with PEP440. 22 | version='0.3', 23 | 24 | description='Software to guide users through generating metadata templates for the Center for Microbiome Innovation', 25 | long_description=long_description, 26 | 27 | # The project's main homepage. 28 | url="https://github.com/ucsd-ccbb/qiimp", 29 | 30 | # Author details 31 | author='The Center for Computational Biology and Bioinformatics', 32 | author_email='abirmingham@ucsd.edu', 33 | 34 | # Choose your license 35 | license='MIT', 36 | 37 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 38 | classifiers=[ 39 | # How mature is this project? Common values are 40 | # 3 - Alpha 41 | # 4 - Beta 42 | # 5 - Production/Stable 43 | 'Development Status :: 3 - Alpha', 44 | 45 | # Indicate who your project is intended for 46 | 'Intended Audience :: Science/Research', 47 | 'Topic :: Scientific/Engineering :: Bio-Informatics', 48 | 'Topic :: Scientific/Engineering :: Medical Science Apps.' 49 | 50 | # Pick your license as you wish (should match "license" above) 51 | 'License :: OSI Approved :: MIT License', 52 | 53 | # Specify the Python versions you support here. In particular, ensure 54 | # that you indicate whether you support Python 2, Python 3 or both. 55 | 'Programming Language:: Python:: 3:: Only', 56 | 'Programming Language :: Python :: 3.3', 57 | 'Programming Language :: Python :: 3.4', 58 | 'Programming Language :: Python :: 3.5', 59 | 'Programming Language :: Python :: 3.6', 60 | ], 61 | 62 | # What does your project relate to? 63 | keywords='microbiome screening bioinformatics', 64 | 65 | # You can just specify the packages manually here if your project is 66 | # simple. Or you can use find_packages(). 67 | packages=find_packages(exclude=['contrib', 'docs', 'tests']), 68 | 69 | # , 70 | # List run-time dependencies here. These will be installed by pip when 71 | # your project is installed, although this can be overridden with a requirements.txt file 72 | install_requires=['openpyxl', 'tornado', 'xlsxwriter', 'PyYAML', 'pandas'], 73 | 74 | # List additional groups of dependencies here (e.g. development 75 | # dependencies). You can install these using the following syntax, 76 | # for example: 77 | # $ pip install -e .[dev,test] 78 | extras_require={ 79 | 'dev': ['check-manifest'], 80 | 'test': ['coverage'], 81 | }, 82 | 83 | package_data={ 84 | 'qiimp': [ 85 | '*.*', 86 | 'output/*.*', 87 | 'client_scripts/*.*', 88 | 'settings/*.*', 89 | 'settings/packages/*.*', 90 | 'templates/*.*', 91 | # man, I *hate* that there's no way to do recursive directory inclusion with package_data! 92 | 'third-party/*.*', 93 | 'third-party/bootstrap-3.3.7-dist/css/*.*', 94 | 'third-party/bootstrap-3.3.7-dist/fonts/*.*', 95 | 'third-party/bootstrap-3.3.7-dist/js/*.*', 96 | 'third-party/jQuery-File-Upload-9.19.2/cors/*.*', 97 | 'third-party/jQuery-File-Upload-9.19.2/css/*.*', 98 | 'third-party/jQuery-File-Upload-9.19.2/img/*.*', 99 | 'third-party/jQuery-File-Upload-9.19.2/js/*.*', 100 | 'third-party/jQuery-File-Upload-9.19.2/js/cors/*.*', 101 | 'third-party/jQuery-File-Upload-9.19.2/js/vendor/*.*', 102 | # I am leaving out the server and test sub-folders on the theory I don't need them for deployment ... 103 | 'third-party/jquery-ui-1.12.1/external/jquery/*.*', 104 | 'third-party/jquery-ui-1.12.1/images/*.*', 105 | 'third-party/jquery-ui-1.12.1/*.*', 106 | 'third-party/jquery_validation/*.*', 107 | ] 108 | }, 109 | 110 | # I'm transferring package data with the install, which I then need to relocate. 111 | # This is harder to do if the data is zipped up in an egg, so no zipping! 112 | zip_safe=False, 113 | 114 | # To provide executable scripts, use entry points in preference to the 115 | # "scripts" keyword. Entry points provide cross-platform support and allow 116 | # pip to create the appropriate form of executable for the target platform. 117 | entry_points={ 118 | 'console_scripts': [ 119 | 'start_qiimp_server=qiimp.metadata_wizard_server:main' 120 | ] 121 | } 122 | ) -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 3 | "camelcase" : true, // true: Identifiers must be in camelCase 4 | "curly" : true, // true: Require {} for every new block or scope 5 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 6 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() 7 | "immed" : true, // true: Require immediate invocations to be wrapped in parens 8 | // e.g. `(function () { } ());` 9 | "indent" : 4, // {int} Number of spaces to use for indentation 10 | "latedef" : true, // true: Require variables/functions to be defined before being used 11 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` 12 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 13 | "noempty" : true, // true: Prohibit use of empty blocks 14 | "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment) 15 | "plusplus" : false, // true: Prohibit use of `++` & `--` 16 | "quotmark" : "single", // Quotation mark consistency: 17 | // false : do nothing (default) 18 | // true : ensure whatever is used is consistent 19 | // "single" : require single quotes 20 | // "double" : require double quotes 21 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 22 | "unused" : true, // true: Require all defined variables be used 23 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode 24 | "trailing" : true, // true: Prohibit trailing whitespaces 25 | "maxparams" : false, // {int} Max number of formal params allowed per function 26 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions) 27 | "maxstatements" : false, // {int} Max number statements per function 28 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function 29 | "maxlen" : false, // {int} Max number of characters per line 30 | 31 | // Relaxing 32 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 33 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 34 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 35 | "eqnull" : false, // true: Tolerate use of `== null` 36 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 37 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) 38 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 39 | // (ex: `for each`, multiple try/catch, function expression…) 40 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 41 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 42 | "funcscope" : false, // true: Tolerate defining variables inside control statements" 43 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') 44 | "iterator" : false, // true: Tolerate using the `__iterator__` property 45 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 46 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 47 | "laxcomma" : false, // true: Tolerate comma-first style coding 48 | "loopfunc" : false, // true: Tolerate functions being defined in loops 49 | "multistr" : false, // true: Tolerate multi-line strings 50 | "proto" : false, // true: Tolerate using the `__proto__` property 51 | "scripturl" : false, // true: Tolerate script-targeted URLs 52 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment 53 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 54 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 55 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 56 | "validthis" : false, // true: Tolerate using this in a non-constructor function 57 | 58 | // Environments 59 | "browser" : false, // Web Browser (window, document, etc) 60 | "couch" : false, // CouchDB 61 | "devel" : false, // Development/debugging (alert, confirm, etc) 62 | "dojo" : false, // Dojo Toolkit 63 | "jquery" : false, // jQuery 64 | "mootools" : false, // MooTools 65 | "node" : false, // Node.js 66 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 67 | "prototypejs" : false, // Prototype and Scriptaculous 68 | "rhino" : false, // Rhino 69 | "worker" : false, // Web Workers 70 | "wsh" : false, // Windows Scripting Host 71 | "yui" : false, // Yahoo User Interface 72 | 73 | // Legacy 74 | "nomen" : true, // true: Prohibit dangling `_` in variables 75 | "onevar" : true, // true: Allow only one `var` statement per function 76 | "passfail" : false, // true: Stop on first error 77 | "white" : true, // true: Check against strict whitespace and indentation rules 78 | 79 | // Custom Globals 80 | "globals" : {} // additional predefined global variables 81 | } 82 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/jquery.fileupload-jquery-ui.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload jQuery UI Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* jshint nomen:false */ 13 | /* global define, require, window */ 14 | 15 | ;(function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define([ 20 | 'jquery', 21 | './jquery.fileupload-ui' 22 | ], factory); 23 | } else if (typeof exports === 'object') { 24 | // Node/CommonJS: 25 | factory( 26 | require('jquery'), 27 | require('./jquery.fileupload-ui') 28 | ); 29 | } else { 30 | // Browser globals: 31 | factory(window.jQuery); 32 | } 33 | }(function ($) { 34 | 'use strict'; 35 | 36 | $.widget('blueimp.fileupload', $.blueimp.fileupload, { 37 | 38 | options: { 39 | processdone: function (e, data) { 40 | data.context.find('.start').button('enable'); 41 | }, 42 | progress: function (e, data) { 43 | if (data.context) { 44 | data.context.find('.progress').progressbar( 45 | 'option', 46 | 'value', 47 | parseInt(data.loaded / data.total * 100, 10) 48 | ); 49 | } 50 | }, 51 | progressall: function (e, data) { 52 | var $this = $(this); 53 | $this.find('.fileupload-progress') 54 | .find('.progress').progressbar( 55 | 'option', 56 | 'value', 57 | parseInt(data.loaded / data.total * 100, 10) 58 | ).end() 59 | .find('.progress-extended').each(function () { 60 | $(this).html( 61 | ($this.data('blueimp-fileupload') || 62 | $this.data('fileupload')) 63 | ._renderExtendedProgress(data) 64 | ); 65 | }); 66 | } 67 | }, 68 | 69 | _renderUpload: function (func, files) { 70 | var node = this._super(func, files), 71 | showIconText = $(window).width() > 480; 72 | node.find('.progress').empty().progressbar(); 73 | node.find('.start').button({ 74 | icons: {primary: 'ui-icon-circle-arrow-e'}, 75 | text: showIconText 76 | }); 77 | node.find('.cancel').button({ 78 | icons: {primary: 'ui-icon-cancel'}, 79 | text: showIconText 80 | }); 81 | if (node.hasClass('fade')) { 82 | node.hide(); 83 | } 84 | return node; 85 | }, 86 | 87 | _renderDownload: function (func, files) { 88 | var node = this._super(func, files), 89 | showIconText = $(window).width() > 480; 90 | node.find('.delete').button({ 91 | icons: {primary: 'ui-icon-trash'}, 92 | text: showIconText 93 | }); 94 | if (node.hasClass('fade')) { 95 | node.hide(); 96 | } 97 | return node; 98 | }, 99 | 100 | _startHandler: function (e) { 101 | $(e.currentTarget).button('disable'); 102 | this._super(e); 103 | }, 104 | 105 | _transition: function (node) { 106 | var deferred = $.Deferred(); 107 | if (node.hasClass('fade')) { 108 | node.fadeToggle( 109 | this.options.transitionDuration, 110 | this.options.transitionEasing, 111 | function () { 112 | deferred.resolveWith(node); 113 | } 114 | ); 115 | } else { 116 | deferred.resolveWith(node); 117 | } 118 | return deferred; 119 | }, 120 | 121 | _create: function () { 122 | this._super(); 123 | this.element 124 | .find('.fileupload-buttonbar') 125 | .find('.fileinput-button').each(function () { 126 | var input = $(this).find('input:file').detach(); 127 | $(this) 128 | .button({icons: {primary: 'ui-icon-plusthick'}}) 129 | .append(input); 130 | }) 131 | .end().find('.start') 132 | .button({icons: {primary: 'ui-icon-circle-arrow-e'}}) 133 | .end().find('.cancel') 134 | .button({icons: {primary: 'ui-icon-cancel'}}) 135 | .end().find('.delete') 136 | .button({icons: {primary: 'ui-icon-trash'}}) 137 | .end().find('.progress').progressbar(); 138 | }, 139 | 140 | _destroy: function () { 141 | this.element 142 | .find('.fileupload-buttonbar') 143 | .find('.fileinput-button').each(function () { 144 | var input = $(this).find('input:file').detach(); 145 | $(this) 146 | .button('destroy') 147 | .append(input); 148 | }) 149 | .end().find('.start') 150 | .button('destroy') 151 | .end().find('.cancel') 152 | .button('destroy') 153 | .end().find('.delete') 154 | .button('destroy') 155 | .end().find('.progress').progressbar('destroy'); 156 | this._super(); 157 | } 158 | 159 | }); 160 | 161 | })); 162 | -------------------------------------------------------------------------------- /qiimp/xlsx_builder.py: -------------------------------------------------------------------------------- 1 | import collections 2 | from random import randrange 3 | import re 4 | import unicodedata 5 | import xlsxwriter 6 | import yaml 7 | 8 | import qiimp.schema_builder 9 | import qiimp.xlsx_basics as xlsxbasics 10 | import qiimp.xlsx_metadata_grid_builder 11 | import qiimp.xlsx_validation_builder 12 | import qiimp.xlsx_static_grid_builder 13 | import qiimp.xlsx_dynamic_grid_builder 14 | 15 | # Ensures defaultdicts are represented as nice yaml rather than nasty (see https://stackoverflow.com/a/19323121 ) 16 | from yaml.representer import Representer 17 | yaml.add_representer(collections.defaultdict, Representer.represent_dict) 18 | 19 | 20 | def write_workbook(study_name, schema_dict, form_dict, metadata_wizard_settings): 21 | num_allowable_samples = 1000 22 | # TODO: someday: either expand code to use num_samples and add real code to get in from interface, or take out unused hook 23 | num_samples = 0 24 | num_columns = len(schema_dict.keys()) 25 | a_regex_handler = metadata_wizard_settings.regex_handler 26 | 27 | # create workbook 28 | file_base_name = slugify(study_name) 29 | file_name = '{0}_{1}.xlsx'.format(file_base_name, randrange(1000, 9999)) 30 | output_path = metadata_wizard_settings.get_output_path(file_name) 31 | workbook = xlsxwriter.Workbook(output_path, {'strings_to_numbers': False, 32 | 'strings_to_formulas': True, 33 | 'strings_to_urls': True}) 34 | 35 | # write metadata worksheet 36 | phi_renamed_schema_dict = qiimp.schema_builder.rewrite_field_names_with_phi_if_relevant(schema_dict) 37 | metadata_worksheet = xlsxbasics.MetadataWorksheet(workbook, num_columns, num_samples, a_regex_handler, 38 | num_allowable_samples=num_allowable_samples) 39 | qiimp.xlsx_metadata_grid_builder.write_metadata_grid(metadata_worksheet, phi_renamed_schema_dict, 40 | DescriptionWorksheet.get_sheet_name()) 41 | 42 | # write validation worksheet 43 | validation_worksheet = qiimp.xlsx_static_grid_builder.ValidationWorksheet(workbook, num_columns, 44 | num_samples, a_regex_handler) 45 | index_and_range_str_tuple_by_header_dict = qiimp.xlsx_static_grid_builder.write_static_validation_grid_and_helpers( 46 | validation_worksheet, phi_renamed_schema_dict) 47 | qiimp.xlsx_dynamic_grid_builder.write_dynamic_validation_grid( 48 | validation_worksheet, index_and_range_str_tuple_by_header_dict) 49 | 50 | # write descriptions worksheet 51 | descriptions_worksheet = DescriptionWorksheet(workbook, num_columns, num_samples, a_regex_handler) 52 | xlsxbasics.write_header(descriptions_worksheet, "field name", 0) 53 | xlsxbasics.write_header(descriptions_worksheet, "field description", 1) 54 | sorted_keys = xlsxbasics.sort_keys(phi_renamed_schema_dict) 55 | for field_index, field_name in enumerate(sorted_keys): 56 | row_num = field_index + 1 + 1 # plus 1 to move past name row, and plus 1 again because row nums are 1-based 57 | field_specs_dict = phi_renamed_schema_dict[field_name] 58 | message = qiimp.xlsx_validation_builder.get_field_constraint_description(field_specs_dict, a_regex_handler) 59 | descriptions_worksheet.worksheet.write("A{0}".format(row_num), field_name, metadata_worksheet.header_format) 60 | descriptions_worksheet.worksheet.write("B{0}".format(row_num), message) 61 | 62 | # write schema worksheet--note, don't use the phi_renamed_schema_dict but the original schema_dict 63 | schema_worksheet = xlsxbasics.create_worksheet(workbook, xlsxbasics.SheetNames.schema.value) 64 | schema_worksheet.write_string("A1", yaml.dump(schema_dict, default_flow_style=False)) 65 | schema_worksheet.hide() 66 | 67 | # write form worksheet 68 | form_worksheet = xlsxbasics.create_worksheet(workbook, xlsxbasics.SheetNames.form.value) 69 | form_worksheet.write_string("A1", yaml.dump(form_dict, default_flow_style=False)) 70 | form_worksheet.hide() 71 | 72 | # write readme worksheet 73 | readme_format = workbook.add_format({'align': 'left', 'valign': 'top'}) 74 | readme_format.set_text_wrap() 75 | readme_worksheet = xlsxbasics.create_worksheet(workbook, xlsxbasics.SheetNames.readme.value) 76 | readme_worksheet.set_column(0, 0, 100) # Width of column A set to 100. 77 | tutorial_hyperlink_str = "=HYPERLINK(\"{0}\", \"Click here for instructions on using this spreadsheet.\")".format( 78 | metadata_wizard_settings.TUTORIAL_LINK) 79 | 80 | readme_worksheet.write_formula(0,0, tutorial_hyperlink_str, 81 | # TODO: someday: centralize link format definitions. 82 | # this link format is a copy-paste of the one in 83 | # xlsx_dynamic_grid_builder._write_dynamic_name_link_col ; assuming we want 84 | # all the link formats in the spreadsheet to look the same, they should be defined 85 | # in one central place. 86 | xlsxbasics.make_format(workbook, {'font_color': 'blue', 'underline': 1})) 87 | readme_worksheet.write_string('A3', metadata_wizard_settings.make_readme_text(), readme_format) 88 | 89 | # close workbook 90 | workbook.close() 91 | return file_name 92 | 93 | 94 | class DescriptionWorksheet(xlsxbasics.MetadataWorksheet): 95 | @classmethod 96 | def get_sheet_name(cls): 97 | return xlsxbasics.SheetNames.data_dictionary.value 98 | 99 | def __init__(self, workbook, num_attributes, num_samples, a_regex_handler): 100 | super().__init__(workbook, num_attributes, num_samples, a_regex_handler, make_sheet=False) 101 | 102 | SHEET_NAME = self.get_sheet_name() 103 | self.worksheet = xlsxbasics.create_worksheet(self.workbook, SHEET_NAME, 104 | self._permissive_protect_options) 105 | 106 | 107 | # very slight modification of django code at https://github.com/django/django/blob/master/django/utils/text.py#L413 108 | def slugify(value, allow_unicode=False): 109 | """ 110 | Convert to ASCII if 'allow_unicode' is False. Convert spaces to hyphens. 111 | Remove characters that aren't alphanumerics, underscores, or hyphens. 112 | Convert to lowercase. Also strip leading and trailing whitespace. 113 | """ 114 | value = str(value) 115 | if allow_unicode: 116 | value = unicodedata.normalize('NFKC', value) 117 | else: 118 | value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii') 119 | value = re.sub(r'[^\w\s-]', '', value).strip().lower() 120 | return re.sub(r'[-\s]+', '-', value) 121 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/js/jquery.fileupload-process.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Processing Plugin 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2012, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* jshint nomen:false */ 13 | /* global define, require, window */ 14 | 15 | ;(function (factory) { 16 | 'use strict'; 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define([ 20 | 'jquery', 21 | './jquery.fileupload' 22 | ], factory); 23 | } else if (typeof exports === 'object') { 24 | // Node/CommonJS: 25 | factory( 26 | require('jquery'), 27 | require('./jquery.fileupload') 28 | ); 29 | } else { 30 | // Browser globals: 31 | factory( 32 | window.jQuery 33 | ); 34 | } 35 | }(function ($) { 36 | 'use strict'; 37 | 38 | var originalAdd = $.blueimp.fileupload.prototype.options.add; 39 | 40 | // The File Upload Processing plugin extends the fileupload widget 41 | // with file processing functionality: 42 | $.widget('blueimp.fileupload', $.blueimp.fileupload, { 43 | 44 | options: { 45 | // The list of processing actions: 46 | processQueue: [ 47 | /* 48 | { 49 | action: 'log', 50 | type: 'debug' 51 | } 52 | */ 53 | ], 54 | add: function (e, data) { 55 | var $this = $(this); 56 | data.process(function () { 57 | return $this.fileupload('process', data); 58 | }); 59 | originalAdd.call(this, e, data); 60 | } 61 | }, 62 | 63 | processActions: { 64 | /* 65 | log: function (data, options) { 66 | console[options.type]( 67 | 'Processing "' + data.files[data.index].name + '"' 68 | ); 69 | } 70 | */ 71 | }, 72 | 73 | _processFile: function (data, originalData) { 74 | var that = this, 75 | dfd = $.Deferred().resolveWith(that, [data]), 76 | chain = dfd.promise(); 77 | this._trigger('process', null, data); 78 | $.each(data.processQueue, function (i, settings) { 79 | var func = function (data) { 80 | if (originalData.errorThrown) { 81 | return $.Deferred() 82 | .rejectWith(that, [originalData]).promise(); 83 | } 84 | return that.processActions[settings.action].call( 85 | that, 86 | data, 87 | settings 88 | ); 89 | }; 90 | chain = chain.then(func, settings.always && func); 91 | }); 92 | chain 93 | .done(function () { 94 | that._trigger('processdone', null, data); 95 | that._trigger('processalways', null, data); 96 | }) 97 | .fail(function () { 98 | that._trigger('processfail', null, data); 99 | that._trigger('processalways', null, data); 100 | }); 101 | return chain; 102 | }, 103 | 104 | // Replaces the settings of each processQueue item that 105 | // are strings starting with an "@", using the remaining 106 | // substring as key for the option map, 107 | // e.g. "@autoUpload" is replaced with options.autoUpload: 108 | _transformProcessQueue: function (options) { 109 | var processQueue = []; 110 | $.each(options.processQueue, function () { 111 | var settings = {}, 112 | action = this.action, 113 | prefix = this.prefix === true ? action : this.prefix; 114 | $.each(this, function (key, value) { 115 | if ($.type(value) === 'string' && 116 | value.charAt(0) === '@') { 117 | settings[key] = options[ 118 | value.slice(1) || (prefix ? prefix + 119 | key.charAt(0).toUpperCase() + key.slice(1) : key) 120 | ]; 121 | } else { 122 | settings[key] = value; 123 | } 124 | 125 | }); 126 | processQueue.push(settings); 127 | }); 128 | options.processQueue = processQueue; 129 | }, 130 | 131 | // Returns the number of files currently in the processsing queue: 132 | processing: function () { 133 | return this._processing; 134 | }, 135 | 136 | // Processes the files given as files property of the data parameter, 137 | // returns a Promise object that allows to bind callbacks: 138 | process: function (data) { 139 | var that = this, 140 | options = $.extend({}, this.options, data); 141 | if (options.processQueue && options.processQueue.length) { 142 | this._transformProcessQueue(options); 143 | if (this._processing === 0) { 144 | this._trigger('processstart'); 145 | } 146 | $.each(data.files, function (index) { 147 | var opts = index ? $.extend({}, options) : options, 148 | func = function () { 149 | if (data.errorThrown) { 150 | return $.Deferred() 151 | .rejectWith(that, [data]).promise(); 152 | } 153 | return that._processFile(opts, data); 154 | }; 155 | opts.index = index; 156 | that._processing += 1; 157 | that._processingQueue = that._processingQueue.then(func, func) 158 | .always(function () { 159 | that._processing -= 1; 160 | if (that._processing === 0) { 161 | that._trigger('processstop'); 162 | } 163 | }); 164 | }); 165 | } 166 | return this._processingQueue; 167 | }, 168 | 169 | _create: function () { 170 | this._super(); 171 | this._processing = 0; 172 | this._processingQueue = $.Deferred().resolveWith(this) 173 | .promise(); 174 | } 175 | 176 | }); 177 | 178 | })); 179 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | jQuery File Upload Demo - Basic version 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 50 |
51 |

jQuery File Upload Demo

52 |

Basic version

53 | 60 |
61 |
62 |

File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
63 | Supports cross-domain, chunked and resumable file uploads.
64 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

65 |
66 |
67 | 68 | 69 | 70 | Select files... 71 | 72 | 73 | 74 |
75 |
76 | 77 |
78 |
79 |
80 | 81 |
82 |
83 |
84 |
85 |

Demo Notes

86 |
87 |
88 |
    89 |
  • The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
  • 90 |
  • Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
  • 91 |
  • Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
  • 92 |
  • You can drag & drop files from your desktop on this webpage (see Browser support).
  • 93 |
  • Please refer to the project website and documentation for more information.
  • 94 |
  • Built with the Bootstrap CSS framework and Icons from Glyphicons.
  • 95 |
96 |
97 |
98 |
99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/README.md: -------------------------------------------------------------------------------- 1 | # jQuery File Upload Plugin 2 | 3 | ## Demo 4 | [Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/) 5 | 6 | ## Description 7 | File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. 8 | Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads. 9 | 10 | ## Setup 11 | * [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup) 12 | * [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin) 13 | 14 | ## Features 15 | * **Multiple file upload:** 16 | Allows to select multiple files at once and upload them simultaneously. 17 | * **Drag & Drop support:** 18 | Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window. 19 | * **Upload progress bar:** 20 | Shows a progress bar indicating the upload progress for individual files and for all uploads combined. 21 | * **Cancelable uploads:** 22 | Individual file uploads can be canceled to stop the upload progress. 23 | * **Resumable uploads:** 24 | Aborted uploads can be resumed with browsers supporting the Blob API. 25 | * **Chunked uploads:** 26 | Large files can be uploaded in smaller chunks with browsers supporting the Blob API. 27 | * **Client-side image resizing:** 28 | Images can be automatically resized on client-side with browsers supporting the required JS APIs. 29 | * **Preview images, audio and video:** 30 | A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs. 31 | * **No browser plugins (e.g. Adobe Flash) required:** 32 | The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins. 33 | * **Graceful fallback for legacy browsers:** 34 | Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers. 35 | * **HTML file upload form fallback:** 36 | Allows progressive enhancement by using a standard HTML file upload form as widget element. 37 | * **Cross-site file uploads:** 38 | Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects. 39 | * **Multiple plugin instances:** 40 | Allows to use multiple plugin instances on the same webpage. 41 | * **Customizable and extensible:** 42 | Provides an API to set individual options and define callback methods for various upload events. 43 | * **Multipart and file contents stream uploads:** 44 | Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload). 45 | * **Compatible with any server-side application platform:** 46 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads. 47 | 48 | ## Requirements 49 | 50 | ### Mandatory requirements 51 | * [jQuery](https://jquery.com/) v. 1.6+ 52 | * [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included): Required for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite. 53 | * [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included): Required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). 54 | 55 | ### Optional requirements 56 | * [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+: Used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions. 57 | * [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+: Required for the image previews and resizing functionality. 58 | * [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+:Required for the image previews and resizing functionality. 59 | * [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+: Used to display the uploaded images in a lightbox. 60 | * [Bootstrap](http://getbootstrap.com/) v. 3.2.0+ 61 | * [Glyphicons](http://glyphicons.com/) 62 | 63 | The user interface of all versions, except the jQuery UI version, is built with [Bootstrap](http://getbootstrap.com/) and icons from [Glyphicons](http://glyphicons.com/). 64 | 65 | ### Cross-domain requirements 66 | [Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server. 67 | 68 | The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests). 69 | The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service. 70 | 71 | ### Custom Backends 72 | 73 | You can add support for various backends by adhering to the specification [outlined here](https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response). 74 | 75 | ## Browsers 76 | 77 | ### Desktop browsers 78 | The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions: 79 | 80 | * Google Chrome 81 | * Apple Safari 4.0+ 82 | * Mozilla Firefox 3.0+ 83 | * Opera 11.0+ 84 | * Microsoft Internet Explorer 6.0+ 85 | 86 | ### Mobile browsers 87 | The File Upload plugin has been tested with and supports the following mobile browsers: 88 | 89 | * Apple Safari on iOS 6.0+ 90 | * Google Chrome on iOS 6.0+ 91 | * Google Chrome on Android 4.0+ 92 | * Default Browser on Android 2.3+ 93 | * Opera Mobile 12.0+ 94 | 95 | ### Supported features 96 | For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support). 97 | 98 | ## Contributing 99 | **Bug fixes** and **new features** can be proposed using [pull requests](https://github.com/blueimp/jQuery-File-Upload/pulls). 100 | Please read the [contribution guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before submitting a pull request. 101 | 102 | ## Support 103 | This project is actively maintained, but there is no official support channel. 104 | If you have a question that another developer might help you with, please post to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload) and tag your question with `blueimp jquery file upload`. 105 | 106 | ## License 107 | Released under the [MIT license](https://opensource.org/licenses/MIT). 108 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 20 | 21 | jQuery File Upload Plugin Test 22 | 23 | 24 | 25 | 26 |

jQuery File Upload Plugin Test

27 |

28 |
29 |

30 |
    31 |
    32 | 33 |
    34 | 35 |
    36 |
    37 | 38 | 39 | 40 | Add files... 41 | 42 | 43 | 47 | 51 | 55 | 56 | 57 | 58 |
    59 | 60 |
    61 | 62 |
    63 |
    64 |
    65 | 66 |
     
    67 |
    68 |
    69 | 70 | 71 |
    72 |
    73 | 74 | 105 | 106 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-python/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # jQuery File Upload Plugin GAE Python Example 4 | # https://github.com/blueimp/jQuery-File-Upload 5 | # 6 | # Copyright 2011, Sebastian Tschan 7 | # https://blueimp.net 8 | # 9 | # Licensed under the MIT license: 10 | # https://opensource.org/licenses/MIT 11 | # 12 | 13 | from google.appengine.api import memcache, images 14 | import json 15 | import os 16 | import re 17 | import urllib 18 | import webapp2 19 | 20 | DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') 21 | WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/' 22 | MIN_FILE_SIZE = 1 # bytes 23 | # Max file size is memcache limit (1MB) minus key size minus overhead: 24 | MAX_FILE_SIZE = 999000 # bytes 25 | IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') 26 | ACCEPT_FILE_TYPES = IMAGE_TYPES 27 | THUMB_MAX_WIDTH = 80 28 | THUMB_MAX_HEIGHT = 80 29 | THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png' 30 | EXPIRATION_TIME = 300 # seconds 31 | # If set to None, only allow redirects to the referer protocol+host. 32 | # Set to a regexp for custom pattern matching against the redirect value: 33 | REDIRECT_ALLOW_TARGET = None 34 | 35 | class CORSHandler(webapp2.RequestHandler): 36 | def cors(self): 37 | headers = self.response.headers 38 | headers['Access-Control-Allow-Origin'] = '*' 39 | headers['Access-Control-Allow-Methods'] =\ 40 | 'OPTIONS, HEAD, GET, POST, DELETE' 41 | headers['Access-Control-Allow-Headers'] =\ 42 | 'Content-Type, Content-Range, Content-Disposition' 43 | 44 | def initialize(self, request, response): 45 | super(CORSHandler, self).initialize(request, response) 46 | self.cors() 47 | 48 | def json_stringify(self, obj): 49 | return json.dumps(obj, separators=(',', ':')) 50 | 51 | def options(self, *args, **kwargs): 52 | pass 53 | 54 | class UploadHandler(CORSHandler): 55 | def validate(self, file): 56 | if file['size'] < MIN_FILE_SIZE: 57 | file['error'] = 'File is too small' 58 | elif file['size'] > MAX_FILE_SIZE: 59 | file['error'] = 'File is too big' 60 | elif not ACCEPT_FILE_TYPES.match(file['type']): 61 | file['error'] = 'Filetype not allowed' 62 | else: 63 | return True 64 | return False 65 | 66 | def validate_redirect(self, redirect): 67 | if redirect: 68 | if REDIRECT_ALLOW_TARGET: 69 | return REDIRECT_ALLOW_TARGET.match(redirect) 70 | referer = self.request.headers['referer'] 71 | if referer: 72 | from urlparse import urlparse 73 | parts = urlparse(referer) 74 | redirect_allow_target = '^' + re.escape( 75 | parts.scheme + '://' + parts.netloc + '/' 76 | ) 77 | return re.match(redirect_allow_target, redirect) 78 | return False 79 | 80 | def get_file_size(self, file): 81 | file.seek(0, 2) # Seek to the end of the file 82 | size = file.tell() # Get the position of EOF 83 | file.seek(0) # Reset the file position to the beginning 84 | return size 85 | 86 | def write_blob(self, data, info): 87 | key = urllib.quote(info['type'].encode('utf-8'), '') +\ 88 | '/' + str(hash(data)) +\ 89 | '/' + urllib.quote(info['name'].encode('utf-8'), '') 90 | try: 91 | memcache.set(key, data, time=EXPIRATION_TIME) 92 | except: #Failed to add to memcache 93 | return (None, None) 94 | thumbnail_key = None 95 | if IMAGE_TYPES.match(info['type']): 96 | try: 97 | img = images.Image(image_data=data) 98 | img.resize( 99 | width=THUMB_MAX_WIDTH, 100 | height=THUMB_MAX_HEIGHT 101 | ) 102 | thumbnail_data = img.execute_transforms() 103 | thumbnail_key = key + THUMB_SUFFIX 104 | memcache.set( 105 | thumbnail_key, 106 | thumbnail_data, 107 | time=EXPIRATION_TIME 108 | ) 109 | except: #Failed to resize Image or add to memcache 110 | thumbnail_key = None 111 | return (key, thumbnail_key) 112 | 113 | def handle_upload(self): 114 | results = [] 115 | for name, fieldStorage in self.request.POST.items(): 116 | if type(fieldStorage) is unicode: 117 | continue 118 | result = {} 119 | result['name'] = urllib.unquote(fieldStorage.filename) 120 | result['type'] = fieldStorage.type 121 | result['size'] = self.get_file_size(fieldStorage.file) 122 | if self.validate(result): 123 | key, thumbnail_key = self.write_blob( 124 | fieldStorage.value, 125 | result 126 | ) 127 | if key is not None: 128 | result['url'] = self.request.host_url + '/' + key 129 | result['deleteUrl'] = result['url'] 130 | result['deleteType'] = 'DELETE' 131 | if thumbnail_key is not None: 132 | result['thumbnailUrl'] = self.request.host_url +\ 133 | '/' + thumbnail_key 134 | else: 135 | result['error'] = 'Failed to store uploaded file.' 136 | results.append(result) 137 | return results 138 | 139 | def head(self): 140 | pass 141 | 142 | def get(self): 143 | self.redirect(WEBSITE) 144 | 145 | def post(self): 146 | if (self.request.get('_method') == 'DELETE'): 147 | return self.delete() 148 | result = {'files': self.handle_upload()} 149 | s = self.json_stringify(result) 150 | redirect = self.request.get('redirect') 151 | if self.validate_redirect(redirect): 152 | return self.redirect(str( 153 | redirect.replace('%s', urllib.quote(s, ''), 1) 154 | )) 155 | if 'application/json' in self.request.headers.get('Accept'): 156 | self.response.headers['Content-Type'] = 'application/json' 157 | self.response.write(s) 158 | 159 | class FileHandler(CORSHandler): 160 | def normalize(self, str): 161 | return urllib.quote(urllib.unquote(str), '') 162 | 163 | def get(self, content_type, data_hash, file_name): 164 | content_type = self.normalize(content_type) 165 | file_name = self.normalize(file_name) 166 | key = content_type + '/' + data_hash + '/' + file_name 167 | data = memcache.get(key) 168 | if data is None: 169 | return self.error(404) 170 | # Prevent browsers from MIME-sniffing the content-type: 171 | self.response.headers['X-Content-Type-Options'] = 'nosniff' 172 | content_type = urllib.unquote(content_type) 173 | if not IMAGE_TYPES.match(content_type): 174 | # Force a download dialog for non-image types: 175 | content_type = 'application/octet-stream' 176 | elif file_name.endswith(THUMB_SUFFIX): 177 | content_type = 'image/png' 178 | self.response.headers['Content-Type'] = content_type 179 | # Cache for the expiration time: 180 | self.response.headers['Cache-Control'] = 'public,max-age=%d' \ 181 | % EXPIRATION_TIME 182 | self.response.write(data) 183 | 184 | def delete(self, content_type, data_hash, file_name): 185 | content_type = self.normalize(content_type) 186 | file_name = self.normalize(file_name) 187 | key = content_type + '/' + data_hash + '/' + file_name 188 | result = {key: memcache.delete(key)} 189 | content_type = urllib.unquote(content_type) 190 | if IMAGE_TYPES.match(content_type): 191 | thumbnail_key = key + THUMB_SUFFIX 192 | result[thumbnail_key] = memcache.delete(thumbnail_key) 193 | if 'application/json' in self.request.headers.get('Accept'): 194 | self.response.headers['Content-Type'] = 'application/json' 195 | s = self.json_stringify(result) 196 | self.response.write(s) 197 | 198 | app = webapp2.WSGIApplication( 199 | [ 200 | ('/', UploadHandler), 201 | ('/(.+)/([^/]+)/([^/]+)', FileHandler) 202 | ], 203 | debug=DEBUG 204 | ) 205 | -------------------------------------------------------------------------------- /qiimp/tests/test_xlsx_validation_builder.py: -------------------------------------------------------------------------------- 1 | from unittest import main, TestCase 2 | import datetime 3 | import qiimp.xlsx_validation_builder as xvb 4 | 5 | 6 | class TestFunctions(TestCase): 7 | # region _make_date_constraint tests 8 | def test__make_date_constraint_YYYY(self): 9 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 10 | 'CONCATENATE({cell},"-01-01"),' 11 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 12 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 13 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 14 | 'CONCATENATE({cell},"-01-01"),' 15 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 16 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 17 | '(IFERROR(DATEVALUE("2008-01-01 00:00:00"),0)+' 18 | 'IFERROR(TIMEVALUE("2008-01-01 00:00:00"),0))') 19 | obs = xvb._make_date_constraint(">=", "2008") 20 | self.assertEqual(exp, obs) 21 | 22 | def test__make_date_constraint_YYYY_MM(self): 23 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 24 | 'CONCATENATE({cell},"-01-01"),' 25 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 26 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 27 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 28 | 'CONCATENATE({cell},"-01-01"),' 29 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 30 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 31 | '(IFERROR(DATEVALUE("2008-12-01 00:00:00"),0)+' 32 | 'IFERROR(TIMEVALUE("2008-12-01 00:00:00"),0))') 33 | obs = xvb._make_date_constraint(">=", "2008-12") 34 | self.assertEqual(exp, obs) 35 | 36 | def test__make_date_constraint_YYYY_MM_DD(self): 37 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 38 | 'CONCATENATE({cell},"-01-01"),' 39 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 40 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 41 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 42 | 'CONCATENATE({cell},"-01-01"),' 43 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 44 | 'CONCATENATE({cell},":00"),{cell})))),0))>' 45 | '(IFERROR(DATEVALUE("2008-12-03 00:00:00"),0)+' 46 | 'IFERROR(TIMEVALUE("2008-12-03 00:00:00"),0))') 47 | # NB: this test uses > rather than >= in other tests, just to show it 48 | # can be done :) 49 | obs = xvb._make_date_constraint(">", "2008-12-03") 50 | self.assertEqual(exp, obs) 51 | 52 | def test__make_date_constraint_YYYY_MM_DD_HH(self): 53 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,CONCATENATE({cell},"-01-01"),' 54 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 55 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 56 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,CONCATENATE({cell},"-01-01"),' 57 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 58 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 59 | '(IFERROR(DATEVALUE("2008-12-03 14:00:00"),0)+' 60 | 'IFERROR(TIMEVALUE("2008-12-03 14:00:00"),0))') 61 | obs = xvb._make_date_constraint(">=", "2008-12-03 14") 62 | self.assertEqual(exp, obs) 63 | 64 | def test__make_date_constraint_YYYY_MM_DD_HH_mm(self): 65 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 66 | 'CONCATENATE({cell},"-01-01"),' 67 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 68 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 69 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 70 | 'CONCATENATE({cell},"-01-01"),' 71 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 72 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 73 | '(IFERROR(DATEVALUE("2008-12-03 14:12:00"),0)+' 74 | 'IFERROR(TIMEVALUE("2008-12-03 14:12:00"),0))') 75 | obs = xvb._make_date_constraint(">=", "2008-12-03 14:12") 76 | self.assertEqual(exp, obs) 77 | 78 | def test__make_date_constraint_YYYY_MM_DD_HH_mm_ss(self): 79 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 80 | 'CONCATENATE({cell},"-01-01"),' 81 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 82 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 83 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 84 | 'CONCATENATE({cell},"-01-01"),' 85 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 86 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 87 | '(IFERROR(DATEVALUE("2008-12-03 14:12:01"),0)+' 88 | 'IFERROR(TIMEVALUE("2008-12-03 14:12:01"),0))') 89 | obs = xvb._make_date_constraint(">=", "2008-12-03 14:12:01") 90 | self.assertEqual(exp, obs) 91 | 92 | def test__make_date_constraint_HH_mm(self): 93 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 94 | 'CONCATENATE({cell},"-01-01"),' 95 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 96 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 97 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 98 | 'CONCATENATE({cell},"-01-01"),' 99 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 100 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 101 | '(IFERROR(DATEVALUE("1900-01-01 14:12:00"),0)+' 102 | 'IFERROR(TIMEVALUE("1900-01-01 14:12:00"),0))') 103 | obs = xvb._make_date_constraint(">=", "14:12") 104 | self.assertEqual(exp, obs) 105 | 106 | def test__make_date_constraint_HH_mm_ss(self): 107 | exp = ('(IFERROR(DATEVALUE(IF(LEN({cell})=4,' 108 | 'CONCATENATE({cell},"-01-01"),' 109 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 110 | 'CONCATENATE({cell},":00"),{cell})))),0)+' 111 | 'IFERROR(TIMEVALUE(IF(LEN({cell})=4,' 112 | 'CONCATENATE({cell},"-01-01"),' 113 | 'IF(LEN({cell})=7,CONCATENATE({cell},"-01"),IF(LEN({cell})=13,' 114 | 'CONCATENATE({cell},":00"),{cell})))),0))>=' 115 | '(IFERROR(DATEVALUE("1900-01-01 14:12:01"),0)+' 116 | 'IFERROR(TIMEVALUE("1900-01-01 14:12:01"),0))') 117 | obs = xvb._make_date_constraint(">=", "14:12:01") 118 | self.assertEqual(exp, obs) 119 | # endregion _make_date_constraint tests 120 | 121 | # region _cast_date_time tests 122 | def test__cast_date_time_YYYY(self): 123 | input_str = "2008" 124 | exp = datetime.datetime.strptime(input_str, "%Y") 125 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 126 | self.assertEqual(exp, obs) 127 | 128 | def test__cast_date_time_YYYY_MM(self): 129 | input_str = "2008-12" 130 | exp = datetime.datetime.strptime(input_str, "%Y-%m") 131 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 132 | self.assertEqual(exp, obs) 133 | 134 | def test__cast_date_time_YYYY_MM_DD(self): 135 | input_str = "2008-12-03" 136 | exp = datetime.datetime.strptime(input_str, "%Y-%m-%d") 137 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 138 | self.assertEqual(exp, obs) 139 | 140 | def test__cast_date_time_YYYY_MM_DD_HH(self): 141 | input_str = "2008-12-03 13" 142 | exp = datetime.datetime.strptime(input_str, "%Y-%m-%d %H") 143 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 144 | self.assertEqual(exp, obs) 145 | 146 | def test__cast_date_time_YYYY_MM_DD_HH_mm(self): 147 | input_str = "2008-12-03 13:04" 148 | exp = datetime.datetime.strptime(input_str, "%Y-%m-%d %H:%M") 149 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 150 | self.assertEqual(exp, obs) 151 | 152 | def test__cast_date_time_YYYY_MM_DD_HH_mm_ss(self): 153 | input_str = "2008-12-03 13:04:08" 154 | exp = datetime.datetime.strptime(input_str, "%Y-%m-%d %H:%M:%S") 155 | obs = xvb._cast_date_time(input_str, xvb.datetime_formats) 156 | self.assertEqual(exp, obs) 157 | 158 | def test__cast_date_time_HH_mm(self): 159 | time_str = "13:04" 160 | date_str = "1900-01-01 " + time_str 161 | exp = datetime.datetime.strptime(date_str, "%Y-%m-%d %H:%M") 162 | obs = xvb._cast_date_time(time_str, xvb.datetime_formats) 163 | self.assertEqual(exp, obs) 164 | 165 | def test__cast_date_time_HH_mm_ss(self): 166 | time_str = "13:04:08" 167 | date_str = "1900-01-01 " + time_str 168 | exp = datetime.datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S") 169 | obs = xvb._cast_date_time(time_str, xvb.datetime_formats) 170 | self.assertEqual(exp, obs) 171 | # endregion _cast_date_time tests 172 | -------------------------------------------------------------------------------- /qiimp/client_scripts/packageWizard.js: -------------------------------------------------------------------------------- 1 | function onModeChange(element){ 2 | // TODO: someday: remove hardcoding of div names, etc 3 | var mode_divs = ["power_div", "wizard_div"]; 4 | var selected_mode = element.value; 5 | var div_to_display_basename = selected_mode.replace("metadata_mode_",""); 6 | var div_to_display = div_to_display_basename + "_div"; 7 | 8 | var existing_package_info = _getEnvAndSampleTypeFromHiddenFields(); 9 | if (existing_package_info !== null){ 10 | var confirm_msg = "Changing the package selection method will remove all package fields and any custom fields. Go ahead?"; 11 | if (!confirm(confirm_msg)){ 12 | return false; 13 | } 14 | } 15 | 16 | resetFieldsAndDivs(null); 17 | 18 | for (var i = 0, len = mode_divs.length; i < len; i++){ 19 | var curr_mode_div = mode_divs[i]; 20 | var curr_mode_div_selector = getIdSelectorFromId(curr_mode_div); 21 | var do_show = false; // default to false 22 | if (curr_mode_div === div_to_display){ 23 | do_show = true; 24 | } else { 25 | // if this is NOT the div to display, unselect any selected values for any selectboxes in this div 26 | var selectboxes_selector = curr_mode_div_selector + " select"; 27 | $(selectboxes_selector).each(function() { 28 | $(this).val(""); 29 | }); 30 | } 31 | showEnableOrHideDisable(curr_mode_div_selector, do_show); 32 | } 33 | 34 | // once user has picked a route, enable the select package button 35 | enableOrDisableBySelectorAndValue(getIdSelectorFromId("select_package_button"), true, true); 36 | validateFormIfSubmitted(); 37 | } 38 | 39 | function onHostChange(event){ 40 | var selected_host = $(event.target).val(); 41 | // TODO: flesh out with getting two-value list 42 | var values_list = g_transferred_variables.SAMPLETYPES_BY_ENV[selected_host]; 43 | var selected_val = (values_list.length === 1) ? values_list[0][0] : null; 44 | updateSelectWithNewCategories("#sample_type_select", values_list, 45 | selected_val, false, true, false, true); 46 | 47 | // show the sampletype div 48 | showEnableOrHideDisable(getIdSelectorFromId("sample_type_div"), true); 49 | } 50 | 51 | function onSelectPackage(){ 52 | var package_info = determinePackageInfo(); 53 | if (package_info === null) { 54 | return false; 55 | } 56 | 57 | // If the user re-chose the SAME package, do nothing 58 | var existing_package_info = _getEnvAndSampleTypeFromHiddenFields(); 59 | if (existing_package_info === package_info){ 60 | return; 61 | } 62 | 63 | // If any custom fields have been added, warn the user they will be cleared by replacing the package 64 | if (g_fields_state.getCurrentNextFieldNum() > 0) { 65 | var confirm_msg = "Changing the package selection will remove all custom fields. Clear existing custom fields and change package?"; 66 | if (!confirm(confirm_msg)) { 67 | return; //do nothing if they fail to confirm 68 | } 69 | } 70 | 71 | resetFieldsAndDivs(package_info); 72 | $("#package-progress").removeClass("hidden"); 73 | 74 | // Make an ajax call to get the list of field names for this package and the list of reserved words 75 | $.ajax({ 76 | url : g_transferred_variables.PACKAGE_PARTIAL_URL, 77 | type : 'POST', 78 | data : package_info, 79 | dataType: 'json', 80 | success : ajax_ok, 81 | error: ajax_err, 82 | complete: function (data) {$("#package-progress").addClass("hidden");} 83 | }); 84 | } 85 | 86 | function determinePackageInfo(){ 87 | var package_info = null; 88 | var package_select_id_selector = getIdSelectorFromId("package_select"); 89 | var sampletype_select_id_selector = getIdSelectorFromId("sample_type_select"); 90 | var host_select_id_selector = getIdSelectorFromId("host_select"); 91 | 92 | // check the "power user" value--the precise, organism-specific package to use 93 | if (!$(package_select_id_selector).is(':disabled')) { 94 | var valid_pkg = $(package_select_id_selector).valid(); 95 | if (valid_pkg) { 96 | var combination_str = $(package_select_id_selector).val(); 97 | var package_info_pieces = combination_str.split(" "); 98 | package_info = makePackageInfoDict(package_info_pieces[0], package_info_pieces[1]) 99 | } 100 | } else { 101 | var valid_sampletype = $(sampletype_select_id_selector).valid(); 102 | var valid_host = $(host_select_id_selector).valid(); 103 | if (valid_sampletype && valid_host) { 104 | // get the host type and the sample type and paste them together to get the package name to look for 105 | var env = $(host_select_id_selector).val(); 106 | var sample_type = $(sampletype_select_id_selector).val(); 107 | package_info = makePackageInfoDict(env, sample_type); 108 | } 109 | } 110 | 111 | return package_info; 112 | } 113 | 114 | function makePackageInfoDict(env, sample_type){ 115 | var result = {}; 116 | result[g_transferred_variables.ELEMENT_IDENTIFIERS.ENV_FIELD] = env; 117 | result[g_transferred_variables.ELEMENT_IDENTIFIERS.SAMPLE_TYPE_FIELD] = sample_type; 118 | return result; 119 | } 120 | 121 | function resetFieldsAndDivs(package_info){ 122 | // hide field_details_div, custom_fields_div, show no_package_warning_div 123 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.EXISTING_FIELDS_DIV)).addClass('hidden'); 124 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.CUSTOM_FIELDS_DIV)).addClass('hidden'); 125 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.NO_PACKAGE_WARNING_DIV)).removeClass('hidden'); 126 | 127 | // clear field_names_sel, field_details_div, which contains the custom fields, and package_details_div 128 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.FIELD_NAMES_SELECT)).empty(); 129 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.FIELD_DETAILS_DIV)).empty(); 130 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.PACKAGE_DETAILS_DIV)).empty(); 131 | 132 | // TODO: someday: remove hardcoding of div name 133 | $("#files").empty(); 134 | 135 | // Reset variables tracking field information 136 | g_fields_state = new Fields(); 137 | _setEnvAndSampleTypeToHiddenFields(package_info) 138 | } 139 | 140 | function _getEnvAndSampleTypeFromHiddenFields(){ 141 | var result = null; 142 | var env_val = $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.ENV_FIELD)).val(); 143 | var sample_type_val = $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.SAMPLE_TYPE_FIELD)).val(); 144 | if ((env_val !== "") || (sample_type_val !== "")) { 145 | result = makePackageInfoDict(env_val, sample_type_val) 146 | } 147 | return result; 148 | } 149 | 150 | function _setEnvAndSampleTypeToHiddenFields(env_and_sample_type_dict){ 151 | var env_val = ""; 152 | var sample_type_val = ""; 153 | if (env_and_sample_type_dict !== null){ 154 | env_val = env_and_sample_type_dict[g_transferred_variables.ELEMENT_IDENTIFIERS.ENV_FIELD]; 155 | sample_type_val = env_and_sample_type_dict[g_transferred_variables.ELEMENT_IDENTIFIERS.SAMPLE_TYPE_FIELD]; 156 | } 157 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.ENV_FIELD)).val(env_val); 158 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.SAMPLE_TYPE_FIELD)).val(sample_type_val); 159 | } 160 | 161 | function ajax_err(request, error) { 162 | console.log(request); 163 | console.log(error); 164 | } 165 | 166 | function ajax_ok(data) { 167 | // Set the reserved words 168 | g_fields_state.setReservedWords(data["reserved_words"]); 169 | 170 | // Set the package field names 171 | var package_field_names_list = data["field_names"]; 172 | g_fields_state.setPackageFields(package_field_names_list); 173 | 174 | var field_desc_dicts_list = data["field_descriptions"]; 175 | var field_descs_html_pieces = []; 176 | for (var i = 0; i < field_desc_dicts_list.length; i++) { 177 | var curr_desc_dict = field_desc_dicts_list[i]; 178 | var curr_desc_html = "" + curr_desc_dict["name"]+ 179 | "" + curr_desc_dict["description"] + ""; 180 | field_descs_html_pieces.push(curr_desc_html); 181 | } 182 | var fields_message = "

    The following fields will be added to your metadata template:

    " + 183 | field_descs_html_pieces.join("") + 184 | "

    Note that none of these fields' names will be available for custom fields.

    "; 185 | $(getIdSelectorFromId("package_details_div")).html(fields_message); 186 | 187 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.NO_PACKAGE_WARNING_DIV)).addClass('hidden'); 188 | $(getIdSelectorFromId(g_transferred_variables.ELEMENT_IDENTIFIERS.CUSTOM_FIELDS_DIV)).removeClass('hidden'); 189 | } -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/server/gae-go/app/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery File Upload Plugin GAE Go Example 3 | * https://github.com/blueimp/jQuery-File-Upload 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | package app 13 | 14 | import ( 15 | "bufio" 16 | "bytes" 17 | "encoding/json" 18 | "fmt" 19 | "github.com/disintegration/gift" 20 | "golang.org/x/net/context" 21 | "google.golang.org/appengine" 22 | "google.golang.org/appengine/memcache" 23 | "hash/crc32" 24 | "image" 25 | "image/gif" 26 | "image/jpeg" 27 | "image/png" 28 | "io" 29 | "log" 30 | "mime/multipart" 31 | "net/http" 32 | "net/url" 33 | "path/filepath" 34 | "regexp" 35 | "strings" 36 | ) 37 | 38 | const ( 39 | WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/" 40 | MIN_FILE_SIZE = 1 // bytes 41 | // Max file size is memcache limit (1MB) minus key size minus overhead: 42 | MAX_FILE_SIZE = 999000 // bytes 43 | IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)" 44 | ACCEPT_FILE_TYPES = IMAGE_TYPES 45 | THUMB_MAX_WIDTH = 80 46 | THUMB_MAX_HEIGHT = 80 47 | EXPIRATION_TIME = 300 // seconds 48 | // If empty, only allow redirects to the referer protocol+host. 49 | // Set to a regexp string for custom pattern matching: 50 | REDIRECT_ALLOW_TARGET = "" 51 | ) 52 | 53 | var ( 54 | imageTypes = regexp.MustCompile(IMAGE_TYPES) 55 | acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES) 56 | thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" + 57 | fmt.Sprint(THUMB_MAX_HEIGHT) 58 | ) 59 | 60 | func escape(s string) string { 61 | return strings.Replace(url.QueryEscape(s), "+", "%20", -1) 62 | } 63 | 64 | func extractKey(r *http.Request) string { 65 | // Use RequestURI instead of r.URL.Path, as we need the encoded form: 66 | path := strings.Split(r.RequestURI, "?")[0] 67 | // Also adjust double encoded slashes: 68 | return strings.Replace(path[1:], "%252F", "%2F", -1) 69 | } 70 | 71 | func check(err error) { 72 | if err != nil { 73 | panic(err) 74 | } 75 | } 76 | 77 | type FileInfo struct { 78 | Key string `json:"-"` 79 | ThumbnailKey string `json:"-"` 80 | Url string `json:"url,omitempty"` 81 | ThumbnailUrl string `json:"thumbnailUrl,omitempty"` 82 | Name string `json:"name"` 83 | Type string `json:"type"` 84 | Size int64 `json:"size"` 85 | Error string `json:"error,omitempty"` 86 | DeleteUrl string `json:"deleteUrl,omitempty"` 87 | DeleteType string `json:"deleteType,omitempty"` 88 | } 89 | 90 | func (fi *FileInfo) ValidateType() (valid bool) { 91 | if acceptFileTypes.MatchString(fi.Type) { 92 | return true 93 | } 94 | fi.Error = "Filetype not allowed" 95 | return false 96 | } 97 | 98 | func (fi *FileInfo) ValidateSize() (valid bool) { 99 | if fi.Size < MIN_FILE_SIZE { 100 | fi.Error = "File is too small" 101 | } else if fi.Size > MAX_FILE_SIZE { 102 | fi.Error = "File is too big" 103 | } else { 104 | return true 105 | } 106 | return false 107 | } 108 | 109 | func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) { 110 | u := &url.URL{ 111 | Scheme: r.URL.Scheme, 112 | Host: appengine.DefaultVersionHostname(c), 113 | Path: "/", 114 | } 115 | uString := u.String() 116 | fi.Url = uString + fi.Key 117 | fi.DeleteUrl = fi.Url 118 | fi.DeleteType = "DELETE" 119 | if fi.ThumbnailKey != "" { 120 | fi.ThumbnailUrl = uString + fi.ThumbnailKey 121 | } 122 | } 123 | 124 | func (fi *FileInfo) SetKey(checksum uint32) { 125 | fi.Key = escape(string(fi.Type)) + "/" + 126 | escape(fmt.Sprint(checksum)) + "/" + 127 | escape(string(fi.Name)) 128 | } 129 | 130 | func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) { 131 | if imageTypes.MatchString(fi.Type) { 132 | src, _, err := image.Decode(bytes.NewReader(buffer.Bytes())) 133 | check(err) 134 | filter := gift.New(gift.ResizeToFit( 135 | THUMB_MAX_WIDTH, 136 | THUMB_MAX_HEIGHT, 137 | gift.LanczosResampling, 138 | )) 139 | dst := image.NewNRGBA(filter.Bounds(src.Bounds())) 140 | filter.Draw(dst, src) 141 | buffer.Reset() 142 | bWriter := bufio.NewWriter(buffer) 143 | switch fi.Type { 144 | case "image/jpeg", "image/pjpeg": 145 | err = jpeg.Encode(bWriter, dst, nil) 146 | case "image/gif": 147 | err = gif.Encode(bWriter, dst, nil) 148 | default: 149 | err = png.Encode(bWriter, dst) 150 | } 151 | check(err) 152 | bWriter.Flush() 153 | thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name) 154 | item := &memcache.Item{ 155 | Key: thumbnailKey, 156 | Value: buffer.Bytes(), 157 | } 158 | err = memcache.Set(c, item) 159 | check(err) 160 | fi.ThumbnailKey = thumbnailKey 161 | } 162 | } 163 | 164 | func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { 165 | fi = &FileInfo{ 166 | Name: p.FileName(), 167 | Type: p.Header.Get("Content-Type"), 168 | } 169 | if !fi.ValidateType() { 170 | return 171 | } 172 | defer func() { 173 | if rec := recover(); rec != nil { 174 | log.Println(rec) 175 | fi.Error = rec.(error).Error() 176 | } 177 | }() 178 | var buffer bytes.Buffer 179 | hash := crc32.NewIEEE() 180 | mw := io.MultiWriter(&buffer, hash) 181 | lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1} 182 | _, err := io.Copy(mw, lr) 183 | check(err) 184 | fi.Size = MAX_FILE_SIZE + 1 - lr.N 185 | if !fi.ValidateSize() { 186 | return 187 | } 188 | fi.SetKey(hash.Sum32()) 189 | item := &memcache.Item{ 190 | Key: fi.Key, 191 | Value: buffer.Bytes(), 192 | } 193 | context := appengine.NewContext(r) 194 | err = memcache.Set(context, item) 195 | check(err) 196 | fi.createThumb(&buffer, context) 197 | fi.CreateUrls(r, context) 198 | return 199 | } 200 | 201 | func getFormValue(p *multipart.Part) string { 202 | var b bytes.Buffer 203 | io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB 204 | return b.String() 205 | } 206 | 207 | func handleUploads(r *http.Request) (fileInfos []*FileInfo) { 208 | fileInfos = make([]*FileInfo, 0) 209 | mr, err := r.MultipartReader() 210 | check(err) 211 | r.Form, err = url.ParseQuery(r.URL.RawQuery) 212 | check(err) 213 | part, err := mr.NextPart() 214 | for err == nil { 215 | if name := part.FormName(); name != "" { 216 | if part.FileName() != "" { 217 | fileInfos = append(fileInfos, handleUpload(r, part)) 218 | } else { 219 | r.Form[name] = append(r.Form[name], getFormValue(part)) 220 | } 221 | } 222 | part, err = mr.NextPart() 223 | } 224 | return 225 | } 226 | 227 | func validateRedirect(r *http.Request, redirect string) bool { 228 | if redirect != "" { 229 | var redirectAllowTarget *regexp.Regexp 230 | if REDIRECT_ALLOW_TARGET != "" { 231 | redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET) 232 | } else { 233 | referer := r.Referer() 234 | if referer == "" { 235 | return false 236 | } 237 | refererUrl, err := url.Parse(referer) 238 | if err != nil { 239 | return false 240 | } 241 | redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta( 242 | refererUrl.Scheme+"://"+refererUrl.Host+"/", 243 | )) 244 | } 245 | return redirectAllowTarget.MatchString(redirect) 246 | } 247 | return false 248 | } 249 | 250 | func get(w http.ResponseWriter, r *http.Request) { 251 | if r.URL.Path == "/" { 252 | http.Redirect(w, r, WEBSITE, http.StatusFound) 253 | return 254 | } 255 | // Use RequestURI instead of r.URL.Path, as we need the encoded form: 256 | key := extractKey(r) 257 | parts := strings.Split(key, "/") 258 | if len(parts) == 3 { 259 | context := appengine.NewContext(r) 260 | item, err := memcache.Get(context, key) 261 | if err == nil { 262 | w.Header().Add("X-Content-Type-Options", "nosniff") 263 | contentType, _ := url.QueryUnescape(parts[0]) 264 | if !imageTypes.MatchString(contentType) { 265 | contentType = "application/octet-stream" 266 | } 267 | w.Header().Add("Content-Type", contentType) 268 | w.Header().Add( 269 | "Cache-Control", 270 | fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), 271 | ) 272 | w.Write(item.Value) 273 | return 274 | } 275 | } 276 | http.Error(w, "404 Not Found", http.StatusNotFound) 277 | } 278 | 279 | func post(w http.ResponseWriter, r *http.Request) { 280 | result := make(map[string][]*FileInfo, 1) 281 | result["files"] = handleUploads(r) 282 | b, err := json.Marshal(result) 283 | check(err) 284 | if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) { 285 | if strings.Contains(redirect, "%s") { 286 | redirect = fmt.Sprintf( 287 | redirect, 288 | escape(string(b)), 289 | ) 290 | } 291 | http.Redirect(w, r, redirect, http.StatusFound) 292 | return 293 | } 294 | w.Header().Set("Cache-Control", "no-cache") 295 | jsonType := "application/json" 296 | if strings.Index(r.Header.Get("Accept"), jsonType) != -1 { 297 | w.Header().Set("Content-Type", jsonType) 298 | } 299 | fmt.Fprintln(w, string(b)) 300 | } 301 | 302 | func delete(w http.ResponseWriter, r *http.Request) { 303 | key := extractKey(r) 304 | parts := strings.Split(key, "/") 305 | if len(parts) == 3 { 306 | result := make(map[string]bool, 1) 307 | context := appengine.NewContext(r) 308 | err := memcache.Delete(context, key) 309 | if err == nil { 310 | result[key] = true 311 | contentType, _ := url.QueryUnescape(parts[0]) 312 | if imageTypes.MatchString(contentType) { 313 | thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2]) 314 | err := memcache.Delete(context, thumbnailKey) 315 | if err == nil { 316 | result[thumbnailKey] = true 317 | } 318 | } 319 | } 320 | w.Header().Set("Content-Type", "application/json") 321 | b, err := json.Marshal(result) 322 | check(err) 323 | fmt.Fprintln(w, string(b)) 324 | } else { 325 | http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed) 326 | } 327 | } 328 | 329 | func handle(w http.ResponseWriter, r *http.Request) { 330 | params, err := url.ParseQuery(r.URL.RawQuery) 331 | check(err) 332 | w.Header().Add("Access-Control-Allow-Origin", "*") 333 | w.Header().Add( 334 | "Access-Control-Allow-Methods", 335 | "OPTIONS, HEAD, GET, POST, DELETE", 336 | ) 337 | w.Header().Add( 338 | "Access-Control-Allow-Headers", 339 | "Content-Type, Content-Range, Content-Disposition", 340 | ) 341 | switch r.Method { 342 | case "OPTIONS", "HEAD": 343 | return 344 | case "GET": 345 | get(w, r) 346 | case "POST": 347 | if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" { 348 | delete(w, r) 349 | } else { 350 | post(w, r) 351 | } 352 | case "DELETE": 353 | delete(w, r) 354 | default: 355 | http.Error(w, "501 Not Implemented", http.StatusNotImplemented) 356 | } 357 | } 358 | 359 | func init() { 360 | http.HandleFunc("/", handle) 361 | } 362 | -------------------------------------------------------------------------------- /qiimp/third-party/jQuery-File-Upload-9.19.2/basic-plus.html: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | jQuery File Upload Demo - Basic Plus version 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 50 |
    51 |

    jQuery File Upload Demo

    52 |

    Basic Plus version

    53 | 60 |
    61 |
    62 |

    File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
    63 | Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
    64 | Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

    65 |
    66 |
    67 | 68 | 69 | 70 | Add files... 71 | 72 | 73 | 74 |
    75 |
    76 | 77 |
    78 |
    79 |
    80 | 81 |
    82 |
    83 |
    84 |
    85 |

    Demo Notes

    86 |
    87 |
    88 |
      89 |
    • The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
    • 90 |
    • Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
    • 91 |
    • Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
    • 92 |
    • You can drag & drop files from your desktop on this webpage (see Browser support).
    • 93 |
    • Please refer to the project website and documentation for more information.
    • 94 |
    • Built with the Bootstrap CSS framework and Icons from Glyphicons.
    • 95 |
    96 |
    97 |
    98 |
    99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /qiimp/schema_builder.py: -------------------------------------------------------------------------------- 1 | import qiimp.metadata_wizard_settings as mws 2 | 3 | 4 | def _get_field_type_to_schema_generator(): 5 | return { 6 | mws.FieldTypes.Text.value: _generate_text_schema, 7 | mws.FieldTypes.Boolean.value: _generate_boolean_schema, 8 | mws.FieldTypes.Categorical.value: _generate_categorical_schema, 9 | mws.FieldTypes.Continuous.value: _generate_continuous_schema 10 | } 11 | 12 | 13 | def _get_default_types_to_input_fields(): 14 | return { 15 | mws.DefaultTypes.no_default.value: None, 16 | mws.DefaultTypes.boolean_default.value: mws.InputNames.boolean_default_select.value, 17 | mws.DefaultTypes.allowed_missing_default.value: mws.InputNames.allowed_missing_default_select.value, 18 | mws.DefaultTypes.categorical_default.value: mws.InputNames.categorical_default_select.value, 19 | mws.DefaultTypes.continuous_default.value: mws.InputNames.continuous_default.value, 20 | mws.DefaultTypes.text_default.value: mws.InputNames.text_default.value, 21 | } 22 | 23 | 24 | def _get_special_handling_fields(): 25 | return [mws.InputNames.field_name.value, mws.InputNames.field_type.value, mws.InputNames.allowed_missing_vals.value, 26 | mws.InputNames.default_value.value, mws.InputNames.allowed_missing_default_select.value, 27 | mws.InputNames.categorical_default_select.value, mws.InputNames.continuous_default.value, 28 | mws.InputNames.boolean_default_select.value, mws.InputNames.text_default.value, 29 | mws.InputNames.datetime_default.value, mws.InputNames.true_value.value, mws.InputNames.false_value.value, 30 | mws.InputNames.data_type.value, mws.InputNames.categorical_values.value, mws.InputNames.minimum_comparison.value, 31 | mws.InputNames.minimum_value.value, mws.InputNames.maximum_comparison.value, mws.InputNames.maximum_value.value, 32 | mws.InputNames.is_phi.value, mws.InputNames.is_unitless.value] 33 | 34 | 35 | def get_validation_schemas(curr_field_from_form, a_regex_handler): 36 | field_name_and_schema_tuples_list = [] 37 | field_name, field_schema = _get_field_validation_schema(curr_field_from_form, a_regex_handler) 38 | 39 | mock_unit_field_form_dict = _mock_a_units_field_if_relevant(curr_field_from_form) 40 | if mock_unit_field_form_dict is not None: 41 | mock_unit_field_name, mock_unit_field_schema = _get_field_validation_schema(mock_unit_field_form_dict, 42 | a_regex_handler) 43 | field_name_and_schema_tuples_list.append((mock_unit_field_name, mock_unit_field_schema)) 44 | field_schema[mws.InputNames.units.value] = mock_unit_field_name 45 | 46 | field_name_and_schema_tuples_list.append((field_name, field_schema)) 47 | return field_name_and_schema_tuples_list 48 | 49 | 50 | def _get_field_validation_schema(curr_field_from_form, a_regex_handler): 51 | field_name = curr_field_from_form[mws.InputNames.field_name.value] 52 | top_level_schema = _build_top_level_schema_dict(curr_field_from_form) 53 | validation_schema = _build_single_validation_schema_dict(curr_field_from_form, a_regex_handler) 54 | 55 | allowed_missing_val_key = mws.InputNames.allowed_missing_vals.value 56 | if allowed_missing_val_key in curr_field_from_form: 57 | # NB: allowed_missing_vals is a fieldset of checkboxes, so it is indicated by its name plus a set of brackets 58 | allowed_missing_vals_from_form = curr_field_from_form[allowed_missing_val_key] 59 | # NB: allowed_missing_vals from form are the *names* of the ebi missing values (like "ebi_not_collected" 60 | # instead of "missing: not collected" because the punctuation/etc in the actual values causes some problems with 61 | # my jquery selectors. Thus, it is necessary to convert them from name to value before use in validation schema 62 | allowed_missing_vals = [_convert_ebi_missing_name_to_ebi_missing_value(x) for x in 63 | allowed_missing_vals_from_form] 64 | missings_schema = _generate_text_schema(None, a_regex_handler) 65 | missings_schema.update({ 66 | mws.ValidationKeys.allowed.value: allowed_missing_vals 67 | }) 68 | 69 | top_level_schema[mws.ValidationKeys.anyof.value] = \ 70 | [missings_schema, validation_schema] 71 | else: 72 | top_level_schema.update(validation_schema) 73 | # end if any allowed missing vals 74 | 75 | top_level_schema = _set_default_keyval_if_any(curr_field_from_form, top_level_schema) 76 | return field_name, top_level_schema 77 | 78 | 79 | def _mock_a_units_field_if_relevant(curr_field_from_form): 80 | result = None 81 | if mws.InputNames.units.value in curr_field_from_form: 82 | base_field_name = curr_field_from_form[mws.InputNames.field_name.value] 83 | units_string = curr_field_from_form[mws.InputNames.units.value] 84 | mock_field_name = base_field_name + mws.UNITS_SUFFIX 85 | 86 | result = { 87 | mws.InputNames.categorical_default_select.value: units_string, 88 | mws.InputNames.categorical_values.value: units_string, 89 | mws.InputNames.default_value.value: mws.DefaultTypes.categorical_default.value, 90 | mws.InputNames.field_name.value: mock_field_name, 91 | mws.InputNames.field_type.value: mws.FieldTypes.Categorical.value 92 | } 93 | 94 | return result 95 | 96 | 97 | # So ... the schema indicates whether a field is phi, but Qiita can't actually read the schema, 98 | # so the customer requests that if a field is marked as phi, then the suffix "_phi" is appended to 99 | # the end of the field name. I kind of hate rewriting the customer's inputs this way, so hopefully 100 | # Qiita will be able to read the schema soon. NB that I COULD change the field names when the schema 101 | # is first generated, but I went with rewriting them afterwards on request so that I can retain a "clean" 102 | # copy of the schema that has the original field names for output on the schema worksheet. 103 | def rewrite_field_names_with_phi_if_relevant(schema_dict): 104 | result = {} 105 | for curr_field_name, curr_field_schema in schema_dict.items(): 106 | new_field_name = curr_field_name 107 | if curr_field_schema[mws.InputNames.is_phi.value]: 108 | new_field_name = new_field_name + mws.PHI_SUFFIX 109 | result[new_field_name] = curr_field_schema 110 | return result 111 | 112 | 113 | def _build_top_level_schema_dict(curr_field_from_form): 114 | top_level_schema = {mws.ValidationKeys.empty.value: False, 115 | mws.ValidationKeys.required.value: True, 116 | mws.InputNames.is_phi.value: mws.InputNames.is_phi.value in curr_field_from_form} 117 | 118 | for curr_key, curr_value in curr_field_from_form.items(): 119 | if curr_key not in _get_special_handling_fields(): 120 | top_level_schema.update({curr_key: curr_value}) 121 | 122 | return top_level_schema 123 | 124 | 125 | def _build_single_validation_schema_dict(curr_field_from_form, a_regex_handler): 126 | generator_funcs_by_type = _get_field_type_to_schema_generator() 127 | field_type = curr_field_from_form[mws.InputNames.field_type.value] 128 | schema_generator_func = generator_funcs_by_type[field_type] 129 | result = schema_generator_func(curr_field_from_form, a_regex_handler) 130 | return result 131 | 132 | 133 | def _generate_text_schema(curr_field_from_form, a_regex_handler): 134 | return _generate_schema_by_data_type( 135 | curr_field_from_form, a_regex_handler, 136 | overriding_datatype=mws.CerberusDataTypes.Text.value) 137 | 138 | 139 | def _generate_boolean_schema(curr_field_from_form, a_regex_handler): 140 | bool_true = curr_field_from_form[mws.InputNames.true_value.value] 141 | bool_false = curr_field_from_form[mws.InputNames.false_value.value] 142 | 143 | curr_schema = _generate_text_schema(curr_field_from_form, a_regex_handler) 144 | curr_schema.update({ 145 | mws.ValidationKeys.allowed.value: [bool_true, bool_false] 146 | }) 147 | return curr_schema 148 | 149 | 150 | def _generate_categorical_schema(curr_field_from_form, a_regex_handler): 151 | curr_schema = _generate_text_schema(curr_field_from_form, a_regex_handler) 152 | 153 | categorical_vals_str = curr_field_from_form[mws.InputNames.categorical_values.value] 154 | split_categorical_vals = categorical_vals_str.split("\r\n") 155 | split_categorical_vals = [x.strip() for x in split_categorical_vals] 156 | non_empty_split_categorical_values = [x for x in split_categorical_vals if x != ""] 157 | 158 | curr_schema.update({ 159 | mws.ValidationKeys.allowed.value: non_empty_split_categorical_values 160 | }) 161 | return curr_schema 162 | 163 | 164 | def _generate_continuous_schema(curr_field_from_form, a_regex_handler): 165 | curr_schema = _generate_schema_by_data_type(curr_field_from_form, a_regex_handler) 166 | 167 | curr_schema = _set_comparison_keyval_if_any(curr_field_from_form, 168 | mws.InputNames.minimum_value.value, 169 | mws.InputNames.minimum_comparison.value, curr_schema) 170 | 171 | curr_schema = _set_comparison_keyval_if_any(curr_field_from_form, 172 | mws.InputNames.maximum_value.value, 173 | mws.InputNames.maximum_comparison.value, curr_schema) 174 | 175 | return curr_schema 176 | 177 | 178 | def _generate_schema_by_data_type(curr_field_from_form, a_regex_handler, overriding_datatype=None): 179 | """ 180 | 181 | :type a_regex_handler: regex_handler.RegexHandler 182 | """ 183 | 184 | data_type = overriding_datatype if overriding_datatype else curr_field_from_form[mws.InputNames.data_type.value] 185 | curr_schema = {mws.ValidationKeys.type.value: data_type} 186 | 187 | regex_for_data_type = a_regex_handler.get_regex_val_by_name(data_type) 188 | if regex_for_data_type: 189 | curr_schema.update({ 190 | mws.ValidationKeys.regex.value: regex_for_data_type 191 | }) 192 | 193 | return curr_schema 194 | 195 | 196 | def _set_default_keyval_if_any(curr_field_from_form, curr_schema): 197 | default_types_to_default_fields = _get_default_types_to_input_fields() 198 | default_type_value = curr_field_from_form[mws.InputNames.default_value.value] 199 | default_value_input_name = default_types_to_default_fields[default_type_value] 200 | if default_value_input_name is not None: 201 | default_val = curr_field_from_form[default_value_input_name] 202 | if default_val in [x.name for x in mws.EbiMissingValues]: 203 | default_val = _convert_ebi_missing_name_to_ebi_missing_value(default_val) 204 | curr_schema[mws.ValidationKeys.default.value] = default_val 205 | return curr_schema 206 | 207 | 208 | def _set_comparison_keyval_if_any(curr_field_from_form, threshold_val_name, comparison_val_name, curr_schema): 209 | if threshold_val_name in curr_field_from_form: 210 | comparison_value = curr_field_from_form[threshold_val_name] 211 | comparison_key = curr_field_from_form[comparison_val_name] 212 | curr_schema.update({ 213 | comparison_key: comparison_value 214 | }) 215 | # end if there's a threshold value 216 | return curr_schema 217 | 218 | 219 | def _convert_ebi_missing_name_to_ebi_missing_value(ebi_missing_name): 220 | return mws.EbiMissingValues[ebi_missing_name].value 221 | --------------------------------------------------------------------------------