mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'dev' into iml_dataset_branch
This commit is contained in:
+20
-4
@@ -1,16 +1,32 @@
|
||||
#!/bin/sh
|
||||
case "$1" in
|
||||
galaxy|"")
|
||||
SCRIPT=./run.sh
|
||||
PORT=8080
|
||||
LOGFILE=galaxy.log
|
||||
;;
|
||||
reports)
|
||||
SCRIPT=./run_reports.sh
|
||||
PORT=9001
|
||||
LOGFILE=reports_webapp.log
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unrecognized app"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
TRIES=120
|
||||
URL=http://localhost:8080
|
||||
URL=http://localhost:$PORT
|
||||
EXIT_CODE=1
|
||||
i=0
|
||||
echo "Testing for correct startup:"
|
||||
bash run.sh --daemon && \
|
||||
$SCRIPT --daemon && \
|
||||
while [ "$i" -le $TRIES ]; do
|
||||
curl --max-time 1 "$URL" && EXIT_CODE=0 && break
|
||||
sleep 1
|
||||
i=$((i + 1))
|
||||
done
|
||||
bash run.sh --skip-wheels --stop-daemon
|
||||
$SCRIPT --skip-wheels --stop-daemon
|
||||
echo "exit code:$EXIT_CODE, showing startup log:"
|
||||
cat galaxy.log
|
||||
cat "$LOGFILE"
|
||||
exit $EXIT_CODE
|
||||
|
||||
@@ -15,5 +15,6 @@ lib/galaxy/util/jstree.py
|
||||
lib/galaxy/web/proxy/js/node_modules
|
||||
static/maps
|
||||
static/scripts
|
||||
test/functional/tools/cwl_tools/v1.?/
|
||||
build
|
||||
dist
|
||||
|
||||
+4
-13
@@ -27,7 +27,7 @@ variables:
|
||||
jobs:
|
||||
get_code:
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
- image: circleci/python:3.7
|
||||
<<: *set_workdir
|
||||
steps:
|
||||
# Replace standard code checkout with shallow clone to speed things up.
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
- ~/repo
|
||||
validate_test_tools:
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
- image: circleci/python:3.7
|
||||
<<: *set_workdir
|
||||
steps:
|
||||
- *restore_repo_cache
|
||||
@@ -93,18 +93,9 @@ jobs:
|
||||
- run: sudo apt-get install -y libxml2-utils
|
||||
- *install_tox
|
||||
- run: tox -e validate_test_tools
|
||||
test_galaxy_release:
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
<<: *set_workdir
|
||||
steps:
|
||||
- *restore_repo_cache
|
||||
- *install_tox
|
||||
- *install_deb_reqs
|
||||
- run: tox -e test_galaxy_release
|
||||
test_galaxy_packages:
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
- image: circleci/python:3.7
|
||||
<<: *set_workdir
|
||||
steps:
|
||||
- *restore_repo_cache
|
||||
@@ -113,7 +104,7 @@ jobs:
|
||||
- run: tox -e test_galaxy_packages
|
||||
js_lint:
|
||||
docker:
|
||||
- image: circleci/node:14-browsers
|
||||
- image: cimg/node:14.15
|
||||
<<: *set_workdir
|
||||
steps:
|
||||
- *restore_yarn_cache
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
.k8s_ci.Dockerfile
|
||||
.venv
|
||||
database
|
||||
node_modules
|
||||
|
||||
@@ -3,7 +3,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'release*'
|
||||
- anvil
|
||||
- dev
|
||||
concurrency:
|
||||
group: docker-build-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -16,24 +16,35 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
# https://stackoverflow.com/questions/59810838/how-to-get-the-short-sha-for-the-github-workflow
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
id: commit
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
- name: Set branch name
|
||||
id: branch
|
||||
run: echo "::set-output name=name::$(BRANCH_NAME=${GITHUB_REF##*/}; echo ${BRANCH_NAME/release_/}-auto)"
|
||||
- run: docker build . -t galaxy/galaxy-min:${{ steps.vars.outputs.sha_short }} -f .k8s_ci.Dockerfile
|
||||
- run: docker tag galaxy/galaxy-min:${{ steps.vars.outputs.sha_short }} quay.io/galaxy-k8s/galaxy:${{ steps.branch.outputs.name }} && docker tag galaxy/galaxy-min:${{ steps.vars.outputs.sha_short }} quay.io/galaxy-k8s/galaxy:${{ steps.vars.outputs.sha_short }}
|
||||
run: echo "::set-output name=name::$(BRANCH_NAME=${GITHUB_REF##*/}; echo ${BRANCH_NAME/release_/})"
|
||||
- name: Build container image
|
||||
run: docker build . --build-arg GIT_COMMIT=$(git rev-parse HEAD) --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg IMAGE_TAG=${{ steps.branch.outputs.name }} -t galaxyproject/galaxy-min:${{ steps.branch.outputs.name }} -t quay.io/galaxyproject/galaxy-min:${{ steps.branch.outputs.name }} -f .k8s_ci.Dockerfile
|
||||
- name: Create auto-expiring one for per-commit auto repository
|
||||
run: echo "FROM galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}" | docker build --label "quay.expires-after"="90d" -t "quay.io/galaxyproject/galaxy-k8s-auto:${{ steps.commit.outputs.sha_short }}" -
|
||||
- name: Login to quay.io
|
||||
uses: actions-hub/docker/login@master
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.QUAY_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.QUAY_PASSWORD }}
|
||||
DOCKER_REGISTRY_URL: quay.io
|
||||
- name: Push to quay.io with commit ID
|
||||
uses: actions-hub/docker@master
|
||||
with:
|
||||
args: push quay.io/galaxy-k8s/galaxy:${{ steps.vars.outputs.sha_short }}
|
||||
- name: Push to quay.io with branch name
|
||||
uses: actions-hub/docker@master
|
||||
with:
|
||||
args: push quay.io/galaxy-k8s/galaxy:${{ steps.branch.outputs.name }}
|
||||
args: push quay.io/galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}
|
||||
- name: Push to quay.io with commit hash
|
||||
uses: actions-hub/docker@master
|
||||
with:
|
||||
args: push quay.io/galaxyproject/galaxy-k8s-auto:${{ steps.commit.outputs.sha_short }}
|
||||
- name: Login to DockerHub
|
||||
uses: actions-hub/docker/login@master
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
- name: Push to DockerHub with branch name
|
||||
uses: actions-hub/docker@master
|
||||
with:
|
||||
args: push galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ dev ]
|
||||
schedule:
|
||||
- cron: '16 6 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript', 'python']
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -0,0 +1,65 @@
|
||||
name: CWL conformance
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'client/**'
|
||||
- 'doc/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'client/**'
|
||||
- 'doc/**'
|
||||
env:
|
||||
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
|
||||
concurrency:
|
||||
group: cwl-conformance-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
if: ${{ false }}
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ startsWith(matrix.marker, 'red') }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.7']
|
||||
marker: ['green', 'red and required', 'red and not required']
|
||||
conformance-version: ['cwl_conformance_v1_0'] #, 'cwl_conformance_v1_1', 'cwl_conformance_v1_2']
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'galaxy root'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Get full Python version
|
||||
id: full-python-version
|
||||
shell: bash
|
||||
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
|
||||
- name: Cache pip dir
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
|
||||
- name: Cache galaxy venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .venv
|
||||
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}
|
||||
- name: Run tests
|
||||
run: ./run_tests.sh --skip_flakey_fails -cwl lib/galaxy_test/api/cwl -- -m "${{ matrix.marker }} and ${{ matrix.conformance-version }}"
|
||||
working-directory: 'galaxy root'
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: CWL conformance test results (${{ matrix.python-version }}, ${{ matrix.marker }}, ${{ matrix.conformance-version }})
|
||||
path: 'galaxy root/run_cwl_tests.html'
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.6']
|
||||
python-version: ['3.7']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
@@ -27,6 +27,7 @@ jobs:
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
author: galaxybot <galaxybot@users.noreply.github.com>
|
||||
token: ${{ secrets.GALAXYBOT_PAT }}
|
||||
commit-message: Update Python dependencies
|
||||
branch: dev_auto_update_dependencies
|
||||
|
||||
@@ -19,10 +19,10 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.6', '3.9']
|
||||
python-version: ['3.7', '3.10']
|
||||
webserver: ['uwsgi']
|
||||
include:
|
||||
- python-version: '3.9'
|
||||
- python-version: '3.10'
|
||||
webserver: 'dev'
|
||||
defaults:
|
||||
run:
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.6', '3.9']
|
||||
python-version: ['3.7', '3.10']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
|
||||
@@ -29,8 +29,8 @@ jobs:
|
||||
id: pip-cache
|
||||
with:
|
||||
path: ~/Library/Caches/pip
|
||||
# scripts/common_startup.sh creates a conda env for Galaxy containing Python 3.6
|
||||
key: pip-cache-3.6-${{ hashFiles('galaxy root/requirements.txt') }}
|
||||
# scripts/common_startup.sh creates a conda env for Galaxy containing Python 3.7
|
||||
key: pip-cache-3.7-${{ hashFiles('galaxy root/requirements.txt') }}
|
||||
- name: Cache tox env
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
name: Reports startup
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
env:
|
||||
YARN_INSTALL_OPTS: --frozen-lockfile
|
||||
concurrency:
|
||||
group: reports-startup-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
|
||||
test:
|
||||
name: Reports startup test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.7', '3.10']
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'galaxy root'
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Get full Python version
|
||||
id: full-python-version
|
||||
shell: bash
|
||||
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
|
||||
- name: Cache pip dir
|
||||
uses: actions/cache@v1
|
||||
id: pip-cache
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
|
||||
- name: Cache tox env
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .tox
|
||||
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-reports-startup
|
||||
- uses: mvdbeek/gha-yarn-cache@master
|
||||
with:
|
||||
yarn-lock-file: 'galaxy root/client/yarn.lock'
|
||||
- name: Install tox
|
||||
run: pip install tox
|
||||
- name: run tests
|
||||
run: tox -e reports_startup
|
||||
working-directory: 'galaxy root'
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
env:
|
||||
GALAXY_CONFIG_GALAXY_URL_PREFIX: '/galaxypf'
|
||||
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
|
||||
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
|
||||
GALAXY_TEST_SELENIUM_RETRIES: 1
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
env:
|
||||
GALAXY_CONFIG_GALAXY_URL_PREFIX: '/galaxypf'
|
||||
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
|
||||
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
|
||||
GALAXY_TEST_SELENIUM_RETRIES: 1
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Test Galaxy release script
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- lib/galaxy/version.py
|
||||
- scripts/release.sh
|
||||
- test/release.sh
|
||||
pull_request:
|
||||
paths:
|
||||
- lib/galaxy/version.py
|
||||
- scripts/release.sh
|
||||
- test/release.sh
|
||||
concurrency:
|
||||
group: test-galaxy-release-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run tests
|
||||
run: ./test/release.sh
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.6', '3.9']
|
||||
python-version: ['3.7', '3.10']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -47,3 +47,8 @@ jobs:
|
||||
- name: Run tests
|
||||
run: tox -e unit
|
||||
working-directory: 'galaxy root'
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: Unit test results (${{ matrix.python-version }})
|
||||
path: 'galaxy root/run_unit_tests.html'
|
||||
|
||||
+11
-1
@@ -125,12 +125,13 @@ tool-data/**/*.fa
|
||||
.pytest_cache/
|
||||
assets/
|
||||
test-data-cache
|
||||
run_api_tests.html
|
||||
run_cwl_tests.html
|
||||
run_framework_tests.html
|
||||
run_functional_tests.html
|
||||
run_integration_tests.html
|
||||
run_selenium_tests.html
|
||||
run_toolshed_tests.html
|
||||
run_api_tests.html
|
||||
test/tool_shed/tmp/*
|
||||
.coverage
|
||||
htmlcov
|
||||
@@ -187,3 +188,12 @@ config/plugins/**/static/dist
|
||||
config/plugins/**/static/script.js
|
||||
config/plugins/**/static/main.css
|
||||
config/plugins/**/static/plugin_build_hash.txt
|
||||
config/plugins/**/static/*.map
|
||||
|
||||
# viz-specific build artifacts to ignore (until these are removed from codebase)
|
||||
config/plugins/visualizations/annotate_image/static/jquery.contextMenu.css
|
||||
config/plugins/visualizations/nvd3/nvd3_bar/static/nvd3.js
|
||||
|
||||
# CWL conformance tests
|
||||
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_?.py
|
||||
test/functional/tools/cwl_tools/v1.?/
|
||||
|
||||
@@ -23,6 +23,10 @@ ARG FINAL_STAGE_BASE=$STAGE1_BASE
|
||||
ARG GALAXY_USER=galaxy
|
||||
ARG GALAXY_PLAYBOOK_REPO=https://github.com/galaxyproject/galaxy-docker-k8s
|
||||
|
||||
ARG GIT_COMMIT=unspecified
|
||||
ARG BUILD_DATE=unspecified
|
||||
ARG IMAGE_TAG=unspecified
|
||||
|
||||
#======================================================
|
||||
# Stage 1 - Setup common requirements for build
|
||||
#======================================================
|
||||
@@ -114,6 +118,22 @@ ARG ROOT_DIR
|
||||
ARG SERVER_DIR
|
||||
ARG GALAXY_USER
|
||||
|
||||
ARG GIT_COMMIT
|
||||
ARG BUILD_DATE
|
||||
ARG IMAGE_TAG
|
||||
|
||||
LABEL org.opencontainers.image.title="Galaxy Minimal Image" \
|
||||
org.opencontainers.image.description="A size optimized image for Galaxy targeting k8s and ci applications" \
|
||||
org.opencontainers.image.authors="galaxyproject.org" \
|
||||
org.opencontainers.image.vendor="Galaxy Project" \
|
||||
org.opencontainers.image.documentation="https://github.com/galaxyproject/galaxy-docker-k8s" \
|
||||
org.opencontainers.image.licenses="MIT" \
|
||||
org.opencontainers.image.version="$IMAGE_TAG" \
|
||||
org.opencontainers.image.url="https://github.com/galaxyproject/galaxy-docker-k8s" \
|
||||
org.opencontainers.image.source="https://github.com/galaxyproject/galaxy.git" \
|
||||
org.opencontainers.image.revision=$GIT_COMMIT \
|
||||
org.opencontainers.image.created=$BUILD_DATE
|
||||
|
||||
# Init Env
|
||||
ENV LC_ALL=en_US.UTF-8
|
||||
ENV LANG=en_US.UTF-8
|
||||
|
||||
@@ -4,6 +4,7 @@ VENV?=.venv
|
||||
IN_VENV=if [ -f "$(VENV)/bin/activate" ]; then . "$(VENV)/bin/activate"; fi;
|
||||
RELEASE_CURR:=22.01
|
||||
RELEASE_UPSTREAM:=upstream
|
||||
TARGET_BRANCH=$(RELEASE_UPSTREAM)/dev
|
||||
CONFIG_MANAGE=$(IN_VENV) python lib/galaxy/config/config_manage.py
|
||||
PROJECT_URL?=https://github.com/galaxyproject/galaxy
|
||||
DOCS_DIR=doc
|
||||
@@ -13,6 +14,12 @@ OPEN_RESOURCE=bash -c 'open $$0 || xdg-open $$0'
|
||||
SLIDESHOW_TO_PDF?=bash -c 'docker run --rm -v `pwd`:/cwd astefanutti/decktape /cwd/$$0 /cwd/`dirname $$0`/`basename -s .html $$0`.pdf'
|
||||
YARN := $(shell command -v yarn 2> /dev/null)
|
||||
YARN_INSTALL_OPTS=--network-timeout 300000 --check-files
|
||||
CWL_TARGETS := test/functional/tools/cwl_tools/v1.0/conformance_tests.yaml \
|
||||
test/functional/tools/cwl_tools/v1.1/conformance_tests.yaml \
|
||||
test/functional/tools/cwl_tools/v1.2/conformance_tests.yaml \
|
||||
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_0.py \
|
||||
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_1.py \
|
||||
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_2.py
|
||||
|
||||
all: help
|
||||
@echo "This makefile is used for building Galaxy's JS client, documentation, and drive the release process. A sensible all target is not implemented."
|
||||
@@ -31,6 +38,9 @@ docs-develop: ## Fast doc generation and more warnings (for development)
|
||||
setup-venv:
|
||||
if [ ! -f $(VENV)/bin/activate ]; then bash scripts/common_startup.sh --dev-wheels; fi
|
||||
|
||||
diff-format:
|
||||
$(IN_VENV) darker -r $(TARGET_BRANCH)
|
||||
|
||||
list-dependency-updates: setup-venv
|
||||
$(IN_VENV) pip list --outdated --format=columns
|
||||
|
||||
@@ -130,6 +140,24 @@ update-lint-requirements:
|
||||
update-dependencies: update-lint-requirements ## update pinned and dev dependencies
|
||||
$(IN_VENV) ./lib/galaxy/dependencies/update.sh
|
||||
|
||||
$(CWL_TARGETS):
|
||||
./scripts/update_cwl_conformance_tests.sh
|
||||
|
||||
generate-cwl-conformance-tests: $(CWL_TARGETS) ## Initialise CWL conformance tests
|
||||
|
||||
clean-cwl-conformance-tests: ## Clean CWL conformance tests
|
||||
for f in $(CWL_TARGETS); do \
|
||||
if [ $$(basename "$$f") = conformance_tests.yaml ]; then \
|
||||
rm -rf $$(dirname "$$f"); \
|
||||
else \
|
||||
rm -f "$$f"; \
|
||||
fi \
|
||||
done
|
||||
|
||||
update-cwl-conformance-tests: ## update CWL conformance tests
|
||||
$(MAKE) clean-cwl-conformance-tests
|
||||
$(MAKE) generate-cwl-conformance-tests
|
||||
|
||||
node-deps: ## Install NodeJS dependencies.
|
||||
ifndef YARN
|
||||
@echo "Could not find yarn, which is required to build the Galaxy client.\nTo install yarn, please visit \033[0;34mhttps://yarnpkg.com/en/docs/install\033[0m for instructions, and package information for all platforms.\n"
|
||||
|
||||
@@ -13,16 +13,22 @@ const glob = require("glob");
|
||||
const STATIC_PLUGIN_BUILD_IDS = [
|
||||
"annotate_image",
|
||||
"chiraviz",
|
||||
"cytoscape",
|
||||
"drawrna",
|
||||
"editor",
|
||||
"example",
|
||||
"heatmap/heatmap_default",
|
||||
"hyphyvision",
|
||||
"jqplot/jqplot_bar",
|
||||
"media_player",
|
||||
"mvpapp",
|
||||
"ngl",
|
||||
"nvd3/nvd3_bar",
|
||||
"openlayers",
|
||||
"openseadragon",
|
||||
"pv",
|
||||
"nora",
|
||||
"venn",
|
||||
];
|
||||
|
||||
const DIST_PLUGIN_BUILD_IDS = ["new_user"];
|
||||
|
||||
+4
-1
@@ -27,6 +27,7 @@
|
||||
"@johmun/vue-tags-input": "^2.1.0",
|
||||
"@sentry/browser": "^5.20.1",
|
||||
"axios": "^0.21.1",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"backbone": "1.4.0",
|
||||
"bootstrap": "4.5.0",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
@@ -89,6 +90,7 @@
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue-multiselect": "^2.1.0",
|
||||
"vue-observe-visibility": "^1.0.0",
|
||||
"vue-prismjs": "^1.2.0",
|
||||
"vue-router": "^3.5.2",
|
||||
"vue-rx": "^6.2.0",
|
||||
"vue-scrollto": "^2.20.0",
|
||||
@@ -97,7 +99,8 @@
|
||||
"vuex": "^3.4.0",
|
||||
"vuex-cache": "^3.2.0",
|
||||
"vuex-persist": "^3.1.3",
|
||||
"vuex-persistedstate": "^4.1.0"
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"xml-beautifier": "^0.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"watch": "gulp && yarn run save-build-hash && yarn run webpack-watch",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
tabWidth: 4,
|
||||
printWidth: 120
|
||||
printWidth: 120,
|
||||
bracketSameLine: true
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ export { TracksterUI } from "viz/trackster";
|
||||
import Circster from "viz/circster";
|
||||
export { PhylovizView as phyloviz } from "viz/phyloviz";
|
||||
export { SweepsterVisualization, SweepsterVisualizationView } from "viz/sweepster";
|
||||
import GalaxyLibrary from "galaxy.library";
|
||||
export { createTabularDatasetChunkedView } from "mvc/dataset/data";
|
||||
import { HistoryCollection } from "mvc/history/history-model";
|
||||
export { History } from "mvc/history/history-model";
|
||||
@@ -44,10 +43,6 @@ export function circster(options) {
|
||||
new Circster.GalaxyApp(options);
|
||||
}
|
||||
|
||||
export function library(options) {
|
||||
new GalaxyLibrary.GalaxyApp(options);
|
||||
}
|
||||
|
||||
export function multiHistory(options) {
|
||||
const histories = new HistoryCollection([], {
|
||||
includeDeleted: options.includingDeleted,
|
||||
@@ -76,20 +71,10 @@ export { default as async_save_text } from "utils/async-save-text";
|
||||
|
||||
// Previously "chart"
|
||||
import Client from "mvc/visualization/chart/chart-client";
|
||||
import Datasets from "mvc/visualization/chart/utilities/datasets";
|
||||
import Series from "mvc/visualization/chart/utilities/series";
|
||||
import Jobs from "mvc/visualization/chart/utilities/jobs";
|
||||
|
||||
export function chart(options) {
|
||||
return new Client(options);
|
||||
}
|
||||
|
||||
export const chartUtilities = {
|
||||
Datasets: Datasets,
|
||||
Jobs: Jobs,
|
||||
Series: Series,
|
||||
};
|
||||
|
||||
export { initMasthead } from "components/Masthead/initMasthead";
|
||||
export { panelManagement } from "onload/globalInits/panelManagement";
|
||||
export { mountMakoTags } from "components/Tags";
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
v-b-tooltip.hover="{ boundary: 'viewport', placement: tooltipPlacement }"
|
||||
:title="'Edit annotation...' | localize"
|
||||
:placeholder="'Edit annotation...' | localize"
|
||||
v-slot="{ toggleEdit, placeholder, stateValidator }"
|
||||
>
|
||||
v-slot="{ toggleEdit, placeholder, stateValidator }">
|
||||
<debounced-input v-model="annotation" :delay="1000" v-slot="inputScope">
|
||||
<b-form-textarea
|
||||
size="sm"
|
||||
@@ -19,8 +18,7 @@
|
||||
@input="inputScope.input"
|
||||
@blur="toggleEdit(false)"
|
||||
:placeholder="placeholder"
|
||||
:state="stateValidator(inputScope.value, annotation)"
|
||||
></b-form-textarea>
|
||||
:state="stateValidator(inputScope.value, annotation)"></b-form-textarea>
|
||||
</debounced-input>
|
||||
</click-to-edit>
|
||||
</template>
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
:citation="citation"
|
||||
:output-format="outputFormat"
|
||||
v-for="(citation, index) in citations"
|
||||
:key="index"
|
||||
/>
|
||||
:key="index" />
|
||||
</div>
|
||||
</b-card>
|
||||
<div v-else-if="citations.length">
|
||||
@@ -38,16 +37,14 @@
|
||||
@show="$emit('show')"
|
||||
@shown="$emit('shown')"
|
||||
@hide="$emit('hide')"
|
||||
@hidden="$emit('hidden')"
|
||||
>
|
||||
@hidden="$emit('hidden')">
|
||||
<b-card>
|
||||
<Citation
|
||||
class="formatted-reference"
|
||||
:citation="citation"
|
||||
:output-format="outputFormat"
|
||||
v-for="(citation, index) in citations"
|
||||
:key="index"
|
||||
/>
|
||||
:key="index" />
|
||||
</b-card>
|
||||
</b-collapse>
|
||||
</div>
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
:toggleEdit="toggleEdit"
|
||||
:editing="editing"
|
||||
:placeholder="placeholder"
|
||||
:stateValidator="stateValidator"
|
||||
>
|
||||
:stateValidator="stateValidator">
|
||||
<debounced-input v-model="localValue" :delay="debounceDelay">
|
||||
<template v-slot="{ value: debouncedValue, input }">
|
||||
<b-form-input
|
||||
@@ -22,8 +21,7 @@
|
||||
@blur="toggleEdit(false)"
|
||||
:autofocus="true"
|
||||
:placeholder="placeholder"
|
||||
:state="stateValidator(debouncedValue, localValue)"
|
||||
/>
|
||||
:state="stateValidator(debouncedValue, localValue)" />
|
||||
</template>
|
||||
</debounced-input>
|
||||
</slot>
|
||||
|
||||
@@ -65,8 +65,7 @@
|
||||
:oncancel="oncancel"
|
||||
:hide-source-items="hideSourceItems"
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate"
|
||||
>
|
||||
@clicked-create="clickedCreate">
|
||||
<template v-slot:help-content>
|
||||
<p>
|
||||
{{
|
||||
@@ -114,11 +113,18 @@
|
||||
{{ l("link.") }}
|
||||
</li>
|
||||
<li>
|
||||
{{ l("Click the") }}
|
||||
{{ l("Click ") }}
|
||||
<i data-target=".reset">
|
||||
{{ l("Start over") }}
|
||||
<font-awesome-icon icon="undo" />
|
||||
</i>
|
||||
{{ l("link to begin again as if you had just opened the interface.") }}
|
||||
{{ l("to begin again as if you had just opened the interface.") }}
|
||||
</li>
|
||||
<li>
|
||||
{{ l("Click ") }}
|
||||
<i data-target=".sort-items">
|
||||
<font-awesome-icon icon="sort-alpha-down" />
|
||||
</i>
|
||||
{{ l("to sort datasets alphabetically.") }}
|
||||
</li>
|
||||
<li>
|
||||
{{ l("Click the") }}
|
||||
@@ -143,23 +149,19 @@
|
||||
</template>
|
||||
<template v-slot:middle-content>
|
||||
<div class="collection-elements-controls">
|
||||
<a
|
||||
class="reset"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
:title="titleUndoButton"
|
||||
@click="reset"
|
||||
>
|
||||
{{ l("Start over") }}
|
||||
</a>
|
||||
<b-button class="reset" :title="titleUndoButton" @click="reset">
|
||||
<font-awesome-icon icon="undo" />
|
||||
</b-button>
|
||||
<b-button class="sort-items" :title="titleSortButton" @click="sortByName">
|
||||
<font-awesome-icon icon="sort-alpha-down" />
|
||||
</b-button>
|
||||
<a
|
||||
class="clear-selected"
|
||||
v-if="atLeastOneDatasetIsSelected"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
:title="titleDeselectButton"
|
||||
@click="clickClearAll"
|
||||
>
|
||||
@click="clickClearAll">
|
||||
{{ l("Clear selected") }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -167,8 +169,7 @@
|
||||
v-model="workingElements"
|
||||
class="collection-elements scroll-container flex-row drop-zone"
|
||||
@start="drag = true"
|
||||
@end="drag = false"
|
||||
>
|
||||
@end="drag = false">
|
||||
<div v-if="noMoreValidDatasets">
|
||||
<b-alert show variant="warning" dismissible>
|
||||
{{ discardedElementsHeader }}
|
||||
@@ -186,8 +187,7 @@
|
||||
@element-is-discarded="elementDiscarded"
|
||||
@onRename="(name) => (element.name = name)"
|
||||
:class="{ selected: getSelectedDatasetElems.includes(element.id) }"
|
||||
:element="element"
|
||||
/>
|
||||
:element="element" />
|
||||
</draggable>
|
||||
</template>
|
||||
</collection-creator>
|
||||
@@ -205,6 +205,11 @@ import "ui/hoverhighlight";
|
||||
import Vue from "vue";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
import draggable from "vuedraggable";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faSortAlphaDown, faUndo } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
library.add(faSortAlphaDown, faUndo);
|
||||
|
||||
Vue.use(BootstrapVue);
|
||||
export default {
|
||||
@@ -214,11 +219,12 @@ export default {
|
||||
this._elementsSetUp();
|
||||
this.saveOriginalNames();
|
||||
},
|
||||
components: { DatasetCollectionElementView, draggable },
|
||||
components: { DatasetCollectionElementView, draggable, FontAwesomeIcon },
|
||||
data: function () {
|
||||
return {
|
||||
state: "build", //error
|
||||
titleUndoButton: _l("Undo all reordering and discards"),
|
||||
titleSortButton: _l("Sort datasets by name"),
|
||||
titleDeselectButton: _l("De-select all selected datasets"),
|
||||
noElementsHeader: _l("No datasets were selected"),
|
||||
discardedElementsHeader: _l("No elements left. Would you like to"),
|
||||
@@ -407,6 +413,18 @@ export default {
|
||||
this._instanceSetUp();
|
||||
this.getOriginalNames();
|
||||
},
|
||||
sortByName: function () {
|
||||
this.workingElements.sort(this.compareNames);
|
||||
},
|
||||
compareNames: function (a, b) {
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
/** string rep */
|
||||
toString: function () {
|
||||
return "ListCollectionCreator";
|
||||
|
||||
@@ -82,8 +82,7 @@
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle"
|
||||
:suggested-name="initialSuggestedName"
|
||||
>
|
||||
:suggested-name="initialSuggestedName">
|
||||
<template v-slot:help-content>
|
||||
<p>
|
||||
{{
|
||||
@@ -130,8 +129,7 @@
|
||||
class="swap"
|
||||
href="javascript:void(0);"
|
||||
title="l('Swap forward and reverse datasets')"
|
||||
@click="swapButton"
|
||||
>
|
||||
@click="swapButton">
|
||||
{{ l("Swap") }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -139,8 +137,7 @@
|
||||
<div
|
||||
v-for="(element, index) in workingElements"
|
||||
:key="element.id"
|
||||
class="collection-element"
|
||||
>
|
||||
class="collection-element">
|
||||
{{ index == 0 ? l("forward") : l("reverse") }}: {{ element.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -104,8 +104,7 @@
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle"
|
||||
:render-extensions-toggle="true"
|
||||
>
|
||||
:render-extensions-toggle="true">
|
||||
<template v-slot:help-content>
|
||||
<p>
|
||||
{{
|
||||
@@ -186,8 +185,7 @@
|
||||
{{ l("Entering regular expressions to match dataset names. See:") }}
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions"
|
||||
target="_blank"
|
||||
>
|
||||
target="_blank">
|
||||
{{ l("MDN's JavaScript Regular Expression Tutorial") }}</a
|
||||
>
|
||||
{{ l("Note: forward slashes (\\) are not needed.") }}
|
||||
@@ -256,22 +254,19 @@
|
||||
float-left
|
||||
search-input search-query
|
||||
input-group
|
||||
"
|
||||
>
|
||||
">
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="filterTextPlaceholder"
|
||||
v-model="forwardFilter"
|
||||
title="filterTextTitle"
|
||||
/>
|
||||
title="filterTextTitle" />
|
||||
<div class="input-group-append" :title="chooseFilterTitle">
|
||||
<button
|
||||
class="btn btn-outline-secondary dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
></button>
|
||||
aria-expanded="false"></button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" @click="changeFilters('illumina')">_1</a>
|
||||
<a class="dropdown-item" @click="changeFilters('Rs')">_R1</a>
|
||||
@@ -287,8 +282,7 @@
|
||||
class="clear-filters-link"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
@click="clickClearFilters"
|
||||
>
|
||||
@click="clickClearFilters">
|
||||
{{ l("Clear Filters") }}
|
||||
</a>
|
||||
<br />
|
||||
@@ -296,8 +290,7 @@
|
||||
class="autopair-link"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
@click="clickAutopair"
|
||||
>
|
||||
@click="clickAutopair">
|
||||
{{ l("Auto-pair") }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -320,22 +313,19 @@
|
||||
float-left
|
||||
search-input search-query
|
||||
input-group
|
||||
"
|
||||
>
|
||||
">
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="filterTextPlaceholder"
|
||||
v-model="reverseFilter"
|
||||
title="filterTextTitle"
|
||||
/>
|
||||
title="filterTextTitle" />
|
||||
<div class="input-group-append" :title="chooseFilterTitle">
|
||||
<button
|
||||
class="btn btn-outline-secondary dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
></button>
|
||||
aria-expanded="false"></button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" @click="changeFilters('illumina')">_2</a>
|
||||
<a class="dropdown-item" @click="changeFilters('Rs')">_R2</a>
|
||||
@@ -365,8 +355,7 @@
|
||||
selectedForwardElement &&
|
||||
element.id == selectedForwardElement.id,
|
||||
}"
|
||||
:element="element"
|
||||
/>
|
||||
:element="element" />
|
||||
</ol>
|
||||
</div>
|
||||
<div class="paired-column flex-column no-flex column truncate">
|
||||
@@ -375,8 +364,7 @@
|
||||
v-for="(pairableElement, index) in pairableElements"
|
||||
:key="index"
|
||||
@click="_pair(pairableElement.forward, pairableElement.reverse)"
|
||||
class="dataset"
|
||||
>
|
||||
class="dataset">
|
||||
{{ l("Pair these datasets") }}
|
||||
</li>
|
||||
</ol>
|
||||
@@ -392,8 +380,7 @@
|
||||
selectedReverseElement &&
|
||||
element.id == selectedReverseElement.id,
|
||||
}"
|
||||
:element="element"
|
||||
/>
|
||||
:element="element" />
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
@@ -407,8 +394,7 @@
|
||||
class="unpair-all-link"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
@click="unpairAll"
|
||||
>
|
||||
@click="unpairAll">
|
||||
{{ l("Unpair all") }}
|
||||
</a>
|
||||
</div>
|
||||
@@ -420,8 +406,7 @@
|
||||
:key="pair.id"
|
||||
:pair="pair"
|
||||
:unlink-fn="clickUnpair(pair)"
|
||||
@onPairRename="(name) => (pair.name = name)"
|
||||
/>
|
||||
@onPairRename="(name) => (pair.name = name)" />
|
||||
</draggable>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
contenteditable
|
||||
v-model="localValue"
|
||||
@blur="editable = false"
|
||||
@keyup.enter="editable = false"
|
||||
/>
|
||||
@keyup.enter="editable = false" />
|
||||
<label v-else @click="editable = true">
|
||||
{{ localValue }}
|
||||
</label>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
@click="_clickForHelp"
|
||||
:title="titleForHelp"
|
||||
>
|
||||
:title="titleForHelp">
|
||||
<div v-if="!isExpanded">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</div>
|
||||
@@ -24,8 +23,7 @@
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
@click="_clickForHelp"
|
||||
:title="titleForHelp"
|
||||
>
|
||||
:title="titleForHelp">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,8 +40,7 @@
|
||||
class="remove-extensions float-right"
|
||||
type="checkbox"
|
||||
@click="$emit('remove-extensions-toggle')"
|
||||
checked
|
||||
/>
|
||||
checked />
|
||||
</label>
|
||||
<label class="setting-prompt float-right">
|
||||
{{ hideOriginalsText }}
|
||||
@@ -54,8 +51,7 @@
|
||||
<input
|
||||
class="collection-name form-control float-right"
|
||||
:placeholder="placeholderEnterName"
|
||||
v-model="collectionName"
|
||||
/>
|
||||
v-model="collectionName" />
|
||||
<div class="collection-name-prompt float-right">
|
||||
{{ l("Name:") }}
|
||||
</div>
|
||||
@@ -71,8 +67,7 @@
|
||||
<button
|
||||
class="create-collection btn btn-primary"
|
||||
@click="$emit('clicked-create', collectionName)"
|
||||
:disabled="!validInput"
|
||||
>
|
||||
:disabled="!validInput">
|
||||
{{ l("Create collection") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
v-if="item && databaseKeyFromElements"
|
||||
:database-key-from-elements="databaseKeyFromElements"
|
||||
:genomes="item"
|
||||
@clicked-save="clickedSave"
|
||||
/>
|
||||
@clicked-save="clickedSave" />
|
||||
</div>
|
||||
</GenomeProvider>
|
||||
</b-tab>
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
<button
|
||||
class="save-collection-edit btn btn-primary"
|
||||
@click="clickedSave"
|
||||
:disabled="selectedGenome.id == databaseKeyFromElements"
|
||||
>
|
||||
:disabled="selectedGenome.id == databaseKeyFromElements">
|
||||
{{ l("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -20,8 +19,7 @@
|
||||
label="text"
|
||||
:options="genomes"
|
||||
:searchable="true"
|
||||
:allow-empty="false"
|
||||
>
|
||||
:allow-empty="false">
|
||||
{{ selectedGenome.text }}
|
||||
</multiselect>
|
||||
</div>
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
<button
|
||||
class="run-tool-collection-edit btn btn-primary"
|
||||
@click="clickedConvert"
|
||||
:disabled="selectedConverter == {}"
|
||||
>
|
||||
:disabled="selectedConverter == {}">
|
||||
{{ l("Convert Collection") }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -20,8 +19,7 @@
|
||||
label="name"
|
||||
:options="suitableConverters"
|
||||
:searchable="true"
|
||||
:allow-empty="true"
|
||||
>
|
||||
:allow-empty="true">
|
||||
</multiselect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
v-model="queryInput"
|
||||
@input="delayQuery"
|
||||
@change="setQuery"
|
||||
@keydown.esc="setQuery()"
|
||||
/>
|
||||
@keydown.esc="setQuery()" />
|
||||
<font-awesome-icon v-if="loading" class="search-clear" icon="spinner" spin />
|
||||
<font-awesome-icon
|
||||
v-else
|
||||
@@ -15,8 +14,7 @@
|
||||
:title="titleClearSearch"
|
||||
class="search-clear"
|
||||
icon="times-circle"
|
||||
@click="setQuery()"
|
||||
/>
|
||||
@click="setQuery()" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
@keydown.enter="onChange"
|
||||
@keydown.esc="onCancel"
|
||||
class="d-inline w-auto h-auto px-1 py-0"
|
||||
ref="input"
|
||||
/>
|
||||
ref="input" />
|
||||
</template>
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<font-awesome-icon :title="title" :icon="['far', 'copy']" @click="copy(text, message)" />
|
||||
<font-awesome-icon class="cursor-pointer" :title="title" :icon="['far', 'copy']" @click="copy(text, message)" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
:error-message="errorMessage"
|
||||
:options-show="optionsShow"
|
||||
:modal-show="modalShow"
|
||||
:hide-modal="onCancel"
|
||||
>
|
||||
:hide-modal="onCancel">
|
||||
<template v-slot:search>
|
||||
<data-dialog-search v-model="filter" />
|
||||
</template>
|
||||
@@ -15,8 +14,7 @@
|
||||
:multiple="multiple"
|
||||
:filter="filter"
|
||||
@clicked="onClick"
|
||||
@load="load"
|
||||
/>
|
||||
@load="load" />
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<b-btn size="sm" class="float-left" v-if="undoShow" @click="load()">
|
||||
@@ -33,8 +31,7 @@
|
||||
class="float-right ml-1"
|
||||
variant="primary"
|
||||
@click="onOk"
|
||||
:disabled="!hasValue"
|
||||
>
|
||||
:disabled="!hasValue">
|
||||
Ok
|
||||
</b-btn>
|
||||
</template>
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
striped
|
||||
hover
|
||||
:fields="fields"
|
||||
:items="directoryContent"
|
||||
>
|
||||
:items="directoryContent">
|
||||
</b-table>
|
||||
<div v-if="errorMessage">
|
||||
<b v-if="path">{{ path }}</b> {{ errorMessage }}
|
||||
|
||||
@@ -5,20 +5,17 @@
|
||||
class="workflow-dropdown font-weight-bold p-2"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
aria-expanded="false">
|
||||
<span
|
||||
v-if="isError"
|
||||
class="dataset-icon error fa fa-times-circle text-danger"
|
||||
v-b-tooltip.hover
|
||||
title="An error occurred for this dataset."
|
||||
/>
|
||||
title="An error occurred for this dataset." />
|
||||
<span
|
||||
v-else-if="isPaused"
|
||||
class="dataset-icon pause fa fa-pause text-info"
|
||||
v-b-tooltip.hover
|
||||
title="The creation of this dataset has been paused."
|
||||
/>
|
||||
title="The creation of this dataset has been paused." />
|
||||
<span v-else class="dataset-icon fa fa-caret-down" />
|
||||
<span class="name">{{ this.getName }}</span>
|
||||
</b-link>
|
||||
|
||||
@@ -9,8 +9,6 @@ import flushPromises from "flush-promises";
|
||||
|
||||
const localVue = getLocalVue();
|
||||
|
||||
jest.mock("components/History/caching");
|
||||
|
||||
function buildWrapper(conversion_disable = false) {
|
||||
return mount(DatasetAttributes, {
|
||||
propsData: {
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
id="dataset-attributes-default-save"
|
||||
@click="submit('attribute', 'attributes')"
|
||||
variant="primary"
|
||||
class="mr-1"
|
||||
>
|
||||
class="mr-1">
|
||||
<font-awesome-icon icon="save" class="mr-1" />{{ "Save" | l }}
|
||||
</b-button>
|
||||
<b-button @click="submit('attribute', 'autodetect')">
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
v-if="!datasetLoading"
|
||||
:jobid="dataset.creating_job"
|
||||
v-slot="{ result: jobDetails, loading }"
|
||||
@error="onError"
|
||||
>
|
||||
@error="onError">
|
||||
<div v-if="!loading">
|
||||
<div class="page-container edit-attr">
|
||||
<div class="response-message"></div>
|
||||
@@ -24,8 +23,7 @@
|
||||
<DatasetErrorDetails
|
||||
:tool-stderr="jobDetails.tool_stderr"
|
||||
:job-stderr="jobDetails.job_stderr"
|
||||
:job-messages="jobDetails.job_messages"
|
||||
/>
|
||||
:job-messages="jobDetails.job_messages" />
|
||||
<JobProblemProvider :jobid="dataset.creating_job" v-slot="{ result: jobProblems }" @error="onError">
|
||||
<div v-if="jobProblems && (jobProblems.has_duplicate_inputs || jobProblems.has_empty_inputs)">
|
||||
<h3 class="common_problems mt-3">Detected Common Potential Problems</h3>
|
||||
@@ -45,7 +43,9 @@
|
||||
<br />
|
||||
Start here:
|
||||
<b>
|
||||
<a href="https://galaxyproject.org/support/tool-error/" target="_blank">
|
||||
<a
|
||||
href="https://training.galaxyproject.org/training-material/faqs/galaxy/#troubleshooting-errors"
|
||||
target="_blank">
|
||||
My job ended with an error. What can I do?
|
||||
</a>
|
||||
</b>
|
||||
@@ -62,20 +62,17 @@
|
||||
v-if="!jobDetails.user_email"
|
||||
id="dataset-error-email"
|
||||
v-model="email"
|
||||
title="Please provide your email:"
|
||||
/>
|
||||
title="Please provide your email:" />
|
||||
<FormElement
|
||||
id="dataset-error-message"
|
||||
v-model="message"
|
||||
:area="true"
|
||||
title="Please provide detailed information on the activities leading to this issue:"
|
||||
/>
|
||||
title="Please provide detailed information on the activities leading to this issue:" />
|
||||
<b-button
|
||||
id="dataset-error-submit"
|
||||
variant="primary"
|
||||
@click="submit(dataset, jobDetails.user_email)"
|
||||
class="mt-3"
|
||||
>
|
||||
class="mt-3">
|
||||
<font-awesome-icon icon="bug" class="mr-1" />Report
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<li class="dataset-hash">
|
||||
<i>{{ hash.hash_value }}</i>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
hash: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<span class="dataset-hashes">
|
||||
<ul class="dataset-hashes-list">
|
||||
<DatasetHash v-for="(hash, index) in hashes" :key="index" :hash="hash" />
|
||||
</ul>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatasetHash from "./DatasetHash";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DatasetHash,
|
||||
},
|
||||
props: {
|
||||
hashes: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dataset-hashes-list {
|
||||
padding-inline-start: 20px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,6 @@ import datasetResponse from "./testData/datasetResponse";
|
||||
import flushPromises from "flush-promises";
|
||||
import moment from "moment";
|
||||
|
||||
jest.mock("components/History/caching");
|
||||
const HDA_ID = "FOO_HDA_ID";
|
||||
|
||||
const mockDatasetProvider = {
|
||||
@@ -21,7 +20,7 @@ const mockDatasetProvider = {
|
||||
|
||||
const localVue = getLocalVue();
|
||||
|
||||
describe("DatasetInformation/DatasetInformation.vue", () => {
|
||||
describe("DatasetInformation/DatasetInformation", () => {
|
||||
let wrapper;
|
||||
let datasetInfoTable;
|
||||
let axiosMock;
|
||||
|
||||
@@ -54,6 +54,22 @@
|
||||
<td>Full Path</td>
|
||||
<td id="file_name">{{ dataset.file_name }}</td>
|
||||
</tr>
|
||||
<tr v-if="dataset.created_from_basename">
|
||||
<td>Originally Created From a File Named</td>
|
||||
<td id="created_from_basename">{{ dataset.created_from_basename }}</td>
|
||||
</tr>
|
||||
<tr v-if="dataset.sources && dataset.sources.length > 0">
|
||||
<td>Sources</td>
|
||||
<td>
|
||||
<DatasetSources :sources="dataset.sources" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="dataset.hashes && dataset.hashes.length > 0">
|
||||
<td>Hashes</td>
|
||||
<td>
|
||||
<DatasetHashes :hashes="dataset.hashes" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -65,6 +81,8 @@ import Utils from "utils/utils";
|
||||
import UtcDate from "components/UtcDate";
|
||||
import DecodedId from "../DecodedId";
|
||||
import { DatasetProvider } from "components/providers";
|
||||
import DatasetSources from "./DatasetSources";
|
||||
import DatasetHashes from "./DatasetHashes";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -74,7 +92,9 @@ export default {
|
||||
},
|
||||
},
|
||||
components: {
|
||||
DatasetHashes,
|
||||
DatasetProvider,
|
||||
DatasetSources,
|
||||
DecodedId,
|
||||
UtcDate,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<li class="dataset-source">
|
||||
<a v-if="browserCompatUri" :href="sourceUri" target="_blank">
|
||||
{{ source.source_uri }}
|
||||
<font-awesome-icon v-b-tooltip.hover title="Dataset Source URL" icon="external-link-alt" />
|
||||
</a>
|
||||
<span v-else>
|
||||
{{ source.source_uri }}
|
||||
</span>
|
||||
<font-awesome-icon v-b-tooltip.hover title="Copy URI" icon="copy" style="cursor: pointer" @click="copyLink" />
|
||||
<br />
|
||||
<DatasetSourceTransform :transform="source.transform" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faCopy, faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons";
|
||||
import { copy } from "utils/clipboard";
|
||||
import DatasetSourceTransform from "./DatasetSourceTransform";
|
||||
|
||||
library.add(faCopy, faExternalLinkAlt);
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DatasetSourceTransform,
|
||||
FontAwesomeIcon,
|
||||
},
|
||||
props: {
|
||||
source: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
browserCompatUri() {
|
||||
const sourceUri = this.sourceUri;
|
||||
return sourceUri && (sourceUri.indexOf("http") == 0 || sourceUri.indexOf("ftp") == 0);
|
||||
},
|
||||
sourceUri() {
|
||||
return this.source.source_uri;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
copyLink() {
|
||||
copy(this.sourceUri, "Link copied to the clipboard.");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<span class="dataset-source-transform-display">
|
||||
<div v-if="transform && transform.length > 0">
|
||||
Upon ingestion into the Galaxy, the following {{ actions }} were performed that modified the dataset
|
||||
contents:
|
||||
<ul>
|
||||
<li v-for="(transformAction, index) in transform" :key="index">
|
||||
<span
|
||||
:title="actionLongDescription(transformAction)"
|
||||
class="dataset-source-transform-element"
|
||||
:data-transform-action="transformAction.action"
|
||||
v-b-tooltip.hover.noninteractive.nofade.bottom>
|
||||
{{ actionShortDescription(transformAction) }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
|
||||
Vue.use(BootstrapVue);
|
||||
|
||||
const TRANSFORM_ACTION_DESCRIPTIONS = {
|
||||
to_posix_lines: {
|
||||
short: "Normalized new line characters",
|
||||
long: "Many Galaxy tools expect data to contain 'posix' newline characters in text files and not the newline format used by the Windows operating system. Additionally, most tools expect a newline at the end of plain text files. This file was converted to use these line endings or add a newline to the end of the file.",
|
||||
},
|
||||
spaces_to_tabs: {
|
||||
short: "Normalized spaces to tabs",
|
||||
long: "In order to convert the referenced data source to tabular data, spaces in the file contents were converted to tab characters to indicate column separations.",
|
||||
},
|
||||
datatype_groom: {
|
||||
short: "Datatype-specific grooming",
|
||||
long: "The Galaxy datatype class indicated the source data required 'groooming' and Galaxy applied datatype specific cleaning of the supplied data.",
|
||||
},
|
||||
};
|
||||
|
||||
const DATATYPE_GROOMING_DESCRIPTIONS = {
|
||||
bam: "The supplied BAM was coordinate-sorted using pysam.",
|
||||
"qname_sorted.bam": "The supplied BAM was 'queryname' sorted using pysam.",
|
||||
"qname_input_sorted.bam": "The supplied BAM was 'queryname' sorted using pysam.",
|
||||
"isa-tab": "The supplied compressed file was converted to an ISA-TAB composite dataset.",
|
||||
"isa-json": "The supplied compressed file was converted to an ISA-JSON composite dataset.",
|
||||
};
|
||||
|
||||
const UNKNOWN_ACTION_DESCRIPTION = {
|
||||
short: "Unknown action.",
|
||||
long: "",
|
||||
};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
transform: {
|
||||
type: Array,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
actions() {
|
||||
return this.transform.length > 1 ? "actions" : "action";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
actionShortDescription(transformAction) {
|
||||
return this.actionDescription(transformAction).short || "Unknown action.";
|
||||
},
|
||||
actionLongDescription(transformAction) {
|
||||
let longDescription = this.actionDescription(transformAction).long || "";
|
||||
if (transformAction.action == "datatype_groom") {
|
||||
const datatypeDescription = DATATYPE_GROOMING_DESCRIPTIONS[transformAction.datatype_ext];
|
||||
if (datatypeDescription) {
|
||||
longDescription += " " + datatypeDescription;
|
||||
}
|
||||
}
|
||||
return longDescription;
|
||||
},
|
||||
actionDescription(transformAction) {
|
||||
return TRANSFORM_ACTION_DESCRIPTIONS[transformAction.action] || UNKNOWN_ACTION_DESCRIPTION;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dataset-source-transform-element {
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dashed;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<span class="dataset-sources">
|
||||
<ul class="dataset-sources-list">
|
||||
<DatasetSource v-for="(source, index) in sources" :key="index" :source="source" />
|
||||
</ul>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatasetSource from "./DatasetSource";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DatasetSource,
|
||||
},
|
||||
props: {
|
||||
sources: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dataset-sources-list {
|
||||
padding-inline-start: 20px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
@@ -2,18 +2,16 @@
|
||||
<ConfigProvider v-slot="{ config }">
|
||||
<DatasetProvider
|
||||
:id="datasetId"
|
||||
v-slot="{ item: dataset, loading: isDatasetLoading, error: datasetLoadingError }"
|
||||
>
|
||||
v-slot="{ item: dataset, loading: isDatasetLoading, error: datasetLoadingError }">
|
||||
<div>
|
||||
<LoadingSpan v-if="isDatasetLoading" />
|
||||
<Alert v-else-if="datasetLoadingError" :message="datasetLoadingError" variant="error" />
|
||||
<CurrentUser v-else v-slot="{ user }">
|
||||
<JobDetailsProvider
|
||||
v-if="!isDatasetLoading"
|
||||
v-if="!isDatasetLoading && dataset.creating_job !== null"
|
||||
:jobid="dataset.creating_job"
|
||||
v-slot="{ result: job, loading: isJobLoading }"
|
||||
:use-cache="false"
|
||||
>
|
||||
:use-cache="false">
|
||||
<div v-if="!isJobLoading">
|
||||
<dataset-information class="detail" :hda_id="datasetId" />
|
||||
<job-parameters class="detail" dataset_type="hda" :dataset-id="datasetId" />
|
||||
@@ -24,13 +22,11 @@
|
||||
class="detail"
|
||||
v-if="config"
|
||||
:aws_estimate="config.aws_estimate"
|
||||
:dataset-id="datasetId"
|
||||
/>
|
||||
:dataset-id="datasetId" />
|
||||
<job-destination-params
|
||||
class="detail"
|
||||
v-if="user.is_admin"
|
||||
:job-id="dataset.creating_job"
|
||||
/>
|
||||
:job-id="dataset.creating_job" />
|
||||
<job-dependencies class="detail" :dependencies="job.dependencies"></job-dependencies>
|
||||
<div class="detail" v-if="dataset.peek">
|
||||
<h3>Dataset Peek:</h3>
|
||||
@@ -38,6 +34,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</JobDetailsProvider>
|
||||
<div v-else-if="!isDatasetLoading">
|
||||
<dataset-information class="detail" :hda_id="datasetId" />
|
||||
<dataset-storage class="detail" :dataset-id="datasetId" />
|
||||
<div>
|
||||
<h3>Job Not Found</h3>
|
||||
<p>
|
||||
No job associated with this dataset is recorded in Galaxy. Galaxy cannot determine full
|
||||
dataset provenance and history for this dataset.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CurrentUser>
|
||||
</div>
|
||||
</DatasetProvider>
|
||||
|
||||
@@ -9,6 +9,7 @@ import axios from "axios";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
|
||||
import {
|
||||
ftpId,
|
||||
rootId,
|
||||
directoryId,
|
||||
subDirectoryId,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
directory2RecursiveResponse,
|
||||
directory1Response,
|
||||
subsubdirectoryResponse,
|
||||
someErrorText,
|
||||
} from "./testingData";
|
||||
import { selectionStates } from "components/SelectionDialog/selectionStates";
|
||||
|
||||
@@ -44,6 +46,11 @@ const initComponent = async (props) => {
|
||||
axiosMock.onGet(path).reply(200, response);
|
||||
}
|
||||
|
||||
axiosMock.onGet("/api/remote_files?target=gxfiles://empty-dir").reply(404, {
|
||||
err_msg: someErrorText,
|
||||
err_code: 404,
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(FilesDialog, {
|
||||
localVue,
|
||||
propsData: props,
|
||||
@@ -193,6 +200,43 @@ describe("FilesDialog, file mode", () => {
|
||||
const rootNode = utils.getRenderedDirectory(rootId);
|
||||
expect(rootNode._rowVariant).toBe(selectionStates.selected);
|
||||
});
|
||||
|
||||
it("should show ftp helper only in ftp directory", async () => {
|
||||
// open some other directory than ftp
|
||||
await utils.open_root_folder();
|
||||
// check that ftp helper is not visible
|
||||
expect(wrapper.vm.showFTPHelper).toBe(false);
|
||||
expect(wrapper.find("#helper").exists()).toBe(false);
|
||||
// back to root folder
|
||||
await utils.navigateBack();
|
||||
|
||||
// open ftp directory
|
||||
await utils.openDirectory(ftpId);
|
||||
// check that ftp helper is visible
|
||||
expect(wrapper.vm.showFTPHelper).toBe(true);
|
||||
expect(wrapper.find("#helper").exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("should show loading error and can return back", async () => {
|
||||
expect(wrapper.vm.errorMessage).toBeNull();
|
||||
|
||||
// open directory with error
|
||||
await utils.openDirectory("empty-dir");
|
||||
// assert that error message is set and showed
|
||||
expect(wrapper.vm.errorMessage).toBe(someErrorText);
|
||||
expect(wrapper.html()).toContain(someErrorText);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
|
||||
// back to the root folder
|
||||
await wrapper.find("#back-btn").trigger("click");
|
||||
await flushPromises();
|
||||
expect(wrapper.vm.items.length).toBe(rootResponse.length);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("FilesDialog, directory mode", () => {
|
||||
@@ -238,6 +282,27 @@ describe("FilesDialog, directory mode", () => {
|
||||
//should close modal
|
||||
expect(wrapper.vm.modalShow).toBe(false);
|
||||
});
|
||||
|
||||
it("should show loading error and can return back", async () => {
|
||||
expect(wrapper.vm.errorMessage).toBeNull();
|
||||
|
||||
// open directory with error
|
||||
await utils.openDirectory("empty-dir");
|
||||
// assert that error message is set and showed
|
||||
expect(wrapper.vm.errorMessage).toBe(someErrorText);
|
||||
expect(wrapper.html()).toContain(someErrorText);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
|
||||
// back to the root folder
|
||||
await wrapper.find("#back-btn").trigger("click");
|
||||
await flushPromises();
|
||||
expect(wrapper.vm.items.length).toBe(rootResponse.length);
|
||||
|
||||
// assert that OK button is disabled
|
||||
expect(wrapper.vm.hasValue).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
/** Util methods **/
|
||||
|
||||
@@ -4,10 +4,23 @@
|
||||
:options-show="optionsShow"
|
||||
:modal-show="modalShow"
|
||||
:hide-modal="() => (modalShow = false)"
|
||||
>
|
||||
:back-func="load"
|
||||
:undo-show="undoShow">
|
||||
<template v-slot:search>
|
||||
<data-dialog-search v-model="filter" />
|
||||
</template>
|
||||
<template v-slot:helper>
|
||||
<b-alert v-if="showFTPHelper" id="helper" variant="info" show>
|
||||
This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at
|
||||
<strong>{{ ftpUploadSite }}</strong> using your Galaxy credentials. For help visit the
|
||||
<a href="https://galaxyproject.org/ftp-upload/" target="_blank">tutorial</a>.
|
||||
<span v-if="oidcEnabled"
|
||||
><br />If you are signed-in to Galaxy using a third-party identity and you
|
||||
<strong>do not have a Galaxy password</strong> please use the reset password option in the login
|
||||
form with your email to create a password for your account.</span
|
||||
>
|
||||
</b-alert>
|
||||
</template>
|
||||
<template v-slot:options>
|
||||
<data-dialog-table
|
||||
v-if="optionsShow"
|
||||
@@ -21,8 +34,7 @@
|
||||
:is-busy="isBusy"
|
||||
@clicked="clicked"
|
||||
@open="open"
|
||||
@toggleSelectAll="toggleSelectAll"
|
||||
/>
|
||||
@toggleSelectAll="toggleSelectAll" />
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<b-btn id="back-btn" size="sm" class="float-left" v-if="undoShow" @click="load()">
|
||||
@@ -36,8 +48,7 @@
|
||||
variant="primary"
|
||||
id="ok-btn"
|
||||
@click="fileMode ? finalize() : selectLeaf(currentDirectory)"
|
||||
:disabled="(fileMode && !hasValue) || isBusy || (!fileMode && urlTracker.atRoot())"
|
||||
>
|
||||
:disabled="(fileMode && !hasValue) || isBusy || (!fileMode && urlTracker.atRoot())">
|
||||
{{ fileMode ? "Ok" : "Select this folder" }}
|
||||
</b-btn>
|
||||
</template>
|
||||
@@ -46,6 +57,7 @@
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import { getGalaxyInstance } from "../../app";
|
||||
import SelectionDialogMixin from "components/SelectionDialog/SelectionDialogMixin";
|
||||
import { selectionStates } from "components/SelectionDialog/selectionStates";
|
||||
import { UrlTracker } from "components/DataDialog/utilities";
|
||||
@@ -92,7 +104,10 @@ export default {
|
||||
showDetails: true,
|
||||
isBusy: false,
|
||||
currentDirectory: undefined,
|
||||
showFTPHelper: false,
|
||||
selectAllIcon: selectionStates.unselected,
|
||||
ftpUploadSite: getGalaxyInstance()?.config?.ftp_upload_site,
|
||||
oidcEnabled: getGalaxyInstance()?.config?.enable_oidc,
|
||||
};
|
||||
},
|
||||
created: function () {
|
||||
@@ -233,7 +248,9 @@ export default {
|
||||
},
|
||||
/** check if all objects in this folders are selected **/
|
||||
checkIfAllSelected() {
|
||||
const isAllSelected = this.items.every(({ id }) => this.model.exists(id) || this.isDirectorySelected(id));
|
||||
const isAllSelected =
|
||||
this.items.length &&
|
||||
this.items.every(({ id }) => this.model.exists(id) || this.isDirectorySelected(id));
|
||||
|
||||
if (isAllSelected && !this.isDirectorySelected(this.currentDirectory.id)) {
|
||||
// if all selected, select current folder
|
||||
@@ -255,16 +272,25 @@ export default {
|
||||
item.isLeaf ? this.model.add(item) : this.selectDirectory(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isUnselectAll && this.items.length !== 0) {
|
||||
this.selectedDirectories.push(this.currentDirectory);
|
||||
} else if (this.isDirectorySelected(this.currentDirectory.id)) {
|
||||
this.selectDirectory(this.currentDirectory);
|
||||
}
|
||||
|
||||
this.hasValue = this.model.count() > 0;
|
||||
this.formatRows();
|
||||
},
|
||||
/** Performs server request to retrieve data records **/
|
||||
load: function (record) {
|
||||
this.currentDirectory = this.urlTracker.getUrl(record);
|
||||
this.showFTPHelper = record?.url === "gxftp://";
|
||||
this.filter = null;
|
||||
this.optionsShow = false;
|
||||
this.undoShow = !this.urlTracker.atRoot();
|
||||
if (this.urlTracker.atRoot()) {
|
||||
if (this.urlTracker.atRoot() || this.errorMessage) {
|
||||
this.errorMessage = null;
|
||||
this.services
|
||||
.getFileSources()
|
||||
.then((items) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export const ftpId = "_ftp";
|
||||
export const rootId = "pdb-gzip";
|
||||
export const directoryId = "gxfiles://pdb-gzip/directory1";
|
||||
export const subDirectoryId = "gxfiles://pdb-gzip/directory1/subdirectory1";
|
||||
@@ -24,6 +25,16 @@ export const rootResponse = [
|
||||
requires_roles: null,
|
||||
requires_groups: null,
|
||||
},
|
||||
{
|
||||
id: "empty-dir",
|
||||
type: "posix",
|
||||
uri_root: "gxfiles://empty-dir",
|
||||
label: "Empty Directory",
|
||||
doc: "Empty Directory",
|
||||
writable: true,
|
||||
requires_roles: null,
|
||||
requires_groups: null,
|
||||
},
|
||||
];
|
||||
|
||||
export const pdbResponse = [
|
||||
@@ -172,3 +183,5 @@ export const subsubdirectoryResponse = [
|
||||
path: "directory1/subdirectory1/subsubdirectory",
|
||||
},
|
||||
];
|
||||
|
||||
export const someErrorText = "some error text";
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<b-row>
|
||||
<b-col class="form-color-input">
|
||||
<b-form-input class="cursor-pointer" :id="id" v-model="currentValue" type="color" size="sm" />
|
||||
</b-col>
|
||||
<b-col class="pl-0">
|
||||
<label class="pt-1 cursor-pointer" :for="id">Select a color</label>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
currentValue: {
|
||||
get() {
|
||||
return this.value;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit("input", val);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.form-color-input {
|
||||
max-width: 3.6rem;
|
||||
}
|
||||
</style>
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { getLocalVue } from "jest/helpers";
|
||||
import DirectoryPathEditableBreadcrumb from "./DirectoryPathEditableBreadcrumb";
|
||||
import FilesDialog from "./FilesDialog";
|
||||
import FormDirectory from "./FormDirectory";
|
||||
import FilesDialog from "components/FilesDialog/FilesDialog";
|
||||
|
||||
import flushPromises from "flush-promises";
|
||||
import MockAdapter from "axios-mock-adapter";
|
||||
import axios from "axios";
|
||||
import { rootResponse } from "./testingData";
|
||||
import { rootResponse } from "components/FilesDialog/testingData";
|
||||
const localVue = getLocalVue();
|
||||
jest.mock("app");
|
||||
|
||||
@@ -46,14 +46,14 @@ describe("DirectoryPathEditableBreadcrumb", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const axiosMock = new MockAdapter(axios);
|
||||
spyOnUrlSet = jest.spyOn(DirectoryPathEditableBreadcrumb.methods, "setUrl");
|
||||
spyOnAddPath = jest.spyOn(DirectoryPathEditableBreadcrumb.methods, "addPath");
|
||||
spyOnUpdateURL = jest.spyOn(DirectoryPathEditableBreadcrumb.methods, "updateURL");
|
||||
spyOnUrlSet = jest.spyOn(FormDirectory.methods, "setUrl");
|
||||
spyOnAddPath = jest.spyOn(FormDirectory.methods, "addPath");
|
||||
spyOnUpdateURL = jest.spyOn(FormDirectory.methods, "updateURL");
|
||||
|
||||
// register axios paths
|
||||
axiosMock.onGet("/api/remote_files/plugins").reply(200, rootResponse);
|
||||
|
||||
wrapper = mount(DirectoryPathEditableBreadcrumb, {
|
||||
wrapper = mount(FormDirectory, {
|
||||
propsData: {
|
||||
callback: () => {},
|
||||
},
|
||||
+8
-13
@@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!url">
|
||||
<b-button id="select-btn" @click="reset"> <font-awesome-icon icon="folder-open" /> Select folder </b-button>
|
||||
<b-button id="select-btn" @click="reset">
|
||||
<font-awesome-icon icon="folder-open" /> {{ selectText }}
|
||||
</b-button>
|
||||
<FilesDialog :key="modalKey" mode="directory" :callback="setUrl" :require-writable="true" />
|
||||
</div>
|
||||
<b-breadcrumb v-if="url">
|
||||
@@ -13,8 +15,7 @@
|
||||
<b-breadcrumb-item
|
||||
v-for="({ pathChunk, editable }, index) in pathChunks"
|
||||
:key="index"
|
||||
class="existent-url-path align-items-center"
|
||||
>
|
||||
class="existent-url-path align-items-center">
|
||||
<b-button class="regular-path-chunk" @click="removePath(index)" :disabled="!editable" variant="dark">
|
||||
{{ pathChunk }}</b-button
|
||||
>
|
||||
@@ -29,8 +30,7 @@
|
||||
@keydown.8.capture="removeLastPath"
|
||||
v-model="currentDirectoryName"
|
||||
placeholder="enter directory name"
|
||||
trim
|
||||
/>
|
||||
trim />
|
||||
</b-breadcrumb-item>
|
||||
</b-breadcrumb>
|
||||
</div>
|
||||
@@ -41,6 +41,7 @@ import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { faFolder, faFolderOpen } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FilesDialog } from "components/FilesDialog";
|
||||
import _l from "utils/localization";
|
||||
|
||||
library.add(faFolder, faFolderOpen);
|
||||
|
||||
@@ -57,13 +58,7 @@ export default {
|
||||
FilesDialog,
|
||||
},
|
||||
data() {
|
||||
return { ...getDefaultValues(), modalKey: 0 };
|
||||
},
|
||||
props: {
|
||||
callback: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
return { ...getDefaultValues(), modalKey: 0, selectText: _l("Select") };
|
||||
},
|
||||
computed: {
|
||||
isValidName() {
|
||||
@@ -123,7 +118,7 @@ export default {
|
||||
// create an string of path chunks separated by `/`
|
||||
url = encodeURI(`${this.url.protocol}//${this.pathChunks.map(({ pathChunk }) => pathChunk).join("/")}`);
|
||||
}
|
||||
this.callback(url);
|
||||
this.$emit("input", url);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { getLocalVue } from "jest/helpers";
|
||||
import FormHidden from "./FormHidden";
|
||||
|
||||
const localVue = getLocalVue();
|
||||
|
||||
describe("FormHidden", () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(FormHidden, {
|
||||
propsData: {
|
||||
value: false,
|
||||
info: "info",
|
||||
},
|
||||
localVue,
|
||||
});
|
||||
});
|
||||
|
||||
it("check initial value and value change", async () => {
|
||||
expect(wrapper.vm.value).toBe(false);
|
||||
await wrapper.setProps({ value: true });
|
||||
expect(wrapper.vm.value).toBe(true);
|
||||
expect(wrapper.text()).toBe("info");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
{{ info }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
required: true,
|
||||
},
|
||||
info: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -2,8 +2,6 @@ import { mount } from "@vue/test-utils";
|
||||
import { getLocalVue } from "jest/helpers";
|
||||
import FormInput from "./FormInput";
|
||||
|
||||
jest.mock("app");
|
||||
|
||||
const localVue = getLocalVue();
|
||||
|
||||
describe("FormInput", () => {
|
||||
|
||||
@@ -9,8 +9,6 @@ import SelectContent from "mvc/ui/ui-select-content";
|
||||
import SelectLibrary from "mvc/ui/ui-select-library";
|
||||
import SelectFtp from "mvc/ui/ui-select-ftp";
|
||||
import RulesEdit from "mvc/ui/ui-rules-edit";
|
||||
import FileSource from "mvc/ui/ui-file-source";
|
||||
import ColorPicker from "mvc/ui/ui-color-picker";
|
||||
import DataPicker from "mvc/ui/ui-data-picker";
|
||||
|
||||
// create form view
|
||||
@@ -26,25 +24,19 @@ export default Backbone.View.extend({
|
||||
data_collection: "_fieldData",
|
||||
integer: "_fieldSlider",
|
||||
float: "_fieldSlider",
|
||||
boolean: "_fieldBoolean",
|
||||
drill_down: "_fieldDrilldown",
|
||||
color: "_fieldColor",
|
||||
group_tag: "_fieldSelect",
|
||||
hidden: "_fieldHidden",
|
||||
hidden_data: "_fieldHidden",
|
||||
baseurl: "_fieldHidden",
|
||||
library_data: "_fieldLibrary",
|
||||
ftpfile: "_fieldFtp",
|
||||
upload: "_fieldUpload",
|
||||
rules: "_fieldRulesEdit",
|
||||
directory_uri: "_fieldDirectoryUri",
|
||||
data_dialog: "_fieldDialog",
|
||||
},
|
||||
|
||||
/** Returns an input field for a given field type */
|
||||
create: function (input_def) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
var fieldClass = this.types[input_def.titleonly ? "hidden" : input_def.type];
|
||||
var fieldClass = this.types[input_def.type];
|
||||
this.field = typeof this[fieldClass] === "function" ? this[fieldClass].call(this, input_def) : null;
|
||||
if (!this.field) {
|
||||
this.field = input_def.options ? this._fieldSelect(input_def) : this._fieldText(input_def);
|
||||
@@ -68,6 +60,7 @@ export default Backbone.View.extend({
|
||||
type: input_def.type,
|
||||
flavor: input_def.flavor,
|
||||
data: input_def.options,
|
||||
tag: input_def.tag,
|
||||
onchange: input_def.onchange,
|
||||
});
|
||||
},
|
||||
@@ -189,30 +182,6 @@ export default Backbone.View.extend({
|
||||
});
|
||||
},
|
||||
|
||||
/** Hidden field */
|
||||
_fieldHidden: function (input_def) {
|
||||
return new Ui.Hidden({
|
||||
id: `field-${input_def.id}`,
|
||||
info: input_def.info,
|
||||
});
|
||||
},
|
||||
|
||||
/** Boolean field */
|
||||
_fieldBoolean: function (input_def) {
|
||||
return new Ui.Switch({
|
||||
id: `field-${input_def.id}`,
|
||||
onchange: input_def.onchange,
|
||||
});
|
||||
},
|
||||
|
||||
/** Color picker field */
|
||||
_fieldColor: function (input_def) {
|
||||
return new ColorPicker({
|
||||
id: `field-${input_def.id}`,
|
||||
onchange: input_def.onchange,
|
||||
});
|
||||
},
|
||||
|
||||
/** Data dialog picker field */
|
||||
_fieldDialog: function (input_def) {
|
||||
return new DataPicker({
|
||||
@@ -242,14 +211,6 @@ export default Backbone.View.extend({
|
||||
});
|
||||
},
|
||||
|
||||
_fieldDirectoryUri: function (input_def) {
|
||||
return new FileSource.View({
|
||||
id: `field-${input_def.id}`,
|
||||
onchange: input_def.onchange,
|
||||
target: input_def.target,
|
||||
});
|
||||
},
|
||||
|
||||
_fieldRulesEdit: function (input_def) {
|
||||
return new RulesEdit.View({
|
||||
id: `field-${input_def.id}`,
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
size="sm"
|
||||
class="float-right"
|
||||
v-b-tooltip.hover.bottom
|
||||
@click="onCollapse"
|
||||
>
|
||||
@click="onCollapse">
|
||||
<font-awesome-icon v-if="expanded" icon="eye-slash" class="fa-fw" />
|
||||
<font-awesome-icon v-else icon="eye" class="fa-fw" />
|
||||
</b-button>
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
:collapsed-disable-icon="collapsedDisableIcon"
|
||||
:errors="errors"
|
||||
:on-change="onChange"
|
||||
:on-change-form="onChangeForm"
|
||||
/>
|
||||
:on-change-form="onChangeForm" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -20,6 +20,10 @@ describe("FormElement", () => {
|
||||
title: "title_text",
|
||||
},
|
||||
localVue,
|
||||
stubs: {
|
||||
FormInput: { template: "<div>form-input</div>" },
|
||||
FormHidden: { template: "<div>form-hidden</div>" },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,9 +47,10 @@ describe("FormElement", () => {
|
||||
await wrapper.setProps({ default_value: "default_value", collapsible_value: "collapsible_value" });
|
||||
expect(wrapper.find(".ui-form-title-text").text()).toEqual("title_text");
|
||||
expect(wrapper.findAll("span[title='Disable']").length).toEqual(1);
|
||||
expect(wrapper.emitted().input[0][0]).toEqual("initial_value");
|
||||
wrapper.find(".ui-form-collapsible-icon").trigger("click");
|
||||
expect(wrapper.emitted().input[0][0]).toEqual("collapsible_value");
|
||||
expect(wrapper.emitted().input[0][1]).toEqual("input");
|
||||
expect(wrapper.emitted().input[1][0]).toEqual("collapsible_value");
|
||||
expect(wrapper.emitted().input[1][1]).toEqual("input");
|
||||
await Vue.nextTick();
|
||||
await wrapper.setProps({
|
||||
collapsedEnableText: "Enable Collapsible",
|
||||
@@ -54,9 +59,16 @@ describe("FormElement", () => {
|
||||
expect(wrapper.findAll("span[title='Enable Collapsible']").length).toEqual(1);
|
||||
expect(wrapper.findAll("span[title='Disable Collapsible']").length).toEqual(0);
|
||||
wrapper.find(".ui-form-collapsible-icon").trigger("click");
|
||||
expect(wrapper.emitted().input[1][0]).toEqual("default_value");
|
||||
expect(wrapper.emitted().input[2][0]).toEqual("default_value");
|
||||
await Vue.nextTick();
|
||||
expect(wrapper.findAll("span[title='Disable Collapsible']").length).toEqual(1);
|
||||
expect(wrapper.findAll("span[title='Enable Collapsible']").length).toEqual(0);
|
||||
});
|
||||
|
||||
it("check type matching", async () => {
|
||||
await wrapper.setProps({ type: "text" });
|
||||
expect(wrapper.find("div[id='input'").text()).toEqual("form-input");
|
||||
await wrapper.setProps({ attributes: { titleonly: true } });
|
||||
expect(wrapper.find("div[id='input'").text()).toEqual("form-hidden");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-show="!hidden" :id="elementId" :class="['ui-form-element section-row', cls]" :tour_id="id">
|
||||
<div v-show="!isHidden" :id="elementId" :class="['ui-form-element section-row', cls]" :tour_id="id">
|
||||
<div v-if="hasError" class="ui-form-error">
|
||||
<span class="fa fa-exclamation mr-1" />
|
||||
<span class="ui-form-error-text" v-html="error" />
|
||||
@@ -22,6 +22,9 @@
|
||||
</div>
|
||||
<div v-if="showField" class="ui-form-field" :data-label="title">
|
||||
<FormBoolean v-if="type == 'boolean'" v-model="currentValue" :id="id" />
|
||||
<FormHidden v-else-if="isHiddenType" v-model="currentValue" :id="id" :info="attrs['info']" />
|
||||
<FormColor v-else-if="type == 'color'" v-model="currentValue" :id="id" />
|
||||
<FormDirectory v-else-if="type == 'directory_uri'" v-model="currentValue" />
|
||||
<FormParameter
|
||||
v-else-if="backbonejs"
|
||||
v-model="currentValue"
|
||||
@@ -29,8 +32,7 @@
|
||||
:data-label="title"
|
||||
:type="type"
|
||||
:attributes="attrs"
|
||||
ref="params"
|
||||
/>
|
||||
ref="params" />
|
||||
<FormInput v-else v-model="currentValue" :id="id" :area="attrs['area']" />
|
||||
</div>
|
||||
<div v-if="showPreview" class="ui-form-preview" v-html="previewText" />
|
||||
@@ -42,14 +44,20 @@
|
||||
import _ from "underscore";
|
||||
import { getElementId } from "./utilities";
|
||||
import FormBoolean from "./Elements/FormBoolean";
|
||||
import FormHidden from "./Elements/FormHidden";
|
||||
import FormInput from "./Elements/FormInput";
|
||||
import FormParameter from "./Elements/FormParameter";
|
||||
import FormColor from "./Elements/FormColor";
|
||||
import FormDirectory from "./Elements/FormDirectory";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
FormBoolean,
|
||||
FormHidden,
|
||||
FormInput,
|
||||
FormColor,
|
||||
FormParameter,
|
||||
FormDirectory,
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
@@ -178,9 +186,15 @@ export default {
|
||||
}
|
||||
return help;
|
||||
},
|
||||
hidden() {
|
||||
isHidden() {
|
||||
return this.attrs["hidden"];
|
||||
},
|
||||
isHiddenType() {
|
||||
return (
|
||||
["hidden", "hidden_data", "baseurl"].includes(this.type) ||
|
||||
(this.attributes && this.attributes.titleonly)
|
||||
);
|
||||
},
|
||||
previewText() {
|
||||
return _.escape(this.textValue).replace(/\n/g, "<br>");
|
||||
},
|
||||
@@ -207,6 +221,7 @@ export default {
|
||||
* Determines to wether expand or collapse the input.
|
||||
*/
|
||||
initialState() {
|
||||
this.setValue(this.value);
|
||||
const collapsibleValue = this.collapsibleValue;
|
||||
const value = JSON.stringify(this.value);
|
||||
this.connected = value == JSON.stringify(this.connectedValue);
|
||||
|
||||
@@ -12,15 +12,13 @@
|
||||
:disabled="sustainConditionals"
|
||||
:attributes="input.test_param"
|
||||
:backbonejs="true"
|
||||
@change="onChange"
|
||||
/>
|
||||
@change="onChange" />
|
||||
<div v-for="(caseDetails, caseId) in input.cases" :key="caseId">
|
||||
<FormNode
|
||||
v-if="conditionalMatch(input, caseId)"
|
||||
v-bind="$props"
|
||||
:inputs="caseDetails.inputs"
|
||||
:prefix="getPrefix(input.name)"
|
||||
/>
|
||||
:prefix="getPrefix(input.name)" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="input.type == 'repeat'">
|
||||
@@ -30,8 +28,7 @@
|
||||
<FormCard
|
||||
v-for="(cache, cacheId) in input.cache"
|
||||
:key="cacheId"
|
||||
:title="repeatTitle(cacheId, input.title)"
|
||||
>
|
||||
:title="repeatTitle(cacheId, input.title)">
|
||||
<template v-slot:operations>
|
||||
<b-button
|
||||
v-if="!sustainRepeats"
|
||||
@@ -40,8 +37,7 @@
|
||||
size="sm"
|
||||
class="float-right"
|
||||
v-b-tooltip.hover.bottom
|
||||
@click="repeatDelete(input, cacheId)"
|
||||
>
|
||||
@click="repeatDelete(input, cacheId)">
|
||||
<font-awesome-icon icon="trash-alt" />
|
||||
</b-button>
|
||||
</template>
|
||||
@@ -76,8 +72,7 @@
|
||||
:collapsed-enable-icon="collapsedEnableIcon"
|
||||
:collapsed-disable-text="collapsedDisableText"
|
||||
:collapsed-disable-icon="collapsedDisableIcon"
|
||||
@change="onChange"
|
||||
/>
|
||||
@change="onChange" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<div
|
||||
class="galaxy-loader"
|
||||
:class="[`galaxy-loader_${style}`, { 'galaxy-loader_center': center }]"
|
||||
:style="{ transform: `scale(${size / 100})` }"
|
||||
>
|
||||
:style="{ transform: `scale(${size / 100})` }">
|
||||
<div class="galaxy-loader_strip-1"></div>
|
||||
<div class="galaxy-loader_strip-2"></div>
|
||||
<div class="galaxy-loader_strip-3"></div>
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
:value="value"
|
||||
@input="input"
|
||||
:placeholder="'Search Filter' | localize"
|
||||
data-description="filter text input"
|
||||
/>
|
||||
data-description="filter text input" />
|
||||
</DebouncedInput>
|
||||
|
||||
<b-input-group-append>
|
||||
@@ -16,8 +15,7 @@
|
||||
:pressed="showDeleted"
|
||||
:variant="showDeleted ? 'info' : 'secondary'"
|
||||
@click="showDeleted = !showDeleted"
|
||||
data-description="show deleted filter toggle"
|
||||
>
|
||||
data-description="show deleted filter toggle">
|
||||
{{ "Deleted" | localize }}
|
||||
</b-button>
|
||||
<b-button
|
||||
@@ -25,8 +23,7 @@
|
||||
:pressed="showHidden"
|
||||
:variant="showHidden ? 'info' : 'secondary'"
|
||||
@click="showHidden = !showHidden"
|
||||
data-description="show hidden filter toggle"
|
||||
>
|
||||
data-description="show hidden filter toggle">
|
||||
{{ "Hidden" | localize }}
|
||||
</b-button>
|
||||
</b-input-group-append>
|
||||
@@ -34,7 +31,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { SearchParams } from "./model/SearchParams";
|
||||
import { SearchParams } from "components/providers/History/SearchParams";
|
||||
import DebouncedInput from "components/DebouncedInput";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -8,15 +8,14 @@
|
||||
@delete="onDelete"
|
||||
@undelete="onUndelete"
|
||||
@unhide="onUnhide"
|
||||
@copy-link="onCopyLink"
|
||||
/>
|
||||
@copy-link="onCopyLink" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatasetUI from "./DatasetUI";
|
||||
import { Dataset } from "../../model";
|
||||
import { deleteContent, updateContentFields } from "../../model/queries";
|
||||
import { cacheContent } from "../../caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
import { copy as sendToClipboard } from "utils/clipboard";
|
||||
import { absPath } from "utils/redirect";
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
:disabled="dataset.purged || isIn(STATES.UPLOAD, STATES.NEW)"
|
||||
@click.stop="viewData"
|
||||
variant="link"
|
||||
class="px-1 display-btn"
|
||||
/>
|
||||
class="px-1 display-btn" />
|
||||
<IconButton
|
||||
v-if="writable && notIn(STATES.DISCARDED)"
|
||||
icon="pen"
|
||||
@@ -17,8 +16,7 @@
|
||||
:disabled="dataset.deleted || isIn(STATES.UPLOAD, STATES.NEW)"
|
||||
@click.stop="$emit('edit')"
|
||||
variant="link"
|
||||
class="px-1 edit-btn"
|
||||
/>
|
||||
class="px-1 edit-btn" />
|
||||
<IconButton
|
||||
v-if="writable && dataset.accessible"
|
||||
:icon="dataset.deleted ? 'trash-restore' : 'trash'"
|
||||
@@ -27,8 +25,7 @@
|
||||
v-b-modal="bsId('delete-modal')"
|
||||
variant="link"
|
||||
class="px-1 delete-btn"
|
||||
@click.stop
|
||||
/>
|
||||
@click.stop />
|
||||
|
||||
<b-dropdown
|
||||
right
|
||||
@@ -38,8 +35,7 @@
|
||||
toggle-class="p-1 pl-2"
|
||||
class="flex-grow-0 dataset-operations-dropdown"
|
||||
v-if="expanded"
|
||||
boundary="window"
|
||||
>
|
||||
boundary="window">
|
||||
<template v-slot:button-content>
|
||||
<Icon icon="ellipsis-v" variant="link" />
|
||||
<span class="sr-only">Dataset Operations</span>
|
||||
@@ -53,8 +49,7 @@
|
||||
backboneRoute('datasets/error', {
|
||||
dataset_id: dataset.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
">
|
||||
<Icon icon="exclamation-triangle" class="mr-1" />
|
||||
<span v-localize>Show Error</span>
|
||||
</b-dropdown-item>
|
||||
@@ -62,8 +57,7 @@
|
||||
<b-dropdown-item
|
||||
v-if="showDownloads && dataset.getUrl('download')"
|
||||
title="Copy Link"
|
||||
@click.stop="$emit('copy-link')"
|
||||
>
|
||||
@click.stop="$emit('copy-link')">
|
||||
<Icon icon="link" class="mr-1" />
|
||||
<span v-localize>Copy Link</span>
|
||||
</b-dropdown-item>
|
||||
@@ -75,8 +69,7 @@
|
||||
:title="'Download ' + mf.file_type"
|
||||
:href="prependPath(dataset.getUrl('meta_download') + mf.file_type)"
|
||||
target="_blank"
|
||||
download
|
||||
>
|
||||
download>
|
||||
<Icon icon="download" class="mr-1" />
|
||||
<span v-localize>{{ "Download " + mf.file_type }}</span>
|
||||
</b-dropdown-item>
|
||||
@@ -88,8 +81,7 @@
|
||||
:href="prependPath(dataset.getUrl('download'))"
|
||||
target="_blank"
|
||||
class="download-btn"
|
||||
download
|
||||
>
|
||||
download>
|
||||
<Icon icon="download" class="mr-1" />
|
||||
<span v-localize>Download</span>
|
||||
</b-dropdown-item>
|
||||
@@ -102,8 +94,7 @@
|
||||
backboneRoute('/', {
|
||||
job_id: dataset.creating_job,
|
||||
})
|
||||
"
|
||||
>
|
||||
">
|
||||
<Icon icon="play" class="mr-1" />
|
||||
<span v-localize>Run job again</span>
|
||||
</b-dropdown-item>
|
||||
@@ -111,8 +102,7 @@
|
||||
<b-dropdown-item
|
||||
v-if="showViz && hasViz && isIn(STATES.OK, STATES.FAILED_METADATA)"
|
||||
title="Visualize Data"
|
||||
@click.stop.prevent="visualize"
|
||||
>
|
||||
@click.stop.prevent="visualize">
|
||||
<Icon icon="chart-area" class="mr-1" />
|
||||
<span v-localize>Visualize Data</span>
|
||||
</b-dropdown-item>
|
||||
@@ -120,8 +110,7 @@
|
||||
<b-dropdown-item
|
||||
v-if="currentUser && currentUser.id && dataset.creating_job"
|
||||
title="Tool Help"
|
||||
@click.stop="showToolHelp(dataset.creating_job)"
|
||||
>
|
||||
@click.stop="showToolHelp(dataset.creating_job)">
|
||||
<Icon icon="question" class="mr-1" />
|
||||
<span v-localize>Tool Help</span>
|
||||
</b-dropdown-item>
|
||||
@@ -131,8 +120,7 @@
|
||||
key="dataset-details"
|
||||
title="View Dataset Details"
|
||||
class="params-btn"
|
||||
@click.stop.prevent="showDetails"
|
||||
>
|
||||
@click.stop.prevent="showDetails">
|
||||
<Icon icon="info-circle" class="mr-1" />
|
||||
<span v-localize>View Dataset Details</span>
|
||||
</b-dropdown-item>
|
||||
@@ -263,8 +251,9 @@ export default {
|
||||
|
||||
// wierd iframe navigation
|
||||
visualize() {
|
||||
const showDetailsUrl = `/datasets/${this.dataset.id}/details`;
|
||||
const redirectParams = {
|
||||
path: this.dataset.getUrl("show_params"),
|
||||
path: showDetailsUrl,
|
||||
title: "Dataset details",
|
||||
tryIframe: false,
|
||||
};
|
||||
@@ -276,13 +265,14 @@ export default {
|
||||
},
|
||||
|
||||
showDetails() {
|
||||
const showDetailsUrl = `/datasets/${this.dataset.id}/details`;
|
||||
const redirectParams = {
|
||||
path: this.dataset.getUrl("show_params"),
|
||||
path: showDetailsUrl,
|
||||
title: "Dataset details",
|
||||
tryIframe: false,
|
||||
};
|
||||
if (!this.iframeAdd(redirectParams)) {
|
||||
this.backboneRoute(this.dataset.getUrl("show_params"));
|
||||
this.backboneRoute(showDetailsUrl);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@ either through the props, and make updates through the events -->
|
||||
:data-state="dataset.state"
|
||||
@keydown.arrow-left.self.stop="$emit('update:expanded', false)"
|
||||
@keydown.arrow-right.self.stop="$emit('update:expanded', true)"
|
||||
@keydown.space.self.stop.prevent="$emit('update:selected', !selected)"
|
||||
>
|
||||
@keydown.space.self.stop.prevent="$emit('update:selected', !selected)">
|
||||
<!-- name, state buttons, menus -->
|
||||
<nav class="content-top-menu p-1 d-flex cursor-pointer" @click.stop="$emit('update:expanded', !expanded)">
|
||||
<div class="d-flex flex-grow-1 overflow-hidden">
|
||||
@@ -26,8 +25,7 @@ either through the props, and make updates through the events -->
|
||||
v-if="!collapsed"
|
||||
class="status-icon px-1"
|
||||
:state="dataset.state"
|
||||
@click.stop="onStatusClick"
|
||||
/>
|
||||
@click.stop="onStatusClick" />
|
||||
|
||||
<IconButton
|
||||
v-if="!collapsed && !dataset.visible"
|
||||
@@ -35,8 +33,7 @@ either through the props, and make updates through the events -->
|
||||
state="hidden"
|
||||
title="Unhide"
|
||||
icon="eye-slash"
|
||||
@click.stop="$emit('unhide')"
|
||||
/>
|
||||
@click.stop="$emit('unhide')" />
|
||||
|
||||
<IconButton
|
||||
v-if="!collapsed && dataset.isDeleted && !dataset.purged"
|
||||
@@ -44,8 +41,7 @@ either through the props, and make updates through the events -->
|
||||
state="deleted"
|
||||
title="Undelete"
|
||||
icon="trash-restore"
|
||||
@click.stop="$emit('undelete')"
|
||||
/>
|
||||
@click.stop="$emit('undelete')" />
|
||||
|
||||
<div class="content-title title p-1 overflow-hidden">
|
||||
<h5 class="text-truncate" v-if="collapsed">
|
||||
@@ -62,8 +58,7 @@ either through the props, and make updates through the events -->
|
||||
:expanded="expanded"
|
||||
:writable="writable"
|
||||
@edit="edit"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
v-on="$listeners" />
|
||||
</slot>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -91,16 +86,14 @@ either through the props, and make updates through the events -->
|
||||
v-model="name"
|
||||
placeholder="Dataset Name"
|
||||
trim
|
||||
max-rows="4"
|
||||
></b-textarea>
|
||||
max-rows="4"></b-textarea>
|
||||
|
||||
<b-textarea
|
||||
class="mb-3"
|
||||
v-model="annotation"
|
||||
placeholder="Annotation (optional)"
|
||||
trim
|
||||
max-rows="4"
|
||||
></b-textarea>
|
||||
max-rows="4"></b-textarea>
|
||||
|
||||
<StatelessTags class="mt-2" v-model="tags" />
|
||||
</div>
|
||||
@@ -115,8 +108,7 @@ either through the props, and make updates through the events -->
|
||||
:valid="valid"
|
||||
:dirty="dirty"
|
||||
@save="save"
|
||||
@revert="revert"
|
||||
/>
|
||||
@revert="revert" />
|
||||
</div>
|
||||
|
||||
<div class="details">
|
||||
|
||||
@@ -8,15 +8,14 @@
|
||||
@update:dsc="onUpdate"
|
||||
@delete="onDelete"
|
||||
@undelete="onUndelete"
|
||||
@unhide="onUnhide"
|
||||
/>
|
||||
@unhide="onUnhide" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DscUI from "./DscUI";
|
||||
import { DatasetCollection } from "../../model";
|
||||
import { deleteDatasetCollection, updateContentFields } from "../../model/queries";
|
||||
import { cacheContent } from "../../caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="description">
|
||||
{{ dsc.collectionType | localize }} of {{ dsc.totalElements }}
|
||||
<b v-if="isHomogeneous">{{ homogeneousDatatype }} </b>datasets
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DatasetCollection } from "../../model/DatasetCollection";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
dsc: { type: DatasetCollection, required: true },
|
||||
},
|
||||
computed: {
|
||||
/** @return {Boolean} */
|
||||
isHomogeneous() {
|
||||
return this.dsc.isHomogeneous;
|
||||
},
|
||||
/** @return {String} */
|
||||
homogeneousDatatype() {
|
||||
return this.dsc.homogeneousDatatype;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -8,8 +8,7 @@
|
||||
title="View Dataset Collection Details"
|
||||
@click.stop.prevent="backboneRoute(collectionDetailsPath)"
|
||||
variant="link"
|
||||
class="px-1"
|
||||
>
|
||||
class="px-1">
|
||||
</IconButton>
|
||||
<IconButton
|
||||
v-if="notIn(STATES.DISCARDED)"
|
||||
@@ -18,8 +17,7 @@
|
||||
:disabled="dsc.deleted || isIn(STATES.UPLOAD, STATES.NEW)"
|
||||
@click.stop="backboneRoute('collection/edit/' + dsc.hdca_id)"
|
||||
variant="link"
|
||||
class="px-1 dsc-edit-view"
|
||||
/>
|
||||
class="px-1 dsc-edit-view" />
|
||||
<b-dropdown v-if="notIn(STATES.DISCARDED)" no-caret right variant="link" size="sm" boundary="window">
|
||||
<template v-slot:button-content>
|
||||
<Icon icon="trash" variant="link" />
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
:id="typedId"
|
||||
:data-state="dsc.state"
|
||||
@keydown.arrow-right.self.stop="$emit('viewCollection')"
|
||||
@keydown.space.self.stop.prevent="$emit('update:selected', !selected)"
|
||||
>
|
||||
@keydown.space.self.stop.prevent="$emit('update:selected', !selected)">
|
||||
<nav class="content-top-menu p-1 d-flex cursor-pointer">
|
||||
<div class="d-flex flex-grow-1 overflow-hidden">
|
||||
<div class="pl-1" v-if="showSelection">
|
||||
@@ -17,16 +16,14 @@
|
||||
class="selector"
|
||||
:checked="selected"
|
||||
@click.stop
|
||||
@change="$emit('update:selected', $event)"
|
||||
/>
|
||||
@change="$emit('update:selected', $event)" />
|
||||
</div>
|
||||
|
||||
<StatusIcon
|
||||
v-if="dsc.state != 'ok'"
|
||||
class="status-icon px-1"
|
||||
:state="dsc.state"
|
||||
@click.stop="onStatusClick"
|
||||
/>
|
||||
@click.stop="onStatusClick" />
|
||||
|
||||
<IconButton
|
||||
v-if="!dsc.visible"
|
||||
@@ -34,8 +31,7 @@
|
||||
state="hidden"
|
||||
title="Unhide"
|
||||
icon="eye-slash"
|
||||
@click.stop="$emit('unhide')"
|
||||
/>
|
||||
@click.stop="$emit('unhide')" />
|
||||
|
||||
<IconButton
|
||||
v-if="dsc.deleted"
|
||||
@@ -43,26 +39,14 @@
|
||||
state="deleted"
|
||||
title="Undelete"
|
||||
icon="trash-restore"
|
||||
@click.stop="$emit('undelete')"
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
class="px-1"
|
||||
state="ok"
|
||||
title="Collection"
|
||||
icon="folder"
|
||||
@click.stop="$emit('viewCollection')"
|
||||
variant="link"
|
||||
/>
|
||||
@click.stop="$emit('undelete')" />
|
||||
|
||||
<div class="content-title title flex-grow-1 overflow-hidden" @click.stop="$emit('viewCollection')">
|
||||
<h5 class="text-truncate">
|
||||
<span class="hid">{{ dsc.hid }}</span>
|
||||
<span class="name">{{ dsc.name }}</span>
|
||||
<span class="description">
|
||||
({{ dsc.collectionType | localize }} {{ dsc.collectionCountDescription | localize }})
|
||||
</span>
|
||||
</h5>
|
||||
<DscDescription :dsc="dsc" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,6 +70,7 @@
|
||||
import { DatasetCollection } from "../../model/DatasetCollection";
|
||||
import StatusIcon from "../../StatusIcon";
|
||||
import JobStateProgress from "./JobStateProgress";
|
||||
import DscDescription from "./DscDescription";
|
||||
import DscMenu from "./DscMenu";
|
||||
import { Nametag } from "components/Nametags";
|
||||
import IconButton from "components/IconButton";
|
||||
@@ -97,6 +82,7 @@ export default {
|
||||
DscMenu,
|
||||
Nametag,
|
||||
IconButton,
|
||||
DscDescription,
|
||||
},
|
||||
props: {
|
||||
dsc: { type: DatasetCollection, required: true },
|
||||
|
||||
+2
-4
@@ -4,8 +4,7 @@
|
||||
<DatasetProvider
|
||||
v-if="contentItem.element_type === 'hda'"
|
||||
:id="contentItem.object.id"
|
||||
v-slot="{ item, loading }"
|
||||
>
|
||||
v-slot="{ item, loading }">
|
||||
<div>
|
||||
<loading-span v-if="loading" message="Loading datasets" />
|
||||
<DatasetUIWrapper v-else :item="item" :element_identifier="contentItem.element_identifier">
|
||||
@@ -15,8 +14,7 @@
|
||||
<DatasetCollectionUIWrapper
|
||||
v-if="contentItem.element_type === 'dataset_collection'"
|
||||
:item="contentItem"
|
||||
:element_count="collectionContents.length + 1"
|
||||
>
|
||||
:element_count="collectionContents.length + 1">
|
||||
</DatasetCollectionUIWrapper>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-4
@@ -2,10 +2,8 @@ import DatasetCollectionUIWrapper from "./DatasetCollectionUIWrapper";
|
||||
import DscUI from "components/History/ContentItem/DatasetCollection/DscUI";
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import flushPromises from "flush-promises";
|
||||
import datasetCollectionRaw from "components/History/test/json/DatasetCollection.json";
|
||||
import datasetCollectionContent from "components/History/test/json/DatasetCollection.nested.json";
|
||||
|
||||
jest.mock("components/History/caching");
|
||||
import datasetCollectionRaw from "components/providers/History/test/json/DatasetCollection.json";
|
||||
import datasetCollectionContent from "components/providers/History/test/json/DatasetCollection.nested.json";
|
||||
|
||||
describe("DatasetUIWrapper.vue with Dataset", () => {
|
||||
let wrapper;
|
||||
|
||||
+2
-3
@@ -10,8 +10,7 @@
|
||||
@hide="onHide(datasetCollection)"
|
||||
@unhide="onUnhide(datasetCollection)"
|
||||
@delete="onDelete(datasetCollection, $event)"
|
||||
@undelete="onUndelete(datasetCollection)"
|
||||
/>
|
||||
@undelete="onUndelete(datasetCollection)" />
|
||||
<DatasetCollectionContentProvider v-if="expand" :id="datasetCollection.contents_url" v-slot="{ item, loading }">
|
||||
<b-spinner v-if="loading">Loading Dataset Collection...</b-spinner>
|
||||
<DatasetCollectionContents v-else :collection-contents="item" />
|
||||
@@ -20,7 +19,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { deleteDatasetCollection, updateContentFields } from "../../model/queries";
|
||||
import { cacheContent } from "../../caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
import { DatasetCollection } from "../../model/DatasetCollection";
|
||||
import DscUI from "components/History/ContentItem/DatasetCollection/DscUI";
|
||||
import { DatasetCollectionContentProvider } from "components/providers";
|
||||
|
||||
+1
-3
@@ -1,9 +1,7 @@
|
||||
import DatasetUIWrapper from "./DatasetUIWrapper";
|
||||
import DatasetUI from "components/History/ContentItem/Dataset/DatasetUI";
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import raw from "components/History/test/json/Dataset.json";
|
||||
|
||||
jest.mock("components/History/caching");
|
||||
import raw from "components/providers/History/test/json/Dataset.json";
|
||||
|
||||
describe("DatasetUIWrapper.vue with Dataset", () => {
|
||||
let wrapper;
|
||||
|
||||
@@ -11,15 +11,14 @@
|
||||
@delete="onDelete"
|
||||
@undelete="onUndelete"
|
||||
@unhide="onUnhide"
|
||||
@update="onUpdate"
|
||||
>
|
||||
@update="onUpdate">
|
||||
</DatasetUI>
|
||||
</template>
|
||||
<script>
|
||||
import DatasetUI from "components/History/ContentItem/Dataset/DatasetUI";
|
||||
import { Dataset } from "../../model";
|
||||
import { deleteContent, updateContentFields } from "../../model/queries";
|
||||
import { cacheContent } from "../../caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
@@ -10,13 +10,12 @@ cache first to see if we already have the data -->
|
||||
:dataset="dataset"
|
||||
:writable="false"
|
||||
:selectable="false"
|
||||
@update:expanded="onExpand"
|
||||
/>
|
||||
@update:expanded="onExpand" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Dataset } from "../model";
|
||||
import { getContentByTypeId, cacheContent } from "../caching";
|
||||
import { getContentByTypeId, cacheContent } from "components/providers/History/caching";
|
||||
import { getContentDetails } from "../model/queries";
|
||||
import DatasetUI from "./Dataset/DatasetUI";
|
||||
|
||||
|
||||
@@ -7,22 +7,19 @@
|
||||
icon="check-square"
|
||||
:disabled="!totalMatches"
|
||||
:pressed="hasSelection"
|
||||
@click="toggleSelectAll"
|
||||
/>
|
||||
@click="toggleSelectAll" />
|
||||
<IconButton
|
||||
title="Filter History Content"
|
||||
icon="filter"
|
||||
:disabled="!totalMatches"
|
||||
:pressed="showFilter"
|
||||
@click="showFilter = !showFilter"
|
||||
data-description="content filter toggle"
|
||||
/>
|
||||
data-description="content filter toggle" />
|
||||
<IconButton
|
||||
title="Collapse Expanded Items"
|
||||
icon="compress"
|
||||
:disabled="!expandedCount"
|
||||
@click="$emit('collapseAllContent')"
|
||||
/>
|
||||
@click="$emit('collapseAllContent')" />
|
||||
</b-button-group>
|
||||
|
||||
<b-button-group>
|
||||
@@ -31,8 +28,7 @@
|
||||
size="sm"
|
||||
text="Selection"
|
||||
:disabled="!hasSelection"
|
||||
data-description="selected content menu"
|
||||
>
|
||||
data-description="selected content menu">
|
||||
<b-dropdown-text id="history-op-selected-content">
|
||||
<span v-localize v-if="hasSelection">With {{ numSelected }} selected items...</span>
|
||||
<span v-localize v-else>You don't have any selected content.</span>
|
||||
@@ -57,40 +53,35 @@
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-selected-content"
|
||||
v-b-modal:purge-selected-content
|
||||
:disabled="!hasSelection"
|
||||
>
|
||||
:disabled="!hasSelection">
|
||||
<span v-localize>Permanently Delete</span>
|
||||
</b-dropdown-item>
|
||||
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-selected-content"
|
||||
@click="buildDatasetList"
|
||||
data-description="build list"
|
||||
>
|
||||
data-description="build list">
|
||||
<span v-localize>Build Dataset List</span>
|
||||
</b-dropdown-item>
|
||||
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-selected-content"
|
||||
@click="buildDatasetPair"
|
||||
data-description="build pair"
|
||||
>
|
||||
data-description="build pair">
|
||||
<span v-localize>Build Dataset Pair</span>
|
||||
</b-dropdown-item>
|
||||
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-selected-content"
|
||||
@click="buildListOfPairs"
|
||||
data-description="build list of pairs"
|
||||
>
|
||||
data-description="build list of pairs">
|
||||
<span v-localize>Build List of Dataset Pairs</span>
|
||||
</b-dropdown-item>
|
||||
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-selected-content"
|
||||
@click="buildCollectionFromRules"
|
||||
data-description="build collection from rules"
|
||||
>
|
||||
data-description="build collection from rules">
|
||||
<span v-localize>Build Collection from Rules</span>
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
@@ -100,8 +91,7 @@
|
||||
size="sm"
|
||||
text="History"
|
||||
:disabled="!totalMatches"
|
||||
data-description="history action menu"
|
||||
>
|
||||
data-description="history action menu">
|
||||
<b-dropdown-text id="history-op-all-content">
|
||||
<span v-localize>With entire history...</span>
|
||||
</b-dropdown-text>
|
||||
@@ -109,8 +99,7 @@
|
||||
<b-dropdown-item
|
||||
aria-describedby="history-op-all-content"
|
||||
@click="iframeRedirect('/dataset/copy_datasets')"
|
||||
data-description="copy datasets"
|
||||
>
|
||||
data-description="copy datasets">
|
||||
<span v-localize>Copy Datasets</span>
|
||||
</b-dropdown-item>
|
||||
|
||||
@@ -172,7 +161,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { SearchParams } from "./model/SearchParams";
|
||||
import { SearchParams } from "components/providers/History/SearchParams";
|
||||
import { History } from "./model/History";
|
||||
import {
|
||||
hideSelectedContent,
|
||||
@@ -185,7 +174,7 @@ import {
|
||||
purgeAllDeletedContent,
|
||||
} from "./model";
|
||||
import { createDatasetCollection } from "./model/queries";
|
||||
import { cacheContent } from "./caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
import { legacyNavigationMixin } from "components/plugins/legacyNavigation";
|
||||
import { buildCollectionModal } from "./adapters/buildCollectionModal";
|
||||
import ContentFilters from "./ContentFilters";
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<section>
|
||||
<nav class="d-flex justify-content-end">
|
||||
<b-button-group>
|
||||
<IconButton
|
||||
v-if="isRoot"
|
||||
class="mb-2 mx-3"
|
||||
icon="download"
|
||||
title="Download Collection"
|
||||
:href="downloadCollectionUrl"
|
||||
download />
|
||||
</b-button-group>
|
||||
</nav>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IconButton from "components/IconButton";
|
||||
|
||||
export default {
|
||||
components: { IconButton },
|
||||
props: {
|
||||
isRoot: { type: Boolean, required: true },
|
||||
collection: { type: Object, required: true },
|
||||
},
|
||||
computed: {
|
||||
/** @return {String} */
|
||||
downloadCollectionUrl() {
|
||||
return `${this.collection.url}/download`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -7,9 +7,7 @@
|
||||
{{ dscName || "(Collection Name)" }}
|
||||
</h3>
|
||||
<p class="mt-1">
|
||||
<i class="fas fa-folder"></i>
|
||||
a {{ dsc.collectionType | localize }}
|
||||
{{ dsc.collectionCount | localize }}
|
||||
<DscDescription :dsc="dsc" />
|
||||
</p>
|
||||
|
||||
<div v-if="isEditing" class="mt-3" @keydown.esc="revertAndCancel" data-description="edit form">
|
||||
@@ -18,8 +16,7 @@
|
||||
placeholder="Collection Name"
|
||||
trim
|
||||
max-rows="4"
|
||||
data-description="name input"
|
||||
></b-textarea>
|
||||
data-description="name input"></b-textarea>
|
||||
<StatelessTags v-model="tags" class="mt-3 tags" />
|
||||
</div>
|
||||
|
||||
@@ -37,8 +34,7 @@
|
||||
:valid="valid"
|
||||
:dirty="dirty"
|
||||
@save="save"
|
||||
@revert="revert"
|
||||
/>
|
||||
@revert="revert" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -47,12 +43,14 @@ import { DatasetCollection } from "../model";
|
||||
import { Nametag } from "components/Nametags";
|
||||
import EditorMenu from "../EditorMenu";
|
||||
import { StatelessTags } from "components/Tags";
|
||||
import DscDescription from "components/History/ContentItem/DatasetCollection/DscDescription";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Nametag,
|
||||
EditorMenu,
|
||||
StatelessTags,
|
||||
DscDescription,
|
||||
},
|
||||
props: {
|
||||
dsc: { type: DatasetCollection, required: true },
|
||||
|
||||
@@ -6,20 +6,19 @@
|
||||
<ExpandedItems
|
||||
:scope-key="selectedCollection.id"
|
||||
:get-item-key="(item) => item.type_id"
|
||||
v-slot="{ isExpanded, setExpanded }"
|
||||
>
|
||||
v-slot="{ isExpanded, setExpanded }">
|
||||
<Layout class="dataset-collection-panel">
|
||||
<template v-slot:globalNav>
|
||||
<TopNav :history="history" :selected-collections="selectedCollections" v-on="$listeners" />
|
||||
</template>
|
||||
|
||||
<template v-slot:localNav>
|
||||
<IconButton
|
||||
icon="download"
|
||||
title="Download Collection"
|
||||
:href="downloadCollectionUrl"
|
||||
download
|
||||
/>
|
||||
<!-- Empty -->
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<template v-slot:listcontrols>
|
||||
<CollectionOperations :collection="selectedCollection" :is-root="isRoot" />
|
||||
</template>
|
||||
|
||||
<template v-slot:details>
|
||||
@@ -32,8 +31,7 @@
|
||||
:class="{ loadingBackground: loading }"
|
||||
v-bind="payload"
|
||||
@scroll="setScrollPos"
|
||||
:debug="false"
|
||||
>
|
||||
:debug="false">
|
||||
<template v-slot="{ item, index, rowKey }">
|
||||
<CollectionContentItem
|
||||
:item="item"
|
||||
@@ -45,8 +43,7 @@
|
||||
@update:expanded="setExpanded(item, $event)"
|
||||
@viewCollection="$emit('viewCollection', item)"
|
||||
:data-index="index"
|
||||
:data-row-key="rowKey"
|
||||
/>
|
||||
:data-row-key="rowKey" />
|
||||
</template>
|
||||
</Scroller>
|
||||
</template>
|
||||
@@ -59,17 +56,18 @@
|
||||
<script>
|
||||
import { History } from "../model";
|
||||
import { updateContentFields } from "../model/queries";
|
||||
import { cacheContent } from "../caching";
|
||||
import { cacheContent } from "components/providers/History/caching";
|
||||
|
||||
import { DscProvider, CollectionContentProvider, ExpandedItems } from "../providers";
|
||||
import { DscProvider, CollectionContentProvider } from "components/providers/History";
|
||||
import ExpandedItems from "../ExpandedItems";
|
||||
import Layout from "../Layout";
|
||||
import TopNav from "./TopNav";
|
||||
import CollectionOperations from "./CollectionOperations.vue";
|
||||
import Details from "./Details";
|
||||
import Scroller from "../Scroller";
|
||||
import { CollectionContentItem } from "../ContentItem";
|
||||
|
||||
import { reportPayload } from "../providers/ContentProvider/helpers";
|
||||
import IconButton from "components/IconButton";
|
||||
import { reportPayload } from "components/providers/History/ContentProvider/helpers";
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
@@ -84,7 +82,7 @@ export default {
|
||||
Scroller,
|
||||
CollectionContentItem,
|
||||
ExpandedItems,
|
||||
IconButton,
|
||||
CollectionOperations,
|
||||
},
|
||||
props: {
|
||||
history: { type: History, required: true },
|
||||
@@ -97,7 +95,7 @@ export default {
|
||||
return selected;
|
||||
},
|
||||
isRoot() {
|
||||
return this.selectedCollection == this.selectedCollections[0];
|
||||
return this.selectedCollection == this.rootCollection;
|
||||
},
|
||||
writable() {
|
||||
return this.isRoot;
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
text="Return to..."
|
||||
boundary="viewport"
|
||||
data-description="collection breadcrumbs menu"
|
||||
no-caret
|
||||
>
|
||||
no-caret>
|
||||
<template v-slot:button-content>
|
||||
<Icon icon="arrow-up" class="mr-1" />
|
||||
<b class="text-nowrap" v-localize>Return to...</b>
|
||||
@@ -27,8 +26,7 @@
|
||||
size="sm"
|
||||
title="`Return to: ${history.name}`"
|
||||
@click="close"
|
||||
data-description="back to history"
|
||||
>
|
||||
data-description="back to history">
|
||||
<Icon icon="arrow-up" class="mr-1" />
|
||||
<b class="text-nowrap">Return to: {{ history.name }}</b>
|
||||
</b-button>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
v-on="handlers"
|
||||
:histories="histories"
|
||||
:current-history="currentHistory"
|
||||
title="Histories"
|
||||
/>
|
||||
title="Histories" />
|
||||
</template>
|
||||
</HistoryPanel>
|
||||
|
||||
@@ -21,7 +20,7 @@
|
||||
|
||||
<script>
|
||||
import CurrentUser from "components/providers/CurrentUser";
|
||||
import UserHistories from "./providers/UserHistories";
|
||||
import UserHistories from "components/providers/History/UserHistories";
|
||||
import HistoryPanel from "./HistoryPanel";
|
||||
import HistoriesMenu from "./HistoriesMenu";
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
:pressed="editing"
|
||||
icon="pen"
|
||||
@click="$emit('update:editing', !editing)"
|
||||
data-description="editor toggle"
|
||||
/>
|
||||
data-description="editor toggle" />
|
||||
|
||||
<template v-if="editing">
|
||||
<!-- save -->
|
||||
@@ -17,8 +16,7 @@
|
||||
:class="{ disabled: !valid }"
|
||||
icon="save"
|
||||
@click="$emit('save')"
|
||||
data-description="editor save button"
|
||||
/>
|
||||
data-description="editor save button" />
|
||||
|
||||
<!-- revert -->
|
||||
<IconButton
|
||||
@@ -27,8 +25,7 @@
|
||||
:class="{ disabled: !dirty }"
|
||||
icon="undo"
|
||||
@click="$emit('revert')"
|
||||
data-description="editor revert button"
|
||||
/>
|
||||
data-description="editor revert button" />
|
||||
|
||||
<!-- form status -->
|
||||
<IconButton
|
||||
@@ -37,8 +34,7 @@
|
||||
:class="{ valid: valid, disabled: !valid }"
|
||||
:icon="valid ? 'check' : 'exclamation-triangle'"
|
||||
variant="link"
|
||||
data-description="editor status"
|
||||
/>
|
||||
data-description="editor status" />
|
||||
</template>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { saveSet, loadSet } from "./setCache";
|
||||
import { saveSet, loadSet } from "utils/setCache";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -9,8 +9,7 @@
|
||||
:text="title | l"
|
||||
toggle-class="text-decoration-none"
|
||||
class="histories-operation-menu"
|
||||
data-description="histories operation menu"
|
||||
>
|
||||
data-description="histories operation menu">
|
||||
<template v-slot:button-content>
|
||||
<Icon fixed-width class="mr-1" icon="folder" />
|
||||
<span class="text-nowrap">{{ title | l }}</span>
|
||||
@@ -39,8 +38,7 @@
|
||||
|
||||
<b-dropdown-item
|
||||
data-description="switch to multi history view"
|
||||
@click="redirect('/history/view_multiple')"
|
||||
>
|
||||
@click="redirect('/history/view_multiple')">
|
||||
<Icon fixed-width class="mr-1" icon="columns" />
|
||||
<span v-localize>Show Histories Side-by-Side</span>
|
||||
</b-dropdown-item>
|
||||
@@ -58,8 +56,7 @@
|
||||
id="history-selector-modal"
|
||||
:histories="histories"
|
||||
:current-history="currentHistory"
|
||||
@selectHistory="$emit('setCurrentHistory', $event)"
|
||||
/>
|
||||
@selectHistory="$emit('setCurrentHistory', $event)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
:disable-poll="false"
|
||||
:debug="false"
|
||||
:debounce-period="500"
|
||||
v-slot="{ loading, payload, manualReload, setScrollPos }"
|
||||
>
|
||||
v-slot="{ loading, payload, manualReload, setScrollPos }">
|
||||
<ExpandedItems
|
||||
:scope-key="history.id"
|
||||
:get-item-key="(item) => item.type_id"
|
||||
v-slot="{ expandedCount, isExpanded, setExpanded, collapseAll }"
|
||||
>
|
||||
v-slot="{ expandedCount, isExpanded, setExpanded, collapseAll }">
|
||||
<SelectedItems
|
||||
:scope-key="history.id"
|
||||
:get-item-key="(item) => item.type_id"
|
||||
@@ -23,8 +21,7 @@
|
||||
isSelected,
|
||||
setSelected,
|
||||
resetSelection,
|
||||
}"
|
||||
>
|
||||
}">
|
||||
<Layout>
|
||||
<template v-slot:globalNav>
|
||||
<slot name="globalNav" :history="history"></slot>
|
||||
@@ -56,8 +53,7 @@
|
||||
@selectAllContent="selectItems(payload.contents)"
|
||||
@manualReload="manualReload"
|
||||
:expanded-count="expandedCount"
|
||||
@collapseAllContent="collapseAll"
|
||||
/>
|
||||
@collapseAllContent="collapseAll" />
|
||||
</template>
|
||||
|
||||
<template v-slot:listing>
|
||||
@@ -69,8 +65,7 @@
|
||||
key-field="hid"
|
||||
v-bind="payload"
|
||||
:debug="false"
|
||||
@scroll="setScrollPos"
|
||||
>
|
||||
@scroll="setScrollPos">
|
||||
<template v-slot="{ item, index, rowKey }">
|
||||
<HistoryContentItem
|
||||
:item="item"
|
||||
@@ -84,8 +79,7 @@
|
||||
@viewCollection="$emit('viewCollection', item)"
|
||||
:data-hid="item.hid"
|
||||
:data-index="index"
|
||||
:data-row-key="rowKey"
|
||||
/>
|
||||
:data-row-key="rowKey" />
|
||||
</template>
|
||||
</Scroller>
|
||||
</template>
|
||||
@@ -100,8 +94,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { History, SearchParams } from "./model";
|
||||
import { HistoryContentProvider, ExpandedItems, SelectedItems } from "./providers";
|
||||
import { History } from "./model";
|
||||
import { SearchParams } from "components/providers/History/SearchParams";
|
||||
import { HistoryContentProvider } from "components/providers/History/";
|
||||
import ExpandedItems from "./ExpandedItems";
|
||||
import SelectedItems from "./SelectedItems";
|
||||
import Layout from "./Layout";
|
||||
import HistoryMessages from "./HistoryMessages";
|
||||
import HistoryDetails from "./HistoryDetails";
|
||||
@@ -110,7 +107,7 @@ import ContentOperations from "./ContentOperations";
|
||||
import ToolHelpModal from "./ToolHelpModal";
|
||||
import Scroller from "./Scroller";
|
||||
import { HistoryContentItem } from "./ContentItem";
|
||||
import { reportPayload } from "./providers/ContentProvider/helpers";
|
||||
import { reportPayload } from "components/providers/History/ContentProvider/helpers";
|
||||
import HistoryMenu from "./HistoryMenu";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -26,8 +26,7 @@ Emit new History model object when done via .sync syntax
|
||||
placeholder="History Name"
|
||||
trim
|
||||
max-rows="4"
|
||||
data-description="name input"
|
||||
></b-textarea>
|
||||
data-description="name input"></b-textarea>
|
||||
|
||||
<b-textarea
|
||||
class="mb-2"
|
||||
@@ -35,8 +34,7 @@ Emit new History model object when done via .sync syntax
|
||||
placeholder="Annotation (optional)"
|
||||
trim
|
||||
max-rows="4"
|
||||
data-description="annotation input"
|
||||
></b-textarea>
|
||||
data-description="annotation input"></b-textarea>
|
||||
|
||||
<StatelessTags class="mt-3 tags" v-model="tags" />
|
||||
</div>
|
||||
@@ -51,8 +49,7 @@ Emit new History model object when done via .sync syntax
|
||||
:valid="valid"
|
||||
:dirty="dirty"
|
||||
@save="save"
|
||||
@revert="revert"
|
||||
/>
|
||||
@revert="revert" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
class="history-dropdown font-weight-bold"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
aria-expanded="false">
|
||||
{{ history.name }}
|
||||
</b-link>
|
||||
<div class="dropdown-menu" aria-labelledby="history-dropdown">
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
variant="link"
|
||||
text="Histories"
|
||||
toggle-class="text-decoration-none"
|
||||
data-description="history menu"
|
||||
>
|
||||
data-description="history menu">
|
||||
<template v-slot:button-content>
|
||||
<Icon fixed-width icon="cog" />
|
||||
<span class="sr-only">Operations on the current history</span>
|
||||
@@ -82,8 +81,7 @@
|
||||
id="history-privacy-modal"
|
||||
title="Make History Private"
|
||||
title-tag="h2"
|
||||
@ok="$emit('secureHistory', history)"
|
||||
>
|
||||
@ok="$emit('secureHistory', history)">
|
||||
<p v-localize>
|
||||
This will make all the data in this history private (excluding library datasets), and will set
|
||||
permissions such that all new data is created as private. Any datasets within that are currently shared
|
||||
@@ -99,8 +97,7 @@
|
||||
id="purge-history-modal"
|
||||
title="Permanently Delete History?"
|
||||
title-tag="h2"
|
||||
@ok="$emit('purgeHistory', history)"
|
||||
>
|
||||
@ok="$emit('purgeHistory', history)">
|
||||
<p v-localize>Really delete the current history permanently? This cannot be undone.</p>
|
||||
</b-modal>
|
||||
|
||||
|
||||
@@ -6,20 +6,16 @@ selected datset collections -->
|
||||
v-if="history && !breadcrumbs.length"
|
||||
:history="history"
|
||||
v-on="$listeners"
|
||||
@viewCollection="drillDown"
|
||||
>
|
||||
@viewCollection="drillDown">
|
||||
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
|
||||
<slot :name="name" v-bind="slotData" :history="history" />
|
||||
</template>
|
||||
</HistoryComponent>
|
||||
|
||||
<CurrentCollection
|
||||
v-else-if="breadcrumbs.length"
|
||||
:history="history"
|
||||
:selected-collections.sync="breadcrumbs"
|
||||
@viewCollection="drillDown"
|
||||
/>
|
||||
|
||||
@viewCollection="drillDown" />
|
||||
<div v-else>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
:current-page="currentPage"
|
||||
@filtered="onFiltered"
|
||||
@row-clicked="switchToHistory"
|
||||
sticky-header="50vh"
|
||||
>
|
||||
sticky-header="50vh">
|
||||
<template v-slot:cell(tags)="row">
|
||||
<!-- just display tags, don't allow editing -->
|
||||
<stateless-tags :value="row.item.tags" :disabled="true" />
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
:selectable="true"
|
||||
select-mode="single"
|
||||
selected-variant="success"
|
||||
@row-selected="switchToHistory"
|
||||
>
|
||||
@row-selected="switchToHistory">
|
||||
<template v-slot:cell(tags)="row">
|
||||
<stateless-tags :value="row.item.tags" :disabled="true" />
|
||||
</template>
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
v-for="(item, index) in itemWindow"
|
||||
:key="getItemKey(item)"
|
||||
:data-row-index="index"
|
||||
:data-row-key="getItemKey(item)"
|
||||
>
|
||||
:data-row-key="getItemKey(item)">
|
||||
<slot :item="item" :index="index" :row-key="getItemKey(item)">
|
||||
<pre>{{ item }}</pre>
|
||||
</slot>
|
||||
@@ -25,8 +24,7 @@
|
||||
ref="scrollSliderContainer"
|
||||
class="scrollSliderContainer"
|
||||
:style="scrollSliderContainerStyles"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
@scroll="onScroll">
|
||||
<div ref="scrollSlider"></div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +38,7 @@
|
||||
|
||||
<script>
|
||||
import { debounce } from "lodash";
|
||||
import { SearchParams } from "./model";
|
||||
import { SearchParams } from "components/providers/History/SearchParams";
|
||||
import { clamp } from "utils/math";
|
||||
|
||||
const clean = (o) => JSON.parse(JSON.stringify(o));
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
:icon="stateIcon"
|
||||
:variant="variant"
|
||||
v-on="$listeners"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
v-bind="$attrs" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user