diff --git a/.env.sample b/.env.sample
index 9d4cb5a54..94f4a336b 100644
--- a/.env.sample
+++ b/.env.sample
@@ -1,137 +1,43 @@
-# Default values are optimized for production to avoid having to configure
-# much in production.
-#
-# However it should be easy to get going in development too. If you see an
-# uncommented option that means it's either mandatory to set or it's being
-# overwritten in development to make your life easier.
+##################### UI configuration ####################
+RAILS_ENV=development
+SITE=Testportal
+ORG=LIRMM
+ORG_URL=http://www.lirmm.fr
-# Enable BuildKit by default:
-# https://docs.docker.com/develop/develop-images/build_enhancements
-export DOCKER_BUILDKIT=1
+UI_URL=http://localhost:3000
+API_URL=http://localhost:9393
+API_KEY=
-# Rather than use the directory name, let's control the name of the project.
-export COMPOSE_PROJECT_NAME=ontoportal-docker
+UI_THEME=ontoportal
-# In development we want all services to start but in production you don't
-# need the asset watchers to run since assets get built into the image.
-#
-# You can even choose not to run postgres and redis in prod if you plan to use
-# managed cloud services. Everything "just works", even optional depends_on!
-#export COMPOSE_PROFILES=postgres,redis,web,worker,cable
-export COMPOSE_PROFILES=db,cache,assets,web
+BIOMIXER_URL=
+BIOMIXER_APIKEY=
-# If you're running native Linux and your uid:gid isn't 1000:1000 you can set
-# these to match your values before you build your image. You can check what
-# your uid:gid is by running `id` from your terminal.
-#export UID=1000
-#export GID=1000
+ANNOTATOR_URL=
-# You can generate a more secure secret by running: ./run rails secret
-export SECRET_KEY_BASE=insecure_key_for_dev
+FAIRNESS_DISABLED=false
+FAIRNESS_URL=
-# Which environment is running? These should be "development" or "production".
-#export RAILS_ENV=production
-#export NODE_ENV=production
-export RAILS_ENV=development
-export NODE_ENV=development
+NCBO_ANNOTATORPLUS_ENABLED=false
+NCBO_ANNOTATOR_URL=
+NCBO_API_KEY=
-# The bind port for puma.
-#
-# Be warned that if you change this value you'll need to change 8000 in both
-# your Dockerfile and in a few spots in docker-compose.yml due to the nature of
-# how this value can be set (Docker Compose doesn't support nested ENV vars).
-#export PORT=8000
+SUPPORT_EMAIL=sifrportal-support@lirmm.fr
+RELEASE_VERSION="OntoPortal Appliance 3.0.1"
-# How many workers and threads should your app use? WEB_CONCURRENCY defaults
-# to the server's CPU count * 2. That is a good starting point. In development
-# it's a good idea to use 1 to avoid race conditions when debugging.
-#export WEB_CONCURRENCY=
-#export RAILS_MAX_THREADS=5
-#export WEB_CONCURRENCY=1
-#export RAILS_MAX_THREADS=1
+ANALYTICS_ID=
+USE_RECAPTCHA=false
+#################### Buidling the API for running tests ####################
+## An ontology that will be imported in the starting of the API server
+STARTER_ONTOLOGY=STY
+## API key of a remote API used to download the starter ontology
+OP_API_KEY=8b5b7825-538d-40e0-9e9e-5ab9274a9aeb
+## API url of the remote API used to download the starter ontology
+OP_API_URL="https://data.bioontology.org"
-# You'll always want to set POSTGRES_USER and POSTGRES_PASSWORD since the
-# postgres Docker image uses them for its default database user and password.
-export POSTGRES_USER=hello
-export POSTGRES_PASSWORD=password
-#export POSTGRES_DB=hello
-#export POSTGRES_HOST=postgres
-#export POSTGRES_PORT=5432
+## Image repositroy from which the ontoportal api will be built
+API_IMAGE_REPOSITORY=agroportal
+## Image tag/version from which the ontoportal api will be built
+API_IMAGE_TAG=master
-# What's your full Redis connection URL? This will be used for caching, Sidekiq,
-# and Action Cable. You can always split them up later.
-#export REDIS_URL=redis://redis:6379/1
-# The bind port for puma but for Action Cable.
-#
-# Be warned that if you change this value you'll need to change 28080 in a few
-# spots in docker-compose.yml due to the nature of how this value can be set
-# (Docker Compose doesn't support nested ENV vars).
-#export CABLE_PORT=28080
-
-# The Action Cable address that will be accessible over HTTP. In production
-# you would typically have this reverse proxied to a sub-domain with nginx, in
-# which case you would set something like: ws://cable.example.com
-#
-# This is one case where it defaults to a development value because it's not
-# possible for me to know what domain name you'll be using.
-#export ACTION_CABLE_FRONTEND_URL=ws://localhost:28080
-
-# Comma separated list of RegExp origins to allow connections from for Action
-# Cable. The values will be converted into a proper RegExp, so omit the / /.
-#
-# Examples:
-# http:\/\/localhost*
-# http:\/\/example.*,https:\/\/example.*
-#export ACTION_CABLE_ALLOWED_REQUEST_ORIGINS=http:\/\/localhost*
-
-# If this is set then Rails will serve files from public/ in production. You
-# probably don't want this behavior unless you're testing prod mode locally,
-# because nginx would typically serve static files.
-#export RAILS_SERVE_STATIC_FILES=
-
-# Should Docker restart your containers if they go down in unexpected ways?
-#export DOCKER_RESTART_POLICY=unless-stopped
-export DOCKER_RESTART_POLICY=no
-
-# What health check test command do you want to run? In development, having it
-# curl your web server will result in a lot of log spam, so setting it to
-# /bin/true is an easy way to make the health check do basically nothing.
-#export DOCKER_WEB_HEALTHCHECK_TEST=curl localhost:8000/up
-export DOCKER_WEB_HEALTHCHECK_TEST=/bin/true
-
-# What ip:port should be published back to the Docker host for the app server?
-# If you're using Docker Toolbox or a custom VM you can't use 127.0.0.1. This
-# is being overwritten in dev to be compatible with more dev environments.
-#
-# If you have a port conflict because something else is using 8000 then you
-# can either stop that process or change 8000 to be something else.
-#
-# Use the default in production to avoid having puma directly accessible to
-# the internet since it'll very likely be behind nginx or a load balancer.
-#export DOCKER_WEB_PORT_FORWARD=127.0.0.1:8000
-export DOCKER_WEB_PORT_FORWARD=127.0.0.1:3000
-
-# This is the same as above except for Action Cable.
-#export DOCKER_CABLE_PORT_FORWARD=127.0.0.1:28080
-export DOCKER_CABLE_PORT_FORWARD=28080
-
-# What volume path should be used? In dev we want to volume mount everything
-# so that we can develop our code without rebuilding our Docker images.
-#export DOCKER_WEB_VOLUME=./public:/app/public
-
-
-export DOCKER_WEB_VOLUME=.:/app
-
-# What CPU and memory constraints will be added to your services? When left at
-# 0 they will happily use as much as needed.
-# export DOCKER_POSTGRES_CPUS=0
-# export DOCKER_POSTGRES_MEMORY=0
-# export DOCKER_REDIS_CPUS=0
-# export DOCKER_REDIS_MEMORY=0
-# export DOCKER_WEB_CPUS=0
-# export DOCKER_WEB_MEMORY=0
-# export DOCKER_WORKER_CPUS=0
-# export DOCKER_WORKER_MEMORY=0
-# export DOCKER_CABLE_CPUS=0
-# export DOCKER_CABLE_MEMORY=0
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index b94686e9d..916bd6cc4 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -9,6 +9,7 @@
# GH_PAT - github Personal Access Token for accessing private config repo
#
# SSH_JUMPHOST - ssh jump/proxy host though which deployments have to though if UI nodes live on private network.
+# SSH_JUMPHOST_USER - username to use to connect to the ssh jump/proxy.
#
# DEPLOY_ENC_KEY - key for decrypting deploymnet ssh key residing in config/
# this SSH key is used for accessing jump host, UI nodes, and private github repo.
@@ -17,26 +18,27 @@ name: Capistrano Deployment
# Controls when the action will run.
on:
push:
- branches: [ development staging ]
+ branches: [ stage test]
# Allows running this workflow manually from the Actions tab
workflow_dispatch:
inputs:
BRANCH:
description: 'Branch/tag to deploy'
options:
- - development
- - staging
+ - stage
+ - test
- master
- default: staging
+ default: test
required: true
environment:
description: 'target environment to deploy to'
type: choice
options:
- - development
- staging
- production
- default: staging
+ - appliance
+ - test
+ default: test
jobs:
deploy:
runs-on: ubuntu-latest
@@ -55,6 +57,13 @@ jobs:
USER_INPUT_ENVIRONMENT=${{ inputs.environment }}
echo "TARGET=${USER_INPUT_ENVIRONMENT:-staging}" >> $GITHUB_ENV
+
+ CONFIG_REPO=${{ secrets.CONFIG_REPO }}
+ GH_PAT=${{ secrets.GH_PAT }}
+ echo "PRIVATE_CONFIG_REPO=https://${GH_PAT}@github.com/${CONFIG_REPO}" >> $GITHUB_ENV
+
+ echo "SSH_JUMPHOST=${{ secrets.SSH_JUMPHOST }}" >> $GITHUB_ENV
+ echo "SSH_JUMPHOST_USER=${{ secrets.SSH_JUMPHOST_USER }}" >> $GITHUB_ENV
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
@@ -69,6 +78,13 @@ jobs:
path: deploy_config
- name: copy-deployment-config
run: cp -r deploy_config/ontoportal_web_ui/${{ inputs.environment }}/* .
+ # add ssh hostkey so that capistrano doesn't complain
+ - name: Add jumphost's hostkey to Known Hosts
+ run: |
+ mkdir -p ~/.ssh
+ echo "${{ secrets.SSH_JUMPHOST }}"
+ ssh-keyscan -H ${{ secrets.SSH_JUMPHOST }} > ~/.ssh/known_hosts
+ shell: bash
- uses: miloserdow/capistrano-deploy@master
with:
target: ${{ env.TARGET }} # which environment to deploy
diff --git a/.github/workflows/docker-image-arm.yml b/.github/workflows/docker-image-arm.yml
new file mode 100644
index 000000000..0de876c29
--- /dev/null
+++ b/.github/workflows/docker-image-arm.yml
@@ -0,0 +1,56 @@
+name: Docker branch Images build - ARM version
+
+on:
+ push:
+ branches:
+ - development
+ - stage
+ - test
+ release:
+ types: [ published ]
+jobs:
+ push_to_registry:
+ name: Push Docker branch image to Docker Hub
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v3
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: |
+ agroportal/ontoportal_web_ui-arm
+ ghcr.io/${{ github.repository }}-arm
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v4
+ with:
+ context: .
+ platforms: linux/arm64
+ build-args: |
+ RUBY_VERSION=2.7.8
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}-${{ env.BRANCH_NAME }}-arm64
+ labels: ${{ steps.meta.outputs.labels }}
+
diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml
new file mode 100644
index 000000000..5d2de1123
--- /dev/null
+++ b/.github/workflows/docker-image.yml
@@ -0,0 +1,55 @@
+name: Docker branch Images build
+
+on:
+ push:
+ branches:
+ - development
+ - stage
+ - test
+ release:
+ types: [ published ]
+jobs:
+ push_to_registry:
+ name: Push Docker branch image to Docker Hub
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v3
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: |
+ agroportal/ontoportal_web_ui
+ ghcr.io/${{ github.repository }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v4
+ with:
+ context: .
+ platforms: linux/amd64
+ build-args: |
+ RUBY_VERSION=2.7.8
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
diff --git a/.github/workflows/tests-real-data-stageportal.yml b/.github/workflows/tests-real-data-stageportal.yml
new file mode 100644
index 000000000..53a9d112d
--- /dev/null
+++ b/.github/workflows/tests-real-data-stageportal.yml
@@ -0,0 +1,52 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+name: "Run remote API (stageportal) tests CI"
+
+on:
+ push:
+ pull_request:
+ types: [ opened, reopened ]
+env:
+ API_URL: https://data.stageportal.lirmm.fr/ # or ${{ secrets.API_URL }}
+ API_KEY: 1de0a270-29c5-4dda-b043-7c3580628cd5 # public apikey or ${{ secrets.API_KEY }}
+ BIOMIXER_URL: ${{ secrets.BIOMIXER_URL }}
+ FAIRNESS_URL: ${{ secrets.FAIRNESS_URL }}
+ ANNOTATOR_URL: ${{ secrets.ANNOTATOR_URL }}
+ DB_HOST: 127.0.0.1
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ services:
+ mysql:
+ image: mysql:8.0
+ ports:
+ - "3306:3306"
+ env:
+ MYSQL_ROOT_PASSWORD: root
+ memcached:
+ image: memcached:1.6
+ ports:
+ - 11211:11211
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ # Add or replace dependency steps here
+ - name: Install Ruby and gems
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7.8
+ bundler-cache: true
+ # Add or replace database setup steps here
+ - name: set up config file
+ run: cp config/database.yml.sample config/database.yml
+ - name: Set up database schema
+ run: RAILS_ENV=test bin/rails db:setup
+ - name: Set up yarn
+ run: yarn install
+ # Add or replace test runners here
+ - name: Run tests
+ run: RAILS_ENV=test bin/rails test test/controllers/* -v
\ No newline at end of file
diff --git a/.github/workflows/tests-real-data-testportal.yml b/.github/workflows/tests-real-data-testportal.yml
new file mode 100644
index 000000000..baa017f4e
--- /dev/null
+++ b/.github/workflows/tests-real-data-testportal.yml
@@ -0,0 +1,52 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+name: "Run remote API (testportal) tests CI"
+
+on:
+ push:
+ pull_request:
+ types: [ opened, reopened ]
+env:
+ API_URL: https://data.testportal.lirmm.fr/ # or ${{ secrets.API_URL }}
+ API_KEY: 1de0a270-29c5-4dda-b043-7c3580628cd5 # public apikey or ${{ secrets.API_KEY }}
+ BIOMIXER_URL: ${{ secrets.BIOMIXER_URL }}
+ FAIRNESS_URL: ${{ secrets.FAIRNESS_URL }}
+ ANNOTATOR_URL: ${{ secrets.ANNOTATOR_URL }}
+ DB_HOST: 127.0.0.1
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ services:
+ mysql:
+ image: mysql:8.0
+ ports:
+ - "3306:3306"
+ env:
+ MYSQL_ROOT_PASSWORD: root
+ memcached:
+ image: memcached:1.6
+ ports:
+ - 11211:11211
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ # Add or replace dependency steps here
+ - name: Install Ruby and gems
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7.8
+ bundler-cache: true
+ # Add or replace database setup steps here
+ - name: set up config file
+ run: cp config/database.yml.sample config/database.yml
+ - name: Set up database schema
+ run: RAILS_ENV=test bin/rails db:setup
+ - name: Set up yarn
+ run: yarn install
+ # Add or replace test runners here
+ - name: Run tests
+ run: RAILS_ENV=test bin/rails test test/controllers/* -v
\ No newline at end of file
diff --git a/.github/workflows/tests-system.yml b/.github/workflows/tests-system.yml
new file mode 100644
index 000000000..8da36c9e6
--- /dev/null
+++ b/.github/workflows/tests-system.yml
@@ -0,0 +1,65 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+name: "Run system tests CI"
+
+on:
+ push:
+ pull_request:
+ types: [ opened, reopened ]
+env:
+ API_URL: http://localhost:9393
+ REMOTE_API_KEY: 8b5b7825-538d-40e0-9e9e-5ab9274a9aeb
+ REMOTE_API_URL: https://data.bioontology.org
+ BIOMIXER_URL: ${{ secrets.BIOMIXER_URL }}
+ FAIRNESS_URL: ${{ secrets.FAIRNESS_URL }}
+ ANNOTATOR_URL: ${{ secrets.ANNOTATOR_URL }}
+ DB_HOST: 127.0.0.1
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ services:
+ mysql:
+ image: mysql:8.0
+ ports:
+ - "3306:3306"
+ env:
+ MYSQL_ROOT_PASSWORD: root
+ memcached:
+ image: memcached:1.6
+ ports:
+ - 11211:11211
+ chrome-server:
+ image: selenium/standalone-chrome:112.0-chromedriver-112.0-grid-4.9.0-20230421
+ options: "--shm-size=2g"
+ ports:
+ - "4444:4444"
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ # Add or replace dependency steps here
+ - name: Install Ruby and gems
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7.8
+ bundler-cache: true
+
+ - name: Run OntoPortal API
+ run: bin/run_api -k ${{ env.REMOTE_API_KEY }} -r agroportal -t master -s STY -u ${{ env.REMOTE_API_URL }}
+
+ # Add or replace database setup steps here
+ - name: set up config file
+ run: cp config/database.yml.sample config/database.yml
+ - name: Set up database schema
+ run: RAILS_ENV=test bin/rails db:setup
+ - name: Set up yarn
+ run: yarn install
+ # Add or replace test runners here
+ - name: Run integration tests
+ run: |
+ CI=true RAILS_ENV=test bin/rails assets:precompile
+ CI=true RAILS_ENV=test bin/rails test -v test/system/*
\ No newline at end of file
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 000000000..9214bc4de
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,61 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+name: "Run local API tests CI"
+
+on:
+ push:
+ pull_request:
+ types: [ opened, reopened ]
+env:
+ API_URL: http://localhost:9393
+ REMOTE_API_KEY: 8b5b7825-538d-40e0-9e9e-5ab9274a9aeb
+ REMOTE_API_URL: https://data.bioontology.org
+ BIOMIXER_URL: ${{ secrets.BIOMIXER_URL }}
+ FAIRNESS_URL: ${{ secrets.FAIRNESS_URL }}
+ ANNOTATOR_URL: ${{ secrets.ANNOTATOR_URL }}
+ DB_HOST: 127.0.0.1
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ services:
+ mysql:
+ image: mysql:8.0
+ ports:
+ - "3306:3306"
+ env:
+ MYSQL_ROOT_PASSWORD: root
+ memcached:
+ image: memcached:1.6
+ ports:
+ - 11211:11211
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ # Add or replace dependency steps here
+ - name: Install Ruby and gems
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.7.8
+ bundler-cache: true
+
+ - name: Run OntoPortal API
+ run: bin/run_api -k ${{ env.REMOTE_API_KEY }} -r agroportal -t master -s STY -u ${{ env.REMOTE_API_URL }}
+
+ # Add or replace database setup steps here
+ - name: set up config file
+ run: cp config/database.yml.sample config/database.yml
+ - name: Set up database schema
+ run: RAILS_ENV=test bin/rails db:setup
+ - name: Set up yarn
+ run: yarn install
+ # Add or replace test runners here
+ - name: Run tests
+ run: COVERAGE=true RAILS_ENV=test bin/rails test -v
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 4ce7bb4e4..06f40b993 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,5 +54,4 @@ docker-sync.yml
/config/credentials/development.key
/config/credentials/test.key
/config/credentials/staging.key
-/config/credentials/appliance.key
-
+/config/credentials/appliance.key
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 88f019fdb..3d5c45f1b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,50 +1,49 @@
-FROM ruby:2.7.5-alpine AS app
-
+# Make sure it matches the Ruby version in .ruby-version and Gemfile
+ARG RUBY_VERSION=3.2.0
+FROM ruby:${RUBY_VERSION}-alpine
+
+# Install libvips for Active Storage preview support
+RUN apk add --no-cache build-base \
+ libxml2-dev \
+ libxslt-dev \
+ mariadb-dev \
+ git \
+ tzdata \
+ nodejs yarn \
+ less \
+ bash \
+ docker \
+ docker-compose \
+ && mkdir /node_modules
+
+# Rails app lives here
WORKDIR /app
-ARG UID=1000
-ARG GID=1000
-
-RUN apk add --no-cache \
- build-base \
- libxml2-dev \
- libxslt-dev \
- mariadb-dev \
- git \
- nodejs \
- tzdata \
- yarn \
- less \
- && addgroup --gid ${GID} ruby \
- && adduser -u ${UID} -G ruby -D ruby \
- && chown ruby:ruby -R /app \
- && mkdir /node_modules \
- && chown ruby:ruby -R /node_modules /app
-
-USER ruby
-
-COPY --chown=ruby:ruby bin/ ./bin
-RUN chmod 0755 bin/*
-
+# Set production environment
ARG RAILS_ENV="production"
+ARG BUNDLE_WITHOUT="development test"
+
+ENV RAILS_LOG_TO_STDOUT="1" \
+ RAILS_SERVE_STATIC_FILES="true" \
+ RAILS_ENV="${RAILS_ENV}" \
+ BUNDLE_PATH=/usr/local/bundle \
+ BUNDLE_WITHOUT="${BUNDLE_WITHOUT}"
+
+RUN gem update --system 3.4.22 # the 3.4.22 can be removed if we support Ruby version > 3.0
-ENV RAILS_ENV="${RAILS_ENV}" \
- NODE_ENV="${NODE_ENV}" \
- PATH="${PATH}:/home/ruby/.local/bin:/node_modules/.bin" \
- USER="ruby" \
- BUNDLE_PATH=/usr/local/bundle
+COPY . .
-COPY --chown=ruby:ruby Gemfile* ./
-RUN bundle install --jobs "$(nproc)"
-RUN gem install rails
+RUN bundle install
+RUN yarn install && yarn build
-RUN echo "--modules-folder /node_modules" > .yarnrc
-COPY --chown=ruby:ruby package.json *yarn* ./
-RUN yarn install
+# Precompile bootsnap code for faster boot times
+RUN bundle exec bootsnap precompile --gemfile app/ lib/
+# RUN SECRET_KEY_BASE_DUMMY="1" ./bin/rails assets:precompile
+ENV BINDING="0.0.0.0"
EXPOSE 3000
-CMD ["sh"]
\ No newline at end of file
+CMD ["bash"]
\ No newline at end of file
diff --git a/README b/README
deleted file mode 100644
index 0d6affddc..000000000
--- a/README
+++ /dev/null
@@ -1,182 +0,0 @@
-== Welcome to Rails
-
-Rails is a web-application and persistence framework that includes everything
-needed to create database-backed web-applications according to the
-Model-View-Control pattern of separation. This pattern splits the view (also
-called the presentation) into "dumb" templates that are primarily responsible
-for inserting pre-built data in between HTML tags. The model contains the
-"smart" domain objects (such as Account, Product, Person, Post) that holds all
-the business logic and knows how to persist themselves to a database. The
-controller handles the incoming requests (such as Save New Account, Update
-Product, Show Post) by manipulating the model and directing data to the view.
-
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
-
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
-
-
-== Getting started
-
-1. At the command prompt, start a new rails application using the rails command
- and your application name. Ex: rails myapp
- (If you've downloaded rails in a complete tgz or zip, this step is already done)
-2. Change directory into myapp and start the web server: script/server (run with --help for options)
-3. Go to http://localhost:3000/ and get "Welcome aboard: You’re riding the Rails!"
-4. Follow the guidelines to start developing your application
-
-
-== Web Servers
-
-By default, Rails will try to use Mongrel and lighttpd if they are installed, otherwise
-Rails will use the WEBrick, the webserver that ships with Ruby. When you run script/server,
-Rails will check if Mongrel exists, then lighttpd and finally fall back to WEBrick. This ensures
-that you can always get up and running quickly.
-
-Mongrel is a Ruby-based webserver with a C-component (which requires compilation) that is
-suitable for development and deployment of Rails applications. If you have Ruby Gems installed,
-getting up and running with mongrel is as easy as: gem install mongrel.
-More info at: http://mongrel.rubyforge.org
-
-If Mongrel is not installed, Rails will look for lighttpd. It's considerably faster than
-Mongrel and WEBrick and also suited for production use, but requires additional
-installation and currently only works well on OS X/Unix (Windows users are encouraged
-to start with Mongrel). We recommend version 1.4.11 and higher. You can download it from
-http://www.lighttpd.net.
-
-And finally, if neither Mongrel or lighttpd are installed, Rails will use the built-in Ruby
-web server, WEBrick. WEBrick is a small Ruby web server suitable for development, but not
-for production.
-
-But of course its also possible to run Rails on any platform that supports FCGI.
-Apache, LiteSpeed, IIS are just a few. For more information on FCGI,
-please visit: http://wiki.rubyonrails.com/rails/pages/FastCGI
-
-
-== Debugging Rails
-
-Have "tail -f" commands running on the server.log and development.log. Rails will
-automatically display debugging and runtime information to these files. Debugging
-info will also be shown in the browser on requests from 127.0.0.1.
-
-
-== Breakpoints
-
-Breakpoint support is available through the script/breakpointer client. This
-means that you can break out of execution at any point in the code, investigate
-and change the model, AND then resume execution! Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.find(:all)
- breakpoint "Breaking out from the list"
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the breakpointer window. Here you can do things like:
-
-Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint'
-
- >> @posts.inspect
- => "[#nil, \"body\"=>nil, \"id\"=>\"1\"}>,
- #\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
- >> @posts.first.title = "hello from a breakpoint"
- => "hello from a breakpoint"
-
-...and even better is that you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you press CTRL-D
-
-
-== Console
-
-You can interact with the domain model by starting the console through script/console.
-Here you'll have all parts of the application configured, just like it is when the
-application is running. You can inspect domain models, change values, and save to the
-database. Starting the script without arguments will launch it in the development environment.
-Passing an argument will specify a different environment, like script/console production.
-
-To reload your controllers and models after launching the console run reload!
-
-To reload your controllers and models after launching the console run reload!
-
-
-
-== Description of contents
-
-app
- Holds all the code that's specific to this particular application.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from ApplicationController
- which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb.
- Most models will descend from ActiveRecord::Base.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.rhtml for the WeblogsController#index action. All views use eRuby
- syntax.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the common
- header/footer method of wrapping views. In your views, define a layout using the
- layout :default and create a file named default.rhtml. Inside default.rhtml,
- call <% yield %> to render the view using this layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are generated
- for you automatically when using script/generate for controllers. Helpers can be used to
- wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database, and other dependencies.
-
-components
- Self-contained mini-applications that can bundle together controllers, models, and views.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all
- the sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when generated
- using rake doc:app
-
-lib
- Application specific libraries. Basically, any kind of custom code that doesn't
- belong under controllers, models, or helpers. This directory is in the load path.
-
-public
- The directory available for the web server. Contains subdirectories for images, stylesheets,
- and javascripts. Also contains the dispatchers and the default HTML files. This should be
- set as the DOCUMENT_ROOT of your web server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the script/generate scripts, template
- test files will be generated for you and placed in this directory.
-
-vendor
- External libraries that the application depends on. Also includes the plugins subdirectory.
- This directory is in the load path.
diff --git a/README.md b/README.md
index 33bdfb964..f3dd62b69 100644
--- a/README.md
+++ b/README.md
@@ -1,130 +1,40 @@
-bioportal_web_ui
-================
+# Run ontologies_web_ui
-A rails application for biological ontologies, see http://bioportal.bioontology.org/
+## Using OntoPortal UI utilities script
+### See help
-## Todo
-
-### Finir les metadata (grosse prio)
-
-#### Grosses tâches
-
-* Faire en sorte de bien récupèrer quand on a des array de metadata (en ajoutant les champs)
- * Faire une method générique (genre une class) qui permet de facilement distinguer les types de metadata (pas besoin d'ajouter les champs en dur dans le code)
-
-* Passer à bootstrap pour faire le joli layout?
- * Dans un premier temps import bootstrap seulement dans le form?
- * On pourrait faire des col pour ranger les metadata par "dates", "description", "links" dans des panels bootstrap
-
-* Meilleur affichage des metadata :
- * Bouton pour les valeurs qui reviennent tout le temps
-
-#### Plein de petits todo
-
-* Permettre de filtrer les ontos en fct des metadata
-Voir col P : https://docs.google.com/spreadsheets/d/1r1twxJvXdQXrkX0Ocis6YY08nlO5cGneCAQ5F7U_CoA/edit#gid=0
-Surtout dans les pages browse et welcome (voir les trucs en orange). Page Landscape plus tard
-
-Le but c'est d'avoir des résultats visibles
-
-* 3 blocks dans edit submission metadata
- * Origin
- * Toutes les prop qui ont la valeur S (colonne Q de docs.google Review of metadata prop) pour Simple
- * Toutes les prop qui ont la valeur C (colonne Q de docs.google Review of metadata prop) pour Complete
-
-
-**SEPARER License, onto hasSyntax, etc. Des meatdata de base de NCBO**
-
-**Change tout**
-* Premier bloc avec les metadata pas du tout extraites (formats, contact, file upload...)
-* 2eme bloc avec les metadata que le portal utilise: description, documentation...
-* Expliquer que quand on ajoute un fichier les metadata sont updatés avec les metadata contenues dans le fichier (après le bloc des metadata non extraites)a
-
-X Add contact > même type de bouton que Add new Language
-
-Petit ? quand tu le survoles on dit qu'on extrait normalement cette metadata de l'onto à partir de: list des metadata mappings
-Et on note "omv:description + rdfs:comment" quand on prend les valeurs de chaque propriété
-Trouver comment montrer qu'on prend omv:naturalLanguage plusieurs fois si remplis plusieurs fois
-
-Rassembler toutes les dates ensembles (au lieu de simple et complete) dans un même table
-
-X Attention date picker par défaut marche pas sur firefox (utiliser date picker de jQuery, celui used par NCBO)
-
-Mettre des espaces : HASCONTRIBUTOR & cie
-
-Afficher dans l'interface graphique quelle metadata on remplis par défaut (on les met toutes au même endroit ?)
-
-TODO list : mettre un champ text plus gros ? (comme description)
-
-Le but est d'éviter d'avoir un gros listing indigeste de metadata
-
-Exemple :
-Sous description ajouter bouton "voulez-vous ajouter un abstract?"
-Sous release date "voulez-vous ajouter d'autre dates"
-Sous contact "voulez-vous ajouter d'autres peoples" ?
-Sous publisher "voulez-vous ajouter d'autre rôle d'institut etc"
-
-Depiction et logo à côté l'un de l'autre
-
-Generalizes, HASDISJUNCTIONSWITH, et toutes les metadata de relations entre onto: faire en sorte de pouvoir choisir des ontos dans BioPortal (pitit popip)
-
-Dans Default Properties sur le spreadsheet des metadata elles sont groupées
-
-
-* Dans browse: permettre de trier dans l'ordre alphabétique
-* Ajouter des petits drapeaux à côté des naturalLang (dans browse et dans la page de présentation des submissions)
-
-* IncludedInDataCatalog: faudrait avoir des boutons plutôt (voir avec logo, pour les catalogs connus comme ontobee)
-
-* Handling des metadata plus propre et
-
-
-### Fermer les issues
-
-
-
-### Page Welcome
-
-https://github.com/sifrproject/bioportal_web_ui/issues/12
-https://github.com/agroportal/agroportal_web_ui/issues/59
-
-
-Dans links par exemple on peut mettre "need an ontology mapper: yamplusplus.lirmm.fr"
-
-Feed twitter: https://support.twitter.com/articles/20170071
-https://twitter.com/agrohackathon
-
-
-## Resolve problems
-
-* Ca lag beaucoup sur des ontos avec beaucoup de submissions (comme TRANSMAT sur AgroPortal)
-
-* En particulier quand on ajoute une nouvelle submission
-
-* Add New submission bug parfois (avec uploadFile) : faire des tests, s'il faut ça fait un moment que ça plante sans qu'on s'en rende compte (on utilise beaucoup l'URL en ce moment)
-```ruby
-TypeError (no implicit conversion of Symbol into Integer):
- app/controllers/submissions_controller.rb:28:in `[]'
- app/controllers/submissions_controller.rb:28:in `create'
-
-
-# Following line bugs
-if @errors[:error][:uploadFilePath] && @errors[:error][:uploadFilePath].first[:options]
-end
+```bash
+bin/ontoportal help
```
-## How to
-
-### Add a facet filter for a metadata in browse
-
-In 3 files :
-* app/views/ontologies/browse.html.erb
-* public/browse/app.js
-* app/controllers/ontologies_controller.rb
+```
+Usage: bin/ontoportal {dev|test|run|help} [--reset-cache] [--api-url API_URL] [--api-key API_KEY]
+ dev : Start the Ontoportal Web UI development server.
+ Example: bin/ontoportal dev --api-url http://localhost:9393 --api-key my_api_key
+ Use --reset-cache to remove volumes: bin/ontoportal dev --reset-cache
+ test : Run tests. Specify either a test file:line_number or empty for 'all'.
+ Example: $0 test test/integration/login_flows_test.rb:22
+ run : Run a command in the Ontoportal Web UI Docker container.
+ help : Show this help message.
+
+Description:
+ This script provides convenient commands for managing an Ontoportal Web UI
+ application using Docker Compose. It includes options for starting the development server,
+ running tests, and executing commands within the Ontoportal Web UI Docker container.
+
+Goals:
+ - Simplify common tasks related to Ontoportal Web UI development using Docker.
+ - Provide a consistent and easy-to-use interface for common actions.
+```
-## Log to production.log
+### Run dev
+```bash
+bin/ontoportal dev --api-url --api-key
+```
-```ruby
-Rails.logger.warn "Submission params: #{params[:submission]}"
+### Run test with a local OntoPortal API
+```bash
+bin/ontoportal test
```
+
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100644
index 3e1c15c81..000000000
--- a/README.rdoc
+++ /dev/null
@@ -1,261 +0,0 @@
-== Welcome to Rails
-
-Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Control pattern.
-
-This pattern splits the view (also called the presentation) into "dumb"
-templates that are primarily responsible for inserting pre-built data in between
-HTML tags. The model contains the "smart" domain objects (such as Account,
-Product, Person, Post) that holds all the business logic and knows how to
-persist themselves to a database. The controller handles the incoming requests
-(such as Save New Account, Update Product, Show Post) by manipulating the model
-and directing data to the view.
-
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
-
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
-
-
-== Getting Started
-
-1. At the command prompt, create a new Rails application:
- rails new myapp (where myapp is the application name)
-
-2. Change directory to myapp and start the web server:
- cd myapp; rails server (run with --help for options)
-
-3. Go to http://localhost:3000/ and you'll see:
- "Welcome aboard: You're riding Ruby on Rails!"
-
-4. Follow the guidelines to start developing your application. You can find
-the following resources handy:
-
-* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
-* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
-
-
-== Debugging Rails
-
-Sometimes your application goes wrong. Fortunately there are a lot of tools that
-will help you debug it and get it back on the rails.
-
-First area to check is the application log files. Have "tail -f" commands
-running on the server.log and development.log. Rails will automatically display
-debugging and runtime information to these files. Debugging info will also be
-shown in the browser on requests from 127.0.0.1.
-
-You can also log your own messages directly into the log file from your code
-using the Ruby logger class from inside your controllers. Example:
-
- class WeblogController < ActionController::Base
- def destroy
- @weblog = Weblog.find(params[:id])
- @weblog.destroy
- logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
- end
- end
-
-The result will be a message in your log file along the lines of:
-
- Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
-
-More information on how to use the logger is at http://www.ruby-doc.org/core/
-
-Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
-several books available online as well:
-
-* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
-* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
-
-These two books will bring you up to speed on the Ruby language and also on
-programming in general.
-
-
-== Debugger
-
-Debugger support is available through the debugger command when you start your
-Mongrel or WEBrick server with --debugger. This means that you can break out of
-execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install ruby-debug to run the server in debugging
-mode. With gems, use sudo gem install ruby-debug. Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.all
- debugger
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the server window. Here you can do things like:
-
- >> @posts.inspect
- => "[#nil, "body"=>nil, "id"=>"1"}>,
- #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
- >> @posts.first.title = "hello from a debugger"
- => "hello from a debugger"
-
-...and even better, you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you can enter "cont".
-
-
-== Console
-
-The console is a Ruby shell, which allows you to interact with your
-application's domain model. Here you'll have all parts of the application
-configured, just like it is when the application is running. You can inspect
-domain models, change values, and save to the database. Starting the script
-without arguments will launch it in the development environment.
-
-To start the console, run rails console from the application
-directory.
-
-Options:
-
-* Passing the -s, --sandbox argument will rollback any modifications
- made to the database.
-* Passing an environment name as an argument will load the corresponding
- environment. Example: rails console production.
-
-To reload your controllers and models after launching the console run
-reload!
-
-More information about irb can be found at:
-link:http://www.rubycentral.org/pickaxe/irb.html
-
-
-== dbconsole
-
-You can go to the command line of your database directly through rails
-dbconsole. You would be connected to the database with the credentials
-defined in database.yml. Starting the script without arguments will connect you
-to the development database. Passing an argument will connect you to a different
-database, like rails dbconsole production. Currently works for MySQL,
-PostgreSQL and SQLite 3.
-
-== Description of Contents
-
-The default directory structure of a generated Ruby on Rails application:
-
- |-- app
- | |-- assets
- | | |-- images
- | | |-- javascripts
- | | `-- stylesheets
- | |-- controllers
- | |-- helpers
- | |-- mailers
- | |-- models
- | `-- views
- | `-- layouts
- |-- config
- | |-- environments
- | |-- initializers
- | `-- locales
- |-- db
- |-- doc
- |-- lib
- | |-- assets
- | `-- tasks
- |-- log
- |-- public
- |-- script
- |-- test
- | |-- fixtures
- | |-- functional
- | |-- integration
- | |-- performance
- | `-- unit
- |-- tmp
- | `-- cache
- | `-- assets
- `-- vendor
- |-- assets
- | |-- javascripts
- | `-- stylesheets
- `-- plugins
-
-app
- Holds all the code that's specific to this particular application.
-
-app/assets
- Contains subdirectories for images, stylesheets, and JavaScript files.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from
- ApplicationController which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb. Models descend from
- ActiveRecord::Base by default.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.html.erb for the WeblogsController#index action. All views use
- eRuby syntax by default.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the
- common header/footer method of wrapping views. In your views, define a layout
- using the layout :default and create a file named default.html.erb.
- Inside default.html.erb, call <% yield %> to render the view using this
- layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are
- generated for you automatically when using generators for controllers.
- Helpers can be used to wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database,
- and other dependencies.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all the
- sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when
- generated using rake doc:app
-
-lib
- Application specific libraries. Basically, any kind of custom code that
- doesn't belong under controllers, models, or helpers. This directory is in
- the load path.
-
-public
- The directory available for the web server. Also contains the dispatchers and the
- default HTML files. This should be set as the DOCUMENT_ROOT of your web
- server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the rails generate
- command, template test files will be generated for you and placed in this
- directory.
-
-vendor
- External libraries that the application depends on. Also includes the plugins
- subdirectory. If the app has frozen rails, those gems also go here, under
- vendor/rails/. This directory is in the load path.
diff --git a/bin/dev b/bin/dev
index a1104a50b..a4e05fa14 100755
--- a/bin/dev
+++ b/bin/dev
@@ -1,9 +1,11 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
-if ! command -v foreman &> /dev/null
-then
+if ! gem list foreman -i --silent; then
echo "Installing foreman..."
gem install foreman
fi
-foreman start -f Procfile.dev "$@"
+# Default to port 3000 if not specified
+export PORT="${PORT:-3000}"
+
+exec foreman start -f Procfile.dev "$@"
diff --git a/bin/ontoportal b/bin/ontoportal
new file mode 100755
index 000000000..80f288cef
--- /dev/null
+++ b/bin/ontoportal
@@ -0,0 +1,213 @@
+#!/usr/bin/env bash
+
+# Function to display script usage information
+show_help() {
+ echo "Usage: $0 {dev|test|run|help} [--reset-cache] [--api-url API_URL] [--api-key API_KEY]"
+ echo " dev : Start the Ontoportal Web UI development server."
+ echo " Example: $0 dev --api-url http://localhost:9393 --api-key my_api_key"
+ echo " Use --reset-cache to remove volumes: $0 dev --reset-cache"
+ echo " test : Run tests. Specify either a test file:line_number or empty for 'all'."
+ echo " Example: $0 test test/integration/login_flows_test.rb:22 "
+ echo " run : Run a command in the Ontoportal Web UI Docker container."
+ echo " help : Show this help message."
+ echo
+ echo "Description:"
+ echo " This script provides convenient commands for managing an Ontoportal Web UI"
+ echo " application using Docker Compose. It includes options for starting the development server,"
+ echo " running tests, and executing commands within the Ontoportal Web UI Docker container."
+ echo
+ echo "Goals:"
+ echo " - Simplify common tasks related to Ontoportal Web UI development using Docker."
+ echo " - Provide a consistent and easy-to-use interface for common actions."
+}
+# Function to update or create the .env file with API_URL and API_KEY
+update_env_file() {
+ local api_url="$1"
+ local api_key="$2"
+
+ # Update the .env file with the provided values
+ file_content=$(<.env)
+
+ # Make changes to the variable
+ while IFS= read -r line; do
+ if [[ "$line" == "API_URL="* ]]; then
+ echo "API_URL=$api_url"
+ elif [[ "$line" == "API_KEY="* ]]; then
+ echo "API_KEY=$api_key"
+ else
+ echo "$line"
+ fi
+ done <<< "$file_content" > .env
+}
+
+# Function to create configuration files if they don't exist
+create_config_files() {
+ if [ ! -f ".env" ]; then
+ echo "Creating .env file from env.sample"
+ cp .env.sample .env
+ fi
+
+ if [ ! -f "config/bioportal_config_development.rb" ]; then
+ echo "Creating config/bioportal_config_development.rb file from config/bioportal_config_env.rb.sample"
+ cp config/bioportal_config_env.rb.sample config/bioportal_config_development.rb
+ fi
+
+ if [ ! -f "config/database.yml" ]; then
+ echo "Creating config/database.yml file from config/database.yml.sample"
+ cp config/database.yml.sample config/database.yml
+ fi
+}
+
+# Function to handle the "dev" option
+dev() {
+ echo "Starting Ontoportal Web UI development server..."
+
+
+ local reset_cache=false
+ local api_client_path=""
+ local api_url=""
+ local api_key=""
+
+ # Check for command line arguments
+ while [[ "$#" -gt 0 ]]; do
+ case $1 in
+ --api-client-path)
+ api_client_path="$2"
+ shift 2
+ ;;
+ --reset-cache)
+ reset_cache=true
+ shift
+ ;;
+ --api-url)
+ api_url="$2"
+ shift 2
+ ;;
+ --api-key)
+ api_key="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ show_help
+ exit 1
+ ;;
+ esac
+ done
+
+
+
+ # Check if arguments are provided
+ if [ -n "$api_url" ] && [ -n "$api_key" ]; then
+ # If arguments are provided, update the .env file
+ update_env_file "$api_url" "$api_key"
+ else
+ # If no arguments, fetch values from the .env file
+ source .env
+ api_url="$API_URL"
+ api_key="$API_KEY"
+ fi
+
+ if [ -z "$api_url" ] || [ -z "$api_key" ]; then
+ echo "Error: Missing required arguments. Please provide both --api-url and --api-key or update them in your .env"
+ exit 1
+ fi
+
+ # Check if --reset-cache is present and execute docker compose down --volumes
+ if [ "$reset_cache" = true ]; then
+ echo "Resetting cache. Running: docker compose down --volumes"
+ docker compose down --volumes
+ fi
+
+ local docker_run_cmd="docker compose run --rm -it"
+ local bash_cmd=""
+ # Conditionally add bind mounts only if the paths are not empty
+ for path_var in "api_client_path:ontologies_api_ruby_client" ; do
+ IFS=':' read -r path value <<< "$path_var"
+
+ if [ -n "${!path}" ]; then
+ host_path="$(realpath "$(dirname "${!path}")")/$value"
+ echo "Run: bundle config local.$value ${!path}"
+ container_path="/app/tmp/$value"
+ docker_run_cmd+=" -v $host_path:$container_path"
+ bash_cmd+="(bundle config local.ontologies_api_client $container_path) &&"
+ else
+ bash_cmd+=" (bundle config unset local.ontologies_api_client) &&"
+ fi
+ done
+ bash_cmd+=" (bundle check || bundle install || bundle update) && bin/rails db:prepare && bundle exec rails s -b 0.0.0.0 -p 3000"
+ docker_run_cmd+=" --service-ports rails bash -c \"$bash_cmd\""
+ echo "$docker_run_cmd"
+ echo "Run: bundle exec rails s -b 0.0.0.0 -p 3000"
+ eval "$docker_run_cmd"
+}
+
+# Function to handle the "test" option
+test() {
+
+
+ local api_url=""
+ local api_key=""
+ local test_options=""
+
+ # Check for command line arguments
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ --api-url)
+ shift
+ api_url="$1"
+ ;;
+ *)
+
+ if [ -z "$test_options" ]; then
+ test_options="$1"
+ else
+
+ test_options="$test_options $1"
+ fi
+ ;;
+ esac
+ shift
+ done
+
+ if [ -z "$api_url" ]; then
+ api_url=http://localhost:9393
+ echo "Running API..."
+ bin/run_api
+ fi
+
+ echo "Running tests..."
+ echo "Run: API_URL=$api_url bundle exec rails test -v $test_options"
+
+ docker compose run --rm -it test bash -c "bundle config unset local.ontologies_api_client && (bundle check || bundle install) && RAILS_ENV=test bin/rails db:prepare && API_URL=$api_url bundle exec rails test -v $test_options"
+
+ # echo "Stopping API..."
+ # bin/stop_api
+}
+
+# Function to handle the "run" option
+run() {
+ echo "Run: $*"
+ docker compose run --rm -it rails bash -c "$*"
+}
+
+create_config_files
+# Main script logic
+case "$1" in
+ "run")
+ run "${@:2}"
+ ;;
+ "dev")
+ dev "${@:2}"
+ ;;
+ "test")
+ test "${@:2}"
+ ;;
+ "help")
+ show_help
+ ;;
+ *)
+ show_help
+ exit 1
+ ;;
+esac
diff --git a/bin/run_api b/bin/run_api
new file mode 100755
index 000000000..8ed4d11dc
--- /dev/null
+++ b/bin/run_api
@@ -0,0 +1,69 @@
+#!/bin/bash
+display_help() {
+ echo "Usage: $0 [options]"
+ echo "Options:"
+ echo " -f Remove tmp/ontoportal_docker"
+ echo " -k API_KEY API key"
+ echo " -r REPOSITORY Image repository"
+ echo " -t TAG Image tag"
+ echo " -s ONTOLOGY Starter ontology"
+ echo " -u URL Remote API URL"
+ echo " -h Display this help message"
+ exit 0
+}
+
+
+env_file_path="$(realpath "$(dirname "$0")")/../.env"
+
+# Read and parse the .env file
+if [ -f "$env_file_path" ]; then
+ while IFS='=' read -r key value; do
+ [[ "$key" =~ ^\s*# ]] && continue # Skip commented lines
+ [[ "$value" ]] || continue # Skip lines without values
+ export "$key"="$value"
+ done < "$env_file_path"
+fi
+
+
+while getopts ":k:r:t:s:u:fh" opt; do
+ case $opt in
+ k) api_key="$OPTARG" ;;
+ r) image_repository="$OPTARG" ;;
+ t) image_tag="$OPTARG" ;;
+ s) starter_ontology="$OPTARG" ;;
+ u) remote_api_url="$OPTARG" ;;
+ f) rm -fr tmp/ontoportal_docker ;;
+ h) display_help ;;
+ \?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
+ :) echo "Option -$OPTARG requires an argument." >&2; exit 1 ;;
+ esac
+done
+
+
+
+if [ ! -d "tmp/ontoportal_docker" ]; then
+ git clone --depth=1 -b main https://github.com/ontoportal-lirmm/ontoportal_docker.git tmp/ontoportal_docker
+fi
+
+# If an option is not provided, check and use the corresponding value from the environment variables
+api_key="${api_key:-$OP_API_KEY}"
+image_repository="${image_repository:-$API_IMAGE_REPOSITORY}"
+image_tag="${image_tag:-$API_IMAGE_TAG}"
+starter_ontology="${starter_ontology:-$STARTER_ONTOLOGY}"
+remote_api_url="${remote_api_url:-$OP_API_URL}"
+
+if curl -sSf http://localhost:9393 > /dev/null 2>&1; then
+ echo "API is already running in http://localhost:9393"
+ exit 0
+fi
+
+# Check if the Docker Compose service exists
+docker compose ls -a --filter "name=ontoportal_docker" | grep -q "ontoportal_docker" && no_provision=true || no_provision=false
+(
+ cd tmp/ontoportal_docker || exit 1
+ command="./run -k $api_key -r $image_repository -t $image_tag -s $starter_ontology -u $remote_api_url"
+ [ "$no_provision" = true ] && command="$command --no-provision"
+ echo "Run: $command"
+ eval "$command"
+)
+
diff --git a/bin/stop_api b/bin/stop_api
new file mode 100755
index 000000000..31308b172
--- /dev/null
+++ b/bin/stop_api
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+# Check if the directory exists
+if [ -d "tmp/ontoportal_docker" ]; then
+ # Check if the container is running
+ if docker ps --filter "name=ontoportal_docker-api" --format "{{.Names}}" | grep -q "ontoportal_docker-api"; then
+ container_names=$(docker ps --filter "name=ontoportal_docker-api" --format "{{.Names}}")
+ docker stop "$container_names"
+ fi
+
+ cd "tmp/ontoportal_docker" && docker compose down --volumes
+fi
+
diff --git a/config/application.rb b/config/application.rb
index f13cb361a..d6796fca1 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -11,6 +11,11 @@ class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
+ # permitted locales available for the application
+ config.i18n.available_locales = [:en, :fr, :it, :de]
+ config.i18n.default_locale = :en
+
+
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
@@ -27,5 +32,9 @@ class Application < Rails::Application
config.change_request = config_for :change_request
config.generators.template_engine = :haml
+ config.generators.test_framework = nil
+
+ # Set the default layout to app/views/layouts/component_preview.html.erb
+ config.view_component.default_preview_layout = "component_preview"
end
end
diff --git a/config/bioportal_config_env.rb.sample b/config/bioportal_config_env.rb.sample
index 6ee1fe750..36b36682f 100644
--- a/config/bioportal_config_env.rb.sample
+++ b/config/bioportal_config_env.rb.sample
@@ -1,33 +1,15 @@
-# coding: utf-8
-
-#local IP address lookup. This doesn't make connection to external hosts
-require 'socket'
-def local_ip
- orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
-
- UDPSocket.open do |s|
- s.connect '8.8.8.8', 1 #google
- s.addr.last
- end
-ensure
- Socket.do_not_reverse_lookup = orig
-end
-
-$LOCAL_IP = local_ip
-
# Organization info
-$ORG = "NCBO"
-$ORG_URL = "http://www.bioontology.org"
+$ORG = ENV['ORG']
+$ORG_URL = ENV['ORG_URL']
# Site name (required)
-$SITE = "BioPortal"
-$SITE_URL = "localhost"
+$SITE = ENV['SITE']
# Full string for site, EX: "NCBO BioPortal", do not modify
-$ORG_SITE = ($ORG.nil? || $ORG.empty?) ? $SITE : "#{$ORG} #{$SITE}"
+$ORG_SITE = $ORG.nil? || $ORG.empty? ? $SITE : "#{$ORG} #{$SITE}"
# The URL for the BioPortal Rails UI (this application)
-$UI_URL = "http://localhost:3000"
+$UI_URL = ENV['UI_URL']
# DOI request service
$DATACITE_DOI_PREFIX
@@ -38,28 +20,32 @@ $DATACITE_PASSWORD
# If you are running a PURL server to provide URLs for ontologies in your BioPortal instance, enable this option
$PURL_ENABLED = false
-
# The PURL URL is generated using this prefix + the abbreviation for an ontology.
# The PURL URL generation algorithm can be altered in app/models/ontology_wrapper.rb
-$PURL_PREFIX = "http://purl.bioontology.org/ontology"
+$PURL_PREFIX = 'http://purl.bioontology.org/ontology'
+
# If your BioPortal installation includes Annotator set this to false
$ANNOTATOR_DISABLED = false
-
# Unique string representing the UI's id for use with the BioPortal Core
-$API_KEY = ""
-
+$API_KEY = ENV['API_KEY']
# BioPortal API service address
-$REST_URL = "http://example.org:8080/"
+$REST_URL = ENV['API_URL']
# Annotator REST service address
-#$ANNOTATOR_URL = "http://services.stageportal.lirmm.fr/annotator"
-$ANNOTATOR_URL = "#{$REST_URL}/annotator"
+# $ANNOTATOR_URL = "http://services.stageportal.lirmm.fr/annotator"
+$ANNOTATOR_URL = $PROXY_URL = ENV['ANNOTATOR_URL']
+# NCBO annotator URL and apikey
+$NCBO_ANNOTATORPLUS_ENABLED = ENV['NCBO_ANNOTATORPLUS_ENABLED']
+$NCBO_ANNOTATOR_URL = ENV['NCBO_ANNOTATOR_URL']
+$NCBO_API_KEY = ENV['NCBO_API_KEY']
+
+# Fairness Assessment.
+$FAIRNESS_DISABLED = ENV['FAIRNESS_DISABLED']
+$FAIRNESS_URL = ENV['FAIRNESS_URL']
+
+
-# Announcements sympa mailing list REQUEST address, EX: list-request@lists.example.org
-$ANNOUNCE_LIST_SERVICE ||= "SERVICE_EXAMPLE"
-$ANNOUNCE_SERVICE_HOST ||= "service@test.com"
-$ANNOUNCE_LIST||= "users-list@test"
# Used to define other bioportal that can be mapped to
# Example to map to ncbo bioportal : {"ncbo" => {"api" => "http://data.bioontology.org", "ui" => "http://bioportal.bioontology.org", "apikey" => ""}
@@ -67,6 +53,43 @@ $ANNOUNCE_LIST||= "users-list@test"
# Where "ncbo" is the namespace used as key in the interportal_hash
$INTERPORTAL_HASH = {}
+$NOT_DOWNLOADABLE = {}
+
+# Bugsnag API key for monitoring exception
+#$BUGSNAG_API_KEY=
+
+# OAuth2 authentication
+$OMNIAUTH_PROVIDERS = {
+ github: {
+ client_id: 'CLIENT_ID',
+ client_secret: 'CLIENT_SECRET',
+ icon: 'github.svg',
+ enable: true
+ },
+ google: {
+ strategy: :google_oauth2,
+ client_id: 'CLIENT_ID',
+ client_secret: 'CLIENT_SECRET',
+ icon: 'google.svg',
+ enable: true
+ },
+ orcid: {
+ client_id: 'CLIENT_SECRET',
+ client_secret: 'CLIENT_SECRET',
+ icon: 'orcid.svg',
+ enable: false
+ },
+ keycloak: {
+ strategy: :keycloak_openid,
+ client_id: 'YOUR_KEYCLOAK_CLIENT_ID',
+ client_secret: 'YOUR_KEYCLOAK_CLIENT_SECRET',
+ client_options: { site: 'KEYCLOAK_SITE', realm: 'KEYCLOAK_REALM' },
+ name: 'keycloak',
+ icon: 'keycloak.svg',
+ enable: false
+ }
+}.freeze
+
# Don't load and don't display recent mappings if false, in case of too many mappings (take longer to load homepage)
$DISPLAY_RECENT = false
@@ -75,69 +98,46 @@ $MULTIPLE_RECOGNIZERS = false
# Remove download for these ontologies. Default:
# ["CPT","ICD10","ICNP","ICPC2P","MDDB","MEDDRA","MSHFRE","MSHSPA_1","NDDF","NDFRT","NIC","RCD","SCTSPA","SNOMEDCT","WHO-ART"]
-$RESTRICTED_DOWNLOADS = ["MDRFRE", "WHO-ARTFRE", "MSHFRE", "CIM-10"]
+$RESTRICTED_DOWNLOADS = []
# Ontolobridge endpoint url
-$ONTOLOBRIDGE_BASE_URL = "https://ontolobridge.ccs.miami.edu/api-test/requests"
-
+$ONTOLOBRIDGE_BASE_URL = 'https://ontolobridge.ccs.miami.edu/api-test/requests'
# Ontolobridge authentication token
-$ONTOLOBRIDGE_AUTHENTICATION_TOKEN = "Token Uq2pae73ktMtmgjUgtnhEOuHxr9sZeuK"
+$ONTOLOBRIDGE_AUTHENTICATION_TOKEN = 'Token Uq2pae73ktMtmgjUgtnhEOuHxr9sZeuK'
# Ontologies for which to enable the new term request (Ontolobridge) tab
$NEW_TERM_REQUEST_ONTOLOGIES = []
# Legacy REST core service address (BioPortal v3.x and lower)
-$LEGACY_REST_URL = "http://example.org:8080/bioportal"
-
-# Max number of children to return when rendering a tree view
-$MAX_CHILDREN = 2500
-
-# Max number of children that it's possible to display (more than this is either too slow or not helpful to users)
-$MAX_POSSIBLE_DISPLAY = 10000
+$LEGACY_REST_URL = 'http://example.org:8080/bioportal'
# Release version text (appears in footer of all pages, except 404 and 500 errors)
-$RELEASE_VERSION = "4.24 (February 2016)"
+$RELEASE_VERSION = ENV['RELEASE_VERSION']
# Enable Slices, filtering of ontologies based on subdomain and ontology groups
$ENABLE_SLICES = false
# Google Analytics ID (optional)
-$ANALYTICS_ID = ""
-
-# A user id for user 'anonymous' for use when a user is required for an action on the REST service but you don't want to require a user to login
-$ANONYMOUS_USER = 0
-
-# Redis server to use for NCBO::Resolver
-$REDIS_HOST = ""
-$REDIS_PORT = 6379
-
-# Cube metrics reporting
-$ENABLE_CUBE = false
-$CUBE_HOST = "localhost"
-$CUBE_PORT = 1180
+$ANALYTICS_ID = ENV['ANALYTICS_ID']
# Enable client request caching
-$CLIENT_REQUEST_CACHING = false
-
-# If you don't use Airbrake you can have exceptions emailed to the $ERROR_EMAIL address by setting this to 'true'
-$EMAIL_EXCEPTIONS = false
+$CLIENT_REQUEST_CACHING = true
# Email settings
ActionMailer::Base.smtp_settings = {
- :address => "", # smtp server address, ex: smtp.example.org
- :port => 25, # smtp server port
- :domain => "", # fqdn of rails server, ex: rails.example.org
+ address: '', # smtp server address, ex: smtp.example.org
+ port: 25, # smtp server port
+ domain: '' # fqdn of rails server, ex: rails.example.org
}
-
# Announcements mailman mailing list REQUEST address, EX: list-request@lists.example.org
# NOTE: You must use the REQUEST address for the mailing list. ONLY WORKS WITH MAILMAN LISTS.
-$ANNOUNCE_LIST = "sifrportal-users@lirmm.fr"
-
+$ANNOUNCE_LIST = ENV['SUPPORT_EMAIL']
# Email addresses used for sending notifications (errors, feedback, support)
-$SUPPORT_EMAIL = "sifrportal-support@lirmm.fr"
-
+$SUPPORT_EMAIL = ENV['SUPPORT_EMAIL']
# Email used to send notifications
-$NOTIFICATION_EMAIL = "notifications@bioportal.lirmm.fr"
+$NOTIFICATION_EMAIL = ENV['SUPPORT_EMAIL']
+
+
# reCAPTCHA
# In order to use reCAPTCHA on the account creation and feedback submission pages:
@@ -150,32 +150,13 @@ $NOTIFICATION_EMAIL = "notifications@bioportal.lirmm.fr"
#
# 3. Set the USE_RECAPTCHA option to 'true'
ENV['USE_RECAPTCHA'] = 'false'
-
# Custom BioPortal logging
require 'log'
-$REMOTE_LOGGING = false
-
-##
-# Flex Options
-##
-
-# URL to pull Flex apps from
-$FLEX_URL = "/flex"
-
-# Flex App API keys
-$ANNOTATOR_FLEX_APIKEY = ""
-$SEARCH_FLEX_APIKEY = ""
-$RECOMMENDER_FLEX_APIKEY = ""
-$FLEXOVIZ_APIKEY = ""
# URL where BioMixer GWT app is located
-#$BIOMIXER_URL = "http://bioportal-integration.bio-mixer.appspot.com"
-$BIOMIXER_URL = "http://#{$SITE_URL}/BioMixer"
-
-# Array with all the additional ontology metadata to display in the ontology details
-$ADDITIONAL_ONTOLOGY_METADATA = ["naturalLanguage", "hasLicense", "notes", "modificationDate", "URI", "hasContributor", "hasCreator", "endorsedBy", "hasDomain",
- "keyClasses", "keywords", "isOfType", "knowUsage", "designedForOntologyTask", "hasFormalityLevel", "usedImports", "usedKnowledgeRepresentationParadigm",
- "usedOntologyEngineeringMethodology", "usedOntologyEngineeringTool"]
+# $BIOMIXER_URL = "http://bioportal-integration.bio-mixer.appspot.com"
+$BIOMIXER_URL = ENV['BIOMIXER_URL']
+$BIOMIXER_APIKEY = ENV['BIOMIXER_APIKEY']
##
# Custom Ontology Details
@@ -186,42 +167,150 @@ $ADDITIONAL_ONTOLOGY_METADATA = ["naturalLanguage", "hasLicense", "notes", "modi
##
$ADDITIONAL_ONTOLOGY_DETAILS = {}
-#Front notice appears on the front page only and is closable by the user. It remains closed for seven days (stored in cookie)
+# Front notice appears on the front page only and is closable by the user. It remains closed for seven days (stored in cookie)
$FRONT_NOTICE = ''
-
# Site notice appears on all pages and remains closed indefinitely. Stored below as a hash with a unique key and a string message
# EX: $SITE_NOTICE = { :unique_key => 'Put your message here (can include html if you use single quotes).' }
-$SITE_NOTICE = { }
-
-# Used in browse for facetted search to avoid having to call the API (for performance)
-$FORMALITY_LEVELS = {
- "http://w3id.org/nkos/nkostype#classification_schema" => "Classification scheme",
- "http://w3id.org/nkos/nkostype#dictionary" => "Dictionary",
- "http://w3id.org/nkos/nkostype#gazetteer" => "Gazetteer",
- "http://w3id.org/nkos/nkostype#glossary" => "Glossary",
- "http://w3id.org/nkos/nkostype#list" => "List",
- "http://w3id.org/nkos/nkostype#name_authority_list" => "Name authority list",
- "http://w3id.org/nkos/nkostype#ontology" => "Ontology",
- "http://w3id.org/nkos/nkostype#semantic_network" => "Semantic network",
- "http://w3id.org/nkos/nkostype#subject_heading_scheme" => "Subject heading scheme",
- "http://w3id.org/nkos/nkostype#synonym_ring" => "Synonym ring",
- "http://w3id.org/nkos/nkostype#taxonomy" => "Taxonomy",
- "http://w3id.org/nkos/nkostype#terminology" => "Terminology",
- "http://w3id.org/nkos/nkostype#thesaurus" => "Thesaurus"
-}
-$IS_OF_TYPE = {
- "http://omv.ontoware.org/2005/05/ontology#ApplicationOntology" => "Application Ontology",
- "http://omv.ontoware.org/2005/05/ontology#CoreOntology" => "Core Ontology",
- "http://omv.ontoware.org/2005/05/ontology#DomainOntology" => "Domain Ontology",
- "http://omv.ontoware.org/2005/05/ontology#TaskOntology" => "Task Ontology",
- "http://omv.ontoware.org/2005/05/ontology#UpperLevelOntology" => "Upper Level Ontology",
- "http://omv.ontoware.org/2005/05/ontology#Vocabulary" => "Vocabulary"
-}
-$NATURAL_LANGUAGES = {
- "http://lexvo.org/id/iso639-3/eng" => "English",
- "http://lexvo.org/id/iso639-3/fra" => "French",
- "http://lexvo.org/id/iso639-3/spa" => "Spanish",
- "http://lexvo.org/id/iso639-3/por" => "Portuguese",
- "http://lexvo.org/id/iso639-3/ita" => "Italian",
- "http://lexvo.org/id/iso639-3/deu" => "German"
+$SITE_NOTICE = {}
+
+$TERMS_AND_CONDITIONS_LINK = 'https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/terms-conditions-naDsDo2Zxq'
+$CITE_ANNOTATOR = 'https://hal.science/hal-00492024'
+$ANNOTATOR_API_DOC = 'https://data.agroportal.lirmm.fr/documentation#nav_annotator'
+$CITE_RECOMMENDER = 'https://doi.org/10.1186/s13326-017-0128-y'
+# Resource term
+$RESOURCE_TERM = ENV['RESOURCE_TERM'] || 'ontology'
+
+$HOME_PAGE_LOGOS = [
+ {
+ img_src: 'logos/supports/numev.png',
+ url: 'http://www.lirmm.fr/numev',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/supports/anr.png',
+ url: 'https://anr.fr/en',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/supports/eu.png',
+ url: 'https://commission.europa.eu/research-and-innovation_en',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/collaboration/d2kab.png',
+ url: 'http://d2kab.mystrikingly.com',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/collaboration/lirmm.png',
+ url: 'http://www.lirmm.fr',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/collaboration/inrae.png',
+ url: 'https://www.inrae.fr/enm',
+ target: '_blank'
+ },
+ {
+ img_src: 'logos/collaboration/stanford.png',
+ url: 'https://www.stanford.edu',
+ target: '_blank'
+ }
+]
+
+$PORTALS_INSTANCES = [
+ {
+ color: '#31b403',
+ portal: 'AgroPortal',
+ link: 'https://agroportal.lirmm.fr/'
+ },
+ {
+ color: '#234979',
+ portal: 'BioPortal',
+ link: 'https://bioportal.bioontology.org/'
+ },
+ {
+ color: '#74a9cb',
+ portal: 'SIFR BioPortal',
+ link: 'https://bioportal.lirmm.fr/'
+ },
+ {
+ color: '#0d508a',
+ portal: 'EcoPortal',
+ link: 'https://ecoportal.lifewatch.eu/'
+ },
+ {
+ color: '#234979',
+ portal: 'MedPortal',
+ link: 'http://medportal.bmicc.cn/'
+ },
+ {
+ color: '#009574',
+ portal: 'MatPortal',
+ link: 'https://matportal.org/'
+ },
+ {
+ color: '#1c0f5d',
+ portal: 'IndustryPortal',
+ link: 'http://industryportal.enit.fr'
+ },
+ {
+ color: '#1e2251',
+ portal: 'EarthPortal',
+ link: 'https://earthportal.eu/'
+ },
+ {
+ color: '#33691B',
+ portal: 'BiodivPortal',
+ link: 'https://biodivportal.gfbio.org/'
+ }
+]
+
+$FOOTER_LINKS = {
+ social: [
+ { logo: "social/people.svg", link: "https://github.com/orgs/agroportal/people" },
+ { logo: "social/github.svg", link: "https://github.com/agroportal" },
+ { logo: "social/twitter.svg", link: "https://twitter.com/lagroportal" },
+ { logo: "json.svg", link: $REST_URL },
+ { logo: "summary/sparql.svg", link: "#{$SPARQL_URL}"},
+ { logo: "social/email.svg", link: "mailto:#{$ANNOUNCE_LIST}" },
+ ],
+ sections: {
+ products: {
+ release_notes: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/release-notes-btKjZk5tU2",
+ api: "https://data.agroportal.lirmm.fr/",
+ tools: "/tools",
+ sparql: "https://sparql.agroportal.lirmm.fr/test/",
+ ontoportal: "https://ontoportal.org/"
+ },
+ support: {
+ contact_us: "https://#{$SITE}.lirmm.fr/feedback",
+ documentation: "https://ontoportal.github.io/documentation/",
+ agro_documentation: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/public-documentation-QMpsC9aVBb"
+ },
+ agreements: {
+ terms: $TERMS_AND_CONDITIONS_LINK,
+ privacy_policy: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/terms-conditions-naDsDo2Zxq#h-privacy-policy",
+ legal_notices: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/terms-conditions-naDsDo2Zxq#h-legal-notice"
+ },
+ about: {
+ about_us: "https://github.com/agroportal/project-management",
+ team: "https://github.com/orgs/agroportal/people",
+ cite_us: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/publications-and-references-87tEoeoGKy",
+ acknowledgments: "https://doc.jonquetlab.lirmm.fr/share/e6158eda-c109-4385-852c-51a42de9a412/doc/acknowledgments-15GdRXLQdm"
+ }
+ }
}
+
+
+
+$UI_THEME = ENV['UI_THEME'] || 'ontoportal'
+$HOSTNAME = ENV['API_URL']
+
+if $HOSTNAME
+ $HOSTNAME = ENV['API_URL'].split('data.').last
+ # add custom stage server configuration if needed (e.g bioportal_config_development_stageportal.lirmm.fr)
+ if File.exist?("config/bioportal_config_development_#{$HOSTNAME}")
+ require_relative "bioportal_config_development_#{$HOSTNAME}"
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
index 282011619..6a51f27d2 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,3 +1,4 @@
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
require "bundler/setup" # Set up gems listed in the Gemfile.
+require 'bootsnap/setup'
\ No newline at end of file
diff --git a/config/database.yml.sample b/config/database.yml.sample
index c92d72df2..6edf6ed31 100644
--- a/config/database.yml.sample
+++ b/config/database.yml.sample
@@ -12,10 +12,9 @@
default: &default
adapter: mysql2
encoding: utf8mb4
- pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
- password: bp_user
- host: db
+ password: root
+ host: <%= ENV["DB_HOST"] %>
development:
<<: *default
diff --git a/config/deploy.rb b/config/deploy.rb
index 6e33b4803..529350eb0 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -44,7 +44,8 @@
set :keep_releases, 5
set :bundle_without, 'development:test'
set :bundle_config, { deployment: true }
-
+set :rails_env, "appliance"
+set :config_folder_path, "#{fetch(:application)}/#{fetch(:stage)}"
# Defaults to [:web]
set :assets_roles, [:web, :app]
set :keep_assets, 3
@@ -57,6 +58,43 @@
# If you don't set `:passenger_restart_with_touch`, capistrano-passenger will check what version of passenger you are running
# and use `passenger-config restart-app` if it is available in that version.
+# you can set custom ssh options
+# it's possible to pass any option but you need to keep in mind that net/ssh understand limited list of options
+# you can see them in [net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start)
+# set it globally
+# set :ssh_options, {
+# keys: %w(/home/rlisowski/.ssh/id_rsa),
+# forward_agent: false,
+# auth_methods: %w(password)
+# }
+# and/or per server
+# server 'example.com',
+# user: 'user_name',
+# roles: %w{web app},
+# ssh_options: {
+# user: 'user_name', # overrides user setting above
+# keys: %w(/home/user_name/.ssh/id_rsa),
+# forward_agent: false,
+# auth_methods: %w(publickey password)
+# # password: 'please use keys'
+# }
+# setting per server overrides global ssh_options
+
+SSH_JUMPHOST = ENV.include?('SSH_JUMPHOST') ? ENV['SSH_JUMPHOST'] : 'jumpbox.hostname.com'
+SSH_JUMPHOST_USER = ENV.include?('SSH_JUMPHOST_USER') ? ENV['SSH_JUMPHOST_USER'] : 'username'
+
+JUMPBOX_PROXY = "#{SSH_JUMPHOST_USER}@#{SSH_JUMPHOST}"
+set :ssh_options, {
+ user: 'ontoportal',
+ forward_agent: 'true',
+ keys: %w(config/deploy_id_rsa),
+ auth_methods: %w(publickey),
+ # use ssh proxy if UI servers are on a private network
+ proxy: Net::SSH::Proxy::Command.new("ssh #{JUMPBOX_PROXY} -W %h:%p")
+}
+
+#private git repo for configuraiton
+PRIVATE_CONFIG_REPO = ENV.include?('PRIVATE_CONFIG_REPO') ? ENV['PRIVATE_CONFIG_REPO'] : 'https://your_github_pat_token@github.com/your_organization/ontoportal-configs.git'
desc "Check if agent forwarding is working"
task :forwarding do
on roles(:all) do |h|
@@ -85,7 +123,7 @@
TMP_CONFIG_PATH = "/tmp/#{SecureRandom.hex(15)}".freeze
on roles(:app) do
execute "git clone -q #{PRIVATE_CONFIG_REPO} #{TMP_CONFIG_PATH}"
- execute "rsync -a #{TMP_CONFIG_PATH}/#{fetch(:application)}/ #{release_path}/"
+ execute "rsync -a #{TMP_CONFIG_PATH}/#{fetch(:config_folder_path)}/ #{release_path}/"
execute "rm -rf #{TMP_CONFIG_PATH}"
end
elsif defined?(LOCAL_CONFIG_PATH)
@@ -104,6 +142,7 @@
end
+ after :updating, :get_config
after :publishing, :restart
after :restart, :clear_cache do
diff --git a/config/environments/appliance.rb b/config/environments/appliance.rb
index db8739398..ec5f5e79f 100644
--- a/config/environments/appliance.rb
+++ b/config/environments/appliance.rb
@@ -87,7 +87,7 @@
# Add custom data attributes to sanitize allowed list
config.action_view.sanitized_allowed_attributes = ['id', 'class', 'style', 'data-cls', 'data-ont']
-
+ config.view_component.show_previews = true
# TODO: Fix this?
# enable json logging format. Useful for logstash
# require 'rackstash'
diff --git a/config/environments/development.rb b/config/environments/development.rb
index b595b87cd..7e0593176 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -7,7 +7,16 @@
# it changes. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
+ config.action_mailer.delivery_method = :letter_opener_web
+ config.action_mailer.raise_delivery_errors = false
+
+ config.action_mailer.perform_deliveries = true
+ config.action_mailer.default_url_options = { host: '0.0.0:3000' } # Adjust the host/port as needed
+
+ config.action_mailer_letter_opener_location = Rails.root.join('tmp', 'my_mails')
+
+
# Do not eager load code on boot.
config.eager_load = false
@@ -16,7 +25,9 @@
# Enable server timing
config.server_timing = true
-
+
+ # Allow all hosts in development
+ config.hosts = nil
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join("tmp/caching-dev.txt").exist?
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 3eea9fbc8..3eb3961f0 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -92,8 +92,10 @@
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
# Include the BioPortal-specific configuration options
- require Rails.root.join('config', "bioportal_config_#{Rails.env}.rb")
-
+ if File.exist?(Rails.root.join('config', "bioportal_config_#{Rails.env}.rb"))
+ require Rails.root.join('config', "bioportal_config_#{Rails.env}.rb")
+ end
+
# Use a different cache store in production.
config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211", { namespace: 'bioportal_web_ui', expires_in: 1.day }
diff --git a/config/environments/test.rb b/config/environments/test.rb
index db8739398..f9364696d 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,22 +1,33 @@
-BioportalWebUi::Application.configure do
+# frozen_string_literal: true
+
+require 'active_support/core_ext/integer/time'
+
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+
+Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
- # Eager load code on boot. This eager loads most of Rails and
- # your application in memory, allowing both threaded web servers
- # and those relying on copy on write to perform better.
- # Rake tasks automatically ignore this option for performance.
- config.eager_load = true
-
- # Full error reports are disabled and caching is turned on.
- config.consider_all_requests_local = false
- config.action_controller.perform_caching = true
-
- # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
- # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
- config.require_master_key = true
+ # Eager loading loads your whole application. When running a single test locally,
+ # this probably isn't necessary. It's a good idea to do in a continuous integration
+ # system, or in some way before deploying your code.
+ config.eager_load = ENV['CI'].present?
+
+ # Configure public file server for tests with Cache-Control for performance.
+ config.public_file_server.enabled = true
+ config.public_file_server.headers = {
+ 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
+ }
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+ config.cache_store = ActiveSupport::Cache::MemCacheStore.new('localhost:11211', namespace: 'BioPortal')
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml
new file mode 100644
index 000000000..6495aad7c
--- /dev/null
+++ b/config/i18n-tasks.yml
@@ -0,0 +1,8 @@
+# config/i18n-tasks.yml
+<% require 'i18n-tasks-csv' %>
+
+csv:
+ export:
+ - "tmp/i18n-export/main.csv"
+ import:
+ - tmp/i18n-export/main.csv
\ No newline at end of file
diff --git a/config/initializers/bugsnag.rb b/config/initializers/bugsnag.rb
new file mode 100644
index 000000000..8704957a0
--- /dev/null
+++ b/config/initializers/bugsnag.rb
@@ -0,0 +1,5 @@
+if $BUGSNAG_API_KEY
+ Bugsnag.configure do |config|
+ config.api_key = $BUGSNAG_API_KEY
+ end
+end
diff --git a/config/initializers/graphql_client.rb b/config/initializers/graphql_client.rb
index 69a909bb9..57760a168 100644
--- a/config/initializers/graphql_client.rb
+++ b/config/initializers/graphql_client.rb
@@ -6,7 +6,7 @@
module GitHub
HTTPAdapter = GraphQL::Client::HTTP.new('https://api.github.com/graphql') do
def headers(_context)
- { 'Authorization': "Bearer #{Rails.application.credentials[:kgcl][:github_access_token]}" }
+ { 'Authorization': "Bearer #{Rails.application.credentials.dig(:kgcl, :github_access_token)}" }
end
end
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
new file mode 100644
index 000000000..c7c4027c3
--- /dev/null
+++ b/config/initializers/omniauth.rb
@@ -0,0 +1,5 @@
+Rails.application.config.middleware.use OmniAuth::Builder do
+ Array($OMNIAUTH_PROVIDERS).each do |provider, config|
+ provider config[:strategy] || provider, config[:client_id], config[:client_secret], client_options: {}.merge(config[:client_options].to_h)
+ end
+end
\ No newline at end of file
diff --git a/config/locales/de.yml.sample b/config/locales/de.yml.sample
new file mode 100644
index 000000000..ed61d6f0c
--- /dev/null
+++ b/config/locales/de.yml.sample
@@ -0,0 +1,429 @@
+---
+de:
+ activaterecord:
+ errors:
+ models:
+ license:
+ attributes:
+ encrypted_key:
+ invalid_license_key: is an invalid license key
+ no_appliance_id_for_comparison: Could not be validated. Unable to retrieve virtual appliance ID.
+ appliance_id_mismatch: is an appliance id mismatch
+ # Konfigurieren Sie den Ressourcenbegriff 'ontology' im gesamten Portal so, dass er durch alternative Begriffe wie 'semantic_resource', 'vocabulary', 'terminology' oder 'semantic_artefact' ersetzt werden kann.
+ resource_term:
+ ontology: Ontologie
+ ontology_plural: Ontologien
+ ontology_single: eine Ontologie
+
+ semantic_resource: semantische Ressource
+ semantic_resource_plural: semantische Ressourcen
+ semantic_resource_single: eine semantische Ressource
+
+ vocabulary: Vokabular
+ vocabulary_plural: Vokabulare
+ vocabulary_single: ein Vokabular
+
+ terminology: Terminologie
+ terminology_plural: Terminologien
+ terminology_single: eine Terminologie
+
+ semantic_artefact: semantisches Artefakt
+ semantic_artefact_plural: semantische Artefakte
+ semantic_artefact_single: ein semantisches Artefakt
+
+ date:
+ formats:
+ year_month_day_concise: "%Y-%m-%d" # 2017-03-01
+ month_day_year: "%b %-d, %Y" # Mar 1, 2017
+ monthfull_day_year: "%B %-d, %Y" # March 1, 2017
+
+ additional_parameters: Zusätzliche Parameter werden erklärt unter
+ admin:
+ licenses:
+ create:
+ success: Lizenz erfolgreich verlängert!
+ all: Alle
+ annotator:
+ annotate_text_prompt: Zu beschriftenden Text eingeben oder einfügen
+ annotations_result: Anmerkungen
+ fast_context: FastContext
+ filters:
+ confidence_threshold: Filterkonfidenzschwellenwert
+ confidence_threshold_help: Geben Sie die Mindestposition in der Punkteverteilung
+ an (zwischen 1 und 100)
+ exclude_numbers: Nummern ausschließen
+ exclude_synonyms: Synonyme ausschließen
+ include_mappings: Mappings einbeziehen
+ match_longest_only: Nur das längste Spiel
+ match_partial_words: Erkennen von Wortteilen
+ max_hierarchy_level: Vorfahren bis zur Ebene einbeziehen
+ score: Punktzahl einbeziehen
+ score_help: Bewertung von Anmerkungen nach der früheren NCBO 2009-Maßnahme (alt)
+ oder Bewertung von Anmerkungen nach der C-Value-Maßnahme (cvalue) oder Bewertung
+ von Anmerkungen nach der C-Value-Maßnahme mit Hierarchieerweiterung (cvalueh)
+ score_threshold: Filter nach Schwellenwert
+ score_threshold_help: Mindestpunktzahl für Anmerkungen festlegen
+ get_annotator: Anmerkungen erhalten
+ index:
+ fast_context:
+ tooltip: Aktivieren Sie FastContext, um zu erkennen, ob ein Konzept verneint
+ wurde (bejaht, verneint), wer das gefundene Konzept erlebt hat (Patient,
+ andere), wann das kommentierte Konzept aufgetreten ist (kürzlich, historisch,
+ hypothetisch) und/oder ob das kommentierte Konzept unsicher ist (sicher,
+ unsicher).
+ intro: Annotationen für biomedizinische Texte mit Ontologieklassen erhalten
+ lemmatize:
+ tooltip: Aktivieren Sie Lemmatize, um eingereichten Text zu lemmatisieren
+ und ein lemmatisiertes Wörterbuch für Anmerkungen zu verwenden
+ sample_text: Das Melanom ist ein bösartiger Tumor der Melanozyten, der hauptsächlich
+ in der Haut, aber auch im Darm und im Auge vorkommt.
+ lemmatize: Lemmatisieren
+ results_filtered_by: Die Ergebnisse werden gefiltert nach
+ select: Wählen Sie %{name}
+ start_typing_to_select: Beginnen Sie mit der Eingabe, um %{type} auszuwählen oder
+ lassen Sie es leer, um alle zu verwenden
+ title: Kommentator
+ umls:
+ semantic_groups: UMLS Semantische Gruppen
+ semantic_types: UMLS-Semantische Typen
+ certainty: Gewissheit
+ class: Klasse
+ clear_selection: Auswahl löschen
+ concepts:
+ request_term:
+ new_term_instructions: |
+
Diese Ontologie ist in OntoloBridge integriert und ermöglicht es den Nutzern der Gemeinschaft, Ergänzungen zur öffentlichen Ontologie vorzuschlagen. Füllen Sie die nachstehende Vorlage aus, um eine Begriffsanfrage direkt an den Ontologiemanager zu senden.
+
+
Begriffsbezeichnung (erforderlich) Vorgeschlagener Begriffsname. Wenn ein Begriff mit mehr als einem Synonym beschrieben werden kann, geben Sie hier nur den bevorzugten Namen ein.
+
+
+
Begriffsbeschreibung (erforderlich) Eine kurze Definition, Beschreibung oder Verwendung des vorgeschlagenen Begriffs. Synonyme von weiteren Begriffen können in diesem Abschnitt aufgeführt werden.
+
+
+
Superclass (erforderlich) Der übergeordnete Begriff des vorgeschlagenen Begriffs. Der übergeordnete Begriff muss ein bestehender Eintrag in der aktuellen Ontologie sein. Die Oberklasse kann direkt aus dem Bioportal-Klassenbaum ausgewählt werden.
+
+
+
Referenzen (optional) Bieten Sie Belege für die Existenz des gesuchten Begriffs, wie Pubmed IDs von Artikeln oder Links zu anderen Ressourcen, die den Begriff beschreiben.
+
+
+
Begründung (optional) Geben Sie hier zusätzliche Informationen über den gesuchten Begriff an.
+
+ context: Kontext
+ coverage: Erfassungsbereich
+ filter: Filter
+ format_results: Ergebnisse formatieren als
+ get_json_version: Abrufen der json-Version
+ get_recommendations: Empfehlungen erhalten
+ help: Hilfe
+ home:
+ agroportal_figures: "%{site} in Zahlen:"
+ benefit1: Entdecken Sie neue Erkenntnisse und Zusammenhänge, indem Sie andere
+ Ontologien im Repository erforschen.
+ benefit2: Tragen Sie zum Wachstum und zur Entwicklung Ihres Bereichs bei, indem
+ Sie neue Konzepte und Kategorien hinzufügen.
+ benefit3: Verwenden Sie die Versionskontrolle, um die Änderungen an Ihrer Ontologie
+ im Laufe der Zeit zu verwalten und mit anderen Benutzern zusammenzuarbeiten.
+ benefit4: Holen Sie sich Feedback und Vorschläge von anderen Benutzern, die Ihre
+ Ontologie überprüfen und kommentieren können.
+ benefit5: Holen Sie sich den FAIR Score und die Metriken für Ihre Ontologie.
+ fair_details: Siehe Details
+ fairness: FAIR-Punkte
+ get_annotations: Anmerkungen erhalten
+ get_recommendations: Empfehlungen erhalten
+ index:
+ tagline: Die Heimat von Vokabularen und Ontologien in der Agrarwissenschaft
+ und verwandten Bereichen.
+ title: Willkommen bei der %{site}
+ welcome: Willkommen auf der %{site},
+ ontology_upload: Möchten Sie eine Ontologie hochladen?
+ ontology_upload_benefits: 'Indem Sie Ihre Ontologie auf %{site} hochladen, können
+ Sie:'
+ ontology_upload_button: Ontologie hochladen
+ discover_ontologies_button: Ontdek ontologieën
+ ontology_upload_desc: Das Hochladen einer Ontologie ist eine Möglichkeit, Ihr
+ Fachwissen mit anderen zu teilen.
+ paste_text_prompt: Einfügen eines Textabsatzes oder einiger Schlüsselwörter ...
+ recommender_annotator: Empfehlungsgeber und Kommentator
+ support_and_collaborations: Ondersteuning en samenwerkingen
+ ontoportal_instances: Ontoportal-Instanzen
+ twitter_news: Nachrichten
+
+ input: Eingabe
+ insert_sample_text: Beispieltext einfügen
+ keywords: Schlüsselwörter
+ keywords_separated_by_commas: Schlüsselwörter durch Kommas getrennt
+ knowledge_detail: Wissen Detail
+ landscape:
+ average_metrics: Durchschnittliche Metriken
+ category: Kategorie
+ filter_network: Netzwerk filtern
+ funding_endorsing_organizations: Organisationen, die die meisten Ontologien finanzieren
+ und befürworten
+ group: Gruppe
+ groups_and_categories: Gruppen und Kategorien
+ intro: Visualisieren Sie das Panorama aller Ontologien auf %{site} durch die Aggregation von Metadaten.
+ more_properties_charts: Weitere Eigenschaftsdiagramme
+ most_active_ontologies: Die aktivsten Ontologien
+ most_active_organizations: Die aktivsten Organisationen
+ most_active_people: Die aktivsten Menschen
+ most_active_people_as_reviewer: Die aktivsten Personen als Gutachter
+ most_mentioned_people: Meistgenannte Personen als Kontaktperson, Ersteller, Mitwirkender
+ oder Kurator
+ most_mentioned_people_as_reviewer: Personen, die Notizen, Rezensionen und Projekte
+ veröffentlicht haben
+ ontologies_activity_on: Ontologie-Aktivität auf %{site}
+ ontologies_by: Ontologien nach %{type}
+ ontologies_contributors: Beiträge zur Ontologieentwicklung
+ ontologies_count_by_catalog: Anzahl der Ontologien in jedem Datenkatalog
+ ontologies_formats: Verwendetes Format
+ ontologies_languages: Natürliche Sprachen der Ontologien
+ ontologies_licenses: Von Ontologien verwendete Lizenzen
+ ontologies_with_notes_reviews_projects: Ontologien mit Notizen, Bewertungen und
+ Projekten
+ ontology_fairness_evaluator: Ontologie FAIRness Evaluator (O'FAIRe)
+ ontology_formality_levels: Formalitätsebenen von Ontologien
+ ontology_properties_pie_charts: Kreisdiagramme für die in Ontologien verwendeten
+ Eigenschaften
+ ontology_relations_network: Ontologie-Beziehungsnetz
+ ontology_tools: Meistgenutzte Tools zur Erstellung von Ontologien
+ owl_ontology_author_uris: URIs für Autoreneigenschaften, die für OWL-Ontologien
+ verwendet werden
+ owl_ontology_definition_uris: URIs für Definitionsmerkmale, die für OWL-Ontologien
+ verwendet werden
+ owl_ontology_preflabel_uris: URIs für prefLabel-Eigenschaften, die für OWL-Ontologien
+ verwendet werden
+ owl_ontology_synonym_uris: URIs für synonyme Eigenschaften, die für OWL-Ontologien
+ verwendet werden
+ properties_usage_proportion: Der Anteil der verwendeten Eigenschaften in den gespeicherten
+ Ontologien
+ properties_use: Nutzung der Immobilie
+ relations_between_stored_ontologies: Beziehungen zwischen gespeicherten Ontologien
+ im Portal
+ size: Größe
+ title: "%{site} Landschaft"
+ layout:
+ header:
+ account_setting: Kontoeinstellungen
+ annotator: Kommentator
+ browse: Durchsuchen
+ documentation: Dokumentation
+ help: Hilfe
+ landscape: Landschaft
+ login: Anmeldung
+ logout: abmeldung
+ mappings: Mappings
+ publications: Veröffentlichungen
+ release_notes: Anmerkungen zur Veröffentlichung
+ search_prompt: Suche in %{portal_name} ...
+ submit_feedback: Feedback senden
+ support: unterstützung
+ login:
+ enter_email: Ihre E-Mail eingeben
+ enter_password: Geben Sie Ihr Passwort ein
+ forgot_password: Passwort vergessen?
+ invalid_login: Fehler im Formular
+ no_account: Sie haben noch kein Konto?
+ password: Passwort
+ register: Register
+ title: Anmeldung
+ username_or_email: Benutzername oder E-Mail
+ mappings:
+ find_mappings: Zuordnungen einer Klasse/eines Konzepts finden
+ intro: Mappings zwischen Klassen verschiedener Ontologien durchsuchen
+ loading_mappings: Mappings laden...
+ mappings_bulk_load: Mapping Bulk Load
+ no_mappings_available: Keine Mappings verfügbar
+ title: Korrespondenzen
+ upload_mappings: Mappings hochladen
+ matched_class: Abgestimmte Klasse
+ matched_ontology: abgestimmte Ontologie
+ max_ontologies_per_set: Maximale Anzahl von Ontologien pro Satz
+ nbco_annotatosplus:
+ annotations: Anmerkungen
+ enter_paste_text_to_annotate: 'Geben Sie den zu beschriftenden Text ein oder fügen
+ Sie ihn ein:'
+ exclude_numbers: Nummern ausschließen
+ exclude_synonyms: Synonyme ausschließen
+ fast_context:
+ help: 'Aktivieren Sie FastContext, um festzustellen: ob ein Konzept verneint
+ wurde (bejaht, verneint), wer das gefundene Konzept erlebt hat (Patient, andere),
+ wann das kommentierte Konzept aufgetreten ist (kürzlich, historisch, hypothetisch)
+ und/oder ob das kommentierte Konzept unsicher ist (sicher, unsicher).'
+ title: FastContext
+ filters:
+ additional_parameters_explained_at: 'Weitere Parameter werden auf der Seite
+ erläutert:'
+ by:
+ certainty: Gewissheit
+ class: Klasse
+ experiencer: Erlebnisträger
+ filter: Filter
+ match_context: Kontext
+ match_type: Typ
+ matched_class: Assoziierte Klasse
+ matched_ontology: Assoziierte Ontologie
+ negation: Negation
+ ontology: Ontologie
+ score: Ergebnis
+ temporality: Zeitlichkeit
+ title: Die Ergebnisse werden gefiltert nach
+ umls_sem_type: UMLS-Semantischer Typ
+ confidence_threshold: Vertrauensschwelle filtern
+ confidence_threshold_help: Geben Sie die Mindestposition in der Punkteverteilung
+ an (zwischen 1 und 100)
+ format_results_as: 'Ergebnisse formatieren als:'
+ reproduce_results_using: Reproduzieren Sie diese Ergebnisse mit der
+ score_threshold: Filter nach Schwellenwert
+ score_threshold_help: Geben Sie den Mindestwert für die Bewertung von Anmerkungen
+ an
+ include_ancestors_up_to_level: Vorfahren bis zur Ebene einbeziehen
+ include_mappings: Mappings einbeziehen
+ include_score: Punktzahl einbeziehen
+ index:
+ intro: |
+ Der NCBO Annotator+ ist ein Proxy, der den NCBO Annotator Web Service auf dem NCBO BioPortal aufruft.
+
+ Tchechmedjiev, A., Abdaoui, A., Emonet, V., Melzi, S., Jonnagaddala, J., & Jonquet, C. (2018). Enhanced features for annotating and indexing clinical text with NCBO Annotator+. Bioinformatics, 34(11), 1962-1965.
+
+ Wenn Sie die API verwenden, geben Sie bitte einen gültigen NCBO BioPortal API-Schlüssel an und greifen Sie auf den Dienst unter http://services.bioportal.lirmm. de/ncbo_annotatorplus zu
+ Der an NCBO Annotator+ übermittelte Text muss in englischer Sprache verfasst sein.
+ sample_text: Das Melanom ist ein bösartiger Tumor der Melanozyten, der hauptsächlich
+ in der Haut, aber auch im Darm und im Auge vorkommt.
+ title: NCBO Annotator +
+ insert_sample_text: Beispieltext einfügen
+ match_longest_only: Nur das längste Spiel
+ match_partial_words: Teilwörter zuordnen
+ recognizer: Erkennung von Entitäten
+ score_help: Bewertung von Anmerkungen nach der früheren NCBO 2009-Maßnahme (alt)
+ oder Bewertung von Anmerkungen nach der C-Value-Maßnahme (cvalue) oder Bewertung
+ von Anmerkungen nach der C-Value-Maßnahme mit Hierarchieerweiterung (cvalueh)
+ select: Wählen Sie %{name}
+ select_ontologies: Beginnen Sie mit der Eingabe, um Ontologien auszuwählen, oder
+ lassen Sie das Feld leer, um alle Ontologien zu verwenden
+ select_ontologies_list: Ontologien auswählen
+ show_advanced_options: Erweiterte Optionen anzeigen
+ start_typing_to_select: Beginnen Sie mit der Eingabe, um %{type} auszuwählen oder
+ lassen Sie es leer, um alle zu verwenden
+ umls:
+ semantic_groups: UMLS Semantische Gruppen
+ semantic_types: UMLS-Semantische Typen
+ negation: verneinung
+ none: keine
+ ontologies:
+ ontology_search_prompt: 'Suche nach einer Ontologie oder einem Konzept (Beispiel:
+ Agrovoc ...)'
+ self: Ontologien
+ ontology: Ontologie
+ ontology_details:
+ concept:
+ definitions: Definitionen
+ id: ID
+ in_schemes: In Schemata
+ member_of: Mitglied von
+ no_preferred_name_for_selected_language: Kein bevorzugter Name für die gewählte
+ Sprache.
+ obsolete: Veraltet
+ preferred_name: Bevorzugter Name
+ synonyms: Synonyme
+ type: Typ
+ metadata:
+ additional_metadata: Zusätzliche Metadaten
+ header:
+ last_submission_date: Datum laatste indiening
+
+ ontology_sets: Ontologie-Sets
+ output: Ausgabe
+ projects:
+ contacts: Kontakte
+ create_new_project: Neues Projekt erstellen
+ created: Erstellt
+ creator: Benutzer
+ delete_admin_only: Löschen (nur für Administratoren)
+ delete_confirm: Sind Sie sicher?
+ description: Beschreibung
+ description_text: Beschreibung Text
+ edit: Bearbeiten
+ home_page: Hauptseite
+ index:
+ intro: Durchsuchen Sie eine Auswahl von Projekten, die %{site} Ressourcen verwenden
+ institutions: Einrichtungen
+ ontologies: Ontologien
+ project_description: Beschreibung des Projekts
+ self: Projekte
+ title: Liste der Projekte
+ view_projects_help: Projekte anzeigen Hilfe
+ recommender:
+ intro: Empfehlungen für die relevantesten Ontologien anhand eines Auszugs aus
+ einem biomedizinischen Text oder einer Liste von Schlüsselwörtern erhalten
+ no_recommendations: Keine Empfehlungen gefunden
+ no_sets_recommended: Es gibt keine empfohlenen Ontologiesätze für die angegebene
+ Eingabe. Bitte versuchen Sie die Ausgabe 'Ontologien'.
+ ontology_recommendation_input: Bitte fügen Sie einen Textabschnitt oder einige
+ Schlüsselwörter ein, um Ontologieempfehlungen zu berechnen.
+ ontology_recommender: Ontologie-Empfehlungsprogramm
+ paste_text_recommendations: Fügen Sie einen Textabschnitt oder einige Schlüsselwörter
+ ein, die bei der Berechnung der Ontologieempfehlungen verwendet werden sollen
+ recommendation_error: Problem beim Abrufen von Empfehlungen, bitte versuchen Sie
+ es erneut
+ text_length_limit: Bitte verwenden Sie weniger als 500 Wörter. Wenn Sie längere
+ Texte kommentieren müssen, können Sie den Webdienst für Empfehlungen nutzen.
+ title: empfehlungsgeber
+ valid_integer_max_ontologies_per_set: Die maximale Anzahl von Ontologien pro Satz
+ muss ein gültiger ganzzahliger Wert sein
+ valid_max_ontologies_per_set_range: Die maximale Anzahl von Ontologien pro Satz
+ muss zwischen 2 und 4 liegen
+ valid_numeric_weights: Alle Gewichte müssen gültige numerische Werte sein
+ weight_sum_greater_than_zero: Die Summe der Gewichte muss größer als Null sein
+ weights_greater_than_zero: Alle Gewichte müssen größer als oder gleich Null sein
+ register:
+ account_errors: 'Fehler bei der Erstellung Ihres Kontos:'
+ confirm_password: Bestätigen Sie das Passwort
+ create_account: Neues Konto erstellen
+ email: E-Mail
+ first_name: Vornamen
+ last_name: Nachname
+ mailing_list: Registrieren Sie sich für die Mailingliste des AgroPortal
+ optional: "(fakultativ)"
+ password: Passwort
+ title: Register
+ username: Benutzername
+ reproduce_results: Reproduzieren Sie diese Ergebnisse mit der
+ score: Ergebnis
+ search:
+ search_place_holder: Geben Sie einen Begriff ein, z.B. Pflanzenhöhe
+ advanced_options:
+ search_language: Suchsprache
+ ontologies: Ontologien
+ include_in_search_title: In der Suche anzeigen
+ include_in_search_values:
+ property_values: Eigenschaftswerte
+ obolete_classses: Veraltete Klassen
+ ontology_views: Ontologie-Ansichten
+ show_only_title: Nur anzeigen
+ show_only_values:
+ exact_matches: Exakte Treffer
+ classes_with_definitions: Klassen mit Definitionen
+ show_advanced_options: Erweiterte Optionen anzeigen
+ hide_advanced_options: Erweiterte Optionen ausblenden
+ match_in: Übereinstimmung in
+ ontologies: Ontologien
+ result_component:
+ details: Details
+ visualize: Visualisieren
+ more_from_ontology: Mehr von dieser Ontologie
+ reuses_in: Wiederverwendungen in
+ reuses_in_other_ontologies: Wiederverwendungen in anderen Ontologien
+
+ select_from_list: Aus Liste auswählen
+ select_ontologies: Beginnen Sie mit der Eingabe, um Ontologien auszuwählen, oder
+ lassen Sie sie leer, um alle zu verwenden
+ select_ontologies_list: Ontologien auswählen
+ show_advanced_options: Erweiterte Optionen anzeigen
+ specialization: Spezialisierung
+ temporality: Zeitlichkeit
+ text: Text
+ type: Typ
+ umls_sem_type: UMLS Sem Typ
+ view_fair_scores_definitions: Definitionen für faire Noten anzeigen
+ visits: Besuche
+ weights_configuration: Gewichte Konfiguration
\ No newline at end of file
diff --git a/config/locales/en.rb.sample b/config/locales/en.rb.sample
deleted file mode 100644
index 56e0ccd50..000000000
--- a/config/locales/en.rb.sample
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- :en => {
- :home => {
- :intro => 'Use ' + $SITE + ' to access and share ontologies. You can create ontology-based
- annotations for your own text , link your own project that uses ontologies to the
- description of those ontologies , find and create relations between terms in
- different ontologies, review and comment on ontologies and their components as you
- browse them. Sign in to ' + $SITE + '
- to submit a new ontology or ontology-based project, provide comments on ontologies or add ontology mappings.',
-
- :facebook_button => '',
-
- :twitter_button => '',
-
- :annotate => {
- :intro => 'The ' + $ORG_SITE + ' Annotator processes text submitted by users, recognizes relevant ontology terms in the text and returns
- the annotations to the user. Use the interface below to submit sample text to get ontology-based annotations. Hover the mouse pointer on any
- button to see what it does. Click on the (?) to see a detailed help panel.
-
- Subscribe to the NCBO Annotator Users Google group to learn more about
- who and how the Annotator is being used in different projects.'
- },
-
- :resources => {
- :intro => $ORG + ' is building a system for automated ontology-based annotation and indexing of data. We process the textual metadata of diverse elements of resources
- to annotate and index them with terms from appropriate ontologies. Use the interface below to search the resulting index of annotations and to identify
- data resources annotated with particular ontology terms.'
- },
-
- :footer => 'Powered by NCBO BioPortal
- Release Notes'
- },
-
- :projects => {
- :intro => 'Browse the ontology-based projects in the community: Each project description is linked to ' + $ORG_SITE + ' ontologies that the project uses.
- Use the ‘Add Project’ link to add your ontology-based project to this list and to link it to ' + $ORG_SITE + ' ontologies.
- Your project will then appear on the pages that list the details for the ontologies that you selected. We also invite you to review ontologies that you used in your project.'
- },
-
- :ontologies => {
- :intro => 'Access all ontologies that are available in ' + $ORG_SITE + ':
- You can filter this list by category to display ontologies relevant for a certain domain.
- You can also filter ontologies that belong to a certain group. Subscribe to the ' + $ORG_SITE + ' RSS feed
- to receive alerts for submissions of new ontologies, new versions of ontologies, new notes, and new projects. You can subscribe to feeds for a specific ontology at
- the individual ontology page. Add a new ontology to ' + $ORG_SITE + ' using the Submit New Ontology link (you need to sign in
- to see this link).',
-
- :metrics => {
- :intro => '' + $SITE + ' calculates the metrics on the salient properties of the ontology, including statistics and quality-control
- and quality-assurance metrics. Each ontology may have all, some, or no values filled in for its metrics and only metrics
- for the most recent version are reflected. The metrics currently do not distinguish between the terms defined directly in
- this ontology and imported terms (for OWL) or referenced terms (for OBO).
- See metrics descriptions.'
- }
- },
-
- :mappings => {
- :intro => 'Use this page to explore mappings between ontologies that you are interested in. You will also see the mappings when you browse individual ontologies.'
- },
-
- :about => {
- :welcome => 'Welcome to the National Center for Biomedical Ontology’s BioPortal. BioPortal is a Web-based application for accessing and sharing biomedical ontologies.',
- :getting_started => $SITE + ' allows users to browse, upload, download, search, comment on, and create mappings for ontologies.',
- :browse => '
-
- Users can browse and explore individual ontologies by navigating either a tree structure or an animated graphical view. Users can also view mappings and ontology metadata, and download ontologies.
-
-
- Additionally, users who are signed in may also submit a new ontology to the library. All submissions to the library are reviewed.
-
- Many vocabularies and ontologies are produced to represent and annotate agronomic data. Therefore, there is a need of
- a common platform to identify, host and use them in agro-informatics application. The AgroPortal project aims to offer
- a reference ontology repository for agronomy, reusing the NCBO BioPortal technology. The scientific outcomes and the
- experience of the biomedical domain are thus exploited and transposed in the agronomy domain, including plants, food,
- environment and possibly animal sciences. We offer an ontology portal which features ontology hosting, search, versioning,
- visualization, comment, recommendation, enables semantic annotation, as well as storing and exploiting ontology alignments.
- All of these within a fully semantic web compliant infrastructure. The AgroPortal specifically pays attention to respect the
- requirements of the agronomic community in terms of ontology formats (e.g., SKOS, trait dictionaries) or supported features.
- AgroPortal project is based on five driving agronomic use cases which participate in the design and orientation of the platform.
- AgroPortal already offers a robust and stable reference repository highly valuable for the agronomic domain.
-
The National Center For Biomedical Ontology (NCBO), Institut de Recherche pour le Développement (IRD), Research Data Alliance (RDA),
- Bioversity International, Food & Agriculture Organization (FAO), Global Open Data for Agriculture & Nutrition (Godan Action), Institut National de la Recherche Agronomique (INRA)
-
Acknowledgments
-
The AgroPortal is partly achieved within the Semantic Indexing of French biomedical Resources (SIFR) project
- that received funding from the EU H2020 research and innovation programme under the Marie Sklodowska-Curie (grant 701771)
- and the French National Research Agency (grant ANR-12-JS02-01001), the NUMEV Labex (grant ANR-10-LABX-20),
- the Computational Biology Institute of Montpellier (grant ANR-11-BINF-0002) as well as by University of Montpellier and the CNRS.
- We also thank the National Center for Biomedical Ontologies for help and time spent with us in deploying the AgroPortal.
-
Team
- To contact us: firstname.lastname@lirmm.fr
-
-
Clément Jonquet, researcher at LIRMM (Univ. of Montpellier, France), main investigator of the AgroPortal project
-
Anne Toulet, researcher at LIRMM (Univ. of Montpellier, France)
-
Vincent Emonet, engineer at LIRMM (Univ. of Montpellier, France)
This ontology integrates with OntoloBridge, allowing community users to suggest additions to the public ontology. Complete the template below to submit a term request directly to the Ontology Manager.
+
+
Term label (required) Suggested term name. If a term can be described with more than one synonym, enter only the preferred name here.
+
+
+
Term Description (required) A brief definition, description, or usage of the suggested term. Synonyms of additional terms may be listed in this section.
+
+
+
Superclass (required) The parent term of the suggested term. The parent term must be an existing entry in the current ontology. The superclass can be selected directly from the class tree.
+
+
+
References (optional) Provide evidence that the requested term exists, such as IDs of articles or links to other resources describing the term.
+
+
+
Justification (optional) Provide here any additional information about the requested term.
+
home:
+ bug: Bug
+ proposition: Proposition
+ question: Question
+ ontology_submissions_request: Ontology submissions request
+ include_name: Please include your name
+ include_email: Please include your email
+ include_comment: Please include your comment
+ fill_text: Please fill in the proper text from the supplied image
+ notice_feedback: Feedback has been sent
+ account_title: Account Information
+ agroportal_figures: "%{site} in figures"
+ benefit1: Discover new insights and knowledge by exploring other ontologies or smeantic resources in the repository.
+ benefit2: Contribute to knowledge sharing and semantic interoperability in your domain.
+ benefit3: Map your ontology to other relevant ones in the domain and collaborate with other users.
+ benefit4: Get feedback and suggestions from other users who can use and comment on your ontology.
+ benefit5: Precisely describe your ontology with relevant metadata and get a FAIR score for your ontology.
+ fair_details: See details
+ fairness: FAIR Score
+ get_annotations: Get annotations
+ get_recommendations: Get recommendations
index:
- find_ontology_placeholder: Start typing resource name, then choose from list
- query_placeholder: Enter a class, e.g. Shape
- tagline: the LifeWatch ERIC repository of semantic resources for ecology and related domains
- title: Welcome to the %{organization}
+ tagline: The home of ontologies and semantic artefacts in agri-food and related domains.
+ title: Welcome to %{site}
welcome: Welcome to %{site},
- help:
- welcome: Welcome to the LifeWatch ERIC’s %{site}. %{site} is a repository of semantic resources for ecology and related domains.
- getting_started: >
- %{site} supports the community in the creation, management, mapping and alignment of its semantic resources and subsequently also of its data.
- browse: >
- Users can browse and explore individual semantic resources by navigating either a tree structure or
- an animated graphical view. Users can also view mappings and semantic resource metadata, and download
- semantic resources. Additionally, users who are signed in may also submit a new semantic resource to the
- library. All submissions to the library are reviewed.
- documentation_html: >
- General documentation is available on GitHub
- rest_examples_html: View documentation and examples of the %{site} REST API.
- announce_list_html: >
- To receive notices of new releases or site outages, please subscribe to the
- bioontology-support list.
- contact_html: >
- If you have any comment or need for support, please email service.centre@lifewatch.eu.
- If you are interested and would like to join our information mailing list, please subscribe to our user mailing
- list.
- annotator:
+ ontology_upload: Do you want to share an ontology?
+ ontology_upload_benefits: 'By uploading and sharing your ontology to %{site}, you can:'
+ ontology_upload_button: Submit ontology
+ discover_ontologies_button: Discover ontologies
+ ontology_upload_desc: Uploading an ontology or another type of semantic artefact (vocabulary, terminology, thesaurus, ...) is a way of sharing your knowledge with others.
+ paste_text_prompt: Enter a paragraph of text or some keywords...
+ recommender_annotator: Recommender and Annotator
+ support_and_collaborations: Support & Collaborations
+ ontoportal_instances: Other OntoPortal Instances
+ see_details: See details
+ info_tooltip_text: "You are seing the average scores for all the public ontologies in AgroPortal. FAIR scores are computed with the O'FAIRe methodology. More details here: https://github.com/agroportal/fairness"
+ average: Average
+ min: Min
+ max: Max
+ ontologies: Ontologies
+ classes: Classes
+ individuals: Individuals
+ properties: Properties
+ projects: Projects
+ mappings: Mappings
+ users: Users
+ twitter_news: News
+ feedback:
+ error_on_form: Errors On Form
+ leave_your_feedback: Leave your feedback
+ feedback_hi_text: Hi
+ feedback_info_text: you can use the form below or email us directly at
+ email: Email
+ name: Name
+ proposition_url_page: Error/Proposition page URL
+ feedback: Feedback
+ tags: Tags
+ bug: Bug
+ proposition: Proposition
+ question: Question
+ ontology_submissions_request: Ontology submissions request
+ optional: (optional)
+ send: Send
+ feedback_complete:
+ title: Feedback sent successfully
+ message: Thank you for taking the time to share your feedback with us. Our support team will review your message and get back to you as soon as possible with a response. We value your opinion and appreciate your help in improving our services. Thank you for your support!
+ landscape:
+ #select_ontologies: Start typing to select ontologies or leave blank to use them all
+ classes: Number of classes
+ individuals: Number of individuals
+ properties: Number of properties
+ max_depth: Max depth
+ max_child_count: Max child count
+ average_child_count: Average child count
+ classes_with_one_child: Classes with one child
+ classes_with_more_than_25_children: Classes with more than 25 children
+ classes_with_no_definition: Classes with no definition
+ number_of_xioms_triples: Number of axioms (triples)
+ projects_count: "%{count} projects"
+ notes_count: "%{count} notes"
+ reviews_count: "%{count} reviews"
+ as_contact_count: "%{count} as contact"
+ as_contributor_count: "%{count} as contributor"
+ as_creator_count: "%{count} as creator"
+ as_curator_count: "%{count} as curator"
+ contributions: "Contributions: %{title}"
+ published_ontologies: published %{count} ontologies
+ funded_ontologies: funded %{count} ontologies
+ endorsed_ontologies: endorsed %{count} ontologies
+ number_of_ontologies_using_format: Number of ontologies using this format
+ number_of_ontologies_of_type: Number of ontologies of this ontology type
+ number_of_ontologies_of_formality_level: Number of ontologies of this formality level
+ number_of_ontologies_in_catalog: Number of ontologies in this catalog
+ number_of_ontologies: Number of ontologies
+ number_of_ontologies_with_class_count_in_range: Number of ontologies with a class count in this range
+ average: Average
+ fairness_interface_introduction: This interface shows how an ontology or a group responded successfully to O’FAIRe FAIRness assessment questions
+ fairness_interface_details: See details for each ontologies on the specific ontology summary pages
+ fairness_interface_hover_instruction: hover on a principle to see details
+ average_metrics: Average metrics
+ category: category
+ filter_network: Filter network
+ funding_endorsing_organizations: Organizations funding and endorsing the most ontologies
+ group: group
+ groups_and_categories: Groups and Categories
+ intro: Visualize the panorama of all ontologies on %{site} via metadata aggregation.
+ more_properties_charts: More properties charts
+ most_active_ontologies: Most active ontologies
+ most_active_organizations: Most active organizations
+ most_active_people: Most active people
+ most_active_people_as_reviewer: Most active user account
+ most_mentioned_people: Most mentioned people as contact, creator, contributor or curator
+ most_mentioned_people_as_reviewer: User account who published notes, reviews, and projects
+ ontologies_activity_on: Ontology activity
+ ontologies_by: Ontologies by %{type}
+ ontologies_contributors: Contributors to ontology development
+ ontologies_count_by_catalog: Number of ontologies in each semantic artefact catalog
+ ontologies_formats: Representation language
+ ontologies_languages: Natural languages
+ ontologies_licenses: Licenses
+ ontologies_with_notes_reviews_projects: Ontologies with notes, reviews, and projects
+ ontology_fairness_evaluator: Ontology FAIRness Evaluator (O’FAIRe)
+ ontology_formality_levels: Formality levels
+ ontology_properties_pie_charts: Pie charts retated to object description properties (i.e., meatdata properties used to describe ontology objects).
+ ontology_relations_network: Ontology relations network
+ ontology_tools: Most used tools to build ontologies
+ owl_ontology_author_uris: Properties used to specify object author
+ owl_ontology_definition_uris: Properties used to specify objects definition
+ owl_ontology_preflabel_uris: Properties used to specify objects preferred label
+ owl_ontology_synonym_uris: Properties used to specify object synonyms
+ properties_usage_proportion: Pie charts related to the most frequent values for certain metadata properties
+ properties_use: Property usage
+ relations_between_stored_ontologies: Set of relationships between %{site} ontologies as captured by metadata. Green ontologies are stored in the repository while those in blue are external resources.
+ size: size
+ title: "Landscape"
+ ontologies_properties: Ontologies properties
+ layout:
+ header:
+ account_setting: Account settings
+ annotator: Annotator
+ browse: Browse
+ documentation: Documentation
+ help: Help
+ landscape: Landscape
+ login: Login
+ logout: Logout
+ mappings: Mappings
+ recommender: Recommender
+ publications: Publications
+ release_notes: Release Notes
+ search_prompt: Search in %{portal_name} ...
+ submit_feedback: Send Feedback
+ support: Support
+ cite_us: Cite Us
+ footer:
+ products: Products
+ ontoportal: OntoPortal
+ release_notes: Release Notes
+ api: API
+ tools: Tools
+ sparql: SPARQL
+ support: Support
+ contact_us: Contact Us
+ wiki: Wiki
+ documentation: Documentation
+ agro_documentation: AgroPortal documentation
+ agreements: Legal
+ terms: Terms and Conditions
+ privacy_policy: Privacy Policy
+ legal_notices: Legal Notices
+ cite_us: Cite Us
+ acknowledgments: Acknowledgments
+ about: About
+ about_us: About Us
+ projects: D2KAB
+ team: Team
+ notices:
+ slice: Slice
+ at: at
+ visit_the_site: visit the full site
+ login:
+ invalid_account_combination: "Invalid account name/password combination"
+ authentication_failed: "%{provider} authentication failed"
+ admin_logged_out: Logged out %{old_user}, returned to %{user}
+ user_logged_out: You have successfully logged out
+ try_again_notice: ". Please try again."
+ reset_password_again: ". Please reset your password again."
+ custom_ontology_set: "The display is now based on your Custom Ontology Set."
+ welcome: "Welcome "
+ error_account_name: Please enter an account name
+ error_password: Please enter a password
+ enter_email: Enter your username
+ enter_password: Enter your password
+ forgot_password: Forgot password?
+ invalid_login: Errors on the form
+ no_account: Do not have an account?
+ password: Password
+ register: Register
+ title: Login
+ username_or_email: Username
+ login_with_provider: Login with %{provider}
+ reset_password_message: A password reset email has been sent to your email address, please follow the instructions to reset your password.
+ back_home_button: Back home
+ recover_password: Recover password
+ email: Email
+ user: User
+ email_address_associated: Enter the email address associated with your account and we will send an email with instructions to reset your password.
+ email_placeholder: Enter the email
+ send_instructions: Send instructions
+ statistics:
+ title: "%{portal} Statistics"
+ lead: (last %{last_years} years)
+ ontologies: Ontologies
+ users: Users
+ projects: Projects
+ date: Date
+ ontology_visits: Ontology visits
+ mappings:
+ all: All
+ description: Dive into an overview of the mappings in the bubble view, efficiently locate a specific ontology in the table view or upload your own mappings.
+ tabs:
+ bubble_view: Bubbles view
+ table_view: Table view
+ upload_mappings: Upload mappings
+ filter_ontologies: Filter ontologies in the bubble view
+ filter_bubbles: Filter bubbles
+ external_mappings: "External Mappings (%{number_with_delimiter})"
+ interportal_mappings: "Interportal Mappings - %{acronym} (%{number_with_delimiter})"
+ test_bulk_load: This is the mappings produced to test the bulk load
+ mapping_created: Mapping created
+ mapping_updated: Mapping updated
+ mapping_deleted: "%{map_id} deleted successfully"
+ mapping_not_found: "Mapping %{id} not found"
+ error_of_source_and_target: Source and target concepts need to be specified
+ mapping_issue: "Mapping issue with '%{mapping}' : %{message}"
+ find_mappings: Find mappings of a class/concept
+ intro: Find all the mappings of an ontology
+ loading_mappings: Loading mappings...
+ no_mappings_available: No mappings available
+ title: Mappings
+ upload_mappings: Upload mappings
+ select_ontologies_list: Select ontologies
+ bubble_view_legend:
+ bubble_size: "Bubble size:"
+ bubble_size_desc: "The global number of mappings with all other ontologies."
+ color_degree: "Color degree:"
+ color_degree_desc: "The number of mappings with the selected ontology."
+ yellow_bubble: "Yellow bubble: "
+ selected_bubble: "The selected bubble."
+ less_mappings: "Less mappings"
+ more_mappings: "More mappings"
+ count:
+ ontology: Ontology
+ mappings: Mappings
+ no_mappings: There are no mappings to or from this ontology
+ form:
+ source_class: Source class
+ mapping_name: Mapping description (name)
+ contact_info: Contact info
+ mapping_source_name: Source name (Mapping set id)
+ mapping_comment: Comment
+ mapping_relation: Mapping relation type
+ save: Save
+ mapping_table:
+ mapping_to: Mapping to
+ relations: Relations
+ source: Source
+ type: Type
+ actions: Actions
+ no_mappings: There are currently no mappings for this class.
+ mapping_type_selector:
+ mapping_type: Mapping type
+ internal: Internal
+ interportal: InterPortal
+ external: External
+ target_class: Target class
+ details: Details
+ ontology_acronym: Ontology (acronym)
+ class: Class
+ ontology_acronym_placeholder: Enter the ontology ACRONYM
+ class_uri_placeholder: Enter the class URI
+ ontology_uri_placeholder: Enter the ontology URI
+ show_line:
+ edit_modal: Edit
+ delete_button: Delete
+ turbo_confirm: Are you sure?
+ edit_mapping: Edit mapping for %{preflabel}
+ show:
+ no_mappings_found: No mappings found
+ bulk_loader:
+ loader:
+ example_of_valid_file: See an example of a valid a file
+ save: Save
+ loaded_mappings:
+ mappings_created: "%{size} mappings created successfully"
+ id: Id
+ source: Source
+ target: Target
+ relation: Relation
+ properties: Properties
+ actions: Actions
+ see_other_properties: See other properties
+ agents:
+ not_found_agent: Agent with id %{id}
+ add_agent: New Agent added successfully
+ update_agent: Agent successfully updated
+ agent_usages_updated: Agent usages successfully updated
+ agent_already_deleted: Agent %{id} already deleted
+ agent_deleted_successfully: Agent %{id} deleted successfully
+ ontology_not_valid: "ontology is not valid, here are the errors: "
+ save: Save
+ not_used: Not used
+ see_usages_count: See usages (%{count})
+ delete: Delete
+ delete_error: "Can't delete this %{agent} because still used"
+ turbo_confirm: Are you sure?
+ modal_title: "Agent \"%{name}\" usages"
+ form:
+ type: Type
+ person: Person
+ organization: Organization
+ name: Name
+ email: Email
+ acronym: Acronym
+ homepage: Homepage
+ creator: Creator
+ identifiers: Identifiers
+ affiliations: Affiliations
index:
- intro: Get annotations for ecological text with classes from the semantic resources.
- annotatorplus_html: Check out AnnotatorPlus beta; a new version of the Annotator with added support for negation, and more!
- fast_context:
- tooltip: "Enable FastContext to detect : if a concept has been negated (affirmed, negated), who experienced the found concept (patient, other), when the annotated concept occurred (recent, historical, hypothetical), and/or if the annotated concept is uncertain (certain, uncertain)."
- sample_text: Invasive alien species are plants, animals, pathogens and other organisms that are non-native to an ecosystem, and which may cause economic or environmental harm or adversely affect human health.
-
- nbco_annotatosplus:
+ create_new_agent: Create New Agent
+ first_name: First name
+ usages: Usages
+ actions: Actions
+ no_agents: There are currently no agents.
+ ontology_details:
+ sections:
+ classes: Classes
+ summary: Summary
+ properties: Properties
+ instances: Instances
+ notes: Notes
+ mappings: Mappings
+ widgets: Widgets
+ sparql: Sparql
+ concepts: Concepts
+ schemes: Schemes
+ collections: Collections
+ concept:
+ definitions: Definitions
+ id: ID
+ in_schemes: In schemes
+ member_of: Member of
+ no_preferred_name_for_selected_language: No preferred name for selected language.
+ obsolete: Obsolete
+ preferred_name: Preferred name
+ synonyms: Synonyms
+ type: Type
+ metadata:
+ additional_metadata: Additional Metadata
+ header:
+ last_submission_date: Last submission date
+ projects:
+ project_not_found: "Project not found: %{id}"
+ project_successfully_created: Project successfully created
+ error_unique_acronym: Project with acronym %{acronym} already exists. Please enter a unique acronym.
+ project_successfully_updated: Project successfully updated
+ error_delete_project: "Project delete failed: %{errors}"
+ project_successfully_deleted: Project successfully deleted
+ contacts: Contacts
+ create_new_project: Create new project
+ created: Created
+ creator: User
+ delete_admin_only: Delete (admin only)
+ delete_confirm: Are you sure?
+ description: Description
+ description_text: Description text
+ edit_text: Edit
+ home_page: Home page
index:
- intro: >
- The NCBO Annotator+ is a proxy calling the NCBO Annotator Web service on the NCBO BioPortal.
-
- Tchechmedjiev, A., Abdaoui, A., Emonet, V., Melzi, S., Jonnagaddala, J., & Jonquet, C. (2018). Enhanced functionalities for annotating and indexing clinical text with the NCBO Annotator+. Bioinformatics, 34(11), 1962-1965.
-
- If using the API, please provide a valid NCBO BioPortal apikey and hit the service at http://services.bioportal.lirmm.fr/ncbo_annotatorplus
- Text submitted to the NCBO Annotator+ must be in English.
- sample_text: Invasive alien species are plants, animals, pathogens and other organisms that are non-native to an ecosystem, and which may cause economic or environmental harm or adversely affect human health.
+ intro: Browse a selection of projects that use %{site} ontologies
+ institutions: Institutions
+ ontologies: Ontologies
+ project_description: Project Description
+ self: Projects
+ title: Projects List
+ view_projects_help: View projects help
+
+ show:
+ title: Project %{name}
+ edit_project: Edit Project
+ description: "Description:"
+ institution: "Institution:"
+ contacts: "Contacts:"
+ home_page: "Home Page:"
+ ontologies_used: Ontologies Used
+ no_ontologies_associated: No ontologies are currently associated with this project
+ form:
+ errors_on_form: Errors On Form
+ name: "Name: *"
+ acronym: "Acronym: *"
+ administrators: "Administrators: *"
+ home_page: "Homepage: *"
+ example: "Example:"
+ description: "Description:*"
+ select_ontologies: Select Ontologies Used
+ select_administrators: Select administrators
+
+ edit:
+ title: Editing Project %{name}
+ editing_project: Editing project
+ cancel: Cancel
+ update_project: Update Project
+
+ new:
+ title: Add your project
+ new_project: New project
+ create_project: Create Project
recommender:
- intro: Get recommendations for the most relevant semantic resources based on an excerpt from a ecological text or a list of keywords
- sample_text: Ecological attributes (=ecological characteristics) are features of a taxon such as its range size, life history, geographical distribution, climatic tolerances, habitat types, environmental indicator values, edaphic preferences, and so on, that describe the overall ecology of the taxon.
- sample_keywords: Ecological attributes (=ecological characteristics) are features of a taxon such as its range size, life history, geographical distribution, climatic tolerances, habitat types, environmental indicator values, edaphic preferences, and so on, that describe the overall ecology of the taxon.
- search:
+ title: Recommender
+ intro: Get recommendations for the most relevant ontologies from an excerpt of text or a list of keywords
+ options: Options
+ input: Input
+ text: Text
+ keywords: Keywords
+ output: Output
+ ontologies: Ontologies
+ ontology_sets: Ontology sets
+ hint: Paste a paragraph of text or some keywords ...
+ weights_configuration: Weights configuration
+ coverage: Coverage
+ acceptance: Acceptance
+ knowledge_detail: Knowledge detail
+ specialization: Specialization
+ ontologies_configuration: Ontologies configuration
+ max_ont_set: Maximum number of ontologies per set
+ select_ontologies: Select ontologies
+ get_recommendations: Get recommendations
+ edit: Edit
+ results_title: Recommended ontologies
+ call_annotator: Call Annotator with the same input
+ cite: Cite
+ results_table:
+ ontology: Ontology
+ final_score: Final score
+ coverage_score: Coverage score
+ acceptance_score: Acceptance score
+ detail_score: Detail score
+ specialization_score: Specialization score
+ annotations: Annotations
+ register:
+ account_errors: 'Errors creating your account:'
+ confirm_password: Confirm password
+ create_account: Create new account
+ email: Email
+ first_name: First name
+ last_name: Last name
+ mailing_list: Register to the %{site}'s mailing list
+ accept_terms_and_conditions: I acknowledge and accept
+ terms_and_conditions: "%{site}'s terms and conditions."
+ optional: "(Optional)"
+ password: Password
+ title: Register
+ username: Username
+ users:
+ account_successfully_created: Account was successfully created
+ account_successfully_updated: Account was successfully updated
+ user_deleted_successfully: User deleted successfully
+ not_permitted: Not permitted
+ error_saving_custom_ontologies: Error saving Custom Ontologies, please try again
+ custom_ontologies_cleared: Custom Ontologies were cleared
+ custom_ontologies_saved: Custom Ontologies were saved
+ subscribe_flash_message: "You have successfully %{action} %{to_or_from} our user mailing list: %{list}"
+ error_subscribe: Something went wrong ...
+ validate_email_address: Please enter an email address
+ validate_password: Please enter a password
+ validate_password_confirmation: Your Password and Password Confirmation do not match
+ recaptcha_validation: Please fill in the proper text from the supplied image
+ validate_orcid: Please enter a valid ORCID.
+ validate_username: please enter a valid username
+ valid_email_adresse: Please enter a valid email adresse
+ validate_terms_and_conditions: Accepting the terms and conditions is required, please check the box to proceed.
+ first_name_required: First name field is required
+ last_name_required: Last name field is required
index:
- intro: Search for a class in multiple semantic resources
- search_keywords_placeholder: Enter a class, e.g. Shape
- categories_placeholder: Start typing to select categories or leave blank to use all
- property_definition: Named association between two entities. Examples are "definition" (a relation between a class and some text) and "part-of" (a relation between two classes).
- obsolete_definition: >
- A class that the authors of the ontology have flagged as being obsolete and which they recommend that people not use. These classes
- are often left in ontologies (rather than removing them entirely) so that existing systems that depend on them will continue to function.
+ first_name: First name
+ last_name: Last name
+ username: Username
+ email: Email
+ roles: Roles
+ ontologies: Ontologies
+ project: Project
+ created: Created At
+ actions: Actions
+ detail: Detail
+ delete: Delete
+ login_as: Login as
+ error_delete_message: Can't delete this user because still used
+ turbo_confirm: Are you sure?
+ edit:
+ user_to_admin: Are you sure you want to make this user an admin?
+ admin_privileges: Are you sure you want to revoke admin privileges for this user?
+ errors_creating_account: "Errors creating your account:"
+ edit_information: Edit personal information
+ first_name: First name
+ last_name: Last name
+ username: Username
+ email: Email
+ orcid_id: ORCID ID
+ github_id: Github ID
+ new_password: New password
+ confirm_password: Confirm password
+ change_password: Change password
+ show:
+ my_account: My account
+ first_name: "First name:"
+ last_name: "Last name:"
+ username: "Username:"
+ email: "Email:"
+ orcid_id: "ORCID ID:"
+ github_id: "GitHub ID:"
+ mailing_list_subscription: Mailing list subscription
+ mailing_list_description: Register to the %{portal} announcements mailing list.
+ api_key_description: Your API Key can be used to access %{portal} Web services
+ api_documentation: API documentation
+ custom_semantic_resource: Custom ontology set
+ please: Please
+ modify_custom_semantic_resource: |
+ visit the main site
+ to modify your Custom Ontology Set.
+ customize_portal_display: "Customize your %{portal} display: Pick the ontologies that you want to see on %{portal} will hide all other ontologies."
+ select_semantic_resources: Select ontologies
+ no_semantic_resources: You haven't picked any ontologies yet
+ note_feature_logged_in: "Note: this feature works only when you are logged in."
+ save_custom_semantic_resources: Save custom ontologies
+ not_subscribed: Not subscribed to any ontology
+ submitted_semantic_resources: Submitted Ontologies
+ upload_semantic_resources: Upload Ontologies
+ projects_created: Projects Created
+ no_project_created: No project created
+ unsubscribe: Unsubscribe
+ subscribe: Subscribe
+ subscriptions: Subscriptions
+ no_uploaded_resources: You didn't upload any ontology yet
+ notes: Notes
+ search:
+ no_search_class_provided: No search class provided
+ search_place_holder: Enter a term, e.g. plant height
+ advanced_options:
+ search_language: Search language
+ ontologies: Ontologies
+ include_in_search_title: Include in search
+ include_in_search_values:
+ property_values: Property values
+ obolete_classses: Obsolete classes
+ ontology_views: Ontology views
+ show_only_title: Show only
+ show_only_values:
+ exact_matches: Exact matches
+ classes_with_definitions: Classes with definitions
+ show_advanced_options: Show options
+ hide_advanced_options: Hide options
+ match_in: Match in
+ ontologies: ontologies
+ result_component:
+ details: Details
+ visualize: Vizualize
+ more_from_ontology: more from this ontology
+ reuses_in: Reuses in
+ notes:
+ no_notes: No notes to display
+ filter_hide_archived: Hide Archived
+ new_class_proposal: New Class Proposal
+ new_relationship_proposal: New Relationship Proposal
+ change_property_value_proposal: Change Property Value Proposal
+ new_comment_added: New comment added successfully
+ note_deleted_successfully: Note %{note_id} was deleted successfully
+ note_not_found: Note %{note_id} was not found in the system
+ comment: Comment
+ new_comment:
+ subject: Subject
+ comment: Comment
+ save: Save
+ new_proposal:
+ reason_for_change: Reason for change
+ new_target: New target
+ old_target: Old target
+ relationship_type: Relationship type
+ property_id: Property id
+ new_value: New value
+ old_value: Old value
+ class_id: Class id
+ label: Label
+ synonym: Synonym
+ definition: Definition
+ parent: Parent
+ save: save
+ note_line:
+ alert_text: "Are you sure you want to delete the note ''%{subject}'' created by %{creator}? This action CAN NOT be undone!!!"
+ delete: Delete
+ archived: archived
+ comment: Comment
+ thread:
+ submitted_by: submitted by
+ reply:
+ about_note_decorator: about %{note_decorator}
+ comment: Comment
+ save: save
+ cancel: cancel
+ ontolobridge:
+ problem_of_creating_new_term: "Problem creating a new term %{endpoint}: %{class} - %{message}"
+ new_term_instructions_saved: New term request instructions for %{acronym} saved
+ error_saving_new_term_instructions: Unable to save new term instructions for %{acronym} due to a server error
+ submissions:
+ filter:
+ all_formats: All formats
+ sort_by_name: Sort by name
+ sort_by_classes: Sort by classes count
+ sort_by_instances_concepts: Sort by instances/concepts count
+ sort_by_submitted_date: Sort by submitted date
+ sort_by_creation_date: Sort by creation date
+ sort_by_fair_score: Sort by FAIR score
+ sort_by_popularity: Sort by popularity
+ sort_by_notes: Sort by notes
+ sort_by_projects: Sort by projects
+ no_submissions_for_ontology: "No submissions for ontology: %{ontology}"
+ submission_updated_successfully: Submission updated successfully
+ save_button: Save
+ id: ID
+ version: Version
+ actions: Actions
+ modified: Modified
+ submitted: Submitted
+ download: Download
+ toggle_dropdown: Toggle Dropdown
+ go_to_api: Go to API
+ edit_button: Edit
+ delete_submission_alert:
+ content_1: "Are you sure you want to delete submission "
+ content_2: " for ontology "
+ content_3: "? This action CAN NOT be undone!!!"
+ ontoportal_virtual_appliance:
+ problem_adding_account: "Problem adding account %{id}: account does not exist"
+ require_login: You must be logged in to access this section
+ title: OntoPortal Virtual Appliance Download
+ intro_paragraph:
+ main: |
+ OntoPortal Virtual Appliance distribution contains a pre-installed,
+ pre-configured version of commonly-used open source NCBO software running
+ on a Linux operating system.
+ included_software: "The following software is included on the image:"
+ ontologies_api: Ontologies API (REST service)
+ annotator: Annotator
+ recommender: Recommender
+ web_user_interface: BioPortal Web User Interface (including ontology visualization, widgets, and Annotator UI)
+ see_documentation: Please see our
+ more_information: for more information on working with the Appliance.
+ download_button_text: Download Latest OntoPortal
+ archives:
+ title: Archives
+ archival_distribution: |
+ The OntoPortal 2.5 Virtual Appliance is not longer offered for new
+ users. This archival distribution is available only as a backup for
+ those who registered for the Appliance before June 2020
+ version: version 2.5
+ admin_add_users:
+ title: "Admin: Add Users"
+ label_account_name: "Account Name:"
+ add_user_button: Add User
+ accounts_with_access: "Accounts with access"
+ export_users_link: "Export Appliance Users As CSV"
+ bioportal_user: BioPortal User ID
+ submission_inputs:
+ edit_ontology_title: Edit ontology
+ metadata_selector_label: "Filter properties to show"
+ metadata_selector_placeholder: "Start typing to select properties"
+ administrators: Administrators
+ ontology_skos_language_link: Please refer to the documentation for more details.
+ ontology_skos_language_help: >
+ SKOS vocabularies submitted to %{portal_name} shall follow a few constraints (e.g., contain a minimum of one skos:ConceptScheme also typed as owl:Ontology)
+ and top concept assertion. %{link}
+ ontology_obo_language_link: the OBOinOWL parser.
+ ontology_obo_language_help: >
+ OBO ontologies submitted to %{portal_name} will be parsed by the OWL-API which integrates %{link}
+ The resulting RDF triples will then be loaded in %{portal_name} triple-store.
+ ontology_owl_language_link: the Protégé
+ ontology_owl_language_help: >
+ OWL ontologies submitted to %{portal_name} will be parsed by the OWL-API. An easy way to verify if your ontology will parse is to open it with
+ %{link}
+ software which does use the same component.
- projects:
- index:
- intro: Browse a selection of projects that use %{site} resources.
+ ontology_umls_language_link: by the UMLS2RDF tool.
+ ontology_umls_language_help: >
+ UMLS-RRF resources are usually produced %{link}
+
+ groups: Groups
+ visibility: Visibility
+ accounts_allowed: Add or remove accounts that are allowed to see this ontology in %{portal_name}.
+ ontology_view_of_another_ontology: Is this ontology a view of another ontology?
+ contact: Contact
+ equivalents: Equivalents
+ validators: Validators
+ help_text: Help text
+ contact_name: "%{name} Name"
+ contact_email: "%{name} Email"
+ edit_metadata_instruction: "Edit the metadata of your ontology here. Some of these values are used by %{portal_name} functionalities, including for FAIRness assessment. %{link}"
+ edit_metadata_instruction_link: "See guidelines and recommendations for metadata here."
+ license_help: "%{portal_name} requires an URI for the license. If you do not find your choice here, %{link}"
+ license_help_link: "Please pick up an URI from here."
+ deprecated_help: "An ontology with status retired shall necessarily be also deprecated, but not the opposite."
+ known_usage_help: "Consider also declaring %{metadata_knownUsage_help}"
+ known_usage_help_link: "the projects that are using the ontology"
+ help_creator: "The following properties take for value an 'agent' in %{portal_name} (either a person or an organization). These agents are shared over all the ontologies and suggested with autocompletion if they already exist. Editing an agent here will change it to all the ontologies that agent is involved in."
+ version_help: "For more information on how to encode versioning information in an ontology, see %{link}"
+ version_helper_link: "guidelines and recommendations."
+ instances:
+ id: ID
+ type: Type
+ label: Label
+ collections:
+ error_valid_collection: "Error: You must provide a valid collection id"
+ no_collections_alert: "%{acronym} does not contain collections (skos:Collection)"
+ id: ID
+ preferred_name: Preferred name
+ members_count: Members count
+ type: Type
+ change_requests:
+ change_request_success_message: Your change request was successfully submitted! View the %{url} on GitHub.
+ label: Label
+ type: Type
+ comment: Comment
+ close: Close
+ submit: Submit
+ check_resolvability:
+ check_resolvability_message_1: "The URL is resolvable and support the following formats: %{supported_format}"
+ check_resolvability_message_2: "The URL resolvable but is not content negotiable, support only: %{supported_format}"
+ check_resolvability_message_3: The URL is not resolvable and not content negotiable (returns %{status}).
+ uri_placeholder: Type a URI to test its resolvability
+ show_help: Show help
+ format_not_specified: Format not specified
+ how_it_works:
+ title: How it works
+ content_1: |
+ The check resolvability tool allows you to test if a given URL is resolvable. It is based on the HTTP HEAD method.
+ We check the resolvability of a URL by sending a HEAD request to the URL and checking if the response status code is 200 (OK) and
+ the returned content type is equal to one of the following %{resolvability_formats}.
+ content_2: |
+ We have a timeout set to %{resolvability_timeout} seconds, so if the URL is not resolvable within that time, the check will fail.
+ And a max redirections set to %{resolvability_max_redirections}, so if the URL is not resolvable within that number of redirections, the check will fail.
+ resolving_uri:
+ title: Resolving a URI
+ content: |
+ In the context of web semantics, dereferencing refers to the process of resolving and obtaining the actual data associated with a Uniform Resource Identifier (URI). In simpler terms, it involves following a link represented by a URI/IRI to retrieve information or resources linked to that identifier.
+ In the Semantic Web, URIs are used to uniquely identify resources, and dereferencing allows systems to access and retrieve data related to those resources. When a URI/IRI is dereferenced, it typically leads to the retrieval of RDF (Resource Description Framework) data or other structured information that describes the resource in a machine-readable format. This enables systems to understand and process the meaning of the linked data, facilitating the exchange and integration of information on the web.
+ content_negotiation:
+ title: Content negotiation
+ content: |
+ Content negotiation in the context of the Semantic Web refers to the mechanism by which two communicating parties, such as a client and a server, agree on the most suitable representation of a resource during the process of dereferencing a URI or IRI. This negotiation aims to ensure effective communication between different systems that may prefer different data formats or languages.
+ In other words, when a client requests a resource by dereferencing a URI, it indicates its preferences for the format or language of the response data through HTTP headers or other negotiation mechanisms. The server, in turn, examines these preferences and selects the most appropriate representation of the resource based on what is available.
+ different formats can be agreed upon between a client and server when accessing linked data. Common formats include:
+ RDF/XML: XML-based representation of Resource Description Framework data.
+ Turtle: Human-readable serialization format for RDF.
+ JSON-LD: JSON-based format for linked data.
+ N-Triples and N-Quads: Text formats for expressing RDF triples and quads.
+ HTML: Markup language for web pages, also used to embed RDF data.
+ RDFa: Embedding RDF data in HTML or XML using attributes.
+ SPARQL Query Results XML and JSON: Formats for representing SPARQL query results.
+
+ errors:
+ error_message: We're sorry but something has gone wrong.
+ notification_error: We have been notified of this error.
+ go_home_button: Go home
+ send_feedback_button: Send a feedback
+ not_found_page: Page not found
+ schemes:
+ error_valid_scheme_id: "Error: You must provide a valid scheme id"
+ no_main_scheme_alert: no main scheme defined in the URI attribute
+ no_schemes_alert: "%{acronym} does not contain schemes (skos:ConceptScheme)"
+ id: ID
+ preferred_name: Preferred name
+ type: Type
+ fair_score:
+ fairness_unreachable_warning: FAIRness service issue unreachable
+ go_to_api: Go to API
+ mod_link: MOD1.4
+ see_the_used_properties: see the used properties
+ metadata_properties: Metadata properties listed in the following are picked from %{mod_link}.
+ ontology_repository: This ontology repository implements %{mod_link} but does not necessarily encode metadata with the same properties (%{submission_link}).
+ see_possible_credits: See possible credits
+ see_metadata_used_properties: See metadata used properties
+ not_found: not found
+ "null": "null"
+ view_fair_scores_definitions: "You are seeing the FAIRness assessment score for this ontology in AgroPortal. FAIR scores are computed with the O'FAIRe methodology. More details here: https://github.com/agroportal/fairness"
+ ontologies_metadata_curator:
+ #bulk_edit: Start bulk edit
+ #use_the_bulk_edit: To use the bulk edit select in the table submissions (the rows) and metadata properties (the columns) for which you want to edit
+ start_the_bulk_edit: Select in the table submissions (rows) and metadata properties (columns) to start the bulk edit
+ alert_success_submissions: Submissions were successfully updated
+ ontologies: Ontologies
+ get_values: Get values
+ select_ontologies_and_metadata: select ontologies and the metadata properties
+ include_all_submissions: Include all submissions
+ apply_the_change_for_all: Apply the change for all
+ update_the_current_displayed_content: "will update the current displayed content to all the following submissions:"
+ save: Save
ontologies:
- intro: Browse the library of semantic resources.
+ showing_ontologies_size: "Showing %{ontologies_size} of %{analytics_size}"
+ filters: Filters
+ no_license: No license
+ view_license: View license
+ access_rights_information: Additional license and access rights information
+ referred_to: It can also be referred to as
+ private_ontology: Private Ontology
+ formality_levels: Formality levels
+ categories: Categories
+ groups: Groups
+ ontology_types: Ontology types
+ natural_languages: Natural languages
+ showing: Showing
+ metadata_properties: of %{acronym} metadata properties are filled
+ home_page: Home Page
+ ontology_processing_failed: "The ontology processing failed, with the current statuses: %{status}"
+ ontology_parsing_succeeded: "The ontology parsing succeeded, but some processing steps failed, here are the current statuses: %{status}"
+ upload_an_ontology: Upload an ontology. Sections such as %{ontology} will be available once done.
+ new_ontology_is_processing: The ontology is processing. Sections such as %{ontology} will be available once processing is complete.
+ ontology_is_processing: The ontology is processing. Sections such as %{ontology} will be updated once processing is complete.
+ contact_support: Contact support
+ edit_natural_languages: Edit natural languages of %{acronym}
+ edit_available_languages: Click here to edit available languages
+ add_new_submission: Add new submission
+ edit_metadata: Edit metadata
+ go_to_api: Go to API
+ projects_using_ontology: Projects using %{acronym}
+ create_new_project: Create new project
+ no_projects_using_ontology: No projects using %{acronym}
+ outside: outside
+ relation_with_other_ontologies: Relation with other ontologies either in %{inside} or %{outside}
+ ontology_search_prompt: 'Search an ontology or a term (e.g., plant height)'
+ views: Views
+ create_new_view: Create new view
+ expand_all: Expand All
+ collapse_all: Collapse All
+ administrator: "Administrator:"
+ create_new_view_submission: create new view submission
+ description: "Description:"
+ definition: "Definition:"
+ created_by: "Created By:"
+ submission: Submission
+ release_date: Release Date
+ upload_date: Upload Date
+ downloads: Downloads
+ admin_links: Admin Links
+ edit_link: Edit
+ no_views: No views available for %{acronym}.
+ fairness_assessment_questions: O'FAIRe FAIRness assessment questions
+ see_details: See details
+ collecting_data: We are still collecting data for %{acronym}
+ location: Location
+ allow_users: Allow users to view the metadata of your ontology (Summary) only.
+ metadata_only: Metadata only (No file)
+ load_from_url: Load from URL
+ new_versions_loaded: New versions loaded on a nightly basis.
+ upload_local_file: Upload local file
+ ontology_submitted: Ontology submitted successfully!
+ users_can_see: Users can now see
+ your_ontology: your ontology
+ exploring_and_searching: |
+ in our ontology list but they cannot explore or search it. To enable exploring and searching,
+ please upload a full version of your ontology.
+ submitting_ontology_view: Thank you for submitting your ontology view to %{site}.
+ submitting_ontology: Thank you for submitting your ontology to %{site}.
+ processing_message: |
+ We will now put your ontology in the queue to be processed. Please keep in mind that it may take up to several
+ hours before %{site} users will be able to explore and search your ontology.
+ notification_message: "When your ontology is ready for viewing, you will receive an email notification and it will be available here:"
+ contact_support_at: "If you have any questions or problems, please email the %{site} support team at:"
+ collecting_data_message: We are still collecting data for %{acronym}
+ submit_new_ontology: Submit new ontology
+ details: Details
+ general_information: General information
+ dates_and_contacts: Dates and contacts
+ uri: URI
+ change_notes: Change notes
+ modification_date: Modification date
+ date_of_original_creation: Date of original creation
+ concepts_browsers:
+ select_scheme: Please select a scheme to display
+ missing_roots: Missing roots for %{acronym} (skos:topConceptOf)
+ select_collection: Please select a collection to display
+ placeholder_jump: Jump to
+ label_jump: "Jump to:"
+ filter: Filter
+ browser:
+ admin_welcome: Welcome admin,this coloring indicates admin-only features
+ show_private_ontology: Show private ontology only
+ show_ontology_views: Show ontology views
+ show_retired_ontologies: Show retired ontologies
+ search_placeholder: Start typing to filter ontologies, e.g., AGROVOC...
+ sections:
+ classes: Classes
+ individuals: Individuals
+ properties: Properties
+ maximum_depth: Maximum depth
+ maximum_number_of_children: Maximum number of children
+ average_number_of_children: Average number of children
+ classes_with_a_single_child: Classes with a single child
+ classes_with_more_than_25_children: Classes with more than 25 children
+ classes_with_no_definition: Classes with no definition
+ identifiers: Identifiers
+ identifiers_tooltip: Principal identifiers of the ontology.
+ dates: Dates
+ person_and_organization: Persons and organizations
+ other_links: Other links
+ info_tooltip_links: Metadata properties that highlight the links enabling access to datasets, downloading ontologies, etc
+ projects_and_usage_information: Projects and usage information
+ info_tooltip_projects: Details pertaining to the utilization of the ontology.
+ methodology_and_provenance: Methodology and provenance
+ community: Community
+ content: Content
+ info_tooltip_properties_dropdown: Metadata properties primarily encompass the design, methods, and actions to create the ontology. This includes elements such as the tools and software employed by the creator of the ontology during its configuration.
+ visits: Visits
+ views: Views of %{acronym}
+ create_new_view: Create new view
+ configuration_metadata: Configuration metadata
+ info_tooltip_configuration: Regroup all the metadata properties used by the portal to configure the behavior of the resource
+ label_groups: Groups
+ download_as_csv: Download as CSV
+ scroll_down_to_see_more: Scroll down to see more
- concepts:
- request_term:
- new_term_instructions: >
-
This ontology integrates with OntoloBridge, allowing community users to suggest additions to the public ontology. Complete the template below to submit a term request directly to the ontology maintainer.
-
-
Term Label (required) Suggested term name. If a term can be described with multiple synonyms, only list the preferred name here.
-
-
-
Term description (required) A brief definition, description, or usage of your suggested term. Additional term synonyms may be listed in this section.
-
-
-
Superclass (required) The parent term of the suggested term. The parent term should be an existing entry of the current ontology. The superclass can be selected directly from Bioportal's Classes tree viewer.
-
-
-
References (optional) Provide evidence for the existence of the requested term such as Pubmed IDs of papers or links to other resources that describe the term.
-
-
-
Justification (optional) Provide any additional information about the requested term here.
-
- mappings:
- intro: Browse mappings between classes in different semantic resources
+ widgets: Widgets are only available for ontologies stored in %{site}.
+ add_acronym_widgets: Add %{acronym} Web Widgets to your site
+ widget_block_component_title_1: Jump To
+ widget_block_component_description_1: Type a class name from %{acronym} and jump to it in %{site}
+ download: Download the
+ put_on_server: and put it on your server.
+ copy_and_paste: Copy the code below and paste it to your HTML page
+ note: "Note:"
+ use_quick_jump: If you would like to use Quick Jump across multiple ontologies
+ enter_list_of_ontologies: You can enter a comma-separated list of ontology ids
+ set_the_variable: "You can set the variable to 'all' to search all ontologies in %{site}:"
+ include_definitions: "To include definitions in the Jump To drop-down, add the following variable in Javascript:"
+ info_pasted_code: In the code that you just pasted, make sure to change the path to the quick_jump.js file to point to the location where you put the file (relative to your HTML file)
+ example_to_use_code: "For example, if you put the quick_jump.js file in the same directory as your HTML file, this is the code you would use:"
+ help_visit: For more help visit
+ widget_block_component_title_2: Autocomplete
+ widget_block_component_description_2: Fill your form fields with classes from %{acronym}
+ example_1: Example 1 (start typing the class name to get its full URI)
+ example_2: Example 2 (get the ID for a class)
+ example_3: Example 3 (get the preferred name for a class)
+ include_file: In the header for the page where you want the form field, include the
+ use_widget: "On your form, for the fields where you want to use the class-selection widget, specify the field's class in the following format:"
+ for_example: For example,
+ use_ontology: will use NCI Thesaurus (ontology id is NCIT) and will put the class URI in the field after the user selects the class from the pull-down list.
+ use_list: "In addition to single ontology ids, you can use a list:"
+ or: OR
+ use_all_to_search: "use 'all' to search across all %{site} ontologies:"
+ autocomplete_widget_accesses: The autocomplete widget accesses ontology content from the latest version of the ontology.
+ use_following_parameters: "You can use the following parameters to select which value will be placed into the user-visible input field:"
+ uri: uri
+ shortid: shortid
+ name: name
+ class_uri_description: "Put the complete URI of the class (e.g.,"
+ class_uri_example: 'put the complete URI of the class (e.g., %{link})'
+ class_shortid_description: put the short id of the class, as used in %{site} (e.g., "Common_Neoplasm");
+ class_name_description: put the preferred name of the class (e.g., "Common Neoplasm");
+ hidden_elements_description: "In addition to the input element you defined, there are four hidden form elements that are created and then set when a user selects a class from the list. For example, if you create a field with this code:"
+ hidden_elements_example: "The 'name' attribute is used to create the four following fields (note how the 'a' from the name attribute is appended to the id attribute):"
+ additional_parameters: Additional parameters are documented on the
+ more_help_visit: For more help visit
+ widget_block_component_title_3: Visualization
+ widget_block_component_description_3: Display a visualization for a given class in %{acronym}
+ widget_block_component_title_4: Tree Widget
+ widget_block_component_description_4: Display a class tree with a search field for %{acronym}
+ can_also_view: You can also view a
+ detailed_demonstration: detailed demonstration
+ ncbo_widget_wiki: NCBO Widget Wiki
+ file: file.
+ no_class_concept_found: No class/concept found
+ instances_search_placeholder: Search an Instance in %{acronym}
+ properties_search_placeholder: Search a property in %{acronym}
+ schemes_search_placeholder: Search a scheme in %{acronym}
+ collections_search_placeholder: Search a collection in %{acronym}
+
+ metadata:
+ fair_score_title: FAIR score
+ total_score: "Total score : %{score} ( %{normalized_score}%)"
+ metrics: Metrics
+ metrics_link_title: Information and evolution diagrams about metrics and other measurements of the ontology.
+ see_all_metrics: See all the metrics of %{acronym}
+ show_modal_title_1: All the metrics of %{acronym}
+ not_calculated_metrics: We have not yet calculated metrics for %{acronym}
+ show_modal_title_2: "Evolution of the number of %{metric} in %{acronym} per submissions."
+ submissions: Submissions
+ submissions_link_title: Set of all the files that have been submitted to %{site}. Each previous metadata record is accessible but only the content of the latest parsed file is accessible via %{site} services
+ relations_network: Ontology relations network
+ general_information: General information
+ initial_created_on: Initial created on
+ additional_information: For additional information, contact
+ categories_and_subjects: Categories and subjects
+ keywords_and_classes: Keywords and classes
+ languages: Languages
+ pull_location: Pull location
+ export_metadata: Export all metadata
+ abstract: Abstract
+ description: Description
+
+ htaccess_modal_title: "Rewrite rules for %{acronym} ontology"
+ instructions_servers: Instructions for %{server} servers
+ htaccess_redirection_description: "We offer a seamless solution to make your ontology URIs resolvable and content negotiable by allowing URL redirection for your ontology URIs to our Agroportal URIs. To facilitate this process, we've provided you with a set of .htaccess rewrite rules. By following the simple instructions below, you'll be able to implement these rules swiftly and efficiently, ensuring smooth redirection"
+
+ redirection_note: |
+ This redirection works only for uri with the form of: url/path/resource_id
+ This will not work for uris in the form of: url/path/to/something#resource_id OR url/path/to/something:resource_id
+ htaccess_redirection:
+ instruction_1: "Access .htaccess File:"
+ instruction_1_content: "Locate the .htaccess file in the root directory of your website, if it doesn't exist create one. This file controls how your web server behaves and is often used for URL rewriting and redirection."
+ instruction_2: "Copy and Paste Redirect Rules in the .htaccess file:"
+ instruction_2_content: "Copy the rewrite rules provided in the black rectangle. Open the .htaccess file and paste the copied redirect rules into the file"
+ instruction_3: "Enable rewrite module (Linux):"
+ instruction_3_content: "you'll need to ensure that the Apache module called 'rewrite' is enabled by running the command `sudo a2enmod rewrite`"
+
+ nginx_redirection:
+ instruction_1: "Access Nginx configuration file:"
+ instruction_1_content: "The location of this file can vary depending on your system, but common locations include /etc/nginx/nginx.conf, /etc/nginx/sites-available/default or /usr/local/etc/nginx/nginx.conf."
+ instruction_2: "Locate the server block or location block where you want to enable URL rewriting:"
+ instruction_2_content: "This is typically within the server { ... } block."
+ instruction_3: "Copy and Paste Redirect Rules :"
+ instruction_3_content: "Copy the rewrite rules provided in the black rectangle. Inside the appropriate block, add the copied rules to enable URL rewriting"
+ instruction_4: "Test the configuration for syntax errors:"
+ instruction_4_content: "Run the following command to test the redirection configuration `sudo nginx -t`"
+ instruction_5: "Reload Nginx to apply the changes:"
+ instruction_5_content: "Restart the nginx server to apply the redirection using this command `sudo systemctl reload nginx`"
+
+ components:
+ check_resolvability: checking resolvability...
+ error_block: child_data_generator block did not provide all the child arguements
+ empty_field: The fields %{properties} are empty
+ save_button: Save
+ cancel_button: Cancel
+ go_to_api: Go to API
+ file_input_message: Drop your file here or, browse files on your device.
+ all_languages: All languages
+ select_anguage: Select a language
+ back: Back
+ next: Next
+ finish: Finish
+ creative_commons_license: Creative Commons License
+ open_source_license: Open Source License
+ show_more: "+ Show more ..."
+ show_less: "- Show less ..."
+ fair_score: FAIR score
+ details_details: FAIR details ...
+ projects: projects
+ notes: notes
+ concepts: concepts
+ instances: instances
+ classes: classes
+ submitted: Submitted
+ by: by
+ creation_date: Creation date %{date}
+ view_of_the_ontology: "View of the ontology %{ontology}"
+ view: View
+ debug: Debug
+ loading: Loading
+ unwatch: UnWatch
+ watch: Watch
+ resource: "%{sub_text} this resource"
+ notified_of_all_updates: Be the first to watch this resource and be notified of all its updates
+ join_the_count: Join the %{count} users, watching this resource and be notified of all its updates
+ see_more: See more...
+ see_less: See less...
+ tree_view_empty: No result found
+ copy_original_uri: Copy original URI
+ copy_portal_uri: Copy %{portal_name} URI
+ properties:
+ id: ID
+ type: Type
+ preferred_name: Preferred name
+ definitions: Definitions
+ parent: Parent
+ no_properties_alert: "%{acronym} does not contain properties"
+ visits:
+ ontology_visits: Ontology visits
+ name: name
+ visits: visits
+ ontologies_selector:
+ clear_selection: Clear selection
+ ontologies_advanced_selection: Ontologies advanced selection
+ search_hint: Filter ontologies ...
+ show_ontology_view: Show ontology views
+ hide_retired_ontologies: Hide retired ontologies
+ tabs_title:
+ categories: Categories
+ groups: Groups
+ format: Format
+ natural_languages: Natural languages
+ formality_levels: Formality levels
+ ontology_types: Ontology types
+ select_all: Select all
+ cancel: Cancel
+ apply: Apply
+ unselect_all: Unselect all
+ tools:
+ search:
+ title: "Search content (coming)"
+ description: >
+ This tool/service enables users to search for any Resource Description Framework (RDF) element within the portal.
+ Users can search by either the unique identifier (URI) associated with the RDF element or by its label.
+ It facilitates efficient navigation and retrieval of specific RDF elements, enhancing user experience and productivity within the portal.
+ converter:
+ title: "Content converter (coming)"
+ description: >
+ The Content Converter tool/service offers the capability to convert any RDF element into various formats such as RDF/XML, Turtle, Ntriples, or JSON.
+ This functionality allows users to transform RDF data into formats suitable for different purposes or compatible with various systems and applications.
+ It promotes interoperability and flexibility in handling RDF data within the portal ecosystem.
+ url_checker:
+ title: "URI resolvability checker"
+ description: >
+ This tool/service verifies the resolvability of Uniform Resource Identifiers (URIs) and their content negotiability.
+ It checks whether a given URI is accessible and whether the content associated with it can be negotiated based on the client's preferences.
+ This functionality ensures the reliability and accessibility of linked resources within the RDF ecosystem, aiding in maintaining data integrity and facilitating seamless integration with external resources.
\ No newline at end of file
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
new file mode 100644
index 000000000..2ac75c679
--- /dev/null
+++ b/config/locales/fr.yml
@@ -0,0 +1,1506 @@
+---
+fr:
+ show_advanced_options: Afficher les options avancées
+ hide_advanced_options: Masquer les options avancées
+ no_result_was_found: Aucun résultat n'a été trouvé
+
+ activaterecord:
+ errors:
+ models:
+ license:
+ attributes:
+ encrypted_key:
+ invalid_license_key: est une clé de licence invalide.
+ no_appliance_id_for_comparison: n'a pas pu être validée. Impossible de récupérer l'ID de l'appliance virtuelle.
+ appliance_id_mismatch: ne correspond pas à l'ID de l'appliance virtuelle.
+
+
+ # Rendre le terme de ressource 'ontologie' configurable dans tout le portail, permettant de le remplacer par des termes alternatifs tels que 'semantic_resource', 'vocabulary', 'terminology', ou 'semantic_artefact'
+ resource_term:
+ ontology: ontologie
+ ontology_plural: ontologies
+ ontology_single: une ontologie
+
+ semantic_resource: ressource sémantique
+ semantic_resource_plural: ressources sémantiques
+ semantic_resource_single: une ressource sémantique
+
+ vocabulary: vocabulaire
+ vocabulary_plural: vocabulaires
+ vocabulary_single: un vocabulaire
+
+ terminology: terminologie
+ terminology_plural: terminologies
+ terminology_single: une terminologie
+
+ semantic_artefact: artefact sémantique
+ semantic_artefact_plural: artefacts sémantiques
+ semantic_artefact_single: un artefact sémantique
+
+ date:
+ formats:
+ year_month_day_concise: "%Y-%m-%d" # 2017-03-01
+ month_day_year: "%b %-d, %Y" # Mar 1, 2017
+ monthfull_day_year: "%-d %B %Y" # Mars 1, 2017
+
+ language:
+ translation_not_available: "Traduction en %{language} non disponible"
+ portal_language_help_text: Indiquez la langue dans laquelle les interfaces doivent apparaître
+ search_language_help_text: Indiquez la langue dans laquelle effectuer la recherche, en restreignant la correspondance de texte exclusivement à des termes dans cette langue
+ content_language_help_text_1: Indiquez la langue dans laquelle le contenu de cette ressource sera affiché.
+ content_language_help_text_2: Les langues disponibles sont spécifiées par l'administrateur de la ressource.
+
+ application:
+ powered_by: Propulsé par BioPortal
+ projects: Projets
+ loading: Chargement en cours...
+ errors_in_fields: Erreurs dans les champs %{errors}
+ add_comment: Ajouter un commentaire
+ add_new_comment: Ajouter un nouveau commentaire
+ reply: Répondre
+ add_proposal: Ajouter une proposition
+ add_new_proposal: Ajouter une nouvelle proposition
+ watching: Surveillance
+ beta_badge_text: Version bêta
+ beta_badge_tooltip: Cette fonctionnalité est expérimentale et peut comporter des problèmes
+ ontology_not_found: Ontologie %{acronym} non trouvée
+ concept_not_found: Concept %{concept} non trouvé
+ error_load: "Erreur : échec du chargement"
+ not_found_message: Non trouvé
+ try_again: Une erreur s'est produite, veuillez réessayer
+ provide_ontology_or_concept: Veuillez fournir un identifiant d'ontologie ou un identifiant de concept avec un identifiant d'ontologie.
+ search_for_class: Veuillez rechercher une classe à l'aide du champ Jump To ci-dessus
+ missing_roots_for_ontology: Racines manquantes pour %{acronym}
+ missing_roots: Racines manquantes
+ missing_class: Classe manquante %{root_child}
+ missing_class_ontology: Classe manquante %{acronym} / %{concept_id}
+ error_simplify_class: "Échec de la simplification de la classe : %{cls}"
+ no_cache: "Pas de cache ou cache expiré pour l'ontologie : %{id}"
+ incomplete_simple_ontology: "Ontologie simple incomplète : %{id}, %{ont}"
+ label_xl:
+ error_valid_label_xl: "Erreur : Vous devez fournir un identifiant de label_xl valide"
+
+ admin:
+ query_not_permitted: Requête non autorisée
+ update_info_successfully: Informations de mise à jour récupérées avec succès
+ error_update_info: Problème lors de la récupération des informations de mise à jour - %{message}
+ current_version: "Version actuelle : %{version}"
+ appliance_id: "ID de l'appareil : %{id}"
+ no_record_exists: Aucun enregistrement existant pour l'ontologie %{acronym}
+ cache_flush_success: Cache de l'interface utilisateur vidé avec succès
+ cache_flush_error: "Problème lors du vidage du cache de l'interface utilisateur - %{class} : %{message}"
+ no_flush_command: "Le cache de l'interface utilisateur ne répond pas à la commande 'flush_all'"
+ cache_reset_success: Connexion au cache de l'interface utilisateur réinitialisée avec succès
+ cache_reset_error: Problème lors de la réinitialisation de la connexion au cache de l'interface utilisateur - %{message}
+ no_reset_command: Le cache de l'interface utilisateur ne répond pas à la commande 'reset'
+ clear_goo_cache_success: Cache Goo vidé avec succès
+ clear_goo_cache_error: "Problème lors du vidage du cache Goo - %{class} : %{message}"
+ clear_http_cache_success: Cache HTTP vidé avec succès
+ clear_http_cache_error: "Problème lors du vidage du cache HTTP - %{class} : %{message}"
+ refresh_report_without_ontologies: Rafraîchissement du rapport des ontologies commencé avec succès
+ refresh_report_with_ontologies: "Rafraîchissement du rapport pour les ontologies : %{ontologies} commencé avec succès"
+ submission_deleted_successfully: Soumission %{id} pour l'ontologie %{ont} supprimée avec succès
+ submission_not_found: Soumission %{id} pour l'ontologie %{ont} non trouvée dans le système
+ ontology_not_found: Ontologie %{ont} non trouvée dans le système
+ problem_deleting_submission: "Problème lors de la suppression de la soumission %{id} pour l'ontologie %{ont} - %{class} : %{message}"
+ problem_refreshing_report: "Problème lors du rafraîchissement du rapport - %{class} : %{message}"
+ report_successfully_regenerated: Rapport régénéré avec succès le %{report_date_generated}
+ ontologies_report_retrieved: Rapport des Ontologies - %{ontologies} ontologies récupérées en %{time}s"
+ problem_retrieving_ontologies: Problème lors de la récupération du rapport des ontologies - %{message}
+ no_ontologies_parameter_passed: "Aucun paramètre d'ontologies passé. Syntaxe : ?ontologies=ONT1,ONT2,...,ONTN"
+ ontology_process_success: "Ontologie %{ont} %{success_keyword} avec succès,"
+ ontology_not_found_system: "Ontologie %{ont} non trouvée dans le système, "
+ ontology_process_error: "Problème %{error_keyword} l'ontologie %{ont} - %{class} : %{message},"
+ new_ontologies_created_title: "Les ontologies suivantes : %{count} ont été créées cette année"
+ turbo_confirm: "Êtes-vous sûr de vouloir %{name} ?"
+ analytics:
+ total_ontologies: Ontologies Totales
+ ontologies_count: "%{size} nouvelle ontologie cette année"
+ ontologies_with_errors: Ontologies avec erreurs
+ total_visits: Visites totales
+ active_users: Utilisateurs actifs
+ visit_users: "%{visits} utilisateurs depuis le mois dernier"
+ ontology_visits: Visites d'ontologies
+ unique_users_visits: Visites d'utilisateurs uniques
+ page_visits: Visites de page de ce mois
+ main:
+ cache_management: GESTION DU CACHE
+ clear_cache: Vider le cache de l'UI
+ reset_cache: Réinitialiser la connexion au cache de l'UI
+ clear_goo_cache: Vider le cache GOO
+ clear_http_cache: Vider le cache HTTP
+ version_management: GESTION DE VERSION
+ checking_for_updates: Vérification des mises à jour ...
+ memcache:
+ title: Statistiques Memcache
+ parse_log:
+ title: Journal d'analyse pour %{acronym}
+ log_file: "Fichier journal : %{path}"
+ index:
+ title: Administration
+ administration_console: Console d'administration
+ analytics: Analytique
+ site_administration: Administration du site
+ ontology_administration: Administration des ontologies
+ licensing: Licences
+ users: Utilisateurs
+ metadata_administration: Administration des métadonnées
+ groups: Groupes
+ categories: Catégories
+ persons_and_organizations: Personnes et Organisations
+ sparql: SPARQL
+ search: Recherche et Indexation
+ report_generated_on: "Rapport généré le :"
+ licensed_to: Licencié à
+ appliance_id: ID de l'appareil
+ valid_till: Valide jusqu'à
+ days_remaining: Jours restants
+ renew_license: Renouveler la licence
+
+ groups:
+ group_created: Groupe créé avec succès en %{time}s
+ group_error_creation: Problème lors de la création du groupe - %{message}
+ group_added_successfully: Nouveau groupe ajouté avec succès
+ group_updated_successfully: Groupe mis à jour avec succès en %{time}s
+ problem_of_updating: Problème lors de la mise à jour du groupe - %{message}
+ group_deleted_successfully: Groupe supprimé avec succès en %{time}s
+ problem_of_deleting: Problème lors de la suppression du groupe - %{message}
+ synchronization_of_groups: Synchronisation des groupes commencée avec succès
+ error_parsing: "Erreur d'analyse de la réponse JSON - %{class} : %{message}"
+ problem_synchronizing_groups: "Problème lors de la synchronisation des groupes - %{class} : %{message}"
+ edit_button: Éditer
+ delete: Supprimer
+ info_error_delete: "Impossible de supprimer ce groupe car il est encore utilisé"
+ turbo_confirm: Êtes-vous sûr ?
+ form:
+ acronym: Acronyme
+ name: Nom
+ description: Description
+ created: Créé
+ ontologies: Ontologies
+ new:
+ create_new_group: Créer un nouveau groupe
+ create_group: Créer groupe
+ index:
+ create_a_new_group: Créer un nouveau groupe
+ synchronize_groups_slices: Synchroniser les groupes avec les tranches
+ id: ID
+ count: COMPTE
+ actions: Actions
+ no_agents: Il n'y a actuellement aucun agent.
+ edit:
+ edit_group: Modifier le groupe
+ save: Sauvegarder
+ categories:
+ category_created: Catégorie créée avec succès en %{time}s
+ category_error_creation: Problème lors de la création de la catégorie - %{message}
+ category_added_successfully: Nouvelle catégorie ajoutée avec succès
+ category_updated_successfully: Catégorie mise à jour avec succès en %{time}s
+ problem_of_updating: Problème lors de la mise à jour de la catégorie - %{message}
+ category_deleted_successfully: Catégorie supprimée avec succès en %{time}s
+ problem_of_deleting: Problème lors de la suppression de la catégorie - %{message}
+ edit_button: Éditer
+ delete: Supprimer
+ info_error_delete: Impossible de supprimer cette catégorie car elle est encore utilisée
+ turbo_confirm: Êtes-vous sûr ?
+ form:
+ acronym: Acronyme
+ name: Nom
+ description: Description
+ created: Créé
+ ontologies: Ontologies
+ edit:
+ edit_category: Modifier la catégorie
+ save: Sauvegarder
+ new:
+ create_new_category: Créer une nouvelle catégorie
+ create_category: Créer catégorie
+ index:
+ create_a_new_category: Créer une nouvelle catégorie
+ id: ID
+ count: COMPTE
+ actions: Actions
+ no_categories: Il n'y a actuellement aucune catégorie.
+ licenses:
+ license_notification:
+ license_contact: >
+ Pour plus d'informations, envoyez un e-mail à support@ontoportal.org ou visitez https://ontoportal.org/licensing.
+ license_obtain: >
+ Si vous êtes le propriétaire de cette installation d'OntoPortal, vous pouvez visiter https://license.ontoportal.org pour obtenir une licence.
+ license_expired: >
+ Nous sommes désolés, mais la licence de cette installation d'OntoPortal a expiré. Si vous êtes le propriétaire de cette installation d'OntoPortal, veuillez visiter https://license.ontoportal.org pour renouveler votre licence.
+ license_trial:
+ one:
+ Cette installation de l'Appliance OntoPortal est une licence d'essai, qui expirera dans 1 jour.
+ other:
+ Cette installation de l'Appliance OntoPortal est une licence d'essai, qui expirera dans %{count} jours.
+ create:
+ success: Licence renouvelée avec succès !
+ label_close: Fermer
+ form:
+ license_from_being_saved: "a empêché cette licence d'être sauvegardée :"
+ paste_your_license: Collez votre clé de licence dans la zone de texte
+ submit: Soumettre
+ search:
+ index:
+ index_data: "DONNÉES INDEXES"
+ collections_management: "GESTION DES COLLECTIONS"
+ name: "Nom"
+ actions: "Actions"
+ select_model: "Sélectionnez un modèle à indexer"
+ ontology: "Ontologie"
+ agent: "Agent"
+ ontology_submission: "Soumission"
+ generate_schema: "Générer le schéma"
+ see_schema: "Voir le schéma"
+ see_indexed_data: "Voir les données indexées"
+ show:
+ field_name: "Nom du champ"
+ type: "Type"
+ multi_valued: "Multivalué"
+ indexed: "Indexé"
+ stored: "Stocké"
+ search:
+ search_query: "Requête de recherche"
+ page: "Page"
+ page_size: "Taille de la page"
+ found_documents: "Trouvé %{count} documents"
+ id: "ID"
+ properties: "Propriétés"
+ show_more: "+ Afficher plus ..."
+ show_less: "- Afficher moins ..."
+
+ annotator:
+ title: Annotateur
+ description: Obtenez des annotations pour le texte avec des classes d'ontologie
+ input_hint: Entrez ou collez un texte à annoter...
+ options: Options
+ whole_word_only: Mot entier seulement
+ match_longest_only: Correspondance uniquement avec le plus long
+ include_mappings: Inclure les mappings
+ exclude_numbers: Exclure les chiffres
+ exclude_synonyms: Exclure les synonymes
+ select_umls_sementic_types: Sélectionner les types sémantiques UMLS
+ select_umls_sementic_groups: Sélectionner les groupes sémantiques UMLS
+ include_ancestors: Inclure les ancêtres jusqu'au niveau
+ include_score: Inclure le score
+ score_threshold: Filtrer par seuil de score
+ confidence_threshold: Filtrer par seuil de confiance
+ fastcontext: FastContext
+ lemmatize: Lématiser
+ context: Contexte
+ certainty: Certitude
+ class: Classe
+ ontology: Ontologie
+ negation: "Négation"
+ temporality: "Temporalité"
+ experiencer: Experiencer
+ score: Score
+ api_documentation: "Documentation de l'API de l'annotateur"
+ get_annotation: Obtenir des annotations
+ total_results: Résultats totaux
+ insert_sample_text: Insérer un texte d'exemple
+ sample_text: Il y a eu de nombreuses études récentes sur l'utilisation d'antagonistes microbiens pour contrôler les maladies causées par des bactéries phytopathogènes telluriques
+ et aériennes, dans le but de remplacer les méthodes actuelles de contrôle chimique et d'éviter l'utilisation extensive de fongicides, qui conduisent souvent à une résistance chez les pathogènes des plantes.
+ En agriculture, les microorganismes promoteurs de croissance des plantes et de biocontrôle ont émergé comme des alternatives sûres aux pesticides chimiques. Les espèces de Streptomyces et leurs
+ métabolites peuvent avoir un grand potentiel en tant qu'agents excellents pour contrôler divers phytopathogènes fongiques et bactériens.
+
+ concepts:
+ error_valid_concept: "Erreur : Vous devez fournir un identifiant de concept valide"
+ missing_roots: Racines manquantes
+ date_sorted_list_error: Les Classes/Concepts n'ont pas défini de dates de création ou de modifications avec dcterms
+ list_error: La Collection n'a défini aucun membre
+ close: Fermer
+ request_terms_instructions: |
+ Le texte ci-dessous est affiché à l'utilisateur comme les instructions sur la manière de demander de nouveaux termes pour votre ontologie.
+ Vous pouvez changer ce texte pour l'ontologie %{acronym} en cliquant n'importe où sur le texte existant pour
+ ouvrir la boîte de dialogue d'édition.
+ Cliquez sur 'Soumettre les changements' pour sauvegarder ou sur 'Annuler' pour abandonner vos changements.
+ submit_changes: Soumettre les changements
+ cancel: Annuler
+ request_new_term: Demander un nouveau terme
+ use_jump_to: Utilisez le "Jump To" pour trouver une classe et afficher les détails, la visualisation, les notes et les mappages
+ instances: Instances
+ notes: Notes
+ details: Détails
+ visualization: Visualisation
+ mappings: Alignements
+ new_term_requests: Nouvelles demandes de termes
+ permanent_link_class: Obtenir un lien permanent vers cette classe
+ request_term:
+ new_term_instructions: |
+
Cette ontologie s'intègre avec OntoloBridge, permettant aux utilisateurs de la communauté de suggérer des ajouts à l'ontologie publique. Complétez le modèle ci-dessous pour soumettre directement une demande de terme au Gestionnaire de l'Ontologie.
+
+
Libellé du terme (obligatoire) Nom suggéré pour le terme. Si un terme peut être décrit avec plus d'un synonyme, entrez uniquement le nom préféré ici.
+
+
+
Description du terme (obligatoire) Une brève définition, description ou utilisation du terme suggéré. Les synonymes d'autres termes peuvent être listés dans cette section.
+
+
+
Superclasse (obligatoire) Le terme parent du terme suggéré. Le terme parent doit être une entrée existante dans l'ontologie actuelle. La superclasse peut être sélectionnée directement à partir de l'arbre des classes.
+
+
+
Références (optionnel) Fournissez des preuves que le terme demandé existe, telles que des IDs d'articles ou des liens vers d'autres ressources décrivant le terme.
+
+
+
Justification (optionnel) Fournissez ici toute information supplémentaire concernant le terme demandé.
+
+
+ home:
+ ontoportal_instances: "Autres installations d’OntoPortal"
+ bug: Bug
+ proposition: Proposition
+ question: Question
+ ontology_submissions_request: Demande de soumissions d'ontologie
+ include_name: Veuillez inclure votre nom
+ include_email: Veuillez inclure votre email
+ include_comment: Veuillez inclure votre commentaire
+ fill_text: Veuillez remplir le texte approprié à partir de l'image fournie
+ notice_feedback: Le retour a été envoyé
+ account_title: Informations sur le compte
+ agroportal_figures: "%{site} en chiffres"
+ benefit1: Découvrir de nouvelles perspectives et connaissances en explorant d'autres ontologies ou ressources sémantiques dans le répertoire.
+ benefit2: Contribuez au partage de connaissances et à l'interopérabilité sémantique dans votre domaine.
+ benefit3: Cartographiez votre ontologie avec d'autres ontologies pertinentes dans le domaine et collaborez avec d'autres utilisateurs.
+ benefit4: Obtenir des retours et des suggestions d'autres utilisateurs qui peuvent utiliser et commenter votre ontologie.
+ benefit5: Décrire précisément votre ontologie avec des métadonnées pertinentes et obtenir votre score FAIR.
+ fair_details: Voir les détails
+ fairness: Score FAIR
+ get_annotations: Obtenir des annotations
+ get_recommendations: Obtenir des recommandations
+ index:
+ tagline: Le foyer des ontologies et des artefacts sémantiques dans l'agroalimentaire et les domaines connexes.
+ title: Bienvenue sur %{site}
+ welcome: Bienvenue sur %{site},
+ ontology_upload: Vous souhaitez partager une ontologie ?
+ ontology_upload_benefits: 'En téléchargeant et partageant votre ontologie sur %{site}, vous pourrez:'
+ ontology_upload_button: Soumettre une ontologie
+ discover_ontologies_button: Découvrir des ontologies
+ ontology_upload_desc: Télécharger une ontologie ou un autre type d'artefact sémantique (vocabulaire, terminologie, thésaurus, ...) est un moyen de partager vos connaissances avec les autres.
+ paste_text_prompt: Entrez un paragraphe de texte ou quelques mots-clés...
+ recommender_annotator: Recommandeur et Annotateur
+ support_and_collaborations: Support & Collaborations
+ see_details: Voir les détails
+ info_tooltip_text: "Vous voyez les scores moyens pour toutes les ontologies publiques dans AgroPortal. Les scores FAIR sont calculés avec la méthodologie O'FAIRe. Plus de détails ici : https://github.com/agroportal/fairness"
+ average: Moyenne
+ min: Min
+ max: Max
+ ontologies: Ontologies
+ classes: Classes
+ individuals: Individus
+ properties: Propriétés
+ projects: Projets
+ mappings: Alignements
+ users: Utilisateurs
+ twitter_news: Nouvelles
+ feedback:
+ error_on_form: Erreurs sur le formulaire
+ leave_your_feedback: Laissez votre retour
+ feedback_hi_text: Salut
+ feedback_info_text: vous pouvez utiliser le formulaire ci-dessous ou nous envoyer un email directement à
+ email: Email
+ name: Nom
+ proposition_url_page: URL de la page Erreur/Proposition
+ feedback: Retour
+ tags: Tags
+ bug: Bug
+ proposition: Proposition
+ question: Question
+ ontology_submissions_request: Demande de soumissions d'ontologie
+ optional: (optionnel)
+ send: Envoyer
+ feedback_complete:
+ title: Retour envoyé avec succès
+ message: Merci d'avoir pris le temps de partager votre retour avec nous. Notre équipe de support examinera votre message et vous répondra dès que possible. Nous apprécions votre opinion et sommes reconnaissants de votre aide pour améliorer nos services. Merci de votre soutien !
+
+ landscape:
+ #select_ontologies: Commencez à taper pour sélectionner des ontologies ou laissez vide pour les utiliser toutes
+ classes: Nombre de classes
+ individuals: Nombre d'individus
+ properties: Nombre de propriétés
+ max_depth: Profondeur maximale
+ max_child_count: Nombre maximal d'enfants
+ average_child_count: Nombre moyen d'enfants
+ classes_with_one_child: Classes avec un enfant
+ classes_with_more_than_25_children: Classes avec plus de 25 enfants
+ classes_with_no_definition: Classes sans définition
+ number_of_xioms_triples: Nombre d'axiomes (triplets)
+ projects_count: "%{count} projets"
+ notes_count: "%{count} notes"
+ reviews_count: "%{count} critiques"
+ as_contact_count: "%{count} comme contact"
+ as_contributor_count: "%{count} comme contributeur"
+ as_creator_count: "%{count} comme créateur"
+ as_curator_count: "%{count} comme conservateur"
+ contributions: "Contributions : %{title}"
+ published_ontologies: publié %{count} ontologies
+ funded_ontologies: financé %{count} ontologies
+ endorsed_ontologies: approuvé %{count} ontologies
+ number_of_ontologies_using_format: Nombre d'ontologies utilisant ce format
+ number_of_ontologies_of_type: Nombre d'ontologies de ce type d'ontologie
+ number_of_ontologies_of_formality_level: Nombre d'ontologies de ce niveau de formalité
+ number_of_ontologies_in_catalog: Nombre d'ontologies dans ce catalogue
+ number_of_ontologies: Nombre d'ontologies
+ number_of_ontologies_with_class_count_in_range: Nombre d'ontologies avec un nombre de classes dans cette plage
+ average: Moyenne
+ fairness_interface_introduction: Cette interface montre comment une ontologie ou un groupe a répondu avec succès aux questions d'évaluation de l'équité FAIR d'O’FAIRe
+ fairness_interface_details: Voir les détails pour chaque ontologie sur les pages de résumé de l'ontologie spécifique
+ fairness_interface_hover_instruction: survolez un principe pour voir les détails
+ average_metrics: Métriques moyennes
+ category: catégorie
+ filter_network: Filtrer le réseau
+ funding_endorsing_organizations: Organisations finançant et approuvant le plus d'ontologies
+ group: groupe
+ groups_and_categories: Groupes et Catégories
+ intro: Visualiser le panorama de toutes les ontologies sur %{site} via l'agrégation des métadonnées.
+ more_properties_charts: Plus de graphiques de propriétés
+ most_active_ontologies: Ontologies les plus actives
+ most_active_organizations: Organisations les plus actives
+ most_active_people: Personnes les plus actives
+ most_active_people_as_reviewer: Compte utilisateur le plus actif
+ most_mentioned_people: Personnes les plus mentionnées comme contact, créateur, contributeur ou conservateur
+ most_mentioned_people_as_reviewer: Compte utilisateur ayant publié des notes, critiques et projets
+ ontologies_activity_on: Activité des ontologies
+ ontologies_by: Ontologies par %{type}
+ ontologies_contributors: Contributeurs au développement des ontologies
+ ontologies_count_by_catalog: Nombre d'ontologies dans chaque catalogue d'artefacts sémantiques
+ ontologies_formats: Langage de représentation
+ ontologies_languages: Langues naturelles
+ ontologies_licenses: Licences
+ ontologies_with_notes_reviews_projects: Ontologies avec notes, critiques et projets
+ ontology_fairness_evaluator: Évaluateur de l'équité FAIR des ontologies (O’FAIRe)
+ ontology_formality_levels: Niveaux de formalité
+ ontology_properties_pie_charts: Graphiques à secteurs relatifs aux propriétés de description des objets (c.-à-d., les propriétés de métadonnées utilisées pour décrire les objets d'ontologie).
+ ontology_relations_network: Réseau de relations d'ontologie
+ ontology_tools: Outils les plus utilisés pour construire des ontologies
+ owl_ontology_author_uris: Propriétés utilisées pour spécifier l'auteur d'un objet
+ owl_ontology_definition_uris: Propriétés utilisées pour spécifier la définition d'objets
+ owl_ontology_preflabel_uris: Propriétés utilisées pour spécifier le libellé préféré d'objets
+ owl_ontology_synonym_uris: Propriétés utilisées pour spécifier les synonymes d'objet
+ properties_usage_proportion: Graphiques à secteurs liés aux valeurs les plus fréquentes pour certaines propriétés de métadonnées
+ properties_use: Utilisation de la propriété
+ relations_between_stored_ontologies: Ensemble de relations entre les ontologies de %{site} telles que capturées par les métadonnées. Les ontologies en vert sont stockées dans le répertoire tandis que celles en bleu sont des ressources externes.
+ size: taille
+ title: "Paysage"
+ ontologies_properties: Propriétés des ontologies
+
+ layout:
+ header:
+ account_setting: Paramètres du compte
+ annotator: Annotateur
+ browse: Parcourir
+ documentation: Documentation
+ help: Aide
+ landscape: Paysage
+ login: Connexion
+ logout: Déconnexion
+ mappings: Alignements
+ recommender: Recommandeur
+ publications: Publications
+ release_notes: Notes de version
+ search_prompt: Rechercher dans %{portal_name} ...
+ submit_feedback: Envoyer un retour
+ support: Aides
+ cite_us: Citez-nous
+ footer:
+ products: Produits
+ ontoportal: OntoPortal
+ release_notes: Notes de version
+ api: API
+ tools: Outils
+ sparql: SPARQL
+ support: Aides
+ contact_us: Contactez-nous
+ wiki: Wiki
+ documentation: Documentation
+ agro_documentation: Documentation d'AgroPortal
+ agreements: Légal
+ terms: Termes et conditions
+ privacy_policy: Politique de confidentialité
+ legal_notices: Mentions légales
+ cite_us: Citez-nous
+ acknowledgments: Remerciements
+ about: À propos
+ about_us: À propos de nous
+ projects: D2KAB
+ team: Équipe
+ notices:
+ slice: Tranche
+ at: à
+ visit_the_site: visitez le site complet
+
+ login:
+ invalid_account_combination: "Combinaison nom de compte/mot de passe invalide"
+ authentication_failed: "L'authentification %{provider} a échoué"
+ admin_logged_out: Déconnecté %{old_user}, retourné à %{user}
+ user_logged_out: Vous vous êtes déconnecté avec succès
+ try_again_notice: ". Veuillez réessayer."
+ reset_password_again: ". Veuillez réinitialiser votre mot de passe à nouveau."
+ custom_ontology_set: "L'affichage est maintenant basé sur votre Ensemble d'Ontologies Personnalisé."
+ welcome: "Bienvenue "
+ error_account_name: Veuillez entrer un nom de compte
+ error_password: Veuillez entrer un mot de passe
+ enter_email: Entrez votre nom d'utilisateur
+ enter_password: Entrez votre mot de passe
+ forgot_password: Mot de passe oublié ?
+ invalid_login: Erreurs sur le formulaire
+ no_account: Vous n'avez pas de compte ?
+ password: Mot de passe
+ register: S'inscrire
+ title: Connexion
+ username_or_email: Nom d'utilisateur
+ login_with_provider: Se connecter avec %{provider}
+ reset_password_message: Un email de réinitialisation de mot de passe a été envoyé à votre adresse email, veuillez suivre les instructions pour réinitialiser votre mot de passe.
+ back_home_button: Retour à l'accueil
+ recover_password: Récupérer le mot de passe
+ email: Email
+ user: utilisateur
+ email_address_associated: Entrez l'adresse email associée à votre compte et nous vous enverrons un email avec les instructions pour réinitialiser votre mot de passe.
+ email_placeholder: Entrez l'email
+ send_instructions: Envoyer les instructions
+
+ statistics:
+ title: "Statistiques de %{portal}"
+ lead: (dernières %{last_years} années)
+ ontologies: Ontologies
+ users: Utilisateurs
+ projects: Projets
+ date: Date
+ ontology_visits: Visites d'ontologies
+
+ mappings:
+ all: Tous
+ description: Plongez dans une vue d'ensemble des mappings dans la vue en bulles, localisez efficacement une ontologie spécifique dans la vue en tableau ou téléchargez vos propres mappings.
+ tabs:
+ bubble_view: Vue en bulles
+ table_view: Vue en tableau
+ upload_mappings: Télécharger des mappings
+ filter_ontologies: Filtrer les ontologies dans la vue en bulles
+ filter_bubbles: Filtrer les bulles
+ external_mappings: "Mappings externes (%{number_with_delimiter})"
+ interportal_mappings: "Mappings interportails - %{acronym} (%{number_with_delimiter})"
+ test_bulk_load: Ceci sont les mappings créés pour tester le chargement en masse
+ mapping_created: Mapping créé
+ mapping_updated: Mapping mis à jour
+ mapping_deleted: "%{map_id} supprimé avec succès"
+ mapping_not_found: "Mapping %{id} non trouvé"
+ error_of_source_and_target: Les concepts source et cible doivent être spécifiés
+ mapping_issue: "Problème de mapping avec '%{mapping}' : %{message}"
+ find_mappings: Trouver tous les mappings d'une classe/concept
+ intro: Trouver tous les mappings d'une ontologie
+ loading_mappings: Chargement des mappings...
+ no_mappings_available: Aucun mapping disponible
+ title: Mappings
+ upload_mappings: Télécharger des mappings
+ select_ontologies_list: Sélectionner les ontologies
+ bubble_view_legend:
+ bubble_size: "Taille de la bulle :"
+ bubble_size_desc: "Le nombre total de correspondances avec toutes les autres ontologies."
+ color_degree: "Degré de couleur :"
+ color_degree_desc: "Le nombre de correspondances avec l'ontologie sélectionnée."
+ yellow_bubble: "Bulle jaune : "
+ selected_bubble: "La bulle sélectionnée."
+ less_mappings: "Moins de correspondances"
+ more_mappings: "Plus de correspondances"
+ count:
+ ontology: Ontologie
+ mappings: Mappings
+ no_mappings: Il n'y a aucun mapping vers ou depuis cette ontologie
+ form:
+ source_class: Classe source
+ mapping_name: Description du mapping (nom)
+ contact_info: Informations de contact
+ mapping_source_name: Nom source (ID de l'ensemble de mappings)
+ mapping_comment: Commentaire
+ mapping_relation: Type de relation de mapping
+ save: Enregistrer
+ mapping_table:
+ mapping_to: Mapping vers
+ relations: Relations
+ source: Source
+ type: Type
+ actions: Actions
+ no_mappings: Il n'y a actuellement aucun mapping pour cette classe.
+ mapping_type_selector:
+ mapping_type: Type de mapping
+ internal: Interne
+ interportal: Interportail
+ external: Externe
+ target_class: Classe cible
+ details: Détails
+ ontology_acronym: Ontologie (acronyme)
+ class: Classe
+ ontology_acronym_placeholder: Entrez l'ACRONYM de l'ontologie
+ class_uri_placeholder: Entrez l'URI de la classe
+ ontology_uri_placeholder: Entrez l'URI de l'ontologie
+ show_line:
+ edit_modal: Modifier
+ delete_button: Supprimer
+ turbo_confirm: Êtes-vous sûr(e) ?
+ edit_mapping: Modifier le mapping pour %{preflabel}
+ show:
+ no_mappings_found: Aucun mapping trouvé
+ bulk_loader:
+ loader:
+ example_of_valid_file: Voir un exemple de fichier valide
+ save: Enregistrer
+ loaded_mappings:
+ mappings_created: "%{size} mappings créés avec succès"
+ id: ID
+ source: Source
+ target: Cible
+ relation: Relation
+ properties: Propriétés
+ actions: Actions
+ see_other_properties: Voir d'autres propriétés
+
+
+ agents:
+ not_found_agent: Agent avec id %{id}
+ add_agent: Nouvel agent ajouté avec succès
+ update_agent: Agent mis à jour avec succès
+ agent_usages_updated: Utilisations de l'agent mises à jour avec succès
+ agent_already_deleted: Agent %{id} déjà supprimé
+ agent_deleted_successfully: Agent %{id} supprimé avec succès
+ ontology_not_valid: "l'ontologie n'est pas valide, voici les erreurs : "
+ save: Sauvegarder
+ not_used: Non utilisé
+ see_usages_count: Voir les utilisations (%{count})
+ delete: Supprimer
+ delete_error: "Impossible de supprimer cet %{agent} car encore utilisé"
+ turbo_confirm: Êtes-vous sûr ?
+ modal_title: "Utilisations de l'agent \"%{name}\""
+ form:
+ type: Type
+ person: Personne
+ organization: Organisation
+ name: Nom
+ email: Email
+ acronym: Acronyme
+ homepage: Page d'accueil
+ creator: Créateur
+ identifiers: Identifiants
+ affiliations: Affiliations
+ index:
+ create_new_agent: Créer un nouvel agent
+ first_name: Prénom
+ usages: Utilisations
+ actions: Actions
+ no_agents: Il n'y a actuellement aucun agent.
+
+ ontology_details:
+ sections:
+ classes: Classes
+ summary: Résumé
+ properties: Propriétés
+ instances: Instances
+ notes: Notes
+ mappings: Alignements
+ widgets: Widgets
+ sparql: SPARQL
+ concepts: Concepts
+ schemes: Schémas
+ collections: Collections
+ concept:
+ definitions: Définitions
+ id: ID
+ in_schemes: Dans les schémas
+ member_of: Membre de
+ no_preferred_name_for_selected_language: Pas de nom préféré pour la langue sélectionnée.
+ obsolete: Obsolète
+ preferred_name: Nom préféré
+ synonyms: Synonymes
+ type: Type
+ metadata:
+ additional_metadata: Métadonnées supplémentaires
+ header:
+ last_submission_date: Date de la dernière soumission le
+
+ projects:
+ project_not_found: "Projet non trouvé : %{id}"
+ project_successfully_created: Projet créé avec succès
+ error_unique_acronym: Le projet avec l'acronyme %{acronym} existe déjà. Veuillez entrer un acronyme unique.
+ project_successfully_updated: Projet mis à jour avec succès
+ error_delete_project: "Échec de la suppression du projet : %{errors}"
+ project_successfully_deleted: Projet supprimé avec succès
+ contacts: Contacts
+ create_new_project: Créer un nouveau projet
+ created: Créé
+ creator: Utilisateur
+ delete_admin_only: Supprimer (admin seulement)
+ delete_confirm: Êtes-vous sûr ?
+ description: Description
+ description_text: Texte de la description
+ edit_text: Éditer
+ home_page: Page d'accueil
+ index:
+ intro: Parcourez une sélection de projets utilisant les ontologies de %{site}
+ institutions: Institutions
+ ontologies: Ontologies
+ project_description: Description du Projet
+ self: Projets
+ title: Liste des Projets
+ view_projects_help: Voir l'aide des projets
+
+ show:
+ title: Projet %{name}
+ edit_project: Éditer le Projet
+ description: "Description :"
+ institution: "Institution :"
+ contacts: "Contacts :"
+ home_page: "Page d'accueil :"
+ ontologies_used: Ontologies utilisées
+ no_ontologies_associated: Aucune ontologie n'est actuellement associée à ce projet
+
+ form:
+ errors_on_form: Erreurs sur le formulaire
+ name: "Nom : *"
+ acronym: "Acronyme : *"
+ administrators: "Administrateurs : *"
+ home_page: "Page d'accueil : *"
+ example: "Exemple :"
+ description: "Description :*"
+ select_ontologies: Sélectionner les ontologies utilisées
+ select_administrators: Sélectionner les administrateurs
+
+ edit:
+ title: Édition du Projet %{name}
+ editing_project: Édition du projet
+ cancel: Annuler
+ update_project: Mettre à jour le Projet
+
+ new:
+ title: Ajoutez votre projet
+ new_project: Nouveau projet
+ create_project: Créer le Projet
+
+ recommender:
+ title: Recommandeur
+ intro: Obtenez des recommandations pour les ontologies les plus pertinentes à partir d'un extrait de texte ou d'une liste de mots-clés
+ options: Options
+ input: Entrée
+ text: Texte
+ keywords: Mots-clés
+ output: Sortie
+ ontologies: Ontologies
+ ontology_sets: Ensembles d'ontologies
+ hint: Collez un paragraphe de texte ou quelques mots-clés ...
+ weights_configuration: Configuration des poids
+ coverage: Couverture
+ acceptance: Acceptation
+ knowledge_detail: Détail des connaissances
+ specialization: Spécialisation
+ ontologies_configuration: Configuration des ontologies
+ max_ont_set: Nombre maximum d'ontologies par ensemble
+ select_ontologies: Sélectionner des ontologies
+ get_recommendations: Obtenir des recommandations
+ edit: Éditer
+ results_title: Ontologies recommandées
+ call_annotator: Appeler l'annotateur avec la même entrée
+ cite: Citer
+ results_table:
+ ontology: Ontologie
+ final_score: Score final
+ coverage_score: Score de couverture
+ acceptance_score: Score d'acceptation
+ detail_score: Score de détail
+ specialization_score: Score de spécialisation
+ annotations: Annotations
+
+ register:
+ account_errors: 'Erreurs lors de la création de votre compte :'
+ confirm_password: Confirmez le mot de passe
+ create_account: Créer un nouveau compte
+ email: Email
+ first_name: Prénom
+ last_name: Nom
+ mailing_list: S'inscrire à la liste de diffusion de %{site}
+ accept_terms_and_conditions: Je reconnais et j'accepte
+ terms_and_conditions: les termes et conditions de %{site}.
+ optional: "(Optionnel)"
+ password: Mot de passe
+ title: S'inscrire
+ username: Nom d'utilisateur
+
+ users:
+ account_successfully_created: Compte créé avec succès
+ account_successfully_updated: Compte mis à jour avec succès
+ user_deleted_successfully: Utilisateur supprimé avec succès
+ not_permitted: Non autorisé
+ error_saving_custom_ontologies: Erreur lors de l'enregistrement des Ontologies Personnalisées, veuillez réessayer
+ custom_ontologies_cleared: Ontologies Personnalisées effacées
+ custom_ontologies_saved: Ontologies Personnalisées enregistrées
+ subscribe_flash_message: "Vous vous êtes %{action} %{to_or_from} notre liste de diffusion : %{list}"
+ error_subscribe: Quelque chose s'est mal passé ...
+ validate_email_address: Veuillez entrer une adresse email
+ validate_password: Veuillez entrer un mot de passe
+ validate_password_confirmation: Votre mot de passe et la confirmation du mot de passe ne correspondent pas
+ recaptcha_validation: Veuillez remplir le texte approprié à partir de l'image fournie
+ validate_orcid: Veuillez entrer un ORCID valide.
+ validate_username: veuillez entrer un nom d'utilisateur valide
+ valid_email_adresse: Veuillez entrer une adresse email valide
+ validate_terms_and_conditions: L'acceptation des termes et conditions est requise, veuillez cocher la case pour continuer.
+ first_name_required: Le champ du prénom est requis
+ last_name_required: Le champ du nom est requis
+ index:
+ first_name: Prénom
+ last_name: Nom
+ username: Nom d'utilisateur
+ email: Email
+ roles: Rôles
+ ontologies: Ontologies
+ project: Projet
+ created: Créé le
+ actions: Actions
+ detail: Détail
+ delete: Supprimer
+ login_as: Se connecter comme
+ error_delete_message: Impossible de supprimer cet utilisateur car encore utilisé
+ turbo_confirm: Êtes-vous sûr ?
+ edit:
+ user_to_admin: Êtes-vous sûr de vouloir rendre cet utilisateur administrateur ?
+ admin_privileges: Êtes-vous sûr de vouloir révoquer les privilèges d'administrateur de cet utilisateur ?
+ errors_creating_account: "Erreurs lors de la création de votre compte :"
+ edit_information: Modifier les informations personnelles
+ first_name: Prénom
+ last_name: Nom
+ username: Nom d'utilisateur
+ email: Email
+ orcid_id: ID ORCID
+ github_id: ID Github
+ new_password: Nouveau mot de passe
+ confirm_password: Confirmer le mot de passe
+ change_password: Changer le mot de passe
+ show:
+ my_account: Mon compte
+ first_name: "Prénom :"
+ last_name: "Nom :"
+ username: "Nom d'utilisateur :"
+ email: "Email :"
+ orcid_id: "ID ORCID :"
+ github_id: "ID GitHub :"
+ mailing_list_subscription: Inscription à la liste de diffusion
+ mailing_list_description: S'inscrire à la liste de diffusion des annonces de %{portal}.
+ api_key_description: Votre clé API peut être utilisée pour accéder aux services Web de %{portal}
+ api_documentation: Documentation de l'API
+ custom_semantic_resource: Ensemble d'ontologies personnalisées
+ please: Veuillez
+ modify_custom_semantic_resource: |
+ visiter le site principal
+ pour modifier votre Ensemble d'ontologies Personnalisées.
+ customize_portal_display: "Personnalisez votre affichage sur %{portal} : Choisissez les ontologies que vous souhaitez voir sur %{portal}, les autres ontologies seront cachées."
+ select_semantic_resources: Sélectionner des ontologies
+ no_semantic_resources: Vous n'avez encore sélectionné aucune ontologie
+ note_feature_logged_in: "Note : cette fonctionnalité ne fonctionne que lorsque vous êtes connecté."
+ save_custom_semantic_resources: Sauvegarder les ontologies personnalisées
+ not_subscribed: Non abonné à aucune ontologie
+ submitted_semantic_resources: Ressources Ontologies
+ upload_semantic_resources: Télécharger ontologies
+ projects_created: Projets Créés
+ no_project_created: Aucun projet créé
+ unsubscribe: Se désabonner
+ subscribe: S'abonner
+ subscriptions: Abonnements
+ no_uploaded_resources: Vous n'avez encore téléchargé aucune ontologie
+ notes: Notes
+
+ search:
+ no_search_class_provided: Aucune classe de recherche fournie
+ search_place_holder: Entrez un terme, par ex. hauteur de plante
+ advanced_options:
+ search_language: Langue de recherche
+ ontologies: Ontologies
+ include_in_search_title: Inclure dans la recherche
+ include_in_search_values:
+ property_values: Valeurs des propriétés
+ obolete_classses: Classes obsolètes
+ ontology_views: Vues d'ontologie
+ show_only_title: Afficher uniquement
+ show_only_values:
+ exact_matches: Correspondances exactes
+ classes_with_definitions: Classes avec définitions
+ show_advanced_options: Afficher les options
+ hide_advanced_options: Cacher les options
+ match_in: Correspondance dans
+ ontologies: ontologies
+ result_component:
+ details: Détails
+ visualize: Visualiser
+ more_from_ontology: de plus de cette ontologie
+ reuses_in: Réutiliser dans
+
+ notes:
+ no_notes: Aucune note à afficher
+ filter_hide_archived: Masquer les archivés
+ new_class_proposal: Proposition de Nouvelle Classe
+ new_relationship_proposal: Proposition de Nouvelle Relation
+ change_property_value_proposal: Proposition de Changement de Valeur de Propriété
+ new_comment_added: Nouveau commentaire ajouté avec succès
+ note_deleted_successfully: Note %{note_id} a été supprimée avec succès
+ note_not_found: Note %{note_id} n'a pas été trouvée dans le système
+ comment: Commentaire
+ new_comment:
+ subject: Sujet
+ comment: Commentaire
+ save: Sauvegarder
+ new_proposal:
+ reason_for_change: Raison du changement
+ new_target: Nouvelle cible
+ old_target: Ancienne cible
+ relationship_type: Type de relation
+ property_id: ID de la propriété
+ new_value: Nouvelle valeur
+ old_value: Ancienne valeur
+ class_id: ID de la classe
+ label: Étiquette
+ synonym: Synonyme
+ definition: Définition
+ parent: Parent
+ save: sauvegarder
+ note_line:
+ alert_text: "Êtes-vous sûr de vouloir supprimer la note ''%{subject}'' créée par %{creator}? Cette action NE PEUT PAS être annulée !!!"
+ delete: Supprimer
+ archived: archivé
+ comment: Commentaire
+ thread:
+ submitted_by: soumis par
+ reply:
+ about_note_decorator: à propos de %{note_decorator}
+ comment: Commentaire
+ save: sauvegarder
+ cancel: annuler
+
+ ontolobridge:
+ problem_of_creating_new_term: "Problème de création d'un nouveau terme %{endpoint} : %{class} - %{message}"
+ new_term_instructions_saved: Instructions de demande de nouveau terme pour %{acronym} enregistrées
+ error_saving_new_term_instructions: Impossible d'enregistrer les nouvelles instructions de terme pour %{acronym} en raison d'une erreur serveur
+
+ submissions:
+ filter:
+ all_formats: Tous les formats
+ sort_by_name: Trier par nom
+ sort_by_classes: Trier par nombre de classes
+ sort_by_instances_concepts: Trier par nombre d'instances/concepts
+ sort_by_submitted_date: Trier par date de soumission
+ sort_by_creation_date: Trier par date de création
+ sort_by_fair_score: Trier par score FAIR
+ sort_by_popularity: Trier par popularité
+ sort_by_notes: Trier par notes
+ sort_by_projects: Trier par projets
+ no_submissions_for_ontology: "Aucune soumission pour l'ontologie : %{ontology}"
+ submission_updated_successfully: Soumission mise à jour avec succès
+ save_button: Sauvegarder
+ id: ID
+ version: Version
+ actions: Actions
+ modified: Modifié
+ submitted: Soumis
+ download: Télécharger
+ toggle_dropdown: Basculer le menu déroulant
+ go_to_api: Aller à l'API
+ edit_button: Éditer
+ delete_submission_alert:
+ content_1: "Êtes-vous sûr de vouloir supprimer la soumission "
+ content_2: " pour l'ontologie "
+ content_3: " ? Cette action est IRREVERSIBLE !!!"
+
+ ontoportal_virtual_appliance:
+ problem_adding_account: "Problème lors de l'ajout du compte %{id} : le compte n'existe pas"
+ require_login: Vous devez être connecté pour accéder à cette section
+ title: Téléchargement de l'appliance virtuelle OntoPortal
+ intro_paragraph:
+ main: |
+ La distribution de l'appliance virtuelle OntoPortal contient une version pré-installée,
+ pré-configurée du logiciel open source NCBO couramment utilisé
+ sur un système d'exploitation Linux.
+ included_software: "Les logiciels suivants sont inclus dans l'image :"
+ ontologies_api: API des Ontologies (service REST)
+ annotator: Annotateur
+ recommender: Recommandeur
+ web_user_interface: Interface utilisateur web de BioPortal (incluant la visualisation d'ontologies, widgets et UI d'Annotateur)
+ see_documentation: Veuillez consulter notre
+ more_information: pour plus d'informations sur l'utilisation de l'Appliance.
+ download_button_text: Télécharger la dernière version d'OntoPortal
+ archives:
+ title: Archives
+ archival_distribution: |
+ L'appliance virtuelle OntoPortal 2.5 n'est plus proposée aux nouveaux
+ utilisateurs. Cette distribution d'archives est disponible uniquement en tant que sauvegarde pour
+ ceux qui se sont inscrits à l'Appliance avant juin 2020
+ version: version 2.5
+ admin_add_users:
+ title: "Admin : Ajouter des utilisateurs"
+ label_account_name: "Nom du compte :"
+ add_user_button: Ajouter un utilisateur
+ accounts_with_access: "Comptes avec accès"
+ export_users_link: "Exporter les utilisateurs de l'Appliance en CSV"
+ bioportal_user: ID utilisateur BioPortal
+
+ submission_inputs:
+ edit_ontology_title: Edition de l'ontologie
+ metadata_selector_label: "Filtrer les propriétés à afficher"
+ metadata_selector_placeholder: "Commencez à taper pour sélectionner les propriétés"
+ administrators: Administrateurs
+ ontology_skos_language_link: Veuillez vous référer à la documentation pour plus de détails.
+ ontology_skos_language_help: >
+ Les vocabulaires SKOS soumis à %{portal_name} doivent suivre quelques contraintes (par exemple, contenir au minimum un skos:ConceptScheme également typé comme owl:Ontology)
+ et assertion de concept principal. %{link}
+ ontology_obo_language_link: le parser OBOinOWL.
+ ontology_obo_language_help: >
+ Les ontologies OBO soumises à %{portal_name} seront analysées par l'OWL-API qui intègre %{link}
+ Les triplets RDF résultants seront ensuite chargés dans le triple-store de %{portal_name}.
+ ontology_owl_language_link: le Protégé
+ ontology_owl_language_help: >
+ Les ontologies OWL soumises à %{portal_name} seront analysées par l'OWL-API. Une manière simple de vérifier si votre ontologie sera analysée est de l'ouvrir avec
+ %{link}
+ logiciel qui utilise le même composant.
+ ontology_umls_language_link: par l'outil UMLS2RDF.
+ ontology_umls_language_help: >
+ Les ressources UMLS-RRF sont généralement produites %{link}
+ groups: Groupes
+ visibility: Visibilité
+ accounts_allowed: Ajouter ou supprimer des comptes autorisés à voir cette ontologie dans %{portal_name}.
+ ontology_view_of_another_ontology: Cette ontologie est-elle une vue d'une autre ontologie ?
+ contact: Contact
+ equivalents: Équivalents
+ validators: Validateurs
+ help_text: Texte d'aide
+ contact_name: "Nom du %{name}"
+ contact_email: "Email du %{name}"
+ edit_metadata_instruction: "Modifiez les métadonnées de votre ontologie ici. Certaines de ces valeurs sont utilisées par les fonctionnalités de %{portal_name}, notamment pour l'évaluation de la FAIRness. %{link}"
+ edit_metadata_instruction_link: "Consultez ici les lignes directrices et recommandations pour les métadonnées."
+ license_help: "%{portal_name} nécessite une URI pour la licence. Si vous ne trouvez pas votre choix ici, %{link}"
+ license_help_link: "Veuillez choisir une URI à partir d'ici."
+ deprecated_help: "Une ontologie avec le statut 'retired' doit nécessairement être également dépréciée, mais pas l'inverse."
+ known_usage_help: "Considérez également de déclarer %{metadata_knownUsage_help}"
+ known_usage_help_link: "les projets utilisant l'ontologie"
+ help_creator: "Les propriétés suivantes prennent pour valeur un 'agent' dans %{portal_name} (soit une personne, soit une organisation). Ces agents sont partagés sur toutes les ontologies et sont suggérés avec l'autocomplétion s'ils existent déjà. Modifier un agent ici le modifiera pour toutes les ontologies auxquelles cet agent est impliqué."
+ version_help: "Pour plus d'informations sur la manière d'encoder les informations de version dans une ontologie, consultez %{link}"
+ version_helper_link: "les lignes directrices et recommandations."
+ instances:
+ id: ID
+ type: Type
+ label: Label
+ collections:
+ error_valid_collection: "Erreur : Vous devez fournir un identifiant de collection valide"
+ no_collections_alert: "%{acronym} ne contient pas de collections (skos:Collection)"
+ id: ID
+ preferred_name: Nom préféré
+ members_count: Nombre de membres
+ type: Type
+
+ change_requests:
+ change_request_success_message: Votre demande de modification a été soumise avec succès ! Voir le %{url} sur GitHub.
+ label: Étiquette
+ type: Type
+ comment: Commentaire
+ close: Fermer
+ submit: Soumettre
+
+ check_resolvability:
+ check_resolvability_message_1: "L'URL est résolvable et supporte les formats suivants : %{supported_format}"
+ check_resolvability_message_2: "L'URL est résolvable mais n'est pas négociable en contenu, supporte uniquement : %{supported_format}"
+ check_resolvability_message_3: L'URL n'est pas résolvable et n'est pas négociable en contenu (retourne %{status}).
+ uri_placeholder: Tapez une URI pour tester sa résolvabilité
+ show_help: Afficher l'aide
+ format_not_specified: Format non spécifié
+ how_it_works:
+ title: Comment ça fonctionne
+ content_1: |
+ L'outil de vérification de la résolvabilité vous permet de tester si une URL donnée est résolvable. Il est basé sur la méthode HTTP HEAD.
+ Nous vérifions la résolvabilité d'une URL en envoyant une requête HEAD à l'URL et en vérifiant si le code de statut de la réponse est 200 (OK) et
+ si le type de contenu retourné est égal à l'un des %{resolvability_formats} suivants.
+ content_2: |
+ Nous avons un délai d'attente fixé à %{resolvability_timeout} secondes, donc si l'URL n'est pas résolvable dans ce délai, la vérification échouera.
+ Et un nombre maximal de redirections fixé à %{resolvability_max_redirections}, donc si l'URL n'est pas résolvable dans ce nombre de redirections, la vérification échouera.
+ resolving_uri:
+ title: Résolution d'une URI
+ content: |
+ Dans le contexte du web sémantique, la déréférenciation se réfère au processus de résolution et d'obtention des données réelles associées à un identifiant de ressource uniforme (URI). En termes plus simples, cela implique de suivre un lien représenté par une URI/IRI pour récupérer des informations ou des ressources liées à cet identifiant.
+ Dans le Web sémantique, les URI sont utilisées pour identifier de manière unique les ressources, et la déréférenciation permet aux systèmes d'accéder et de récupérer des données liées à ces ressources. Lorsqu'une URI/IRI est déréférencée, cela conduit généralement à la récupération de données RDF (Resource Description Framework) ou d'autres informations structurées qui décrivent la ressource dans un format lisible par machine. Cela permet aux systèmes de comprendre et de traiter le sens des données liées, facilitant l'échange et l'intégration d'informations sur le web.
+ content_negotiation:
+ title: Négociation de contenu
+ content: |
+ La négociation de contenu, dans le contexte du Web sémantique, fait référence au mécanisme par lequel deux parties communicantes, telles qu'un client et un serveur, s'accordent sur la représentation la plus appropriée d'une ressource pendant le processus de déréférenciation d'une URI ou IRI. Cette négociation vise à assurer une communication efficace entre différents systèmes qui peuvent préférer différents formats de données ou langues.
+ En d'autres termes, lorsqu'un client demande une ressource en déréférençant une URI, il indique ses préférences pour le format ou la langue des données de réponse à travers des en-têtes HTTP ou d'autres mécanismes de négociation. Le serveur, à son tour, examine ces préférences et sélectionne la représentation la plus appropriée de la ressource en fonction de ce qui est disponible.
+ différents formats peuvent être convenus entre un client et un serveur lors de l'accès aux données liées. Les formats courants incluent :
+
+ RDF/XML : représentation basée sur XML des données du Framework de Description de Ressource.
+ Turtle : format de sérialisation lisible par l'homme pour RDF.
+ JSON-LD : format basé sur JSON pour les données liées.
+ N-Triples et N-Quads : formats de texte pour exprimer des triplets et quads RDF.
+ HTML : langage de balisage pour les pages web, également utilisé pour intégrer des données RDF.
+ RDFa : intégration de données RDF dans HTML ou XML à l'aide d'attributs.
+ Résultats de requête SPARQL XML et JSON : formats pour représenter les résultats de requête SPARQL.
+
+ errors:
+ error_message: Nous sommes désolés mais quelque chose a mal tourné.
+ notification_error: Nous avons été informés de cette erreur.
+ go_home_button: Aller à l'accueil
+ send_feedback_button: Envoyer un retour
+ not_found_page: Page non trouvée
+
+ schemes:
+ error_valid_scheme_id: "Erreur : Vous devez fournir un identifiant de schéma valide"
+ no_main_scheme_alert: aucun schéma principal défini dans l'attribut URI
+ no_schemes_alert: "%{acronym} ne contient pas de schémas (skos:ConceptScheme)"
+ id: ID
+ preferred_name: Nom préféré
+ type: Type
+
+ fair_score:
+ fairness_unreachable_warning: Problème d'accès au service FAIRness
+ go_to_api: Aller à l'API
+ mod_link: MOD1.4
+ see_the_used_properties: voir les propriétés utilisées
+ metadata_properties: Les propriétés de métadonnées listées ci-dessous sont extraites de %{mod_link}.
+ ontology_repository: Ce dépôt d'ontologies implémente %{mod_link} mais n'encode pas nécessairement les métadonnées avec les mêmes propriétés (%{submission_link}).
+ see_possible_credits: Voir les crédits possibles
+ see_metadata_used_properties: Voir les propriétés de métadonnées utilisées
+ not_found: non trouvé
+ "null": "null"
+ view_fair_scores_definitions: "Vous voyez le score d'évaluation de l'équité FAIR pour cette ontologie dans AgroPortal. Les scores FAIR sont calculés avec la méthodologie O'FAIRe. Plus de détails ici : https://github.com/agroportal/fairness"
+
+ ontologies_metadata_curator:
+ #bulk_edit: Commencer l'édition en masse
+ #use_the_bulk_edit: Pour utiliser l'édition en masse, sélectionnez dans le tableau les soumissions (les lignes) et les propriétés de métadonnées (les colonnes) que vous souhaitez éditer
+ start_the_bulk_edit: Sélectionnez dans le tableau les soumissions (lignes) et les propriétés de métadonnées (colonnes) pour commencer l'édition en masse
+ alert_success_submissions: Les soumissions ont été mises à jour avec succès
+ ontologies: Ontologies
+ get_values: Obtenir les valeurs
+ select_ontologies_and_metadata: sélectionner les ontologies et les propriétés de métadonnées
+ include_all_submissions: Inclure toutes les soumissions
+ apply_the_change_for_all: Appliquer le changement pour tous
+ update_the_current_displayed_content: "mettra à jour le contenu actuellement affiché pour toutes les soumissions suivantes :"
+ save: Sauvegarder
+
+ ontologies:
+ showing_ontologies_size: "Affichage de %{ontologies_size} sur %{analytics_size}"
+ filters: Filtres
+ no_license: Pas de licence
+ view_license: Voir la licence
+ access_rights_information: Informations supplémentaires sur la licence et les droits d'accès
+ referred_to: Peut également être désigné comme
+ private_ontology: Ontologie Privée
+ formality_levels: Niveaux de formalité
+ categories: Catégories
+ groups: Groupes
+ ontology_types: Types d'ontologies
+ natural_languages: Langues naturelles
+ showing: Affichage
+ metadata_properties: des propriétés de métadonnées de %{acronym} sont remplies
+ home_page: Page d'accueil
+ ontology_processing_failed: "Le traitement de l'ontologie a échoué, avec les statuts actuels : %{status}"
+ ontology_parsing_succeeded: "L'analyse de l'ontologie a réussi, mais certaines étapes de traitement ont échoué, voici les statuts actuels : %{status}"
+ upload_an_ontology: Téléchargez une ontologie. Des sections comme %{ontology} seront disponibles une fois terminées.
+ new_ontology_is_processing: L'ontologie est en cours de traitement. Des sections comme %{ontology} seront disponibles une fois le traitement terminé.
+ ontology_is_processing: L'ontologie est en cours de traitement. Des sections comme %{ontology} seront mis a jours une fois le traitement terminé.
+ contact_support: Contacter le support
+ edit_natural_languages: Modifier les langues naturelles de %{acronym}
+ edit_available_languages: Cliquez ici pour modifier les langues disponibles
+ add_new_submission: Ajouter une nouvelle soumission
+ edit_metadata: Modifier les métadonnées
+ projects_using_ontology: Projets utilisant %{acronym}
+ create_new_project: Créer un nouveau projet
+ no_projects_using_ontology: Aucun projet n'utilise %{acronym}
+ outside: extérieur
+ relation_with_other_ontologies: Relation avec d'autres ontologies soit à l'intérieur soit à l'extérieur
+ ontology_search_prompt: 'Rechercher une ontologie ou un terme (par exemple, hauteur de plante)'
+ views: Vues
+ create_new_view: Créer une nouvelle vue
+ expand_all: Tout déplier
+ collapse_all: Tout replier
+ administrator: "Administrateur :"
+ create_new_view_submission: créer une nouvelle soumission de vue
+ description: "Description :"
+ definition: "Définition :"
+ created_by: "Créé par :"
+ submission: Soumission
+ release_date: Date de publication
+ upload_date: Date de téléchargement
+ downloads: Téléchargements
+ admin_links: Liens administratifs
+ edit_link: Éditer
+ no_views: Aucune vue disponible pour %{acronym}.
+ fairness_assessment_questions: Questions d'évaluation FAIR O'FAIRe
+ see_details: Voir les détails
+ collecting_data: Nous collectons encore des données pour %{acronym}
+ location: Emplacement
+ allow_users: Permettre aux utilisateurs de voir uniquement le résumé de la métadonnée de votre ontologie.
+ metadata_only: Métadonnées uniquement (Pas de fichier)
+ load_from_url: Charger depuis une URL
+ new_versions_loaded: De nouvelles versions chargées chaque nuit.
+ upload_local_file: Télécharger un fichier local
+ ontology_submitted: Ontologie soumise avec succès !
+ users_can_see: Les utilisateurs peuvent maintenant voir
+ your_ontology: votre ontologie
+ exploring_and_searching: |
+ dans notre liste d'ontologies mais ils ne peuvent pas l'explorer ou la rechercher. Pour permettre l'exploration et la recherche,
+ veuillez télécharger une version complète de votre ontologie.
+ submitting_ontology_view: Merci d'avoir soumis votre vue d'ontologie à %{site}.
+ submitting_ontology: Merci d'avoir soumis votre ontologie à %{site}.
+ processing_message: |
+ Nous allons maintenant mettre votre ontologie dans la file d'attente pour être traitée. Veuillez garder à l'esprit que cela peut prendre plusieurs
+ heures avant que les utilisateurs de %{site} puissent explorer et rechercher votre ontologie.
+ notification_message: "Lorsque votre ontologie sera prête à être consultée, vous recevrez une notification par email et elle sera disponible ici :"
+ contact_support_at: "Si vous avez des questions ou des problèmes, veuillez envoyer un email à l'équipe de support de %{site} à :"
+ collecting_data_message: Nous collectons encore des données pour %{acronym}
+ submit_new_ontology: Soumettre une nouvelle ontologie
+ go_to_api: Aller à l'API
+ details: Détails
+ general_information: Informations générales
+ dates_and_contacts: Dates et contacts
+ uri: URI
+ change_notes: Notes de changement
+ modification_date: Date de modification
+ date_of_original_creation: Date de création originale
+ concepts_browsers:
+ select_scheme: Veuillez sélectionner un schéma à afficher
+ missing_roots: Racines manquantes pour %{acronym} (skos:topConceptOf)
+ select_collection: Veuillez sélectionner une collection à afficher
+ placeholder_jump: Aller à
+ label_jump: "Aller à :"
+ filter: Filtre
+ browser:
+ admin_welcome: Bienvenue admin, cette coloration indique les fonctionnalités réservées aux administrateurs
+ show_private_ontology: Afficher uniquement les ontologies privées
+ show_ontology_views: Afficher les vues d'ontologie
+ show_retired_ontologies: Afficher les ontologies abandonner
+ search_placeholder: Commencez à taper pour filtrer les ontologies, par ex., AGROVOC...
+ sections:
+ classes: Classes
+ individuals: Individus
+ properties: Propriétés
+ maximum_depth: Profondeur maximale
+ maximum_number_of_children: Nombre maximum d'enfants
+ average_number_of_children: Nombre moyen d'enfants
+ classes_with_a_single_child: Classes avec un seul enfant
+ classes_with_more_than_25_children: Classes avec plus de 25 enfants
+ classes_with_no_definition: Classes sans définition
+ identifiers: Identifiants
+ identifiers_tooltip: Identifiants principaux de l'ontologie.
+ dates: Dates
+ person_and_organization: Personnes et organisations
+ other_links: Autres liens
+ info_tooltip_links: Propriétés de métadonnées qui mettent en évidence les liens permettant l'accès aux ensembles de données, le téléchargement de ressources sémantiques, etc.
+ projects_and_usage_information: Informations sur les projets et l'utilisation
+ info_tooltip_projects: Détails concernant l'utilisation de l'ontologie.
+ methodology_and_provenance: Méthodologie et provenance
+ community: Communauté
+ content: Contenu
+ info_tooltip_properties_dropdown: Propriétés de métadonnées englobant principalement la conception, les méthodes et les actions pour créer l'ontologie. Cela inclut des éléments tels que les outils et logiciels utilisés par le créateur de l'ontologie lors de sa configuration.
+ visits: Visites
+ views: Vues de %{acronym}
+ create_new_view: Créer une nouvelle vue
+ configuration_metadata: Métadonnées de configuration
+ info_tooltip_configuration: Regroupe toutes les propriétés de métadonnées utilisées par le portail pour configurer le comportement de la ressource
+ label_groups: Groupes
+ download_as_csv: Télécharger en CSV
+ scroll_down_to_see_more: Faites défiler vers le bas pour en voir plus
+ widgets: Les widgets ne sont disponibles que pour les ontologies stockées dans %{site}.
+ add_acronym_widgets: Ajouter des widgets web %{acronym} à votre site
+ widget_block_component_title_1: Aller à
+ widget_block_component_description_1: Tapez un nom de classe de %{acronym} et allez-y dans %{site}
+ download: Téléchargez le
+ put_on_server: et mettez-le sur votre serveur.
+ copy_and_paste: Copiez le code ci-dessous et collez-le sur votre page HTML
+ note: "Note :"
+ use_quick_jump: Si vous souhaitez utiliser Quick Jump pour plusieurs ontologies
+ enter_list_of_ontologies: Vous pouvez entrer une liste d'identifiants d'ontologie séparés par des virgules
+ set_the_variable: "Vous pouvez régler la variable sur 'all' pour rechercher dans toutes les ontologies de %{site} :"
+ include_definitions: "Pour inclure des définitions dans le menu déroulant Aller à, ajoutez la variable suivante en Javascript :"
+ info_pasted_code: Dans le code que vous venez de coller, assurez-vous de changer le chemin vers le fichier quick_jump.js pour le pointer vers l'emplacement où vous avez mis le fichier (relatif à votre fichier HTML)
+ example_to_use_code: "Par exemple, si vous mettez le fichier quick_jump.js dans le même répertoire que votre fichier HTML, voici le code que vous utiliseriez :"
+ help_visit: Pour plus d'aide, visitez
+ widget_block_component_title_2: Autocomplétion
+ widget_block_component_description_2: Remplissez vos champs de formulaire avec des classes de %{acronym}
+ example_1: Exemple 1 (commencez à taper le nom de la classe pour obtenir son URI complet)
+ example_2: Exemple 2 (obtenez l'ID d'une classe)
+ example_3: Exemple 3 (obtenez le nom préféré d'une classe)
+ include_file: Dans l'en-tête de la page où vous souhaitez le champ de formulaire, incluez le
+ use_widget: "Sur votre formulaire, pour les champs où vous souhaitez utiliser le widget de sélection de classe, spécifiez la classe du champ dans le format suivant :"
+ for_example: Par exemple,
+ use_ontology: utilisera NCI Thesaurus (l'identifiant de l'ontologie est NCIT) et mettra l'URI de la classe dans le champ après que l'utilisateur ait sélectionné la classe dans la liste déroulante.
+ use_list: "En plus des identifiants d'ontologie uniques, vous pouvez utiliser une liste :"
+ or: OU
+ use_all_to_search: "utilisez 'all' pour rechercher dans toutes les ontologies de %{site} :"
+ autocomplete_widget_accesses: Le widget d'autocomplétion accède au contenu de l'ontologie de la dernière version de l'ontologie.
+ use_following_parameters: "Vous pouvez utiliser les paramètres suivants pour sélectionner quelle valeur sera placée dans le champ de saisie visible par l'utilisateur :"
+ uri: uri
+ shortid: shortid
+ name: nom
+ class_uri_description: "Mettez l'URI complet de la classe (par exemple,"
+ class_uri_example: 'mettez l’URI complet de la classe (par exemple, %{link})'
+ class_shortid_description: mettez l'identifiant court de la classe, tel qu'utilisé dans %{site} (par exemple, "Common_Neoplasm");
+ class_name_description: mettez le nom préféré de la classe (par exemple, "Common Neoplasm");
+ hidden_elements_description: "En plus de l'élément de saisie que vous avez défini, quatre éléments de formulaire cachés sont créés puis définis lorsque l'utilisateur sélectionne une classe dans la liste. Par exemple, si vous créez un champ avec ce code :"
+ hidden_elements_example: "L'attribut 'name' est utilisé pour créer les quatre champs suivants (notez comment le 'a' de l'attribut name est ajouté à l'attribut id) :"
+ additional_parameters: Les paramètres supplémentaires sont documentés sur le
+ more_help_visit: Pour plus d'aide, visitez
+ widget_block_component_title_3: Visualisation
+ widget_block_component_description_3: Affichez une visualisation pour une classe donnée dans %{acronym}
+ widget_block_component_title_4: Widget Arbre
+ widget_block_component_description_4: Affichez un arbre de classe avec un champ de recherche pour %{acronym}
+ can_also_view: Vous pouvez également voir une
+ detailed_demonstration: démonstration détaillée
+ ncbo_widget_wiki: Wiki des Widgets NCBO
+ file: fichier.
+ no_class_concept_found: Aucune classe/concept trouvé
+ instances_search_placeholder: Rechercher une instance dans %{acronym}
+ properties_search_placeholder: Rechercher une propriété dans %{acronym}
+ schemes_search_placeholder: Rechercher un schéma dans %{acronym}
+ collections_search_placeholder: Rechercher une collection dans %{acronym}
+
+ metadata:
+ fair_score_title: Score FAIR
+ total_score: "Score total : %{score} ( %{normalized_score}%)"
+
+ metrics: Métriques
+ metrics_link_title: Informations et diagrammes d'évolution sur les métriques et autres mesures de l'ontologie.
+ see_all_metrics: Voir toutes les métriques de %{acronym}
+ show_modal_title_1: Toutes les métriques de %{acronym}
+ not_calculated_metrics: Nous n'avons pas encore calculé de métriques pour %{acronym}
+ show_modal_title_2: "Évolution du nombre de %{metric} dans %{acronym} par soumissions."
+
+ submissions: Soumissions
+ submissions_link_title: Ensemble de tous les fichiers qui ont été soumis à %{site}. Chaque enregistrement de métadonnées précédent est accessible mais seul le contenu du dernier fichier analysé est accessible via les services de %{site}
+
+ relations_network: Réseau de relations des ontologies
+
+ general_information: Informations générales
+ initial_created_on: Créé initialement le
+ additional_information: Pour des informations supplémentaires, contactez
+ categories_and_subjects: Catégories et sujets
+ keywords_and_classes: Mots-clés et classes
+ languages: Langues
+ pull_location: Emplacement de tirage
+ export_metadata: Exporter toutes les métadonnées
+ abstract: Résumé
+ description: Description
+
+ htaccess_modal_title: "Règles de redirection pour l'ontologie %{acronym}"
+ instructions_servers: Instructions pour les servers %{server}
+ htaccess_redirection_description: "Nous proposons une solution transparente pour rendre les URI de votre ontologie résolubles et le contenu négociable en autorisant la redirection d'URL de vos URI d'ontologie vers nos URI d'Agroportal. Pour faciliter ce processus, nous vous avons fourni un ensemble de règles de réécriture .htaccess. En suivant les instructions simples ci-dessous, vous serez en mesure de mettre en œuvre ces règles rapidement et efficacement, garantissant ainsi une redirection fluide"
+
+ redirection_note: >
+ Cette redirection fonctionne uniquement pour les uri sous la forme: url/path/resource_id.
+ Cela ne fonctionnera pas pour les URIS sous la forme: url/path/to/something#resource_id OR url/path/to/something:resource_id
+ htaccess_redirection:
+ instruction_1: "Accéder au fichier .htaccess:"
+ instruction_1_content: "Localisez le fichier .htaccess dans le répertoire racine de votre site Web, s'il n'existe pas, créez-en un. Ce fichier contrôle le comportement de votre serveur Web et est souvent utilisé pour la réécriture et la redirection d'URL"
+ instruction_2: "Copiez et collez les règles de redirection dans le fichier .htaccess:"
+ instruction_2_content: "Copiez les règles de redirection fournies dans le rectangle noir. Ouvrez le fichier .htaccess et collez les règles de redirection copiées dans le fichier"
+ instruction_3: "Activer le module de réécriture (Linux):"
+ instruction_3_content: "vous devrez vous assurer que le module Apache appelé 'rewrite' est activé en exécutant la commande `sudo a2enmod rewrite`"
+
+ nginx_redirection:
+ instruction_1: "Accéder au fichier de configuration Nginx:"
+ instruction_1_content: "L'emplacement de ce fichier peut varier en fonction de votre système, mais les emplacements courants incluent /etc/nginx/nginx.conf, /etc/nginx/sites-available/default ou /usr/local/etc/nginx/nginx. conf."
+ instruction_2: "Localisez le bloc de serveur ou le bloc d'emplacement dans lequel vous souhaitez activer la réécriture d'URL:"
+ instruction_2_content: "C'est généralement dans le bloc serveur { ... }."
+ instruction_3: "Copier et coller les règles de redirection:"
+ instruction_3_content: "Copiez les règles de redirection fournies dans le rectangle noir. Dans le bloc approprié, ajoutez les règles copiées pour activer la réécriture d'URL"
+ instruction_4: "Testez la configuration pour les erreurs de syntaxe:"
+ instruction_4_content: "Exécutez la commande suivante pour tester la configuration de redirection `sudo nginx -t`"
+ instruction_5: "Redémarrez Nginx pour appliquer les modifications:"
+ instruction_5_content: "Redémarrez le serveur nginx pour appliquer la redirection à l'aide de cette commande `sudo systemctl reload nginx`"
+
+
+
+
+ components:
+ check_resolvability: vérification de la résolvabilité...
+ error_block: le bloc child_data_generator n'a pas fourni tous les arguments enfants
+ empty_field: Les champs %{properties} sont vides
+ save_button: Sauvegarder
+ cancel_button: Annuler
+ go_to_api: Aller à l'API
+ file_input_message: Déposez votre fichier ici ou, parcourez les fichiers sur votre appareil.
+ all_languages: Toutes les langues
+ select_language: Sélectionnez une langue
+ back: Retour
+ next: Suivant
+ finish: Terminer
+ creative_commons_license: Licence Creative Commons
+ open_source_license: Licence Open Source
+ show_more: "+ Afficher plus ..."
+ show_less: "- Afficher moins ..."
+ fair_score: Score FAIR
+ details_details: Détails FAIR ...
+ projects: projets
+ notes: notes
+ concepts: concepts
+ instances: instances
+ classes: classes
+ submitted: Soumis
+ by: par
+ creation_date: Date de création %{date}
+ view_of_the_ontology: "Vue de l'ontologie %{ontology}"
+ view: Vue
+ debug: Débogage
+ loading: Chargement
+ unwatch: Ne plus surveiller
+ watch: Surveiller
+ resource: "%{sub_text} cette ressource"
+ notified_of_all_updates: Soyez le premier à surveiller cette ressource et soyez informé de toutes ses mises à jour
+ join_the_count: Rejoignez les %{count} utilisateurs, surveillant cette ressource et soyez informé de toutes ses mises à jour
+ see_more: Voir plus...
+ see_less: Voir moins...
+ tree_view_empty: Pas de résultat
+ copy_original_uri: Copier l'URI d'origine
+ copy_portal_uri: Copier l'URI de %{portal_name}
+
+ properties:
+ id: ID
+ type: Type
+ preferred_name: Nom préféré
+ definitions: Définitions
+ parent: Parent
+ no_properties_alert: "%{acronym} ne contient pas de propriétés"
+
+ visits:
+ ontology_visits: Visites de l'ontologie
+ name: nom
+ visits: visites
+
+ ontologies_selector:
+ clear_selection: Effacer la sélection
+ ontologies_advanced_selection: Sélection avancée des ontologies
+ search_hint: Filtrer les ontologies...
+ show_ontology_view: Afficher les vues d'ontologie
+ hide_retired_ontologies: Masquer les ontologies abandonner
+ tabs_title:
+ categories: Catégories
+ groups: Groupes
+ format: Format
+ natural_languages: Langues naturelles
+ formality_levels: Niveaux de formalité
+ ontology_types: Types d'ontologie
+ select_all: Tout sélectionner
+ cancel: Annuler
+ apply: Appliquer
+ unselect_all: Tout désélectionner
+
+ tools:
+ search:
+ title: "Rechercher du contenu (à venir)"
+ description: >
+ Cet outil/service permet aux utilisateurs de rechercher n'importe quel élément du Cadre de Description des Ressources (RDF) dans le portail.
+ Les utilisateurs peuvent rechercher soit par l'identifiant unique (URI) associé à l'élément RDF, soit par son libellé.
+ Il facilite la navigation efficace et la récupération d'éléments RDF spécifiques, améliorant ainsi l'expérience utilisateur et la productivité au sein du portail.
+
+ converter:
+ title: "Convertisseur de contenu (à venir)"
+ description: >
+ L'outil/service de conversion de contenu offre la possibilité de convertir n'importe quel élément RDF en divers formats tels que RDF/XML, Turtle, Ntriples ou JSON.
+ Cette fonctionnalité permet aux utilisateurs de transformer les données RDF en formats adaptés à différents usages ou compatibles avec divers systèmes et applications.
+ Il favorise l'interopérabilité et la flexibilité dans la manipulation des données RDF au sein de l'écosystème du portail.
+
+ url_checker:
+ title: "Vérificateur de résolvabilité d'URI"
+ description: >
+ Cet outil/service vérifie la résolvabilité des Identifiants Uniformes de Ressource (URI) et leur négociabilité de contenu.
+ Il vérifie si un URI donné est accessible et si le contenu associé peut être négocié en fonction des préférences du client.
+ Cette fonctionnalité garantit la fiabilité et l'accessibilité des ressources liées dans l'écosystème RDF, aidant ainsi à maintenir l'intégrité des données et facilitant l'intégration transparente avec des ressources externes.
+
+
diff --git a/config/locales/it.yml.sample b/config/locales/it.yml.sample
new file mode 100644
index 000000000..c2052752a
--- /dev/null
+++ b/config/locales/it.yml.sample
@@ -0,0 +1,424 @@
+---
+it:
+ activaterecord:
+ errors:
+ models:
+ license:
+ attributes:
+ encrypted_key:
+ invalid_license_key: is an invalid license key
+ no_appliance_id_for_comparison: Could not be validated. Unable to retrieve virtual appliance ID.
+ appliance_id_mismatch: is an appliance id mismatch
+
+ # Configurare il termine di risorsa 'ontology' nell'intero portale in modo che possa essere sostituito da alternative come 'semantic_resource', 'vocabulary', 'terminology', o 'semantic_artefact'
+ resource_term:
+ ontology: ontologia
+ ontology_plural: ontologie
+ ontology_single: un'ontologia
+
+ semantic_resource: risorsa semantica
+ semantic_resource_plural: risorse semantiche
+ semantic_resource_single: una risorsa semantica
+
+ vocabulary: vocabolario
+ vocabulary_plural: vocabolari
+ vocabulary_single: un vocabolario
+
+ terminology: terminologia
+ terminology_plural: terminologie
+ terminology_single: una terminologia
+
+ semantic_artefact: artefatto semantico
+ semantic_artefact_plural: artefatti semantici
+ semantic_artefact_single: un artefatto semantico
+
+ date:
+ formats:
+ year_month_day_concise: "%Y-%m-%d" # 2017-03-01
+ month_day_year: "%b %-d, %Y" # Mar 1, 2017
+ monthfull_day_year: "%B %-d, %Y" # March 1, 2017
+
+ additional_parameters: Parametri aggiuntivi spiegati in
+ admin:
+ licenses:
+ create:
+ success: Licenza rinnovata con successo!
+ all: Tutti
+ annotator:
+ annotate_text_prompt: Inserire o incollare il testo da annotare
+ annotations_result: Annotazioni
+ fast_context: Contesto veloce
+ filters:
+ confidence_threshold: Soglia di confidenza del filtro
+ confidence_threshold_help: Specificare la posizione minima nella distribuzione
+ dei punteggi (tra 1 e 100)
+ exclude_numbers: Escludere i numeri
+ exclude_synonyms: Escludere sinonimi
+ include_mappings: Includere le mappature
+ match_longest_only: Solo la partita più lunga
+ match_partial_words: Riconoscere parole parziali
+ max_hierarchy_level: Includere gli antenati fino al livello
+ score: Includere il punteggio
+ score_help: Punteggio delle annotazioni secondo la precedente misura NCBO 2009
+ (old) o Punteggio delle annotazioni secondo la misura C-Value (cvalue) o Punteggio
+ delle annotazioni secondo la misura C-Value con espansione gerarchica (cvalueh)
+ score_threshold: Filtrare per soglia di punteggio
+ score_threshold_help: Specificare il valore minimo del punteggio per le annotazioni
+ get_annotator: Ottenere le annotazioni
+ index:
+ fast_context:
+ tooltip: 'Abilita FastContext a rilevare: se un concetto è stato negato (affermato,
+ negato), chi ha sperimentato il concetto trovato (paziente, altro), quando
+ si è verificato il concetto annotato (recente, storico, ipotetico), e/o
+ se il concetto annotato è incerto (certo, incerto).'
+ intro: Ottenere annotazioni per un testo biomedico con classi ontologiche
+ lemmatize:
+ tooltip: Abilita Lemmatize per lemmatizzare il testo inviato e utilizzare
+ un dizionario lemmatizzato per le annotazioni
+ sample_text: Il melanoma è un tumore maligno dei melanociti che si trova principalmente
+ nella pelle, ma anche nell'intestino e nell'occhio.
+ lemmatize: Lemmatizzare
+ results_filtered_by: I risultati sono filtrati da
+ select: Selezionare %{name}
+ start_typing_to_select: Iniziare a digitare per selezionare %{type} o lasciare
+ in bianco per utilizzare tutti i dati
+ title: Annotatore
+ umls:
+ semantic_groups: Gruppi semantici UMLS
+ semantic_types: Tipi semantici UMLS
+ certainty: Certezza
+ class: Classe
+ clear_selection: Azzeramento della selezione
+ concepts:
+ request_term:
+ new_term_instructions: |
+
Questa ontologia si integra con OntoloBridge, permettendo agli utenti della comunità di suggerire aggiunte all'ontologia pubblica. Compilare il modello sottostante per inviare una richiesta di termine direttamente al gestore dell'ontologia.
+
+
Etichetta del termine (obbligatorio) Nome del termine suggerito. Se un termine può essere descritto con più di un sinonimo, inserire qui solo il nome preferito.
+
+
+
Descrizione del termine (obbligatorio) Breve definizione, descrizione o uso del termine suggerito. In questa sezione si possono elencare i sinonimi di altri termini.
+
+
+
Superclasse (obbligatorio) Il termine padre del termine suggerito. Il termine genitore deve essere una voce esistente nell'ontologia corrente. La superclasse può essere selezionata direttamente dall'albero delle classi del Bioportale.
+
+
+
Riferimenti (facoltativo) Fornire prove dell'esistenza del termine richiesto, come ID Pubmed di articoli o link ad altre risorse che descrivono il termine.
+
+
+
Giustificazione (opzionale) Fornisci qui qualsiasi informazione aggiuntiva sul termine richiesto.
+
+ context: Contesto
+ coverage: Copertura
+ filter: Filtro
+ format_results: Formatta i risultati come
+ get_json_version: Ottenere la versione json
+ get_recommendations: Raccomandazioni
+ help: Aiuto
+ home:
+ agroportal_figures: "%{site} in cifre:"
+ benefit1: Scoprite nuove intuizioni e connessioni esplorando le altre ontologie
+ presenti nel repository.
+ benefit2: Contribuite alla crescita e allo sviluppo del vostro dominio aggiungendo
+ nuovi concetti e categorie.
+ benefit3: Utilizzate il controllo di versione per gestire le modifiche alla vostra
+ ontologia nel tempo e collaborare con altri utenti.
+ benefit4: Ottenere feedback e suggerimenti da altri utenti che possono rivedere
+ e commentare la vostra ontologia.
+ benefit5: Ottenere il punteggio e le metriche FAIR per l'ontologia.
+ fair_details: Vedi dettagli
+ fairness: Punteggi FAIR
+ get_annotations: Ottenere le annotazioni
+ get_recommendations: Raccomandazioni
+ index:
+ tagline: La casa dei vocabolari e delle ontologie in agronomia e nei campi correlati.
+ title: Benvenuti alla %{site}
+ welcome: Benvenuti al %{site},
+ ontology_upload: Volete caricare un'ontologia?
+ ontology_upload_benefits: 'Caricando la propria ontologia su %{site}, è possibile:'
+ ontology_upload_button: Caricare l'ontologia
+ discover_ontologies_button: Scopri le ontologie
+ ontology_upload_desc: Caricare un'ontologia è un modo per condividere la propria
+ conoscenza del dominio con altri.
+ paste_text_prompt: Incollare un paragrafo di testo o alcune parole chiave ...
+ recommender_annotator: Raccomandatore e annotatore
+ support_and_collaborations: Supporto e collaborazioni
+ ontoportal_instances: Istanze di Ontoportal
+ twitter_news: Notizie
+
+ input: Ingresso
+ insert_sample_text: Inserire un testo di esempio
+ keywords: Parole chiave
+ keywords_separated_by_commas: Parole chiave separate da virgole
+ knowledge_detail: Dettaglio della conoscenza
+ landscape:
+ average_metrics: Metriche medie
+ category: Categoria
+ filter_network: Rete di filtraggio
+ funding_endorsing_organizations: Organizzazioni che finanziano e sostengono il
+ maggior numero di ontologie
+ group: Gruppo
+ groups_and_categories: Gruppi e categorie
+ intro: Visualizza il panorama di tutte le ontologie su %{site} tramite l'aggregazione dei metadati.
+ more_properties_charts: Altri grafici delle proprietà
+ most_active_ontologies: Le ontologie più attive
+ most_active_organizations: Le organizzazioni più attive
+ most_active_people: Le persone più attive
+ most_active_people_as_reviewer: Le persone più attive come recensori
+ most_mentioned_people: Le persone più citate come contatto, creatore, collaboratore
+ o curatore
+ most_mentioned_people_as_reviewer: Persone che hanno pubblicato note, recensioni
+ e progetti
+ ontologies_activity_on: Attività ontologica su %{site}
+ ontologies_by: Ontologie per %{type}
+ ontologies_contributors: Contribuenti allo sviluppo dell'ontologia
+ ontologies_count_by_catalog: Numero di ontologie in ogni catalogo di dati
+ ontologies_formats: Formato utilizzato
+ ontologies_languages: Linguaggi naturali delle ontologie
+ ontologies_licenses: Licenze utilizzate dalle ontologie
+ ontologies_with_notes_reviews_projects: Ontologie con note, recensioni e progetti
+ ontology_fairness_evaluator: Valutatore di ontologia FAIR (O'FAIRe)
+ ontology_formality_levels: Livelli di formalità delle ontologie
+ ontology_properties_pie_charts: Grafici a torta per le proprietà utilizzate nelle
+ ontologie
+ ontology_relations_network: Rete di relazioni ontologiche
+ ontology_tools: Strumenti più utilizzati per costruire ontologie
+ owl_ontology_author_uris: URI per le proprietà dell'autore utilizzate per le ontologie
+ OWL
+ owl_ontology_definition_uris: URI per le proprietà di definizione utilizzate per
+ le ontologie OWL
+ owl_ontology_preflabel_uris: URI per le proprietà prefLabel utilizzate per le
+ ontologie OWL
+ owl_ontology_synonym_uris: URI per le proprietà dei sinonimi utilizzati per le
+ ontologie OWL
+ properties_usage_proportion: La percentuale di utilizzo delle proprietà tra le
+ ontologie memorizzate
+ properties_use: Uso della proprietà
+ relations_between_stored_ontologies: Relazioni tra le ontologie memorizzate nel
+ portale
+ size: Dimensione
+ title: "%{site} Paesaggio"
+ layout:
+ header:
+ account_setting: Impostazioni dell'account
+ annotator: Annotatore
+ browse: Sfogliare
+ documentation: Documentazione
+ help: Aiuto
+ landscape: Paesaggio
+ login: Accesso
+ logout: logout
+ mappings: Mappature
+ publications: Pubblicazioni
+ release_notes: Note di rilascio
+ search_prompt: Cerca in %{portal_name} ...
+ submit_feedback: Invia un feedback
+ support: supporto
+ login:
+ enter_email: Inserisci il tuo indirizzo e-mail
+ enter_password: Inserire la password
+ forgot_password: Hai dimenticato la password?
+ invalid_login: Errori nel modulo
+ no_account: Non avete un account?
+ password: Password
+ register: Registro
+ title: Accesso
+ username_or_email: Nome utente o e-mail
+ mappings:
+ find_mappings: Trovare le mappature di una classe/concetto
+ intro: Sfogliare le mappature tra classi di diverse ontologie
+ loading_mappings: Caricamento delle mappature...
+ mappings_bulk_load: Mappatura del carico massivo
+ no_mappings_available: Nessuna mappatura disponibile
+ title: Corrispondenze
+ upload_mappings: Caricare le mappature
+ matched_class: Classe abbinata
+ matched_ontology: ontologia abbinata
+ max_ontologies_per_set: Numero massimo di ontologie per set
+ nbco_annotatosplus:
+ annotations: Annotazioni
+ enter_paste_text_to_annotate: 'Inserire o incollare il testo da annotare:'
+ exclude_numbers: Escludere i numeri
+ exclude_synonyms: Escludere sinonimi
+ fast_context:
+ help: 'Attivare FastContext per rilevare: se un concetto è stato negato (affermato,
+ negato), chi ha sperimentato il concetto trovato (paziente, altro), quando
+ si è verificato il concetto annotato (recente, storico, ipotetico), e/o se
+ il concetto annotato è incerto (certo, incerto).'
+ title: Contesto veloce
+ filters:
+ additional_parameters_explained_at: 'Ulteriori parametri sono spiegati nella
+ pagina:'
+ by:
+ certainty: Certezza
+ class: Classe
+ experiencer: Esperto
+ filter: Filtro
+ match_context: Contesto
+ match_type: Tipo
+ matched_class: Classe associata
+ matched_ontology: Ontologia associata
+ negation: Negazione
+ ontology: Ontologia
+ score: Punteggio
+ temporality: Temporalità
+ title: I risultati sono filtrati da
+ umls_sem_type: Tipo semantico UMLS
+ confidence_threshold: Soglia di fiducia del filtro
+ confidence_threshold_help: Specificare la posizione minima nella distribuzione
+ dei punteggi (tra 1 e 100)
+ format_results_as: 'Formattare i risultati come:'
+ reproduce_results_using: Riprodurre questi risultati utilizzando il metodo
+ score_threshold: Filtrare per soglia di punteggio
+ score_threshold_help: Specificare il valore minimo del punteggio per le annotazioni
+ include_ancestors_up_to_level: Includere gli antenati fino al livello
+ include_mappings: Includere le mappature
+ include_score: Includere il punteggio
+ index:
+ intro: |
+ NCBO Annotator+ è un proxy che chiama il servizio web NCBO Annotator sul BioPortale NCBO.
+
+ Tchechmedjiev, A., Abdaoui, A., Emonet, V., Melzi, S., Jonnagaddala, J., & Jonquet, C. (2018). Funzioni migliorate per l'annotazione e l'indicizzazione di testi clinici con NCBO Annotator+. Bioinformatica, 34(11), 1962-1965.
+
+ Se si utilizza l'API, fornire una chiave API NCBO BioPortal valida e accedere al servizio all'indirizzo http://services.bioportal.lirmm. en/ncbo_annotatorplus
+ Il testo inviato a NCBO Annotator+ deve essere in inglese.
+ sample_text: Il melanoma è un tumore maligno dei melanociti che si trova principalmente
+ nella pelle, ma anche nell'intestino e nell'occhio.
+ title: Annotatore NCBO +
+ insert_sample_text: Inserire un testo di esempio
+ match_longest_only: Solo la partita più lunga
+ match_partial_words: Abbinare parole parziali
+ recognizer: Riconoscimento dell'entità
+ score_help: Punteggio delle annotazioni secondo la precedente misura NCBO 2009
+ (old) o Punteggio delle annotazioni secondo la misura C-Value (cvalue) o Punteggio
+ delle annotazioni secondo la misura C-Value con espansione gerarchica (cvalueh)
+ select: Selezionare %{name}
+ select_ontologies: Iniziare a digitare per selezionare le ontologie o lasciare
+ vuoto per utilizzare tutte le ontologie
+ select_ontologies_list: Selezionare le ontologie
+ show_advanced_options: Mostra le opzioni avanzate
+ start_typing_to_select: Iniziare a digitare per selezionare %{type} o lasciare
+ vuoto per usare tutti
+ umls:
+ semantic_groups: Gruppi semantici UMLS
+ semantic_types: Tipi semantici UMLS
+ negation: negazione
+ none: nessuno
+ ontologies:
+ ontology_search_prompt: 'Ricerca di un''ontologia o di un concetto (es.: Agrovoc
+ ...)'
+ self: Ontologie
+ ontology: Ontologia
+ ontology_details:
+ concept:
+ definitions: Definizioni
+ id: ID
+ in_schemes: In Schemi
+ member_of: Membro di
+ no_preferred_name_for_selected_language: Nessun nome preferito per la lingua
+ selezionata.
+ obsolete: Obsoleto
+ preferred_name: Nome preferito
+ synonyms: Sinonimi
+ type: Tipo
+ metadata:
+ additional_metadata: Metadati aggiuntivi
+ header:
+ last_submission_date: Data dell'ultimo invio
+
+ ontology_sets: Insiemi di ontologie
+ output: Uscita
+ projects:
+ contacts: Contatti
+ create_new_project: Creare un nuovo progetto
+ created: Creato
+ creator: Utente
+ delete_admin_only: Elimina (solo per l'amministratore)
+ delete_confirm: Sei sicuro?
+ description: Descrizione
+ description_text: Descrizione Testo
+ edit: Modifica
+ home_page: Pagina iniziale
+ index:
+ intro: Sfoglia una selezione di progetti che utilizzano risorse %{site}
+ institutions: Istituzioni
+ ontologies: Ontologie
+ project_description: Descrizione del progetto
+ self: Progetti
+ title: Elenco dei progetti
+ view_projects_help: Visualizza i progetti Aiuto
+ recommender:
+ intro: Ottenere raccomandazioni per le ontologie più rilevanti da un estratto
+ di un testo biomedico o da un elenco di parole chiave
+ no_recommendations: Nessuna raccomandazione trovata
+ no_sets_recommended: Non ci sono set di ontologie consigliati per l'input fornito.
+ Provare con l'output "Ontologie".
+ ontology_recommendation_input: Incollare un paragrafo di testo o alcune parole
+ chiave per calcolare le raccomandazioni dell'ontologia.
+ ontology_recommender: Raccomandatore di ontologia
+ paste_text_recommendations: Incollare un paragrafo di testo o alcune parole chiave
+ da utilizzare per calcolare le raccomandazioni dell'ontologia
+ recommendation_error: Problema nel recupero delle raccomandazioni, provare di
+ nuovo
+ text_length_limit: Si prega di utilizzare meno di 500 parole. Se avete bisogno
+ di annotare testi più lunghi, potete utilizzare il servizio web di raccomandazione.
+ title: raccomandatore
+ valid_integer_max_ontologies_per_set: Il numero massimo di ontologie per set deve
+ essere un valore intero valido
+ valid_max_ontologies_per_set_range: Il numero massimo di ontologie per set deve
+ essere un numero compreso tra 2 e 4
+ valid_numeric_weights: Tutti i pesi devono essere valori numerici validi
+ weight_sum_greater_than_zero: La somma dei pesi deve essere maggiore di zero
+ weights_greater_than_zero: Tutti i pesi devono essere maggiori o uguali a zero
+ register:
+ account_errors: 'Errori nella creazione dell''account:'
+ confirm_password: Confermare la password
+ create_account: Creare un nuovo account
+ email: Email
+ first_name: Nome
+ last_name: Cognome
+ mailing_list: Registrarsi alla mailing list di AgroPortal
+ optional: "(Opzionale)"
+ password: Password
+ title: Registro
+ username: Nome utente
+ reproduce_results: Riprodurre questi risultati utilizzando il metodo
+ score: Punteggio
+ search:
+ search_place_holder: Inserisci un termine, ad esempio altezza della pianta
+ advanced_options:
+ search_language: Lingua di ricerca
+ ontologies: Ontologie
+ include_in_search_title: Includi nella ricerca
+ include_in_search_values:
+ property_values: Valori di proprietà
+ obolete_classses: Classi obsolete
+ ontology_views: Viste ontologiche
+ show_only_title: Mostra solo
+ show_only_values:
+ exact_matches: Corrispondenze esatte
+ classes_with_definitions: Classi con definizioni
+ show_advanced_options: Mostra opzioni avanzate
+ hide_advanced_options: Nascondi opzioni avanzate
+ match_in: Corrispondi in
+ ontologies: ontologie
+ result_component:
+ details: Dettagli
+ visualize: Visualizza
+ more_from_ontology: Altro da questa ontologia
+ reuses_in: Riutilizzi in
+ reuses_in_other_ontologies: Riutilizzi in altre ontologie
+
+ select_from_list: Selezionare dall'elenco
+ select_ontologies: Iniziare a digitare per selezionare le ontologie o lasciare vuoto
+ per utilizzarle tutte
+ select_ontologies_list: Selezionare le ontologie
+ show_advanced_options: Mostra le opzioni avanzate
+ specialization: Specializzazione
+ temporality: Temporalità
+ text: Testo
+ type: Tipo
+ umls_sem_type: Tipo UMLS Sem
+ view_fair_scores_definitions: Visualizza le definizioni dei punteggi equi
+ visits: Visite
+ weights_configuration: Configurazione dei pesi
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 740832c5e..ea8595feb 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,14 +1,24 @@
Rails.application.routes.draw do
root to: 'home#index'
+ mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
+
+ get'/tools', to: 'home#tools'
+ get 'auth/:provider/callback', to: 'login#create_omniauth'
+ get 'locale/:language', to: 'language#set_locale_language'
+ get 'metadata_export/index'
get '/notes/new_comment', to: 'notes#new_comment'
get '/notes/new_proposal', to: 'notes#new_proposal'
get '/notes/new_reply', to: 'notes#new_reply'
delete '/notes', to: 'notes#destroy'
resources :notes, constraints: { id: /.+/ }
+ get 'agents/show_search', to: 'agents#show_search'
+ get 'agents/:id/usages', to: 'agents#agent_usages', constraints: { id: /.+/ }
+ post 'agents/:id/usages', to: 'agents#update_agent_usages', constraints: { id: /.+/ }
resources :agents, constraints: { id: /.+/ }
post 'agents/:id', to: 'agents#update', constraints: { id: /.+/ }
+
resources :ontolobridge do
post :save_new_term_instructions, on: :collection
end
@@ -17,12 +27,9 @@
resources :users, path: :accounts, constraints: { id: /[\d\w\.\-\%\+ ]+/ }
- resources :reviews
-
get '/users/subscribe/:username', to: 'users#subscribe'
get '/users/un-subscribe/:email', to: 'users#un_subscribe'
- get '/mappings/loader' , to: 'mappings#loader'
post '/mappings/loader', to: 'mappings#loader_process'
get 'mappings/count/:id', to: 'mappings#count', constraints: { id: /.+/ }
get 'mappings/show_mappings', to: 'mappings#show_mappings'
@@ -33,16 +40,36 @@
resources :mappings
get 'mappings/:id', to: 'mappings#show', constraints: { id: /.+/ }
- resources :margin_notes
-
resources :concepts
- get 'ontologies/:ontology_id/concepts', to: 'concepts#show_concept'
+
+ scope :ontologies do
+ get ':ontology/concepts' => 'concepts#index'
+ get ':ontology/concepts/show', to: 'concepts#show'
+
+
+ get ':ontology/instances', to: 'instances#index'
+ get ':ontology/instances/show', to: 'instances#show'
+
+ get ':ontology/properties', to: 'properties#index'
+ get ':ontology/properties/show', to: 'properties#show'
+
+ get ':ontology/schemes', to: 'schemes#index'
+ get ':ontology/schemes/show', to: 'schemes#show'
+
+ get ':ontology/collections', to: 'collections#index'
+ get ':ontology/collections/show', to: 'collections#show'
+ end
+
+
resources :ontologies do
- resources :submissions
- get 'instances/:instance_id', to: 'instances#show', constraints: { instance_id: /[^\/?]+/ }
- get 'schemes/show_scheme', to: 'schemes#show'
- get 'collections/show'
+ resources :submissions do
+ get 'edit_properties'
+ end
+
+ get 'metrics'
+ get 'metrics_evolution'
+ get 'subscriptions'
end
if $SSO_ENABLED
@@ -61,19 +88,39 @@
namespace :admin do
resources :licenses, only: [:index, :create, :new]
+ match 'groups/synchronize_groups' => 'groups#synchronize_groups', via: [:post]
resources :groups, only: [:index, :create, :new, :edit, :update, :destroy]
resources :categories, only: [:index, :create, :new, :edit, :update, :destroy]
+ scope :search do
+ get '/', to: 'search#index'
+ post 'index_batch', to: 'search#index_batch'
+ post ':collection/init_schema', to: 'search#init_schema'
+ get ':collection/schema', to: 'search#show'
+ get ':collection/data', to: 'search#search'
+ end
+
end
+ post 'admin/clearcache', to: 'admin#clearcache'
+ post 'admin/resetcache', to: 'admin#resetcache'
+ post 'admin/clear_goo_cache', to: 'admin#clear_goo_cache'
+ post 'admin/clear_http_cache', to: 'admin#clear_http_cache'
+ get 'admin/ontologies_report', to: 'admin#ontologies_report'
+ post 'admin/refresh_ontologies_report', to: 'admin#refresh_ontologies_report'
+ delete 'admin/ontologies', to: 'admin#delete_ontologies'
+ delete 'admin/ontologies/:acronym/submissions/:id', to: 'admin#delete_submission'
+ put 'admin/ontologies', to: 'admin#process_ontologies'
+ get 'admin/update_check_enabled', to: 'admin#update_check_enabled'
+ get 'admin/ontologies/:acronym/log', to: 'admin#parse_log'
+
resources :subscriptions
resources :recommender
- resources :annotator
-
- resources :annotatorplus
+ get '/annotator', to: 'annotator#index'
+ get '/annotatorplus', to: 'annotator#annotator_plus'
+ get '/ncbo_annotatorplus', to: 'annotator#ncbo_annotator_plus'
- resources :ncbo_annotatorplus
resources :virtual_appliance
@@ -88,9 +135,11 @@
get '/:ontology/submissions/:submission_id/attributes/:attribute', to: 'ontologies_metadata_curator#show_metadata_value'
get '/:ontology/submissions/:submission_id', to: 'ontologies_metadata_curator#show_metadata_by_ontology'
end
-
+
get '' => 'home#index'
+ match 'sparql_proxy', to: 'admin#sparql_endpoint', via: [:get, :post]
+
# Top-level pages
match '/feedback', to: 'home#feedback', via: [:get, :post]
get '/account' => 'home#account'
@@ -99,25 +148,24 @@
get '/team' => 'static_pages#team'
get '/citeus' => 'static_pages#citeus'
get '/site_config' => 'home#site_config'
- get '/validate_ontology_file' => 'home#validate_ontology_file_show'
- match '/validate_ontology_file' => 'home#validate_ontology_file', via: [:get, :post]
- get '/layout_partial/:partial' => 'home#render_layout_partial'
+ post '/annotator_recommender_form' => 'home#annotator_recommender_form'
match '/visits', to: 'visits#index', via: :get
+ get 'statistics/index'
# Error pages
match "/404", to: "errors#not_found", via: :all
match "/500", to: "errors#internal_server_error", via: :all
- # Analytics
- match 'analytics', to: 'analytics#track', via: [:post]
-
# Robots.txt
get '/robots.txt' => 'robots#index'
# Ontologies
get '/ontologies/view/edit/:id' => 'ontologies#edit_view', :constraints => { id: /[^\/?]+/ }
get '/ontologies/view/new/:id' => 'ontologies#new_view'
-
+ get '/ontologies/:acronym/download' => 'ontologies_redirection#redirect_ontology'
+ get '/ontologies/:acronym/:id/serialize/:output_format' => 'ontologies#content_serializer', :id => /.+/
+ get '/ontologies/:acronym/htaccess' => 'ontologies_redirection#generate_htaccess'
+
get '/ontologies/virtual/:ontology' => 'ontologies#virtual', :as => :ontology_virtual
get '/ontologies/success/:id' => 'ontologies#submit_success'
match '/ontologies/:acronym' => 'ontologies#update', via: [:get, :post]
@@ -128,23 +176,25 @@
get '/ontologies/:acronym/classes/:purl_conceptid', to: 'ontologies#show', constraints: { purl_conceptid: /[^\/]+/ }
get '/ontologies/:acronym/: f', to: 'ontologies#show', constraints: { purl_conceptid: /[^\/]+/ }
match '/ontologies/:acronym/submissions/:id/edit_metadata' => 'submissions#edit_metadata', via: [:get, :post]
+ get '/ontologies_filter', to: 'ontologies#ontologies_filter'
- # Analytics
- get '/analytics/:action' => 'analytics#(?-mix:search_result_clicked|user_intention_surveys)'
+ get 'ontologies_selector', to: 'ontologies#ontologies_selector'
+ get 'ontologies_selector/results', to: 'ontologies#ontologies_selector_results'
# Notes
get 'ontologies/:ontology/notes/:noteid', to: 'notes#virtual_show', as: :note_virtual, noteid: /.+/
get 'ontologies/:ontology/notes', to: 'notes#virtual_show'
+ get '/ontologies/:acronym/:id' => 'ontologies_redirection#redirect', :id => /.+/
+
+
# Ajax
get '/ajax/' => 'ajax_proxy#get', :as => :ajax
- get '/ajax_concepts/:ontology/' => 'concepts#show', :constraints => { id: /[^\/?]+/ }
get '/ajax/class_details' => 'concepts#details'
get '/ajax/mappings/get_concept_table' => 'mappings#get_concept_table'
get '/ajax/json_ontology' => 'ajax_proxy#json_ontology'
get '/ajax/json_class' => 'ajax_proxy#json_class'
get '/ajax/jsonp' => 'ajax_proxy#jsonp'
- get '/ajax/loading_spinner' => 'ajax_proxy#loading_spinner'
get '/ajax/notes/delete' => 'notes#destroy'
get '/ajax/notes/concept_list' => 'notes#show_concept_list'
get '/ajax/classes/label' => 'concepts#show_label'
@@ -152,6 +202,7 @@
get '/ajax/classes/treeview' => 'concepts#show_tree'
get '/ajax/classes/list' => 'collections#show_members'
get '/ajax/classes/date_sorted_list' => 'concepts#show_date_sorted_list'
+ get '/ajax/properties/children' => 'properties#show_children'
get '/ajax/properties/tree' => 'concepts#property_tree'
get 'ajax/schemes/label', to: "schemes#show_label"
get 'ajax/collections/label', to: "collections#show_label"
@@ -160,21 +211,22 @@
get '/ajax/biomixer' => 'concepts#biomixer'
match '/ajax/cancelIdentifierRequest' => 'ajax_proxy#cancelIdentifierRequest', via: :post
get '/ajax/fair_score/html' => 'fair_score#details_html'
+ get '/ajax/submission/show_licenses/:id' => 'ontologies#show_licenses'
get '/ajax/fair_score/json' => 'fair_score#details_json'
- get '/ajax/:ontology/instances' => 'instances#index_by_ontology'
- get '/ajax/:ontology/classes/:conceptid/instances' => 'instances#index_by_class', :constraints => { conceptid: /[^\/?]+/ }
- get '/ajax/ontologies' , to:"ontologies#ajax_ontologies"
- get '/ajax/agents' , to:"agents#ajax_agents"
-
+ get '/ajax/ontologies', to: "ontologies#ajax_ontologies"
+ get '/ajax/agents', to: "agents#ajax_agents"
+ get '/ajax/images/show' => 'application#show_image_modal'
# User
post '/accounts/:id/custom_ontologies' => 'users#custom_ontologies', :as => :custom_ontologies
- get '/login_as/:login_as' => 'login#login_as' , constraints: { login_as: /[\d\w\.\-\%\+ ]+/ }
+ get '/login_as/:login_as' => 'login#login_as', constraints: { login_as: /[\d\w\.\-\%\+ ]+/ }
+ post '/login/send_pass', to: 'login#send_pass'
- # History
- get '/tab/remove/:ontology' => 'history#remove', :as => :remove_tab
- get '/tab/update/:ontology/:concept' => 'history#update', :as => :update_tab
+ # Search
+ get 'search', to: 'search#index'
+ get 'ajax/search/ontologies/content', to: 'search#json_ontology_content_search'
- get 'jambalaya/:ontology/:id' => 'visual#jam', :as => :jam
+ get 'check_resolvability' => 'check_resolvability#index'
+ get 'check_url_resolvability' => 'check_resolvability#check_resolvability'
# Admin
match '/admin/clearcache' => 'admin#clearcache', via: [:post]
@@ -221,5 +273,8 @@
get '/visualize' => 'ontologies#visualize', :as => :visualize_concept, :constraints => { ontology: /[^\/?]+/, id: /[^\/?]+/, ontologyid: /[^\/?]+/, conceptid: /[^\/?]+/ }
get '/exhibit/:ontology/:id' => 'concepts#exhibit'
-
+
+
+ mount Lookbook::Engine, at: "/lookbook"
+
end
diff --git a/config/settings.yml b/config/settings.yml
index d914e5f5d..6c2194f52 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -21,6 +21,7 @@ shared:
virtual_appliance: 'https://ontoportal.github.io/administration/'
widgets: 'http://www.bioontology.org/wiki/NCBO_Widgets'
mappings: 'https://www.bioontology.org/wiki/BioPortal_Help#Mappings_Tab'
+ metadata_help: 'https://doc.jonquetlab.lirmm.fr/share/32c082ff-97f5-45f4-bafe-05f41c9a5ce4'
wiki: 'https://github.com/lifewatch-eric/documentation/wiki'
youtube: 'https://www.youtube.com/channel/UCP6ag3SoJ6oeisE7ibg4-pg'
diff --git a/db/schema.rb b/db/schema.rb
index 51716810e..22dc2b318 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2020_09_21_120918) do
- create_table "analytics", id: :integer, charset: "utf8mb3", force: :cascade do |t|
+ create_table "analytics", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.string "segment"
t.string "action"
t.string "bp_slice"
@@ -22,13 +22,13 @@
t.datetime "updated_at", precision: nil
end
- create_table "licenses", charset: "utf8mb3", force: :cascade do |t|
+ create_table "licenses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.text "encrypted_key"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
end
- create_table "ontologies", charset: "utf8mb3", force: :cascade do |t|
+ create_table "ontologies", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.string "acronym", null: false
t.text "new_term_instructions"
t.text "custom_message"
@@ -37,7 +37,7 @@
t.index ["acronym"], name: "index_ontologies_on_acronym", unique: true
end
- create_table "timeouts", id: :integer, charset: "utf8mb3", force: :cascade do |t|
+ create_table "timeouts", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.string "path"
t.integer "ontology_id"
t.text "concept_id"
@@ -45,7 +45,7 @@
t.timestamp "created"
end
- create_table "virtual_appliance_users", id: :integer, charset: "utf8mb3", force: :cascade do |t|
+ create_table "virtual_appliance_users", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.string "user_id"
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
diff --git a/docker-compose.yml b/docker-compose.yml
index 38be0278f..1eb928b19 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,52 +1,86 @@
x-app: &default-app
- build:
- context: "."
- target: "app"
- args:
- - "UID=${UID:-1000}"
- - "GID=${GID:-1000}"
- - "RAILS_ENV=${RAILS_ENV:-production}"
- - "NODE_ENV=${NODE_ENV:-production}"
- depends_on:
- - "db"
- - "cache"
- links:
- - "db"
- - "cache"
+ image: agroportal/ontoportal_web_ui:development
env_file:
- ".env"
tty: true
volumes:
- - "${DOCKER_WEB_VOLUME}"
- - bundle:/usr/local/bundle
+ - .:/app
+ - bundle:/usr/local/bundle
- node:/node_modules
+ - rails_cache:/app/tmp/cache
+ - assets:/app/public/assets
+ - /var/run/docker.sock:/var/run/docker.sock
+ tmpfs:
+ - /tmp
+ - /app/tmp/pids
services:
db:
- environment:
- MYSQL_ROOT_PASSWORD: 'bp_user'
- image: "mysql:latest"
- profiles: ["db"]
+ image: "mysql:8.0"
+ networks:
+ - default
+ volumes:
+ - mysql-data:/var/lib/mysql
ports:
- "3306:3306"
- volumes:
- - db-v:/var/lib/mysql
+ environment:
+ MYSQL_ROOT_PASSWORD: root
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
+ timeout: 5s
+ retries: 3
+
cache:
- deploy:
- resources:
- limits:
- cpus: "${DOCKER_REDIS_CPUS:-0}"
- memory: "${DOCKER_REDIS_MEMORY:-0}"
- image: "memcached:1.6.17-bullseye"
- profiles: ["cache"]
+ image: memcached:latest
+ restart: unless-stopped
+ command: [ "-m", "1024" ]
+ networks:
+ - default
+ ports:
+ - "11211:11211"
+ node:
+ <<: *default-app
+ command: "yarn build --watch"
- web:
+ rails:
<<: *default-app
+ depends_on:
+ db:
+ condition: service_healthy
+ cache:
+ condition: service_started
+ node:
+ condition: service_started
+ links:
+ - db
+ - cache
+ environment:
+ BUNDLE_WITHOUT: ''
+ DB_HOST: db
+ CACHE_HOST: cache
ports:
- - "${DOCKER_WEB_PORT_FORWARD:-127.0.0.1:3000}:${PORT:-3000}"
- profiles: ["web"]
- command: "yarn build --watch"
+ - "3000:3000"
+ test:
+ <<: *default-app
+ depends_on:
+ - db
+ - cache
+ - chrome-server
+ network_mode: 'host'
+ environment:
+ BUNDLE_WITHOUT: ''
+ DB_HOST: 127.0.0.1
+ CACHE_HOST: 127.0.0.1
+ chrome-server:
+ image: selenium/standalone-chrome:112.0-chromedriver-112.0-grid-4.9.0-20230421
+ shm_size: 2g
+ ports:
+ - "4444:4444"
+ - "7900:7900"
+
volumes:
- db-v:
+ mysql-data:
bundle:
+ rails_cache:
+ assets:
node:
diff --git a/lib/log.rb b/lib/log.rb
index 00c815d60..edef5506f 100644
--- a/lib/log.rb
+++ b/lib/log.rb
@@ -12,13 +12,7 @@ class LOG
# :concept_id
# :concept_name
def self.add(level, message, request = nil, remote_params = nil)
- if request
- if !$REMOTE_LOGGING.nil? && $REMOTE_LOGGING
- remote(level, message, request, remote_params)
- end
- else
- local(level, message)
- end
+ local(level, message)
end
private
diff --git a/lib/tasks/generate_component_previews.rake b/lib/tasks/generate_component_previews.rake
new file mode 100644
index 000000000..2bc61c28b
--- /dev/null
+++ b/lib/tasks/generate_component_previews.rake
@@ -0,0 +1,34 @@
+# lib/tasks/generate_component_previews.rake
+
+namespace :component_previews do
+ desc "Generate previews for all components"
+ task generate: :environment do
+ components_path = Rails.root.join("app/components")
+ components = Dir.glob("#{components_path}/**/*_component.rb")
+
+ components.each do |component_path|
+ component_name = File.basename(component_path, "_component.rb")
+ preview_path = Rails.root.join("test/components/previews/#{component_name}_preview.rb")
+
+ # Skip if the preview already exists
+ next if File.exist?(preview_path)
+
+ File.open(preview_path, "w") do |file|
+ file.puts("class #{component_name.camelize}Preview < ViewComponent::Preview")
+ file.puts(" def default")
+ file.puts(" # Initialize the component with any necessary data")
+ file.puts(" component = #{component_name.camelize}Component.new")
+
+ file.puts(" # Add any necessary data or context to the component")
+ file.puts(" # component.some_data = some_value")
+
+ file.puts(" # Render the component")
+ file.puts(" render(component)")
+ file.puts(" end")
+ file.puts("end")
+ end
+
+ puts "Generated preview for #{component_name}"
+ end
+ end
+end
diff --git a/public/browse/.bowerrc b/public/browse/.bowerrc
deleted file mode 100755
index 7dcff4cd0..000000000
--- a/public/browse/.bowerrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "directory" : "lib"
-}
\ No newline at end of file
diff --git a/public/browse/.gitignore b/public/browse/.gitignore
deleted file mode 100755
index b702acc68..000000000
--- a/public/browse/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-logs/*
-!.gitkeep
-node_modules/
-bower_components/
-tmp
-.DS_Store
-.idea
\ No newline at end of file
diff --git a/public/browse/.jshintrc b/public/browse/.jshintrc
deleted file mode 100755
index 6f00218e3..000000000
--- a/public/browse/.jshintrc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "globalstrict": true,
- "globals": {
- "angular": false,
- "describe": false,
- "it": false,
- "expect": false,
- "beforeEach": false,
- "afterEach": false,
- "module": false,
- "inject": false
- }
-}
\ No newline at end of file
diff --git a/public/browse/app.css b/public/browse/app.css
deleted file mode 100755
index 4cc86735e..000000000
--- a/public/browse/app.css
+++ /dev/null
@@ -1,184 +0,0 @@
-.grid-container {
- max-width: 1400px;
-}
-[ng-cloak].splash {
- display: block !important;
-}
-.splash {
- display: none;
- width: 25%;
- height: 4em;
- padding: 2em;
- text-align: center;
- margin: 2em auto;
- background-color: #ECECEC;
- border-radius: 3px;
-}
-[ng-cloak] {
- display: none;
-}
-.admin {
- background-color: #EFFFEF !important;
-}
-.welcome_admin {
- width: 33%;
- padding: 7px 10px 5px;
- border-radius: 3px;
- text-align: center;
- top: -5em;
- position: relative;
- float: right;
- left: -33%;
-}
-.search {
- float: left;
- width: 150px;
- padding: 2px 4px 1px;
- margin-top: -5px;
- width: 200px;
-}
-.smaller {
- color: gray;
- font-size: .8em;
- padding-bottom: 2px;
-}
-#facets {
- margin-top: 1em;
-}
-.new_ontology_button {
- display: inline-block;
- width: 100%;
- padding-left: 0px !important;
- padding-right: 0px !important;
- margin-top: 1em;
-}
-.facet {
- margin: 1em 0;
- border: thin lightGray solid;
- padding: 5px;
- border-radius: 3px;
-}
-.facet_disabled {
- color: gray;
-}
-.checkbox_list {
- max-height: 200px;
- overflow: auto;
- padding-left: 1px;
-}
-.checkbox_list > span {
- overflow-x: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- width: 200px;
- display: block;
-}
-#sorting {
-}
-#sorting_float {
- float: right;
- margin-bottom: .5em;
-}
-@keyframes highlight {
- 0% {
- background: yellow;
- }
- 100% {
- background: none;
- }
-}
-@-webkit-keyframes highlight {
- 0% {
- background: yellow;
- }
- 100% {
- background: none;
- }
-}
-.trigger_highlight-add, .trigger_highlight-remove {
- -webkit-animation: highlight 1s;
- animation: highlight 1s;
-}
-#ontologies {
-}
-.clear {
- clear: both;
-}
-.ontology {
- border: thin gray solid;
- border-radius: 5px;
- padding: .5em 1em .5em;
- margin: 1em 0;
-}
-.ontology_view_badge {
- float: left;
- padding: 5px;
- text-align: center;
- margin-right: 5px;
- border-radius: 3px;
- color: white;
- background-color: #234979;
- font-size: 1em;
- font-weight: bold;
-}
-.ontology_view_badge a {
- color: white;
- text-decoration: none;
-}
-.locked_ont {
- font-size: .65em;
- padding-left: .2em;
- color: gray;
- cursor: help;
- /* Make the lock appear in the upper left corner */
- /*
- background-color: #234979;
- padding: 2.5px 4px;
- font-size: 1em;
- color: white;
- position: relative;
- left: -10px;
- top: -8px;
- border-radius: 5px 0px;
- float: left;
- */
-}
-.ont-info {
- margin: 5px 5px 0 0;
- display: inline-block;
- padding: 5px 10px 3px;
- border-radius: 3px;
- background-color: #ECECEC;
- font-size: 11px;
-}
-.badge_grid {
- padding-bottom: 10px;
- float: right !important;
-}
-.ontology_badge {
- border-radius: 5px;
- text-align: center;
- max-width: 120px;
- height: 45px;
- max-height: 45px;
- border: solid #234979 thin;
-}
-.ontology_badge:hover {
- cursor: pointer;
-}
-.badge_title {
- border-radius: 4px 4px 0 0;
- font-size: 12px;
- color: white;
- background-color: #234979;
-}
-.badge_count {
- border-radius: 0 0 4px 4px;
- height: 22px;
- font-size: 1.1em;
- font-weight: bold;
- color: #234979;
-}
-.ontology_badge:hover .badge_count {
- background-color: rgba(220, 235, 255, 0.79);
-}
\ No newline at end of file
diff --git a/public/browse/app.js b/public/browse/app.js
deleted file mode 100755
index fe18ca0d9..000000000
--- a/public/browse/app.js
+++ /dev/null
@@ -1,417 +0,0 @@
-'use strict';
-
-// Declare app level module which depends on views, and components
-angular.module('FacetedBrowsing', [
- 'ngRoute',
- 'FacetedBrowsing.OntologyList'
-]).
-config( ['$locationProvider', function ($locationProvider) {
- $locationProvider.html5Mode(true);
-}])
-;
-
-var app = angular.module('FacetedBrowsing.OntologyList', ['checklist-model', 'ngAnimate', 'pasvaz.bindonce'])
-
-.controller('OntologyList', ['$scope', '$animate', '$timeout', function($scope, $animate, $timeout) {
- // Default values
- $scope.visible_ont_count = 0;
- $scope.ontology_sort_order = "-popularity";
- $scope.previous_sort_order = "-popularity";
- $scope.show_highlight = false;
-
- // Data transfer from Rails
- $scope.debug = jQuery(document).data().bp.development;
- $scope.admin = jQuery(document).data().bp.admin;
- $scope.ontologies = jQuery(document).data().bp.ontologies;
- $scope.formats = jQuery(document).data().bp.formats.sort();
- $scope.categories = jQuery(document).data().bp.categories.sort(function(a, b){
- if (a.name < b.name) return -1;
- if (a.name > b.name) return 1;
- return 0;
- });
- $scope.categories_hash = jQuery(document).data().bp.categories_hash;
- $scope.groups = jQuery(document).data().bp.groups.sort(function(a, b){
- if (a.acronym < b.acronym) return -1;
- if (a.acronym > b.acronym) return 1;
- return 0;
- });
- $scope.groups_hash = jQuery(document).data().bp.groups_hash;
-
- $scope.formality_levels = jQuery(document).data().bp.formality_levels;
- $scope.natural_languages = jQuery(document).data().bp.natural_languages;
- $scope.is_of_type = jQuery(document).data().bp.is_of_type;
-
- // Search setup
- $scope.searchText = null;
- $scope.ontIndex = lunr(function() {
- this.field('acronym', 100);
- this.field('name', 50);
- this.field('description');
- this.ref('id');
- });
- $scope.ontIndex.pipeline.reset();
-
- // Default setup for facets
- $scope.facets = {
- types: {
- active: ["ontology"],
- ont_property: "type",
- filter: function(ontology) {
- if ($scope.facets.types.active.length == 0)
- return true;
- if ($scope.facets.types.active.indexOf(ontology.type) === -1)
- return false;
- return true;
- },
- },
- formats: {
- active: [],
- ont_property: "format",
- filter: function(ontology) {
- if ($scope.facets.formats.active.length == 0)
- return true;
- if ($scope.facets.formats.active.indexOf(ontology.format) === -1)
- return false;
- return true;
- },
- },
- groups: {
- active: [],
- ont_property: "groups",
- filter: function(ontology) {
- if ($scope.facets.groups.active.length == 0)
- return true;
- if (intersection($scope.facets.groups.active, ontology.groups).length === 0)
- return false;
- return true;
- },
- },
- categories: {
- active: [],
- ont_property: "categories",
- filter: function(ontology) {
- if ($scope.facets.categories.active.length == 0)
- return true;
- if (intersection($scope.facets.categories.active, ontology.categories).length === 0)
- return false;
- return true;
- },
- },
- artifacts: {
- active: [],
- ont_property: "artifacts",
- filter: function(ontology) {
- if ($scope.facets.artifacts.active.length == 0)
- return true;
- if (intersection($scope.facets.artifacts.active, ontology.artifacts).length === 0)
- return false;
- return true;
- },
- },
- missing_status: {
- active: "",
- ont_property: "submissionStatus",
- values: ["None", "RDF", "OBSOLETE", "METRICS", "RDF_LABELS", "UPLOADED", "INDEXED", "ANNOTATOR", "DIFF"],
- filter: function(ontology) {
- if ($scope.facets.missing_status.active == "")
- return true;
- if (ontology.submissionStatus.indexOf($scope.facets.missing_status.active) !== -1)
- return false;
- return true;
- }
- },
- upload_date: {
- active: "",
- ont_property: "creationDate",
- values: {day: 1, week: 7, month: 30, three_months: 90, six_months: 180, year: 365, all: "all"},
- day_text: ["day", "week", "month", "three_months", "six_months", "year", "all"],
- filter: function(ontology) {
- var active = $scope.facets.upload_date.active;
- if (active == "")
- return true;
- if (!ontology.submission)
- return false;
- var ontDate = new Date(ontology.creationDate);
- var compareDate = new Date();
- compareDate.setDate(compareDate.getDate() - active);
- if (ontDate >= compareDate)
- return true;
- return false;
- }
- },
- formality_levels: {
- active: [],
- ont_property: "hasFormalityLevel",
- filter: function(ontology) {
- if ($scope.facets.formality_levels.active.length == 0)
- return true;
- if ($scope.facets.formality_levels.active.indexOf(ontology.hasFormalityLevel) === -1)
- return false;
- return true;
- }
- },
- natural_languages: {
- active: [],
- ont_property: "naturalLanguage",
- filter: function(ontology) {
- if ($scope.facets.natural_languages.active.length == 0)
- return true;
- if ( !ontology.naturalLanguage )
- return false;
- for (var i = 0; i < ontology.naturalLanguage.length; i++) {
- if ($scope.facets.natural_languages.active.indexOf(ontology.naturalLanguage[i]) !== -1)
- return true;
- }
- return false;
- }
- },
- is_of_type: {
- active: [],
- ont_property: "isOfType",
- filter: function(ontology) {
- if ($scope.facets.is_of_type.active.length == 0)
- return true;
- if ($scope.facets.is_of_type.active.indexOf(ontology.isOfType) === -1)
- return false;
- return true;
- }
- }
- }
-
- // Instantiate object counts
- // This doesn't happen on the facet itself because
- // there is a $watch directive and updating counts
- // on the facets causes an infinite loop.
- $scope.facet_counts = {};
- Object.keys($scope.facets).forEach(function(facet) {$scope.facet_counts[facet] = {}});
-
- // Default values for facets that aren't definied on the ontologies
- $scope.types = {
- ontology: {sort: 1, id: "ontology"},
- ontology_view: {sort: 2, id: "ontology_view"}
- };
- $scope.artifacts = ["notes", "reviews", "projects", "summary_only"];
-
- $scope.groupAcronyms = function(groups) {
- var groupNames = [];
- angular.forEach(groups, function(group) {
- groupNames.push($scope.groups_hash[group].acronym);
- });
- return groupNames;
- };
-
- $scope.categoryNames = function(categories) {
- var catNames = [];
- angular.forEach(categories, function(category) {
- catNames.push($scope.categories_hash[category].name)
- })
- return catNames;
- }
-
- $scope.adminUsernames = function(admins) {
- return admins.map(function(a){return a.split('/').slice(-1)[0]});
- }
-
- $scope.ontologySortOrder = function(newOrder) {
- $scope.ontology_sort_order = newOrder;
- }
-
- // This watches the facets and updates the list depending on which facets are selected
- // All facets are basically ANDed together and return true if no options under the facet are selected.
- $scope.$watch('facets', function() {
- filterOntologies();
- }, true);
-
- $scope.$watch('searchText', function() {
- filterOntologies();
- });
-
- var filterOntologies = function() {
- var key, i, ontology, facet, facet_count, show, other_facets, count = 0;
- $scope.show_highlight = false;
- $scope.show_highlight = true;
-
- // Reset facet counts
- Object.keys($scope.facet_counts).forEach(function(key) {
- $scope.facet_counts[key] = {};
- });
-
- // First, filter by search. Do this first because the facets
- // will apply on top of the search results (EX: for hiding views)
- filterSearch();
-
- // Filter ontologies based on facet + count for facets
- for (i = 0; i < $scope.ontologies.length; i++) {
- ontology = $scope.ontologies[i];
-
- if (searchActive() && ontology.show === false) continue;
-
- // Filter out ontologies based on their facet filter functions
- ontology.show = Object.keys($scope.facets).map(function(key) {
- return $scope.facets[key].filter(ontology);
- }).every(Boolean);
-
- // Check each facet entry to calculate counts
- // Counts are calculated by looking at whether or not ontologies match OTHER facets
- // IE, counts show what will be available for a given facet entry if that entry
- // were to be selected relative to what is already selected in other facets.
- Object.keys($scope.facets).forEach(function(key) {
- facet = $scope.facets[key];
- other_facets = Object.keys($scope.facets).filter(function(f){return key != f});
- show = other_facets.map(function(other_facet){return $scope.facets[other_facet].filter(ontology)}).every(Boolean);
- if (show) {
- facet_count = $scope.facet_counts[key];
- if (angular.isArray(ontology[facet.ont_property])) {
- ontology[facet.ont_property].forEach(function(val) {
- facet_count[val] = (facet_count[val] || 0) + 1;
- });
- } else {
- facet_count[ontology[facet.ont_property]] = (facet_count[ontology[facet.ont_property]] || 0) + 1;
- }
- }
- });
- }
-
- $scope.visible_ont_count = $scope.ontologies.filter(function(ont) {return ont.show}).length;
-
- // Highlight the count
- count = $("#visible_ont_count");
- if (count.hasClass("trigger_highlight")) {
- $animate.removeClass(count, "trigger_highlight");
- } else {
- $animate.addClass(count, "trigger_highlight");
- }
- }
-
- var filterSearch = function() {
- var i, results, ontology, found = {};
- if (!searchActive()) {
- $scope.ontologySortOrder($scope.previous_sort_order);
- return;
- }
- if ($scope.ontology_sort_order !== "-search_rank") {
- $scope.previous_sort_order = $scope.ontology_sort_order;
- }
- $scope.ontologySortOrder("-search_rank");
- results = $scope.ontIndex.search($scope.searchText);
-
- angular.forEach(results, function(r){found[r.ref] = r});
- for (i = 0; i < $scope.ontologies.length; i++) {
- ontology = $scope.ontologies[i];
- ontology.show = false;
- ontology.search_rank = 0;
- if (found[ontology.id]) {
- ontology.show = true;
- ontology.search_rank = found[ontology.id].score;
- }
- }
- }
-
- var searchActive = function() {
- return !($scope.searchText === null || $scope.searchText === "");
- }
-
- var countAllInFacet = function(facet) {
- var active_facets = Object.keys($scope.facets).filter(function(facet) {return $scope.facets[facet].active.length > 0});
- if (active_facets.length == 0 || (active_facets.length == 1 && active_facets[0] == facet)) {
- return true;
- }
- return false;
- }
-
- var intersection = function(x, y) {
- if (typeof x === 'undefined' || typeof y === 'undefined') {return [];}
- var ret = [];
- for (var i = 0; i < x.length; i++) {
- for (var z = 0; z < y.length; z++) {
- if (x[i] == y[z]) {
- ret.push(i);
- break;
- }
- }
- }
- return ret;
- }
-
-
- $scope.init = function() {
- $scope.ontologies = jQuery(document).data().bp.fullOntologies;
- if (BP_queryString().filter) {
- angular.forEach($scope.groups, function(group) {
- if (group.acronym == BP_queryString().filter)
- $scope.facets.groups.active.push(group.id);
- });
- }
- filterOntologies();
- angular.forEach($scope.ontologies, function(ont) {
- $scope.ontIndex.add({
- id: ont.id,
- acronym: ont.acronym,
- name: ont.name,
- description: ont.description
- })
- });
- }
- $timeout($scope.init);
-
-}])
-
-.filter('idToTitle', function() {
- return function(input) {
- if (input) {
- var splitInput = input.replace(/_/g, " ").split(" ");
- var newInput = [];
- var word;
- for (word in splitInput) {
- word = splitInput[word];
- if (word[0].toUpperCase() == word[0]) {
- newInput.push(word);
- } else {
- newInput.push(word[0].toUpperCase() + word.slice(1));
- }
-
- }
- return newInput.join(" ");
- }
- };
-})
-
-.filter('humanShortNum', function() {
- return function(input) {
- if (input) {
- var num = parseInt(input);
- if (num < 10000) {return num;}
- if (num > 10000 && num < 1000000) {
- return String(+(Math.round(num / 1000 + "e+1") + "e-1")) + "k"
- }
- if (num > 1000000) {
- return String(+(Math.round(num / 100000 + "e+1") + "e-1")) + "M"
- }
- return newInput.join(" ");
- }
- };
-})
-
-.filter("toArray", function() {
- return function(obj) {
- var result = [];
- angular.forEach(obj, function(val, key) {
- result.push(val);
- });
- return result;
- };
-})
-
-.filter('htmlToText', function() {
- return function(text) {
- return String(text).replace(/<[^>]+>/gm, '');
- }
-})
-
-.filter('descriptionToText', function() {
- return function(text) {
- text = String(text).replace(/<[^>]+>/gm, '');
- return text.split(/\.\W/)[0];
- }
-})
-;
\ No newline at end of file
diff --git a/public/browse/bower.json b/public/browse/bower.json
deleted file mode 100755
index ed30585ec..000000000
--- a/public/browse/bower.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "angular-seed",
- "description": "A starter project for AngularJS",
- "version": "0.0.0",
- "homepage": "https://github.com/angular/angular-seed",
- "license": "MIT",
- "private": true,
- "dependencies": {
- "angular": "1.3.x",
- "angular-route": "1.3.x",
- "angular-loader": "1.3.x",
- "angular-mocks": "~1.3.x",
- "angular-animate": "1.3.x",
- "html5-boilerplate": "~4.3.0",
- "lunr.js": "~0.5.6",
- "angular-bindonce": "~0.3.3"
- }
-}
diff --git a/public/browse/checklist-model.js b/public/browse/checklist-model.js
deleted file mode 100644
index 228f0c5a0..000000000
--- a/public/browse/checklist-model.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Checklist-model
- * AngularJS directive for list of checkboxes
- */
-
-angular.module('checklist-model', [])
-.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
- // contains
- function contains(arr, item) {
- if (angular.isArray(arr)) {
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- return true;
- }
- }
- }
- return false;
- }
-
- // add
- function add(arr, item) {
- arr = angular.isArray(arr) ? arr : [];
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- return arr;
- }
- }
- arr.push(item);
- return arr;
- }
-
- // remove
- function remove(arr, item) {
- if (angular.isArray(arr)) {
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- arr.splice(i, 1);
- break;
- }
- }
- }
- return arr;
- }
-
- // http://stackoverflow.com/a/19228302/1458162
- function postLinkFn(scope, elem, attrs) {
- // compile with `ng-model` pointing to `checked`
- $compile(elem)(scope);
-
- // getter / setter for original model
- var getter = $parse(attrs.checklistModel);
- var setter = getter.assign;
-
- // value added to list
- var value = $parse(attrs.checklistValue)(scope.$parent);
-
- // watch UI checked change
- scope.$watch('checked', function(newValue, oldValue) {
- if (newValue === oldValue) {
- return;
- }
- var current = getter(scope.$parent);
- if (newValue === true) {
- setter(scope.$parent, add(current, value));
- } else {
- setter(scope.$parent, remove(current, value));
- }
- });
-
- // watch original model change
- scope.$parent.$watch(attrs.checklistModel, function(newArr, oldArr) {
- scope.checked = contains(newArr, value);
- }, true);
- }
-
- return {
- restrict: 'A',
- priority: 1000,
- terminal: true,
- scope: true,
- compile: function(tElement, tAttrs) {
- if (tElement[0].tagName !== 'INPUT' || tElement[0].getAttribute('type') !== 'checkbox') {
- throw 'checklist-model should be applied to `input[type="checkbox"]`.';
- }
-
- if (!tAttrs.checklistValue) {
- throw 'You should provide `checklist-value`.';
- }
-
- // exclude recursion
- tElement.removeAttr('checklist-model');
-
- // local scope var storing individual checkbox model
- tElement.attr('ng-model', 'checked');
-
- return postLinkFn;
- }
- };
-}]);
diff --git a/public/browse/e2e-tests/protractor.conf.js b/public/browse/e2e-tests/protractor.conf.js
deleted file mode 100755
index b45a117aa..000000000
--- a/public/browse/e2e-tests/protractor.conf.js
+++ /dev/null
@@ -1,19 +0,0 @@
-exports.config = {
- allScriptsTimeout: 11000,
-
- specs: [
- '*.js'
- ],
-
- capabilities: {
- 'browserName': 'chrome'
- },
-
- baseUrl: 'http://localhost:8000/app/',
-
- framework: 'jasmine',
-
- jasmineNodeOpts: {
- defaultTimeoutInterval: 30000
- }
-};
diff --git a/public/browse/e2e-tests/scenarios.js b/public/browse/e2e-tests/scenarios.js
deleted file mode 100755
index 59d816fc1..000000000
--- a/public/browse/e2e-tests/scenarios.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-/* https://github.com/angular/protractor/blob/master/docs/toc.md */
-
-describe('faceted browsing', function() {
-
- browser.get('index.html');
-
- it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
- expect(browser.getLocationAbsUrl()).toMatch("/view1");
- });
-
-
- describe('view1', function() {
-
- beforeEach(function() {
- browser.get('index.html#/view1');
- });
-
-
- it('should render view1 when user navigates to /view1', function() {
- expect(element.all(by.css('[ng-view] p')).first().getText()).
- toMatch(/partial for view 1/);
- });
-
- });
-
-
- describe('view2', function() {
-
- beforeEach(function() {
- browser.get('index.html#/view2');
- });
-
-
- it('should render view2 when user navigates to /view2', function() {
- expect(element.all(by.css('[ng-view] p')).first().getText()).
- toMatch(/partial for view 2/);
- });
-
- });
-});
diff --git a/public/browse/font/webhostinghub-glyphs.eot b/public/browse/font/webhostinghub-glyphs.eot
deleted file mode 100755
index 7e9248cee..000000000
Binary files a/public/browse/font/webhostinghub-glyphs.eot and /dev/null differ
diff --git a/public/browse/font/webhostinghub-glyphs.svg b/public/browse/font/webhostinghub-glyphs.svg
deleted file mode 100755
index b54ba7923..000000000
--- a/public/browse/font/webhostinghub-glyphs.svg
+++ /dev/null
@@ -1,7835 +0,0 @@
-
-
-
diff --git a/public/browse/font/webhostinghub-glyphs.ttf b/public/browse/font/webhostinghub-glyphs.ttf
deleted file mode 100755
index 6ad706c63..000000000
Binary files a/public/browse/font/webhostinghub-glyphs.ttf and /dev/null differ
diff --git a/public/browse/font/whhg.css b/public/browse/font/whhg.css
deleted file mode 100755
index 9423e9914..000000000
--- a/public/browse/font/whhg.css
+++ /dev/null
@@ -1,2085 +0,0 @@
-@font-face {
- font-family: 'WebHostingHub-Glyphs';
- src: url('webhostinghub-glyphs.eot');
- src: url('webhostinghub-glyphs.eot?#iefix') format('embedded-opentype'),
- url('webhostinghub-glyphs.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
- -moz-font-feature-settings: "calt=0,liga=0";
-}
-[class^="icon-"], [class*=" icon-"] {font-family:'WebHostingHub-Glyphs';background:none;width:auto;height:auto;font-style:normal}
-.icon-aaabattery:before{content:'\f413'}
-.icon-abacus:before{content:'\f261'}
-.icon-accountfilter:before{content:'\f05e'}
-.icon-acsource:before{content:'\f3ea'}
-.icon-addfriend:before{content:'\f3da'}
-.icon-address:before{content:'\f08f'}
-.icon-addshape:before{content:'\f1fd'}
-.icon-addtocart:before{content:'\f394'}
-.icon-addtolist:before{content:'\f2ac'}
-.icon-adjust:before{content:'\f484'}
-.icon-adobe:before{content:'\f1c9'}
-.icon-ads-bilboard:before{content:'\f082'}
-.icon-affiliate:before{content:'\f01e'}
-.icon-ajax:before{content:'\f06f'}
-.icon-alarm:before{content:'\f233'}
-.icon-alarmalt:before{content:'\f23d'}
-.icon-album-cover:before{content:'\f19f'}
-.icon-alertalt:before{content:'\f2b4'}
-.icon-alertpay:before{content:'\f269'}
-.icon-algorhythm:before{content:'\f0b8'}
-.icon-alienship:before{content:'\f41f'}
-.icon-alienware:before{content:'\f3be'}
-.icon-align-center:before{content:'\f1d9'}
-.icon-align-justify:before{content:'\f1da'}
-.icon-align-left:before{content:'\f1d7'}
-.icon-align-right:before{content:'\f1d8'}
-.icon-alignbottomedge:before{content:'\f1d3'}
-.icon-alignhorizontalcenter:before{content:'\f1d2'}
-.icon-alignleftedge:before{content:'\f1d6'}
-.icon-alignrightedge:before{content:'\f1d5'}
-.icon-aligntopedge:before{content:'\f1d4'}
-.icon-alignverticalcenter:before{content:'\f1d1'}
-.icon-amd:before{content:'\f020'}
-.icon-analogdown:before{content:'\f2cb'}
-.icon-analogleft:before{content:'\f2c8'}
-.icon-analogright:before{content:'\f2c9'}
-.icon-analogup:before{content:'\f2ca'}
-.icon-analytics-piechart:before{content:'\f000'}
-.icon-analyticsalt-piechartalt:before{content:'\f001'}
-.icon-anchor-port:before{content:'\f21d'}
-.icon-android:before{content:'\f12a'}
-.icon-angrybirds:before{content:'\f3c1'}
-.icon-antenna:before{content:'\f3ec'}
-.icon-apache-feather:before{content:'\f056'}
-.icon-aperture:before{content:'\f356'}
-.icon-appointment-agenda:before{content:'\f26c'}
-.icon-archive:before{content:'\f171'}
-.icon-arrow-down:before{content:'\f2fe'}
-.icon-arrow-left:before{content:'\f305'}
-.icon-arrow-right:before{content:'\f304'}
-.icon-arrow-up:before{content:'\f301'}
-.icon-asterisk:before{content:'\f317'}
-.icon-asteriskalt:before{content:'\002a'}
-.icon-at:before{content:'\40'}
-.icon-atari:before{content:'\f3b9'}
-.icon-authentication-keyalt:before{content:'\f051'}
-.icon-automobile-car:before{content:'\f239'}
-.icon-autorespond:before{content:'\f08e'}
-.icon-avatar:before{content:'\f15a'}
-.icon-avataralt:before{content:'\f161'}
-.icon-avengers:before{content:'\f342'}
-.icon-awstats:before{content:'\f04c'}
-.icon-axe:before{content:'\f2ef'}
-.icon-backup-vault:before{content:'\f004'}
-.icon-backupalt-vaultalt:before{content:'\f005'}
-.icon-backupwizard:before{content:'\f05f'}
-.icon-backward:before{content:'\f183'}
-.icon-bag:before{content:'\f234'}
-.icon-baloon:before{content:'\f405'}
-.icon-ban-circle:before{content:'\f313'}
-.icon-banana:before{content:'\f3f4'}
-.icon-bandwidth:before{content:'\f006'}
-.icon-bank:before{content:'\f262'}
-.icon-barchart:before{content:'\f02f'}
-.icon-barchartalt:before{content:'\f07d'}
-.icon-barcode:before{content:'\f276'}
-.icon-basecamp:before{content:'\f160'}
-.icon-basketball:before{content:'\f2e9'}
-.icon-bat:before{content:'\f3d3'}
-.icon-batman:before{content:'\f348'}
-.icon-batteryaltcharging:before{content:'\f104'}
-.icon-batteryaltfull:before{content:'\f101'}
-.icon-batteryaltsixty:before{content:'\f102'}
-.icon-batteryaltthird:before{content:'\f103'}
-.icon-batterycharged:before{content:'\f0f4'}
-.icon-batterycharging:before{content:'\f0f3'}
-.icon-batteryeighty:before{content:'\f0f9'}
-.icon-batteryempty:before{content:'\f0f5'}
-.icon-batteryforty:before{content:'\f0f7'}
-.icon-batteryfull:before{content:'\f0fa'}
-.icon-batterysixty:before{content:'\f0f8'}
-.icon-batterytwenty:before{content:'\f0f6'}
-.icon-bed:before{content:'\f2b9'}
-.icon-beer:before{content:'\f244'}
-.icon-bell:before{content:'\2407'}
-.icon-bigger:before{content:'\f30a'}
-.icon-bill:before{content:'\f278'}
-.icon-binary:before{content:'\f087'}
-.icon-binoculars-searchalt:before{content:'\f2a0'}
-.icon-birdhouse:before{content:'\f390'}
-.icon-birthday:before{content:'\f36b'}
-.icon-bishop:before{content:'\f2f9'}
-.icon-blackberry:before{content:'\f421'}
-.icon-blankstare:before{content:'\f13e'}
-.icon-blogger-blog:before{content:'\f167'}
-.icon-bluetooth:before{content:'\f12b'}
-.icon-bluetoothconnected:before{content:'\f386'}
-.icon-boardgame:before{content:'\f2d9'}
-.icon-boat:before{content:'\f21a'}
-.icon-bold:before{content:'\f1f4'}
-.icon-bomb:before{content:'\f2dc'}
-.icon-bone:before{content:'\f35f'}
-.icon-book:before{content:'\f1ba'}
-.icon-bookmark:before{content:'\f143'}
-.icon-boombox:before{content:'\f195'}
-.icon-bottle:before{content:'\f361'}
-.icon-bow:before{content:'\f2ee'}
-.icon-bowling:before{content:'\f2f3'}
-.icon-bowlingpins:before{content:'\f3d2'}
-.icon-bowtie:before{content:'\f37f'}
-.icon-boxtrapper-mousetrap:before{content:'\f046'}
-.icon-braces:before{content:'\f0b4'}
-.icon-braille0:before{content:'\f44b'}
-.icon-braille1:before{content:'\f44c'}
-.icon-braille2:before{content:'\f44d'}
-.icon-braille3:before{content:'\f44e'}
-.icon-braille4:before{content:'\f44f'}
-.icon-braille5:before{content:'\f450'}
-.icon-braille6:before{content:'\f451'}
-.icon-braille7:before{content:'\f452'}
-.icon-braille8:before{content:'\f453'}
-.icon-braille9:before{content:'\f454'}
-.icon-braillea:before{content:'\f431'}
-.icon-brailleb:before{content:'\f432'}
-.icon-braillec:before{content:'\f433'}
-.icon-brailled:before{content:'\f434'}
-.icon-braillee:before{content:'\f435'}
-.icon-braillef:before{content:'\f436'}
-.icon-brailleg:before{content:'\f437'}
-.icon-brailleh:before{content:'\f438'}
-.icon-braillei:before{content:'\f439'}
-.icon-braillej:before{content:'\f43a'}
-.icon-braillek:before{content:'\f43b'}
-.icon-braillel:before{content:'\f43c'}
-.icon-braillem:before{content:'\f43d'}
-.icon-braillen:before{content:'\f43e'}
-.icon-brailleo:before{content:'\f43f'}
-.icon-braillep:before{content:'\f440'}
-.icon-brailleq:before{content:'\f441'}
-.icon-brailler:before{content:'\f442'}
-.icon-brailles:before{content:'\f443'}
-.icon-braillespace:before{content:'\f455'}
-.icon-braillet:before{content:'\f444'}
-.icon-brailleu:before{content:'\f445'}
-.icon-braillev:before{content:'\f446'}
-.icon-braillew:before{content:'\f447'}
-.icon-braillex:before{content:'\f448'}
-.icon-brailley:before{content:'\f449'}
-.icon-braillez:before{content:'\f44a'}
-.icon-brain:before{content:'\f3e3'}
-.icon-bread:before{content:'\f42f'}
-.icon-breakable:before{content:'\f41c'}
-.icon-briefcase:before{content:'\f25e'}
-.icon-briefcasethree:before{content:'\f25f'}
-.icon-briefcasetwo:before{content:'\f0a2'}
-.icon-brightness:before{content:'\f10a'}
-.icon-brightnessfull:before{content:'\f10b'}
-.icon-brightnesshalf:before{content:'\f10c'}
-.icon-broom:before{content:'\f40a'}
-.icon-browser:before{content:'\f159'}
-.icon-brush:before{content:'\f1b8'}
-.icon-bucket:before{content:'\f1b5'}
-.icon-bug:before{content:'\f0a7'}
-.icon-bullhorn:before{content:'\f287'}
-.icon-bus:before{content:'\f241'}
-.icon-businesscardalt:before{content:'\f137'}
-.icon-buttona:before{content:'\f2bf'}
-.icon-buttonb:before{content:'\f2c0'}
-.icon-buttonx:before{content:'\f2c1'}
-.icon-buttony:before{content:'\f2c2'}
-.icon-cactus-desert:before{content:'\f22c'}
-.icon-calculator:before{content:'\f258'}
-.icon-calculatoralt:before{content:'\f265'}
-.icon-calendar:before{content:'\f20f'}
-.icon-calendaralt-cronjobs:before{content:'\f0a1'}
-.icon-camera:before{content:'\f19b'}
-.icon-candle:before{content:'\f29a'}
-.icon-candy:before{content:'\f42d'}
-.icon-candycane:before{content:'\f37d'}
-.icon-cannon:before{content:'\f401'}
-.icon-canvas:before{content:'\f1c8'}
-.icon-canvasrulers:before{content:'\f205'}
-.icon-capacitator:before{content:'\f3e8'}
-.icon-capslock:before{content:'\21ea'}
-.icon-captainamerica:before{content:'\f341'}
-.icon-carrot:before{content:'\f3f2'}
-.icon-cashregister:before{content:'\f26e'}
-.icon-cassette:before{content:'\f377'}
-.icon-cd-dvd:before{content:'\f0cd'}
-.icon-certificate:before{content:'\f277'}
-.icon-certificatealt:before{content:'\f058'}
-.icon-certificatethree:before{content:'\f059'}
-.icon-cgi:before{content:'\f086'}
-.icon-cgicenter:before{content:'\f079'}
-.icon-chair:before{content:'\2441'}
-.icon-chat:before{content:'\f162'}
-.icon-check:before{content:'\f310'}
-.icon-checkboxalt:before{content:'\f311'}
-.icon-checkin:before{content:'\f223'}
-.icon-checkinalt:before{content:'\f227'}
-.icon-chef:before{content:'\f3ce'}
-.icon-cherry:before{content:'\f35d'}
-.icon-chevron-down:before{content:'\f48b'}
-.icon-chevron-left:before{content:'\f489'}
-.icon-chevron-right:before{content:'\f488'}
-.icon-chevron-up:before{content:'\f48a'}
-.icon-chevrons:before{content:'\f0b5'}
-.icon-chicken:before{content:'\f359'}
-.icon-chocolate:before{content:'\f367'}
-.icon-christiancross:before{content:'\f40f'}
-.icon-christmastree:before{content:'\f37b'}
-.icon-chrome:before{content:'\f14e'}
-.icon-cigarette:before{content:'\f229'}
-.icon-circle-arrow-down:before{content:'\f475'}
-.icon-circle-arrow-left:before{content:'\f472'}
-.icon-circle-arrow-right:before{content:'\f473'}
-.icon-circle-arrow-up:before{content:'\f474'}
-.icon-circleadd:before{content:'\f0d1'}
-.icon-circledelete:before{content:'\f0d2'}
-.icon-circledown:before{content:'\f3c7'}
-.icon-circleleft:before{content:'\f3c6'}
-.icon-circleright:before{content:'\f3c9'}
-.icon-circleselect:before{content:'\f0d3'}
-.icon-circleselection:before{content:'\f1b1'}
-.icon-circleup:before{content:'\f3c8'}
-.icon-clearformatting:before{content:'\f1e7'}
-.icon-clipboard-paste:before{content:'\f0cb'}
-.icon-clockalt-timealt:before{content:'\f22b'}
-.icon-closetab:before{content:'\f170'}
-.icon-closewindow:before{content:'\f16e'}
-.icon-cloud:before{content:'\f0b9'}
-.icon-clouddownload:before{content:'\f0bb'}
-.icon-cloudhosting:before{content:'\f007'}
-.icon-cloudsync:before{content:'\f0bc'}
-.icon-cloudupload:before{content:'\f0ba'}
-.icon-clubs:before{content:'\f2f6'}
-.icon-cmd:before{content:'\f33a'}
-.icon-cms:before{content:'\f036'}
-.icon-cmsmadesimple:before{content:'\f0b0'}
-.icon-codeigniter:before{content:'\f077'}
-.icon-coffee:before{content:'\f235'}
-.icon-coffeebean:before{content:'\f366'}
-.icon-cog:before{content:'\f00f'}
-.icon-colocation:before{content:'\f024'}
-.icon-colocationalt:before{content:'\f023'}
-.icon-colors:before{content:'\f1e6'}
-.icon-comment:before{content:'\f12c'}
-.icon-commentout:before{content:'\f080'}
-.icon-commentround:before{content:'\f155'}
-.icon-commentroundempty:before{content:'\f156'}
-.icon-commentroundtyping:before{content:'\f157'}
-.icon-commentroundtypingempty:before{content:'\f158'}
-.icon-commenttyping:before{content:'\f12d'}
-.icon-compass:before{content:'\263c'}
-.icon-concretefive:before{content:'\f0af'}
-.icon-contact-businesscard:before{content:'\f040'}
-.icon-controllernes:before{content:'\f2d2'}
-.icon-controllerps:before{content:'\f2d1'}
-.icon-controllersnes:before{content:'\f2d3'}
-.icon-controlpanel:before{content:'\f008'}
-.icon-controlpanelalt:before{content:'\f009'}
-.icon-cooling:before{content:'\f00a'}
-.icon-coppermine:before{content:'\f0a4'}
-.icon-copy:before{content:'\f0c9'}
-.icon-copyright:before{content:'\00a9'}
-.icon-coupon:before{content:'\f254'}
-.icon-cpanel:before{content:'\f072'}
-.icon-cplusplus:before{content:'\f0b1'}
-.icon-cpu-processor:before{content:'\f002'}
-.icon-cpualt-processoralt:before{content:'\f003'}
-.icon-crayon:before{content:'\f383'}
-.icon-createfile:before{content:'\f0c6'}
-.icon-createfolder:before{content:'\f0da'}
-.icon-creativecommons:before{content:'\f1fc'}
-.icon-creditcard:before{content:'\f279'}
-.icon-cricket:before{content:'\f418'}
-.icon-croisant:before{content:'\f29f'}
-.icon-crop:before{content:'\f1af'}
-.icon-crown:before{content:'\f28f'}
-.icon-csharp:before{content:'\f0b2'}
-.icon-cssthree:before{content:'\f06a'}
-.icon-cup-coffeealt:before{content:'\f24b'}
-.icon-cupcake:before{content:'\f35b'}
-.icon-curling:before{content:'\f3d7'}
-.icon-cursor:before{content:'\f0dc'}
-.icon-cut-scissors:before{content:'\f0ca'}
-.icon-dagger:before{content:'\2020'}
-.icon-danger:before{content:'\f415'}
-.icon-dart:before{content:'\f3d4'}
-.icon-darthvader:before{content:'\f34a'}
-.icon-database:before{content:'\f00b'}
-.icon-databaseadd:before{content:'\f00c'}
-.icon-databasedelete:before{content:'\f00d'}
-.icon-davidstar:before{content:'\f40e'}
-.icon-dcsource:before{content:'\f3e9'}
-.icon-dedicatedserver:before{content:'\f00e'}
-.icon-deletefile:before{content:'\f0c7'}
-.icon-deletefolder:before{content:'\f0db'}
-.icon-delicious:before{content:'\f152'}
-.icon-designcontest:before{content:'\f351'}
-.icon-desklamp:before{content:'\f412'}
-.icon-dialpad:before{content:'\f399'}
-.icon-diamond:before{content:'\2666'}
-.icon-diamonds:before{content:'\f2f7'}
-.icon-die-dice:before{content:'\f2d8'}
-.icon-diefive:before{content:'\f3fb'}
-.icon-diefour:before{content:'\f3fa'}
-.icon-dieone:before{content:'\f3f7'}
-.icon-diesix:before{content:'\f3fc'}
-.icon-diethree:before{content:'\f3f9'}
-.icon-dietwo:before{content:'\f3f8'}
-.icon-diode:before{content:'\f3e7'}
-.icon-director:before{content:'\f2ae'}
-.icon-diskspace:before{content:'\f096'}
-.icon-distributehorizontalcenters:before{content:'\f1dc'}
-.icon-distributeverticalcenters:before{content:'\f1db'}
-.icon-divide:before{content:'\00f7'}
-.icon-dna:before{content:'\f409'}
-.icon-dnszone:before{content:'\f07f'}
-.icon-document:before{content:'\f0c2'}
-.icon-doghouse:before{content:'\f38f'}
-.icon-dollar:before{content:'\24'}
-.icon-dollaralt:before{content:'\f259'}
-.icon-dolphinsoftware:before{content:'\f064'}
-.icon-domain:before{content:'\f01d'}
-.icon-domainaddon:before{content:'\f053'}
-.icon-domino:before{content:'\f3d5'}
-.icon-donut:before{content:'\f3ca'}
-.icon-downleft:before{content:'\f2ff'}
-.icon-download:before{content:'\f47b'}
-.icon-download-alt:before{content:'\f11a'}
-.icon-downright:before{content:'\f300'}
-.icon-draft:before{content:'\f172'}
-.icon-dreamweaver:before{content:'\f1d0'}
-.icon-dribbble:before{content:'\f14c'}
-.icon-dropmenu:before{content:'\f0a5'}
-.icon-drupal:before{content:'\f075'}
-.icon-drwho:before{content:'\f3c0'}
-.icon-edit:before{content:'\f47c'}
-.icon-editalt:before{content:'\f0f2'}
-.icon-egg:before{content:'\f407'}
-.icon-eightball:before{content:'\f36e'}
-.icon-eject:before{content:'\f199'}
-.icon-elipse:before{content:'\f1bc'}
-.icon-emailalt:before{content:'\f136'}
-.icon-emailexport:before{content:'\f176'}
-.icon-emailforward:before{content:'\f175'}
-.icon-emailforwarders:before{content:'\f049'}
-.icon-emailimport:before{content:'\f177'}
-.icon-emailrefresh:before{content:'\f174'}
-.icon-emailtrace:before{content:'\f091'}
-.icon-emergency:before{content:'\f246'}
-.icon-emptycart:before{content:'\f395'}
-.icon-enter:before{content:'\f323'}
-.icon-envelope:before{content:'\f028'}
-.icon-equalizer:before{content:'\f18e'}
-.icon-equalizeralt:before{content:'\f18f'}
-.icon-equals:before{content:'\f30c'}
-.icon-eraser:before{content:'\f1f1'}
-.icon-erroralt:before{content:'\f05a'}
-.icon-euro:before{content:'\20ac'}
-.icon-euroalt:before{content:'\f25a'}
-.icon-evernote:before{content:'\f17c'}
-.icon-exchange-currency:before{content:'\f26b'}
-.icon-exclamation-sign:before{content:'\f04a'}
-.icon-excludeshape:before{content:'\f200'}
-.icon-exit:before{content:'\f324'}
-.icon-explorerwindow:before{content:'\f0d9'}
-.icon-exportfile:before{content:'\f32f'}
-.icon-exposure:before{content:'\f1de'}
-.icon-extinguisher:before{content:'\f2b7'}
-.icon-eye-close:before{content:'\f481'}
-.icon-eye-open:before{content:'\f2b5'}
-.icon-eye-view:before{content:'\f280'}
-.icon-eyedropper:before{content:'\f1ad'}
-.icon-facebook:before{content:'\f140'}
-.icon-facebookalt:before{content:'\f14b'}
-.icon-facetime-video:before{content:'\f19c'}
-.icon-factory:before{content:'\f27a'}
-.icon-fantastico:before{content:'\f0ae'}
-.icon-faq:before{content:'\f099'}
-.icon-fast-backward:before{content:'\f47e'}
-.icon-fast-forward:before{content:'\f47f'}
-.icon-fastdown:before{content:'\f31d'}
-.icon-fastleft:before{content:'\f31a'}
-.icon-fastright:before{content:'\f31b'}
-.icon-fastup:before{content:'\f31c'}
-.icon-favoritefile:before{content:'\f381'}
-.icon-favoritefolder:before{content:'\f382'}
-.icon-featheralt-write:before{content:'\f1c5'}
-.icon-fedora:before{content:'\f3f1'}
-.icon-fence:before{content:'\f2af'}
-.icon-file:before{content:'\f0d6'}
-.icon-film:before{content:'\f19d'}
-.icon-filmstrip:before{content:'\f3ed'}
-.icon-filter:before{content:'\f05c'}
-.icon-finder:before{content:'\f398'}
-.icon-fire:before{content:'\f27f'}
-.icon-firefox:before{content:'\f420'}
-.icon-firewall:before{content:'\f021'}
-.icon-firewire:before{content:'\f0fc'}
-.icon-firstaid:before{content:'\f2ba'}
-.icon-fish:before{content:'\f35a'}
-.icon-fishbone:before{content:'\f42b'}
-.icon-flag:before{content:'\f487'}
-.icon-flagalt:before{content:'\f232'}
-.icon-flagtriangle:before{content:'\f20b'}
-.icon-flash:before{content:'\f1cf'}
-.icon-flashlight:before{content:'\f299'}
-.icon-flashplayer:before{content:'\f070'}
-.icon-flaskfull:before{content:'\f27e'}
-.icon-flickr:before{content:'\f146'}
-.icon-flower:before{content:'\f2a5'}
-.icon-flowernew:before{content:'\f3a8'}
-.icon-folder-close:before{content:'\f094'}
-.icon-folder-open:before{content:'\f483'}
-.icon-foldertree:before{content:'\f0f0'}
-.icon-font:before{content:'\f1ae'}
-.icon-foodtray:before{content:'\f3d0'}
-.icon-football-soccer:before{content:'\f2eb'}
-.icon-forbiddenalt:before{content:'\f314'}
-.icon-forest-tree:before{content:'\f217'}
-.icon-forestalt-treealt:before{content:'\f21c'}
-.icon-fork:before{content:'\22d4'}
-.icon-forklift:before{content:'\f29b'}
-.icon-form:before{content:'\f08c'}
-.icon-forrst:before{content:'\f14d'}
-.icon-fort:before{content:'\f400'}
-.icon-forward:before{content:'\f182'}
-.icon-fourohfour:before{content:'\f09d'}
-.icon-foursquare:before{content:'\f42a'}
-.icon-freeway:before{content:'\f24a'}
-.icon-fridge:before{content:'\f40d'}
-.icon-fries:before{content:'\f36a'}
-.icon-ftp:before{content:'\f029'}
-.icon-ftpaccounts:before{content:'\f07b'}
-.icon-ftpsession:before{content:'\f07c'}
-.icon-fullscreen:before{content:'\f485'}
-.icon-gameboy:before{content:'\f403'}
-.icon-gamecursor:before{content:'\f2d0'}
-.icon-gasstation:before{content:'\f216'}
-.icon-gearfour:before{content:'\f3a7'}
-.icon-ghost:before{content:'\f2da'}
-.icon-gift:before{content:'\f260'}
-.icon-github:before{content:'\f081'}
-.icon-glass:before{content:'\f236'}
-.icon-glasses:before{content:'\f295'}
-.icon-glassesalt:before{content:'\f39d'}
-.icon-globe:before{content:'\f01b'}
-.icon-globealt:before{content:'\f36c'}
-.icon-glue:before{content:'\f36d'}
-.icon-gmail:before{content:'\f150'}
-.icon-golf:before{content:'\f2f1'}
-.icon-googledrive:before{content:'\f163'}
-.icon-googleplus:before{content:'\f165'}
-.icon-googlewallet:before{content:'\f270'}
-.icon-gpsoff-gps:before{content:'\f21e'}
-.icon-gpson:before{content:'\f21f'}
-.icon-gpu-graphicscard:before{content:'\f108'}
-.icon-gradient:before{content:'\2207'}
-.icon-grails:before{content:'\f085'}
-.icon-greenlantern:before{content:'\f340'}
-.icon-greenlightbulb:before{content:'\f406'}
-.icon-grooveshark:before{content:'\f3a2'}
-.icon-groups-friends:before{content:'\f134'}
-.icon-guitar:before{content:'\f19a'}
-.icon-halflife:before{content:'\f3ba'}
-.icon-halo:before{content:'\f3bb'}
-.icon-hamburger:before{content:'\f2b3'}
-.icon-hammer:before{content:'\f291'}
-.icon-hand-down:before{content:'\f387'}
-.icon-hand-left:before{content:'\f389'}
-.icon-hand-right:before{content:'\f388'}
-.icon-hand-up:before{content:'\f0dd'}
-.icon-handcuffs:before{content:'\f393'}
-.icon-handdrag:before{content:'\f0de'}
-.icon-handtwofingers:before{content:'\f0df'}
-.icon-hanger:before{content:'\f2ab'}
-.icon-happy:before{content:'\f13c'}
-.icon-harrypotter:before{content:'\f38b'}
-.icon-hdd:before{content:'\f02a'}
-.icon-hdtv:before{content:'\f1a0'}
-.icon-headphones:before{content:'\f180'}
-.icon-headphonesalt:before{content:'\f1a3'}
-.icon-heart:before{content:'\f131'}
-.icon-heartempty-love:before{content:'\f132'}
-.icon-hearts:before{content:'\f2f4'}
-.icon-helicopter:before{content:'\f3e4'}
-.icon-hexagon-polygon:before{content:'\f1be'}
-.icon-hockey:before{content:'\f3d9'}
-.icon-home:before{content:'\21b8'}
-.icon-homealt:before{content:'\f02b'}
-.icon-hospital:before{content:'\f247'}
-.icon-hotdog:before{content:'\f3cc'}
-.icon-hotlinkprotection:before{content:'\f050'}
-.icon-hourglassalt:before{content:'\f122'}
-.icon-html:before{content:'\f068'}
-.icon-htmlfive:before{content:'\f069'}
-.icon-hydrant:before{content:'\f3ff'}
-.icon-icecream:before{content:'\f2a4'}
-.icon-icecreamalt:before{content:'\f289'}
-.icon-illustrator:before{content:'\f1ce'}
-.icon-imac:before{content:'\f0fb'}
-.icon-images-gallery:before{content:'\f09f'}
-.icon-importcontacts:before{content:'\f092'}
-.icon-importfile:before{content:'\f32e'}
-.icon-inbox:before{content:'\f17a'}
-.icon-inboxalt:before{content:'\f178'}
-.icon-incomingcall:before{content:'\f15d'}
-.icon-indent-left:before{content:'\f1f2'}
-.icon-indent-right:before{content:'\f1f3'}
-.icon-indexmanager:before{content:'\f09e'}
-.icon-infinity:before{content:'\221e'}
-.icon-info-sign:before{content:'\f315'}
-.icon-infographic:before{content:'\f336'}
-.icon-ink:before{content:'\f3f6'}
-.icon-inkpen:before{content:'\f1ac'}
-.icon-insertbarchart:before{content:'\f1e5'}
-.icon-insertpicture:before{content:'\f1e0'}
-.icon-insertpicturecenter:before{content:'\f1e3'}
-.icon-insertpictureleft:before{content:'\f1e1'}
-.icon-insertpictureright:before{content:'\f1e2'}
-.icon-insertpiechart:before{content:'\f1e4'}
-.icon-instagram:before{content:'\f14a'}
-.icon-install:before{content:'\f128'}
-.icon-intel:before{content:'\f01f'}
-.icon-intersection:before{content:'\2229'}
-.icon-intersectshape:before{content:'\f1ff'}
-.icon-invert:before{content:'\f1df'}
-.icon-invoice:before{content:'\f3e5'}
-.icon-ipcontrol:before{content:'\f08b'}
-.icon-iphone:before{content:'\f0e6'}
-.icon-ipod:before{content:'\f190'}
-.icon-ironman:before{content:'\f349'}
-.icon-islam:before{content:'\f410'}
-.icon-island:before{content:'\f392'}
-.icon-italic:before{content:'\f1f5'}
-.icon-jar:before{content:'\f2b6'}
-.icon-jason:before{content:'\f38c'}
-.icon-java:before{content:'\f083'}
-.icon-joomla:before{content:'\f073'}
-.icon-joystickarcade:before{content:'\f2d4'}
-.icon-joystickatari:before{content:'\f2d5'}
-.icon-jquery:before{content:'\f06b'}
-.icon-jqueryui:before{content:'\f06c'}
-.icon-kerning:before{content:'\f1e9'}
-.icon-key:before{content:'\f093'}
-.icon-keyboard:before{content:'\f119'}
-.icon-keyboardalt:before{content:'\f105'}
-.icon-keyboarddelete:before{content:'\f3a6'}
-.icon-kidney:before{content:'\f3e0'}
-.icon-king:before{content:'\f2fc'}
-.icon-knife:before{content:'\f214'}
-.icon-knight:before{content:'\f2fb'}
-.icon-knob:before{content:'\f376'}
-.icon-lab-flask:before{content:'\f27d'}
-.icon-lamp:before{content:'\f2b1'}
-.icon-lan:before{content:'\f0ee'}
-.icon-language:before{content:'\f042'}
-.icon-laptop:before{content:'\f0d8'}
-.icon-lasso:before{content:'\f396'}
-.icon-lastfm:before{content:'\f3a3'}
-.icon-laugh:before{content:'\f13f'}
-.icon-law:before{content:'\f263'}
-.icon-layers:before{content:'\f1ca'}
-.icon-layersalt:before{content:'\f1cb'}
-.icon-leaf:before{content:'\f039'}
-.icon-leechprotect:before{content:'\f07e'}
-.icon-legacyfilemanager:before{content:'\f095'}
-.icon-lego:before{content:'\f370'}
-.icon-lifeempty:before{content:'\f2e1'}
-.icon-lifefull:before{content:'\f2e3'}
-.icon-lifehacker:before{content:'\f380'}
-.icon-lifehalf:before{content:'\f2e2'}
-.icon-lifepreserver:before{content:'\f015'}
-.icon-lightbulb-idea:before{content:'\f338'}
-.icon-lighthouse:before{content:'\f3e6'}
-.icon-lightning:before{content:'\f231'}
-.icon-lightningalt:before{content:'\f2a8'}
-.icon-line:before{content:'\f1bf'}
-.icon-lineheight:before{content:'\f1c0'}
-.icon-link:before{content:'\f022'}
-.icon-linkalt:before{content:'\f333'}
-.icon-linkedin:before{content:'\f166'}
-.icon-linux:before{content:'\f01a'}
-.icon-list:before{content:'\f111'}
-.icon-list-alt:before{content:'\f480'}
-.icon-liver:before{content:'\f3e2'}
-.icon-loading-hourglass:before{content:'\f123'}
-.icon-loadingalt:before{content:'\f339'}
-.icon-lock:before{content:'\f0be'}
-.icon-lockalt-keyhole:before{content:'\f0eb'}
-.icon-lollypop:before{content:'\f3ee'}
-.icon-lungs:before{content:'\f3df'}
-.icon-macpro:before{content:'\f3a5'}
-.icon-macro-plant:before{content:'\f1c6'}
-.icon-magazine:before{content:'\f1ec'}
-.icon-magento:before{content:'\f06e'}
-.icon-magnet:before{content:'\f281'}
-.icon-mailbox:before{content:'\f044'}
-.icon-mailinglists:before{content:'\f090'}
-.icon-man-male:before{content:'\f2a1'}
-.icon-managedhosting:before{content:'\f038'}
-.icon-map:before{content:'\f209'}
-.icon-map-marker:before{content:'\f220'}
-.icon-marker:before{content:'\f204'}
-.icon-marvin:before{content:'\f3dd'}
-.icon-mastercard:before{content:'\f266'}
-.icon-maximize:before{content:'\f30f'}
-.icon-medal:before{content:'\f2e5'}
-.icon-medalbronze:before{content:'\f2e8'}
-.icon-medalgold:before{content:'\f2e6'}
-.icon-medalsilver:before{content:'\f2e7'}
-.icon-mediarepeat:before{content:'\f187'}
-.icon-men:before{content:'\f24c'}
-.icon-menu:before{content:'\f127'}
-.icon-merge:before{content:'\f334'}
-.icon-mergecells:before{content:'\f327'}
-.icon-mergeshapes:before{content:'\f201'}
-.icon-metro-subway:before{content:'\f24f'}
-.icon-metronome:before{content:'\f374'}
-.icon-mickeymouse:before{content:'\f37a'}
-.icon-microphone:before{content:'\f191'}
-.icon-microscope:before{content:'\f283'}
-.icon-microsd:before{content:'\f107'}
-.icon-microwave:before{content:'\f42e'}
-.icon-mimetype:before{content:'\f057'}
-.icon-minimize:before{content:'\f30e'}
-.icon-minus:before{content:'\2212'}
-.icon-minus-sign:before{content:'\f477'}
-.icon-missedcall:before{content:'\f15c'}
-.icon-mobile:before{content:'\f0e8'}
-.icon-moleskine:before{content:'\f1f0'}
-.icon-money-cash:before{content:'\f27b'}
-.icon-moneybag:before{content:'\f271'}
-.icon-monitor:before{content:'\f0d5'}
-.icon-monstersinc:before{content:'\f3bd'}
-.icon-moon-night:before{content:'\f207'}
-.icon-mouse:before{content:'\f0d4'}
-.icon-mousealt:before{content:'\f126'}
-.icon-move:before{content:'\f322'}
-.icon-movieclapper:before{content:'\f193'}
-.icon-moviereel:before{content:'\f17f'}
-.icon-muffin:before{content:'\f363'}
-.icon-mug:before{content:'\f24e'}
-.icon-mushroom:before{content:'\f35e'}
-.icon-music:before{content:'\f181'}
-.icon-musicalt:before{content:'\f18d'}
-.icon-mutealt:before{content:'\f0e5'}
-.icon-mxentry:before{content:'\f07a'}
-.icon-mybb:before{content:'\f065'}
-.icon-myspace:before{content:'\f153'}
-.icon-mysql-dolphin:before{content:'\f076'}
-.icon-nail:before{content:'\f428'}
-.icon-navigation:before{content:'\f23a'}
-.icon-network:before{content:'\f0a6'}
-.icon-networksignal:before{content:'\f3a9'}
-.icon-news:before{content:'\f256'}
-.icon-newtab:before{content:'\f16f'}
-.icon-newwindow:before{content:'\f16d'}
-.icon-next:before{content:'\f18a'}
-.icon-nexus:before{content:'\f0e7'}
-.icon-nintendods:before{content:'\f404'}
-.icon-nodejs:before{content:'\f084'}
-.icon-notes:before{content:'\f0d7'}
-.icon-notificationbottom:before{content:'\f144'}
-.icon-notificationtop:before{content:'\f145'}
-.icon-nut:before{content:'\f427'}
-.icon-off:before{content:'\f11d'}
-.icon-office-building:before{content:'\f245'}
-.icon-officechair:before{content:'\f26d'}
-.icon-ok:before{content:'\2713'}
-.icon-ok-circle:before{content:'\f471'}
-.icon-ok-sign:before{content:'\f479'}
-.icon-oneup:before{content:'\f3b7'}
-.icon-oneupalt:before{content:'\f3b6'}
-.icon-opencart:before{content:'\f060'}
-.icon-opennewwindow:before{content:'\f332'}
-.icon-orange:before{content:'\f29e'}
-.icon-outbox:before{content:'\f179'}
-.icon-outgoingcall:before{content:'\f15e'}
-.icon-oxwall:before{content:'\f06d'}
-.icon-pacman:before{content:'\f2db'}
-.icon-pageback:before{content:'\f31e'}
-.icon-pagebreak:before{content:'\f1cc'}
-.icon-pageforward:before{content:'\f31f'}
-.icon-pagesetup:before{content:'\f331'}
-.icon-paintbrush:before{content:'\f1e8'}
-.icon-paintroll:before{content:'\f1fa'}
-.icon-palette-painting:before{content:'\f1b9'}
-.icon-paperclip:before{content:'\f284'}
-.icon-paperclipalt:before{content:'\f285'}
-.icon-paperclipvertical:before{content:'\f286'}
-.icon-paperplane:before{content:'\f296'}
-.icon-parentheses:before{content:'\f3c4'}
-.icon-parkeddomain:before{content:'\f055'}
-.icon-password:before{content:'\f03e'}
-.icon-passwordalt:before{content:'\f03f'}
-.icon-pasta:before{content:'\f408'}
-.icon-patch:before{content:'\f2a3'}
-.icon-path:before{content:'\f169'}
-.icon-pause:before{content:'\f186'}
-.icon-paw-pet:before{content:'\f29d'}
-.icon-pawn:before{content:'\f2f8'}
-.icon-paypal:before{content:'\f267'}
-.icon-peace:before{content:'\f2a7'}
-.icon-pen:before{content:'\f1ee'}
-.icon-pencil:before{content:'\f1b7'}
-.icon-pepperoni:before{content:'\f364'}
-.icon-percent:before{content:'\25'}
-.icon-perl-camel:before{content:'\f0b6'}
-.icon-perlalt:before{content:'\f0b7'}
-.icon-phone-call:before{content:'\f14f'}
-.icon-phonealt:before{content:'\f15b'}
-.icon-phonebook:before{content:'\f149'}
-.icon-phonebookalt:before{content:'\f135'}
-.icon-phonemic:before{content:'\f391'}
-.icon-phoneold:before{content:'\f148'}
-.icon-photoshop:before{content:'\f1cd'}
-.icon-php:before{content:'\f09c'}
-.icon-phpbb:before{content:'\f063'}
-.icon-phppear:before{content:'\f09b'}
-.icon-piano:before{content:'\f19e'}
-.icon-picture:before{content:'\22b7'}
-.icon-pictureframe:before{content:'\f41e'}
-.icon-piggybank:before{content:'\f257'}
-.icon-pigpena:before{content:'\f456'}
-.icon-pigpenb:before{content:'\f457'}
-.icon-pigpenc:before{content:'\f458'}
-.icon-pigpend:before{content:'\f459'}
-.icon-pigpene:before{content:'\f45a'}
-.icon-pigpenf:before{content:'\f45b'}
-.icon-pigpeng:before{content:'\f45c'}
-.icon-pigpenh:before{content:'\f45d'}
-.icon-pigpeni:before{content:'\f45e'}
-.icon-pigpenj:before{content:'\f45f'}
-.icon-pigpenk:before{content:'\f460'}
-.icon-pigpenl:before{content:'\f461'}
-.icon-pigpenm:before{content:'\f462'}
-.icon-pigpenn:before{content:'\f463'}
-.icon-pigpeno:before{content:'\f464'}
-.icon-pigpenp:before{content:'\f465'}
-.icon-pigpenq:before{content:'\f466'}
-.icon-pigpenr:before{content:'\f467'}
-.icon-pigpens:before{content:'\f468'}
-.icon-pigpent:before{content:'\f469'}
-.icon-pigpenu:before{content:'\f46a'}
-.icon-pigpenv:before{content:'\f46b'}
-.icon-pigpenw:before{content:'\f46c'}
-.icon-pigpenx:before{content:'\f46d'}
-.icon-pigpeny:before{content:'\f46e'}
-.icon-pigpenz:before{content:'\f46f'}
-.icon-pilcrow:before{content:'\00b6'}
-.icon-pill-antivirusalt:before{content:'\f0aa'}
-.icon-pin:before{content:'\f20a'}
-.icon-pipe:before{content:'\01c0'}
-.icon-piwigo:before{content:'\f0ad'}
-.icon-pizza:before{content:'\f35c'}
-.icon-placeadd:before{content:'\f221'}
-.icon-placealt:before{content:'\f224'}
-.icon-placealtadd:before{content:'\f225'}
-.icon-placealtdelete:before{content:'\f226'}
-.icon-placedelete:before{content:'\f222'}
-.icon-placeios:before{content:'\f20c'}
-.icon-plane:before{content:'\f23e'}
-.icon-plaque:before{content:'\f2b8'}
-.icon-play:before{content:'\f184'}
-.icon-play-circle:before{content:'\f17e'}
-.icon-playstore:before{content:'\f255'}
-.icon-playvideo:before{content:'\f03d'}
-.icon-plug:before{content:'\f0ea'}
-.icon-pluginalt:before{content:'\f098'}
-.icon-plus:before{content:'\002b'}
-.icon-plus-sign:before{content:'\f476'}
-.icon-pocket:before{content:'\f16b'}
-.icon-podcast:before{content:'\f1a2'}
-.icon-podium-winner:before{content:'\f2d6'}
-.icon-pokemon:before{content:'\f354'}
-.icon-police:before{content:'\f2aa'}
-.icon-polygonlasso:before{content:'\f397'}
-.icon-post:before{content:'\f12e'}
-.icon-postalt:before{content:'\f130'}
-.icon-pound:before{content:'\f25b'}
-.icon-poundalt:before{content:'\f25c'}
-.icon-powerjack:before{content:'\f0fd'}
-.icon-powerplug:before{content:'\f0ed'}
-.icon-powerplugeu:before{content:'\f28b'}
-.icon-powerplugus:before{content:'\f28c'}
-.icon-presentation:before{content:'\f0c4'}
-.icon-prestashop:before{content:'\f061'}
-.icon-pretzel:before{content:'\f3cf'}
-.icon-preview:before{content:'\f330'}
-.icon-previous:before{content:'\f18b'}
-.icon-print:before{content:'\f125'}
-.icon-protecteddirectory:before{content:'\f04d'}
-.icon-pscircle:before{content:'\f2bb'}
-.icon-pscursor:before{content:'\f2c3'}
-.icon-psdown:before{content:'\f2c6'}
-.icon-psleft:before{content:'\f2c7'}
-.icon-pslone:before{content:'\f2cc'}
-.icon-psltwo:before{content:'\f2cd'}
-.icon-psright:before{content:'\f2c5'}
-.icon-psrone:before{content:'\f2ce'}
-.icon-psrtwo:before{content:'\f2cf'}
-.icon-pssquare:before{content:'\f2bc'}
-.icon-pstriangle:before{content:'\f2bd'}
-.icon-psup:before{content:'\f2c4'}
-.icon-psx:before{content:'\f2be'}
-.icon-pull:before{content:'\f089'}
-.icon-punisher:before{content:'\f343'}
-.icon-push:before{content:'\f088'}
-.icon-puzzle-plugin:before{content:'\f0a0'}
-.icon-python:before{content:'\f071'}
-.icon-qrcode:before{content:'\f275'}
-.icon-quake:before{content:'\f355'}
-.icon-queen:before{content:'\f2fd'}
-.icon-query:before{content:'\f08a'}
-.icon-question-sign:before{content:'\f0a3'}
-.icon-quote:before{content:'\f12f'}
-.icon-quotedown:before{content:'\f329'}
-.icon-quoteup:before{content:'\f328'}
-.icon-raceflag:before{content:'\f38e'}
-.icon-racquet:before{content:'\f2f2'}
-.icon-radio:before{content:'\f1a1'}
-.icon-radioactive:before{content:'\f282'}
-.icon-radiobutton:before{content:'\f312'}
-.icon-railroad:before{content:'\f248'}
-.icon-rain:before{content:'\f22f'}
-.icon-ram:before{content:'\f02c'}
-.icon-random:before{content:'\f188'}
-.icon-rar:before{content:'\f117'}
-.icon-raspberry:before{content:'\f368'}
-.icon-raspberrypi:before{content:'\f369'}
-.icon-rawaccesslogs:before{content:'\f0c1'}
-.icon-razor:before{content:'\f416'}
-.icon-reademail:before{content:'\f173'}
-.icon-record:before{content:'\f189'}
-.icon-rectangle:before{content:'\25ad'}
-.icon-recycle:before{content:'\f297'}
-.icon-reddit:before{content:'\f154'}
-.icon-redirect:before{content:'\f054'}
-.icon-refresh:before{content:'\f078'}
-.icon-reliability:before{content:'\f016'}
-.icon-remote:before{content:'\f298'}
-.icon-remove:before{content:'\00d7'}
-.icon-remove-circle:before{content:'\f470'}
-.icon-remove-sign:before{content:'\f478'}
-.icon-removefriend:before{content:'\f3db'}
-.icon-repeat:before{content:'\f32b'}
-.icon-repeatone:before{content:'\f196'}
-.icon-resellerhosting:before{content:'\f03a'}
-.icon-residentevil:before{content:'\f350'}
-.icon-resistor:before{content:'\f3eb'}
-.icon-resize:before{content:'\f1ed'}
-.icon-resize-full:before{content:'\f325'}
-.icon-resize-horizontal:before{content:'\f318'}
-.icon-resize-small:before{content:'\f326'}
-.icon-resize-vertical:before{content:'\f319'}
-.icon-restart:before{content:'\f11f'}
-.icon-restaurantmenu:before{content:'\f362'}
-.icon-restore:before{content:'\f30d'}
-.icon-restricted:before{content:'\f0ab'}
-.icon-retweet:before{content:'\f486'}
-.icon-rim:before{content:'\f36f'}
-.icon-ring:before{content:'\02da'}
-.icon-road:before{content:'\f249'}
-.icon-roadsign-roadsignright:before{content:'\f21b'}
-.icon-roadsignleft:before{content:'\f240'}
-.icon-robocop:before{content:'\f357'}
-.icon-rocket-launch:before{content:'\f29c'}
-.icon-rook:before{content:'\f2fa'}
-.icon-root:before{content:'\f33c'}
-.icon-rorschach:before{content:'\f358'}
-.icon-rotateclockwise:before{content:'\f202'}
-.icon-rotatecounterclockwise:before{content:'\f203'}
-.icon-roundrectangle:before{content:'\f1bd'}
-.icon-route:before{content:'\f402'}
-.icon-router:before{content:'\f0e9'}
-.icon-rss:before{content:'\f17b'}
-.icon-rubberstamp:before{content:'\f274'}
-.icon-ruby:before{content:'\f067'}
-.icon-ruler:before{content:'\f1ef'}
-.icon-sad:before{content:'\f13d'}
-.icon-safetypin:before{content:'\f417'}
-.icon-satellite:before{content:'\f38a'}
-.icon-satellitedish-remotemysql:before{content:'\f0c0'}
-.icon-save-floppy:before{content:'\f0c8'}
-.icon-scales:before{content:'\f3fd'}
-.icon-science-atom:before{content:'\f2b0'}
-.icon-scope-scan:before{content:'\f212'}
-.icon-scopealt:before{content:'\f237'}
-.icon-screenshot:before{content:'\f109'}
-.icon-screw:before{content:'\f426'}
-.icon-screwdriver:before{content:'\f292'}
-.icon-screwdriveralt:before{content:'\f293'}
-.icon-script:before{content:'\f08d'}
-.icon-sd:before{content:'\f106'}
-.icon-search:before{content:'\f0c5'}
-.icon-searchdocument:before{content:'\f419'}
-.icon-searchfolder:before{content:'\f41a'}
-.icon-security-shield:before{content:'\f02d'}
-.icon-securityalt-shieldalt:before{content:'\f02e'}
-.icon-selection-rectangleselection:before{content:'\f1b0'}
-.icon-selectionadd:before{content:'\f1b2'}
-.icon-selectionintersect:before{content:'\f1b4'}
-.icon-selectionremove:before{content:'\f1b3'}
-.icon-seo:before{content:'\f030'}
-.icon-server:before{content:'\f026'}
-.icon-servers:before{content:'\f027'}
-.icon-settingsandroid:before{content:'\f309'}
-.icon-settingsfour-gearsalt:before{content:'\f306'}
-.icon-settingsthree-gears:before{content:'\f307'}
-.icon-settingstwo-gearalt:before{content:'\f308'}
-.icon-shades-sunglasses:before{content:'\f294'}
-.icon-shapes:before{content:'\f1dd'}
-.icon-share:before{content:'\f47d'}
-.icon-share-alt:before{content:'\f16c'}
-.icon-sharealt:before{content:'\f147'}
-.icon-sharedfile:before{content:'\f0ef'}
-.icon-sharedhosting:before{content:'\f037'}
-.icon-sharethree:before{content:'\f414'}
-.icon-sheriff:before{content:'\f2a9'}
-.icon-shipping:before{content:'\f23f'}
-.icon-shopping:before{content:'\f010'}
-.icon-shopping-cart:before{content:'\f035'}
-.icon-shoppingbag:before{content:'\f273'}
-.icon-shortcut:before{content:'\f043'}
-.icon-shovel:before{content:'\f290'}
-.icon-shredder:before{content:'\f27c'}
-.icon-shutdown:before{content:'\f11e'}
-.icon-sidebar:before{content:'\f124'}
-.icon-signal:before{content:'\f100'}
-.icon-sim:before{content:'\f0e1'}
-.icon-simalt:before{content:'\f121'}
-.icon-skrill:before{content:'\f268'}
-.icon-skull:before{content:'\f38d'}
-.icon-skype:before{content:'\f141'}
-.icon-skypeaway:before{content:'\f39f'}
-.icon-skypebusy:before{content:'\f3a0'}
-.icon-skypeoffline:before{content:'\f3a1'}
-.icon-skypeonline:before{content:'\f39e'}
-.icon-smaller:before{content:'\f30b'}
-.icon-smf:before{content:'\f062'}
-.icon-smile:before{content:'\263a'}
-.icon-snow:before{content:'\f22e'}
-.icon-snowman:before{content:'\f37c'}
-.icon-socialnetwork:before{content:'\f03b'}
-.icon-software:before{content:'\f09a'}
-.icon-sortbynameascending-atoz:before{content:'\f1c2'}
-.icon-sortbynamedescending-ztoa:before{content:'\f1c1'}
-.icon-sortbysizeascending:before{content:'\f1c3'}
-.icon-sortbysizedescending:before{content:'\f1c4'}
-.icon-soundwave:before{content:'\f194'}
-.icon-soup:before{content:'\f3d1'}
-.icon-spaceinvaders:before{content:'\f352'}
-.icon-spades:before{content:'\f2f5'}
-.icon-spam:before{content:'\f047'}
-.icon-spamalt:before{content:'\f048'}
-.icon-spawn:before{content:'\f344'}
-.icon-speaker:before{content:'\f372'}
-.icon-speed:before{content:'\f40b'}
-.icon-spider:before{content:'\f346'}
-.icon-spiderman:before{content:'\f347'}
-.icon-split:before{content:'\f335'}
-.icon-spoon:before{content:'\f213'}
-.icon-spray:before{content:'\f1c7'}
-.icon-spreadsheet:before{content:'\f0c3'}
-.icon-squareapp:before{content:'\f26f'}
-.icon-squarebrackets:before{content:'\f0b3'}
-.icon-ssh:before{content:'\f04e'}
-.icon-sslmanager:before{content:'\f04f'}
-.icon-stadium:before{content:'\f3d6'}
-.icon-stamp:before{content:'\f242'}
-.icon-stampalt:before{content:'\f243'}
-.icon-star:before{content:'\f13a'}
-.icon-star-empty:before{content:'\f13b'}
-.icon-starempty:before{content:'\f2de'}
-.icon-starfull:before{content:'\f2e0'}
-.icon-starhalf:before{content:'\f2df'}
-.icon-steak:before{content:'\f360'}
-.icon-steam:before{content:'\f2dd'}
-.icon-step-backward:before{content:'\f198'}
-.icon-step-forward:before{content:'\f197'}
-.icon-sticker:before{content:'\f3f5'}
-.icon-stiletto:before{content:'\f429'}
-.icon-stockdown:before{content:'\f252'}
-.icon-stocks:before{content:'\f250'}
-.icon-stockup:before{content:'\f251'}
-.icon-stomach:before{content:'\f3e1'}
-.icon-stop:before{content:'\f185'}
-.icon-stopwatch:before{content:'\f219'}
-.icon-storage-box:before{content:'\f011'}
-.icon-storagealt-drawer:before{content:'\f012'}
-.icon-store:before{content:'\f272'}
-.icon-storm:before{content:'\f230'}
-.icon-stove:before{content:'\f371'}
-.icon-strawberry:before{content:'\f3f3'}
-.icon-strikethrough:before{content:'\f1f7'}
-.icon-student-school:before{content:'\f288'}
-.icon-stumbleupon:before{content:'\f40c'}
-.icon-subdomain:before{content:'\f052'}
-.icon-submarine:before{content:'\f373'}
-.icon-subscript:before{content:'\f1ea'}
-.icon-subtractshape:before{content:'\f1fe'}
-.icon-sum:before{content:'\f33b'}
-.icon-sun-day:before{content:'\f206'}
-.icon-sunnysideup:before{content:'\f365'}
-.icon-superman:before{content:'\f33f'}
-.icon-superscript:before{content:'\f1eb'}
-.icon-support:before{content:'\f013'}
-.icon-supportalt:before{content:'\f014'}
-.icon-switch:before{content:'\f28a'}
-.icon-switchoff:before{content:'\f32d'}
-.icon-switchoffalt:before{content:'\f28e'}
-.icon-switchon:before{content:'\f32c'}
-.icon-switchonalt:before{content:'\f28d'}
-.icon-sword:before{content:'\f2ed'}
-.icon-sync:before{content:'\f0bd'}
-.icon-syncalt:before{content:'\f11c'}
-.icon-synckeeplocal:before{content:'\f33e'}
-.icon-synckeepserver:before{content:'\f33d'}
-.icon-syringe-antivirus:before{content:'\f0a9'}
-.icon-tablet:before{content:'\f118'}
-.icon-tabletennis-pingpong:before{content:'\f2f0'}
-.icon-taco:before{content:'\f3cd'}
-.icon-tag:before{content:'\f032'}
-.icon-tagalt-pricealt:before{content:'\f264'}
-.icon-tags:before{content:'\f482'}
-.icon-tagvertical:before{content:'\f15f'}
-.icon-tank:before{content:'\f423'}
-.icon-target:before{content:'\f2a6'}
-.icon-taskmanager-logprograms:before{content:'\f04b'}
-.icon-tasks:before{content:'\f0e0'}
-.icon-taxi:before{content:'\f3a4'}
-.icon-tea:before{content:'\f3cb'}
-.icon-teapot:before{content:'\f42c'}
-.icon-telescope:before{content:'\f3ef'}
-.icon-temperature-thermometer:before{content:'\f20d'}
-.icon-temperaturealt-thermometeralt:before{content:'\f20e'}
-.icon-tennis:before{content:'\f2ea'}
-.icon-tent-camping:before{content:'\f215'}
-.icon-terminal:before{content:'\f114'}
-.icon-tethering:before{content:'\f0f1'}
-.icon-tetrisone:before{content:'\f34b'}
-.icon-tetristhree:before{content:'\f34d'}
-.icon-tetristwo:before{content:'\f34c'}
-.icon-text-height:before{content:'\f1f8'}
-.icon-text-width:before{content:'\f1f9'}
-.icon-th:before{content:'\f110'}
-.icon-th-large:before{content:'\f112'}
-.icon-th-list:before{content:'\f113'}
-.icon-theather:before{content:'\f39c'}
-.icon-theme-style:before{content:'\f041'}
-.icon-thissideup:before{content:'\f41d'}
-.icon-threecolumns:before{content:'\f1ab'}
-.icon-thumbs-down:before{content:'\f139'}
-.icon-thumbs-up:before{content:'\f138'}
-.icon-ticket:before{content:'\f3dc'}
-.icon-tictactoe:before{content:'\f39a'}
-.icon-tie-business:before{content:'\2040'}
-.icon-time:before{content:'\f210'}
-.icon-timeline:before{content:'\f253'}
-.icon-tint:before{content:'\f208'}
-.icon-toast:before{content:'\f2ad'}
-.icon-toiletpaper:before{content:'\f384'}
-.icon-tooth:before{content:'\f3de'}
-.icon-toothbrush:before{content:'\f385'}
-.icon-tophat:before{content:'\f3f0'}
-.icon-torigate:before{content:'\f411'}
-.icon-touchpad:before{content:'\f115'}
-.icon-trafficlight:before{content:'\f22a'}
-.icon-transform:before{content:'\f1a6'}
-.icon-trash:before{content:'\f0ce'}
-.icon-trashempty:before{content:'\f0cf'}
-.icon-trashfull:before{content:'\f0d0'}
-.icon-travel:before{content:'\f422'}
-.icon-treediagram:before{content:'\f0ec'}
-.icon-treeornament:before{content:'\f37e'}
-.icon-triangle:before{content:'\25b3'}
-.icon-tron:before{content:'\f34f'}
-.icon-trophy:before{content:'\f2d7'}
-.icon-truck:before{content:'\f211'}
-.icon-trumpet:before{content:'\f375'}
-.icon-tumblr:before{content:'\f164'}
-.icon-tv:before{content:'\f1a4'}
-.icon-twitter:before{content:'\f16a'}
-.icon-twocolumnsleft:before{content:'\f1a9'}
-.icon-twocolumnsleftalt:before{content:'\f1aa'}
-.icon-twocolumnsright:before{content:'\f1a7'}
-.icon-twocolumnsrightalt:before{content:'\f1a8'}
-.icon-ubuntu:before{content:'\f120'}
-.icon-umbrella:before{content:'\f218'}
-.icon-underline:before{content:'\f1f6'}
-.icon-undo:before{content:'\f32a'}
-.icon-unlock:before{content:'\f0bf'}
-.icon-upleft:before{content:'\f302'}
-.icon-upload:before{content:'\f47a'}
-.icon-uploadalt:before{content:'\f11b'}
-.icon-upright:before{content:'\f303'}
-.icon-uptime:before{content:'\f017'}
-.icon-usb:before{content:'\f10d'}
-.icon-usbalt:before{content:'\f10e'}
-.icon-usbplug:before{content:'\f10f'}
-.icon-user:before{content:'\f133'}
-.icon-userfilter:before{content:'\f05d'}
-.icon-usfootball:before{content:'\f2ec'}
-.icon-value-coins:before{content:'\f018'}
-.icon-vector:before{content:'\f1b6'}
-.icon-vendetta:before{content:'\f3c5'}
-.icon-video:before{content:'\f17d'}
-.icon-viking:before{content:'\f379'}
-.icon-vimeo:before{content:'\f168'}
-.icon-vinyl:before{content:'\f0cc'}
-.icon-violin:before{content:'\f1a5'}
-.icon-virus:before{content:'\f0a8'}
-.icon-visa:before{content:'\f3c2'}
-.icon-visitor:before{content:'\f097'}
-.icon-vlc-cone:before{content:'\f192'}
-.icon-voice:before{content:'\f18c'}
-.icon-volume-down:before{content:'\f0e3'}
-.icon-volume-off:before{content:'\f0e4'}
-.icon-volume-up:before{content:'\f0e2'}
-.icon-vps:before{content:'\f025'}
-.icon-wacom:before{content:'\f1bb'}
-.icon-walle:before{content:'\f3bc'}
-.icon-wallet:before{content:'\e000'}
-.icon-warcraft:before{content:'\f3bf'}
-.icon-warmedal:before{content:'\f2e4'}
-.icon-warning-sign:before{content:'\f316'}
-.icon-washer:before{content:'\f39b'}
-.icon-watch:before{content:'\f378'}
-.icon-watertap-plumbing:before{content:'\f22d'}
-.icon-wave-sea:before{content:'\f23c'}
-.icon-wavealt-seaalt:before{content:'\f23b'}
-.icon-webcam:before{content:'\f0fe'}
-.icon-webcamalt:before{content:'\f129'}
-.icon-webhostinghub:before{content:'\f031'}
-.icon-webmail:before{content:'\f045'}
-.icon-webpage:before{content:'\f033'}
-.icon-webplatform:before{content:'\f3c3'}
-.icon-websitealt:before{content:'\f01c'}
-.icon-websitebuilder:before{content:'\f034'}
-.icon-weight:before{content:'\f430'}
-.icon-westernunion:before{content:'\f26a'}
-.icon-wheel:before{content:'\f228'}
-.icon-wheelchair:before{content:'\f3fe'}
-.icon-whistle:before{content:'\f3d8'}
-.icon-whmcs:before{content:'\f066'}
-.icon-wifi:before{content:'\f0ff'}
-.icon-wind:before{content:'\f41b'}
-.icon-windleft:before{content:'\f424'}
-.icon-windows:before{content:'\f019'}
-.icon-windright:before{content:'\f425'}
-.icon-wine:before{content:'\f238'}
-.icon-wizard:before{content:'\f03c'}
-.icon-wizardalt:before{content:'\f1fb'}
-.icon-wizardhat:before{content:'\f337'}
-.icon-woman-female:before{content:'\f2a2'}
-.icon-women:before{content:'\f24d'}
-.icon-wordpress:before{content:'\f074'}
-.icon-wrench:before{content:'\f05b'}
-.icon-wrenchalt:before{content:'\f2b2'}
-.icon-xbox:before{content:'\f353'}
-.icon-xmen:before{content:'\f345'}
-.icon-yahoo:before{content:'\f151'}
-.icon-yen:before{content:'\00a5'}
-.icon-yenalt:before{content:'\f25d'}
-.icon-yinyang:before{content:'\262f'}
-.icon-youtube:before{content:'\f142'}
-.icon-zelda:before{content:'\f3b8'}
-.icon-zikula:before{content:'\f0ac'}
-.icon-zip:before{content:'\f116'}
-.icon-zodiac-aquarius:before{content:'\f3b4'}
-.icon-zodiac-aries:before{content:'\f3aa'}
-.icon-zodiac-cancer:before{content:'\f3ad'}
-.icon-zodiac-capricorn:before{content:'\f3b3'}
-.icon-zodiac-gemini:before{content:'\f3ac'}
-.icon-zodiac-leo:before{content:'\f3ae'}
-.icon-zodiac-libra:before{content:'\f3b0'}
-.icon-zodiac-pisces:before{content:'\f3b5'}
-.icon-zodiac-sagitarius:before{content:'\f3b2'}
-.icon-zodiac-scorpio:before{content:'\f3b1'}
-.icon-zodiac-taurus:before{content:'\f3ab'}
-.icon-zodiac-virgo:before{content:'\f3af'}
-.icon-zoom-in:before{content:'\f320'}
-.icon-zoom-out:before{content:'\f321'}
-.icon-vk:before{content:'\f34e'}
-.icon-bitcoin:before{content:'\f584'}
-.icon-rouble:before{content:'\f4ca'}
-.icon-phpnuke:before{content:'\f48c'}
-.icon-modx:before{content:'\f48d'}
-.icon-eoneohseven:before{content:'\f48e'}
-.icon-subrion:before{content:'\f48f'}
-.icon-typothree:before{content:'\f490'}
-.icon-tikiwiki:before{content:'\f491'}
-.icon-pligg:before{content:'\f492'}
-.icon-pyrocms:before{content:'\f493'}
-.icon-mambo:before{content:'\f494'}
-.icon-contao:before{content:'\f495'}
-.icon-crackedegg:before{content:'\f496'}
-.icon-coffeecupalt:before{content:'\f497'}
-.icon-reademailalt:before{content:'\f498'}
-.icon-train:before{content:'\f499'}
-.icon-shoebox:before{content:'\f49a'}
-.icon-bathtub:before{content:'\f49b'}
-.icon-ninegag:before{content:'\f49c'}
-.icon-pebble:before{content:'\f49d'}
-.icon-musicthree:before{content:'\f49e'}
-.icon-stairsup:before{content:'\f49f'}
-.icon-stairsdown:before{content:'\f4a0'}
-.icon-bookalt:before{content:'\f4a1'}
-.icon-programclose:before{content:'\f4a2'}
-.icon-programok:before{content:'\f4a3'}
-.icon-splitalt:before{content:'\f4a4'}
-.icon-solarsystem:before{content:'\f4a5'}
-.icon-honeycomb:before{content:'\f4a6'}
-.icon-tools:before{content:'\f4a7'}
-.icon-xoops:before{content:'\f4a8'}
-.icon-pixie:before{content:'\f4a9'}
-.icon-dotclear:before{content:'\f4aa'}
-.icon-impresscms:before{content:'\f4ab'}
-.icon-saurus:before{content:'\f4ac'}
-.icon-impresspages:before{content:'\f4ad'}
-.icon-monstra:before{content:'\f4ae'}
-.icon-snews:before{content:'\f4af'}
-.icon-jcore:before{content:'\f4b0'}
-.icon-silverstripe:before{content:'\f4b1'}
-.icon-btwoevolution:before{content:'\f4b2'}
-.icon-nucleus:before{content:'\f4b3'}
-.icon-symphony:before{content:'\f4b5'}
-.icon-vanillacms:before{content:'\f4b6'}
-.icon-bbpress:before{content:'\f4b7'}
-.icon-phpbbalt:before{content:'\f4b8'}
-.icon-chyrp:before{content:'\f4b9'}
-.icon-pivotx:before{content:'\f4ba'}
-.icon-pagecookery:before{content:'\f4bb'}
-.icon-moviereelalt:before{content:'\f4bc'}
-.icon-cassettealt:before{content:'\f4bd'}
-.icon-photobucket:before{content:'\f4be'}
-.icon-technorati:before{content:'\f4bf'}
-.icon-theverge:before{content:'\f4c0'}
-.icon-stacks:before{content:'\f4c1'}
-.icon-dotlist:before{content:'\f4c2'}
-.icon-numberlist:before{content:'\f4c3'}
-.icon-indentleft:before{content:'\f4c4'}
-.icon-indentright:before{content:'\f4c5'}
-.icon-fblike:before{content:'\f4c6'}
-.icon-fbdislike:before{content:'\f4c7'}
-.icon-sale:before{content:'\f4c8'}
-.icon-sharetronix:before{content:'\f4c9'}
-.icon-markerdown:before{content:'\f4cb'}
-.icon-markerup:before{content:'\f4cc'}
-.icon-markerleft:before{content:'\f4cd'}
-.icon-markerright:before{content:'\f4ce'}
-.icon-bookmarkalt:before{content:'\f4cf'}
-.icon-calendarthree:before{content:'\f4d0'}
-.icon-wineglass:before{content:'\f4d1'}
-.icon-slidersoff:before{content:'\f4d2'}
-.icon-slidersmiddle:before{content:'\f4d3'}
-.icon-slidersfull:before{content:'\f4d4'}
-.icon-slidersdesc:before{content:'\f4d5'}
-.icon-slidersasc:before{content:'\f4d6'}
-.icon-slideronefull:before{content:'\f4d7'}
-.icon-slidertwofull:before{content:'\f4d8'}
-.icon-sliderthreefull:before{content:'\f4d9'}
-.icon-noborders:before{content:'\f4da'}
-.icon-bottomborder:before{content:'\f4db'}
-.icon-topborder:before{content:'\f4dc'}
-.icon-leftborder:before{content:'\f4dd'}
-.icon-rightborder:before{content:'\f4de'}
-.icon-horizontalborder:before{content:'\f4df'}
-.icon-verticalborder:before{content:'\f4e0'}
-.icon-outerborders:before{content:'\f4e1'}
-.icon-innerborders:before{content:'\f4e2'}
-.icon-fullborders:before{content:'\f4e3'}
-.icon-networksignalalt:before{content:'\f4e4'}
-.icon-resizeverticalalt:before{content:'\f4e5'}
-.icon-resizehorizontalalt:before{content:'\f4e6'}
-.icon-moneyalt:before{content:'\f4e7'}
-.icon-fontcase:before{content:'\f4e8'}
-.icon-playstation:before{content:'\f4e9'}
-.icon-cube:before{content:'\f4ea'}
-.icon-sphere:before{content:'\f4eb'}
-.icon-ceilinglight:before{content:'\f4ec'}
-.icon-chandelier:before{content:'\f4ed'}
-.icon-details:before{content:'\f4ee'}
-.icon-detailsalt:before{content:'\f4ef'}
-.icon-bullet:before{content:'\f4f0'}
-.icon-gun:before{content:'\f4f1'}
-.icon-processorthree:before{content:'\f4f2'}
-.icon-world:before{content:'\f4f3'}
-.icon-statistics:before{content:'\f4f4'}
-.icon-shoppingcartalt:before{content:'\f4f5'}
-.icon-microphonealt:before{content:'\f4f6'}
-.icon-routeralt:before{content:'\f4f7'}
-.icon-shell:before{content:'\f4f8'}
-.icon-squareplay:before{content:'\f4f9'}
-.icon-squarestop:before{content:'\f4fa'}
-.icon-squarepause:before{content:'\f4fb'}
-.icon-squarerecord:before{content:'\f4fc'}
-.icon-squareforward:before{content:'\f4fd'}
-.icon-squareback:before{content:'\f4fe'}
-.icon-squarenext:before{content:'\f4ff'}
-.icon-squareprevious:before{content:'\f500'}
-.icon-mega:before{content:'\f501'}
-.icon-charliechaplin:before{content:'\f502'}
-.icon-popcorn:before{content:'\f503'}
-.icon-fatarrowright:before{content:'\f504'}
-.icon-fatarrowleft:before{content:'\f505'}
-.icon-fatarrowdown:before{content:'\f506'}
-.icon-fatarrowup:before{content:'\f507'}
-.icon-shirtbutton:before{content:'\f508'}
-.icon-shirtbuttonalt:before{content:'\f509'}
-.icon-cuckooclock:before{content:'\f50a'}
-.icon-lens:before{content:'\f50b'}
-.icon-voltage:before{content:'\f50c'}
-.icon-planealt:before{content:'\f50d'}
-.icon-busalt:before{content:'\f50e'}
-.icon-lipstick:before{content:'\f50f'}
-.icon-plantalt:before{content:'\f510'}
-.icon-paperboat:before{content:'\f511'}
-.icon-texture:before{content:'\f512'}
-.icon-dominoone:before{content:'\f513'}
-.icon-dominotwo:before{content:'\f514'}
-.icon-dominothree:before{content:'\f515'}
-.icon-dominofour:before{content:'\f516'}
-.icon-dominofive:before{content:'\f517'}
-.icon-dominosix:before{content:'\f518'}
-.icon-dominoseven:before{content:'\f519'}
-.icon-dominoeight:before{content:'\f51a'}
-.icon-dominonine:before{content:'\f51b'}
-.icon-connected:before{content:'\f51c'}
-.icon-connectedpc:before{content:'\f51d'}
-.icon-musicsheet:before{content:'\f51e'}
-.icon-rdio:before{content:'\f51f'}
-.icon-spotify:before{content:'\f520'}
-.icon-deviantart:before{content:'\f521'}
-.icon-yelp:before{content:'\f522'}
-.icon-behance:before{content:'\f523'}
-.icon-nfc:before{content:'\f524'}
-.icon-earbudsalt:before{content:'\f525'}
-.icon-earbuds:before{content:'\f526'}
-.icon-amazon:before{content:'\f527'}
-.icon-openid:before{content:'\f528'}
-.icon-digg:before{content:'\f529'}
-.icon-retweet:before{content:'\f52a'}
-.icon-moonnew:before{content:'\f52b'}
-.icon-moonwaxingcrescent:before{content:'\f52c'}
-.icon-moonfirstquarter:before{content:'\f52d'}
-.icon-moonwaxinggibbous:before{content:'\f52e'}
-.icon-moonfull:before{content:'\f52f'}
-.icon-moonwaninggibbous:before{content:'\f530'}
-.icon-moonthirdquarter:before{content:'\f531'}
-.icon-moonwaningcrescent:before{content:'\f532'}
-.icon-planet:before{content:'\f533'}
-.icon-sodacup:before{content:'\f534'}
-.icon-cocktail:before{content:'\f535'}
-.icon-church:before{content:'\f536'}
-.icon-mosque:before{content:'\f537'}
-.icon-comedy:before{content:'\f538'}
-.icon-tragedy:before{content:'\f539'}
-.icon-bacon:before{content:'\f53a'}
-.icon-trailor:before{content:'\f53b'}
-.icon-tshirt:before{content:'\f53c'}
-.icon-design:before{content:'\f53d'}
-.icon-spiderweb:before{content:'\f53e'}
-.icon-fireplace:before{content:'\f53f'}
-.icon-tallglass:before{content:'\f540'}
-.icon-grapes:before{content:'\f541'}
-.icon-biohazard:before{content:'\f542'}
-.icon-directions:before{content:'\f543'}
-.icon-equalizerthree:before{content:'\f544'}
-.icon-mountains:before{content:'\f545'}
-.icon-bing:before{content:'\f546'}
-.icon-windowseight:before{content:'\f547'}
-.icon-microsoftoffice:before{content:'\f548'}
-.icon-salealt:before{content:'\f549'}
-.icon-purse:before{content:'\f54a'}
-.icon-chickenalt:before{content:'\f54b'}
-.icon-podium:before{content:'\f54c'}
-.icon-findfriends:before{content:'\f54d'}
-.icon-microphonethree:before{content:'\f54e'}
-.icon-workshirt:before{content:'\f54f'}
-.icon-donotdisturb:before{content:'\f550'}
-.icon-addtags:before{content:'\f551'}
-.icon-removetags:before{content:'\f556'}
-.icon-carbattery:before{content:'\f553'}
-.icon-debug:before{content:'\f554'}
-.icon-trojan:before{content:'\f555'}
-.icon-molecule:before{content:'\f556'}
-.icon-safetygoggles:before{content:'\f557'}
-.icon-leather:before{content:'\f558'}
-.icon-teddybear:before{content:'\f559'}
-.icon-stroller:before{content:'\f55a'}
-.icon-circleplay:before{content:'\f55b'}
-.icon-circlestop:before{content:'\f55c'}
-.icon-circlepause:before{content:'\f55d'}
-.icon-circlerecord:before{content:'\f55e'}
-.icon-circleforward:before{content:'\f55f'}
-.icon-circlebackward:before{content:'\f560'}
-.icon-circlenext:before{content:'\f561'}
-.icon-circleprevious:before{content:'\f562'}
-.icon-circleplayempty:before{content:'\f563'}
-.icon-circlestopempty:before{content:'\f564'}
-.icon-circlepauseempty:before{content:'\f565'}
-.icon-circlerecordempty:before{content:'\f566'}
-.icon-circleforwardempty:before{content:'\f567'}
-.icon-circlebackwardempty:before{content:'\f568'}
-.icon-circlenextempty:before{content:'\f569'}
-.icon-circlepreviousempty:before{content:'\f56a'}
-.icon-belt:before{content:'\f56b'}
-.icon-bait:before{content:'\f56c'}
-.icon-manalt:before{content:'\f56d'}
-.icon-womanalt:before{content:'\f56e'}
-.icon-clover:before{content:'\f56f'}
-.icon-pacifier:before{content:'\f570'}
-.icon-calcplus:before{content:'\f571'}
-.icon-calcminus:before{content:'\f572'}
-.icon-calcmultiply:before{content:'\f573'}
-.icon-calcdivide:before{content:'\f574'}
-.icon-calcequals:before{content:'\f575'}
-.icon-city:before{content:'\f576'}
-.icon-hdvideo:before{content:'\f577'}
-.icon-horizontalexpand:before{content:'\f578'}
-.icon-horizontalcontract:before{content:'\f579'}
-.icon-radar:before{content:'\f57a'}
-.icon-threed:before{content:'\f57b'}
-.icon-flickralt:before{content:'\f57c'}
-.icon-pattern:before{content:'\f57d'}
-.icon-elevator:before{content:'\f57e'}
-.icon-escalator:before{content:'\f57f'}
-.icon-portrait:before{content:'\f580'}
-.icon-cigar:before{content:'\f581'}
-.icon-dropbox:before{content:'\f582'}
-.icon-origami:before{content:'\f583'}
-.icon-opensource:before{content:'\f585'}
-.icon-redaxscript:before{content:'\f586'}
-.icon-mahara:before{content:'\f587'}
-.icon-forkcms:before{content:'\f588'}
-.icon-pimcore:before{content:'\f589'}
-.icon-bigace:before{content:'\f58a'}
-.icon-aef:before{content:'\f58b'}
-.icon-punbb:before{content:'\f58c'}
-.icon-phorum:before{content:'\f58d'}
-.icon-fluxbb:before{content:'\f58e'}
-.icon-minibb:before{content:'\f58f'}
-.icon-zenphoto:before{content:'\f590'}
-.icon-fourimages:before{content:'\f591'}
-.icon-plogger:before{content:'\f592'}
-.icon-jcow:before{content:'\f593'}
-.icon-elgg:before{content:'\f594'}
-.icon-etano:before{content:'\f595'}
-.icon-openclassifieds:before{content:'\f596'}
-.icon-osclass:before{content:'\f597'}
-.icon-openx:before{content:'\f598'}
-.icon-phplist:before{content:'\f599'}
-.icon-roundcube:before{content:'\f59a'}
-.icon-pommo:before{content:'\f59b'}
-.icon-webinsta:before{content:'\f59c'}
-.icon-limesurvey:before{content:'\f59d'}
-.icon-fengoffice:before{content:'\f59e'}
-.icon-eyeos:before{content:'\f59f'}
-.icon-dotproject:before{content:'\f5a0'}
-.icon-collabtive:before{content:'\f5a1'}
-.icon-projectpier:before{content:'\f5a2'}
-.icon-taskfreak:before{content:'\f5a3'}
-.icon-eventum:before{content:'\f5a4'}
-.icon-traq:before{content:'\f5a5'}
-.icon-mantisbugtracker:before{content:'\f5a6'}
-.icon-oscommerce:before{content:'\f5a7'}
-.icon-zencart:before{content:'\f5a8'}
-.icon-tomatocart:before{content:'\f5a9'}
-.icon-boxbilling:before{content:'\f5aa'}
-.icon-zurmo:before{content:'\f5ab'}
-.icon-orangehrm:before{content:'\f5ac'}
-.icon-vtiger:before{content:'\f5ad'}
-.icon-mibew:before{content:'\f5ae'}
-.icon-phpmyfaq:before{content:'\f5af'}
-.icon-yiiframework:before{content:'\f5b0'}
-.icon-zendframework:before{content:'\f5b1'}
-.icon-fuelphp:before{content:'\f5b2'}
-.icon-kohana:before{content:'\f5b3'}
-.icon-smarty:before{content:'\f5b4'}
-.icon-sidu:before{content:'\f5b5'}
-.icon-simplepie:before{content:'\f5b6'}
-.icon-projectsend:before{content:'\f5b7'}
-.icon-extjs:before{content:'\f5b8'}
-.icon-raphael:before{content:'\f5b9'}
-.icon-sizzle:before{content:'\f5ba'}
-.icon-yui:before{content:'\f5bb'}
-.icon-scissorsalt:before{content:'\f5bc'}
-.icon-cuthere:before{content:'\f5bd'}
-.icon-coinsalt:before{content:'\f5be'}
-.icon-parkingmeter:before{content:'\f5bf'}
-.icon-treethree:before{content:'\f5c0'}
-.icon-packarchive:before{content:'\f5c1'}
-.icon-unpackarchive:before{content:'\f5c2'}
-.icon-terminalalt:before{content:'\f5c3'}
-.icon-jersey:before{content:'\f5c4'}
-.icon-vial:before{content:'\f5c5'}
-.icon-noteslist:before{content:'\f5c6'}
-.icon-notestasks:before{content:'\f5c7'}
-.icon-notesdate:before{content:'\f5c8'}
-.icon-noteslocation:before{content:'\f5c9'}
-.icon-noteslistalt:before{content:'\f5ca'}
-.icon-notestasksalt:before{content:'\f5cb'}
-.icon-notesdatealt:before{content:'\f5cc'}
-.icon-noteslocationalt:before{content:'\f5cd'}
-.icon-useralt:before{content:'\f5ce'}
-.icon-adduseralt:before{content:'\f5cf'}
-.icon-removeuseralt:before{content:'\f5d0'}
-.icon-banuseralt:before{content:'\f5d1'}
-.icon-banuser:before{content:'\f5d2'}
-.icon-paintrollalt:before{content:'\f5d3'}
-.icon-textcursor:before{content:'\f5d4'}
-.icon-textfield:before{content:'\f5d5'}
-.icon-precisecursor:before{content:'\f5d6'}
-.icon-brokenlink:before{content:'\f5d7'}
-.icon-bookmarkthree:before{content:'\f5d8'}
-.icon-bookmarkfour:before{content:'\f5d9'}
-.icon-warmedalalt:before{content:'\f5da'}
-.icon-thinking:before{content:'\f5db'}
-.icon-commentlove:before{content:'\f5dc'}
-.icon-commentsmiley:before{content:'\f5dd'}
-.icon-sharetwo:before{content:'\f147'}
-.icon-emptystar:before{content:'\f2de'}
-.icon-halfstar:before{content:'\f2df'}
-.icon-fullstar:before{content:'\f2e0'}
-.icon-forbidden:before{content:'\f314'}
-.icon-indentleftalt:before{content:'\f4c4'}
-.icon-indentrightalt:before{content:'\f4c5'}
-.icon-modxalt:before{content:'\f5de'}
-.icon-apple:before{content:'\f5df'}
-.icon-greekcolumn:before{content:'\f5e0'}
-.icon-walletalt:before{content:'\f5e1'}
-.icon-dollarsquare:before{content:'\f5e2'}
-.icon-poundsquare:before{content:'\f5e3'}
-.icon-yensquare:before{content:'\f5e4'}
-.icon-eurosquare:before{content:'\f5e5'}
-.icon-bitcoinsquare:before{content:'\f5e6'}
-.icon-roublesquare:before{content:'\f5e7'}
-.icon-roublealt:before{content:'\f5e8'}
-.icon-bitcoinalt:before{content:'\f5e9'}
-.icon-gavel:before{content:'\f5ea'}
-.icon-barchartasc:before{content:'\f5eb'}
-.icon-barchartdesc:before{content:'\f5ec'}
-.icon-house:before{content:'\f5ed'}
-.icon-garage:before{content:'\f5ee'}
-.icon-milk:before{content:'\f5ef'}
-.icon-hryvnia:before{content:'\f5f0'}
-.icon-hryvniasquare:before{content:'\f5f1'}
-.icon-hryvniaalt:before{content:'\f5f2'}
-.icon-beeralt:before{content:'\f5f3'}
-.icon-trolleyfull:before{content:'\f5f4'}
-.icon-trolleyload:before{content:'\f5f5'}
-.icon-trolleyunload:before{content:'\f5f6'}
-.icon-trolleyempty:before{content:'\f5f7'}
-.icon-mootools:before{content:'\f5f8'}
-.icon-mootoolstwo:before{content:'\f5f9'}
-.icon-mootoolsthree:before{content:'\f5fa'}
-.icon-mysqlthree:before{content:'\f5fb'}
-.icon-mysqlalt:before{content:'\f5fc'}
-.icon-pgsql:before{content:'\f5fd'}
-.icon-mongodb:before{content:'\f5fe'}
-.icon-neofourj:before{content:'\f5ff'}
-.icon-nosql:before{content:'\f600'}
-.icon-catface:before{content:'\f601'}
-.icon-polaroid:before{content:'\f602'}
-.icon-clouderror:before{content:'\f603'}
-.icon-camcorder:before{content:'\f604'}
-.icon-projector:before{content:'\f605'}
-.icon-sdvideo:before{content:'\f606'}
-.icon-fx:before{content:'\f607'}
-.icon-gramophone:before{content:'\f608'}
-.icon-speakeralt:before{content:'\f609'}
-.icon-hddalt:before{content:'\f60a'}
-.icon-usbflash:before{content:'\f60b'}
-.icon-manillaenvelope:before{content:'\f60c'}
-.icon-stickynote:before{content:'\f60d'}
-.icon-stickynotealt:before{content:'\f60e'}
-.icon-torch:before{content:'\f60f'}
-.icon-flashlightalt:before{content:'\f610'}
-.icon-campfire:before{content:'\f611'}
-.icon-cctv:before{content:'\f612'}
-.icon-drill:before{content:'\f613'}
-.icon-lampalt:before{content:'\f614'}
-.icon-flowerpot:before{content:'\f615'}
-.icon-defragment:before{content:'\f616'}
-.icon-panoramio:before{content:'\f617'}
-.icon-panorama:before{content:'\f618'}
-.icon-photosphere:before{content:'\f619'}
-.icon-panoramaalt:before{content:'\f61a'}
-.icon-timer:before{content:'\f61b'}
-.icon-burstmode:before{content:'\f61c'}
-.icon-cameraflash:before{content:'\f61d'}
-.icon-autoflash:before{content:'\f61e'}
-.icon-noflash:before{content:'\f61f'}
-.icon-threetofour:before{content:'\f620'}
-.icon-sixteentonine:before{content:'\f621'}
-.icon-cat:before{content:'\f622'}
-.icon-dog:before{content:'\f623'}
-.icon-rabbit:before{content:'\f624'}
-.icon-koala:before{content:'\f625'}
-.icon-butterflyalt:before{content:'\f626'}
-.icon-butterfly:before{content:'\f627'}
-.icon-wwf:before{content:'\f628'}
-.icon-poop:before{content:'\f629'}
-.icon-poopalt:before{content:'\f62a'}
-.icon-kiwi:before{content:'\f62b'}
-.icon-kiwifruit:before{content:'\f62c'}
-.icon-lemon:before{content:'\f62d'}
-.icon-pear:before{content:'\f62e'}
-.icon-watermelon:before{content:'\f62f'}
-.icon-onion:before{content:'\f630'}
-.icon-turnip:before{content:'\f631'}
-.icon-eggplant:before{content:'\f632'}
-.icon-avocado:before{content:'\f633'}
-.icon-perfume:before{content:'\f634'}
-.icon-arch:before{content:'\f635'}
-.icon-pluspages:before{content:'\f636'}
-.icon-community:before{content:'\f637'}
-.icon-pluscircles:before{content:'\f638'}
-.icon-googleplusold:before{content:'\f639'}
-.icon-plusgames:before{content:'\f63a'}
-.icon-event:before{content:'\f63b'}
-.icon-miui:before{content:'\f63c'}
-.icon-hot:before{content:'\f63d'}
-.icon-flowup:before{content:'\f63e'}
-.icon-flowdown:before{content:'\f63f'}
-.icon-moustache:before{content:'\f640'}
-.icon-angle:before{content:'\f641'}
-.icon-sleep:before{content:'\f642'}
-.icon-acorn:before{content:'\f643'}
-.icon-steamalt:before{content:'\f644'}
-.icon-resizeupleft:before{content:'\f645'}
-.icon-resizeupright:before{content:'\f646'}
-.icon-resizedownright:before{content:'\f647'}
-.icon-resizedownleft:before{content:'\f648'}
-.icon-hammeralt:before{content:'\f649'}
-.icon-bamboo:before{content:'\f64a'}
-.icon-mypictures:before{content:'\f64b'}
-.icon-mymusic:before{content:'\f64c'}
-.icon-myvideos:before{content:'\f64d'}
-.icon-systemfolder:before{content:'\f64e'}
-.icon-bookthree:before{content:'\f64f'}
-.icon-compile:before{content:'\f650'}
-.icon-report:before{content:'\f651'}
-.icon-fliphorizontal:before{content:'\f652'}
-.icon-flipvertical:before{content:'\f653'}
-.icon-construction:before{content:'\f654'}
-.icon-counteralt:before{content:'\f655'}
-.icon-counter:before{content:'\f656'}
-.icon-papercutter:before{content:'\f657'}
-.icon-snaptodot:before{content:'\f658'}
-.icon-snaptogrid:before{content:'\f659'}
-.icon-caligraphy:before{content:'\f65a'}
-.icon-icecreamthree:before{content:'\f65b'}
-.icon-skitch:before{content:'\f65c'}
-.icon-archlinux:before{content:'\f65d'}
-.icon-elementaryos:before{content:'\f65e'}
-.icon-loadingone:before{content:'\f65f'}
-.icon-loadingtwo:before{content:'\f660'}
-.icon-loadingthree:before{content:'\f661'}
-.icon-loadingfour:before{content:'\f662'}
-.icon-loadingfive:before{content:'\f663'}
-.icon-loadingsix:before{content:'\f664'}
-.icon-loadingseven:before{content:'\f665'}
-.icon-loadingeight:before{content:'\f666'}
-.icon-brokenheart:before{content:'\f667'}
-.icon-heartarrow:before{content:'\f668'}
-.icon-heartsparkle:before{content:'\f669'}
-.icon-cell:before{content:'\f66a'}
-.icon-panda:before{content:'\f66b'}
-.icon-refreshalt:before{content:'\f66c'}
-.icon-mirror:before{content:'\f66d'}
-.icon-headphonesthree:before{content:'\f66e'}
-.icon-fan:before{content:'\f66f'}
-.icon-tornado:before{content:'\f670'}
-.icon-hangout:before{content:'\f671'}
-.icon-beaker:before{content:'\f672'}
-.icon-beakeralt:before{content:'\f673'}
-.icon-phonescreensize:before{content:'\f674'}
-.icon-tabletscreensize:before{content:'\f675'}
-.icon-notification:before{content:'\f676'}
-.icon-googleglass:before{content:'\f677'}
-.icon-pinterest:before{content:'\f678'}
-.icon-soundcloud:before{content:'\f679'}
-.icon-alarmclock:before{content:'\f67a'}
-.icon-addalarm:before{content:'\f67b'}
-.icon-deletealarm:before{content:'\f67c'}
-.icon-turnoffalarm:before{content:'\f67d'}
-.icon-snooze:before{content:'\f67e'}
-.icon-bringforward:before{content:'\f67f'}
-.icon-sendbackward:before{content:'\f680'}
-.icon-bringtofront:before{content:'\f681'}
-.icon-sendtoback:before{content:'\f682'}
-.icon-tectile:before{content:'\f683'}
-.icon-grave:before{content:'\f684'}
-.icon-gravetwo:before{content:'\f685'}
-.icon-gravethree:before{content:'\f686'}
-.icon-gravefour:before{content:'\f687'}
-.icon-textlayer:before{content:'\f688'}
-.icon-vectoralt:before{content:'\f689'}
-.icon-drmanhattan:before{content:'\f68a'}
-.icon-foursquarealt:before{content:'\f68b'}
-.icon-hashtag:before{content:'\f68c'}
-.icon-enteralt:before{content:'\f68d'}
-.icon-exitalt:before{content:'\f68e'}
-.icon-cartalt:before{content:'\f68f'}
-.icon-vaultthree:before{content:'\f690'}
-.icon-fatundo:before{content:'\f691'}
-.icon-fatredo:before{content:'\f692'}
-.icon-feedly:before{content:'\f693'}
-.icon-feedlyalt:before{content:'\f694'}
-.icon-squareheart:before{content:'\f695'}
-.icon-squarestar:before{content:'\f696'}
-.icon-squarecomment:before{content:'\f697'}
-.icon-squarelike:before{content:'\f698'}
-.icon-squarebookmark:before{content:'\f699'}
-.icon-squaresearch:before{content:'\f69a'}
-.icon-squaresettings:before{content:'\f69b'}
-.icon-squarevoice:before{content:'\f69c'}
-.icon-google:before{content:'\f69d'}
-.icon-emojigrinalt:before{content:'\f69e'}
-.icon-emojigrin:before{content:'\f69f'}
-.icon-constellation:before{content:'\f6a0'}
-.icon-emojisurprise:before{content:'\f6a1'}
-.icon-emojidead:before{content:'\f6a2'}
-.icon-emojiangry:before{content:'\f6a3'}
-.icon-emojidevil:before{content:'\f6a4'}
-.icon-emojiwink:before{content:'\f6a5'}
-.icon-moonorbit:before{content:'\f6a6'}
-.icon-emojismile:before{content:'\f6a7'}
-.icon-emojisorry:before{content:'\f6a8'}
-.icon-emojiconfused:before{content:'\f6a9'}
-.icon-emojisleep:before{content:'\f6aa'}
-.icon-emojicry:before{content:'\f6ab'}
-.icon-circlefork:before{content:'\f6ac'}
-.icon-circlespoon:before{content:'\f6ad'}
-.icon-circleknife:before{content:'\f6ae'}
-.icon-circlepencil:before{content:'\f6af'}
-.icon-circlehammer:before{content:'\f6b0'}
-.icon-circlescrewdriver:before{content:'\f6b1'}
-.icon-middlefinger:before{content:'\f6b2'}
-.icon-heavymetal:before{content:'\f6b3'}
-.icon-turnright:before{content:'\f6b4'}
-.icon-turnleft:before{content:'\f6b5'}
-.icon-vineapp:before{content:'\f6b6'}
-.icon-vineappalt:before{content:'\f6b7'}
-.icon-finance:before{content:'\f6b8'}
-.icon-survey:before{content:'\f6b9'}
-.icon-hangouts:before{content:'\f6ba'}
-.icon-square0:before{content:'\f6bb'}
-.icon-square1:before{content:'\f6bc'}
-.icon-square2:before{content:'\f6bd'}
-.icon-square3:before{content:'\f6be'}
-.icon-square4:before{content:'\f6bf'}
-.icon-square5:before{content:'\f6c0'}
-.icon-square6:before{content:'\f6c1'}
-.icon-square7:before{content:'\f6c2'}
-.icon-square8:before{content:'\f6c3'}
-.icon-square9:before{content:'\f6c4'}
-.icon-squarea:before{content:'\f6c5'}
-.icon-squareb:before{content:'\f6c6'}
-.icon-squarec:before{content:'\f6c7'}
-.icon-squared:before{content:'\f6c8'}
-.icon-squaree:before{content:'\f6c9'}
-.icon-squaref:before{content:'\f6ca'}
-.icon-squareg:before{content:'\f6cb'}
-.icon-squareh:before{content:'\f6cc'}
-.icon-squarei:before{content:'\f6cd'}
-.icon-squarej:before{content:'\f6ce'}
-.icon-squarek:before{content:'\f6cf'}
-.icon-squarel:before{content:'\f6d0'}
-.icon-squarem:before{content:'\f6d1'}
-.icon-squaren:before{content:'\f6d2'}
-.icon-squareo:before{content:'\f6d3'}
-.icon-squarep:before{content:'\f6d4'}
-.icon-squareq:before{content:'\f6d5'}
-.icon-squarer:before{content:'\f6d6'}
-.icon-squares:before{content:'\f6d7'}
-.icon-squaret:before{content:'\f6d8'}
-.icon-squareu:before{content:'\f6d9'}
-.icon-squarev:before{content:'\f6da'}
-.icon-squarew:before{content:'\f6db'}
-.icon-squarex:before{content:'\f6dc'}
-.icon-squarey:before{content:'\f6dd'}
-.icon-squarez:before{content:'\f6de'}
-.icon-shuttle:before{content:'\f6df'}
-.icon-meteor:before{content:'\f6e0'}
-.icon-galaxy:before{content:'\f6e1'}
-.icon-observatory:before{content:'\f6e2'}
-.icon-astronaut:before{content:'\f6e3'}
-.icon-asteroid:before{content:'\f6e4'}
-.icon-sunrise:before{content:'\f6e5'}
-.icon-sunset:before{content:'\f6e6'}
-.icon-tiderise:before{content:'\f6e7'}
-.icon-tidefall:before{content:'\f6e8'}
-.icon-mushroomcloud:before{content:'\f6e9'}
-.icon-galaxyalt:before{content:'\f6ea'}
-.icon-sputnik:before{content:'\f6eb'}
-.icon-sextant:before{content:'\f6ec'}
-.icon-spock:before{content:'\f6ed'}
-.icon-meteorite:before{content:'\f6ee'}
-.icon-deathstar:before{content:'\f6ef'}
-.icon-deathstarbulding:before{content:'\f6f0'}
-.icon-fallingstar:before{content:'\f6f1'}
-.icon-windmill:before{content:'\f6f2'}
-.icon-windmillalt:before{content:'\f6f3'}
-.icon-pumpjack:before{content:'\f6f4'}
-.icon-nuclearplant:before{content:'\f6f5'}
-.icon-solarpanel:before{content:'\f6f6'}
-.icon-barrel:before{content:'\f6f7'}
-.icon-canister:before{content:'\f6f8'}
-.icon-railtunnel:before{content:'\f6f9'}
-.icon-roadtunnel:before{content:'\f6fa'}
-.icon-pickaxe:before{content:'\f6fb'}
-.icon-cow:before{content:'\f6fc'}
-.icon-sheep:before{content:'\f6fd'}
-.icon-fountain:before{content:'\f6fe'}
-.icon-circlezero:before{content:'\f6ff'}
-.icon-circleone:before{content:'\f700'}
-.icon-circletwo:before{content:'\f701'}
-.icon-circlethree:before{content:'\f702'}
-.icon-circlefour:before{content:'\f703'}
-.icon-circlefive:before{content:'\f704'}
-.icon-circlesix:before{content:'\f705'}
-.icon-circleseven:before{content:'\f706'}
-.icon-circleeight:before{content:'\f707'}
-.icon-circlenine:before{content:'\f708'}
-.icon-circlea:before{content:'\f709'}
-.icon-circleb:before{content:'\f70a'}
-.icon-circlec:before{content:'\f70b'}
-.icon-circled:before{content:'\f70c'}
-.icon-circlee:before{content:'\f70d'}
-.icon-circlef:before{content:'\f70e'}
-.icon-circleg:before{content:'\f70f'}
-.icon-circleh:before{content:'\f710'}
-.icon-circlei:before{content:'\f711'}
-.icon-circlej:before{content:'\f712'}
-.icon-circlek:before{content:'\f713'}
-.icon-circlel:before{content:'\f714'}
-.icon-circlem:before{content:'\f715'}
-.icon-circlen:before{content:'\f716'}
-.icon-circleo:before{content:'\f717'}
-.icon-circlep:before{content:'\f718'}
-.icon-circleq:before{content:'\f719'}
-.icon-circler:before{content:'\f71a'}
-.icon-circles:before{content:'\f71b'}
-.icon-circlet:before{content:'\f71c'}
-.icon-circleu:before{content:'\f71d'}
-.icon-circlev:before{content:'\f71e'}
-.icon-circlew:before{content:'\f71f'}
-.icon-circlex:before{content:'\f720'}
-.icon-circley:before{content:'\f721'}
-.icon-circlez:before{content:'\f722'}
-.icon-creeper:before{content:'\f723'}
-.icon-minecraft:before{content:'\f724'}
-.icon-minecraftalt:before{content:'\f725'}
-.icon-pixelsword:before{content:'\f726'}
-.icon-pixelbroadsword:before{content:'\f727'}
-.icon-pixelwand:before{content:'\f728'}
-.icon-pixelpotion:before{content:'\f729'}
-.icon-pixelpotionalt:before{content:'\f72a'}
-.icon-pixelpickaxe:before{content:'\f72b'}
-.icon-pixelbow:before{content:'\f72c'}
-.icon-pixelarrow:before{content:'\f72d'}
-.icon-pixelaxe:before{content:'\f72e'}
-.icon-pixeldagger:before{content:'\f72f'}
-.icon-pixelbastardsword:before{content:'\f730'}
-.icon-pixellance:before{content:'\f731'}
-.icon-pixelbattleaxe:before{content:'\f732'}
-.icon-pixelshovel:before{content:'\f733'}
-.icon-pixelsphere:before{content:'\f734'}
-.icon-pixelelixir:before{content:'\f735'}
-.icon-pixelchest:before{content:'\f736'}
-.icon-pixelshield:before{content:'\f737'}
-.icon-pixelheart:before{content:'\f738'}
-.icon-rudder:before{content:'\f739'}
-.icon-folderalt:before{content:'\f73a'}
-.icon-removefolderalt:before{content:'\f73b'}
-.icon-addfolderalt:before{content:'\f73c'}
-.icon-deletefolderalt:before{content:'\f73d'}
-.icon-openfolderalt:before{content:'\f73e'}
-.icon-clipboardalt:before{content:'\f73f'}
-.icon-pastealt:before{content:'\f740'}
-.icon-loadingflowccw:before{content:'\f741'}
-.icon-loadingflowcw:before{content:'\f742'}
-.icon-code:before{content:'\f743'}
-.icon-cloveralt:before{content:'\f744'}
-.icon-lips:before{content:'\f745'}
-.icon-kiss:before{content:'\f746'}
-.icon-manualshift:before{content:'\f747'}
-.icon-simcardthree:before{content:'\f748'}
-.icon-parthenon:before{content:'\f749'}
-.icon-addcomment:before{content:'\f74a'}
-.icon-deletecomment:before{content:'\f74b'}
-.icon-gender:before{content:'\f74c'}
-.icon-callalt:before{content:'\f74d'}
-.icon-outgoingcallalt:before{content:'\f74e'}
-.icon-incomingcallalt:before{content:'\f74f'}
-.icon-missedcallalt:before{content:'\f750'}
-.icon-export:before{content:'\f751'}
-.icon-import:before{content:'\f752'}
-.icon-cherryalt:before{content:'\f753'}
-.icon-panties:before{content:'\f754'}
-.icon-kimai:before{content:'\f755'}
-.icon-livejournal:before{content:'\f756'}
-.icon-livejournalalt:before{content:'\f757'}
-.icon-tagged:before{content:'\f758'}
-.icon-temple:before{content:'\f759'}
-.icon-mayanpyramid:before{content:'\f75a'}
-.icon-egyptpyramid:before{content:'\f75b'}
-.icon-tampermonkey:before{content:'\f75c'}
-.icon-pushbullet:before{content:'\f75d'}
-.icon-currents:before{content:'\f75e'}
-.icon-communitysmall:before{content:'\f75f'}
-.icon-squaregithub:before{content:'\f760'}
-.icon-projectfork:before{content:'\f761'}
-.icon-projectmerge:before{content:'\f762'}
-.icon-projectcompare:before{content:'\f763'}
-.icon-history:before{content:'\f764'}
-.icon-notebook:before{content:'\f765'}
-.icon-issue:before{content:'\f766'}
-.icon-issueclosed:before{content:'\f767'}
-.icon-issuereopened:before{content:'\f768'}
-.icon-rubyalt:before{content:'\f769'}
-.icon-lighton:before{content:'\f76a'}
-.icon-lightoff:before{content:'\f76b'}
-.icon-bellalt:before{content:'\f76c'}
-.icon-versions:before{content:'\f777'}
-.icon-twog:before{content:'\f76e'}
-.icon-threeg:before{content:'\f76f'}
-.icon-fourg:before{content:'\f770'}
-.icon-gpsalt:before{content:'\f771'}
-.icon-circleloaderfull:before{content:'\f772'}
-.icon-circleloaderseven:before{content:'\f773'}
-.icon-circleloadersix:before{content:'\f774'}
-.icon-circleloaderfive:before{content:'\f775'}
-.icon-circleloaderfour:before{content:'\f776'}
-.icon-circleloaderthree:before{content:'\f777'}
-.icon-circleloadertwo:before{content:'\f778'}
-.icon-circleloaderone:before{content:'\f779'}
-.icon-circleloaderempty:before{content:'\f77a'}
-.icon-whatsapp:before{content:'\f77b'}
-.icon-whatsappalt:before{content:'\f77c'}
-.icon-viber:before{content:'\f77d'}
-.icon-squareviber:before{content:'\f77e'}
-.icon-teamviewer:before{content:'\f77f'}
-.icon-tunein:before{content:'\f780'}
-.icon-tuneinalt:before{content:'\f781'}
-.icon-weightscale:before{content:'\f782'}
-.icon-boxing:before{content:'\f783'}
-.icon-speedalt:before{content:'\f784'}
-.icon-scriptalt:before{content:'\f785'}
-.icon-splitthree:before{content:'\f786'}
-.icon-mergethree:before{content:'\f787'}
-.icon-layersthree:before{content:'\f788'}
-.icon-mutemic:before{content:'\f789'}
-.icon-zerply:before{content:'\f78a'}
-.icon-circlegoogleplus:before{content:'\f78b'}
-.icon-circletwitter:before{content:'\f78c'}
-.icon-circlefacebook:before{content:'\f78d'}
-.icon-circleyahoo:before{content:'\f78e'}
-.icon-circlegithub:before{content:'\f78f'}
-.icon-forumsalt:before{content:'\f790'}
-.icon-circlepath:before{content:'\f791'}
-.icon-circlevimeo:before{content:'\f792'}
-.icon-circlevine:before{content:'\f793'}
-.icon-instagramtwo:before{content:'\f794'}
-.icon-instagramthree:before{content:'\f795'}
-.icon-flickrthree:before{content:'\f796'}
-.icon-quora:before{content:'\f797'}
-.icon-squarequora:before{content:'\f798'}
-.icon-circlequora:before{content:'\f799'}
-.icon-picasa:before{content:'\f79a'}
-.icon-branch:before{content:'\f79b'}
-.icon-ingress:before{content:'\f79c'}
-.icon-squarezerply:before{content:'\f79d'}
-.icon-circlezerply:before{content:'\f79e'}
-.icon-squarevimeo:before{content:'\f79f'}
-.icon-squaretwitter:before{content:'\f7a0'}
-.icon-brightnessalt:before{content:'\f7a1'}
-.icon-brightnessalthalf:before{content:'\f7a2'}
-.icon-brightnessaltfull:before{content:'\f7a3'}
-.icon-brightnessaltauto:before{content:'\f7a4'}
-.icon-shirtbuttonthree:before{content:'\f7a5'}
-.icon-openshare:before{content:'\f7a6'}
-.icon-copyapp:before{content:'\f7a7'}
-.icon-bowl:before{content:'\f7a8'}
-.icon-cloudalt:before{content:'\f7a9'}
-.icon-cloudaltdownload:before{content:'\f7aa'}
-.icon-cloudaltupload:before{content:'\f7ab'}
-.icon-cloudaltsync:before{content:'\f7ac'}
-.icon-cloudaltprivate:before{content:'\f7ad'}
-.icon-flipboard:before{content:'\f7ae'}
-.icon-octoloaderempty:before{content:'\f7af'}
-.icon-octoloaderone:before{content:'\f7b0'}
-.icon-octoloadertwo:before{content:'\f7b1'}
-.icon-octoloaderthree:before{content:'\f7b2'}
-.icon-octoloaderfour:before{content:'\f7b3'}
-.icon-octoloaderfive:before{content:'\f7b4'}
-.icon-octoloadersix:before{content:'\f7b5'}
-.icon-octoloaderseven:before{content:'\f7b6'}
-.icon-octoloaderfull:before{content:'\f7b7'}
-.icon-selectionsymbol:before{content:'\f7b8'}
-.icon-infinityalt:before{content:'\f7b9'}
-.icon-pullrequest:before{content:'\f7ba'}
-.icon-projectforkdelete:before{content:'\f7bb'}
-.icon-projectforkprivate:before{content:'\f7bc'}
-.icon-commit:before{content:'\f7bd'}
-.icon-htmlfile:before{content:'\f7be'}
-.icon-pushalt:before{content:'\f7bf'}
-.icon-pullalt:before{content:'\f7c0'}
-.icon-photonineframes:before{content:'\f7c1'}
-.icon-wetfloor:before{content:'\f7c2'}
-.icon-instagramfour:before{content:'\f7c3'}
-.icon-circleinstagram:before{content:'\f7c4'}
-.icon-videocamerathree:before{content:'\f7c5'}
-.icon-subtitles:before{content:'\f7c6'}
-.icon-subtitlesoff:before{content:'\f7c7'}
-.icon-compress:before{content:'\f7c8'}
-.icon-baby:before{content:'\f7c9'}
-.icon-ducky:before{content:'\f7ca'}
-.icon-handswipe:before{content:'\f7cb'}
-.icon-swipeup:before{content:'\f7cc'}
-.icon-swipedown:before{content:'\f7cd'}
-.icon-twofingerswipedown:before{content:'\f7ce'}
-.icon-twofingerswipeup:before{content:'\f7cf'}
-.icon-doubletap:before{content:'\f7d0'}
-.icon-dribbblealt:before{content:'\f7d1'}
-.icon-circlecallmissed:before{content:'\f7d2'}
-.icon-circlecallincoming:before{content:'\f7d3'}
-.icon-circlecalloutgoing:before{content:'\f7d4'}
-.icon-circledownload:before{content:'\f7d5'}
-.icon-circleupload:before{content:'\f7d6'}
-.icon-minismile:before{content:'\f7d7'}
-.icon-minisad:before{content:'\f7d8'}
-.icon-minilaugh:before{content:'\f7d9'}
-.icon-minigrin:before{content:'\f7da'}
-.icon-miniangry:before{content:'\f7db'}
-.icon-minitongue:before{content:'\f7dc'}
-.icon-minitonguealt:before{content:'\f7dd'}
-.icon-miniwink:before{content:'\f7de'}
-.icon-minitonguewink:before{content:'\f7df'}
-.icon-miniconfused:before{content:'\f7e0'}
-.icon-soundright:before{content:'\f7e1'}
-.icon-soundleft:before{content:'\f7e2'}
-.icon-savetodrive:before{content:'\f7e3'}
-.icon-layerorderup:before{content:'\f7e4'}
-.icon-layerorderdown:before{content:'\f7e5'}
-.icon-layerorder:before{content:'\f7e6'}
-.icon-circledribbble:before{content:'\f7e7'}
-.icon-squaredribbble:before{content:'\f7e8'}
-.icon-handexpand:before{content:'\f7e9'}
-.icon-handpinch:before{content:'\f7ea'}
-.icon-fontserif:before{content:'\f7eb'}
-.icon-fontsansserif:before{content:'\f7ec'}
-.icon-fontrounded:before{content:'\f7ed'}
-.icon-fonthandwriting:before{content:'\f7ee'}
-.icon-fonttypewriter:before{content:'\f7ef'}
-.icon-fontcomic:before{content:'\f7f0'}
-.icon-fontcaligraphy:before{content:'\f7f1'}
-.icon-fontgothic:before{content:'\f7f2'}
-.icon-fontstencil:before{content:'\f7f3'}
diff --git a/public/browse/karma.conf.js b/public/browse/karma.conf.js
deleted file mode 100755
index 44bb29f1a..000000000
--- a/public/browse/karma.conf.js
+++ /dev/null
@@ -1,33 +0,0 @@
-module.exports = function(config){
- config.set({
-
- basePath : './',
-
- files : [
- 'app/bower_components/angular/angular.js',
- 'app/bower_components/angular-route/angular-route.js',
- 'app/bower_components/angular-mocks/angular-mocks.js',
- 'app/components/**/*.js',
- 'app/view*/**/*.js'
- ],
-
- autoWatch : true,
-
- frameworks: ['jasmine'],
-
- browsers : ['Chrome'],
-
- plugins : [
- 'karma-chrome-launcher',
- 'karma-firefox-launcher',
- 'karma-jasmine',
- 'karma-junit-reporter'
- ],
-
- junitReporter : {
- outputFile: 'test_out/unit.xml',
- suite: 'unit'
- }
-
- });
-};
diff --git a/public/browse/lib/angular-animate/.bower.json b/public/browse/lib/angular-animate/.bower.json
deleted file mode 100644
index 493bf5609..000000000
--- a/public/browse/lib/angular-animate/.bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "angular-animate",
- "version": "1.3.5",
- "main": "./angular-animate.js",
- "ignore": [],
- "dependencies": {
- "angular": "1.3.5"
- },
- "homepage": "https://github.com/angular/bower-angular-animate",
- "_release": "1.3.5",
- "_resolution": {
- "type": "version",
- "tag": "v1.3.5",
- "commit": "f1ce791ecb58c64af1caac6253f93ecf3e2bf203"
- },
- "_source": "git://github.com/angular/bower-angular-animate.git",
- "_target": "1.3.x",
- "_originalSource": "angular-animate"
-}
\ No newline at end of file
diff --git a/public/browse/lib/angular-animate/README.md b/public/browse/lib/angular-animate/README.md
deleted file mode 100644
index 930b5dcc5..000000000
--- a/public/browse/lib/angular-animate/README.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# packaged angular-animate
-
-This repo is for distribution on `npm` and `bower`. The source for this module is in the
-[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngAnimate).
-Please file issues and pull requests against that repo.
-
-## Install
-
-You can install this package either with `npm` or with `bower`.
-
-### npm
-
-```shell
-npm install angular-animate
-```
-
-Add a `
-```
-
-Then add `ngAnimate` as a dependency for your app:
-
-```javascript
-angular.module('myApp', ['ngAnimate']);
-```
-
-Note that this package is not in CommonJS format, so doing `require('angular-animate')` will
-return `undefined`.
-
-### bower
-
-```shell
-bower install angular-animate
-```
-
-Then add a `
-```
-
-Then add `ngAnimate` as a dependency for your app:
-
-```javascript
-angular.module('myApp', ['ngAnimate']);
-```
-
-## Documentation
-
-Documentation is available on the
-[AngularJS docs site](http://docs.angularjs.org/api/ngAnimate).
-
-## License
-
-The MIT License
-
-Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public/browse/lib/angular-animate/angular-animate.js b/public/browse/lib/angular-animate/angular-animate.js
deleted file mode 100644
index 761d622ea..000000000
--- a/public/browse/lib/angular-animate/angular-animate.js
+++ /dev/null
@@ -1,2136 +0,0 @@
-/**
- * @license AngularJS v1.3.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/* jshint maxlen: false */
-
-/**
- * @ngdoc module
- * @name ngAnimate
- * @description
- *
- * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.
- *
- *
- *
- * # Usage
- *
- * To see animations in action, all that is required is to define the appropriate CSS classes
- * or to register a JavaScript animation via the myModule.animation() function. The directives that support animation automatically are:
- * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation
- * by using the `$animate` service.
- *
- * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:
- *
- * | Directive | Supported Animations |
- * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
- * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
- * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
- * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
- * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
- * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
- * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
- * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
- * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
- * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
- * | {@link module:ngMessages#animations ngMessage} | enter and leave |
- *
- * You can find out more information about animations upon visiting each directive page.
- *
- * Below is an example of how to apply animations to a directive that supports animation hooks:
- *
- * ```html
- *
- *
- *
- *
- * ```
- *
- * Keep in mind that, by default, if an animation is running, any child elements cannot be animated
- * until the parent element's animation has completed. This blocking feature can be overridden by
- * placing the `ng-animate-children` attribute on a parent container tag.
- *
- * ```html
- *
- *
- *
- * ...
- *
- *
- *
- * ```
- *
- * When the `on` expression value changes and an animation is triggered then each of the elements within
- * will all animate without the block being applied to child elements.
- *
- * ## Are animations run when the application starts?
- * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid
- * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work,
- * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering
- * layout changes in the application will trigger animations as normal.
- *
- * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular
- * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests
- * are complete.
- *
- * ## CSS-defined Animations
- * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes
- * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported
- * and can be used to play along with this naming structure.
- *
- * The following code below demonstrates how to perform animations using **CSS transitions** with Angular:
- *
- * ```html
- *
- *
- *
- *
- *
- * ```
- *
- * The following code below demonstrates how to perform animations using **CSS animations** with Angular:
- *
- * ```html
- *
- *
- *
- *
- *
- * ```
- *
- * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing.
- *
- * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add
- * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically
- * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be
- * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end
- * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element
- * has no CSS transition/animation classes applied to it.
- *
- * ### Structural transition animations
- *
- * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition
- * value to force the browser into rendering the styles defined in the setup (.ng-enter, .ng-leave
- * or .ng-move) class. This means that any active transition animations operating on the element
- * will be cut off to make way for the enter, leave or move animation.
- *
- * ### Class-based transition animations
- *
- * Class-based transitions refer to transition animations that are triggered when a CSS class is
- * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,
- * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).
- * They are different when compared to structural animations since they **do not cancel existing
- * animations** nor do they **block successive transitions** from rendering on the same element.
- * This distinction allows for **multiple class-based transitions** to be performed on the same element.
- *
- * In addition to ngAnimate supporting the default (natural) functionality of class-based transition
- * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the
- * developer in further styling the element throughout the transition animation. Earlier versions
- * of ngAnimate may have caused natural CSS transitions to break and not render properly due to
- * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class
- * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of
- * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS
- * class transitions are compatible with ngAnimate.
- *
- * There is, however, one special case when dealing with class-based transitions in ngAnimate.
- * When rendering class-based transitions that make use of the setup and active CSS classes
- * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define
- * the transition value **on the active CSS class** and not the setup class.
- *
- * ```css
- * .fade-add {
- * /* remember to place a 0s transition here
- * to ensure that the styles are applied instantly
- * even if the element already has a transition style */
- * transition:0s linear all;
- *
- * /* starting CSS styles */
- * opacity:1;
- * }
- * .fade-add.fade-add-active {
- * /* this will be the length of the animation */
- * transition:1s linear all;
- * opacity:0;
- * }
- * ```
- *
- * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it
- * has a duration of zero. This may not be required, however, incase the browser is unable to render
- * the styling present in this CSS class instantly then it could be that the browser is attempting
- * to perform an unnecessary transition.
- *
- * This workaround, however, does not apply to standard class-based transitions that are rendered
- * when a CSS class containing a transition is applied to an element:
- *
- * ```css
- * /* this works as expected */
- * .fade {
- * transition:1s linear all;
- * opacity:0;
- * }
- * ```
- *
- * Please keep this in mind when coding the CSS markup that will be used within class-based transitions.
- * Also, try not to mix the two class-based animation flavors together since the CSS code may become
- * overly complex.
- *
- *
- * ### Preventing Collisions With Third Party Libraries
- *
- * Some third-party frameworks place animation duration defaults across many element or className
- * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
- * is expecting actual animations on these elements and has to wait for their completion.
- *
- * You can prevent this unwanted behavior by using a prefix on all your animation classes:
- *
- * ```css
- * /* prefixed with animate- */
- * .animate-fade-add.animate-fade-add-active {
- * transition:1s linear all;
- * opacity:0;
- * }
- * ```
- *
- * You then configure `$animate` to enforce this prefix:
- *
- * ```js
- * $animateProvider.classNameFilter(/animate-/);
- * ```
- *
- *
- * ### CSS Staggering Animations
- * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
- * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
- * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
- * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
- * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
- *
- * ```css
- * .my-animation.ng-enter {
- * /* standard transition code */
- * -webkit-transition: 1s linear all;
- * transition: 1s linear all;
- * opacity:0;
- * }
- * .my-animation.ng-enter-stagger {
- * /* this will have a 100ms delay between each successive leave animation */
- * -webkit-transition-delay: 0.1s;
- * transition-delay: 0.1s;
- *
- * /* in case the stagger doesn't work then these two values
- * must be set to 0 to avoid an accidental CSS inheritance */
- * -webkit-transition-duration: 0s;
- * transition-duration: 0s;
- * }
- * .my-animation.ng-enter.ng-enter-active {
- * /* standard transition styles */
- * opacity:1;
- * }
- * ```
- *
- * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
- * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
- * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
- * will also be reset if more than 10ms has passed after the last animation has been fired.
- *
- * The following code will issue the **ng-leave-stagger** event on the element provided:
- *
- * ```js
- * var kids = parent.children();
- *
- * $animate.leave(kids[0]); //stagger index=0
- * $animate.leave(kids[1]); //stagger index=1
- * $animate.leave(kids[2]); //stagger index=2
- * $animate.leave(kids[3]); //stagger index=3
- * $animate.leave(kids[4]); //stagger index=4
- *
- * $timeout(function() {
- * //stagger has reset itself
- * $animate.leave(kids[5]); //stagger index=0
- * $animate.leave(kids[6]); //stagger index=1
- * }, 100, false);
- * ```
- *
- * Stagger animations are currently only supported within CSS-defined animations.
- *
- * ## JavaScript-defined Animations
- * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not
- * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module.
- *
- * ```js
- * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.
- * var ngModule = angular.module('YourApp', ['ngAnimate']);
- * ngModule.animation('.my-crazy-animation', function() {
- * return {
- * enter: function(element, done) {
- * //run the animation here and call done when the animation is complete
- * return function(cancelled) {
- * //this (optional) function will be called when the animation
- * //completes or when the animation is cancelled (the cancelled
- * //flag will be set to true if cancelled).
- * };
- * },
- * leave: function(element, done) { },
- * move: function(element, done) { },
- *
- * //animation that can be triggered before the class is added
- * beforeAddClass: function(element, className, done) { },
- *
- * //animation that can be triggered after the class is added
- * addClass: function(element, className, done) { },
- *
- * //animation that can be triggered before the class is removed
- * beforeRemoveClass: function(element, className, done) { },
- *
- * //animation that can be triggered after the class is removed
- * removeClass: function(element, className, done) { }
- * };
- * });
- * ```
- *
- * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run
- * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits
- * the element's CSS class attribute value and then run the matching animation event function (if found).
- * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will
- * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported).
- *
- * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned.
- * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run,
- * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation
- * or transition code that is defined via a stylesheet).
- *
- *
- * ### Applying Directive-specific Styles to an Animation
- * In some cases a directive or service may want to provide `$animate` with extra details that the animation will
- * include into its animation. Let's say for example we wanted to render an animation that animates an element
- * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click
- * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function
- * call to `$animate.addClass`.
- *
- * ```js
- * canvas.on('click', function(e) {
- * $animate.addClass(element, 'on', {
- * to: {
- * left : e.client.x + 'px',
- * top : e.client.y + 'px'
- * }
- * }):
- * });
- * ```
- *
- * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will
- * also include and transition the styling of the `left` and `top` properties into its running animation. If we want
- * to provide some starting animation values then we can do so by placing the starting animations styles into an object
- * called `from` in the same object as the `to` animations.
- *
- * ```js
- * canvas.on('click', function(e) {
- * $animate.addClass(element, 'on', {
- * from: {
- * position: 'absolute',
- * left: '0px',
- * top: '0px'
- * },
- * to: {
- * left : e.client.x + 'px',
- * top : e.client.y + 'px'
- * }
- * }):
- * });
- * ```
- *
- * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the
- * element. If `ngAnimate` is not present then the styles will be applied immediately.
- *
- */
-
-angular.module('ngAnimate', ['ng'])
-
- /**
- * @ngdoc provider
- * @name $animateProvider
- * @description
- *
- * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module.
- * When an animation is triggered, the $animate service will query the $animate service to find any animations that match
- * the provided name value.
- *
- * Requires the {@link ngAnimate `ngAnimate`} module to be installed.
- *
- * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
- *
- */
- .directive('ngAnimateChildren', function() {
- var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
- return function(scope, element, attrs) {
- var val = attrs.ngAnimateChildren;
- if (angular.isString(val) && val.length === 0) { //empty attribute
- element.data(NG_ANIMATE_CHILDREN, true);
- } else {
- scope.$watch(val, function(value) {
- element.data(NG_ANIMATE_CHILDREN, !!value);
- });
- }
- };
- })
-
- //this private service is only used within CSS-enabled animations
- //IE8 + IE9 do not support rAF natively, but that is fine since they
- //also don't support transitions and keyframes which means that the code
- //below will never be used by the two browsers.
- .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {
- var bod = $document[0].body;
- return function(fn) {
- //the returned function acts as the cancellation function
- return $$rAF(function() {
- //the line below will force the browser to perform a repaint
- //so that all the animated elements within the animation frame
- //will be properly updated and drawn on screen. This is
- //required to perform multi-class CSS based animations with
- //Firefox. DO NOT REMOVE THIS LINE.
- var a = bod.offsetWidth + 1;
- fn();
- });
- };
- }])
-
- .config(['$provide', '$animateProvider', function($provide, $animateProvider) {
- var noop = angular.noop;
- var forEach = angular.forEach;
- var selectors = $animateProvider.$$selectors;
- var isArray = angular.isArray;
- var isString = angular.isString;
- var isObject = angular.isObject;
-
- var ELEMENT_NODE = 1;
- var NG_ANIMATE_STATE = '$$ngAnimateState';
- var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
- var NG_ANIMATE_CLASS_NAME = 'ng-animate';
- var rootAnimateState = {running: true};
-
- function extractElementNode(element) {
- for (var i = 0; i < element.length; i++) {
- var elm = element[i];
- if (elm.nodeType == ELEMENT_NODE) {
- return elm;
- }
- }
- }
-
- function prepareElement(element) {
- return element && angular.element(element);
- }
-
- function stripCommentsFromElement(element) {
- return angular.element(extractElementNode(element));
- }
-
- function isMatchingElement(elm1, elm2) {
- return extractElementNode(elm1) == extractElementNode(elm2);
- }
-
- $provide.decorator('$animate',
- ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest',
- function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest) {
-
- $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);
-
- // Wait until all directive and route-related templates are downloaded and
- // compiled. The $templateRequest.totalPendingRequests variable keeps track of
- // all of the remote templates being currently downloaded. If there are no
- // templates currently downloading then the watcher will still fire anyway.
- var deregisterWatch = $rootScope.$watch(
- function() { return $templateRequest.totalPendingRequests; },
- function(val, oldVal) {
- if (val !== 0) return;
- deregisterWatch();
-
- // Now that all templates have been downloaded, $animate will wait until
- // the post digest queue is empty before enabling animations. By having two
- // calls to $postDigest calls we can ensure that the flag is enabled at the
- // very end of the post digest queue. Since all of the animations in $animate
- // use $postDigest, it's important that the code below executes at the end.
- // This basically means that the page is fully downloaded and compiled before
- // any animations are triggered.
- $rootScope.$$postDigest(function() {
- $rootScope.$$postDigest(function() {
- rootAnimateState.running = false;
- });
- });
- }
- );
-
- var globalAnimationCounter = 0;
- var classNameFilter = $animateProvider.classNameFilter();
- var isAnimatableClassName = !classNameFilter
- ? function() { return true; }
- : function(className) {
- return classNameFilter.test(className);
- };
-
- function classBasedAnimationsBlocked(element, setter) {
- var data = element.data(NG_ANIMATE_STATE) || {};
- if (setter) {
- data.running = true;
- data.structural = true;
- element.data(NG_ANIMATE_STATE, data);
- }
- return data.disabled || (data.running && data.structural);
- }
-
- function runAnimationPostDigest(fn) {
- var cancelFn, defer = $$q.defer();
- defer.promise.$$cancelFn = function() {
- cancelFn && cancelFn();
- };
- $rootScope.$$postDigest(function() {
- cancelFn = fn(function() {
- defer.resolve();
- });
- });
- return defer.promise;
- }
-
- function parseAnimateOptions(options) {
- // some plugin code may still be passing in the callback
- // function as the last param for the $animate methods so
- // it's best to only allow string or array values for now
- if (isObject(options)) {
- if (options.tempClasses && isString(options.tempClasses)) {
- options.tempClasses = options.tempClasses.split(/\s+/);
- }
- return options;
- }
- }
-
- function resolveElementClasses(element, cache, runningAnimations) {
- runningAnimations = runningAnimations || {};
-
- var lookup = {};
- forEach(runningAnimations, function(data, selector) {
- forEach(selector.split(' '), function(s) {
- lookup[s]=data;
- });
- });
-
- var hasClasses = Object.create(null);
- forEach((element.attr('class') || '').split(/\s+/), function(className) {
- hasClasses[className] = true;
- });
-
- var toAdd = [], toRemove = [];
- forEach((cache && cache.classes) || [], function(status, className) {
- var hasClass = hasClasses[className];
- var matchingAnimation = lookup[className] || {};
-
- // When addClass and removeClass is called then $animate will check to
- // see if addClass and removeClass cancel each other out. When there are
- // more calls to removeClass than addClass then the count falls below 0
- // and then the removeClass animation will be allowed. Otherwise if the
- // count is above 0 then that means an addClass animation will commence.
- // Once an animation is allowed then the code will also check to see if
- // there exists any on-going animation that is already adding or remvoing
- // the matching CSS class.
- if (status === false) {
- //does it have the class or will it have the class
- if (hasClass || matchingAnimation.event == 'addClass') {
- toRemove.push(className);
- }
- } else if (status === true) {
- //is the class missing or will it be removed?
- if (!hasClass || matchingAnimation.event == 'removeClass') {
- toAdd.push(className);
- }
- }
- });
-
- return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')];
- }
-
- function lookup(name) {
- if (name) {
- var matches = [],
- flagMap = {},
- classes = name.substr(1).split('.');
-
- //the empty string value is the default animation
- //operation which performs CSS transition and keyframe
- //animations sniffing. This is always included for each
- //element animation procedure if the browser supports
- //transitions and/or keyframe animations. The default
- //animation is added to the top of the list to prevent
- //any previous animations from affecting the element styling
- //prior to the element being animated.
- if ($sniffer.transitions || $sniffer.animations) {
- matches.push($injector.get(selectors['']));
- }
-
- for (var i=0; i < classes.length; i++) {
- var klass = classes[i],
- selectorFactoryName = selectors[klass];
- if (selectorFactoryName && !flagMap[klass]) {
- matches.push($injector.get(selectorFactoryName));
- flagMap[klass] = true;
- }
- }
- return matches;
- }
- }
-
- function animationRunner(element, animationEvent, className, options) {
- //transcluded directives may sometimes fire an animation using only comment nodes
- //best to catch this early on to prevent any animation operations from occurring
- var node = element[0];
- if (!node) {
- return;
- }
-
- if (options) {
- options.to = options.to || {};
- options.from = options.from || {};
- }
-
- var classNameAdd;
- var classNameRemove;
- if (isArray(className)) {
- classNameAdd = className[0];
- classNameRemove = className[1];
- if (!classNameAdd) {
- className = classNameRemove;
- animationEvent = 'removeClass';
- } else if (!classNameRemove) {
- className = classNameAdd;
- animationEvent = 'addClass';
- } else {
- className = classNameAdd + ' ' + classNameRemove;
- }
- }
-
- var isSetClassOperation = animationEvent == 'setClass';
- var isClassBased = isSetClassOperation
- || animationEvent == 'addClass'
- || animationEvent == 'removeClass'
- || animationEvent == 'animate';
-
- var currentClassName = element.attr('class');
- var classes = currentClassName + ' ' + className;
- if (!isAnimatableClassName(classes)) {
- return;
- }
-
- var beforeComplete = noop,
- beforeCancel = [],
- before = [],
- afterComplete = noop,
- afterCancel = [],
- after = [];
-
- var animationLookup = (' ' + classes).replace(/\s+/g,'.');
- forEach(lookup(animationLookup), function(animationFactory) {
- var created = registerAnimation(animationFactory, animationEvent);
- if (!created && isSetClassOperation) {
- registerAnimation(animationFactory, 'addClass');
- registerAnimation(animationFactory, 'removeClass');
- }
- });
-
- function registerAnimation(animationFactory, event) {
- var afterFn = animationFactory[event];
- var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)];
- if (afterFn || beforeFn) {
- if (event == 'leave') {
- beforeFn = afterFn;
- //when set as null then animation knows to skip this phase
- afterFn = null;
- }
- after.push({
- event: event, fn: afterFn
- });
- before.push({
- event: event, fn: beforeFn
- });
- return true;
- }
- }
-
- function run(fns, cancellations, allCompleteFn) {
- var animations = [];
- forEach(fns, function(animation) {
- animation.fn && animations.push(animation);
- });
-
- var count = 0;
- function afterAnimationComplete(index) {
- if (cancellations) {
- (cancellations[index] || noop)();
- if (++count < animations.length) return;
- cancellations = null;
- }
- allCompleteFn();
- }
-
- //The code below adds directly to the array in order to work with
- //both sync and async animations. Sync animations are when the done()
- //operation is called right away. DO NOT REFACTOR!
- forEach(animations, function(animation, index) {
- var progress = function() {
- afterAnimationComplete(index);
- };
- switch (animation.event) {
- case 'setClass':
- cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options));
- break;
- case 'animate':
- cancellations.push(animation.fn(element, className, options.from, options.to, progress));
- break;
- case 'addClass':
- cancellations.push(animation.fn(element, classNameAdd || className, progress, options));
- break;
- case 'removeClass':
- cancellations.push(animation.fn(element, classNameRemove || className, progress, options));
- break;
- default:
- cancellations.push(animation.fn(element, progress, options));
- break;
- }
- });
-
- if (cancellations && cancellations.length === 0) {
- allCompleteFn();
- }
- }
-
- return {
- node: node,
- event: animationEvent,
- className: className,
- isClassBased: isClassBased,
- isSetClassOperation: isSetClassOperation,
- applyStyles: function() {
- if (options) {
- element.css(angular.extend(options.from || {}, options.to || {}));
- }
- },
- before: function(allCompleteFn) {
- beforeComplete = allCompleteFn;
- run(before, beforeCancel, function() {
- beforeComplete = noop;
- allCompleteFn();
- });
- },
- after: function(allCompleteFn) {
- afterComplete = allCompleteFn;
- run(after, afterCancel, function() {
- afterComplete = noop;
- allCompleteFn();
- });
- },
- cancel: function() {
- if (beforeCancel) {
- forEach(beforeCancel, function(cancelFn) {
- (cancelFn || noop)(true);
- });
- beforeComplete(true);
- }
- if (afterCancel) {
- forEach(afterCancel, function(cancelFn) {
- (cancelFn || noop)(true);
- });
- afterComplete(true);
- }
- }
- };
- }
-
- /**
- * @ngdoc service
- * @name $animate
- * @kind object
- *
- * @description
- * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations.
- * When any of these operations are run, the $animate service
- * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object)
- * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run.
- *
- * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives
- * will work out of the box without any extra configuration.
- *
- * Requires the {@link ngAnimate `ngAnimate`} module to be installed.
- *
- * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
- * ## Callback Promises
- * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The
- * promise itself is then resolved once the animation has completed itself, has been cancelled or has been
- * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still
- * call the resolve function of the animation.)
- *
- * ```js
- * $animate.enter(element, container).then(function() {
- * //...this is called once the animation is complete...
- * });
- * ```
- *
- * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope,
- * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using
- * `$scope.$apply(...)`;
- *
- * ```js
- * $animate.leave(element).then(function() {
- * $scope.$apply(function() {
- * $location.path('/new-page');
- * });
- * });
- * ```
- *
- * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided
- * promise that was returned when the animation was started.
- *
- * ```js
- * var promise = $animate.addClass(element, 'super-long-animation').then(function() {
- * //this will still be called even if cancelled
- * });
- *
- * element.on('click', function() {
- * //tooo lazy to wait for the animation to end
- * $animate.cancel(promise);
- * });
- * ```
- *
- * (Keep in mind that the promise cancellation is unique to `$animate` since promises in
- * general cannot be cancelled.)
- *
- */
- return {
- /**
- * @ngdoc method
- * @name $animate#animate
- * @kind function
- *
- * @description
- * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element.
- * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation
- * will take on the provided styles. For example, if a transition animation is set for the given className then the
- * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is
- * detected then the provided styles will be given in as function paramters.
- *
- * ```js
- * ngModule.animation('.my-inline-animation', function() {
- * return {
- * animate : function(element, className, from, to, done) {
- * //styles
- * }
- * }
- * });
- * ```
- *
- * Below is a breakdown of each step that occurs during the `animate` animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
- * | 1. $animate.animate(...) is called | class="my-animation" |
- * | 2. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
- * | 3. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
- * | 4. the className class value is added to the element | class="my-animation ng-animate className" |
- * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate className" |
- * | 6. $animate blocks all CSS transitions on the element to ensure the .className class styling is applied right away| class="my-animation ng-animate className" |
- * | 7. $animate applies the provided collection of `from` CSS styles to the element | class="my-animation ng-animate className" |
- * | 8. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate className" |
- * | 9. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate className" |
- * | 10. the className-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate className className-active" |
- * | 11. $animate applies the collection of `to` CSS styles to the element which are then handled by the transition | class="my-animation ng-animate className className-active" |
- * | 12. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate className className-active" |
- * | 13. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
- * | 14. The returned promise is resolved. | class="my-animation" |
- *
- * @param {DOMElement} element the element that will be the focus of the enter animation
- * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation
- * @param {object} to a collection of CSS styles that the element will animate towards
- * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`)
- * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- animate: function(element, from, to, className, options) {
- className = className || 'ng-inline-animate';
- options = parseAnimateOptions(options) || {};
- options.from = to ? from : null;
- options.to = to ? to : from;
-
- return runAnimationPostDigest(function(done) {
- return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done);
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#enter
- * @kind function
- *
- * @description
- * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once
- * the animation is started, the following CSS classes will be present on the element for the duration of the animation:
- *
- * Below is a breakdown of each step that occurs during enter animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
- * | 1. $animate.enter(...) is called | class="my-animation" |
- * | 2. element is inserted into the parentElement element or beside the afterElement element | class="my-animation" |
- * | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
- * | 4. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
- * | 5. the .ng-enter class is added to the element | class="my-animation ng-animate ng-enter" |
- * | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-enter" |
- * | 7. $animate blocks all CSS transitions on the element to ensure the .ng-enter class styling is applied right away | class="my-animation ng-animate ng-enter" |
- * | 8. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-enter" |
- * | 9. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-enter" |
- * | 10. the .ng-enter-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-enter ng-enter-active" |
- * | 11. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-enter ng-enter-active" |
- * | 12. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
- * | 13. The returned promise is resolved. | class="my-animation" |
- *
- * @param {DOMElement} element the element that will be the focus of the enter animation
- * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation
- * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation
- * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- enter: function(element, parentElement, afterElement, options) {
- options = parseAnimateOptions(options);
- element = angular.element(element);
- parentElement = prepareElement(parentElement);
- afterElement = prepareElement(afterElement);
-
- classBasedAnimationsBlocked(element, true);
- $delegate.enter(element, parentElement, afterElement);
- return runAnimationPostDigest(function(done) {
- return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#leave
- * @kind function
- *
- * @description
- * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once
- * the animation is started, the following CSS classes will be added for the duration of the animation:
- *
- * Below is a breakdown of each step that occurs during leave animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
- * | 1. $animate.leave(...) is called | class="my-animation" |
- * | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
- * | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
- * | 4. the .ng-leave class is added to the element | class="my-animation ng-animate ng-leave" |
- * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-leave" |
- * | 6. $animate blocks all CSS transitions on the element to ensure the .ng-leave class styling is applied right away | class="my-animation ng-animate ng-leave" |
- * | 7. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-leave" |
- * | 8. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-leave" |
- * | 9. the .ng-leave-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-leave ng-leave-active" |
- * | 10. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-leave ng-leave-active" |
- * | 11. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
- * | 12. The element is removed from the DOM | ... |
- * | 13. The returned promise is resolved. | ... |
- *
- * @param {DOMElement} element the element that will be the focus of the leave animation
- * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- leave: function(element, options) {
- options = parseAnimateOptions(options);
- element = angular.element(element);
-
- cancelChildAnimations(element);
- classBasedAnimationsBlocked(element, true);
- return runAnimationPostDigest(function(done) {
- return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
- $delegate.leave(element);
- }, options, done);
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#move
- * @kind function
- *
- * @description
- * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or
- * add the element directly after the afterElement element if present. Then the move animation will be run. Once
- * the animation is started, the following CSS classes will be added for the duration of the animation:
- *
- * Below is a breakdown of each step that occurs during move animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
- * | 1. $animate.move(...) is called | class="my-animation" |
- * | 2. element is moved into the parentElement element or beside the afterElement element | class="my-animation" |
- * | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
- * | 4. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
- * | 5. the .ng-move class is added to the element | class="my-animation ng-animate ng-move" |
- * | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-move" |
- * | 7. $animate blocks all CSS transitions on the element to ensure the .ng-move class styling is applied right away | class="my-animation ng-animate ng-move" |
- * | 8. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-move" |
- * | 9. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-move" |
- * | 10. the .ng-move-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-move ng-move-active" |
- * | 11. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-move ng-move-active" |
- * | 12. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
- * | 13. The returned promise is resolved. | class="my-animation" |
- *
- * @param {DOMElement} element the element that will be the focus of the move animation
- * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation
- * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation
- * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- move: function(element, parentElement, afterElement, options) {
- options = parseAnimateOptions(options);
- element = angular.element(element);
- parentElement = prepareElement(parentElement);
- afterElement = prepareElement(afterElement);
-
- cancelChildAnimations(element);
- classBasedAnimationsBlocked(element, true);
- $delegate.move(element, parentElement, afterElement);
- return runAnimationPostDigest(function(done) {
- return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done);
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#addClass
- *
- * @description
- * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.
- * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide
- * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions
- * or keyframes are defined on the -add-active or base CSS class).
- *
- * Below is a breakdown of each step that occurs during addClass animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |----------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
- * | 1. $animate.addClass(element, 'super') is called | class="my-animation" |
- * | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
- * | 3. the .super-add class is added to the element | class="my-animation ng-animate super-add" |
- * | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate super-add" |
- * | 5. the .super and .super-add-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate super super-add super-add-active" |
- * | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super super-add super-add-active" |
- * | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate super super-add super-add-active" |
- * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation super" |
- * | 9. The super class is kept on the element | class="my-animation super" |
- * | 10. The returned promise is resolved. | class="my-animation super" |
- *
- * @param {DOMElement} element the element that will be animated
- * @param {string} className the CSS class that will be added to the element and then animated
- * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- addClass: function(element, className, options) {
- return this.setClass(element, className, [], options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#removeClass
- *
- * @description
- * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value
- * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in
- * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if
- * no CSS transitions or keyframes are defined on the -remove or base CSS classes).
- *
- * Below is a breakdown of each step that occurs during removeClass animation:
- *
- * | Animation Step | What the element class attribute looks like |
- * |------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
- * | 1. $animate.removeClass(element, 'super') is called | class="my-animation super" |
- * | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation super ng-animate" |
- * | 3. the .super-remove class is added to the element | class="my-animation super ng-animate super-remove" |
- * | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation super ng-animate super-remove" |
- * | 5. the .super-remove-active classes are added and .super is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate super-remove super-remove-active" |
- * | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super-remove super-remove-active" |
- * | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate super-remove super-remove-active" |
- * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
- * | 9. The returned promise is resolved. | class="my-animation" |
- *
- *
- * @param {DOMElement} element the element that will be animated
- * @param {string} className the CSS class that will be animated and then removed from the element
- * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- removeClass: function(element, className, options) {
- return this.setClass(element, [], className, options);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#setClass
- *
- * @description Adds and/or removes the given CSS classes to and from the element.
- * Once complete, the done() callback will be fired (if provided).
- *
- * | Animation Step | What the element class attribute looks like |
- * |--------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|
- * | 1. $animate.setClass(element, 'on', 'off') is called | class="my-animation off" |
- * | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate off" |
- * | 3. the .on-add and .off-remove classes are added to the element | class="my-animation ng-animate on-add off-remove off" |
- * | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate on-add off-remove off" |
- * | 5. the .on, .on-add-active and .off-remove-active classes are added and .off is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active" |
- * | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active" |
- * | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active" |
- * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation on" |
- * | 9. The returned promise is resolved. | class="my-animation on" |
- *
- * @param {DOMElement} element the element which will have its CSS classes changed
- * removed from it
- * @param {string} add the CSS classes which will be added to the element
- * @param {string} remove the CSS class which will be removed from the element
- * CSS classes have been set on the element
- * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation
- * @return {Promise} the animation callback promise
- */
- setClass: function(element, add, remove, options) {
- options = parseAnimateOptions(options);
-
- var STORAGE_KEY = '$$animateClasses';
- element = angular.element(element);
- element = stripCommentsFromElement(element);
-
- if (classBasedAnimationsBlocked(element)) {
- return $delegate.$$setClassImmediately(element, add, remove, options);
- }
-
- // we're using a combined array for both the add and remove
- // operations since the ORDER OF addClass and removeClass matters
- var classes, cache = element.data(STORAGE_KEY);
- var hasCache = !!cache;
- if (!cache) {
- cache = {};
- cache.classes = {};
- }
- classes = cache.classes;
-
- add = isArray(add) ? add : add.split(' ');
- forEach(add, function(c) {
- if (c && c.length) {
- classes[c] = true;
- }
- });
-
- remove = isArray(remove) ? remove : remove.split(' ');
- forEach(remove, function(c) {
- if (c && c.length) {
- classes[c] = false;
- }
- });
-
- if (hasCache) {
- if (options && cache.options) {
- cache.options = angular.extend(cache.options || {}, options);
- }
-
- //the digest cycle will combine all the animations into one function
- return cache.promise;
- } else {
- element.data(STORAGE_KEY, cache = {
- classes: classes,
- options: options
- });
- }
-
- return cache.promise = runAnimationPostDigest(function(done) {
- var parentElement = element.parent();
- var elementNode = extractElementNode(element);
- var parentNode = elementNode.parentNode;
- // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed
- if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) {
- done();
- return;
- }
-
- var cache = element.data(STORAGE_KEY);
- element.removeData(STORAGE_KEY);
-
- var state = element.data(NG_ANIMATE_STATE) || {};
- var classes = resolveElementClasses(element, cache, state.active);
- return !classes
- ? done()
- : performAnimation('setClass', classes, element, parentElement, null, function() {
- if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]);
- if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]);
- }, cache.options, done);
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#cancel
- * @kind function
- *
- * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
- *
- * @description
- * Cancels the provided animation.
- */
- cancel: function(promise) {
- promise.$$cancelFn();
- },
-
- /**
- * @ngdoc method
- * @name $animate#enabled
- * @kind function
- *
- * @param {boolean=} value If provided then set the animation on or off.
- * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation
- * @return {boolean} Current animation state.
- *
- * @description
- * Globally enables/disables animations.
- *
- */
- enabled: function(value, element) {
- switch (arguments.length) {
- case 2:
- if (value) {
- cleanup(element);
- } else {
- var data = element.data(NG_ANIMATE_STATE) || {};
- data.disabled = true;
- element.data(NG_ANIMATE_STATE, data);
- }
- break;
-
- case 1:
- rootAnimateState.disabled = !value;
- break;
-
- default:
- value = !rootAnimateState.disabled;
- break;
- }
- return !!value;
- }
- };
-
- /*
- all animations call this shared animation triggering function internally.
- The animationEvent variable refers to the JavaScript animation event that will be triggered
- and the className value is the name of the animation that will be applied within the
- CSS code. Element, parentElement and afterElement are provided DOM elements for the animation
- and the onComplete callback will be fired once the animation is fully complete.
- */
- function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) {
- var noopCancel = noop;
- var runner = animationRunner(element, animationEvent, className, options);
- if (!runner) {
- fireDOMOperation();
- fireBeforeCallbackAsync();
- fireAfterCallbackAsync();
- closeAnimation();
- return noopCancel;
- }
-
- animationEvent = runner.event;
- className = runner.className;
- var elementEvents = angular.element._data(runner.node);
- elementEvents = elementEvents && elementEvents.events;
-
- if (!parentElement) {
- parentElement = afterElement ? afterElement.parent() : element.parent();
- }
-
- //skip the animation if animations are disabled, a parent is already being animated,
- //the element is not currently attached to the document body or then completely close
- //the animation if any matching animations are not found at all.
- //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.
- if (animationsDisabled(element, parentElement)) {
- fireDOMOperation();
- fireBeforeCallbackAsync();
- fireAfterCallbackAsync();
- closeAnimation();
- return noopCancel;
- }
-
- var ngAnimateState = element.data(NG_ANIMATE_STATE) || {};
- var runningAnimations = ngAnimateState.active || {};
- var totalActiveAnimations = ngAnimateState.totalActive || 0;
- var lastAnimation = ngAnimateState.last;
- var skipAnimation = false;
-
- if (totalActiveAnimations > 0) {
- var animationsToCancel = [];
- if (!runner.isClassBased) {
- if (animationEvent == 'leave' && runningAnimations['ng-leave']) {
- skipAnimation = true;
- } else {
- //cancel all animations when a structural animation takes place
- for (var klass in runningAnimations) {
- animationsToCancel.push(runningAnimations[klass]);
- }
- ngAnimateState = {};
- cleanup(element, true);
- }
- } else if (lastAnimation.event == 'setClass') {
- animationsToCancel.push(lastAnimation);
- cleanup(element, className);
- }
- else if (runningAnimations[className]) {
- var current = runningAnimations[className];
- if (current.event == animationEvent) {
- skipAnimation = true;
- } else {
- animationsToCancel.push(current);
- cleanup(element, className);
- }
- }
-
- if (animationsToCancel.length > 0) {
- forEach(animationsToCancel, function(operation) {
- operation.cancel();
- });
- }
- }
-
- if (runner.isClassBased
- && !runner.isSetClassOperation
- && animationEvent != 'animate'
- && !skipAnimation) {
- skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR
- }
-
- if (skipAnimation) {
- fireDOMOperation();
- fireBeforeCallbackAsync();
- fireAfterCallbackAsync();
- fireDoneCallbackAsync();
- return noopCancel;
- }
-
- runningAnimations = ngAnimateState.active || {};
- totalActiveAnimations = ngAnimateState.totalActive || 0;
-
- if (animationEvent == 'leave') {
- //there's no need to ever remove the listener since the element
- //will be removed (destroyed) after the leave animation ends or
- //is cancelled midway
- element.one('$destroy', function(e) {
- var element = angular.element(this);
- var state = element.data(NG_ANIMATE_STATE);
- if (state) {
- var activeLeaveAnimation = state.active['ng-leave'];
- if (activeLeaveAnimation) {
- activeLeaveAnimation.cancel();
- cleanup(element, 'ng-leave');
- }
- }
- });
- }
-
- //the ng-animate class does nothing, but it's here to allow for
- //parent animations to find and cancel child animations when needed
- element.addClass(NG_ANIMATE_CLASS_NAME);
- if (options && options.tempClasses) {
- forEach(options.tempClasses, function(className) {
- element.addClass(className);
- });
- }
-
- var localAnimationCount = globalAnimationCounter++;
- totalActiveAnimations++;
- runningAnimations[className] = runner;
-
- element.data(NG_ANIMATE_STATE, {
- last: runner,
- active: runningAnimations,
- index: localAnimationCount,
- totalActive: totalActiveAnimations
- });
-
- //first we run the before animations and when all of those are complete
- //then we perform the DOM operation and run the next set of animations
- fireBeforeCallbackAsync();
- runner.before(function(cancelled) {
- var data = element.data(NG_ANIMATE_STATE);
- cancelled = cancelled ||
- !data || !data.active[className] ||
- (runner.isClassBased && data.active[className].event != animationEvent);
-
- fireDOMOperation();
- if (cancelled === true) {
- closeAnimation();
- } else {
- fireAfterCallbackAsync();
- runner.after(closeAnimation);
- }
- });
-
- return runner.cancel;
-
- function fireDOMCallback(animationPhase) {
- var eventName = '$animate:' + animationPhase;
- if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {
- $$asyncCallback(function() {
- element.triggerHandler(eventName, {
- event: animationEvent,
- className: className
- });
- });
- }
- }
-
- function fireBeforeCallbackAsync() {
- fireDOMCallback('before');
- }
-
- function fireAfterCallbackAsync() {
- fireDOMCallback('after');
- }
-
- function fireDoneCallbackAsync() {
- fireDOMCallback('close');
- doneCallback();
- }
-
- //it is less complicated to use a flag than managing and canceling
- //timeouts containing multiple callbacks.
- function fireDOMOperation() {
- if (!fireDOMOperation.hasBeenRun) {
- fireDOMOperation.hasBeenRun = true;
- domOperation();
- }
- }
-
- function closeAnimation() {
- if (!closeAnimation.hasBeenRun) {
- if (runner) { //the runner doesn't exist if it fails to instantiate
- runner.applyStyles();
- }
-
- closeAnimation.hasBeenRun = true;
- if (options && options.tempClasses) {
- forEach(options.tempClasses, function(className) {
- element.removeClass(className);
- });
- }
-
- var data = element.data(NG_ANIMATE_STATE);
- if (data) {
-
- /* only structural animations wait for reflow before removing an
- animation, but class-based animations don't. An example of this
- failing would be when a parent HTML tag has a ng-class attribute
- causing ALL directives below to skip animations during the digest */
- if (runner && runner.isClassBased) {
- cleanup(element, className);
- } else {
- $$asyncCallback(function() {
- var data = element.data(NG_ANIMATE_STATE) || {};
- if (localAnimationCount == data.index) {
- cleanup(element, className, animationEvent);
- }
- });
- element.data(NG_ANIMATE_STATE, data);
- }
- }
- fireDoneCallbackAsync();
- }
- }
- }
-
- function cancelChildAnimations(element) {
- var node = extractElementNode(element);
- if (node) {
- var nodes = angular.isFunction(node.getElementsByClassName) ?
- node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) :
- node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME);
- forEach(nodes, function(element) {
- element = angular.element(element);
- var data = element.data(NG_ANIMATE_STATE);
- if (data && data.active) {
- forEach(data.active, function(runner) {
- runner.cancel();
- });
- }
- });
- }
- }
-
- function cleanup(element, className) {
- if (isMatchingElement(element, $rootElement)) {
- if (!rootAnimateState.disabled) {
- rootAnimateState.running = false;
- rootAnimateState.structural = false;
- }
- } else if (className) {
- var data = element.data(NG_ANIMATE_STATE) || {};
-
- var removeAnimations = className === true;
- if (!removeAnimations && data.active && data.active[className]) {
- data.totalActive--;
- delete data.active[className];
- }
-
- if (removeAnimations || !data.totalActive) {
- element.removeClass(NG_ANIMATE_CLASS_NAME);
- element.removeData(NG_ANIMATE_STATE);
- }
- }
- }
-
- function animationsDisabled(element, parentElement) {
- if (rootAnimateState.disabled) {
- return true;
- }
-
- if (isMatchingElement(element, $rootElement)) {
- return rootAnimateState.running;
- }
-
- var allowChildAnimations, parentRunningAnimation, hasParent;
- do {
- //the element did not reach the root element which means that it
- //is not apart of the DOM. Therefore there is no reason to do
- //any animations on it
- if (parentElement.length === 0) break;
-
- var isRoot = isMatchingElement(parentElement, $rootElement);
- var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});
- if (state.disabled) {
- return true;
- }
-
- //no matter what, for an animation to work it must reach the root element
- //this implies that the element is attached to the DOM when the animation is run
- if (isRoot) {
- hasParent = true;
- }
-
- //once a flag is found that is strictly false then everything before
- //it will be discarded and all child animations will be restricted
- if (allowChildAnimations !== false) {
- var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);
- if (angular.isDefined(animateChildrenFlag)) {
- allowChildAnimations = animateChildrenFlag;
- }
- }
-
- parentRunningAnimation = parentRunningAnimation ||
- state.running ||
- (state.last && !state.last.isClassBased);
- }
- while (parentElement = parentElement.parent());
-
- return !hasParent || (!allowChildAnimations && parentRunningAnimation);
- }
- }]);
-
- $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow',
- function($window, $sniffer, $timeout, $$animateReflow) {
- // Detect proper transitionend/animationend event names.
- var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
-
- // If unprefixed events are not supported but webkit-prefixed are, use the latter.
- // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
- // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
- // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
- // Register both events in case `window.onanimationend` is not supported because of that,
- // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
- // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
- // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition
- if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
- CSS_PREFIX = '-webkit-';
- TRANSITION_PROP = 'WebkitTransition';
- TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
- } else {
- TRANSITION_PROP = 'transition';
- TRANSITIONEND_EVENT = 'transitionend';
- }
-
- if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
- CSS_PREFIX = '-webkit-';
- ANIMATION_PROP = 'WebkitAnimation';
- ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
- } else {
- ANIMATION_PROP = 'animation';
- ANIMATIONEND_EVENT = 'animationend';
- }
-
- var DURATION_KEY = 'Duration';
- var PROPERTY_KEY = 'Property';
- var DELAY_KEY = 'Delay';
- var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
- var ANIMATION_PLAYSTATE_KEY = 'PlayState';
- var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';
- var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';
- var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
- var CLOSING_TIME_BUFFER = 1.5;
- var ONE_SECOND = 1000;
-
- var lookupCache = {};
- var parentCounter = 0;
- var animationReflowQueue = [];
- var cancelAnimationReflow;
- function clearCacheAfterReflow() {
- if (!cancelAnimationReflow) {
- cancelAnimationReflow = $$animateReflow(function() {
- animationReflowQueue = [];
- cancelAnimationReflow = null;
- lookupCache = {};
- });
- }
- }
-
- function afterReflow(element, callback) {
- if (cancelAnimationReflow) {
- cancelAnimationReflow();
- }
- animationReflowQueue.push(callback);
- cancelAnimationReflow = $$animateReflow(function() {
- forEach(animationReflowQueue, function(fn) {
- fn();
- });
-
- animationReflowQueue = [];
- cancelAnimationReflow = null;
- lookupCache = {};
- });
- }
-
- var closingTimer = null;
- var closingTimestamp = 0;
- var animationElementQueue = [];
- function animationCloseHandler(element, totalTime) {
- var node = extractElementNode(element);
- element = angular.element(node);
-
- //this item will be garbage collected by the closing
- //animation timeout
- animationElementQueue.push(element);
-
- //but it may not need to cancel out the existing timeout
- //if the timestamp is less than the previous one
- var futureTimestamp = Date.now() + totalTime;
- if (futureTimestamp <= closingTimestamp) {
- return;
- }
-
- $timeout.cancel(closingTimer);
-
- closingTimestamp = futureTimestamp;
- closingTimer = $timeout(function() {
- closeAllAnimations(animationElementQueue);
- animationElementQueue = [];
- }, totalTime, false);
- }
-
- function closeAllAnimations(elements) {
- forEach(elements, function(element) {
- var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
- if (elementData) {
- forEach(elementData.closeAnimationFns, function(fn) {
- fn();
- });
- }
- });
- }
-
- function getElementAnimationDetails(element, cacheKey) {
- var data = cacheKey ? lookupCache[cacheKey] : null;
- if (!data) {
- var transitionDuration = 0;
- var transitionDelay = 0;
- var animationDuration = 0;
- var animationDelay = 0;
-
- //we want all the styles defined before and after
- forEach(element, function(element) {
- if (element.nodeType == ELEMENT_NODE) {
- var elementStyles = $window.getComputedStyle(element) || {};
-
- var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY];
- transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration);
-
- var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY];
- transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay);
-
- var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY];
- animationDelay = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay);
-
- var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]);
-
- if (aDuration > 0) {
- aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1;
- }
- animationDuration = Math.max(aDuration, animationDuration);
- }
- });
- data = {
- total: 0,
- transitionDelay: transitionDelay,
- transitionDuration: transitionDuration,
- animationDelay: animationDelay,
- animationDuration: animationDuration
- };
- if (cacheKey) {
- lookupCache[cacheKey] = data;
- }
- }
- return data;
- }
-
- function parseMaxTime(str) {
- var maxValue = 0;
- var values = isString(str) ?
- str.split(/\s*,\s*/) :
- [];
- forEach(values, function(value) {
- maxValue = Math.max(parseFloat(value) || 0, maxValue);
- });
- return maxValue;
- }
-
- function getCacheKey(element) {
- var parentElement = element.parent();
- var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY);
- if (!parentID) {
- parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter);
- parentID = parentCounter;
- }
- return parentID + '-' + extractElementNode(element).getAttribute('class');
- }
-
- function animateSetup(animationEvent, element, className, styles) {
- var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;
-
- var cacheKey = getCacheKey(element);
- var eventCacheKey = cacheKey + ' ' + className;
- var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;
-
- var stagger = {};
- if (itemIndex > 0) {
- var staggerClassName = className + '-stagger';
- var staggerCacheKey = cacheKey + ' ' + staggerClassName;
- var applyClasses = !lookupCache[staggerCacheKey];
-
- applyClasses && element.addClass(staggerClassName);
-
- stagger = getElementAnimationDetails(element, staggerCacheKey);
-
- applyClasses && element.removeClass(staggerClassName);
- }
-
- element.addClass(className);
-
- var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};
- var timings = getElementAnimationDetails(element, eventCacheKey);
- var transitionDuration = timings.transitionDuration;
- var animationDuration = timings.animationDuration;
-
- if (structural && transitionDuration === 0 && animationDuration === 0) {
- element.removeClass(className);
- return false;
- }
-
- var blockTransition = styles || (structural && transitionDuration > 0);
- var blockAnimation = animationDuration > 0 &&
- stagger.animationDelay > 0 &&
- stagger.animationDuration === 0;
-
- var closeAnimationFns = formerData.closeAnimationFns || [];
- element.data(NG_ANIMATE_CSS_DATA_KEY, {
- stagger: stagger,
- cacheKey: eventCacheKey,
- running: formerData.running || 0,
- itemIndex: itemIndex,
- blockTransition: blockTransition,
- closeAnimationFns: closeAnimationFns
- });
-
- var node = extractElementNode(element);
-
- if (blockTransition) {
- blockTransitions(node, true);
- if (styles) {
- element.css(styles);
- }
- }
-
- if (blockAnimation) {
- blockAnimations(node, true);
- }
-
- return true;
- }
-
- function animateRun(animationEvent, element, className, activeAnimationComplete, styles) {
- var node = extractElementNode(element);
- var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
- if (node.getAttribute('class').indexOf(className) == -1 || !elementData) {
- activeAnimationComplete();
- return;
- }
-
- var activeClassName = '';
- var pendingClassName = '';
- forEach(className.split(' '), function(klass, i) {
- var prefix = (i > 0 ? ' ' : '') + klass;
- activeClassName += prefix + '-active';
- pendingClassName += prefix + '-pending';
- });
-
- var style = '';
- var appliedStyles = [];
- var itemIndex = elementData.itemIndex;
- var stagger = elementData.stagger;
- var staggerTime = 0;
- if (itemIndex > 0) {
- var transitionStaggerDelay = 0;
- if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {
- transitionStaggerDelay = stagger.transitionDelay * itemIndex;
- }
-
- var animationStaggerDelay = 0;
- if (stagger.animationDelay > 0 && stagger.animationDuration === 0) {
- animationStaggerDelay = stagger.animationDelay * itemIndex;
- appliedStyles.push(CSS_PREFIX + 'animation-play-state');
- }
-
- staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100;
- }
-
- if (!staggerTime) {
- element.addClass(activeClassName);
- if (elementData.blockTransition) {
- blockTransitions(node, false);
- }
- }
-
- var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;
- var timings = getElementAnimationDetails(element, eventCacheKey);
- var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
- if (maxDuration === 0) {
- element.removeClass(activeClassName);
- animateClose(element, className);
- activeAnimationComplete();
- return;
- }
-
- if (!staggerTime && styles) {
- if (!timings.transitionDuration) {
- element.css('transition', timings.animationDuration + 's linear all');
- appliedStyles.push('transition');
- }
- element.css(styles);
- }
-
- var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);
- var maxDelayTime = maxDelay * ONE_SECOND;
-
- if (appliedStyles.length > 0) {
- //the element being animated may sometimes contain comment nodes in
- //the jqLite object, so we're safe to use a single variable to house
- //the styles since there is always only one element being animated
- var oldStyle = node.getAttribute('style') || '';
- if (oldStyle.charAt(oldStyle.length - 1) !== ';') {
- oldStyle += ';';
- }
- node.setAttribute('style', oldStyle + ' ' + style);
- }
-
- var startTime = Date.now();
- var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;
- var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;
- var totalTime = (staggerTime + animationTime) * ONE_SECOND;
-
- var staggerTimeout;
- if (staggerTime > 0) {
- element.addClass(pendingClassName);
- staggerTimeout = $timeout(function() {
- staggerTimeout = null;
-
- if (timings.transitionDuration > 0) {
- blockTransitions(node, false);
- }
- if (timings.animationDuration > 0) {
- blockAnimations(node, false);
- }
-
- element.addClass(activeClassName);
- element.removeClass(pendingClassName);
-
- if (styles) {
- if (timings.transitionDuration === 0) {
- element.css('transition', timings.animationDuration + 's linear all');
- }
- element.css(styles);
- appliedStyles.push('transition');
- }
- }, staggerTime * ONE_SECOND, false);
- }
-
- element.on(css3AnimationEvents, onAnimationProgress);
- elementData.closeAnimationFns.push(function() {
- onEnd();
- activeAnimationComplete();
- });
-
- elementData.running++;
- animationCloseHandler(element, totalTime);
- return onEnd;
-
- // This will automatically be called by $animate so
- // there is no need to attach this internally to the
- // timeout done method.
- function onEnd() {
- element.off(css3AnimationEvents, onAnimationProgress);
- element.removeClass(activeClassName);
- element.removeClass(pendingClassName);
- if (staggerTimeout) {
- $timeout.cancel(staggerTimeout);
- }
- animateClose(element, className);
- var node = extractElementNode(element);
- for (var i in appliedStyles) {
- node.style.removeProperty(appliedStyles[i]);
- }
- }
-
- function onAnimationProgress(event) {
- event.stopPropagation();
- var ev = event.originalEvent || event;
- var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
-
- /* Firefox (or possibly just Gecko) likes to not round values up
- * when a ms measurement is used for the animation */
- var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
-
- /* $manualTimeStamp is a mocked timeStamp value which is set
- * within browserTrigger(). This is only here so that tests can
- * mock animations properly. Real events fallback to event.timeStamp,
- * or, if they don't, then a timeStamp is automatically created for them.
- * We're checking to see if the timeStamp surpasses the expected delay,
- * but we're using elapsedTime instead of the timeStamp on the 2nd
- * pre-condition since animations sometimes close off early */
- if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
- activeAnimationComplete();
- }
- }
- }
-
- function blockTransitions(node, bool) {
- node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : '';
- }
-
- function blockAnimations(node, bool) {
- node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : '';
- }
-
- function animateBefore(animationEvent, element, className, styles) {
- if (animateSetup(animationEvent, element, className, styles)) {
- return function(cancelled) {
- cancelled && animateClose(element, className);
- };
- }
- }
-
- function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) {
- if (element.data(NG_ANIMATE_CSS_DATA_KEY)) {
- return animateRun(animationEvent, element, className, afterAnimationComplete, styles);
- } else {
- animateClose(element, className);
- afterAnimationComplete();
- }
- }
-
- function animate(animationEvent, element, className, animationComplete, options) {
- //If the animateSetup function doesn't bother returning a
- //cancellation function then it means that there is no animation
- //to perform at all
- var preReflowCancellation = animateBefore(animationEvent, element, className, options.from);
- if (!preReflowCancellation) {
- clearCacheAfterReflow();
- animationComplete();
- return;
- }
-
- //There are two cancellation functions: one is before the first
- //reflow animation and the second is during the active state
- //animation. The first function will take care of removing the
- //data from the element which will not make the 2nd animation
- //happen in the first place
- var cancel = preReflowCancellation;
- afterReflow(element, function() {
- //once the reflow is complete then we point cancel to
- //the new cancellation function which will remove all of the
- //animation properties from the active animation
- cancel = animateAfter(animationEvent, element, className, animationComplete, options.to);
- });
-
- return function(cancelled) {
- (cancel || noop)(cancelled);
- };
- }
-
- function animateClose(element, className) {
- element.removeClass(className);
- var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
- if (data) {
- if (data.running) {
- data.running--;
- }
- if (!data.running || data.running === 0) {
- element.removeData(NG_ANIMATE_CSS_DATA_KEY);
- }
- }
- }
-
- return {
- animate: function(element, className, from, to, animationCompleted, options) {
- options = options || {};
- options.from = from;
- options.to = to;
- return animate('animate', element, className, animationCompleted, options);
- },
-
- enter: function(element, animationCompleted, options) {
- options = options || {};
- return animate('enter', element, 'ng-enter', animationCompleted, options);
- },
-
- leave: function(element, animationCompleted, options) {
- options = options || {};
- return animate('leave', element, 'ng-leave', animationCompleted, options);
- },
-
- move: function(element, animationCompleted, options) {
- options = options || {};
- return animate('move', element, 'ng-move', animationCompleted, options);
- },
-
- beforeSetClass: function(element, add, remove, animationCompleted, options) {
- options = options || {};
- var className = suffixClasses(remove, '-remove') + ' ' +
- suffixClasses(add, '-add');
- var cancellationMethod = animateBefore('setClass', element, className, options.from);
- if (cancellationMethod) {
- afterReflow(element, animationCompleted);
- return cancellationMethod;
- }
- clearCacheAfterReflow();
- animationCompleted();
- },
-
- beforeAddClass: function(element, className, animationCompleted, options) {
- options = options || {};
- var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from);
- if (cancellationMethod) {
- afterReflow(element, animationCompleted);
- return cancellationMethod;
- }
- clearCacheAfterReflow();
- animationCompleted();
- },
-
- beforeRemoveClass: function(element, className, animationCompleted, options) {
- options = options || {};
- var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from);
- if (cancellationMethod) {
- afterReflow(element, animationCompleted);
- return cancellationMethod;
- }
- clearCacheAfterReflow();
- animationCompleted();
- },
-
- setClass: function(element, add, remove, animationCompleted, options) {
- options = options || {};
- remove = suffixClasses(remove, '-remove');
- add = suffixClasses(add, '-add');
- var className = remove + ' ' + add;
- return animateAfter('setClass', element, className, animationCompleted, options.to);
- },
-
- addClass: function(element, className, animationCompleted, options) {
- options = options || {};
- return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to);
- },
-
- removeClass: function(element, className, animationCompleted, options) {
- options = options || {};
- return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to);
- }
- };
-
- function suffixClasses(classes, suffix) {
- var className = '';
- classes = isArray(classes) ? classes : classes.split(/\s+/);
- forEach(classes, function(klass, i) {
- if (klass && klass.length > 0) {
- className += (i > 0 ? ' ' : '') + klass + suffix;
- }
- });
- return className;
- }
- }]);
- }]);
-
-
-})(window, window.angular);
diff --git a/public/browse/lib/angular-animate/angular-animate.min.js b/public/browse/lib/angular-animate/angular-animate.min.js
deleted file mode 100644
index 63cbbbb02..000000000
--- a/public/browse/lib/angular-animate/angular-animate.min.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- AngularJS v1.3.5
- (c) 2010-2014 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(M,f,S){'use strict';f.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(T,B,k){k=k.ngAnimateChildren;f.isString(k)&&0===k.length?B.data("$$ngAnimateChildren",!0):T.$watch(k,function(f){B.data("$$ngAnimateChildren",!!f)})}}).factory("$$animateReflow",["$$rAF","$document",function(f,B){return function(k){return f(function(){k()})}}]).config(["$provide","$animateProvider",function(T,B){function k(f){for(var g=0;g=A&&d>=x&&c()}var m=k(d);a=d.data("$$ngAnimateCSS3Data");if(-1!=m.getAttribute("class").indexOf(b)&&a){var q="",r="";g(b.split(" "),function(a,d){var b=(0",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/angular/angular.js/issues"
- },
- "homepage": "http://angularjs.org"
-}
diff --git a/public/browse/lib/angular-bindonce/.bower.json b/public/browse/lib/angular-bindonce/.bower.json
deleted file mode 100644
index 313c654cc..000000000
--- a/public/browse/lib/angular-bindonce/.bower.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "angular-bindonce",
- "version": "0.3.3",
- "main": "bindonce.js",
- "description": "Zero watchers binding directives for AngularJS",
- "homepage": "https://github.com/Pasvaz/bindonce",
- "author": "Pasquale Vazzana ",
- "repository": {
- "type": "git",
- "url": "https://github.com/Pasvaz/bindonce.git"
- },
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "components"
- ],
- "dependencies": {},
- "keywords": [
- "angularjs",
- "angular",
- "directive",
- "binding",
- "watcher",
- "bindonce"
- ],
- "_release": "0.3.3",
- "_resolution": {
- "type": "version",
- "tag": "0.3.3",
- "commit": "0fcf71e6effc88179893c9c06baf6c6bf9037632"
- },
- "_source": "git://github.com/Pasvaz/bindonce.git",
- "_target": "~0.3.3",
- "_originalSource": "angular-bindonce",
- "_direct": true
-}
\ No newline at end of file
diff --git a/public/browse/lib/angular-bindonce/CHANGELOG.md b/public/browse/lib/angular-bindonce/CHANGELOG.md
deleted file mode 100644
index 8246d986e..000000000
--- a/public/browse/lib/angular-bindonce/CHANGELOG.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# 0.3.3 (2014-02-12)
-### Features
-- **bo-disabled:**
- - Add support for ng-disabled/bo-disabled #110
-
-
-# 0.3.2 (2014-11-23)
-### Bug Fixes
-- **Angular 1.3 compatibility**
-
-
-# 0.3.1 (2014-02-12)
-### Features
-- **bo-bind:**
- - alias for bo-text
-
-### Bug Fixes
-- **Angular Promises**
- - Ensures that promises are resolved before to run binders ([b3ef1b4](https://github.com/Pasvaz/bindonce/commit/b3ef1b46edfe83f10ed455d5520027f731563f32))
-
-### Minor improvements
-- Updated Readme
-
-
-# 0.3.0 (2014-01-21)
-### Features
-- **bo-switch:**
- - Create new directive: bo-switch ([652d0db](https://github.com/Pasvaz/bindonce/commit/652d0db04325166a180377c738a376543b5f2357))
-
-
-# 0.2.3 (2014-01-20)
-### Bug Fixes
-
-- **bo-if:**
- - Ensures that we both process newly added binders from bo-if, and that
-we only process each binder once ([d11f863](https://github.com/Pasvaz/bindonce/commit/e091c273bbd17603d410fecc363874f0d1e6f38e))
-
-### Features
-
-- **Minification:**
- - add min file ([47277ee](https://github.com/Pasvaz/bindonce/commit/47277eedd092b3210de362c725a7dadcddac8e87))
-- **Changelog:**
- - Created a changelog file
diff --git a/public/browse/lib/angular-bindonce/README.md b/public/browse/lib/angular-bindonce/README.md
deleted file mode 100644
index c8d753fbe..000000000
--- a/public/browse/lib/angular-bindonce/README.md
+++ /dev/null
@@ -1,154 +0,0 @@
-Bindonce
-========
-
-High performance binding for AngularJs
-
-## Usage
-* download, clone or fork it or install it using [bower](http://twitter.github.com/bower/) `bower install angular-bindonce`
-* Include the `bindonce.js` script provided by this component into your app.
-* Add `'pasvaz.bindonce'` as a module dependency to your app: `angular.module('app', ['pasvaz.bindonce'])`
-
-## Demo
-Here is an example of how AngularJs can [freeze your UI](http://plnkr.co/edit/jwrHVb?p=preview), try to press and hold a key inside the input field, when the table is filled with only 1 person everything is ok, you can see how the DOM is updated by the input in real time, however if you try to load 1000 person *(or even 500 if the testing device is not powerfull)* and repeat the experiment you can see how the UI is frozen. In [this other demo](http://plnkr.co/edit/0DGOrk?p=preview) BindOnce will take care of your watchers and the UI will be reactive as it should be. The code is the same for both demos, the only difference is that I replaced any `ng-*` tag inside the table with the equivalent `bo-*` tag.
-* [AngularJs regular Demo](http://plnkr.co/edit/jwrHVb?p=preview)
-* [Demo with Bindonce](http://plnkr.co/edit/0DGOrk?p=preview)
-
-## Overview
-AngularJs provides a great data binding system but if you abuse of it the page can run into some performance issues, it's known that more of 2000 watchers can lag the UI and that amount can be reached easily if you don't pay attention to the data-binding. Sometime you really need to bind your data using watchers, especially for SPA because the data are updated in real time, but often you can avoid it with some efforts, most of the data presented in your page, once rendered, are immutable so you shouldn't keep watching them for changes.
-
-For instance, take a look to this snippet:
-```html
-
-
-
-
-
-
-
-```
-Angular internally creates a `$watch` for each `ng-*` directive in order to keep the data up to date, so in this example just for displaying few info it creates 6 + 1 *(ngRepeatWatch)* watchers per `person`, even if the `person` is supposed to remain the same once shown. Iterate this amount for each person and you can have an idea about how easy is to reach 2000 watchers. Now if you need it because those data could change while you show the page or are bound to some models, it's ok. But most of the time they are static data that don't change once rendered. This is where **bindonce** can really help you.
-
-The above example done with **bindonce**:
-```html
-
-
-
-
-
-
-
-```
-Now this example uses **0 watches** per `person` and renders exactly the same result as the above that uses ng-*. *(Angular still uses 1 watcher for ngRepeatWatch)*
-
-### The smart approach
-OK until here nothing completely new, with a bit of efforts you could create your own directive and render the `person` inside the `link` function, or you could use [watch fighters](https://github.com/abourget/abourget-angular) that has a similar approach, but there is still one problem that you have to face and **bindonce** already handles it: *the existence of the data when the directive renders the content*. Usually the directives, unless you use watchers or bind their attributes to the scope (still a watcher), render the content when they are loaded into the markup, but if at that given time your data is not available, the directive can't render it. Bindonce can wait until the data is ready before to rendering the content.
-Let's take a look at the follow snippet to better understand the concept:
-```html
-
-
-...
-
-```
-This basic directive works as expected, it renders the `Person` data without using any watchers. However, if `Person` is not yet available inside the $scope when the page is loaded (say we get `Person` via $http or via $resource), the directive is useless, `scope.$eval(attr.myCustomSetText)` simply renders nothing and exits.
-
-Here is how we can solve this issue with **bindonce**:
-```html
-
-
-
-
-
-
-```
-`bindonce="Person"` does the trick, any `bo-*` attribute belonging to `bindonce` waits until the parent `bindonce="{somedata}"` is validated and then renders its content. Once the scope contains the value `Person` then each bo-* child gets filled with the proper values. In order to accomplish this task, **bindonce** uses just **one** temporary watcher, no matters how many children need to be rendered. As soon as it gets `Person` the watcher is promptly removed. If the $scope already contains the data `bindonce` is looking for, then it doesn't create the temporary watcher and simply starts rendering its children.
-
-You may have noticed that the first example didn't assign any value to the `bindonce` attribute:
-```html
-
-
- ...
-```
-when used with `ng-repeat` `bindonce` doesn't need to check if `person` is defined because `ng-repeat` creates the directives only when `person` exists. You could be more explicit: `
`, however assigning a value to `bindonce` in an `ng-repeat` won't make any difference.
-
-### Interpolation
-Some directives (ng-href, ng-src) use interpolation, ie: `ng-href="/profile/{{User.profileId}}"`.
-Both `ng-href` and `ng-src` have the bo-* equivalent directives: `bo-href-i` and `bo-src-i` (pay attention to the **-i**, it stands for **interpolate**). As expected they don't use watchers however Angular creates one watcher per interpolation, for instance `bo-href-i="/profile/{{User.profileId}}"` sets the element's href **once**, as expected, but Angular keeps a watcher active on `{{User.profileId}}` even if `bo-href-i` doesn't use it.
-That's why by default the `bo-href` doesn't use interpolation or watchers. The above equivalent with 0 watchers would be `bo-href="'/profile/' + User.profileId"`. Nevertheless, `bo-href-i` and `bo-src-i` are still maintained for compatibility reasons.
-
-### Filters
-Almost every `bo-*` directive replace the equivalent `ng-*` and works in the same ways, except it is evaluated once.
-Consequentially you can use any valid angular expression, including filters. This is an example how to use a filter:
-```html
-
-
-
-```
-
-## Attribute Usage
-| Directive | Description | Example |
-|------------|----------------|-----|
-| `bindonce="{somedata}"`| **bindonce** is the main directive. `{somedata}` is optional, and if present, forces bindonce to wait until `somedata` is defined before rendering its children | `
...
` |
-| `bo-if = "condition"` | equivalent to `ng-if` but doesn't use watchers |``|
-| `bo-switch = "expression"` | equivalent to `ng-switch` but doesn't use watchers |`
` `public` `private` `
`|
-| `bo-show = "condition"` | equivalent to `ng-show` but doesn't use watchers |``|
-| `bo-hide = "condition"` | equivalent to `ng-hide` but doesn't use watchers |``|
-| `bo-disabled = "condition"` | equivalent to `ng-disabled` but doesn't use watchers |``|
-| `bo-text = "text"` | evaluates "text" and print it as text inside the element | `` |
-| `bo-bind = "text"` | alias for `bo-text`, equivalent to `ng-bind` but doesn't use watchers | `` |
-| `bo-html = "markup"` | evaluates "markup" and render it as html inside the element |`bo-html="Person.description"`|
-| `bo-href-i = "url"` *use `bo-href` instead* | **equivalent** to `ng-href`. **Heads up!** Using interpolation `{{}}` it creates one watcher: `bo-href-i="/p/{{Person.id}}"`. Use `bo-href` to avoid the watcher: `bo-href="'/p/' + Person.id"` |``|
-| `bo-href = "url"` | **similar** to `ng-href` but doesn't allow interpolation using `{{}}` like `ng-href`. **Heads up!** You can't use interpolation `{{}}` inside the url, use bo-href-i for that purpose |`` or ``|
-| `bo-src-i = "url"` *use `bo-src` instead* | **equivalent** to `ng-src`. **Heads up!** It creates one watcher |``|
-| `bo-src = "url"` | **similar** to `ng-src` but doesn't allow interpolation using `{{}}` like `ng-src`. **Heads up!** You can't use interpolation `{{}}`, use bo-src-i for that purpose |``|
-| `bo-class = "object/string"` | equivalent to `ng-class` but doesn't use watchers |``|
-| `bo-alt = "text"` | evaluates "text" and render it as `alt` for the element |``|
-| `bo-title = "text"` | evaluates "text" and render it as `title` for the element |``|
-| `bo-id = "#id"` | evaluates "#id" and render it as `id` for the element |``|
-| `bo-style = "object"` | equivalent to `ng-style` but doesn't use watchers |``|
-| `bo-value = "expression"` | evaluates "expression" and render it as `value` for the element |``|
-| `bo-attr bo-attr-foo = "text"` | evaluates "text" and render it as a custom attribute for the element |``|
-
-## Build
-```
-$ npm install uglify-js -g
-$ uglifyjs bindonce.js -c -m -o bindonce.min.js
-```
-
-## Todo
-Tests
-
-## Copyright
-BindOnce was written by **Pasquale Vazzana**, you can follow him on [google+](https://plus.google.com/101872882413388363602) or on [@twitter](https://twitter.com/PasqualeVazzana)
-
-Thanks to all the [contributors](https://github.com/Pasvaz/bindonce/graphs/contributors)
-
-## LICENSE - "MIT License"
-
-Copyright (c) 2013-2014 Pasquale Vazzana
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public/browse/lib/angular-bindonce/bindonce.js b/public/browse/lib/angular-bindonce/bindonce.js
deleted file mode 100644
index 8742d8917..000000000
--- a/public/browse/lib/angular-bindonce/bindonce.js
+++ /dev/null
@@ -1,325 +0,0 @@
-(function () {
- "use strict";
- /**
- * Bindonce - Zero watches binding for AngularJs
- * @version v0.3.3
- * @link https://github.com/Pasvaz/bindonce
- * @author Pasquale Vazzana
- * @license MIT License, http://www.opensource.org/licenses/MIT
- */
-
- var bindonceModule = angular.module('pasvaz.bindonce', []);
-
- bindonceModule.directive('bindonce', function ()
- {
- var toBoolean = function (value)
- {
- if (value && value.length !== 0)
- {
- var v = angular.lowercase("" + value);
- value = !(v === 'f' || v === '0' || v === 'false' || v === 'no' || v === 'n' || v === '[]');
- }
- else
- {
- value = false;
- }
- return value;
- };
-
- var msie = parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
- if (isNaN(msie))
- {
- msie = parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
- }
-
- var bindonceDirective =
- {
- restrict: "AM",
- controller: ['$scope', '$element', '$attrs', '$interpolate', function ($scope, $element, $attrs, $interpolate)
- {
- var showHideBinder = function (elm, attr, value)
- {
- var show = (attr === 'show') ? '' : 'none';
- var hide = (attr === 'hide') ? '' : 'none';
- elm.css('display', toBoolean(value) ? show : hide);
- };
- var classBinder = function (elm, value)
- {
- if (angular.isObject(value) && !angular.isArray(value))
- {
- var results = [];
- angular.forEach(value, function (value, index)
- {
- if (value) results.push(index);
- });
- value = results;
- }
- if (value)
- {
- elm.addClass(angular.isArray(value) ? value.join(' ') : value);
- }
- };
- var transclude = function (transcluder, scope)
- {
- transcluder.transclude(scope, function (clone)
- {
- var parent = transcluder.element.parent();
- var afterNode = transcluder.element && transcluder.element[transcluder.element.length - 1];
- var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
- var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
- angular.forEach(clone, function (node)
- {
- parentNode.insertBefore(node, afterNextSibling);
- });
- });
- };
-
- var ctrl =
- {
- watcherRemover: undefined,
- binders: [],
- group: $attrs.boName,
- element: $element,
- ran: false,
-
- addBinder: function (binder)
- {
- this.binders.push(binder);
-
- // In case of late binding (when using the directive bo-name/bo-parent)
- // it happens only when you use nested bindonce, if the bo-children
- // are not dom children the linking can follow another order
- if (this.ran)
- {
- this.runBinders();
- }
- },
-
- setupWatcher: function (bindonceValue)
- {
- var that = this;
- this.watcherRemover = $scope.$watch(bindonceValue, function (newValue)
- {
- if (newValue === undefined) return;
- that.removeWatcher();
- that.checkBindonce(newValue);
- }, true);
- },
-
- checkBindonce: function (value)
- {
- var that = this, promise = (value.$promise) ? value.$promise.then : value.then;
- // since Angular 1.2 promises are no longer
- // undefined until they don't get resolved
- if (typeof promise === 'function')
- {
- promise(function ()
- {
- that.runBinders();
- });
- }
- else
- {
- that.runBinders();
- }
- },
-
- removeWatcher: function ()
- {
- if (this.watcherRemover !== undefined)
- {
- this.watcherRemover();
- this.watcherRemover = undefined;
- }
- },
-
- runBinders: function ()
- {
- while (this.binders.length > 0)
- {
- var binder = this.binders.shift();
- if (this.group && this.group != binder.group) continue;
- var value = binder.scope.$eval((binder.interpolate) ? $interpolate(binder.value) : binder.value);
- switch (binder.attr)
- {
- case 'boIf':
- if (toBoolean(value))
- {
- transclude(binder, binder.scope.$new());
- }
- break;
- case 'boSwitch':
- var selectedTranscludes, switchCtrl = binder.controller[0];
- if ((selectedTranscludes = switchCtrl.cases['!' + value] || switchCtrl.cases['?']))
- {
- binder.scope.$eval(binder.attrs.change);
- angular.forEach(selectedTranscludes, function (selectedTransclude)
- {
- transclude(selectedTransclude, binder.scope.$new());
- });
- }
- break;
- case 'boSwitchWhen':
- var ctrl = binder.controller[0];
- ctrl.cases['!' + binder.attrs.boSwitchWhen] = (ctrl.cases['!' + binder.attrs.boSwitchWhen] || []);
- ctrl.cases['!' + binder.attrs.boSwitchWhen].push({ transclude: binder.transclude, element: binder.element });
- break;
- case 'boSwitchDefault':
- var ctrl = binder.controller[0];
- ctrl.cases['?'] = (ctrl.cases['?'] || []);
- ctrl.cases['?'].push({ transclude: binder.transclude, element: binder.element });
- break;
- case 'hide':
- case 'show':
- showHideBinder(binder.element, binder.attr, value);
- break;
- case 'class':
- classBinder(binder.element, value);
- break;
- case 'text':
- binder.element.text(value);
- break;
- case 'html':
- binder.element.html(value);
- break;
- case 'style':
- binder.element.css(value);
- break;
- case 'disabled':
- binder.element.prop('disabled', value);
- break;
- case 'src':
- binder.element.attr(binder.attr, value);
- if (msie) binder.element.prop('src', value);
- break;
- case 'attr':
- angular.forEach(binder.attrs, function (attrValue, attrKey)
- {
- var newAttr, newValue;
- if (attrKey.match(/^boAttr./) && binder.attrs[attrKey])
- {
- newAttr = attrKey.replace(/^boAttr/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
- newValue = binder.scope.$eval(binder.attrs[attrKey]);
- binder.element.attr(newAttr, newValue);
- }
- });
- break;
- case 'href':
- case 'alt':
- case 'title':
- case 'id':
- case 'value':
- binder.element.attr(binder.attr, value);
- break;
- }
- }
- this.ran = true;
- }
- };
-
- angular.extend(this, ctrl);
- }],
-
- link: function (scope, elm, attrs, bindonceController)
- {
- var value = attrs.bindonce && scope.$eval(attrs.bindonce);
- if (value !== undefined)
- {
- bindonceController.checkBindonce(value);
- }
- else
- {
- bindonceController.setupWatcher(attrs.bindonce);
- elm.bind("$destroy", bindonceController.removeWatcher);
- }
- }
- };
-
- return bindonceDirective;
- });
-
- angular.forEach(
- [
- { directiveName: 'boShow', attribute: 'show' },
- { directiveName: 'boHide', attribute: 'hide' },
- { directiveName: 'boClass', attribute: 'class' },
- { directiveName: 'boText', attribute: 'text' },
- { directiveName: 'boBind', attribute: 'text' },
- { directiveName: 'boHtml', attribute: 'html' },
- { directiveName: 'boSrcI', attribute: 'src', interpolate: true },
- { directiveName: 'boSrc', attribute: 'src' },
- { directiveName: 'boHrefI', attribute: 'href', interpolate: true },
- { directiveName: 'boHref', attribute: 'href' },
- { directiveName: 'boAlt', attribute: 'alt' },
- { directiveName: 'boTitle', attribute: 'title' },
- { directiveName: 'boId', attribute: 'id' },
- { directiveName: 'boStyle', attribute: 'style' },
- { directiveName: 'boDisabled', attribute: 'disabled' },
- { directiveName: 'boValue', attribute: 'value' },
- { directiveName: 'boAttr', attribute: 'attr' },
-
- { directiveName: 'boIf', transclude: 'element', terminal: true, priority: 1000 },
- { directiveName: 'boSwitch', require: 'boSwitch', controller: function () { this.cases = {}; } },
- { directiveName: 'boSwitchWhen', transclude: 'element', priority: 800, require: '^boSwitch' },
- { directiveName: 'boSwitchDefault', transclude: 'element', priority: 800, require: '^boSwitch' }
- ],
- function (boDirective)
- {
- var childPriority = 200;
- return bindonceModule.directive(boDirective.directiveName, function ()
- {
- var bindonceDirective =
- {
- priority: boDirective.priority || childPriority,
- transclude: boDirective.transclude || false,
- terminal: boDirective.terminal || false,
- require: ['^bindonce'].concat(boDirective.require || []),
- controller: boDirective.controller,
- compile: function (tElement, tAttrs, transclude)
- {
- return function (scope, elm, attrs, controllers)
- {
- var bindonceController = controllers[0];
- var name = attrs.boParent;
- if (name && bindonceController.group !== name)
- {
- var element = bindonceController.element.parent();
- bindonceController = undefined;
- var parentValue;
-
- while (element[0].nodeType !== 9 && element.length)
- {
- if ((parentValue = element.data('$bindonceController'))
- && parentValue.group === name)
- {
- bindonceController = parentValue;
- break;
- }
- element = element.parent();
- }
- if (!bindonceController)
- {
- throw new Error("No bindonce controller: " + name);
- }
- }
-
- bindonceController.addBinder(
- {
- element: elm,
- attr: boDirective.attribute || boDirective.directiveName,
- attrs: attrs,
- value: attrs[boDirective.directiveName],
- interpolate: boDirective.interpolate,
- group: name,
- transclude: transclude,
- controller: controllers.slice(1),
- scope: scope
- });
- };
- }
- };
-
- return bindonceDirective;
- });
- })
-})();
diff --git a/public/browse/lib/angular-bindonce/bindonce.min.js b/public/browse/lib/angular-bindonce/bindonce.min.js
deleted file mode 100644
index 555ded4bf..000000000
--- a/public/browse/lib/angular-bindonce/bindonce.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(){"use strict";var e=angular.module("pasvaz.bindonce",[]);e.directive("bindonce",function(){var e=function(e){if(e&&0!==e.length){var t=angular.lowercase(""+e);e=!("f"===t||"0"===t||"false"===t||"no"===t||"n"===t||"[]"===t)}else e=!1;return e},t=parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10);isNaN(t)&&(t=parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10));var r={restrict:"AM",controller:["$scope","$element","$attrs","$interpolate",function(r,a,i,n){var c=function(t,r,a){var i="show"===r?"":"none",n="hide"===r?"":"none";t.css("display",e(a)?i:n)},o=function(e,t){if(angular.isObject(t)&&!angular.isArray(t)){var r=[];angular.forEach(t,function(e,t){e&&r.push(t)}),t=r}t&&e.addClass(angular.isArray(t)?t.join(" "):t)},s=function(e,t){e.transclude(t,function(t){var r=e.element.parent(),a=e.element&&e.element[e.element.length-1],i=r&&r[0]||a&&a.parentNode,n=a&&a.nextSibling||null;angular.forEach(t,function(e){i.insertBefore(e,n)})})},l={watcherRemover:void 0,binders:[],group:i.boName,element:a,ran:!1,addBinder:function(e){this.binders.push(e),this.ran&&this.runBinders()},setupWatcher:function(e){var t=this;this.watcherRemover=r.$watch(e,function(e){void 0!==e&&(t.removeWatcher(),t.checkBindonce(e))},!0)},checkBindonce:function(e){var t=this,r=e.$promise?e.$promise.then:e.then;"function"==typeof r?r(function(){t.runBinders()}):t.runBinders()},removeWatcher:function(){void 0!==this.watcherRemover&&(this.watcherRemover(),this.watcherRemover=void 0)},runBinders:function(){for(;this.binders.length>0;){var r=this.binders.shift();if(!this.group||this.group==r.group){var a=r.scope.$eval(r.interpolate?n(r.value):r.value);switch(r.attr){case"boIf":e(a)&&s(r,r.scope.$new());break;case"boSwitch":var i,l=r.controller[0];(i=l.cases["!"+a]||l.cases["?"])&&(r.scope.$eval(r.attrs.change),angular.forEach(i,function(e){s(e,r.scope.$new())}));break;case"boSwitchWhen":var u=r.controller[0];u.cases["!"+r.attrs.boSwitchWhen]=u.cases["!"+r.attrs.boSwitchWhen]||[],u.cases["!"+r.attrs.boSwitchWhen].push({transclude:r.transclude,element:r.element});break;case"boSwitchDefault":var u=r.controller[0];u.cases["?"]=u.cases["?"]||[],u.cases["?"].push({transclude:r.transclude,element:r.element});break;case"hide":case"show":c(r.element,r.attr,a);break;case"class":o(r.element,a);break;case"text":r.element.text(a);break;case"html":r.element.html(a);break;case"style":r.element.css(a);break;case"disabled":r.element.prop("disabled",a);break;case"src":r.element.attr(r.attr,a),t&&r.element.prop("src",a);break;case"attr":angular.forEach(r.attrs,function(e,t){var a,i;t.match(/^boAttr./)&&r.attrs[t]&&(a=t.replace(/^boAttr/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),i=r.scope.$eval(r.attrs[t]),r.element.attr(a,i))});break;case"href":case"alt":case"title":case"id":case"value":r.element.attr(r.attr,a)}}}this.ran=!0}};angular.extend(this,l)}],link:function(e,t,r,a){var i=r.bindonce&&e.$eval(r.bindonce);void 0!==i?a.checkBindonce(i):(a.setupWatcher(r.bindonce),t.bind("$destroy",a.removeWatcher))}};return r}),angular.forEach([{directiveName:"boShow",attribute:"show"},{directiveName:"boHide",attribute:"hide"},{directiveName:"boClass",attribute:"class"},{directiveName:"boText",attribute:"text"},{directiveName:"boBind",attribute:"text"},{directiveName:"boHtml",attribute:"html"},{directiveName:"boSrcI",attribute:"src",interpolate:!0},{directiveName:"boSrc",attribute:"src"},{directiveName:"boHrefI",attribute:"href",interpolate:!0},{directiveName:"boHref",attribute:"href"},{directiveName:"boAlt",attribute:"alt"},{directiveName:"boTitle",attribute:"title"},{directiveName:"boId",attribute:"id"},{directiveName:"boStyle",attribute:"style"},{directiveName:"boDisabled",attribute:"disabled"},{directiveName:"boValue",attribute:"value"},{directiveName:"boAttr",attribute:"attr"},{directiveName:"boIf",transclude:"element",terminal:!0,priority:1e3},{directiveName:"boSwitch",require:"boSwitch",controller:function(){this.cases={}}},{directiveName:"boSwitchWhen",transclude:"element",priority:800,require:"^boSwitch"},{directiveName:"boSwitchDefault",transclude:"element",priority:800,require:"^boSwitch"}],function(t){var r=200;return e.directive(t.directiveName,function(){var e={priority:t.priority||r,transclude:t.transclude||!1,terminal:t.terminal||!1,require:["^bindonce"].concat(t.require||[]),controller:t.controller,compile:function(e,r,a){return function(e,r,i,n){var c=n[0],o=i.boParent;if(o&&c.group!==o){var s=c.element.parent();c=void 0;for(var l;9!==s[0].nodeType&&s.length;){if((l=s.data("$bindonceController"))&&l.group===o){c=l;break}s=s.parent()}if(!c)throw new Error("No bindonce controller: "+o)}c.addBinder({element:r,attr:t.attribute||t.directiveName,attrs:i,value:i[t.directiveName],interpolate:t.interpolate,group:o,transclude:a,controller:n.slice(1),scope:e})}}};return e})})}();
\ No newline at end of file
diff --git a/public/browse/lib/angular-bindonce/bower.json b/public/browse/lib/angular-bindonce/bower.json
deleted file mode 100644
index 924259459..000000000
--- a/public/browse/lib/angular-bindonce/bower.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "angular-bindonce",
- "version": "0.3.3",
- "main": "bindonce.js",
- "description": "Zero watchers binding directives for AngularJS",
- "homepage": "https://github.com/Pasvaz/bindonce",
- "author": "Pasquale Vazzana ",
- "repository": {
- "type": "git",
- "url": "https://github.com/Pasvaz/bindonce.git"
- },
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "components"
- ],
- "dependencies": {
- },
- "keywords": [
- "angularjs",
- "angular",
- "directive",
- "binding",
- "watcher",
- "bindonce"
- ]
-}
diff --git a/public/browse/lib/angular-bindonce/package.json b/public/browse/lib/angular-bindonce/package.json
deleted file mode 100644
index 924259459..000000000
--- a/public/browse/lib/angular-bindonce/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "angular-bindonce",
- "version": "0.3.3",
- "main": "bindonce.js",
- "description": "Zero watchers binding directives for AngularJS",
- "homepage": "https://github.com/Pasvaz/bindonce",
- "author": "Pasquale Vazzana ",
- "repository": {
- "type": "git",
- "url": "https://github.com/Pasvaz/bindonce.git"
- },
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "components"
- ],
- "dependencies": {
- },
- "keywords": [
- "angularjs",
- "angular",
- "directive",
- "binding",
- "watcher",
- "bindonce"
- ]
-}
diff --git a/public/browse/lib/angular-loader/.bower.json b/public/browse/lib/angular-loader/.bower.json
deleted file mode 100644
index c0b518149..000000000
--- a/public/browse/lib/angular-loader/.bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "angular-loader",
- "version": "1.3.5",
- "main": "./angular-loader.js",
- "ignore": [],
- "dependencies": {
- "angular": "1.3.5"
- },
- "homepage": "https://github.com/angular/bower-angular-loader",
- "_release": "1.3.5",
- "_resolution": {
- "type": "version",
- "tag": "v1.3.5",
- "commit": "afb779fa2e865a1f13f87278586aa71bbea518bb"
- },
- "_source": "git://github.com/angular/bower-angular-loader.git",
- "_target": "1.3.x",
- "_originalSource": "angular-loader"
-}
\ No newline at end of file
diff --git a/public/browse/lib/angular-loader/README.md b/public/browse/lib/angular-loader/README.md
deleted file mode 100644
index 0f16d5def..000000000
--- a/public/browse/lib/angular-loader/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# packaged angular-loader
-
-This repo is for distribution on `npm` and `bower`. The source for this module is in the
-[main AngularJS repo](https://github.com/angular/angular.js/blob/master/src/loader.js).
-Please file issues and pull requests against that repo.
-
-## Install
-
-You can install this package either with `npm` or with `bower`.
-
-### npm
-
-```shell
-npm install angular-loader
-```
-
-Add a `
-```
-
-Note that this package is not in CommonJS format, so doing `require('angular-loader')` will
-return `undefined`.
-
-### bower
-
-```shell
-bower install angular-loader
-```
-
-Add a `
-```
-
-## Documentation
-
-Documentation is available on the
-[AngularJS docs site](http://docs.angularjs.org/guide/bootstrap).
-
-## License
-
-The MIT License
-
-Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public/browse/lib/angular-loader/angular-loader.js b/public/browse/lib/angular-loader/angular-loader.js
deleted file mode 100644
index 3b27049c1..000000000
--- a/public/browse/lib/angular-loader/angular-loader.js
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- * @license AngularJS v1.3.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-
-(function() {'use strict';
-
-/**
- * @description
- *
- * This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
- *
- * var exampleMinErr = minErr('example');
- * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
- *
- * The above creates an instance of minErr in the example namespace. The
- * resulting error will have a namespaced error code of example.one. The
- * resulting error will replace {0} with the value of foo, and {1} with the
- * value of bar. The object is not restricted in the number of arguments it can
- * take.
- *
- * If fewer arguments are specified than necessary for interpolation, the extra
- * interpolation markers will be preserved in the final string.
- *
- * Since data will be parsed statically during a build step, some restrictions
- * are applied with respect to how minErr instances are created and called.
- * Instances should have names of the form namespaceMinErr for a minErr created
- * using minErr('namespace') . Error codes, namespaces and template strings
- * should all be static strings, not variables or general expressions.
- *
- * @param {string} module The namespace to use for the new minErr instance.
- * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
- * error from returned function, for cases when a particular type of error is useful.
- * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
- */
-
-function minErr(module, ErrorConstructor) {
- ErrorConstructor = ErrorConstructor || Error;
- return function() {
- var code = arguments[0],
- prefix = '[' + (module ? module + ':' : '') + code + '] ',
- template = arguments[1],
- templateArgs = arguments,
-
- message, i;
-
- message = prefix + template.replace(/\{\d+\}/g, function(match) {
- var index = +match.slice(1, -1), arg;
-
- if (index + 2 < templateArgs.length) {
- return toDebugString(templateArgs[index + 2]);
- }
- return match;
- });
-
- message = message + '\nhttp://errors.angularjs.org/1.3.5/' +
- (module ? module + '/' : '') + code;
- for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
- encodeURIComponent(toDebugString(arguments[i]));
- }
- return new ErrorConstructor(message);
- };
-}
-
-/**
- * @ngdoc type
- * @name angular.Module
- * @module ng
- * @description
- *
- * Interface for configuring angular {@link angular.module modules}.
- */
-
-function setupModuleLoader(window) {
-
- var $injectorMinErr = minErr('$injector');
- var ngMinErr = minErr('ng');
-
- function ensure(obj, name, factory) {
- return obj[name] || (obj[name] = factory());
- }
-
- var angular = ensure(window, 'angular', Object);
-
- // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
- angular.$$minErr = angular.$$minErr || minErr;
-
- return ensure(angular, 'module', function() {
- /** @type {Object.} */
- var modules = {};
-
- /**
- * @ngdoc function
- * @name angular.module
- * @module ng
- * @description
- *
- * The `angular.module` is a global place for creating, registering and retrieving Angular
- * modules.
- * All modules (angular core or 3rd party) that should be available to an application must be
- * registered using this mechanism.
- *
- * When passed two or more arguments, a new module is created. If passed only one argument, an
- * existing module (the name passed as the first argument to `module`) is retrieved.
- *
- *
- * # Module
- *
- * A module is a collection of services, directives, controllers, filters, and configuration information.
- * `angular.module` is used to configure the {@link auto.$injector $injector}.
- *
- * ```js
- * // Create a new module
- * var myModule = angular.module('myModule', []);
- *
- * // register a new service
- * myModule.value('appName', 'MyCoolApp');
- *
- * // configure existing services inside initialization blocks.
- * myModule.config(['$locationProvider', function($locationProvider) {
- * // Configure existing providers
- * $locationProvider.hashPrefix('!');
- * }]);
- * ```
- *
- * Then you can create an injector and load your modules like this:
- *
- * ```js
- * var injector = angular.injector(['ng', 'myModule'])
- * ```
- *
- * However it's more likely that you'll just use
- * {@link ng.directive:ngApp ngApp} or
- * {@link angular.bootstrap} to simplify this process for you.
- *
- * @param {!string} name The name of the module to create or retrieve.
- * @param {!Array.=} requires If specified then new module is being created. If
- * unspecified then the module is being retrieved for further configuration.
- * @param {Function=} configFn Optional configuration function for the module. Same as
- * {@link angular.Module#config Module#config()}.
- * @returns {module} new module with the {@link angular.Module} api.
- */
- return function module(name, requires, configFn) {
- var assertNotHasOwnProperty = function(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
- }
- };
-
- assertNotHasOwnProperty(name, 'module');
- if (requires && modules.hasOwnProperty(name)) {
- modules[name] = null;
- }
- return ensure(modules, name, function() {
- if (!requires) {
- throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
- "the module name or forgot to load it. If registering a module ensure that you " +
- "specify the dependencies as the second argument.", name);
- }
-
- /** @type {!Array.>} */
- var invokeQueue = [];
-
- /** @type {!Array.} */
- var configBlocks = [];
-
- /** @type {!Array.} */
- var runBlocks = [];
-
- var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
-
- /** @type {angular.Module} */
- var moduleInstance = {
- // Private state
- _invokeQueue: invokeQueue,
- _configBlocks: configBlocks,
- _runBlocks: runBlocks,
-
- /**
- * @ngdoc property
- * @name angular.Module#requires
- * @module ng
- *
- * @description
- * Holds the list of modules which the injector will load before the current module is
- * loaded.
- */
- requires: requires,
-
- /**
- * @ngdoc property
- * @name angular.Module#name
- * @module ng
- *
- * @description
- * Name of the module.
- */
- name: name,
-
-
- /**
- * @ngdoc method
- * @name angular.Module#provider
- * @module ng
- * @param {string} name service name
- * @param {Function} providerType Construction function for creating new instance of the
- * service.
- * @description
- * See {@link auto.$provide#provider $provide.provider()}.
- */
- provider: invokeLater('$provide', 'provider'),
-
- /**
- * @ngdoc method
- * @name angular.Module#factory
- * @module ng
- * @param {string} name service name
- * @param {Function} providerFunction Function for creating new instance of the service.
- * @description
- * See {@link auto.$provide#factory $provide.factory()}.
- */
- factory: invokeLater('$provide', 'factory'),
-
- /**
- * @ngdoc method
- * @name angular.Module#service
- * @module ng
- * @param {string} name service name
- * @param {Function} constructor A constructor function that will be instantiated.
- * @description
- * See {@link auto.$provide#service $provide.service()}.
- */
- service: invokeLater('$provide', 'service'),
-
- /**
- * @ngdoc method
- * @name angular.Module#value
- * @module ng
- * @param {string} name service name
- * @param {*} object Service instance object.
- * @description
- * See {@link auto.$provide#value $provide.value()}.
- */
- value: invokeLater('$provide', 'value'),
-
- /**
- * @ngdoc method
- * @name angular.Module#constant
- * @module ng
- * @param {string} name constant name
- * @param {*} object Constant value.
- * @description
- * Because the constant are fixed, they get applied before other provide methods.
- * See {@link auto.$provide#constant $provide.constant()}.
- */
- constant: invokeLater('$provide', 'constant', 'unshift'),
-
- /**
- * @ngdoc method
- * @name angular.Module#animation
- * @module ng
- * @param {string} name animation name
- * @param {Function} animationFactory Factory function for creating new instance of an
- * animation.
- * @description
- *
- * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
- *
- *
- * Defines an animation hook that can be later used with
- * {@link ngAnimate.$animate $animate} service and directives that use this service.
- *
- * ```js
- * module.animation('.animation-name', function($inject1, $inject2) {
- * return {
- * eventName : function(element, done) {
- * //code to run the animation
- * //once complete, then run done()
- * return function cancellationFunction(element) {
- * //code to cancel the animation
- * }
- * }
- * }
- * })
- * ```
- *
- * See {@link ng.$animateProvider#register $animateProvider.register()} and
- * {@link ngAnimate ngAnimate module} for more information.
- */
- animation: invokeLater('$animateProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#filter
- * @module ng
- * @param {string} name Filter name.
- * @param {Function} filterFactory Factory function for creating new instance of filter.
- * @description
- * See {@link ng.$filterProvider#register $filterProvider.register()}.
- */
- filter: invokeLater('$filterProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#controller
- * @module ng
- * @param {string|Object} name Controller name, or an object map of controllers where the
- * keys are the names and the values are the constructors.
- * @param {Function} constructor Controller constructor function.
- * @description
- * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
- */
- controller: invokeLater('$controllerProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#directive
- * @module ng
- * @param {string|Object} name Directive name, or an object map of directives where the
- * keys are the names and the values are the factories.
- * @param {Function} directiveFactory Factory function for creating new instance of
- * directives.
- * @description
- * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
- */
- directive: invokeLater('$compileProvider', 'directive'),
-
- /**
- * @ngdoc method
- * @name angular.Module#config
- * @module ng
- * @param {Function} configFn Execute this function on module load. Useful for service
- * configuration.
- * @description
- * Use this method to register work which needs to be performed on module loading.
- * For more about how to configure services, see
- * {@link providers#provider-recipe Provider Recipe}.
- */
- config: config,
-
- /**
- * @ngdoc method
- * @name angular.Module#run
- * @module ng
- * @param {Function} initializationFn Execute this function after injector creation.
- * Useful for application initialization.
- * @description
- * Use this method to register work which should be performed when the injector is done
- * loading all modules.
- */
- run: function(block) {
- runBlocks.push(block);
- return this;
- }
- };
-
- if (configFn) {
- config(configFn);
- }
-
- return moduleInstance;
-
- /**
- * @param {string} provider
- * @param {string} method
- * @param {String=} insertMethod
- * @returns {angular.Module}
- */
- function invokeLater(provider, method, insertMethod, queue) {
- if (!queue) queue = invokeQueue;
- return function() {
- queue[insertMethod || 'push']([provider, method, arguments]);
- return moduleInstance;
- };
- }
- });
- };
- });
-
-}
-
-setupModuleLoader(window);
-})(window);
-
-/**
- * Closure compiler type information
- *
- * @typedef { {
- * requires: !Array.,
- * invokeQueue: !Array.>,
- *
- * service: function(string, Function):angular.Module,
- * factory: function(string, Function):angular.Module,
- * value: function(string, *):angular.Module,
- *
- * filter: function(string, Function):angular.Module,
- *
- * init: function(Function):angular.Module
- * } }
- */
-angular.Module;
-
diff --git a/public/browse/lib/angular-loader/angular-loader.min.js b/public/browse/lib/angular-loader/angular-loader.min.js
deleted file mode 100644
index bc6333ed5..000000000
--- a/public/browse/lib/angular-loader/angular-loader.min.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- AngularJS v1.3.5
- (c) 2010-2014 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(){'use strict';function d(b){return function(){var c=arguments[0],e;e="["+(b?b+":":"")+c+"] http://errors.angularjs.org/1.3.5/"+(b?b+"/":"")+c;for(c=1;c",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/angular/angular.js/issues"
- },
- "homepage": "http://angularjs.org"
-}
diff --git a/public/browse/lib/angular-mocks/.bower.json b/public/browse/lib/angular-mocks/.bower.json
deleted file mode 100644
index e321d3002..000000000
--- a/public/browse/lib/angular-mocks/.bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "angular-mocks",
- "version": "1.3.5",
- "main": "./angular-mocks.js",
- "ignore": [],
- "dependencies": {
- "angular": "1.3.5"
- },
- "homepage": "https://github.com/angular/bower-angular-mocks",
- "_release": "1.3.5",
- "_resolution": {
- "type": "version",
- "tag": "v1.3.5",
- "commit": "e5356ca3fa80f824ac7e3d9651156401e6bf2a38"
- },
- "_source": "git://github.com/angular/bower-angular-mocks.git",
- "_target": "~1.3.x",
- "_originalSource": "angular-mocks"
-}
\ No newline at end of file
diff --git a/public/browse/lib/angular-mocks/README.md b/public/browse/lib/angular-mocks/README.md
deleted file mode 100644
index 1604ef880..000000000
--- a/public/browse/lib/angular-mocks/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# packaged angular-mocks
-
-This repo is for distribution on `npm` and `bower`. The source for this module is in the
-[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngMock).
-Please file issues and pull requests against that repo.
-
-## Install
-
-You can install this package either with `npm` or with `bower`.
-
-### npm
-
-```shell
-npm install angular-mocks
-```
-
-The mocks are then available at `node_modules/angular-mocks/angular-mocks.js`.
-
-Note that this package is not in CommonJS format, so doing `require('angular-mocks')` will
-return `undefined`.
-
-### bower
-
-```shell
-bower install angular-mocks
-```
-
-The mocks are then available at `bower_components/angular-mocks/angular-mocks.js`.
-
-## Documentation
-
-Documentation is available on the
-[AngularJS docs site](https://docs.angularjs.org/guide/unit-testing).
-
-## License
-
-The MIT License
-
-Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public/browse/lib/angular-mocks/angular-mocks.js b/public/browse/lib/angular-mocks/angular-mocks.js
deleted file mode 100644
index 3d33b2232..000000000
--- a/public/browse/lib/angular-mocks/angular-mocks.js
+++ /dev/null
@@ -1,2380 +0,0 @@
-/**
- * @license AngularJS v1.3.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {
-
-'use strict';
-
-/**
- * @ngdoc object
- * @name angular.mock
- * @description
- *
- * Namespace from 'angular-mocks.js' which contains testing related code.
- */
-angular.mock = {};
-
-/**
- * ! This is a private undocumented service !
- *
- * @name $browser
- *
- * @description
- * This service is a mock implementation of {@link ng.$browser}. It provides fake
- * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
- * cookies, etc...
- *
- * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
- * that there are several helper methods available which can be used in tests.
- */
-angular.mock.$BrowserProvider = function() {
- this.$get = function() {
- return new angular.mock.$Browser();
- };
-};
-
-angular.mock.$Browser = function() {
- var self = this;
-
- this.isMock = true;
- self.$$url = "http://server/";
- self.$$lastUrl = self.$$url; // used by url polling fn
- self.pollFns = [];
-
- // TODO(vojta): remove this temporary api
- self.$$completeOutstandingRequest = angular.noop;
- self.$$incOutstandingRequestCount = angular.noop;
-
-
- // register url polling fn
-
- self.onUrlChange = function(listener) {
- self.pollFns.push(
- function() {
- if (self.$$lastUrl !== self.$$url || self.$$state !== self.$$lastState) {
- self.$$lastUrl = self.$$url;
- self.$$lastState = self.$$state;
- listener(self.$$url, self.$$state);
- }
- }
- );
-
- return listener;
- };
-
- self.$$checkUrlChange = angular.noop;
-
- self.cookieHash = {};
- self.lastCookieHash = {};
- self.deferredFns = [];
- self.deferredNextId = 0;
-
- self.defer = function(fn, delay) {
- delay = delay || 0;
- self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
- self.deferredFns.sort(function(a, b) { return a.time - b.time;});
- return self.deferredNextId++;
- };
-
-
- /**
- * @name $browser#defer.now
- *
- * @description
- * Current milliseconds mock time.
- */
- self.defer.now = 0;
-
-
- self.defer.cancel = function(deferId) {
- var fnIndex;
-
- angular.forEach(self.deferredFns, function(fn, index) {
- if (fn.id === deferId) fnIndex = index;
- });
-
- if (fnIndex !== undefined) {
- self.deferredFns.splice(fnIndex, 1);
- return true;
- }
-
- return false;
- };
-
-
- /**
- * @name $browser#defer.flush
- *
- * @description
- * Flushes all pending requests and executes the defer callbacks.
- *
- * @param {number=} number of milliseconds to flush. See {@link #defer.now}
- */
- self.defer.flush = function(delay) {
- if (angular.isDefined(delay)) {
- self.defer.now += delay;
- } else {
- if (self.deferredFns.length) {
- self.defer.now = self.deferredFns[self.deferredFns.length - 1].time;
- } else {
- throw new Error('No deferred tasks to be flushed');
- }
- }
-
- while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
- self.deferredFns.shift().fn();
- }
- };
-
- self.$$baseHref = '/';
- self.baseHref = function() {
- return this.$$baseHref;
- };
-};
-angular.mock.$Browser.prototype = {
-
-/**
- * @name $browser#poll
- *
- * @description
- * run all fns in pollFns
- */
- poll: function poll() {
- angular.forEach(this.pollFns, function(pollFn) {
- pollFn();
- });
- },
-
- addPollFn: function(pollFn) {
- this.pollFns.push(pollFn);
- return pollFn;
- },
-
- url: function(url, replace, state) {
- if (angular.isUndefined(state)) {
- state = null;
- }
- if (url) {
- this.$$url = url;
- // Native pushState serializes & copies the object; simulate it.
- this.$$state = angular.copy(state);
- return this;
- }
-
- return this.$$url;
- },
-
- state: function() {
- return this.$$state;
- },
-
- cookies: function(name, value) {
- if (name) {
- if (angular.isUndefined(value)) {
- delete this.cookieHash[name];
- } else {
- if (angular.isString(value) && //strings only
- value.length <= 4096) { //strict cookie storage limits
- this.cookieHash[name] = value;
- }
- }
- } else {
- if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
- this.lastCookieHash = angular.copy(this.cookieHash);
- this.cookieHash = angular.copy(this.cookieHash);
- }
- return this.cookieHash;
- }
- },
-
- notifyWhenNoOutstandingRequests: function(fn) {
- fn();
- }
-};
-
-
-/**
- * @ngdoc provider
- * @name $exceptionHandlerProvider
- *
- * @description
- * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
- * passed to the `$exceptionHandler`.
- */
-
-/**
- * @ngdoc service
- * @name $exceptionHandler
- *
- * @description
- * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
- * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
- * information.
- *
- *
- * ```js
- * describe('$exceptionHandlerProvider', function() {
- *
- * it('should capture log messages and exceptions', function() {
- *
- * module(function($exceptionHandlerProvider) {
- * $exceptionHandlerProvider.mode('log');
- * });
- *
- * inject(function($log, $exceptionHandler, $timeout) {
- * $timeout(function() { $log.log(1); });
- * $timeout(function() { $log.log(2); throw 'banana peel'; });
- * $timeout(function() { $log.log(3); });
- * expect($exceptionHandler.errors).toEqual([]);
- * expect($log.assertEmpty());
- * $timeout.flush();
- * expect($exceptionHandler.errors).toEqual(['banana peel']);
- * expect($log.log.logs).toEqual([[1], [2], [3]]);
- * });
- * });
- * });
- * ```
- */
-
-angular.mock.$ExceptionHandlerProvider = function() {
- var handler;
-
- /**
- * @ngdoc method
- * @name $exceptionHandlerProvider#mode
- *
- * @description
- * Sets the logging mode.
- *
- * @param {string} mode Mode of operation, defaults to `rethrow`.
- *
- * - `rethrow`: If any errors are passed to the handler in tests, it typically means that there
- * is a bug in the application or test, so this mock will make these tests fail.
- * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
- * mode stores an array of errors in `$exceptionHandler.errors`, to allow later
- * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
- * {@link ngMock.$log#reset reset()}
- */
- this.mode = function(mode) {
- switch (mode) {
- case 'rethrow':
- handler = function(e) {
- throw e;
- };
- break;
- case 'log':
- var errors = [];
-
- handler = function(e) {
- if (arguments.length == 1) {
- errors.push(e);
- } else {
- errors.push([].slice.call(arguments, 0));
- }
- };
-
- handler.errors = errors;
- break;
- default:
- throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
- }
- };
-
- this.$get = function() {
- return handler;
- };
-
- this.mode('rethrow');
-};
-
-
-/**
- * @ngdoc service
- * @name $log
- *
- * @description
- * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
- * (one array per logging level). These arrays are exposed as `logs` property of each of the
- * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
- *
- */
-angular.mock.$LogProvider = function() {
- var debug = true;
-
- function concat(array1, array2, index) {
- return array1.concat(Array.prototype.slice.call(array2, index));
- }
-
- this.debugEnabled = function(flag) {
- if (angular.isDefined(flag)) {
- debug = flag;
- return this;
- } else {
- return debug;
- }
- };
-
- this.$get = function() {
- var $log = {
- log: function() { $log.log.logs.push(concat([], arguments, 0)); },
- warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
- info: function() { $log.info.logs.push(concat([], arguments, 0)); },
- error: function() { $log.error.logs.push(concat([], arguments, 0)); },
- debug: function() {
- if (debug) {
- $log.debug.logs.push(concat([], arguments, 0));
- }
- }
- };
-
- /**
- * @ngdoc method
- * @name $log#reset
- *
- * @description
- * Reset all of the logging arrays to empty.
- */
- $log.reset = function() {
- /**
- * @ngdoc property
- * @name $log#log.logs
- *
- * @description
- * Array of messages logged using {@link ng.$log#log `log()`}.
- *
- * @example
- * ```js
- * $log.log('Some Log');
- * var first = $log.log.logs.unshift();
- * ```
- */
- $log.log.logs = [];
- /**
- * @ngdoc property
- * @name $log#info.logs
- *
- * @description
- * Array of messages logged using {@link ng.$log#info `info()`}.
- *
- * @example
- * ```js
- * $log.info('Some Info');
- * var first = $log.info.logs.unshift();
- * ```
- */
- $log.info.logs = [];
- /**
- * @ngdoc property
- * @name $log#warn.logs
- *
- * @description
- * Array of messages logged using {@link ng.$log#warn `warn()`}.
- *
- * @example
- * ```js
- * $log.warn('Some Warning');
- * var first = $log.warn.logs.unshift();
- * ```
- */
- $log.warn.logs = [];
- /**
- * @ngdoc property
- * @name $log#error.logs
- *
- * @description
- * Array of messages logged using {@link ng.$log#error `error()`}.
- *
- * @example
- * ```js
- * $log.error('Some Error');
- * var first = $log.error.logs.unshift();
- * ```
- */
- $log.error.logs = [];
- /**
- * @ngdoc property
- * @name $log#debug.logs
- *
- * @description
- * Array of messages logged using {@link ng.$log#debug `debug()`}.
- *
- * @example
- * ```js
- * $log.debug('Some Error');
- * var first = $log.debug.logs.unshift();
- * ```
- */
- $log.debug.logs = [];
- };
-
- /**
- * @ngdoc method
- * @name $log#assertEmpty
- *
- * @description
- * Assert that all of the logging methods have no logged messages. If any messages are present,
- * an exception is thrown.
- */
- $log.assertEmpty = function() {
- var errors = [];
- angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
- angular.forEach($log[logLevel].logs, function(log) {
- angular.forEach(log, function(logItem) {
- errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
- (logItem.stack || ''));
- });
- });
- });
- if (errors.length) {
- errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or " +
- "an expected log message was not checked and removed:");
- errors.push('');
- throw new Error(errors.join('\n---------\n'));
- }
- };
-
- $log.reset();
- return $log;
- };
-};
-
-
-/**
- * @ngdoc service
- * @name $interval
- *
- * @description
- * Mock implementation of the $interval service.
- *
- * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
- * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
- * time.
- *
- * @param {function()} fn A function that should be called repeatedly.
- * @param {number} delay Number of milliseconds between each function call.
- * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
- * indefinitely.
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
- * @returns {promise} A promise which will be notified on each iteration.
- */
-angular.mock.$IntervalProvider = function() {
- this.$get = ['$browser', '$rootScope', '$q', '$$q',
- function($browser, $rootScope, $q, $$q) {
- var repeatFns = [],
- nextRepeatId = 0,
- now = 0;
-
- var $interval = function(fn, delay, count, invokeApply) {
- var iteration = 0,
- skipApply = (angular.isDefined(invokeApply) && !invokeApply),
- deferred = (skipApply ? $$q : $q).defer(),
- promise = deferred.promise;
-
- count = (angular.isDefined(count)) ? count : 0;
- promise.then(null, null, fn);
-
- promise.$$intervalId = nextRepeatId;
-
- function tick() {
- deferred.notify(iteration++);
-
- if (count > 0 && iteration >= count) {
- var fnIndex;
- deferred.resolve(iteration);
-
- angular.forEach(repeatFns, function(fn, index) {
- if (fn.id === promise.$$intervalId) fnIndex = index;
- });
-
- if (fnIndex !== undefined) {
- repeatFns.splice(fnIndex, 1);
- }
- }
-
- if (skipApply) {
- $browser.defer.flush();
- } else {
- $rootScope.$apply();
- }
- }
-
- repeatFns.push({
- nextTime:(now + delay),
- delay: delay,
- fn: tick,
- id: nextRepeatId,
- deferred: deferred
- });
- repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
-
- nextRepeatId++;
- return promise;
- };
- /**
- * @ngdoc method
- * @name $interval#cancel
- *
- * @description
- * Cancels a task associated with the `promise`.
- *
- * @param {promise} promise A promise from calling the `$interval` function.
- * @returns {boolean} Returns `true` if the task was successfully cancelled.
- */
- $interval.cancel = function(promise) {
- if (!promise) return false;
- var fnIndex;
-
- angular.forEach(repeatFns, function(fn, index) {
- if (fn.id === promise.$$intervalId) fnIndex = index;
- });
-
- if (fnIndex !== undefined) {
- repeatFns[fnIndex].deferred.reject('canceled');
- repeatFns.splice(fnIndex, 1);
- return true;
- }
-
- return false;
- };
-
- /**
- * @ngdoc method
- * @name $interval#flush
- * @description
- *
- * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
- *
- * @param {number=} millis maximum timeout amount to flush up until.
- *
- * @return {number} The amount of time moved forward.
- */
- $interval.flush = function(millis) {
- now += millis;
- while (repeatFns.length && repeatFns[0].nextTime <= now) {
- var task = repeatFns[0];
- task.fn();
- task.nextTime += task.delay;
- repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
- }
- return millis;
- };
-
- return $interval;
- }];
-};
-
-
-/* jshint -W101 */
-/* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
- * This directive should go inside the anonymous function but a bug in JSHint means that it would
- * not be enacted early enough to prevent the warning.
- */
-var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
-
-function jsonStringToDate(string) {
- var match;
- if (match = string.match(R_ISO8061_STR)) {
- var date = new Date(0),
- tzHour = 0,
- tzMin = 0;
- if (match[9]) {
- tzHour = int(match[9] + match[10]);
- tzMin = int(match[9] + match[11]);
- }
- date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
- date.setUTCHours(int(match[4] || 0) - tzHour,
- int(match[5] || 0) - tzMin,
- int(match[6] || 0),
- int(match[7] || 0));
- return date;
- }
- return string;
-}
-
-function int(str) {
- return parseInt(str, 10);
-}
-
-function padNumber(num, digits, trim) {
- var neg = '';
- if (num < 0) {
- neg = '-';
- num = -num;
- }
- num = '' + num;
- while (num.length < digits) num = '0' + num;
- if (trim)
- num = num.substr(num.length - digits);
- return neg + num;
-}
-
-
-/**
- * @ngdoc type
- * @name angular.mock.TzDate
- * @description
- *
- * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
- *
- * Mock of the Date type which has its timezone specified via constructor arg.
- *
- * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
- * offset, so that we can test code that depends on local timezone settings without dependency on
- * the time zone settings of the machine where the code is running.
- *
- * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
- * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
- *
- * @example
- * !!!! WARNING !!!!!
- * This is not a complete Date object so only methods that were implemented can be called safely.
- * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
- *
- * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
- * incomplete we might be missing some non-standard methods. This can result in errors like:
- * "Date.prototype.foo called on incompatible Object".
- *
- * ```js
- * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
- * newYearInBratislava.getTimezoneOffset() => -60;
- * newYearInBratislava.getFullYear() => 2010;
- * newYearInBratislava.getMonth() => 0;
- * newYearInBratislava.getDate() => 1;
- * newYearInBratislava.getHours() => 0;
- * newYearInBratislava.getMinutes() => 0;
- * newYearInBratislava.getSeconds() => 0;
- * ```
- *
- */
-angular.mock.TzDate = function(offset, timestamp) {
- var self = new Date(0);
- if (angular.isString(timestamp)) {
- var tsStr = timestamp;
-
- self.origDate = jsonStringToDate(timestamp);
-
- timestamp = self.origDate.getTime();
- if (isNaN(timestamp))
- throw {
- name: "Illegal Argument",
- message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
- };
- } else {
- self.origDate = new Date(timestamp);
- }
-
- var localOffset = new Date(timestamp).getTimezoneOffset();
- self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
- self.date = new Date(timestamp + self.offsetDiff);
-
- self.getTime = function() {
- return self.date.getTime() - self.offsetDiff;
- };
-
- self.toLocaleDateString = function() {
- return self.date.toLocaleDateString();
- };
-
- self.getFullYear = function() {
- return self.date.getFullYear();
- };
-
- self.getMonth = function() {
- return self.date.getMonth();
- };
-
- self.getDate = function() {
- return self.date.getDate();
- };
-
- self.getHours = function() {
- return self.date.getHours();
- };
-
- self.getMinutes = function() {
- return self.date.getMinutes();
- };
-
- self.getSeconds = function() {
- return self.date.getSeconds();
- };
-
- self.getMilliseconds = function() {
- return self.date.getMilliseconds();
- };
-
- self.getTimezoneOffset = function() {
- return offset * 60;
- };
-
- self.getUTCFullYear = function() {
- return self.origDate.getUTCFullYear();
- };
-
- self.getUTCMonth = function() {
- return self.origDate.getUTCMonth();
- };
-
- self.getUTCDate = function() {
- return self.origDate.getUTCDate();
- };
-
- self.getUTCHours = function() {
- return self.origDate.getUTCHours();
- };
-
- self.getUTCMinutes = function() {
- return self.origDate.getUTCMinutes();
- };
-
- self.getUTCSeconds = function() {
- return self.origDate.getUTCSeconds();
- };
-
- self.getUTCMilliseconds = function() {
- return self.origDate.getUTCMilliseconds();
- };
-
- self.getDay = function() {
- return self.date.getDay();
- };
-
- // provide this method only on browsers that already have it
- if (self.toISOString) {
- self.toISOString = function() {
- return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
- padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
- padNumber(self.origDate.getUTCDate(), 2) + 'T' +
- padNumber(self.origDate.getUTCHours(), 2) + ':' +
- padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
- padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
- padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
- };
- }
-
- //hide all methods not implemented in this mock that the Date prototype exposes
- var unimplementedMethods = ['getUTCDay',
- 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
- 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
- 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
- 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
- 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
-
- angular.forEach(unimplementedMethods, function(methodName) {
- self[methodName] = function() {
- throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
- };
- });
-
- return self;
-};
-
-//make "tzDateInstance instanceof Date" return true
-angular.mock.TzDate.prototype = Date.prototype;
-/* jshint +W101 */
-
-angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
-
- .config(['$provide', function($provide) {
-
- var reflowQueue = [];
- $provide.value('$$animateReflow', function(fn) {
- var index = reflowQueue.length;
- reflowQueue.push(fn);
- return function cancel() {
- reflowQueue.splice(index, 1);
- };
- });
-
- $provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser',
- function($delegate, $$asyncCallback, $timeout, $browser) {
- var animate = {
- queue: [],
- cancel: $delegate.cancel,
- enabled: $delegate.enabled,
- triggerCallbackEvents: function() {
- $$asyncCallback.flush();
- },
- triggerCallbackPromise: function() {
- $timeout.flush(0);
- },
- triggerCallbacks: function() {
- this.triggerCallbackEvents();
- this.triggerCallbackPromise();
- },
- triggerReflow: function() {
- angular.forEach(reflowQueue, function(fn) {
- fn();
- });
- reflowQueue = [];
- }
- };
-
- angular.forEach(
- ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {
- animate[method] = function() {
- animate.queue.push({
- event: method,
- element: arguments[0],
- options: arguments[arguments.length - 1],
- args: arguments
- });
- return $delegate[method].apply($delegate, arguments);
- };
- });
-
- return animate;
- }]);
-
- }]);
-
-
-/**
- * @ngdoc function
- * @name angular.mock.dump
- * @description
- *
- * *NOTE*: this is not an injectable instance, just a globally available function.
- *
- * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
- * debugging.
- *
- * This method is also available on window, where it can be used to display objects on debug
- * console.
- *
- * @param {*} object - any object to turn into string.
- * @return {string} a serialized string of the argument
- */
-angular.mock.dump = function(object) {
- return serialize(object);
-
- function serialize(object) {
- var out;
-
- if (angular.isElement(object)) {
- object = angular.element(object);
- out = angular.element('');
- angular.forEach(object, function(element) {
- out.append(angular.element(element).clone());
- });
- out = out.html();
- } else if (angular.isArray(object)) {
- out = [];
- angular.forEach(object, function(o) {
- out.push(serialize(o));
- });
- out = '[ ' + out.join(', ') + ' ]';
- } else if (angular.isObject(object)) {
- if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
- out = serializeScope(object);
- } else if (object instanceof Error) {
- out = object.stack || ('' + object.name + ': ' + object.message);
- } else {
- // TODO(i): this prevents methods being logged,
- // we should have a better way to serialize objects
- out = angular.toJson(object, true);
- }
- } else {
- out = String(object);
- }
-
- return out;
- }
-
- function serializeScope(scope, offset) {
- offset = offset || ' ';
- var log = [offset + 'Scope(' + scope.$id + '): {'];
- for (var key in scope) {
- if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
- log.push(' ' + key + ': ' + angular.toJson(scope[key]));
- }
- }
- var child = scope.$$childHead;
- while (child) {
- log.push(serializeScope(child, offset + ' '));
- child = child.$$nextSibling;
- }
- log.push('}');
- return log.join('\n' + offset);
- }
-};
-
-/**
- * @ngdoc service
- * @name $httpBackend
- * @description
- * Fake HTTP backend implementation suitable for unit testing applications that use the
- * {@link ng.$http $http service}.
- *
- * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
- * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
- *
- * During unit testing, we want our unit tests to run quickly and have no external dependencies so
- * we don’t want to send [XHR](https://developer.mozilla.org/en/xmlhttprequest) or
- * [JSONP](http://en.wikipedia.org/wiki/JSONP) requests to a real server. All we really need is
- * to verify whether a certain request has been sent or not, or alternatively just let the
- * application make requests, respond with pre-trained responses and assert that the end result is
- * what we expect it to be.
- *
- * This mock implementation can be used to respond with static or dynamic responses via the
- * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
- *
- * When an Angular application needs some data from a server, it calls the $http service, which
- * sends the request to a real server using $httpBackend service. With dependency injection, it is
- * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
- * the requests and respond with some testing data without sending a request to a real server.
- *
- * There are two ways to specify what test data should be returned as http responses by the mock
- * backend when the code under test makes http requests:
- *
- * - `$httpBackend.expect` - specifies a request expectation
- * - `$httpBackend.when` - specifies a backend definition
- *
- *
- * # Request Expectations vs Backend Definitions
- *
- * Request expectations provide a way to make assertions about requests made by the application and
- * to define responses for those requests. The test will fail if the expected requests are not made
- * or they are made in the wrong order.
- *
- * Backend definitions allow you to define a fake backend for your application which doesn't assert
- * if a particular request was made or not, it just returns a trained response if a request is made.
- * The test will pass whether or not the request gets made during testing.
- *
- *
- *
- *
Request expectations
Backend definitions
- *
- *
Syntax
- *
.expect(...).respond(...)
- *
.when(...).respond(...)
- *
- *
- *
Typical usage
- *
strict unit tests
- *
loose (black-box) unit testing
- *
- *
- *
Fulfills multiple requests
- *
NO
- *
YES
- *
- *
- *
Order of requests matters
- *
YES
- *
NO
- *
- *
- *
Request required
- *
YES
- *
NO
- *
- *
- *
Response required
- *
optional (see below)
- *
YES
- *
- *
- *
- * In cases where both backend definitions and request expectations are specified during unit
- * testing, the request expectations are evaluated first.
- *
- * If a request expectation has no response specified, the algorithm will search your backend
- * definitions for an appropriate response.
- *
- * If a request didn't match any expectation or if the expectation doesn't have the response
- * defined, the backend definitions are evaluated in sequential order to see if any of them match
- * the request. The response from the first matched definition is returned.
- *
- *
- * # Flushing HTTP requests
- *
- * The $httpBackend used in production always responds to requests asynchronously. If we preserved
- * this behavior in unit testing, we'd have to create async unit tests, which are hard to write,
- * to follow and to maintain. But neither can the testing mock respond synchronously; that would
- * change the execution of the code under test. For this reason, the mock $httpBackend has a
- * `flush()` method, which allows the test to explicitly flush pending requests. This preserves
- * the async api of the backend, while allowing the test to execute synchronously.
- *
- *
- * # Unit testing with mock $httpBackend
- * The following code shows how to setup and use the mock backend when unit testing a controller.
- * First we create the controller under test:
- *
- ```js
- // The module code
- angular
- .module('MyApp', [])
- .controller('MyController', MyController);
-
- // The controller code
- function MyController($scope, $http) {
- var authToken;
-
- $http.get('/auth.py').success(function(data, status, headers) {
- authToken = headers('A-Token');
- $scope.user = data;
- });
-
- $scope.saveMessage = function(message) {
- var headers = { 'Authorization': authToken };
- $scope.status = 'Saving...';
-
- $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
- $scope.status = '';
- }).error(function() {
- $scope.status = 'ERROR!';
- });
- };
- }
- ```
- *
- * Now we setup the mock backend and create the test specs:
- *
- ```js
- // testing controller
- describe('MyController', function() {
- var $httpBackend, $rootScope, createController, authRequestHandler;
-
- // Set up the module
- beforeEach(module('MyApp'));
-
- beforeEach(inject(function($injector) {
- // Set up the mock http service responses
- $httpBackend = $injector.get('$httpBackend');
- // backend definition common for all tests
- authRequestHandler = $httpBackend.when('GET', '/auth.py')
- .respond({userId: 'userX'}, {'A-Token': 'xxx'});
-
- // Get hold of a scope (i.e. the root scope)
- $rootScope = $injector.get('$rootScope');
- // The $controller service is used to create instances of controllers
- var $controller = $injector.get('$controller');
-
- createController = function() {
- return $controller('MyController', {'$scope' : $rootScope });
- };
- }));
-
-
- afterEach(function() {
- $httpBackend.verifyNoOutstandingExpectation();
- $httpBackend.verifyNoOutstandingRequest();
- });
-
-
- it('should fetch authentication token', function() {
- $httpBackend.expectGET('/auth.py');
- var controller = createController();
- $httpBackend.flush();
- });
-
-
- it('should fail authentication', function() {
-
- // Notice how you can change the response even after it was set
- authRequestHandler.respond(401, '');
-
- $httpBackend.expectGET('/auth.py');
- var controller = createController();
- $httpBackend.flush();
- expect($rootScope.status).toBe('Failed...');
- });
-
-
- it('should send msg to server', function() {
- var controller = createController();
- $httpBackend.flush();
-
- // now you don’t care about the authentication, but
- // the controller will still send the request and
- // $httpBackend will respond without you having to
- // specify the expectation and response for this request
-
- $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
- $rootScope.saveMessage('message content');
- expect($rootScope.status).toBe('Saving...');
- $httpBackend.flush();
- expect($rootScope.status).toBe('');
- });
-
-
- it('should send auth header', function() {
- var controller = createController();
- $httpBackend.flush();
-
- $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
- // check if the header was send, if it wasn't the expectation won't
- // match the request and the test will fail
- return headers['Authorization'] == 'xxx';
- }).respond(201, '');
-
- $rootScope.saveMessage('whatever');
- $httpBackend.flush();
- });
- });
- ```
- */
-angular.mock.$HttpBackendProvider = function() {
- this.$get = ['$rootScope', createHttpBackendMock];
-};
-
-/**
- * General factory function for $httpBackend mock.
- * Returns instance for unit testing (when no arguments specified):
- * - passing through is disabled
- * - auto flushing is disabled
- *
- * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
- * - passing through (delegating request to real backend) is enabled
- * - auto flushing is enabled
- *
- * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
- * @param {Object=} $browser Auto-flushing enabled if specified
- * @return {Object} Instance of $httpBackend mock
- */
-function createHttpBackendMock($rootScope, $delegate, $browser) {
- var definitions = [],
- expectations = [],
- responses = [],
- responsesPush = angular.bind(responses, responses.push),
- copy = angular.copy;
-
- function createResponse(status, data, headers, statusText) {
- if (angular.isFunction(status)) return status;
-
- return function() {
- return angular.isNumber(status)
- ? [status, data, headers, statusText]
- : [200, status, data, headers];
- };
- }
-
- // TODO(vojta): change params to: method, url, data, headers, callback
- function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
- var xhr = new MockXhr(),
- expectation = expectations[0],
- wasExpected = false;
-
- function prettyPrint(data) {
- return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
- ? data
- : angular.toJson(data);
- }
-
- function wrapResponse(wrapped) {
- if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
-
- return handleResponse;
-
- function handleResponse() {
- var response = wrapped.response(method, url, data, headers);
- xhr.$$respHeaders = response[2];
- callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
- copy(response[3] || ''));
- }
-
- function handleTimeout() {
- for (var i = 0, ii = responses.length; i < ii; i++) {
- if (responses[i] === handleResponse) {
- responses.splice(i, 1);
- callback(-1, undefined, '');
- break;
- }
- }
- }
- }
-
- if (expectation && expectation.match(method, url)) {
- if (!expectation.matchData(data))
- throw new Error('Expected ' + expectation + ' with different data\n' +
- 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
-
- if (!expectation.matchHeaders(headers))
- throw new Error('Expected ' + expectation + ' with different headers\n' +
- 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
- prettyPrint(headers));
-
- expectations.shift();
-
- if (expectation.response) {
- responses.push(wrapResponse(expectation));
- return;
- }
- wasExpected = true;
- }
-
- var i = -1, definition;
- while ((definition = definitions[++i])) {
- if (definition.match(method, url, data, headers || {})) {
- if (definition.response) {
- // if $browser specified, we do auto flush all requests
- ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
- } else if (definition.passThrough) {
- $delegate(method, url, data, callback, headers, timeout, withCredentials);
- } else throw new Error('No response defined !');
- return;
- }
- }
- throw wasExpected ?
- new Error('No response defined !') :
- new Error('Unexpected request: ' + method + ' ' + url + '\n' +
- (expectation ? 'Expected ' + expectation : 'No more request expected'));
- }
-
- /**
- * @ngdoc method
- * @name $httpBackend#when
- * @description
- * Creates a new backend definition.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
- * data string and returns true if the data is as expected.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current definition.
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- *
- * - respond –
- * `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can
- * return an array containing response status (number), response data (string), response
- * headers (Object), and the text for the status (string). The respond method returns the
- * `requestHandler` object for possible overrides.
- */
- $httpBackend.when = function(method, url, data, headers) {
- var definition = new MockHttpExpectation(method, url, data, headers),
- chain = {
- respond: function(status, data, headers, statusText) {
- definition.passThrough = undefined;
- definition.response = createResponse(status, data, headers, statusText);
- return chain;
- }
- };
-
- if ($browser) {
- chain.passThrough = function() {
- definition.response = undefined;
- definition.passThrough = true;
- return chain;
- };
- }
-
- definitions.push(definition);
- return chain;
- };
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenGET
- * @description
- * Creates a new backend definition for GET requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenHEAD
- * @description
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenDELETE
- * @description
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenPOST
- * @description
- * Creates a new backend definition for POST requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
- * data string and returns true if the data is as expected.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenPUT
- * @description
- * Creates a new backend definition for PUT requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
- * data string and returns true if the data is as expected.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#whenJSONP
- * @description
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
- createShortMethods('when');
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#expect
- * @description
- * Creates a new request expectation.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
- * receives data string and returns true if the data is as expected, or Object if request body
- * is in JSON format.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current expectation.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- *
- * - respond –
- * `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can
- * return an array containing response status (number), response data (string), response
- * headers (Object), and the text for the status (string). The respond method returns the
- * `requestHandler` object for possible overrides.
- */
- $httpBackend.expect = function(method, url, data, headers) {
- var expectation = new MockHttpExpectation(method, url, data, headers),
- chain = {
- respond: function(status, data, headers, statusText) {
- expectation.response = createResponse(status, data, headers, statusText);
- return chain;
- }
- };
-
- expectations.push(expectation);
- return chain;
- };
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectGET
- * @description
- * Creates a new request expectation for GET requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled. See #expect for more info.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectHEAD
- * @description
- * Creates a new request expectation for HEAD requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectDELETE
- * @description
- * Creates a new request expectation for DELETE requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectPOST
- * @description
- * Creates a new request expectation for POST requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
- * receives data string and returns true if the data is as expected, or Object if request body
- * is in JSON format.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectPUT
- * @description
- * Creates a new request expectation for PUT requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
- * receives data string and returns true if the data is as expected, or Object if request body
- * is in JSON format.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectPATCH
- * @description
- * Creates a new request expectation for PATCH requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
- * receives data string and returns true if the data is as expected, or Object if request body
- * is in JSON format.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
-
- /**
- * @ngdoc method
- * @name $httpBackend#expectJSONP
- * @description
- * Creates a new request expectation for JSONP requests. For more info see `expect()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled.
- */
- createShortMethods('expect');
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#flush
- * @description
- * Flushes all pending requests using the trained responses.
- *
- * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
- * all pending requests will be flushed. If there are no pending requests when the flush method
- * is called an exception is thrown (as this typically a sign of programming error).
- */
- $httpBackend.flush = function(count, digest) {
- if (digest !== false) $rootScope.$digest();
- if (!responses.length) throw new Error('No pending request to flush !');
-
- if (angular.isDefined(count) && count !== null) {
- while (count--) {
- if (!responses.length) throw new Error('No more pending request to flush !');
- responses.shift()();
- }
- } else {
- while (responses.length) {
- responses.shift()();
- }
- }
- $httpBackend.verifyNoOutstandingExpectation(digest);
- };
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#verifyNoOutstandingExpectation
- * @description
- * Verifies that all of the requests defined via the `expect` api were made. If any of the
- * requests were not made, verifyNoOutstandingExpectation throws an exception.
- *
- * Typically, you would call this method following each test case that asserts requests using an
- * "afterEach" clause.
- *
- * ```js
- * afterEach($httpBackend.verifyNoOutstandingExpectation);
- * ```
- */
- $httpBackend.verifyNoOutstandingExpectation = function(digest) {
- if (digest !== false) $rootScope.$digest();
- if (expectations.length) {
- throw new Error('Unsatisfied requests: ' + expectations.join(', '));
- }
- };
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#verifyNoOutstandingRequest
- * @description
- * Verifies that there are no outstanding requests that need to be flushed.
- *
- * Typically, you would call this method following each test case that asserts requests using an
- * "afterEach" clause.
- *
- * ```js
- * afterEach($httpBackend.verifyNoOutstandingRequest);
- * ```
- */
- $httpBackend.verifyNoOutstandingRequest = function() {
- if (responses.length) {
- throw new Error('Unflushed requests: ' + responses.length);
- }
- };
-
-
- /**
- * @ngdoc method
- * @name $httpBackend#resetExpectations
- * @description
- * Resets all request expectations, but preserves all backend definitions. Typically, you would
- * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
- * $httpBackend mock.
- */
- $httpBackend.resetExpectations = function() {
- expectations.length = 0;
- responses.length = 0;
- };
-
- return $httpBackend;
-
-
- function createShortMethods(prefix) {
- angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
- $httpBackend[prefix + method] = function(url, headers) {
- return $httpBackend[prefix](method, url, undefined, headers);
- };
- });
-
- angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
- $httpBackend[prefix + method] = function(url, data, headers) {
- return $httpBackend[prefix](method, url, data, headers);
- };
- });
- }
-}
-
-function MockHttpExpectation(method, url, data, headers) {
-
- this.data = data;
- this.headers = headers;
-
- this.match = function(m, u, d, h) {
- if (method != m) return false;
- if (!this.matchUrl(u)) return false;
- if (angular.isDefined(d) && !this.matchData(d)) return false;
- if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
- return true;
- };
-
- this.matchUrl = function(u) {
- if (!url) return true;
- if (angular.isFunction(url.test)) return url.test(u);
- if (angular.isFunction(url)) return url(u);
- return url == u;
- };
-
- this.matchHeaders = function(h) {
- if (angular.isUndefined(headers)) return true;
- if (angular.isFunction(headers)) return headers(h);
- return angular.equals(headers, h);
- };
-
- this.matchData = function(d) {
- if (angular.isUndefined(data)) return true;
- if (data && angular.isFunction(data.test)) return data.test(d);
- if (data && angular.isFunction(data)) return data(d);
- if (data && !angular.isString(data)) {
- return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d));
- }
- return data == d;
- };
-
- this.toString = function() {
- return method + ' ' + url;
- };
-}
-
-function createMockXhr() {
- return new MockXhr();
-}
-
-function MockXhr() {
-
- // hack for testing $http, $httpBackend
- MockXhr.$$lastInstance = this;
-
- this.open = function(method, url, async) {
- this.$$method = method;
- this.$$url = url;
- this.$$async = async;
- this.$$reqHeaders = {};
- this.$$respHeaders = {};
- };
-
- this.send = function(data) {
- this.$$data = data;
- };
-
- this.setRequestHeader = function(key, value) {
- this.$$reqHeaders[key] = value;
- };
-
- this.getResponseHeader = function(name) {
- // the lookup must be case insensitive,
- // that's why we try two quick lookups first and full scan last
- var header = this.$$respHeaders[name];
- if (header) return header;
-
- name = angular.lowercase(name);
- header = this.$$respHeaders[name];
- if (header) return header;
-
- header = undefined;
- angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
- if (!header && angular.lowercase(headerName) == name) header = headerVal;
- });
- return header;
- };
-
- this.getAllResponseHeaders = function() {
- var lines = [];
-
- angular.forEach(this.$$respHeaders, function(value, key) {
- lines.push(key + ': ' + value);
- });
- return lines.join('\n');
- };
-
- this.abort = angular.noop;
-}
-
-
-/**
- * @ngdoc service
- * @name $timeout
- * @description
- *
- * This service is just a simple decorator for {@link ng.$timeout $timeout} service
- * that adds a "flush" and "verifyNoPendingTasks" methods.
- */
-
-angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) {
-
- /**
- * @ngdoc method
- * @name $timeout#flush
- * @description
- *
- * Flushes the queue of pending tasks.
- *
- * @param {number=} delay maximum timeout amount to flush up until
- */
- $delegate.flush = function(delay) {
- $browser.defer.flush(delay);
- };
-
- /**
- * @ngdoc method
- * @name $timeout#verifyNoPendingTasks
- * @description
- *
- * Verifies that there are no pending tasks that need to be flushed.
- */
- $delegate.verifyNoPendingTasks = function() {
- if ($browser.deferredFns.length) {
- throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
- formatPendingTasksAsString($browser.deferredFns));
- }
- };
-
- function formatPendingTasksAsString(tasks) {
- var result = [];
- angular.forEach(tasks, function(task) {
- result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
- });
-
- return result.join(', ');
- }
-
- return $delegate;
-}];
-
-angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
- var queue = [];
- var rafFn = function(fn) {
- var index = queue.length;
- queue.push(fn);
- return function() {
- queue.splice(index, 1);
- };
- };
-
- rafFn.supported = $delegate.supported;
-
- rafFn.flush = function() {
- if (queue.length === 0) {
- throw new Error('No rAF callbacks present');
- }
-
- var length = queue.length;
- for (var i = 0; i < length; i++) {
- queue[i]();
- }
-
- queue = [];
- };
-
- return rafFn;
-}];
-
-angular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {
- var callbacks = [];
- var addFn = function(fn) {
- callbacks.push(fn);
- };
- addFn.flush = function() {
- angular.forEach(callbacks, function(fn) {
- fn();
- });
- callbacks = [];
- };
- return addFn;
-}];
-
-/**
- *
- */
-angular.mock.$RootElementProvider = function() {
- this.$get = function() {
- return angular.element('');
- };
-};
-
-/**
- * @ngdoc module
- * @name ngMock
- * @packageName angular-mocks
- * @description
- *
- * # ngMock
- *
- * The `ngMock` module provides support to inject and mock Angular services into unit tests.
- * In addition, ngMock also extends various core ng services such that they can be
- * inspected and controlled in a synchronous manner within test code.
- *
- *
- *
- *
- */
-angular.module('ngMock', ['ng']).provider({
- $browser: angular.mock.$BrowserProvider,
- $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
- $log: angular.mock.$LogProvider,
- $interval: angular.mock.$IntervalProvider,
- $httpBackend: angular.mock.$HttpBackendProvider,
- $rootElement: angular.mock.$RootElementProvider
-}).config(['$provide', function($provide) {
- $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
- $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
- $provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);
- $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
-}]);
-
-/**
- * @ngdoc module
- * @name ngMockE2E
- * @module ngMockE2E
- * @packageName angular-mocks
- * @description
- *
- * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
- * Currently there is only one mock present in this module -
- * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
- */
-angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
- $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
-}]);
-
-/**
- * @ngdoc service
- * @name $httpBackend
- * @module ngMockE2E
- * @description
- * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
- * applications that use the {@link ng.$http $http service}.
- *
- * *Note*: For fake http backend implementation suitable for unit testing please see
- * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
- *
- * This implementation can be used to respond with static or dynamic responses via the `when` api
- * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
- * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
- * templates from a webserver).
- *
- * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
- * is being developed with the real backend api replaced with a mock, it is often desirable for
- * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
- * templates or static files from the webserver). To configure the backend with this behavior
- * use the `passThrough` request handler of `when` instead of `respond`.
- *
- * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
- * testing. For this reason the e2e $httpBackend flushes mocked out requests
- * automatically, closely simulating the behavior of the XMLHttpRequest object.
- *
- * To setup the application to run with this http backend, you have to create a module that depends
- * on the `ngMockE2E` and your application modules and defines the fake backend:
- *
- * ```js
- * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
- * myAppDev.run(function($httpBackend) {
- * phones = [{name: 'phone1'}, {name: 'phone2'}];
- *
- * // returns the current list of phones
- * $httpBackend.whenGET('/phones').respond(phones);
- *
- * // adds a new phone to the phones array
- * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
- * var phone = angular.fromJson(data);
- * phones.push(phone);
- * return [200, phone, {}];
- * });
- * $httpBackend.whenGET(/^\/templates\//).passThrough();
- * //...
- * });
- * ```
- *
- * Afterwards, bootstrap your app with this new module.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#when
- * @module ngMockE2E
- * @description
- * Creates a new backend definition.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current definition.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- *
- * - respond –
- * `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can return
- * an array containing response status (number), response data (string), response headers
- * (Object), and the text for the status (string).
- * - passThrough – `{function()}` – Any request matching a backend definition with
- * `passThrough` handler will be passed through to the real backend (an XHR request will be made
- * to the server.)
- * - Both methods return the `requestHandler` object for possible overrides.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenGET
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for GET requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenHEAD
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenDELETE
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenPOST
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for POST requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenPUT
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for PUT requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenPATCH
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for PATCH requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name $httpBackend#whenJSONP
- * @module ngMockE2E
- * @description
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
- *
- * @param {string|RegExp|function(string)} url HTTP url or function that receives the url
- * and returns true if the url match the current definition.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-angular.mock.e2e = {};
-angular.mock.e2e.$httpBackendDecorator =
- ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
-
-
-/**
- * @ngdoc type
- * @name $rootScope.Scope
- * @module ngMock
- * @description
- * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These
- * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when
- * `ngMock` module is loaded.
- *
- * In addition to all the regular `Scope` methods, the following helper methods are available:
- */
-angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
-
- var $rootScopePrototype = Object.getPrototypeOf($delegate);
-
- $rootScopePrototype.$countChildScopes = countChildScopes;
- $rootScopePrototype.$countWatchers = countWatchers;
-
- return $delegate;
-
- // ------------------------------------------------------------------------------------------ //
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$countChildScopes
- * @module ngMock
- * @description
- * Counts all the direct and indirect child scopes of the current scope.
- *
- * The current scope is excluded from the count. The count includes all isolate child scopes.
- *
- * @returns {number} Total number of child scopes.
- */
- function countChildScopes() {
- // jshint validthis: true
- var count = 0; // exclude the current scope
- var pendingChildHeads = [this.$$childHead];
- var currentScope;
-
- while (pendingChildHeads.length) {
- currentScope = pendingChildHeads.shift();
-
- while (currentScope) {
- count += 1;
- pendingChildHeads.push(currentScope.$$childHead);
- currentScope = currentScope.$$nextSibling;
- }
- }
-
- return count;
- }
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$countWatchers
- * @module ngMock
- * @description
- * Counts all the watchers of direct and indirect child scopes of the current scope.
- *
- * The watchers of the current scope are included in the count and so are all the watchers of
- * isolate child scopes.
- *
- * @returns {number} Total number of watchers.
- */
- function countWatchers() {
- // jshint validthis: true
- var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope
- var pendingChildHeads = [this.$$childHead];
- var currentScope;
-
- while (pendingChildHeads.length) {
- currentScope = pendingChildHeads.shift();
-
- while (currentScope) {
- count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
- pendingChildHeads.push(currentScope.$$childHead);
- currentScope = currentScope.$$nextSibling;
- }
- }
-
- return count;
- }
-}];
-
-
-if (window.jasmine || window.mocha) {
-
- var currentSpec = null,
- isSpecRunning = function() {
- return !!currentSpec;
- };
-
-
- (window.beforeEach || window.setup)(function() {
- currentSpec = this;
- });
-
- (window.afterEach || window.teardown)(function() {
- var injector = currentSpec.$injector;
-
- angular.forEach(currentSpec.$modules, function(module) {
- if (module && module.$$hashKey) {
- module.$$hashKey = undefined;
- }
- });
-
- currentSpec.$injector = null;
- currentSpec.$modules = null;
- currentSpec = null;
-
- if (injector) {
- injector.get('$rootElement').off();
- injector.get('$browser').pollFns.length = 0;
- }
-
- // clean up jquery's fragment cache
- angular.forEach(angular.element.fragments, function(val, key) {
- delete angular.element.fragments[key];
- });
-
- MockXhr.$$lastInstance = null;
-
- angular.forEach(angular.callbacks, function(val, key) {
- delete angular.callbacks[key];
- });
- angular.callbacks.counter = 0;
- });
-
- /**
- * @ngdoc function
- * @name angular.mock.module
- * @description
- *
- * *NOTE*: This function is also published on window for easy access.
- * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
- *
- * This function registers a module configuration code. It collects the configuration information
- * which will be used when the injector is created by {@link angular.mock.inject inject}.
- *
- * See {@link angular.mock.inject inject} for usage example
- *
- * @param {...(string|Function|Object)} fns any number of modules which are represented as string
- * aliases or as anonymous module initialization functions. The modules are used to
- * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
- * object literal is passed they will be registered as values in the module, the key being
- * the module name and the value being what is returned.
- */
- window.module = angular.mock.module = function() {
- var moduleFns = Array.prototype.slice.call(arguments, 0);
- return isSpecRunning() ? workFn() : workFn;
- /////////////////////
- function workFn() {
- if (currentSpec.$injector) {
- throw new Error('Injector already created, can not register a module!');
- } else {
- var modules = currentSpec.$modules || (currentSpec.$modules = []);
- angular.forEach(moduleFns, function(module) {
- if (angular.isObject(module) && !angular.isArray(module)) {
- modules.push(function($provide) {
- angular.forEach(module, function(value, key) {
- $provide.value(key, value);
- });
- });
- } else {
- modules.push(module);
- }
- });
- }
- }
- };
-
- /**
- * @ngdoc function
- * @name angular.mock.inject
- * @description
- *
- * *NOTE*: This function is also published on window for easy access.
- * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
- *
- * The inject function wraps a function into an injectable function. The inject() creates new
- * instance of {@link auto.$injector $injector} per test, which is then used for
- * resolving references.
- *
- *
- * ## Resolving References (Underscore Wrapping)
- * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
- * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
- * that is declared in the scope of the `describe()` block. Since we would, most likely, want
- * the variable to have the same name of the reference we have a problem, since the parameter
- * to the `inject()` function would hide the outer variable.
- *
- * To help with this, the injected parameters can, optionally, be enclosed with underscores.
- * These are ignored by the injector when the reference name is resolved.
- *
- * For example, the parameter `_myService_` would be resolved as the reference `myService`.
- * Since it is available in the function body as _myService_, we can then assign it to a variable
- * defined in an outer scope.
- *
- * ```
- * // Defined out reference variable outside
- * var myService;
- *
- * // Wrap the parameter in underscores
- * beforeEach( inject( function(_myService_){
- * myService = _myService_;
- * }));
- *
- * // Use myService in a series of tests.
- * it('makes use of myService', function() {
- * myService.doStuff();
- * });
- *
- * ```
- *
- * See also {@link angular.mock.module angular.mock.module}
- *
- * ## Example
- * Example of what a typical jasmine tests looks like with the inject method.
- * ```js
- *
- * angular.module('myApplicationModule', [])
- * .value('mode', 'app')
- * .value('version', 'v1.0.1');
- *
- *
- * describe('MyApp', function() {
- *
- * // You need to load modules that you want to test,
- * // it loads only the "ng" module by default.
- * beforeEach(module('myApplicationModule'));
- *
- *
- * // inject() is used to inject arguments of all given functions
- * it('should provide a version', inject(function(mode, version) {
- * expect(version).toEqual('v1.0.1');
- * expect(mode).toEqual('app');
- * }));
- *
- *
- * // The inject and module method can also be used inside of the it or beforeEach
- * it('should override a version and test the new version is injected', function() {
- * // module() takes functions or strings (module aliases)
- * module(function($provide) {
- * $provide.value('version', 'overridden'); // override version here
- * });
- *
- * inject(function(version) {
- * expect(version).toEqual('overridden');
- * });
- * });
- * });
- *
- * ```
- *
- * @param {...Function} fns any number of functions which will be injected using the injector.
- */
-
-
-
- var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {
- this.message = e.message;
- this.name = e.name;
- if (e.line) this.line = e.line;
- if (e.sourceId) this.sourceId = e.sourceId;
- if (e.stack && errorForStack)
- this.stack = e.stack + '\n' + errorForStack.stack;
- if (e.stackArray) this.stackArray = e.stackArray;
- };
- ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;
-
- window.inject = angular.mock.inject = function() {
- var blockFns = Array.prototype.slice.call(arguments, 0);
- var errorForStack = new Error('Declaration Location');
- return isSpecRunning() ? workFn.call(currentSpec) : workFn;
- /////////////////////
- function workFn() {
- var modules = currentSpec.$modules || [];
- var strictDi = !!currentSpec.$injectorStrict;
- modules.unshift('ngMock');
- modules.unshift('ng');
- var injector = currentSpec.$injector;
- if (!injector) {
- if (strictDi) {
- // If strictDi is enabled, annotate the providerInjector blocks
- angular.forEach(modules, function(moduleFn) {
- if (typeof moduleFn === "function") {
- angular.injector.$$annotate(moduleFn);
- }
- });
- }
- injector = currentSpec.$injector = angular.injector(modules, strictDi);
- currentSpec.$injectorStrict = strictDi;
- }
- for (var i = 0, ii = blockFns.length; i < ii; i++) {
- if (currentSpec.$injectorStrict) {
- // If the injector is strict / strictDi, and the spec wants to inject using automatic
- // annotation, then annotate the function here.
- injector.annotate(blockFns[i]);
- }
- try {
- /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
- injector.invoke(blockFns[i] || angular.noop, this);
- /* jshint +W040 */
- } catch (e) {
- if (e.stack && errorForStack) {
- throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
- }
- throw e;
- } finally {
- errorForStack = null;
- }
- }
- }
- };
-
-
- angular.mock.inject.strictDi = function(value) {
- value = arguments.length ? !!value : true;
- return isSpecRunning() ? workFn() : workFn;
-
- function workFn() {
- if (value !== currentSpec.$injectorStrict) {
- if (currentSpec.$injector) {
- throw new Error('Injector already created, can not modify strict annotations');
- } else {
- currentSpec.$injectorStrict = value;
- }
- }
- }
- };
-}
-
-
-})(window, window.angular);
diff --git a/public/browse/lib/angular-mocks/bower.json b/public/browse/lib/angular-mocks/bower.json
deleted file mode 100644
index 739097ac6..000000000
--- a/public/browse/lib/angular-mocks/bower.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "angular-mocks",
- "version": "1.3.5",
- "main": "./angular-mocks.js",
- "ignore": [],
- "dependencies": {
- "angular": "1.3.5"
- }
-}
diff --git a/public/browse/lib/angular-mocks/package.json b/public/browse/lib/angular-mocks/package.json
deleted file mode 100644
index a4665805e..000000000
--- a/public/browse/lib/angular-mocks/package.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "name": "angular-mocks",
- "version": "1.3.5",
- "description": "AngularJS mocks for testing",
- "main": "angular-mocks.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/angular/angular.js.git"
- },
- "keywords": [
- "angular",
- "framework",
- "browser",
- "mocks",
- "testing",
- "client-side"
- ],
- "author": "Angular Core Team ",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/angular/angular.js/issues"
- },
- "homepage": "http://angularjs.org"
-}
diff --git a/public/browse/lib/angular-route/.bower.json b/public/browse/lib/angular-route/.bower.json
deleted file mode 100644
index 011e7abb2..000000000
--- a/public/browse/lib/angular-route/.bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "angular-route",
- "version": "1.3.5",
- "main": "./angular-route.js",
- "ignore": [],
- "dependencies": {
- "angular": "1.3.5"
- },
- "homepage": "https://github.com/angular/bower-angular-route",
- "_release": "1.3.5",
- "_resolution": {
- "type": "version",
- "tag": "v1.3.5",
- "commit": "4a949e84a15e474daa1cf0a4f4fbb3dd1f7536cb"
- },
- "_source": "git://github.com/angular/bower-angular-route.git",
- "_target": "1.3.x",
- "_originalSource": "angular-route"
-}
\ No newline at end of file
diff --git a/public/browse/lib/angular-route/README.md b/public/browse/lib/angular-route/README.md
deleted file mode 100644
index b33a0dc33..000000000
--- a/public/browse/lib/angular-route/README.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# packaged angular-route
-
-This repo is for distribution on `npm` and `bower`. The source for this module is in the
-[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngRoute).
-Please file issues and pull requests against that repo.
-
-## Install
-
-You can install this package either with `npm` or with `bower`.
-
-### npm
-
-```shell
-npm install angular-route
-```
-
-Add a `
-```
-
-Then add `ngRoute` as a dependency for your app:
-
-```javascript
-angular.module('myApp', ['ngRoute']);
-```
-
-Note that this package is not in CommonJS format, so doing `require('angular-route')` will
-return `undefined`.
-
-### bower
-
-```shell
-bower install angular-route
-```
-
-Add a `
-```
-
-Then add `ngRoute` as a dependency for your app:
-
-```javascript
-angular.module('myApp', ['ngRoute']);
-```
-
-## Documentation
-
-Documentation is available on the
-[AngularJS docs site](http://docs.angularjs.org/api/ngRoute).
-
-## License
-
-The MIT License
-
-Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/public/browse/lib/angular-route/angular-route.js b/public/browse/lib/angular-route/angular-route.js
deleted file mode 100644
index 2959c50b5..000000000
--- a/public/browse/lib/angular-route/angular-route.js
+++ /dev/null
@@ -1,996 +0,0 @@
-/**
- * @license AngularJS v1.3.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngRoute
- * @description
- *
- * # ngRoute
- *
- * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- *
- *
- */
- /* global -ngRouteModule */
-var ngRouteModule = angular.module('ngRoute', ['ng']).
- provider('$route', $RouteProvider),
- $routeMinErr = angular.$$minErr('ngRoute');
-
-/**
- * @ngdoc provider
- * @name $routeProvider
- *
- * @description
- *
- * Used for configuring routes.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- * ## Dependencies
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- */
-function $RouteProvider() {
- function inherit(parent, extra) {
- return angular.extend(Object.create(parent), extra);
- }
-
- var routes = {};
-
- /**
- * @ngdoc method
- * @name $routeProvider#when
- *
- * @param {string} path Route path (matched against `$location.path`). If `$location.path`
- * contains redundant trailing slash or is missing one, the route will still match and the
- * `$location.path` will be updated to add or drop the trailing slash to exactly match the
- * route definition.
- *
- * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
- * to the next slash are matched and stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain named groups starting with a colon and ending with a star:
- * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
- *
- * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
- * `/color/brown/largecode/code/with/slashes/edit` and extract:
- *
- * * `color: brown`
- * * `largecode: code/with/slashes`.
- *
- *
- * @param {Object} route Mapping information to be assigned to `$route.current` on route
- * match.
- *
- * Object properties:
- *
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
- * newly created scope or the name of a {@link angular.Module#controller registered
- * controller} if passed as a string.
- * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
- * published to scope under the `controllerAs` name.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used by {@link
- * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
- * This property takes precedence over `templateUrl`.
- *
- * If `template` is a function, it will be called with the following parameters:
- *
- * - `{Array.