diff --git a/.buildpacks b/.buildpacks deleted file mode 100644 index 6c3c501da..000000000 --- a/.buildpacks +++ /dev/null @@ -1 +0,0 @@ -https://github.com/plotly/heroku-buildpack-python#3.3.0b8 diff --git a/CHANGELOG.md b/CHANGELOG.md index d359657bb..5033648fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ * [#554](https://github.com/plotly/dash-bio/pull/554) Added additional props and arbitrary layout arguments to VolcanoPlot. +### Fixed +- [#550](https://github.com/plotly/dash-bio/pull/548) Updated CONTRIBUTING.md andbasic demo app structure. In addition, removed residual code and pre-deploy scripts associated with now-discontinued Dash Bio gallery. + + ## [0.6.1] - 2021-02-15 ### Fixed * [#544](https://github.com/plotly/dash-bio/pull/544) Miscellaneous fixes for NglMoleculeViewer component. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5327bf1ef..1f651eea6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -## Development +# Development -#### Prerequisites +### Prerequisites - [Git](https://git-scm.com/) - [node.js](https://nodejs.org/en/). We recommend using node.js v10.x, but all @@ -17,7 +17,7 @@ client ([setup instructions](http://faculty.smu.edu/reynolds/unixtut/windows.html)). -#### Step 1: Clone the dash-bio repo and install its dependencies +## Step 1: Clone the dash-bio repo and install its dependencies ```bash git clone https://github.com/plotly/dash-bio.git @@ -25,13 +25,13 @@ cd dash-bio npm ci ``` -#### Step 2: Develop +## Step 2: Develop -Development of a component for this repository comprises two parts: +Development of a component for this repository is composed of two parts: the component itself, and a sample application that showcases the capabilities of your component and how it interacts with Dash. -##### Components +### Components Components can either be created using React, or they can be written in pure Python. React components are written in `src/lib/components` before being compiled into Python components that are in the @@ -39,71 +39,79 @@ before being compiled into Python components that are in the `dash_bio/component_factory/` and must be imported in `dash_bio/__init__.py`. -##### Installing new npm packages +### Installing new npm packages If developing a new component based on a React library, please ensure that you have already installed the correct versions of the -preexisting dependencies by running `npm ci`. Then, add the package to +pre-existing dependencies by running `npm ci`. Then, add the package to `package.json` and run `npm i` to add it to the `package-lock.json` file. -###### Naming components +### Naming components Components, regardless of whether they are written using React or Python, need to be named in upper camel case. This is incredibly important due to the amount of parsing we perform in our testing suite and app deployments. -##### Demo applications -Instead of creating standalone Dash apps for each component, there is a file -structure in place to create a main "gallery" page that contains links to each -(component) application. Consequently, the implementation of a component needs -to follow a specific file structure for the corresponding app to be displayed -and run correctly. - -###### Setup -In the `tests/dashbio_demos/` subfolder, please create a file named -`app_{your component name in snake case}.py`. In this file, please include the -following functions: - -* `layout()` should return whatever you would have in your `app.layout`. Due to -the way the CSS is set up for each application, it is advisable to create a -container `div` that will house your application, e.g., -```python -def layout(): - return html.Div(id='my-component-container', children=[ - "A sample component", - dash_bio.MyComponent(id='my-component'), - html.Div(id='my-component-output'), - ]) -``` -* `callbacks(app)` should contain all of the callbacks in the application and -not return anything, e.g., -```python -def callbacks(app): - @app.callback( - Output('my-component-output', 'children'), - [Input('my-component', 'someProperty')] - ) - def update_output(property): - return "Value: {}".format(str(property)) -``` - -###### Testing +### Demo applications +Dash Bio demo apps follow a standardized template and showcase the properties +of the component and possible use-cases with sample datasets. The `assets` and +`layout_helper.py` modules in the `common` subdirectory include the base CSS styling for +demo apps and helper functions to generate the layout and callback structure to run +the demo as a standalone Dash app. These should be added to your demo app directory +to ensure that the layout and structure of your app is consistent when deployed +to the Dash Gallery. See *Setup* below for more details on using `layout_helper.py` +within your demo application. + +### Setup +In the `tests/dashbio_demos/common` subdirectory, you will find the minimal project structure for a Dash Bio demo app. This includes the following files: + +* `app.py`: This contains your Python app code with the demo component. The `app.py` in this case contains a basic outline of the code required for a Dash Bio sample app, but it can be modified or replaced as necessary for a particular component or demo app. If you are using this template, please note the following: +>* `layout()` should return whatever you would have in your `app.layout`. Due to +>the way the CSS is set up for each application, it is advisable to create a +>container `div` that will house your application, e.g., +>```python +>def layout(): +> return html.Div(id='my-component-container', children=[ +> "A sample component", +> dash_bio.MyComponent(id='my-component'), +> html.Div(id='my-component-output'), +> ]) +>``` +>* `callbacks(app)` should contain all of the callbacks in the application and +>not return anything, e.g., +>```python +>def callbacks(app): +> @app.callback( +> Output('my-component-output', 'children'), +> [Input('my-component', 'someProperty')] +> ) +> def update_output(property): +> return "Value: {}".format(str(property)) +>``` + +* `requirements.txt`: A text file which includes all the Python dependencies that need to be installed in order to run the app. +* `layout_helper.py`: A Python module with helper functions to generate the template app layout and callback structure for a Dash Bio gallery app. +* `data`: A directory that can contain sample datasets. +* `assets`: A directory which can contain custom CSS, JS, favicon, or styling assets. Dash will automatically serve all of the files that are included in this folder. +* `Procfile`: Procfile is a required text file that declares which commands should be run by the server on startup like starting your app's web server, scheduling jobs and running background processes. For Dash Bio demo apps, it can remain unmodified. + + +### Testing Test out your application by going to the repository's root directory and running ```bash -python index.py +python tests/dashbio_demos/{YOUR_DEMO_APP}/app.py ``` -Then navigate to `localhost:8050` in your web browser. You should see the -gallery page. To get to your application, click on the square that displays the -name of your component upon hover. + +Then navigate to `localhost:8050` in your web browser. You will need to quit the Python application and rerun it if you have made changes to the Python file itself, or have recently rebuilt/reinstalled the Dash Bio package. To see updated CSS changes, you can simply reload the webpage -in your browser. +in your browser, or enable hot-reloading with [Dash Dev Tools](https://dash.plotly.com/devtools). -###### CSS +### CSS All custom CSS stylesheets should go in the `assets/` folder. Please create a stylesheet with a filename specific to your component. In addition, all ids and class names in your application should be prefixed by the name of your @@ -115,31 +123,31 @@ if you want to make a container `div` for your application as mentioned in the Setup subsection, please account for an extra height of `100px` that is taken up by the header when you are specifying the height of the container. -###### Final touches +### Final touches In the `tests/dashbio_demos/images/` subfolder, please include a PNG file named `pic_{your component name in snake case}.png`. In your demo app file, please include the following functions: -* `description()` is responsible for the text that shows up on hovering over +>* `description()` is responsible for the text that shows up on hovering over your application in the gallery page. It should return a short string with a description of the component, e.g., -```python -def description(): - return "Display bioinformatics data with this component." -``` -* `header_colors()` controls the appearance of the header for your application. +>```python +>def description(): +> return "Display bioinformatics data with this component." +>``` +>* `header_colors()` controls the appearance of the header for your application. It should return a dictionary with any or all of the specified keys `bg_color` (string), `font_color` (string), and `light_logo` (boolean). Please change the background color from default, and try to choose one that isn't used for another application, e.g., -```python -def header_colors(): - return { - 'bg_color': 'rgb(255, 0, 0)', - 'font_color': 'rgb(255, 255, 255)', - 'light_logo': True - } -``` +>```python +>def header_colors(): +> return { +> 'bg_color': 'rgb(255, 0, 0)', +> 'font_color': 'rgb(255, 255, 255)', +> 'light_logo': True +> } +>``` Please lint any additions to Python code with `pylint` and/or `flake8`. @@ -147,7 +155,7 @@ Commit each changeset corresponding to a conceptual entity. Write commit messages at the imperative (e.g., "Document workflow"). Each commit is small; a pull request typically consists of a few commits. -#### Step 3: Run tests locally +## Step 3: Run tests locally To run integration tests locally on, say, Google Chrome: ```bash @@ -160,7 +168,7 @@ pytest tests/integration #for testing all apps pytest tests/integration/test_yourNewApp #for testing only one app ``` Do not worry if you get errors running this last command. You will have to -download a Chrome driver (Linux:chromium), install it, and add its path. +download a Chrome driver (Linux:chromium), install it, and add it to your PATH. Follow what the error messages point to (this will be platform-specific). To write more integration tests, please read this @@ -173,26 +181,27 @@ python tests/unit/unit_test_data_setup.py npm run test ``` -#### Step 4: Rebuild the package if necessary +## Step 4: Rebuild the package if necessary If you have made changes to the JS code, then you need to rebuild the package: ```bash -npm run build +npm run build:all ``` The auto-generated Python files will reflect your updates to the logic. If, instead, you have made changes to the layout, you do not need to rebuild the package. -#### Step 5: Submit a pull request (PR) +## Step 5: Submit a pull request (PR) -Fill out the description template in the GitHub interface. -When you submit the PR, a Heroku review app will be automatically created; it -will remain available for 5 days. +Fill out the description template in the GitHub interface. Please include a +link to the original JavaScript component if your PR is porting a React component +to Dash Bio, and any relevant details or sample datasets that might help with +testing the component and demo app. -### Deployment +## Deployment *Deployment is done from the `master` branch only.* @@ -207,39 +216,28 @@ remote add [app name]-test [deployment server git URL]`. #### Step 2: Edit and commit app-specific files -##### Step 2a: Edit the `Procfile` -Edit the `Procfile` at the root of the repository to say `gunicorn -tests.dashbio_demos.app_name:server`, where `app_name` is the name of -the app you want to deploy in the `tests/dashbio_demos/` folder. - -##### Step 2b: Edit `config.py` -Edit the `config.py` file at the root of the repository such that the variable -`DASH_APP_NAME` be set to the name of your app, but with `app` -replaced by `dash` and underscores (`_`) replaced by dashes -(`-`). (e.g., for `app_manhattan_plot`, the `DASH_APP_NAME` variable -should be set to `dash-manhattan-plot`.) - -##### Step 2c: Commit the changes -Commit the `Procfile` and `config.py`, but *do not push to the -`dash-bio` repo*! +>#### Step 2a: Edit the `Procfile` +>Edit the `Procfile` at the root of the repository to say `web: gunicorn app:server`. +> +>#### Step 2b: Commit the changes +>Commit the `Procfile` and other changes, but *do not push to the +`dash-bio` repo* ! #### Step 3: Push to the playground server -Run `git push [app name]-test master`. This will deploy the app -on the playground server. Check that it works by visiting the URL that -is displayed in the console. Try out a few of the callbacks to make +Run `git subtree push --prefix tests/dashbio_demos/[app directory] [app name]-test master`. This will deploy the app on the playground server. Check that it works by visiting the URL that is displayed in the console. Try out a few of the callbacks to make sure that they are working. #### Step 4: Initialize the app on the dash-gallery server and push to it Log into the `developers` account on [dash-gallery.plotly.host](dash-gallery.plotly.host) and follow the same instructions as in Step 1, but give this remote a different name -(e.g., by running `git remote add gallery [deployment server git -URL]`). Then, run `git push gallery master`. +(e.g. by running `git remote add gallery [deployment server git +URL]`). Then, run `git subtree push --prefix tests/dashbio_demos/[app directory] gallery master`. #### Step 5: Undo the app-specific commit Run `git log` to find the ID of the commit prior to the one that you just made to change the `Procfile`. Then, reset your local branch to -this commit so that the `index.py` app still deploys and runs +this commit so that the `app.py` app still deploys and runs normally. You can do this by running `git reset --hard [commit ID]`. #### Step 6: Ensure that your branch is even with `master` diff --git a/Procfile b/Procfile deleted file mode 100644 index 24896bcdf..000000000 --- a/Procfile +++ /dev/null @@ -1,2 +0,0 @@ -web: gunicorn index:server - diff --git a/app.json b/app.json deleted file mode 100644 index e792e7c04..000000000 --- a/app.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "dash-bio", - "scripts": {}, - "env": {}, - "formation": { - "web": { - "quantity": 1 - } - }, - "addons": [], - "buildpacks": [ - { - "url": "heroku/python" - } - ], - "scripts": { - "dokku": { - "predeploy": "python predeploy.py" - } - } -} diff --git a/config.py b/config.py deleted file mode 100644 index 53082f40e..000000000 --- a/config.py +++ /dev/null @@ -1,52 +0,0 @@ -import os - -# Replace with the name of your Dash app -# This will end up being part of the URL of your deployed app, -# so it can't contain any spaces, capitalizations, or special characters -# -# This name MUST match the name that you specified in the -# Dash App Manager -DASH_APP_NAME = 'dash-bio' -# Set to 'private' if you want to add a login screen to your app -# You can choose who can view the app in your list of files -# at /organize. -# Set to 'public' if you want your app to be accessible to -# anyone who has access to your Plotly server on your network without -# a login screen. -# Set to 'secret' if you want to add a login screen, but allow it -# to be bypassed by using a secret "share_key" parameter. -DASH_APP_PRIVACY = 'public' -# Dash On-Premise is configured with either "Path based routing" -# or "Domain based routing" -# Ask your server administrator which version was set up. -# If a separate subdomain was created, -# then set this to `False`. If it was not, set this to 'True'. -# Path based routing is the default option and most On-Premise -# users use this option. -PATH_BASED_ROUTING = True -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# This section only needs to be filled out # -# if DASH_APP_PRIVACY is set to 'private' or 'secret' # -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Fill in with your Plotly On-Premise username -os.environ['PLOTLY_USERNAME'] = 'developers' -# Fill in with your Plotly On-Premise API key -# See /settings/api to generate a key -# If you have already created a key and saved it on your own machine -# (from the Plotly-Python library instructions at https://plotly.com/python/getting-started) -# then you can view that key in your ~/.plotly/.config file -# or inside a Python session with these commands: -# import plotly -# print(plotly.tools.get_config_file()) -os.environ['PLOTLY_API_KEY'] = 'your-plotly-api-key' -# Fill in with your Plotly On-Premise domain -os.environ['PLOTLY_DOMAIN'] = 'https://your-plotly-domain.com' -os.environ['PLOTLY_API_DOMAIN'] = os.environ['PLOTLY_DOMAIN'] -# Fill in with the domain of your Dash subdomain. -# This matches the domain of the Dash App Manager -PLOTLY_DASH_DOMAIN = 'https://your-dash-manager-plotly-domain.com' -# Keep as True if your SSL certificates are valid. -# If you are just trialing Plotly On-Premise with self signed certificates, -# then you can set this to False. Note that self-signed certificates are not -# safe for production. -os.environ['PLOTLY_SSL_VERIFICATION'] = 'True' diff --git a/data/p53fasta.RData b/data/p53fasta.RData deleted file mode 100644 index de6cd1bb5..000000000 Binary files a/data/p53fasta.RData and /dev/null differ diff --git a/data/voldata.RData b/data/voldata.RData deleted file mode 100644 index 5d0acf02a..000000000 Binary files a/data/voldata.RData and /dev/null differ diff --git a/deploy b/deploy deleted file mode 100755 index 512143d25..000000000 --- a/deploy +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env bash -[[ -n "$TRACE" ]] && set -x -set -eo pipefail - -readonly SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -readonly APPS_DIR_RELATIVE="${APPS_DIR_RELATIVE:-/apps}" -readonly APPS_DIR="${APPS_DIR:-${SOURCE_DIR}${APPS_DIR_RELATIVE}}" -readonly DASH_ENTERPRISE_URL="${DASH_ENTERPRISE_URL:-https://dash-playground.plotly.host}" -readonly CREATE_APP="${CREATE_APP:-false}" -readonly ALLOW_DASHR="${ALLOW_DASHR:-false}" - -log-header() { - declare desc="Log header formatter"; - echo "====> $*" -} - -log-info() { - declare desc="Log info formatter"; - echo " $*" -} - -log-warn() { - declare desc="Log warn formatter"; - echo " ? $*" 1>&2 -} - -log-fail() { - declare desc="Log fail formatter"; - echo " ! $*" 1>&2 - exit 1 -} - -log-exit() { - declare desc="Log exit formatter"; - echo " ! $*" 1>&2 - exit 0 -} - -fn-check-env() { - declare APP="$1" - - if grep -Fxq "$APP" "$SOURCE_DIR/.deployignore"; then - log-exit "App $APP is in the .deployignore file, skipping deploy" - fi - - if ! command -v "dds-client" >/dev/null; then - log-fail "dds-client binary not found" - fi - - if [[ -z "$DASH_ENTERPRISE_API_KEY" ]]; then - log-fail "DASH_ENTERPRISE_API_KEY is not defined" - fi - - if [[ -z "$DASH_ENTERPRISE_USERNAME" ]]; then - log-fail "DASH_ENTERPRISE_USERNAME is not defined" - fi - - if [[ -z "$DASH_ENTERPRISE_URL" ]]; then - log-fail "DASH_ENTERPRISE_URL is not defined" - fi - - if [[ -z "$CIRCLE_SHA1" ]]; then - log-fail "CIRCLE_SHA1 is not defined" - fi -} - -main() { - declare APP="$1" - local app_dir="$APPS_DIR/$APP" - local remote_url="$DASH_ENTERPRISE_URL/GIT/$APP" - local is_dashr=false - local tmp_shallow_clone="$(mktemp -d -t apps-XXXXXXXXXX)" - local tmp_full_clone="$(mktemp -d -t apps-XXXXXXXXXX)" - local force_push=false - local push_code=false - local exit_code remote_sha - trap "rm -rf '$tmp_shallow_clone' '$tmp_full_clone' >/dev/null" RETURN INT TERM EXIT - - fn-check-env "$APP" - - if [[ -z "$APP" ]]; then - log-fail "No app name specified" - fi - - if [[ ! -d "$app_dir" ]]; then - log-fail "Invalid app name: $APP" - fi - - if [[ "$APP" =~ "dashr" ]]; then - is_dashr=true - if [[ "$ALLOW_DASHR" != "true" ]]; then - log-exit "App $APP is a dashr app, skipping deploy" - fi - fi - - if [[ ! -d "$app_dir/assets" ]]; then - log-fail "App $APP is missing the assets directory" - fi - - log-header "Deploying $APP" - log-info "dashr: ${is_dashr}" - if [[ "$is_dashr" == "false" ]]; then - local celery_version="$(cat "$app_dir/requirements.txt" | grep -E "^celery=")" - local redis_version="$(cat "$app_dir/requirements.txt" | grep -E "^redis=")" - - log-info "dash python version: $(cat "$app_dir/requirements.txt" | grep -E "^dash=")" - [[ -n "$celery_version" ]] && log-info "celery python version: $(cat "$app_dir/requirements.txt" | grep -E "^celery=")" - [[ -n "$redis_version" ]] && log-info "redis python version: $(cat "$app_dir/requirements.txt" | grep -E "^redis=")" - - if [[ -n "$celery_version" ]] || [[ -n "$redis_version" ]]; then - log-exit "Skipping service that requires a redis instance" - fi - fi - - if ! dds-client apps:exists --name "$APP" >/dev/null 2>&1; then - log-info "exists: false" - if [[ "$CREATE_APP" == "true" ]]; then - log-warn "$APP not found, creating" - dds-client apps:create --name "$APP" - else - log-exit "Deploy failed because there is no such app on Dash Gallery: $APP. Please use the web interface to create an app with this name" - fi - else - log-info "exists: true" - fi - - if ! git clone --depth 1 "$remote_url" "$tmp_shallow_clone" 2>/dev/null; then - log-fail "Unable to clone repository" - fi - - remote_sha=$(git -C "$tmp_shallow_clone" log --pretty=format:"%h" 2>/dev/null || true) - log-info "remote-sha: $remote_sha" - if [[ -z "$remote_sha" ]]; then - log-header "Initializing repository" - git -C "$tmp_full_clone" init -q - git -C "$tmp_full_clone" remote rm origin 2>/dev/null || true - git -C "$tmp_full_clone" remote add origin "$remote_url" - elif git show "$remote_sha" >/dev/null 2>&1; then - log-header "Existing repository uses old monorepo, recreating" - git -C "$tmp_full_clone" init -q - git -C "$tmp_full_clone" remote rm origin 2>/dev/null || true - git -C "$tmp_full_clone" remote add origin "$remote_url" - force_push=true - else - if ! git clone "$remote_url" "$tmp_full_clone" 2>/dev/null; then - log-fail "Unable to clone repository" - fi - fi - - log-header "Ensuring code is up to date" - log-info "Copying updated app source" - pushd "$tmp_full_clone" >/dev/null - find -not -path "./.git/*" -not -name ".git" -delete 2> /dev/null - popd >/dev/null - - pushd "$app_dir" >/dev/null - cp -Rfp * "$tmp_full_clone" - [[ -f .buildpacks ]] && cp -fp .buildpacks "$tmp_full_clone/.buildpacks" - [[ -f .gitignore ]] && cp -fp .gitignore "$tmp_full_clone/.gitignore" - popd >/dev/null - - if [[ "$is_dashr" == false ]]; then - log-info "Python app detected, injecting common python-specific files" - cp -p "$SOURCE_DIR/app.json" "$tmp_full_clone/app.json" - cp -p "$SOURCE_DIR/predeploy.py" "$tmp_full_clone/predeploy.py" - cp -p "$SOURCE_DIR/runtime.txt" "$tmp_full_clone/runtime.txt" - cp -p "$APPS_DIR/common/layout_helper.py" "$tmp_full_clone/layout_helper.py" - pushd "$APPS_DIR/common/assets" >/dev/null - cp -p * "$tmp_full_clone/assets" - popd >/dev/null - fi - - set +e - git -C "$tmp_full_clone" status | grep -Eo "working (directory|tree) clean" &> /dev/null - exit_code="$?" - set -e - - if [[ "$exit_code" -ne 0 ]]; then - pushd "$tmp_full_clone" >/dev/null - push_code=true - git add . - git commit -qm "Deployed commit: $CIRCLE_SHA1" - popd >/dev/null - fi - - if [[ "$push_code" != "true" ]]; then - log-header "🤜 App not updated, skipping deploy" - log-info "Check app out at $DASH_ENTERPRISE_URL/$APP/" - return 0 - fi - - if [[ "$force_push" == "true" ]]; then - log-header "Deploying via force push" - git -C "$tmp_full_clone" push --force origin master - else - log-header "Deploying" - git -C "$tmp_full_clone" push origin master - fi -} - -main "$@" diff --git a/index.html b/index.html deleted file mode 100644 index 1e40571c1..000000000 --- a/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - dash-bio - - -
- - - diff --git a/predeploy.py b/predeploy.py deleted file mode 100644 index 784fd0780..000000000 --- a/predeploy.py +++ /dev/null @@ -1,70 +0,0 @@ -# flake8: noqa -import os -import sys - - -app_index_string = """ app.index_string = \'\'\' - - - - {%metas%} - {%title%} - {%favicon%} - {%css%} - - - - - - - {%app_entry%} - - - -\'\'\'\n\n""" - -app_file_name = "" - -# get the name of the file used to run the app; -# this is not always 'app.py' - -with open(os.path.join("/app", "Procfile"), "r") as f: - contents = f.read().split(" ") - for item in contents: - if "server" in item: - app_file_name = item.split(":")[0] - -if app_file_name == "": - print("Could not find app file") - sys.exit(1) - -full_app_path = os.path.join("/app", app_file_name + ".py") - -lines = [] - -# find the line with the conditional used to run -# the app server; anything after the `app.run_server` -# call will not get executed because the app is running -with open(full_app_path, "r") as f: - lines = f.readlines() - name_main_index = 0 - for line in lines: - if "__name__ == '__main__'" in line: - name_main_index = lines.index(line) - break - - # insert the index_string declaration just above - # the run_server conditional - lines.insert(name_main_index, app_index_string) - -# if something has gone wrong, don't overwrite -# the file; otherwise, write the new lines into it -# (which include the tags) -if len(lines) > 0: - with open(full_app_path, "w") as f: - f.writelines(lines) diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index 9fbd3bf0a..000000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.6.8 diff --git a/tests/dashbio_demos/common/Procfile b/tests/dashbio_demos/common/Procfile new file mode 100644 index 000000000..38371ebbf --- /dev/null +++ b/tests/dashbio_demos/common/Procfile @@ -0,0 +1 @@ +web: gunicorn app:server diff --git a/tests/dashbio_demos/common/app.py b/tests/dashbio_demos/common/app.py new file mode 100644 index 000000000..fb835e8ff --- /dev/null +++ b/tests/dashbio_demos/common/app.py @@ -0,0 +1,107 @@ +import os + +import dash_html_components as html +import dash_core_components as dcc +from dash.dependencies import Input, Output +import dash_bio + +from layout_helper import run_standalone_app + +# Font and text color +text_style = { + 'color': "#506784", + 'font-family': 'Open Sans' +} + +# Set the data path for your demo app +DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') + +# Load the sample datasets +with open(os.path.join(DATAPATH, 'sample.fasta'), encoding='utf-8') as data_file: + dataset = data_file.read() + + +# Description for your app that will be shown in the gallery +def description(): + return 'View multiple sequence samples of genomic or protenomic sequences.' + + +# Header colors for the app template +def header_colors(): + return { + 'bg_color': '#0C4142', + 'font_color': 'white', + } + + +# Layout of the app +def layout(): + return html.Div(id='sample-body', className='app-body', children=[ + html.Div([ + html.Div(id='sample-control-tabs', className='control-tabs', children=[ + dcc.Tabs( + id='sample-tabs', value='what-is', + children=[ + dcc.Tab( + label='About', + value='what-is', + children=html.Div(className='control-tab', children=[ + html.P("Insert description here.") + ]) + ), + dcc.Tab( + label='Data', + value='sample-tab-select', + children=html.Div(className='control-tab', children=[ + html.Div(className='app-controls-block', children=[ + html.Div( + className='fullwidth-app-controls-name', + children="Select preloaded dataset" + ), + dcc.Dropdown( + id='sample-dropdown', + options=[ + { + 'label': 'Sample.fasta', + 'value': 'dataset1' + } + ], + value='dataset' + ) + ]), + ]) + ), + ], + ), + ]), + ]), + dcc.Loading(parent_className='dashbio-loading', children=html.Div([ + dash_bio.AlignmentChart( + id='sample-chart', + height=725, + data=dataset, + ), + ])), + + dcc.Store(id='sample-data-store'), + ]) + + +# Returns callbacks for the app +def callbacks(_app): + # Render main chart + @_app.callback( + Output('sample-chart', 'data'), + [Input('sample-data-store', 'data')] + ) + def update_chart(input_data): + return input_data + + +# Helper function from `layout_helper` which generates app template +app = run_standalone_app(layout, callbacks, header_colors, __file__) +# Creates a server object for deployment +server = app.server + +if __name__ == '__main__': + app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/common/data/sample.fasta b/tests/dashbio_demos/common/data/sample.fasta new file mode 100644 index 000000000..2dc160bac --- /dev/null +++ b/tests/dashbio_demos/common/data/sample.fasta @@ -0,0 +1,45 @@ +>FER_CAPAN +MA------SVSATMISTSFMPRKPAVTSL-KPIPNVGE--ALFGLKS-A--NGGKVTCMASYKVKLITPDGPIEFDCPDN +VYILDQAEEAGHDLPYSCRAGSCSSCAGKIAGGAVDQTDGNFLDDDQLEEGWVLTCVAYPQSDVTIETHKEAELVG- +>FER1_SOLLC +MA------SISGTMISTSFLPRKPAVTSL-KAISNVGE--ALFGLKS-G--RNGRITCMASYKVKLITPEGPIEFECPDD +VYILDQAEEEGHDLPYSCRAGSCSSCAGKVTAGSVDQSDGNFLDEDQEAAGFVLTCVAYPKGDVTIETHKEEELTA- +>Q93XJ9_SOLTU +MA------SISGTMISTSFLPRKPVVTSL-KAISNVGE--ALFGLKS-G--RNGRITCMASYKVKLITPDGPIEFECPDD +VYILDQAEEEGHDLPYSCRAGSCSSCAGKVTAGTVDQSDGKFLDDDQEAAGFVLTCVAYPKCDVTIETHKEEELTA- +>FER1_MESCR +MAAT--TAALSGATMSTAFAPK--TPPMTAALPTNVGR--ALFGLKS-SASR-GRVTAMAAYKVTLVTPEGKQELECPDD +VYILDAAEEAGIDLPYSCRAGSCSSCAGKVTSGSVNQDDGSFLDDDQIKEGWVLTCVAYPTGDVTIETHKEEELTA- +>FER1_SPIOL +MAAT--TTTMMG--MATTFVPKPQAPPMMAALPSNTGR--SLFGLKT-GSR--GGRMTMAAYKVTLVTPTGNVEFQCPDD +VYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDDQSFLDDDQIDEGWVLTCAAYPVSDVTIETHKEEELTA- +>FER1_ARATH +MAST----ALSSAIVGTSFIRRSPAPISLRSLPSANTQ--SLFGLKS-GTARGGRVTAMATYKVKFITPEGELEVECDDD +VYVLDAAEEAGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSFLDDEQIGEGFVLTCAAYPTSDVTIETHKEEDIV-- +>FER2_ARATH +MAST----ALSSAIVSTSFLRRQQTPISLRSLPFANTQ--SLFGLKS-STARGGRVTAMATYKVKFITPEGEQEVECEED +VYVLDAAEEAGLDLPYSCRAGSCSSCAGKVVSGSIDQSDQSFLDDEQMSEGYVLTCVAYPTSDVVIETHKEEAIM-- +>FER1_PEA +MATT---PALYGTAVSTSFLRTQPMPMSV-TTTKAFSN--GFLGLKT-SLKRGDLAVAMASYKVKLVTPDGTQEFECPSD +VYILDHAEEVGIDLPYSCRAGSCSSCAGKVVGGEVDQSDGSFLDDEQIEAGFVLTCVAYPTSDVVIETHKEEDLTA- +>Q7XA98_TRIPR +MATT---PALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGFGLKSVSTKRGDLAVAMATYKVKLITPEGPQEFDCPDD +VYILDHAEEVGIELPYSCRAGSCSSCAGKVVNGNVNQEDGSFLDDEQIEGGWVLTCVAFPTSDVTIETHKEEELTA- +>FER1_MAIZE +MATVLGSPRAPAFFFSSSSLRAAPAPTAV--ALPAAKV--GIMGRSA-SSRR--RLRAQATYNVKLITPEGEVELQVPDD +VYILDQAEEDGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSYLDDGQIADGWVLTCHAYPTSDVVIETHKEEELTGA +>O80429_MAIZE +MAAT---------ALSMSILR---APPPCFSSPLRLRV--AVAKPLA-APMRRQLLRAQATYNVKLITPEGEVELQVPDD +VYILDFAEEEGIDLPFSCRAGSCSSCAGKVVSGSVDQSDQSFLNDNQVADGWVLTCAAYPTSDVVIETHKEDDLL-- +>Q93Z60_ARATH +MAST----ALSSAIVSTSFLRRQQTPISLRSLPFANTQ--SLFGLKS-STARGGRVTAMATYKVKFITPEGEQEVECEED +VYVLDAAEEAGLDLPYSCRAGSCSSCAGKVVSGSIDQSDQSFLDD-------------------------------- +>FER_CAPAA +-----------------------------------------------------------ASYKVKLITPDGPIEFDCPDD +VYILDQAEEAGHDLPYSCRAGSCSSCAGKIAGGAVDQTDGNFLDDDQLEEGWVLTCVAYPQSDVTIETHKEAELVG- +>FER3_RAPSA +-----------------------------------------------------------ATYKVKFITPEGEQEVECDDD +VYVLDAAEEAGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSFLDDDQIAEGFVLTCAAYPTSDVTIETHREEDMV-- +>FER_BRANA +-----------------------------------------------------------ATYKVKFITPEGEQEVECDDD +VYVLDAAEEAGIDLPYSCRAGSCSSCAGKVVSGFVDQSDESFLDDDQIAEGFVLTCAAYPTSDVTIETHKEEELV-- diff --git a/tests/dashbio_demos/common/requirements.txt b/tests/dashbio_demos/common/requirements.txt new file mode 100644 index 000000000..7a94dcbc9 --- /dev/null +++ b/tests/dashbio_demos/common/requirements.txt @@ -0,0 +1,15 @@ +cython>=0.19 +dash>=1.6.1 +-e git://github.com/plotly/dash-bio.git#egg=dash_bio +dash-bio-utils==0.0.4 +dash-daq==0.2.2 +gunicorn==19.9.0 +jsonschema==2.6.0 +matplotlib==3.0.2 +numpy==1.15.4 +pandas>=0.24.2 +plotly>=3.5.0 +PubChemPy==1.0.4 +requests==2.21.0 +scikit-learn==0.20.2 +scipy>=1.1.0 diff --git a/tests/dashbio_demos/dash-alignment-chart/app.py b/tests/dashbio_demos/dash-alignment-chart/app.py index 944af3eb8..81e087095 100644 --- a/tests/dashbio_demos/dash-alignment-chart/app.py +++ b/tests/dashbio_demos/dash-alignment-chart/app.py @@ -7,11 +7,7 @@ from dash.dependencies import Input, Output import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app - +from layout_helper import run_standalone_app text_style = { 'color': "#506784", @@ -547,7 +543,7 @@ def layout(): ), ]), ]), - dcc.Loading(className='dashbio-loading', children=html.Div([ + dcc.Loading(parent_className='dashbio-loading', children=html.Div([ dash_bio.AlignmentChart( id='alignment-chart', height=725, @@ -698,10 +694,8 @@ def customize_showid(val): return val -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-alignment-chart/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-alignment-chart/assets/base.css b/tests/dashbio_demos/dash-alignment-chart/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-alignment-chart/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-alignment-chart/assets/general-app-page.css b/tests/dashbio_demos/dash-alignment-chart/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-alignment-chart/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-alignment-chart/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-alignment-chart/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-alignment-chart/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-alignment-chart/layout_helper.py b/tests/dashbio_demos/dash-alignment-chart/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-alignment-chart/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-circos/app.py b/tests/dashbio_demos/dash-circos/app.py index e9d9dde3f..0486e87c5 100644 --- a/tests/dashbio_demos/dash-circos/app.py +++ b/tests/dashbio_demos/dash-circos/app.py @@ -12,11 +12,7 @@ from dash_bio_utils import circos_parser as cp import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app - +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') # Main dataset used for all graphs @@ -908,7 +904,7 @@ def header_colors(): def layout(): return html.Div(id='circos-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id="circos-hold", children=[empty] )), @@ -1397,10 +1393,8 @@ def event_data_select(event_datum, _): return contents -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-circos/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-circos/assets/base.css b/tests/dashbio_demos/dash-circos/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-circos/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-circos/assets/general-app-page.css b/tests/dashbio_demos/dash-circos/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-circos/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-circos/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-circos/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-circos/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-circos/layout_helper.py b/tests/dashbio_demos/dash-circos/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-circos/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-circos/requirements.txt b/tests/dashbio_demos/dash-circos/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-circos/requirements.txt +++ b/tests/dashbio_demos/dash-circos/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-clustergram/app.py b/tests/dashbio_demos/dash-clustergram/app.py index 5e00aaa32..b1eebe620 100644 --- a/tests/dashbio_demos/dash-clustergram/app.py +++ b/tests/dashbio_demos/dash-clustergram/app.py @@ -10,11 +10,7 @@ from dash_bio_utils import gene_expression_reader import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app - +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -148,7 +144,7 @@ def layout(): return html.Div(id='clustergram-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id='clustergram-wrapper', children=dcc.Graph(id='clustergram', style={'display': 'none'}) )), @@ -892,10 +888,8 @@ def clear_preloaded_on_upload(contents, filename, current): return current -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-clustergram/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-clustergram/assets/base.css b/tests/dashbio_demos/dash-clustergram/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-clustergram/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-clustergram/assets/general-app-page.css b/tests/dashbio_demos/dash-clustergram/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-clustergram/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-clustergram/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-clustergram/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-clustergram/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-clustergram/layout_helper.py b/tests/dashbio_demos/dash-clustergram/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-clustergram/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-clustergram/requirements.txt b/tests/dashbio_demos/dash-clustergram/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-clustergram/requirements.txt +++ b/tests/dashbio_demos/dash-clustergram/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-forna-container/app.py b/tests/dashbio_demos/dash-forna-container/app.py index 0d9dae0f6..d1be5149c 100644 --- a/tests/dashbio_demos/dash-forna-container/app.py +++ b/tests/dashbio_demos/dash-forna-container/app.py @@ -1,5 +1,3 @@ -import os - from dash.dependencies import Input, Output, State from dash.exceptions import PreventUpdate import dash_html_components as html @@ -7,10 +5,7 @@ import dash_daq as daq import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app def header_colors(): @@ -574,10 +569,8 @@ def update_shown_sequences(selected_sequence_ids, stored_sequences): return sequences -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-forna-container/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-forna-container/assets/base.css b/tests/dashbio_demos/dash-forna-container/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-forna-container/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-forna-container/assets/general-app-page.css b/tests/dashbio_demos/dash-forna-container/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-forna-container/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-forna-container/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-forna-container/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-forna-container/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-forna-container/layout_helper.py b/tests/dashbio_demos/dash-forna-container/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-forna-container/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-forna-container/requirements.txt b/tests/dashbio_demos/dash-forna-container/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-forna-container/requirements.txt +++ b/tests/dashbio_demos/dash-forna-container/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-ideogram/app.py b/tests/dashbio_demos/dash-ideogram/app.py index ecb6e865b..8911309b1 100644 --- a/tests/dashbio_demos/dash-ideogram/app.py +++ b/tests/dashbio_demos/dash-ideogram/app.py @@ -1,15 +1,10 @@ -import os - import dash_core_components as dcc from dash.dependencies import Input, Output, State import dash_html_components as html import dash_daq as daq import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app def description(): @@ -462,7 +457,7 @@ def chromosome_div( def layout(): return html.Div(id='ideogram-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div(id='ideogram-container')), + dcc.Loading(parent_className='dashbio-loading', children=html.Div(id='ideogram-container')), html.Div(className='control-tabs', children=[ dcc.Tabs(id='ideogram-control-tabs', value='what-is', children=[ dcc.Tab( @@ -802,10 +797,9 @@ def annote_data(data): return data -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server + if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-ideogram/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-ideogram/assets/base.css b/tests/dashbio_demos/dash-ideogram/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-ideogram/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-ideogram/assets/general-app-page.css b/tests/dashbio_demos/dash-ideogram/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-ideogram/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-ideogram/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-ideogram/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-ideogram/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-ideogram/layout_helper.py b/tests/dashbio_demos/dash-ideogram/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-ideogram/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-ideogram/requirements.txt b/tests/dashbio_demos/dash-ideogram/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-ideogram/requirements.txt +++ b/tests/dashbio_demos/dash-ideogram/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-igv/app.py b/tests/dashbio_demos/dash-igv/app.py index 4e62f842e..3fc4db08d 100644 --- a/tests/dashbio_demos/dash-igv/app.py +++ b/tests/dashbio_demos/dash-igv/app.py @@ -1,13 +1,10 @@ -import os import dash_html_components as html import dash_core_components as dcc from dash.dependencies import Input, Output import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app + text_style = { 'color': "#506784", @@ -128,7 +125,7 @@ def layout(): ] ) ]), - dcc.Loading(className='dashbio-loading', id='igv-output'), + dcc.Loading(parent_className='dashbio-loading', id='igv-output'), ]) @@ -152,10 +149,9 @@ def return_igv(genome, bases): ) -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server + if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-igv/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-igv/assets/base.css b/tests/dashbio_demos/dash-igv/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-igv/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-igv/assets/general-app-page.css b/tests/dashbio_demos/dash-igv/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-igv/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-igv/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-igv/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-igv/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-igv/requirements.txt b/tests/dashbio_demos/dash-igv/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-igv/requirements.txt +++ b/tests/dashbio_demos/dash-igv/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-manhattan-plot/app.py b/tests/dashbio_demos/dash-manhattan-plot/app.py index 36379e7f5..7cccf4ba5 100644 --- a/tests/dashbio_demos/dash-manhattan-plot/app.py +++ b/tests/dashbio_demos/dash-manhattan-plot/app.py @@ -7,11 +7,7 @@ import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app - +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -46,7 +42,7 @@ def header_colors(): def layout(): return html.Div(id='mhp-page-content', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id='mhp-graph-div', children=dcc.Graph( figure=fig, @@ -149,10 +145,8 @@ def update_graph(slider_genome, slider_indic): ) -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-manhattan-plot/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-manhattan-plot/assets/base.css b/tests/dashbio_demos/dash-manhattan-plot/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-manhattan-plot/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-manhattan-plot/assets/general-app-page.css b/tests/dashbio_demos/dash-manhattan-plot/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-manhattan-plot/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-manhattan-plot/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-manhattan-plot/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-manhattan-plot/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-manhattan-plot/layout_helper.py b/tests/dashbio_demos/dash-manhattan-plot/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-manhattan-plot/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-manhattan-plot/requirements.txt b/tests/dashbio_demos/dash-manhattan-plot/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-manhattan-plot/requirements.txt +++ b/tests/dashbio_demos/dash-manhattan-plot/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/app.py b/tests/dashbio_demos/dash-molecule-2d-viewer/app.py index 0573e505a..e7c4c7dac 100644 --- a/tests/dashbio_demos/dash-molecule-2d-viewer/app.py +++ b/tests/dashbio_demos/dash-molecule-2d-viewer/app.py @@ -10,10 +10,7 @@ from dash_bio_utils.chem_structure_reader import read_structure import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -219,10 +216,8 @@ def reset_selected_atoms(_): return [] -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/assets/base.css b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/assets/general-app-page.css b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-2d-viewer/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/layout_helper.py b/tests/dashbio_demos/dash-molecule-2d-viewer/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-2d-viewer/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-molecule-2d-viewer/requirements.txt b/tests/dashbio_demos/dash-molecule-2d-viewer/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-molecule-2d-viewer/requirements.txt +++ b/tests/dashbio_demos/dash-molecule-2d-viewer/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/app.py b/tests/dashbio_demos/dash-molecule-3d-viewer/app.py index 41ee2c4d5..ea7119891 100644 --- a/tests/dashbio_demos/dash-molecule-3d-viewer/app.py +++ b/tests/dashbio_demos/dash-molecule-3d-viewer/app.py @@ -13,10 +13,7 @@ from dash_bio_utils import pdb_parser as parser, styles_parser as sparser import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -515,10 +512,8 @@ def selout(selected_atom_ids, model_data): return html.Div(residue_summary) -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/assets/base.css b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/assets/general-app-page.css b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-molecule-3d-viewer/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/layout_helper.py b/tests/dashbio_demos/dash-molecule-3d-viewer/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-molecule-3d-viewer/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-molecule-3d-viewer/requirements.txt b/tests/dashbio_demos/dash-molecule-3d-viewer/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-molecule-3d-viewer/requirements.txt +++ b/tests/dashbio_demos/dash-molecule-3d-viewer/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-needle-plot/app.py b/tests/dashbio_demos/dash-needle-plot/app.py index 625059da9..5c4a4e17d 100644 --- a/tests/dashbio_demos/dash-needle-plot/app.py +++ b/tests/dashbio_demos/dash-needle-plot/app.py @@ -11,10 +11,7 @@ parse_domain_upload_file, parse_mutations_uniprot_data, load_mutation_data import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -105,7 +102,7 @@ def header_colors(): def layout(): return html.Div(id='needleplot-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id='needleplot-wrapper', children=dash_bio.NeedlePlot( id='needle-plot', @@ -1074,10 +1071,8 @@ def update_domain_style( return domain_sty -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-needle-plot/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-needle-plot/assets/base.css b/tests/dashbio_demos/dash-needle-plot/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-needle-plot/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-needle-plot/assets/general-app-page.css b/tests/dashbio_demos/dash-needle-plot/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-needle-plot/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-needle-plot/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-needle-plot/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-needle-plot/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-needle-plot/layout_helper.py b/tests/dashbio_demos/dash-needle-plot/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-needle-plot/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-needle-plot/requirements.txt b/tests/dashbio_demos/dash-needle-plot/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-needle-plot/requirements.txt +++ b/tests/dashbio_demos/dash-needle-plot/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/app.py b/tests/dashbio_demos/dash-ngl-moleculeviewer/app.py index 9820be5d5..5eab0ed70 100755 --- a/tests/dashbio_demos/dash-ngl-moleculeviewer/app.py +++ b/tests/dashbio_demos/dash-ngl-moleculeviewer/app.py @@ -1,5 +1,4 @@ from base64 import b64decode -import os import glob import gzip import zlib @@ -11,10 +10,8 @@ import dash_core_components as dcc import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app + # Preset colors for the shown molecules COLORS = [ @@ -860,10 +857,8 @@ def download_image(n_clicks, antialias, trim, transparent): ) -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/base.css b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/general-app-page.css b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-ngl-moleculeviewer/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/layout_helper.py b/tests/dashbio_demos/dash-ngl-moleculeviewer/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-ngl-moleculeviewer/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-ngl-moleculeviewer/requirements.txt b/tests/dashbio_demos/dash-ngl-moleculeviewer/requirements.txt index b77709f77..67ec00b03 100644 --- a/tests/dashbio_demos/dash-ngl-moleculeviewer/requirements.txt +++ b/tests/dashbio_demos/dash-ngl-moleculeviewer/requirements.txt @@ -1,5 +1,5 @@ -dash==1.8.0 -dash-html-components==1.0.2 -dash-core-components==1.7.0 -dash-daq==0.3.2 +dash>=1.8.0 +dash-html-components>=1.0.2 +dash-core-components>=1.7.0 +dash-daq>=0.3.2 diff --git a/tests/dashbio_demos/dash-onco-print/app.py b/tests/dashbio_demos/dash-onco-print/app.py index eeddaa0de..29d7d92d8 100644 --- a/tests/dashbio_demos/dash-onco-print/app.py +++ b/tests/dashbio_demos/dash-onco-print/app.py @@ -6,10 +6,7 @@ import dash_daq as daq import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app text_style = { @@ -100,7 +97,7 @@ def header_colors(): def layout(): return html.Div(id='oncoprint-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=dash_bio.OncoPrint( + dcc.Loading(parent_className='dashbio-loading', children=dash_bio.OncoPrint( id='oncoprint-chart', height=550, data=[] @@ -393,10 +390,8 @@ def update_colorscale(data): return data[COLORSCALE_KEY] -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-onco-print/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-onco-print/assets/base.css b/tests/dashbio_demos/dash-onco-print/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-onco-print/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-onco-print/assets/general-app-page.css b/tests/dashbio_demos/dash-onco-print/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-onco-print/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-onco-print/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-onco-print/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-onco-print/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-onco-print/layout_helper.py b/tests/dashbio_demos/dash-onco-print/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-onco-print/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-onco-print/requirements.txt b/tests/dashbio_demos/dash-onco-print/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-onco-print/requirements.txt +++ b/tests/dashbio_demos/dash-onco-print/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-sequence-viewer/app.py b/tests/dashbio_demos/dash-sequence-viewer/app.py index e37d4daf1..c7b788de0 100644 --- a/tests/dashbio_demos/dash-sequence-viewer/app.py +++ b/tests/dashbio_demos/dash-sequence-viewer/app.py @@ -2,7 +2,6 @@ import base64 from Bio.SeqUtils import seq3 -from Bio.Alphabet import generic_dna, generic_rna from Bio.Seq import Seq from Bio.Data.CodonTable import TranslationError from dash.dependencies import Input, Output, State @@ -12,10 +11,7 @@ from dash_bio_utils import protein_reader as pr import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -924,7 +920,7 @@ def get_aa_comp(v, alphabet, seq): subsequence = subsequence[:-(len(subsequence) % 3)] \ if (len(subsequence) % 3) != 0 \ else subsequence - s = Seq(subsequence, generic_dna) + s = Seq(subsequence) try: aa_string = str(s.translate()) except TranslationError: @@ -934,7 +930,7 @@ def get_aa_comp(v, alphabet, seq): subsequence = subsequence[:-(len(subsequence) % 3)] \ if (len(subsequence) % 3) != 0 \ else subsequence - s = Seq(subsequence, generic_rna) + s = Seq(subsequence) try: aa_string = str(s.translate()) except TranslationError: @@ -1066,10 +1062,8 @@ def update_subpart_sel(v): return test -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-sequence-viewer/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-sequence-viewer/assets/base.css b/tests/dashbio_demos/dash-sequence-viewer/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-sequence-viewer/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-sequence-viewer/assets/general-app-page.css b/tests/dashbio_demos/dash-sequence-viewer/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-sequence-viewer/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-sequence-viewer/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-sequence-viewer/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-sequence-viewer/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-sequence-viewer/layout_helper.py b/tests/dashbio_demos/dash-sequence-viewer/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-sequence-viewer/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-sequence-viewer/requirements.txt b/tests/dashbio_demos/dash-sequence-viewer/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-sequence-viewer/requirements.txt +++ b/tests/dashbio_demos/dash-sequence-viewer/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-speck/app.py b/tests/dashbio_demos/dash-speck/app.py index c71dc5517..8bfca69cd 100644 --- a/tests/dashbio_demos/dash-speck/app.py +++ b/tests/dashbio_demos/dash-speck/app.py @@ -7,10 +7,7 @@ from dash_bio_utils.xyz_reader import read_xyz import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -128,7 +125,7 @@ def layout(): return html.Div(id='speck-body', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id='speck-container', children=[ dash_bio.Speck( @@ -421,10 +418,8 @@ def keep_atom_style(render, current): return current -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-speck/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-speck/assets/base.css b/tests/dashbio_demos/dash-speck/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-speck/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-speck/assets/general-app-page.css b/tests/dashbio_demos/dash-speck/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-speck/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-speck/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-speck/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-speck/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-speck/layout_helper.py b/tests/dashbio_demos/dash-speck/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-speck/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-speck/requirements.txt b/tests/dashbio_demos/dash-speck/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-speck/requirements.txt +++ b/tests/dashbio_demos/dash-speck/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0 diff --git a/tests/dashbio_demos/dash-volcano-plot/app.py b/tests/dashbio_demos/dash-volcano-plot/app.py index eb75eb7a2..27bfc23e7 100644 --- a/tests/dashbio_demos/dash-volcano-plot/app.py +++ b/tests/dashbio_demos/dash-volcano-plot/app.py @@ -10,10 +10,7 @@ import dash_daq as daq import dash_bio -try: - from layout_helper import run_standalone_app -except ModuleNotFoundError: - from .layout_helper import run_standalone_app +from layout_helper import run_standalone_app DATAPATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data') @@ -63,7 +60,7 @@ def header_colors(): def layout(): return html.Div(id='vp-page-content', className='app-body', children=[ - dcc.Loading(className='dashbio-loading', children=html.Div( + dcc.Loading(parent_className='dashbio-loading', children=html.Div( id='vp-graph-div', children=dcc.Graph( id='vp-graph' @@ -388,10 +385,8 @@ def update_genomic_line_val(val): return val -# only declare app/server if the file is being run directly -if 'DEMO_STANDALONE' not in os.environ: - app = run_standalone_app(layout, callbacks, header_colors, __file__) - server = app.server +app = run_standalone_app(layout, callbacks, header_colors, __file__) +server = app.server if __name__ == '__main__': app.run_server(debug=True, port=8050) diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-64px.png b/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-64px.png differ diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-Light-64px.png b/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/tests/dashbio_demos/dash-volcano-plot/assets/GitHub-Mark-Light-64px.png differ diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/base.css b/tests/dashbio_demos/dash-volcano-plot/assets/base.css new file mode 100644 index 000000000..30dc161da --- /dev/null +++ b/tests/dashbio_demos/dash-volcano-plot/assets/base.css @@ -0,0 +1,422 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + +/* Remove Undo Button +--------------------------------------------------*/ +._dash-undo-redo { + display: none; + } + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); + margin: 0!important; + } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/default.css b/tests/dashbio_demos/dash-volcano-plot/assets/default.css new file mode 100755 index 000000000..c3f8fb77d --- /dev/null +++ b/tests/dashbio_demos/dash-volcano-plot/assets/default.css @@ -0,0 +1,415 @@ +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Plotly.js +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* PLotly.js +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* plotly.js's modebar's z-index is 1001 by default + * https://github.com/plotly/plotly.js/blob/7e4d8ab164258f6bd48be56589dacd9bdd7fded2/src/css/_modebar.scss#L5 + * In case a dropdown is above the graph, the dropdown's options + * will be rendered below the modebar + * Increase the select option's z-index + */ + +/* This was actually not quite right - + dropdowns were overlapping each other (edited October 26) + +.Select { + z-index: 1002; +}*/ + + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Open Sans", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: rgb(50, 50, 50); } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + font-weight: 300; } +h1 { font-size: 4.5rem; line-height: 1.2; letter-spacing: -.1rem; margin-bottom: 2rem; } +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; margin-bottom: 1.8rem; margin-top: 1.8rem;} +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; margin-bottom: 1.5rem; margin-top: 1.5rem;} +h4 { font-size: 2.6rem; line-height: 1.35; letter-spacing: -.08rem; margin-bottom: 1.2rem; margin-top: 1.2rem;} +h5 { font-size: 2.2rem; line-height: 1.5; letter-spacing: -.05rem; margin-bottom: 0.6rem; margin-top: 0.6rem;} +h6 { font-size: 2.0rem; line-height: 1.6; letter-spacing: 0; margin-bottom: 0.75rem; margin-top: 0.75rem;} + +p { + margin-top: 0; } + + +/* Blockquotes +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +blockquote { + border-left: 4px lightgrey solid; + padding-left: 1rem; + margin-top: 2rem; + margin-bottom: 2rem; + margin-left: 0rem; +} + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; + text-decoration: underline; + cursor: pointer;} +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; + font-family: inherit; + font-size: inherit; /*https://stackoverflow.com/questions/6080413/why-doesnt-input-inherit-the-font-from-body*/} +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: 0px; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +table { + border-collapse: collapse; +} +th:not(.CalendarDay), +td:not(.CalendarDay) { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child:not(.CalendarDay), +td:first-child:not(.CalendarDay) { + padding-left: 0; } +th:last-child:not(.CalendarDay), +td:last-child:not(.CalendarDay) { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 0rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 0rem; } +pre, +dl, +figure, +table, +form { + margin-bottom: 0rem; } +p, +ul, +ol { + margin-bottom: 0.75rem; } + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} \ No newline at end of file diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/general-app-page.css b/tests/dashbio_demos/dash-volcano-plot/assets/general-app-page.css new file mode 100644 index 000000000..ef35deedd --- /dev/null +++ b/tests/dashbio_demos/dash-volcano-plot/assets/general-app-page.css @@ -0,0 +1,248 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400'); + +.dashbio-loading { + display: inline-block; +} +.dash-default-spinner { + opacity: 0.3 !important; +} + +/* Basic app page with header and content area */ +#app-page-content { + margin: 0px; + margin-top: 0px; /* hide border between header and content */ + width: 100%; + height: auto; + min-height: calc(100vh - 60px); + position: absolute; + top: 60px; +} + +#app-page-header { + width: 100%; + height: 60px !important; + position: absolute; + top: 0px; +} + +#app-page-header > a > img { + height: 70px; + float: left; + padding: 15px; + padding-bottom: 0px; + transition-duration: 500ms; +} + +#app-page-header > a > img:hover { + filter: brightness(2); +} + +#app-page-header h2 { + font-size: 22pt; + font-family: 'Times'; + font-weight: 200 !important; + letter-spacing: 1px; + position: absolute; + top: -5px; + display: inline-block; +} + +#dashbio-logo > img { + height: 30px !important; +} + +#app-page-header > img { + height: 36px; + float: right; + margin-top: 12px; + margin-right: 10px; + transition-duration: 500ms; +} +#gh-link { + text-decoration: none; + font-size: 10pt; + font-family: sans-serif; + color: white; + border: solid 1px white; + border-radius: 2px; + padding: 2px; + padding-top: 5px; + padding-left: 15px; + padding-right: 15px; + font-weight: 100; + position: relative; + top: 15px; + float: right; + margin-right: 20px; + margin-left: 0px; + transition-duration: 400ms; +} +#gh-link:hover { + color: #dfe8f3 !important; + border-color: #dfe8f3 !important; +} + +/* Scrollbar */ +#app-page-content ::-webkit-scrollbar { + width: 4px; + height: 0px; + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} + +#app-page-content ::-webkit-scrollbar-thumb { + width: 2px; + border-radius: 15px; + padding-right: 5px; + background-color: #119dff; /* Change in individual app stylesheet */ +} + +/* Body */ +#app-page-content .app-body { + padding: 5px; + min-height: calc(100vh - 70px); + overflow: auto; + background-color: #f6f6f6; /* Change in individual app stylesheet */ + color: #303030; /* Change in individual app stylesheet */ +} + +/* Fonts */ +#app-page-content .app-body { + font-family: 'Open Sans'; + font-weight: 200; +} + +#app-page-content .app-body h4.what-is { + font-weight: 400; + font-size: 20pt; + margin-bottom: 30px; + text-align: center; +} + +/* Tabs */ +#app-page-content .control-tabs { + width: 400px; + height: 550px; + margin: 50px; + margin-right: 0px; + font-size: 10pt; + float: left; + background-color: #ffffff; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab-content { + display: inline-block; + padding: 20px; +} + +#app-page-content .control-tab { + height: 415px; + overflow-y: auto; + padding-right: 20px; + margin: 20px; + margin-right: 0px; +} + +#app-page-content .control-tabs .tab { + font-weight: 200; + font-size: 9pt; + height: 50px; + padding: 15px; + background-color: #ffffff; /* Change in individual app stylesheet */ + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ +} + +#app-page-content .control-tabs .tab--selected { + font-weight: bolder; + border: none; + border-top: solid 2px; + color: #119dff; /* Change in individual app stylesheet */ +} + +/* Control names */ +.app-controls-block { + display: block; + margin-top: 20px; + margin-bottom: 40px; +} +.app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 160px; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; +} +.fullwidth-app-controls-name { + display: inline-block; + font-weight: 400; + vertical-align: top; + width: 100%; + font-size: 12pt; + margin-top: 5px; + margin-bottom: 5px; + width: 100%; +} +.app-controls-desc { + font-size: 9pt; + margin-left: 10px; + margin-right: 10px; + margin-top: 5px; +} + +/* Dash components */ +#app-page-content .Select { + width: 100% !important; +} + +#app-page-content .Select-menu-outer { + width: 100% !important; + margin: 0px; +} +#app-page-content .Select-input { + padding-top: 0px !important; +} +#app-page-content .control-slider { + display: inline-block; + width: 150px; + float: right; +} +#app-page-content .control-upload { + display: block; + border: dotted 1px #119dff; /* Change in individual app stylesheet */ + border-radius: 5px; + padding: 30px; + font-size: 9pt; + text-align: center; +} +#app-page-content .control-download { + width: 100%; + margin-top: 10px; + margin-bottom: 20px; + font-size: 7pt; + transition-duration: 500ms; +} +#app-page-content .control-download:hover { + color: #119dff; /* Change in individual app stylesheet */ + border-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-rail { + background-color: #f6f6f6; /* Change in individual app stylesheet */ +} +#app-page-content .rc-slider-track { + background-color: #119dff; /* Change in individual app stylesheet */ +} + +#app-page-content .rc-slider-handle { + border: solid 2px #119dff; /* Change in individual app stylesheet */ +} +@media (max-width: 800px) { + #app-page-content .control-tabs { + height: 650px; + } + + #app-page-content .control-tabs .tab--selected { + border: solid 1px #d3d3d3; /* Change in individual app stylesheet */ + } +} diff --git a/tests/dashbio_demos/dash-volcano-plot/assets/plotly-dash-bio-logo.png b/tests/dashbio_demos/dash-volcano-plot/assets/plotly-dash-bio-logo.png new file mode 100644 index 000000000..dc42cbaa1 Binary files /dev/null and b/tests/dashbio_demos/dash-volcano-plot/assets/plotly-dash-bio-logo.png differ diff --git a/tests/dashbio_demos/dash-volcano-plot/layout_helper.py b/tests/dashbio_demos/dash-volcano-plot/layout_helper.py new file mode 100644 index 000000000..2cbe104da --- /dev/null +++ b/tests/dashbio_demos/dash-volcano-plot/layout_helper.py @@ -0,0 +1,112 @@ +import base64 +import os + +import dash +import dash_core_components as dcc +import dash_html_components as html + + +def run_standalone_app( + layout, + callbacks, + header_colors, + filename +): + """Run demo app (tests/dashbio_demos/*/app.py) as standalone app.""" + app = dash.Dash(__name__) + app.scripts.config.serve_locally = True + # Handle callback to component with id "fullband-switch" + app.config['suppress_callback_exceptions'] = True + + # Get all information from filename + app_name = os.getenv('DASH_APP_NAME', '') + if app_name == '': + app_name = os.path.basename(os.path.dirname(filename)) + app_name = app_name.replace('dash-', '') + + app_title = "{}".format(app_name.replace('-', ' ').title()) + + # Assign layout + app.layout = app_page_layout( + page_layout=layout(), + app_title=app_title, + app_name=app_name, + standalone=True, + **header_colors() + ) + + # Register all callbacks + callbacks(app) + + # return app object + return app + + +def app_page_layout(page_layout, + app_title="Dash Bio App", + app_name="", + light_logo=True, + standalone=False, + bg_color="#506784", + font_color="#F3F6FA"): + return html.Div( + id='main_page', + children=[ + dcc.Location(id='url', refresh=False), + html.Div( + id='app-page-header', + children=[ + html.A( + id='dashbio-logo', children=[ + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/plotly-dash-bio-logo.png', 'rb' + ).read() + ).decode() + ) + )], + href="/Portal" if standalone else "/dash-bio" + ), + html.H2( + app_title + ), + + html.A( + id='gh-link', + children=[ + 'View on GitHub' + ], + href="http://github.com/plotly/dash-bio/" + "blob/master/tests/dashbio_demos/dash-{}/app.py".format( + app_name + ), + style={'color': 'white' if light_logo else 'black', + 'border': 'solid 1px white' if light_logo else 'solid 1px black'} + ), + + html.Img( + src='data:image/png;base64,{}'.format( + base64.b64encode( + open( + './assets/GitHub-Mark-{}64px.png'.format( + 'Light-' if light_logo else '' + ), + 'rb' + ).read() + ).decode() + ) + ) + ], + style={ + 'background': bg_color, + 'color': font_color, + } + ), + html.Div( + id='app-page-content', + children=page_layout + ) + ], + ) diff --git a/tests/dashbio_demos/dash-volcano-plot/requirements.txt b/tests/dashbio_demos/dash-volcano-plot/requirements.txt index 7a94dcbc9..11e8f0103 100644 --- a/tests/dashbio_demos/dash-volcano-plot/requirements.txt +++ b/tests/dashbio_demos/dash-volcano-plot/requirements.txt @@ -1,7 +1,7 @@ cython>=0.19 dash>=1.6.1 -e git://github.com/plotly/dash-bio.git#egg=dash_bio -dash-bio-utils==0.0.4 +dash-bio-utils==0.0.6 dash-daq==0.2.2 gunicorn==19.9.0 jsonschema==2.6.0