diff --git a/.devcontainer/Dockerfile-devcontainer b/.devcontainer/Dockerfile-devcontainer index 7cb8beb26..7d832ddd3 100644 --- a/.devcontainer/Dockerfile-devcontainer +++ b/.devcontainer/Dockerfile-devcontainer @@ -1,5 +1,5 @@ -FROM node:18 +FROM node:20 -RUN apt-get update && \ - apt-get install -y npm python3 git make bash && \ - npm install --location=global npm@10.2.0 +RUN apt-get update && apt-get install -y default-jre + +RUN npm install --location=global npm@10.5.2 diff --git a/.devcontainer/custom.env b/.devcontainer/custom.env deleted file mode 100644 index 4c847aac5..000000000 --- a/.devcontainer/custom.env +++ /dev/null @@ -1,10 +0,0 @@ - -# dynamic_service_proxies=ORCIDLink -# Note that dynamic service proxies use the module name (preserve case), -# whereas core service proxies are typically lower_snake_cased. -# dynamic_service_proxies=NarrativePublisher -# service_proxies="DOIRequest orcidlink" -# service_proxies=orcidlink -# service_proxies=servicewidgetdemo -# service_proxies=staging_service -# local_narrative=t \ No newline at end of file diff --git a/.devcontainer/devcontainer.env b/.devcontainer/devcontainer.env deleted file mode 100644 index f913bec90..000000000 --- a/.devcontainer/devcontainer.env +++ /dev/null @@ -1 +0,0 @@ -DEPLOY_ENV=ci \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f0bcd370d..6c1e538be 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,12 +14,19 @@ // The optional 'workspaceFolder' property is the path VS Code should open by default when // connected. This is typically a file mount in .devcontainer/docker-compose.yml "workspaceFolder": "/workspace", - // Set *default* container specific settings.json values on container create. - "settings": {}, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "DavidAnson.vscode-markdownlint" - ], + "customizations": { + "vscode": { + "extensions": [ + "DavidAnson.vscode-markdownlint", + "jebbs.plantuml", + "srmeyers.git-prefix", + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "darkriszty.markdown-table-prettify" + ], + "settings": {} + } + }, // "containerEnv": { // "DEPLOY_ENV": "narrative-dev" // } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 62326960b..a3ce3ca11 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,107 +1,64 @@ -version: '3.6' +name: kbase-dev networks: - kbase-dev: - name: kbase-dev + kbase-dev: + name: kbase-dev services: - kbase-ui: - build: - context: . - dockerfile: Dockerfile-devcontainer - # just use dev for the image tag so we can easily clean - # up afterwards. - - image: kbase/kbase-ui:dev - - container_name: kbase-ui - dns: 8.8.8.8 - volumes: - # Update this to wherever you want VS Code to mount the folder of your project - - ..:/workspace:cached - # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details. - # - /var/run/docker.sock:/var/run/docker.sock - - # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust. - # cap_add: - # - SYS_PTRACE - # security_opt: - # - seccomp:unconfined - # volumes: - # - ${APP_DIR}:/kb/deployment/app - # Map local source into expected location within container - # - "${PWD}/react-app:/kb/deployment/app" - # # Map local configuration directory into expected location within container - # - "${PWD}/dev/gitlab-config:/kb/deployment/config" - # - ${PWD}/deployment/scripts:/kb/deployment/scripts - # # Map locally installed plugins into the expected location within container - # - ${PWD}/build/dist/deploy/plugins:/kb/deployment/app/public/deploy/plugins - # - ${SCRIPTS_DIR}:/kb/deployment/scripts - - # just use dev for the image tag so we can easily clean - # up afterwards. - # image: kbase/kbase-ui:dev - networks: - - kbase-dev - environment: - # - PORT=80 - - DEPLOY_ENV=${DEPLOY_ENV:-ci} - # - BASE_PATH= - # Required for a devcontainer -- keeps the container running. - # Don't worry, our main interaction with the container is through the - # VSC terminal, which for a devcontainer opens a shell within the - # container. - command: /bin/sh -c "while sleep 1000; do :; done" - kbase-ui-deploy: - image: nginx:1.25.1-alpine - container_name: kbase-ui-deploy - volumes: - - ../build:/usr/share/nginx/html - # - /Users/erikpearson/Work/KBase/2023/CE-255/kbase-ui-plugin-react-profile-view/dist/plugin:/usr/share/nginx/html/plugins/react-profile-view - # - /Users/erikpearson/Work/KBase/2023/UFI-60/kbase-ui-plugin-auth2-client/dist/plugin:/usr/share/nginx/html/plugins/auth2-client - # - /Users/erikpearson/Work/KBase/2023/helpdesk/UFI-48/kbase-ui-plugin-dataview/dist/plugin:/usr/share/nginx/html/plugins/dataview - # - /Users/erikpearson/Work/KBase/2023/helpdesk/UFI-48/kbase-ui-plugin-dataview/dist/plugin:/usr/share/nginx/html/plugins/dataview - # - /Users/erikpearson/Work/KBase/2022/fix-app-icons/kbase-ui-plugin-organizations/react-app:/usr/share/nginx/html/plugins/organizations - # - /Users/erikpearson/Work/KBase/2022/UIP-7/kbase-ui-plugin-auth2-client/dist/plugin:/usr/share/nginx/html/plugins/auth2-client - # - /Users/erikpearson/Work/KBase/2022/UIP-7/kbase-ui-plugin-auth2-client/dist/plugin:/usr/share/nginx/html/plugins/auth2-client - networks: - - kbase-dev - ports: - - "8081:80" - environment: - # um, does nothing? - # for now, set the proxy port to 80 to match the default - # nginx config. - # TODO: use the templating built into the nginx image. - # or switch to a custom image using dockerize. - - NGINX_HOST=kbase-ui-deploy.ci.kbase.us - - NGINX_PORT=5000 - kbase-ui-proxy: - build: - context: ../tools/proxy - # there is only one proxy image, for local development, so just call it :dev - image: kbase/kbase-ui-proxy:dev - depends_on: - - kbase-ui - - kbase-ui-deploy - networks: - - kbase-dev - container_name: kbase-ui-proxy - ports: - - '80:80' - - '443:443' - dns: - # TODO: sort this out! - - 8.8.8.8 - - 9.9.9.9 - - 1.1.1.1 - - 208.67.222.222 - environment: - - BASE_PATH=/ - - - # note that this is really a docker env file and is relative to the docker-compose file - # TODO: I think we may need to use an entrypoint which selects the deploy environment - # config (env) file based on the DEPLOY_ENV. - - env_file: - - ../tools/proxy/conf/ci.env - - custom.env + kbase-ui: + build: + context: . + dockerfile: Dockerfile-devcontainer + image: kbase/kbase-ui:dev + container_name: kbase-ui + dns: 8.8.8.8 + volumes: + # Update this to wherever you want VS Code to mount the folder of your project + - ..:/workspace:cached + networks: + - kbase-dev + env_file: + - runtime.env + # Required for a devcontainer -- keeps the container running. + # Don't worry, our main interaction with the container is through the + # VSC terminal, which for a devcontainer opens a shell within the + # container. + command: /bin/sh -c "while sleep 1000; do :; done" + kbase-ui-deploy: + image: nginx:1.25.4-alpine3.18 + container_name: kbase-ui-deploy + volumes: + - ../build:/usr/share/nginx/html + # Example of volume mounts for local plugins + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-auth2-client/dist/plugin:/usr/share/nginx/html/plugins/auth2-client + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-catalog/dist/plugin:/usr/share/nginx/html/plugins/catalog + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-dataview/dist/plugin:/usr/share/nginx/html/plugins/dataview + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-typeview/dist/plugin:/usr/share/nginx/html/plugins/typeview + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-data-search/dist/plugin:/usr/share/nginx/html/plugins/data-search + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-jgi-search/dist/plugin:/usr/share/nginx/html/plugins/jgi-search + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-organizations/dist/plugin:/usr/share/nginx/html/plugins/organizations + # - /Users/erikpearson/Work/KBase/2023/europa-integration/kbase-ui-plugin-samples/dist/plugin:/usr/share/nginx/html/plugins/samples + networks: + - kbase-dev + ports: + - '8081:80' + kbase-ui-proxy: + build: + context: ../tools/proxy + # there is only one proxy image, for local development, so just call it :dev + image: kbase/kbase-ui-proxy:dev + depends_on: + - kbase-ui + - kbase-ui-deploy + networks: + - kbase-dev + container_name: kbase-ui-proxy + ports: + - '80:80' + - '443:443' + dns: + # TODO: sort this out! + - 8.8.8.8 + - 9.9.9.9 + - 1.1.1.1 + - 208.67.222.222 + env_file: + - proxy.env diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index cba0df147..000000000 --- a/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -/node_modules/ -/build/ -/deployment/ -# **/*.js -# !/src/**/*.js \ No newline at end of file diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 61eb41541..000000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,48 +0,0 @@ -env: - amd: true - browser: true - es6: true - node: true -extends: - - 'eslint:recommended' - - prettier - - preact - - 'plugin:@typescript-eslint/recommended' -parserOptions: - ecmaVersion: 2018 -root: true -rules: - strict: - - error - - function - no-console: - - error - - allow: - - warn - - error - require-await: - - error - no-confusing-arrow: - - error - no-const-assign: - - error - no-duplicate-imports: - - error - no-useless-computed-key: - - error - no-useless-rename: - - error - no-var: - - error - prefer-arrow-callback: - - warn - prefer-const: - - error - prefer-rest-params: - - warn - prefer-spread: - - warn - indent: - - error - - 4 - - SwitchCase: 1 diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 18cbb09ba..20c358c2f 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -1,14 +1,14 @@ --- name: Manual on: - workflow_dispatch: + workflow_dispatch: jobs: - test: - uses: ./.github/workflows/reusable_test-crats.yml - build-push: - needs: test - uses: ./.github/workflows/reusable_build-push.yml - with: - name: '${{ github.event.repository.name }}' - tags: '${{ github.ref_name }}' - secrets: inherit + test: + uses: ./.github/workflows/reusable_test.yml + build-push: + needs: test + uses: ./.github/workflows/reusable_build-push.yml + with: + name: '${{ github.event.repository.name }}' + tags: 'manual-${{ github.ref_name }}' + secrets: inherit diff --git a/.github/workflows/pull-request-to-main-activity.yml b/.github/workflows/pull-request-to-main-activity.yml index aec191e2b..9761ffec9 100644 --- a/.github/workflows/pull-request-to-main-activity.yml +++ b/.github/workflows/pull-request-to-main-activity.yml @@ -1,20 +1,20 @@ --- name: PR to main3 opened on: - pull_request: - branches: - - main3 - types: - - opened - - reopened - - synchronize + pull_request: + branches: + - main3 + types: + - opened + - reopened + - synchronize jobs: - test: - uses: ./.github/workflows/reusable_test.yml - build-push: - needs: test - uses: ./.github/workflows/reusable_build-push.yml - with: - name: '${{ github.event.repository.name }}' - tags: pr${{ github.event.number }} - secrets: inherit + test: + uses: ./.github/workflows/reusable_test.yml + build-push: + needs: test + uses: ./.github/workflows/reusable_build-push.yml + with: + name: '${{ github.event.repository.name }}' + tags: pr-${{ github.event.number }} + secrets: inherit diff --git a/.github/workflows/reusable_build-push.yml b/.github/workflows/reusable_build-push.yml index 40240eca6..381481b38 100644 --- a/.github/workflows/reusable_build-push.yml +++ b/.github/workflows/reusable_build-push.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out GitHub Repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get current date id: date @@ -28,10 +28,10 @@ jobs: run: ./Taskfile build-kbase-ui - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to GHCR - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io # note that the calling workflow must set `secrets: inherit` @@ -40,7 +40,7 @@ jobs: - name: Create github action tags from image tags id: tags - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: result-encoding: string script: | @@ -52,7 +52,7 @@ jobs: }).join(','); - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile diff --git a/.github/workflows/reusable_build.yml b/.github/workflows/reusable_build.yml index 9a349df2c..262931db2 100644 --- a/.github/workflows/reusable_build.yml +++ b/.github/workflows/reusable_build.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out GitHub Repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build the app env: @@ -15,10 +15,10 @@ jobs: run: ./Taskfile build-kbase-ui - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build without push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile diff --git a/.github/workflows/reusable_test.yml b/.github/workflows/reusable_test.yml index 24afa4ce6..3e595a143 100644 --- a/.github/workflows/reusable_test.yml +++ b/.github/workflows/reusable_test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out GitHub Repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run tests - name: Run all tests diff --git a/.github/workflows/reusable_validate-release-tag.yml b/.github/workflows/reusable_validate-release-tag.yml index 559b0a1ab..7e9afd3bc 100644 --- a/.github/workflows/reusable_validate-release-tag.yml +++ b/.github/workflows/reusable_validate-release-tag.yml @@ -1,20 +1,20 @@ --- name: Ensure release tag is semantic version on: - workflow_call: - inputs: - release_tag: - required: true - type: string + workflow_call: + inputs: + release_tag: + required: true + type: string jobs: - ensure-semver: - runs-on: ubuntu-latest - steps: - - name: Validate that release tag as a proper semantic version prefixed with a v - uses: actions/github-script@v6 - with: - script: | - const releaseTag = '${{ inputs.release_tag }}'; - if (!/^v[0-9]+\.[0-9]+\.[0-9]+$/.test(releaseTag)) { - core.setFailed(`Release version must follow semantic version naming prefixed with a "v" (e.g. v1.2.3) but is "${releaseTag}"`) - } + ensure-semver: + runs-on: ubuntu-latest + steps: + - name: Validate that release tag as a proper semantic version prefixed with a v + uses: actions/github-script@v7 + with: + script: | + const releaseTag = '${{ inputs.release_tag }}'; + if (!/^v[0-9]+\.[0-9]+\.[0-9]+$/.test(releaseTag)) { + core.setFailed(`Release version must follow semantic version naming prefixed with a "v" (e.g. v1.2.3) but is "${releaseTag}"`) + } diff --git a/.gitignore b/.gitignore index 20bcc427f..eeba23f9b 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ _attic/ # Build artifacts /build/ !/build/README.md +*.pyc report.*.json @@ -30,6 +31,8 @@ yarn.lock # /react-app/public/data # !/react-app/public/data/README.md _working/ +_todo/ +.devcontainer/*.env # General purpose temp directory /temp/* diff --git a/.markdownlint.json b/.markdownlint.json index 5b84e87d3..f36411fe6 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,6 +1,12 @@ { - "MD007": { - "indent": 4 - }, - "MD013": false -} \ No newline at end of file + "MD007": { + "indent": 4 + }, + "MD013": { + "line_length": 80, + "code_blocks": false + }, + "no-inline-html": { + "allowed_elements": ["a", "div"] + } +} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 2e1fa2d52..000000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -*.md \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..4032f2ef8 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + semi: true, + useTabs: false, + tabWidth: 4, + trailingComma: 'all', +}; diff --git a/.prettierrc.yaml b/.prettierrc.yaml deleted file mode 100644 index 181366eb8..000000000 --- a/.prettierrc.yaml +++ /dev/null @@ -1,5 +0,0 @@ -printWidth: 100 -trailingComma: 'es5' -tabWidth: 4 -# use single quotes instead of double quotes -singleQuote: true diff --git a/.vscode/settings.json b/.vscode/settings.json index e52998381..14293d7a3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { + "window.title": "kbase-ui/${activeRepositoryBranchName}", "editor.detectIndentation": false, "editor.quickSuggestionsDelay": 1000, "eslint.format.enable": true, @@ -29,5 +30,26 @@ "latex", "plaintext", "typescript" - ] + ], + "typescript.tsserver.log": "verbose", + "peacock.remoteColor": "#42b883", + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#65c89b", + "activityBar.background": "#65c89b", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#945bc4", + "activityBarBadge.foreground": "#e7e7e7", + "commandCenter.border": "#15202b99", + "sash.hoverBorder": "#65c89b", + "statusBar.background": "#42b883", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#359268", + "statusBarItem.remoteBackground": "#42b883", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#42b883", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#42b88399", + "titleBar.inactiveForeground": "#15202b99" + } } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3ab6c674d..c5360f7a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.18.4 +FROM alpine:3.19.1 RUN apk upgrade --update-cache --available && \ apk add --update --no-cache bash ca-certificates nginx bash && \ @@ -50,4 +50,4 @@ ENTRYPOINT [ "dockerize" ] CMD [ \ "-template", "/kb/deployment/templates/nginx.conf.tmpl:/etc/nginx/nginx.conf", \ "-template", "/kb/deployment/templates/config.json.tmpl:/kb/deployment/app/deploy/config.json", \ - "bash", "/kb/deployment/scripts/start-server.bash" ] + "bash", "-x", "/kb/deployment/scripts/start-server.bash" ] diff --git a/LICENSE.md b/LICENSE.md index 7c7facc05..24de0d536 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2015-2023 The KBase Project and its Contributors +Copyright (c) 2015-2024 The KBase Project and its Contributors 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: diff --git a/README.md b/README.md index 51141cbf2..534e13d9f 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,19 @@ The KBase User Interface (_kbase-ui_) is a web browser Single Page App (SPA) pro tools for [KBase](http://www.base.us) users. It is one of several user-facing interfaces at KBase. -`kbase-ui` has traditionally served as a container for various "plugins" which provide most of the -functionality of the interface. The current set of plugins may be found in [the plugins -config](conig/plugins.yml). +`kbase-ui` has traditionally served as a container for various "plugins" which +provide most of the functionality of the interface. The current set of plugins +may be found in [the plugins config](conig/plugins.yml). Some examples include: - -- _Data Viewer_, for inspecting any data object a user has access to (aka "landing pages"), +- _Data Viewer_, for inspecting any data object a user has access to (aka + "landing pages"), - _Type Viewer_, for inspecting the attributes of any data type, -- _Authenticator_, for logging into and out of user's KBase Account and granting authorization to the web app, -- _Catalog_, for browsing, searching and (for developers) managing KBase Narrative Apps. +- _Authenticator_, for logging into and out of user's KBase Account and granting + authorization to the web app, +- _Catalog_, for browsing, searching and (for developers) managing KBase + Narrative Apps. More recently functionality has been added directly to the `kbase-ui` codebase, including: diff --git a/Taskfile b/Taskfile index 94e3f31ea..6416d9941 100755 --- a/Taskfile +++ b/Taskfile @@ -9,13 +9,13 @@ # # Runs docker compose with the given docker compose filename suffix with the given command arguments # -function _run-dc { - docker compose -f "etc/docker-compose-${1}.yml" --project-directory "${PWD}" --project-name orcidlink run --rm orcidlink "${@:2}" -} +# function _run-dc { +# docker compose -f "etc/docker-compose-${1}.yml" --project-directory "${PWD}" --project-name orcidlink run --rm orcidlink "${@:2}" +# } -function _dc-up { - docker compose -f "etc/docker-compose-${1}.yml" --project-directory "${PWD}" --project-name orcidlink up -} +# function _dc-up { +# docker compose -f "etc/docker-compose-${1}.yml" --project-directory "${PWD}" --project-name orcidlink up +# } function _noop { echo "Not implemented yet" @@ -30,19 +30,15 @@ function alias-me { } function install-plugins { - bash tools/deno/scripts/install-plugins.sh "${GH_TOKEN:?GH_TOKEN is required}" -} - -function install-plugin { - bash tools/deno/scripts/install-plugin.sh "${1}" + bash scripts/host/install-plugins.sh } function git-info { - bash tools/deno/scripts/git-info.sh + bash scripts/host/git-info.sh } function build-info { - bash tools/deno/scripts/build-info.sh + bash scripts/host/build-info.sh } function prepare-build { @@ -54,7 +50,7 @@ function create-deploy { } function build { - env DIR="${PWD}/vite-app" bash scripts/host/build.sh + env DIR="${PWD}/vite-app" KBASE_UI_BASE_PATH="${KBASE_UI_BASE_PATH}" bash scripts/host/build.sh } function shell { @@ -77,7 +73,6 @@ function setup-for-build-or-dev { git-info build-info install-plugins - render-templates } # @@ -97,6 +92,7 @@ function build-kbase-ui { # function dev-setup { setup-for-build-or-dev + render-templates } # @@ -107,8 +103,73 @@ function format { _noop } -function render-templates { - env DIR="${PWD}" ENV="${ENV:-ci}" DEFAULT_PATH="${DEFAULT_PATH}" bash tools/dockerize/scripts/render-templates.sh + +# Creates environment variables required for the local development proxy. +# See "create-proxy-env-vars.bash", which documents the required and optional input +# environment variables, as well as the generated ones. +# Saves the environment variables into an env file in .devcontainer/proxy-env +function generate-proxy-env { + # ./scripts/host/generate-proxy-env.bash + # DIR="${PWD}" && cd tools/node && docker compose -f run --rm node-tool echo + # "Network Created" + DIR="${PWD}" \ + docker compose \ + -f tools/node/docker-compose.yml \ + -p kbase-dev \ + run \ + -e DIR="${PWD}" \ + -e USE_DEFAULTS \ + -e DEPLOY_ENV \ + -e KBASE_UI_BASE_PATH \ + -e KBASE_UI_HOSTNAME \ + -e SERVICE_PROXIES \ + -e DYNAMIC_SERVICE_PROXIES \ + -e SERVICES_DOMAIN \ + -e KBASE_UI_HOST \ + -e KBASE_UI_PORT \ + -e NARRATIVE_HOST \ + -e NARRATIVE_PORT \ + -e EUROPA_UI_HOST \ + -e EUROPA_UI_PORT \ + --rm \ + node-tool ./scripts/container/generate-proxy-env +} + +function generate-runtime-env { + DIR="${PWD}" \ + docker compose \ + -f tools/node/docker-compose.yml \ + -p kbase-dev \ + run \ + -e USE_DEFAULTS \ + -e DEPLOY_ENV \ + -e KBASE_UI_BASE_PATH \ + -e KBASE_DOMAIN \ + -e KBASE_UI_HOSTNAME \ + -e FEATURE_SWITCHES_ENABLED \ + -e FEATURE_SWITCHES_DISABLED \ + -e DEFAULT_PATH \ + -e DEFAULT_PATH_TYPE \ + --rm \ + node-tool ./scripts/container/generate-runtime-env +} + +function generate-runtime-config { + generate-runtime-env + DIR="${PWD}" tools/dockerize/scripts/render-templates.sh +} + +function remove-proxy-container { + docker rm $(docker ps -a --no-trunc --format="{{.ID}}" --filter name=^/kbase-ui-proxy$) +} + +# Renders the proxy server config file into build/deploy/proxy-nginx.conf +# Depends upon the proxy env variables existing in .devcontainer/proxy.env +# Use ./Taskfile generate-proxy-env. +# This is useful for previwing the development proxy nginx config, especially when +# making changes to it. +function render-proxy-config { + DIR="${PWD}" ENV_FILE="${PWD}/.devcontainer/proxy.env" tools/dockerize/scripts/render-proxy-configs.sh } # Optional dev tooling: @@ -121,8 +182,28 @@ function remove-dev-cert { rm tools/proxy/contents/ssl/* } -function start-local-server { - docker compose up +function run-server { + docker compose up ${IMAGE:+--no-build} + docker compose rm -f +} + +function build-image { + ./scripts/host/build-image.sh +} + +function run-image { + ./scripts/host/run-image.sh +} + +function run-proxy { + ./scripts/host/run-proxy.sh +} + +function create-docker-network { + DIR="${PWD}" && cd tools/node && docker compose -f run --rm node-tool echo "Network Created" + #!/usr/bin/env bash + + # DIR="${PWD}" docker compose -f tools/node/docker-compose.yml run --rm node-tool "$@" } # diff --git a/config/README.md b/config/README.md index 681b17472..0008911e7 100644 --- a/config/README.md +++ b/config/README.md @@ -1,14 +1,3 @@ # Configuration This directory contains files necessary to configure kbase ui builds: - -```services.yml`` is a YAML file containing definitions of all service endpoints which need to be known to the ui. Most service endpoints are defined as template strings in which the base url is placeholder which is populated at runtime by the deployment configuration (more about that later.) - - -```npmInstall.yml``` is a YAML file containing declarative instructions for installing each and every package brought into the project via bower. - - -- ```builds``` - one file per named configuration set. -- ```deploy``` - classic KBase deploy configuration: service urls, target dirs, per KBase deploy environment. -- ```ui``` - ui build configurations -- ```bowerInstall``` - master file for importing bower packages into kbase module space. diff --git a/config/plugins.yml b/config/plugins.yml index 50f650954..22b22aec4 100644 --- a/config/plugins.yml +++ b/config/plugins.yml @@ -1,13 +1,6 @@ ## Plugin Build Configuration --- plugins: - - name: auth2-client - globalName: kbase-ui-plugin-auth2-client - version: 3.2.21 - source: - github: - account: kbase - release: true - name: biochem-search globalName: kbase-ui-plugin-biochem-search version: 2.2.1 @@ -16,10 +9,11 @@ plugins: account: kbase - name: catalog globalName: kbase-ui-plugin-catalog - version: 2.3.4 + version: 3.0.8 source: github: account: kbase + release: true - name: dashboard4 globalName: kbase-ui-plugin-dashboard4 version: 0.4.3 @@ -28,36 +22,32 @@ plugins: account: eapearson - name: data-search globalName: kbase-ui-plugin-data-search - version: 2.5.1 + version: 2.6.3 source: github: account: kbase release: true - name: dataview globalName: kbase-ui-plugin-dataview - version: 4.15.6 + version: 4.16.7 source: github: account: kbase release: true - - name: feeds - globalName: kbase-ui-plugin-feeds - version: 2.1.2 - source: - github: - account: kbase + # in progress - can always revert to this if the new version is problematic + # - name: feeds + # globalName: kbase-ui-plugin-feeds + # version: 2.1.2 + # source: + # github: + # account: kbase - name: jgi-search globalName: kbase-ui-plugin-jgi-search - version: 2.1.5 - source: - github: - account: kbase - - name: job-browser2 - globalName: kbase-ui-plugin-job-browser2 - version: 1.6.3 + version: 2.2.2 source: github: account: kbase + release: true - name: ontology globalName: kbase-ui-plugin-ontology version: 1.0.1 @@ -66,7 +56,7 @@ plugins: account: kbase - name: organizations globalName: kbase-ui-plugin-organizations - version: 2.3.2 + version: 3.0.4 source: github: account: kbase @@ -89,10 +79,3 @@ plugins: source: github: account: kbase - - name: typeview - globalName: kbase-ui-plugin-typeview - version: 4.2.1 - source: - github: - account: kbase - release: true diff --git a/deployment/config/README.md b/deployment/config/README.md deleted file mode 100644 index 94c4678ef..000000000 --- a/deployment/config/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# Docker Run Configuration files - -This directory contains example configuration files for each environment, in docker "env" format. These files are used by the "run-image-dev.sh" script tool to populate the environment with "docker run". - -In KBase deployments, similar files are supplied directly to dockerize via the kbase-specific "-env" option which supports http/https download of the env files. - -These files are only used for local development. They are superseded if the official configs are found in `dev/gitlab-config`. (Which can be installed with `make get-gitlab-config`.) - -> Note: The kbase dockerize extension, at present, uses an INI library to parse the env file content. This has unfortunate side effects, since the INI format and the library specifically have parsing rules beyond those supported by the very simple docker env file format. - -## File format caveats - -The format of the file should follow the docker env file format. This allows the same env file to be used for local development and testing (via docker run, docker compose, etc.), and for deployment (via dockerize -env). - -The reason for this is that the INI parser used by the kbase "-env" dockerize performs transformations beyond what docker env does. - -The general rule is that the file must follow the docker run env_file rules, environment variable naming rules, and template variable naming rules. - -Below are some rules that I've found avoid inconsistencies between the two usages of the env file. - -#### don't put spaces around key value pairs - -The ENV file preserves all characters from the key and value; spaces are preserved. - -So - -``` - key = value -``` - -provides the key ```key``` and the value ```value```. - -The INI parser trims whitespace from the beginning and end of the value, so the above would produce ```key``` and ```value```. - -#### don't use spaces in variable names - -docker run will fail if a variable has one or more spaces before a variable name and the beginning of the line, after the variable name and the ```=``` sign, or within the variable name. - -E.g. using - -``` -key2 =hello -``` - -results in the docker error: - -``` -docker: poorly formatted environment: variable 'key2 ' has white spaces. -``` - -The INI parser accepts spaces in these positions, and will trim whitespae from the beginning and ending of the variable name. - -Always format variables like: - -``` -variable=value -``` - -#### Variable names must be valid environment variables - -docker run will silently ignore ENV file variables which violate naming rules for environment variables; the INI parser will not. - -In addition, at least some of the rules for ENV variable names apply to template variable names. So, for example the variable ```myvar*``` will be rejected by docker run, accepted by dockerize -env (INI parser), and rejected by the dockerize (go) template parser. - -To be safe, use only alphanumeric characters and the underscore - -#### don't use quoted strings (or quotes at all) - -Given that docker ENV files preserve all characters for the key and value, embedded quotes are literally preserved. A quoted string like ```"my string"``` is literally preserved as that text, without removing the quotes. - -The INI parser, hover, does remove the quotes from quoted strings. It does not always unquote strings, but I don't know all the parsing rules; it certainly does unquote quoted strings, though. - -So, it is best to avoid quotes altogether. - -#### don't use ini sections - -The INI format supports the usage of "sections". A section is a line of the format: - -``` -[section] -``` - -where ```section``` is a section name, and variables following it are considered to be in that "section". - -The docker ENV format does not support sections. Docker run will interpret a section provided in an ENV file as a variable name, but will ignore it because it violates the environment variable naming rules. - -So in theory, a section will simply be ignored and may be used. - -However, I'm not confident that the "ignore" behavior of env files is a permanent condition. docker run does error out with spaces in variable names, and I would expect that other unacceptable variable names should behave the same. - -Probably harmless, but best not to tempt fate. - -## Value Format - -A env variable's value includes all text, including spaces, following the ```=``` sign after the variable name, up to the end of the line. - -Since env variable values are literal strings, and must be utilized as values in dockerize templates, there are some simple rules for representing data: - - -### JSON template target - -1. strings: the template will surround the value call with double quotes - the string should contain no quotes -2. numbers: the env value must be in the form of an integer or floating point as recognized by JSON. -3. arrays: arrays of strings or numbers may be represented, but not mixed types; use a space to separate elements. In the template a somewhat tricky expression will split the string and arrange it into a list of either strings or numbers, with commas separating elements and square brackets surrounding it all. -4. map: not supported - - -## Testing - -The env files within the repo should be tested against each environment locally, using ```scripts/run-image-dev.sh```. The ```kbase-web-assets``` repo may be used to test these same files provide by ```dockerize -env```. [to be documented] \ No newline at end of file diff --git a/deployment/config/appdev_config.ini b/deployment/config/appdev_config.ini deleted file mode 100644 index 47b95be70..000000000 --- a/deployment/config/appdev_config.ini +++ /dev/null @@ -1,55 +0,0 @@ -# KBase UI appdev Config - -deploy_environment=appdev -deploy_hostname=appdev.kbase.us -deploy_icon=wrench -deploy_name=App Dev -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=appdev,severity=info -nginx_log_stdout=false -nginx_log_stderr=true - -ui_backupCookie_domain= -ui_backupCookie_enabled=false - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=appdev.kbase.us -ui_services_analytics_google_code=UA-74533556-1 - -allow= - -services_narrative_url=https://appdev.kbase.us -services_auth2_providers=Google,Globus -services_auth2_version_minimum=0.2.0 - -ui_services_menu_hamburger_disabled= -ui_services_menu_sidebar_disabled=feeds,public-search,organizations,feeds - -ui_featureSwitches_enabled= -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled=Feeds,Groups,RelationEngine diff --git a/deployment/config/ci_config.ini b/deployment/config/ci_config.ini deleted file mode 100644 index e5664708e..000000000 --- a/deployment/config/ci_config.ini +++ /dev/null @@ -1,58 +0,0 @@ -# KBase UI CI Config - -deploy_environment=ci -deploy_hostname=ci.kbase.us -deploy_icon=flask -deploy_name=Continuous Integration -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=ci,severity=info -nginx_log_stdout=true -nginx_log_stderr=true - -ui_backupCookie_domain= -ui_backupCookie_enabled=false - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=ci.kbase.us -ui_services_analytics_google_code=UA-74532036-1 - -allow=alpha,beta - -services_narrative_url=https://ci.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.5 - -ui_services_menu_hamburger_disabled= -ui_services_menu_sidebar_disabled= - -ui_featureSwitches_enabled=search_features,system_alert_notification,new_provenance_widget,similar_genomes,re-lineage,object-link-to-term -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled= - -base_path=/kbase-ui \ No newline at end of file diff --git a/deployment/config/dev_config.ini b/deployment/config/dev_config.ini deleted file mode 100644 index ec381c1fa..000000000 --- a/deployment/config/dev_config.ini +++ /dev/null @@ -1,57 +0,0 @@ -# KBase UI Local Dev Config - -deploy_environment=ci -deploy_hostname=ci.kbase.us -deploy_icon=flask -deploy_name=Local Development -deploy_debug=true - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - - -nginx_log_syslog= -nginx_log_stdout=false -nginx_log_stderr=true - -ui_backupCookie_domain= -ui_backupCookie_enabled=false - -# ui_services_analytics_google_apiEndpoint=https://ci.kbase.us/google-analytics-collect -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=ci.kbase.us -ui_services_analytics_google_code=UA-74532036-1 - -allow=alpha,beta - -services_narrative_url=https://ci.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.5 - -ui_services_menu_hamburger_disabled= -ui_services_menu_sidebar_disabled= - -ui_featureSwitches_enabled=search_features,system_alert_notification,new_provenance_widget,similar_genomes,object-link-to-term -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled= diff --git a/deployment/config/narrative2_config.ini b/deployment/config/narrative2_config.ini deleted file mode 100644 index a73617720..000000000 --- a/deployment/config/narrative2_config.ini +++ /dev/null @@ -1,55 +0,0 @@ -# KBase UI production Config - -deploy_environment=narrative2 -deploy_hostname=narrative2.kbase.us -deploy_icon=code -deploy_name=narrative2 -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info -nginx_log_stdout=true -nginx_log_stderr=true - -ui_backupCookie_domain=kbase.us -ui_backupCookie_enabled=true - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=narrative2.kbase.us -ui_services_analytics_google_code=UA-131054609-1 - -allow=alpha,beta - -services_narrative_url=https://narrative2.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.0 - -ui_services_menu_hamburger_disabled=simple-search,reske-admin,staging-browser -ui_services_menu_sidebar_disabled=public-search - -ui_featureSwitches_enabled=search_features,similar_genomes -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled= \ No newline at end of file diff --git a/deployment/config/narrativedev_config.ini b/deployment/config/narrativedev_config.ini deleted file mode 100644 index 75300ccde..000000000 --- a/deployment/config/narrativedev_config.ini +++ /dev/null @@ -1,55 +0,0 @@ -# KBase UI production Config - -deploy_environment=narrative-dev -deploy_hostname=narrative-dev.kbase.us -deploy_icon=code -deploy_name=Narrative Dev -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info -nginx_log_stdout=true -nginx_log_stderr=true - -ui_backupCookie_domain=kbase.us -ui_backupCookie_enabled=true - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=narrative-dev.kbase.us -ui_services_analytics_google_code=UA-131054609-1 - -allow=alpha,beta - -services_narrative_url=https://narrative-dev.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.0 - -ui_services_menu_hamburger_disabled=simple-search,reske-admin,staging-browser -ui_services_menu_sidebar_disabled=public-search - -ui_featureSwitches_enabled=search_features,similar_genomes -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled= diff --git a/deployment/config/next_config.ini b/deployment/config/next_config.ini deleted file mode 100644 index 25b5ec437..000000000 --- a/deployment/config/next_config.ini +++ /dev/null @@ -1,55 +0,0 @@ -# KBase UI next Config - -deploy_environment=next -deploy_hostname=next.kbase.us -deploy_icon=bullseye -deploy_name=Next -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=next,severity=info -nginx_log_stdout=true -nginx_log_stderr=true - -ui_backupCookie_domain= -ui_backupCookie_enabled=false - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=next.kbase.us -ui_services_analytics_google_code=UA-74530365-1 - -allow= - -services_narrative_url=https://next.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.0 - -ui_services_menu_hamburger_disabled=simple-search,reske-admin,staging-browser -ui_services_menu_sidebar_disabled=public-search,organizations,feeds - -ui_featureSwitches_enabled=similar_genomes -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled=Groups,Feeds,RelationEngine diff --git a/deployment/config/prod_config.ini b/deployment/config/prod_config.ini deleted file mode 100644 index e69aa428f..000000000 --- a/deployment/config/prod_config.ini +++ /dev/null @@ -1,55 +0,0 @@ -# KBase UI production Config - -deploy_environment=prod -deploy_hostname=kbase.us -deploy_icon=thumbs-up -deploy_name=Production -deploy_debug=false - -# Core service deployment path overrides -# The format is ui_coreServices_SERVICEMODULE_path -# where SERVICEMODULE is the module name for the service in all lower case. -deploy_services_auth2_path=services/auth -deploy_services_catalog_path=services/catalog -deploy_services_feeds_path=services/feeds -deploy_services_groups_path=services/groups -deploy_services_narrativemethodstore_path=services/narrative_method_store/rpc -deploy_services_shock_path=services/shock-api -deploy_services_userprofile_path=services/user_profile/rpc -deploy_services_userandjobstate_path=services/userandjobstate -deploy_services_narrativejobservice_path=services/njs_wrapper -deploy_services_kbasedataimport_path=services/data_import_export -deploy_services_kbasesearchengine_path=services/searchapi -deploy_services_servicewizard_path=services/service_wizard -deploy_services_relationengine_path=services/relation_engine_api -deploy_services_workspace_path=services/ws -deploy_services_staging_path=services/staging_service -deploy_services_searchapi2_path=services/searchapi2/rpc -deploy_services_searchapi2_legacy_path=services/searchapi2/legacy - -nginx_log_syslog=syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info -nginx_log_stdout=true -nginx_log_stderr=true - -ui_backupCookie_domain=kbase.us -ui_backupCookie_enabled=true - -ui_services_analytics_google_apiEndpoint=https://www.google-analytics.com/collect -ui_services_analytics_google_hostname=kbase.us -ui_services_analytics_google_code=UA-38443357-1 - -allow= - -services_narrative_url=https://narrative.kbase.us -services_auth2_providers=Google,Globus,OrcID -services_auth2_version_minimum=0.2.0 - -ui_services_menu_hamburger_disabled=simple-search,reske-admin,staging-browser -ui_services_menu_sidebar_disabled=public-search - -ui_featureSwitches_enabled=similar_genomes -ui_featureSwitches_disabled= - -dynamic_service_proxies= - -ui_coreServices_disabled= diff --git a/deployment/templates/config.json.tmpl b/deployment/templates/config.json.tmpl index aeeff4e5c..8e6e3d345 100644 --- a/deployment/templates/config.json.tmpl +++ b/deployment/templates/config.json.tmpl @@ -2,17 +2,9 @@ "deploy": { "id": "kbase-ui", "target": "/kb/deployment/app", - "basePath": "{{ default "" .Env.deploy_basepath }}", - "environment": "{{ .Env.deploy_environment }}", - "displayEnvironment": {{ eq .Env.deploy_environment "prod" | ternary true false }}, - "hostname": "{{ .Env.deploy_hostname }}", - "icon": "{{ .Env.deploy_icon }}", - "name": "{{ .Env.deploy_name }}", + "hostname": "{{ .Env.KBASE_DOMAIN }}", "ui": { - "origin": "https://{{ default .Env.deploy_hostname .Env.deploy_ui_hostname }}" - }, - "services": { - "urlBase": "{{ .Env.deploy_hostname }}" + "origin": "https://{{ .Env.KBASE_DOMAIN }}" } }, "ui": { @@ -41,12 +33,7 @@ "name": "Session", "cookie": { "maxAge": 5184000, - "name": "kbase_session", - "backup": { - "name": "kbase_session_backup", - "domain": {{ if .Env.ui_backupCookie_domain }}"{{.Env.ui_backupCookie_domain}}"{{else}}null{{end}}, - "enabled": {{ default "false" .Env.ui_backupCookie_enabled }} - } + "name": "kbase_session" }, "loginWidget": "kb_login_signin", "cookieChangeDetectionInterval": 1000, @@ -62,15 +49,15 @@ }, "urls": { "marketing": { - "url": "www.kbase.us", + "url": "https://www.kbase.us", "title": "Marketing Site" }, "documentation": { - "url": "docs.kbase.us", + "url": "https://docs.kbase.us", "title": "Documentation Site" }, "statusPage": { - "url": "http://kbase.us/internal/status", + "url": "https://kbase.us/internal/status", "title": "KBase Status Page" }, "submitJiraTicket": { @@ -78,7 +65,7 @@ "title": "Submit a Jira Ticket" }, "narrative": { - "url": "https://{{ .Env.deploy_hostname }}.kbase.us/narrative", + "url": "https://{{ .Env.KBASE_DOMAIN }}/narrative", "title": "Narrative User Interface" }, "loginHelp": { @@ -119,48 +106,9 @@ "beta" ], "featureSwitches": { - "enabled": [{{ range $i, $v := splitList "," (default "" .Env.ui_featureSwitches_enabled) }}{{if $v }}{{ if $i }}, {{end}}"{{ $v }}"{{ end }}{{ end }}], - "disabled": [{{ range $i, $v := splitList "," (default "" .Env.ui_featureSwitches_disabled) }}{{if $v }}{{ if $i }}, {{end}}"{{ $v }}"{{ end }}{{ end }}], - "available": [ - { - "id": "orcid_auth_provider", - "title": "ORCiD auth provider", - "description": "The ORCiD auth provider is" - }, - { - "id": "system_alert_notification", - "title": "The New System Alert Notification", - "disabled": true - }, - { - "id": "search_features", - "title": "Search over Genome Features" - }, - { - "id": "similar_genomes", - "title": "Similar Genomes Landing Page Widget" - }, - { - "id": "new_provenance_widget", - "title": "New Provenance Widget" - }, - { - "id": "re-lineage", - "title": "Lineage driven by Relation Engine" - }, - { - "id": "object-link-to-term", - "title": "Data objects linked to ontology terms" - }, - { - "id": "redirect-to-www", - "title": "Redirect to www.kbase.us if not physical path, ui hash path, or token" - }, - { - "id": "sampleset-data-links", - "title": "Enable data links for sample sets" - } - ] + "enabled": [{{ range $i, $v := splitList "," (default "" .Env.FEATURE_SWITCHES_ENABLED) }}{{if $v }}{{ if $i }}, {{end}}"{{ $v }}"{{ end }}{{ end }}], + "disabled": [{{ range $i, $v := splitList "," (default "" .Env.FEATURE_SWITCHES_DISABLED) }}{{if $v }}{{ if $i }}, {{end}}"{{ $v }}"{{ end }}{{ end }}], + "available": [] }, "constants": { "clientTimeout": 900000, @@ -173,15 +121,12 @@ }, "defaults": { "path": { - "type": "path", - "value": "{{ default "/narratives" .Env.DEFAULT_PATH }}" - }, - "hideHeader": {{ default "false" .Env.HIDE_HEADER }}, - "hideNavigation": {{ default "false" .Env.HIDE_NAVIGATION }}, - "integratedHamburgerAndLogo": {{ default "false" - .Env.INTEGRATED_HAMBURGER_AND_LOGO }} + "path": "{{ default "narratives" .Env.DEFAULT_PATH }}", + "type": "{{ default "europaui" .Env.DEFAULT_PATH_TYPE }}" + } } }, + {{ $services_endpoint := (printf "https://%s/services/" .Env.KBASE_DOMAIN) }} "services": { "Auth2": { "module": "Auth2", @@ -190,7 +135,7 @@ "auth", "Auth" ], - "url": "https://{{ .Env.deploy_hostname }}/{{ default "services/auth" .Env.deploy_services_auth2_path }}", + "url": "{{ $services_endpoint }}auth", "cookieName": "kbase_session", "extraCookieNames": [], "name": "Authorization Version 2", @@ -199,18 +144,40 @@ "path": "/", "propertyPath": "version" }, - "providers": [ - "Google", - "Globus", - "OrcID" - ] + "supportedProviders": [ + { + "id": "Google", + "label": "Google", + "logoutUrl": "https://accounts.google.com/Logout", + "priority": 1, + "confirmSignin": false, + "description": "Any Google account may be used to access KBase.\n" + }, + { + "id": "OrcID", + "label": "ORCID", + "logoutUrl": "https://www.orcid.org/signout", + "priority": 1, + "confirmSignin": true, + "description": "Use your ORCiD account to access KBase.\n" + }, + { + "id": "Globus", + "label": "Globus", + "logoutUrl": "https://app.globus.org/logout", + "priority": 2, + "confirmSignin": true, + "description": "Use your Globus ID to access KBase.\n" + } + ], + "providers": [{{ range $i, $v := splitList "," (default "Google,Globus,OrcID" .Env.AUTH2_PROVIDERS) }}{{if $v }}{{ if $i }}, {{end}}"{{ $v }}"{{ end }}{{ end }}] }, "Catalog": { "module": "Catalog", "aliases": [ "catalog" ], - "url": "https://{{ .Env.deploy_hostname }}/services/catalog", + "url": "{{ $services_endpoint }}catalog", "name": "Catalog", "type": "jsonrpc", "version": { @@ -223,7 +190,7 @@ "ee2", "ExecutionEngine2" ], - "url": "https://{{ .Env.deploy_hostname }}/services/ee2", + "url": "{{ $services_endpoint }}ee2", "name": "Execution Engine2", "type": "jsonrpc" }, @@ -232,7 +199,7 @@ "aliases": [ "feeds" ], - "url": "https://{{ .Env.deploy_hostname }}/services/feeds", + "url": "{{ $services_endpoint }}feeds", "name": "Feeds", "type": "rest", "version": { @@ -245,7 +212,7 @@ "aliases": [ "groups" ], - "url": "https://{{ .Env.deploy_hostname }}/services/groups", + "url": "{{ $services_endpoint }}groups", "name": "Groups", "type": "rest", "version": { @@ -259,7 +226,7 @@ "narrative_job_service", "njs" ], - "url": "https://{{ .Env.deploy_hostname }}/services/njs_wrapper", + "url": "{{ $services_endpoint }}njs_wrapper", "name": "Narrative Job Service", "type": "jsonrpc", "version": { @@ -271,8 +238,8 @@ "aliases": [ "narrative_method_store" ], - "url": "https://{{ .Env.deploy_hostname }}/services/narrative_method_store/rpc", - "image_url": "https://{{ .Env.deploy_hostname }}/services/narrative_method_store/", + "url": "{{ $services_endpoint }}narrative_method_store/rpc", + "image_url": "{{ $services_endpoint }}narrative_method_store/", "name": "Narrative Method Store", "type": "jsonrpc", "version": { @@ -284,7 +251,7 @@ "aliases": [ "user_profile" ], - "url": "https://{{ .Env.deploy_hostname }}/services/user_profile/rpc", + "url": "{{ $services_endpoint }}user_profile/rpc", "name": "User Profile", "type": "jsonrpc", "version": { @@ -293,7 +260,7 @@ }, "SampleService": { "module": "SampleService", - "url": "https://{{ .Env.deploy_hostname }}/services/sampleservice", + "url": "{{ $services_endpoint }}sampleservice", "name": "Sample Service", "type": "jsonrpc" }, @@ -302,7 +269,7 @@ "aliases": [ "service_wizard" ], - "url": "https://{{ .Env.deploy_hostname }}/services/service_wizard", + "url": "{{ $services_endpoint }}service_wizard", "name": "Service Wizard", "type": "jsonrpc", "version": { @@ -314,7 +281,7 @@ "aliases": [ "workspace" ], - "url": "https://{{ .Env.deploy_hostname }}/services/ws", + "url": "{{ $services_endpoint }}ws", "name": "Workspace", "type": "jsonrpc", "version": { @@ -324,7 +291,7 @@ "RelationEngine": { "module": "RelationEngine", "aliases": [], - "url": "https://{{ .Env.deploy_hostname }}/services/relation_engine_api", + "url": "{{ $services_endpoint }}relation_engine_api", "name": "Relation Engine", "type": "rest", "version": { @@ -335,22 +302,22 @@ "SearchAPI2": { "module": "SearchAPI2", "aliases": [], - "url": "https://{{ .Env.deploy_hostname }}/services/searchapi2/rpc", - "legacyUrl": "https://{{ .Env.deploy_hostname }}/services/searchapi2/legacy", + "url": "{{ $services_endpoint }}searchapi2/rpc", + "legacyUrl": "{{ $services_endpoint }}searchapi2/legacy", "name": "Search Engine", "type": "jsonrpc2" }, "SearchAPI2Legacy": { "aliases": [], "module": "KBaseSearchEngine", - "url": "https://{{ .Env.deploy_hostname }}/services/searchapi2/legacy", + "url": "{{ $services_endpoint }}searchapi2/legacy", "name": "Search Engine", "type": "jsonrpc" }, "ORCIDLink": { "aliases": [], "module": "ORCIDLink", - "url": "https://{{ .Env.deploy_hostname }}/services/orcidlink", + "url": "{{ $services_endpoint }}orcidlink", "name": "KBase ORCID® Link", "type": "rest", "version": { diff --git a/deployment/templates/nginx.conf.tmpl b/deployment/templates/nginx.conf.tmpl index 285f53d8f..4183e98c4 100644 --- a/deployment/templates/nginx.conf.tmpl +++ b/deployment/templates/nginx.conf.tmpl @@ -4,6 +4,24 @@ worker_processes auto; pid /var/run/nginx.pid; user kbmodule; +# Build Environment Variables: +# KBASE_DOMAIN = {{ or .Env.KBASE_DOMAIN "NO DEFAULT" }} +# KBASE_UI_HOSTNAME = {{ or .Env.KBASE_UI_HOSTNAME "defaulting to 'legacy'" }} +# KBASE_UI_BASE_PATH = {{ or .Env.KBASE_UI_BASE_PATH "defaulting to ''" }} +# NGINX_LOG_SYSLOG = {{ or .Env.NGINX_LOG_SYSLOG "defaulting to ''" }} +# NGINX_LOG_STDOUT = {{ or .Env.NGINX_LOG_STDOUT "defaulting to 'true'" }} +# NGINX_LOG_STDERR = {{ or .Env.NGINX_LOG_STDERR "defaulting to 'true'" }} +# NGINX_LOG_LEVEL = {{ or .Env.NGINX_LOG_LEVEL "defaulting to 'error'" }} +# NGINX_LISTEN = {{ or .Env.NGINX_LISTEN "defaulting to '80'"}} +# NGINX_SERVER_NAME = {{ or .Env.NGINX_SERVER_NAME "defaulting to 'localhost'" }} + +{{ $subhost := false -}} +{{- $kbase_ui_domain := .Env.KBASE_DOMAIN -}} +{{- if .Env.KBASE_UI_HOSTNAME -}} + {{- $kbase_ui_domain = print .Env.KBASE_UI_HOSTNAME "." .Env.KBASE_DOMAIN -}} + {{- $subhost = true -}} +{{- end -}} + events { worker_connections 256; # multi_accept on; @@ -27,19 +45,19 @@ http { # as optional # If the template is passed an nginx syslog path via nginx_log_syslog env var, log to there - {{ if .Env.nginx_log_syslog }} - access_log {{ .Env.nginx_log_syslog }} combined; + {{ if (default "" .Env.NGINX_LOG_SYSLOG) }} + access_log {{ .Env.NGINX_LOG_SYSLOG }} combined; {{ end }} # If nginx_log_stdout env var isn't false or empty, log to stdout - {{ if isTrue (default "true" .Env.nginx_log_stdout) }} + {{ if isTrue (default "true" .Env.NGINX_LOG_STDOUT) }} access_log /dev/stdout; {{ end }} access_log /var/log/nginx/access.log; - {{ if isTrue (default "true" .Env.nginx_log_stderr) }} - error_log /dev/stderr {{ default "error" .Env.nginx_loglevel }}; + {{ if isTrue (default "true" .Env.NGINX_LOG_STDERR) }} + error_log /dev/stderr {{ default "error" .Env.NGINX_LOG_LEVEL }}; {{ end }} - error_log /var/log/nginx/error.log {{ default "error" .Env.nginx_loglevel }}; + error_log /var/log/nginx/error.log {{ default "error" .Env.NGINX_LOG_LEVEL }}; ## # Gzip settings @@ -51,117 +69,73 @@ http { gzip_types text/plain text/css text/xml text/javascript application/json application/x-javascript application/xml; gzip_disable "MSIE [1-6]\."; - upstream docs { - server docs.kbase.us:443; - } - - upstream marketing { - server www.kbase.us:443; - } - server { - listen {{ default "80" .Env.nginx_listen }} default_server; - server_name {{ default "localhost" .Env.nginx_server_name }}; - - location {{ default "" .Env.BASE_PATH }}/ { - # Ensure that index.html is invoked even if a path is - # specified and doesn't exist. - # try_files $uri /$uri /index.html; - ssi_silent_errors off; + listen {{ default "80" .Env.NGINX_LISTEN }} default_server; + server_name {{ default "localhost" .Env.NGINX_SERVER_NAME }}; + + # Matches the root - the index page. + # TODO: this won't work if the base path is empty - fix that. + location = /{{ if .Env.KBASE_UI_BASE_PATH }}{{ .Env.KBASE_UI_BASE_PATH }}/{{ end }} { allow all; # this ensures that a downstream cache service will revalidate. - add_header Cache-Control 'no-cache'; - # add_header Cache-Control 'no-store'; - # expires 0; + add_header Cache-Control 'no-store'; + + {{ if $subhost }} + add_header Content-Security-Policy "frame-ancestors https://{{ .Env.KBASE_DOMAIN }} https://{{ $kbase_ui_domain }} ;" always; + {{ else }} + add_header Content-Security-Policy "frame-ancestors 'self';" always; add_header X-Frame-Options "SAMEORIGIN" always; - add_header Content-Security-Policy "frame-ancestors 'self';" always; + {{ end }} root /kb/deployment/app; + try_files /index.html =404; } - - location {{ default "" .Env.BASE_PATH }}/__ping__ { + + # Catches references to old "modules/plugins" path; used by + # some plugins to fetch resources from within themselves. + # We just map it to the new canonical location for plugins. + location ^~ {{ default "" .Env.KBASE_UI_BASE_PATH }}/modules/plugins/ { + ssi_silent_errors off; + allow all; + add_header Cache-Control 'no-cache'; + alias /kb/deployment/app/plugins/; + } + + # Used as a simple endpoint to determine the health of the connection + # to kbase without touching the filesystem. + location = {{ default "" .Env.KBASE_UI_BASE_PATH }}/__ping__ { default_type text/html; return 204; } - location {{ default "" .Env.BASE_PATH }}/data/__perf__ { + # Used by a performance measuring tool, about/connection + # Inside the __perf__ directory are files of specific sizes + # which can be fetched, and their download time measured as a + # rough estimate of network performance. + location = {{ default "" .Env.KBASE_UI_BASE_PATH }}/data/__perf__ { gzip off; add_header Cache-Control 'no-cache'; root /kb/deployment/app; } - - location {{ default "" .Env.BASE_PATH }}/modules/plugins/ { + + # Matches all other resources + location ~ /{{ default "" .Env.KBASE_UI_BASE_PATH }} { ssi_silent_errors off; allow all; + # this ensures that a downstream cache service will revalidate. add_header Cache-Control 'no-cache'; - alias /kb/deployment/app/plugins/; - } - - # Format is /__poke/https://www.example.com/some/path - location ~* ^{{ default "" .Env.BASE_PATH }}/__poke/docs/(.*)$ { - proxy_hide_header Content-Security-Policy; - proxy_hide_header X-Content-Security-Policy; - proxy_hide_header X-Webkit-Csp; - proxy_pass https://docs/$1; - proxy_http_version 1.1; - proxy_set_header Connection ""; - client_max_body_size 300M; - proxy_buffer_size 128k; - proxy_buffers 4 256k; - proxy_busy_buffers_size 256k; - proxy_set_header Host docs.kbase.us; - proxy_intercept_errors on; - recursive_error_pages on; - error_page 301 302 307 = @handle_redirect_docs; - } - - location @handle_redirect_docs { - set $saved_redirect_location '$upstream_http_location'; - - # These header fields are massive in gitbook. - proxy_hide_header Content-Security-Policy; - proxy_hide_header X-Content-Security-Policy; - proxy_hide_header X-Webkit-Csp; - proxy_http_version 1.1; - proxy_set_header Connection ""; - client_max_body_size 300M; - proxy_buffer_size 128k; - proxy_buffers 4 256k; - proxy_busy_buffers_size 256k; - proxy_set_header Host docs.kbase.us; - proxy_pass $saved_redirect_location; - proxy_intercept_errors on; - recursive_error_pages on; - error_page 301 302 307 = @handle_redirect_docs; - } + # add_header Cache-Control 'no-store'; + # expires 0; - location ~* ^{{ default "" .Env.BASE_PATH }}/__poke/marketing/(.*)$ { - proxy_pass https://marketing/$1; - proxy_http_version 1.1; - proxy_set_header Connection ""; - client_max_body_size 300M; - proxy_set_header Host www.kbase.us; - proxy_intercept_errors on; - recursive_error_pages on; - error_page 301 302 307 = @handle_redirect_marketing; - } + {{ if $subhost }} + add_header Content-Security-Policy "frame-ancestors https://{{ .Env.KBASE_DOMAIN }} https://{{ $kbase_ui_domain }} ;" always; + {{ else }} + add_header Content-Security-Policy "frame-ancestors 'self';" always; + add_header X-Frame-Options "SAMEORIGIN" always; + {{ end }} - location @handle_redirect_marketing { - set $saved_redirect_location '$upstream_http_location'; - set $path $saved_redirect_location; - - if ($saved_redirect_location ~* ^https://www.kbase.us/(.*)$) { - set $path $1; - } - - proxy_http_version 1.1; - proxy_set_header Connection ""; - client_max_body_size 300M; - proxy_set_header Host www.kbase.us; - proxy_pass https://marketing/$path; - proxy_intercept_errors on; - recursive_error_pages on; - error_page 301 302 307 = @handle_redirect_marketing; + root /kb/deployment/app; + rewrite ^/{{ default "" .Env.KBASE_UI_BASE_PATH }}(/.*)$ $1 break; } } } diff --git a/docker-compose.yml b/docker-compose.yml index 45e1728c1..f53b9ec4a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.6' +name: kbase-dev networks: kbase-dev: name: kbase-dev @@ -7,34 +7,9 @@ services: build: context: . dockerfile: Dockerfile - - image: local/kbase-ui:dev - + image: ${IMAGE:-local/kbase-ui:dev} container_name: kbase-ui dns: 8.8.8.8 networks: - kbase-dev - environment: - - DEFAULT_PATH=${DEFAULT_PATH} - command: - - "-template" - - "/kb/deployment/templates/nginx.conf.tmpl:/etc/nginx/nginx.conf" - - "-template" - - "/kb/deployment/templates/config.json.tmpl:/kb/deployment/app/deploy/config.json" - - "bash" - - "/kb/deployment/scripts/start-server.bash" - env_file: dev/gitlab-config/${DEPLOY_ENV:-ci}_config.ini - kbase-ui-proxy: - build: - context: ./tools/proxy - image: local/kbase-ui-proxy:dev - depends_on: - - kbase-ui - networks: - - kbase-dev - container_name: kbase-ui-proxy - ports: - - '80:80' - - '443:443' - dns: 8.8.8.8 - env_file: tools/proxy/conf/${DEPLOY_ENV:-ci}.env + env_file: .devcontainer/runtime.env diff --git a/docs/deployment/configuration.md b/docs/deployment/configuration.md index 382a2cec9..adcea8431 100644 --- a/docs/deployment/configuration.md +++ b/docs/deployment/configuration.md @@ -36,7 +36,7 @@ Here is a laundry list: - constants for various kbase-ui features, such as the polling intervals for feeds, auth cookie changes, auth token validation checks, service call timeout. -- urls to common documentation and other endpoints +- urls to common documentation and other endpoints - feature switches to enable or disable specific features, usually under development but not necessarily @@ -192,7 +192,7 @@ dynamicServices_TaxonomyAPI_version=auto ui_services_menu_hamburger_disabled= ui_services_menu_sidebar_disabled= -ui_featureSwitches_enabled=search_features,system_alert_notification,new_provenance_widget,similar_genomes,re-lineage,linked-samples,sampleset-data-links,object-link-to-term +ui_featureSwitches_enabled=search_features,re-lineage,linked-samples,sampleset-data-links,object-link-to-term ui_featureSwitches_disabled= dynamic_service_proxies= @@ -215,14 +215,11 @@ The environment variables listed below are supported. | Name | Default | Description | |------|---------|-------------| |`DEFAULT_PATH`| `"/narratives"` | A url path or "hash path" to serve as the target internal path if kbase-ui is invoked without a path (root) or the old `#dashboard` path is requested | -| `HIDE_HEADER` | `"false"` | A boolean-like string; setting to `"true"` will cause the page header to be omitted | -| `HIDE_NAVIGATION` | "false"` | A boolean-like string; setting to `"true"` will cause the sidebar navigation to be omitted | -| `INTEGRATED_HAMBURGER_AND_LOGO` | "false"` | A boolean-like string; setting to `"true"` causes the hamburger menu icon to be the KBase logo, and the Kbase logo to be omitted | ### `DEFAULT_PATH` `kbase-ui` traditionally shows the `#dashbaord` by default - that is, if no other path -was provided in the url. This was hard coded. +was provided in the url. This was hard coded. Several years ago the dashboard was replaced by the "Narratives Navigator", or "Navigator". This is an external url, as the Navigator is a standalone web app. This was @@ -235,11 +232,11 @@ change it. But it never changed, so that was fine. However, in the near future kbase-ui will be run inside an iframe of yet another Kbase UI. In this case, the current behavior of redirecting to the Navigator is not desired, as the outer UI will handle that. This environment variable allows us to set that path, -either internal or external. +either internal or external. The internal path is in the form `#path` where the path must be prefixed with the `#` url fragment symbol. Any internal path configured within -the app may be used. +the app may be used. The external path is in the form `/path`, where the path should be prefixed with a `/` forward slash. This will cause kbase-ui to navigate to the given path on the same @@ -248,39 +245,3 @@ forward slash. This will cause kbase-ui to navigate to the given path on the sam be redirected to `httpos://ci.kbase.us/narratives`. The configuration defaults to the current behavior, `/narratives`. - -### `HIDE_HEADER` - -This and the following environment variable have been supported in a different form -previously (TODO: documenet that!), but it was not exposed for configuration. - -The value of `HIDE_HEADER` is a "string boolean". Well, since environment variables are -by definition strings, it must be a string representation of a boolean. Since this is a -TypeScript/Javascript application, the Javascript form for boolean is used. In this -case, the value `"true"` indicates that the configuration should be considered `true`, -and any other value should be considered `false`. - -Setting `HIDE_HEADER` to `"true"` causes the entire header area of the site to not be -rendered. It defaults to `"false"` which resolves to `false`. - -This setting, along with the partner "HIDE_NAVIGATION", can be used to make a -"frameless" version of kbase-ui. - -The motivation for this is the same as for "DEFAULT_PATH" - to allow kbase-ui to run -inside a hosted environment which provides the equivalent services (menus, title, -notification, login indicator with avatar). - -### `HIDE_NAVIGATION` - -The value of `HIDE_NAVIGATION` is a string boolean. Setting it to `"true"`causes the -entire sidebar navigation to not be rendered. It defaults to `"false"` and thus resolves -to `false`. - -### `INTEGRATED_HAMBURGER_AND_LOGO` - -The value of `INTEGRATED_HAMBURGER_AND_LOGO` is a string boolean. A `true` value causes -the KBase logo to be integrated into the hamburger menu, replacing the triple-line -hamburger icon. The impact is that the header area is more compact. However, as there -are two other KBase user interfaces (Narrative and Navigator) which share the same -header design, it is not appropriate to default to this unless they are also similarly -updated. Thus this setting defaults to `false`. diff --git a/docs/deployment/index.md b/docs/deployment/index.md index 618099068..8be1bd5de 100644 --- a/docs/deployment/index.md +++ b/docs/deployment/index.md @@ -1,6 +1,9 @@ # Deployment -kbase-ui is deployed as a Docker container which includes the compiled kbase-ui web app, kbase-ui plugins, and an nginx server to provide the http interface. This can be prepared locally on your host workstation or at GitHub via a GitHub Action workflow. +kbase-ui is deployed as a Docker container which includes the compiled kbase-ui +web app, kbase-ui plugins, and an nginx server to provide the http interface. +This can be prepared locally on your host workstation or at GitHub via a GitHub +Action workflow. For both methods, the ultimate product is a Docker image which contains the above. @@ -17,59 +20,68 @@ For both methods, the ultimate product is a Docker image which contains the abov The quickest way to get a production build of kbase-ui running locally! -- dependences - Make sure you have the following available: +### dependences - Make sure you have the following available - - make - - docker - - mkcert (optional) +- make +- docker +- mkcert (optional) -- map ci.kbase.us to localhost +### map ci.kbase.us to localhost - In order to be able to access kbase-ui naturally, with login and login via KBase, it must be accessed via a browser at `https://ci.kbase.us` (or another environment). +In order to be able to access kbase-ui naturally, with login and login via +KBase, it must be accessed via a browser at `https://ci.kbase.us` (or another +environment). - In order to accomplish this one must first map ci.kbase.us to the local host by editing the "hosts" file. The hosts file is located at: +In order to accomplish this one must first map ci.kbase.us to the local host by +editing the "hosts" file. The hosts file is located at: - - `/etc/hosts` for macOS, Linux, FreeBSD and like systems - - `?/hosts` for Windows +- `/etc/hosts` for macOS, Linux, FreeBSD and like systems +- `?/hosts` for Windows - ```shell - ## - # Host Database - # - # localhost is used to configure the loopback interface - # when the system is booting. Do not change this entry. - ## - 127.0.0.1 localhost - 255.255.255.255 broadcasthost - ::1 localhost +```shell +## +# Host Database +# +# localhost is used to configure the loopback interface +# when the system is booting. Do not change this entry. +## +127.0.0.1 localhost +255.255.255.255 broadcasthost +::1 localhost - # KBase - 127.0.0.1 ci.kbase.us - # End KBase - ``` +# KBase +127.0.0.1 ci.kbase.us +# End KBase +``` - > Tip: I leave this in /etc/hosts and simply comment it out when not using it. +> Tip: I leave this in /etc/hosts and simply comment it out when not using it. -- set up developer cert +### set up developer cert - By default, kbase-ui will use a self-signed certificate. However, using an https site with a self-signed certificate is painful, and adds work which forces the user experience to deviate from that which we provide to users in a real deployment. +By default, kbase-ui will use a self-signed certificate. However, using an https +site with a self-signed certificate is painful, and adds work which forces the +user experience to deviate from that which we provide to users in a real +deployment. - Fortunately there is a handy tool `mkcert` which can be used to create temporary ssl certificates which will make the browser happy. +Fortunately there is a handy tool `mkcert` which can be used to create temporary +ssl certificates which will make the browser happy. - The make task +The make task - ```shell - make dev-cert - ``` +```shell +make dev-cert +``` - will create a temporary certificate for kbase.us and *.kbase.us, install it into the system, install it into Firefox, and copy the certs to the local proxy used in the deploy. +will create a temporary certificate for kbase.us and *.kbase.us, install it into +the system, install it into Firefox, and copy the certs to the local proxy used +in the deploy. -- build and run kbase-ui: - - Compiling kbase-ui, downloading plugins, assembling files, building the image, and running the kbase-ui container and associated proxy is conducted with a single comamnd: - - ```shell - make local-server - ``` +### build and run kbase-ui +Compiling kbase-ui, downloading plugins, assembling files, building the image, +and running the kbase-ui container and associated proxy is conducted with a +single comamnd: +```shell +make local-server +``` diff --git a/docs/design/configuration.md b/docs/design/configuration.md new file mode 100644 index 000000000..cf613dd29 --- /dev/null +++ b/docs/design/configuration.md @@ -0,0 +1,36 @@ +# Configuration + +> Copied from elsewhere, in progress. + +## nginx config + +The `nginx` configuration is used to control nginx logging and caching policy +for the kbase-ui web app and its assets. + +It is generated from `deployment/templates/nginx.conf.tmpl` and results in an +nginx config file being deposited at `/etc/nginx/nginx.conf` in the image. Yes, +it overwrites the main nginx config file, because nginx needs to do nothing else +than support kbase-ui! + +By default kbase-ui is hosted on the root path, which is mapped in the image to +`/kb/deployment/app`. The configuration supports accessing kbase-ui on a path, +but this is not utilized at present. The configuration is a fairly normal one to +support a SPA of this ilk - it resolves to the web app file `index.html` on the +root path, and otherwise attempts to load the requested resource (js, css, +images, html, etc.). + +The configuration is also responsible for ensuring that the kbase-ui web app +main file `index.html` is not cached in browser memory. This ensures that a +browser, upon receiving a url to the root url for kbase ui, e.g. +`https://legacy.ci.kbase.us`, will always fetch the file. Without this, there +are strange scenarios in which a browser will utilize a copy of the kbase-ui web +app runtime, leading to consistency and state issues, especially wrt Europa. + +## kbase-ui config + +The `kbase-ui` configuration is used to supply: + +- the base path, +- hostnames for the top level user interface (Europa, Narrative) and services. +- special auth behavior for prod (backup cookie) +- feature switches diff --git a/docs/design/europa-integration.md b/docs/design/europa-integration.md new file mode 100644 index 000000000..c5bd0a6ab --- /dev/null +++ b/docs/design/europa-integration.md @@ -0,0 +1,237 @@ +# Euoropa Integration of kbase-ui + +In 2024 kbase-ui became a client application of the Europa UI. At the same time, +kbase-ui had undergone a slow transformation from an old-school AMD javascript +to a "modern" React / Typescript web app. + +The initial Europa integration was based on the old kbase-ui codebase. It basically +worked, but was incomplete and carried several important defects. Soon after this +release, the next release was based on the new kbase-ui codebase, and a refactored +integration. + +We'll not discuss the original implementation in detail. + +## Overview + +The integration itself is based almost purely on "window messages" passed back +and forth between Europa and kbase-ui. + +A "window message" is a browser DOM event of type "message" that is only +implemented on windows. A window, in this context, is either the main browser +window or an iframe. In the Europa/kbase-ui integration, Europa is associated +with the main browser window, and, when loaded, kbase-ui is associated with an +iframe window. + +We'll discuss the messaging implementation later, but suffice to say for now +that Europa sends messages to kbase-ui on the iframe window, and kbase-ui sends +messages to Europa on the Europa window. + +### Invoking a kbase-ui endpoint + +The "hash path" form is that used by kbase-ui since it's inception. The +"fragment identifier" component of a url is used by kbase-ui to match a request +path. This fragment identifier may have parameters attached. One example is the +path to a user profile, which looks like `#people/foo` +(`https://ci.kbase.us#people/foo`) to view the profile for user "foo". Another +is a path to the search page with a pre-supplied query: `#data-search$q=coli` +(`https://ci.kbase.us#data-search$q=coli`). + +The "legacy path" is a transformation of the hash path. It is a "normal" URL +path, with a common prefix of `/legacy`. The legacy path form of the examples +above are `/legacy/people/foo` and `/legacy/data-search?q=coli`. + +### kbase-ui startup + +1. kbase-ui is hosted in an iframe within Europa. As such, kbase-ui comes to life +when the iframe is inserted into the DOM with a `src` url pointing to the +kbase-ui deployment location. Eruopa will naturally perform this when it detects +a url destined for kbase-ui, as described above. + + This is **step 1** of the sequence illustrated in [Diagram 1](#diagram01) below. + +2. As Europa creates the iframe, it also creates a "timeout monitor". This is a +separate process which, if it reaches the timeout limit (defaults to 60 +seconds), will remove the iframe and display an error message. + + Don't worry, the timeout monitor is canceled in step 7, after the +communication handshake is complete. + +3. Back to the loading sequence, kbase-ui should have been contacted at the appropriate + URL, e.g. `https://legacy.ci.kbase.us`, after which the web app will start loading, + loading it's configuration, and then ... + +4. After kbase-ui loads and it's app starts up successfully, it sends a + `kbase-ui.connect` message to Europa. This message's payload contains a + unique "connection id". As described in the [window message + implemenatation](#window-messaging-implementation), this unique channel id + ensures that the communication between Europa and kbase-ui is private. + +5. After receiving `kbase-ui.connect`, Europa will set up it's channel with the channel + id, do some housekeeping, and send the message `europa.connect`. + +6. After receive `europa.connect`, kbase-ui will do some housekeeping, prepare itself + for operation, and send the message `kbase-ui.connected`. + +7. This last message indicates that the connection between Europa and kbase-ui + has been established. Europa proceeds to stop the timeout monitor it had + previuosly started. + +8. Finally, Europa sends the message `europa.authnavigate`. This message + contains the KBase Login Token if Europa is authenticated, and the requested + path and params from the original request (URL). + + This special message allows kbase-ui to both set up it's authentication state + and then follow this immediately with a navigation to the requested location. + +
+Diagram 1: Europa/kbase-ui startup sequence +
+ +![startup sequence](../diagrams/out/europa-startup-sequence.png) + +### Login + +### Logout + +### Navigation + +### Authentication Events + +## Technical Topics + +### URL Formats + +There are three URL formats work discussion: kbase-ui "classic" urls, Europa "legacy" +urls, and the kbase-ui "connection" url. + +#### Classic kbase-ui hash paths + +The "classic" kbase-ui url uses no URL paths, but rather the "fragment +identifier", also known as the "hash". kbase-ui documentation often refers to it +as the "hash path". + +For example, a link to a user profile in CI looks like: + +```url +https://ci.kbase.us#people/kbaseuitest +``` + +The reason for this url form is primarily because when kbase-ui was created in 2014, +there was poor support for Javascript to capture the setting of local URL paths. +Honestly, I don't remember how good the support was. Javascript capture of hash change +via the `hashchange` event was available and stable. + +In addition to the hash path, kbase-ui also has supported parameters via the +"query string", also known as "search params". This support has come in various +flavors, all of which are still supported. The search params can be on the url, +like: + +```url +https://ci.kbase.us?q=coli#data-search +``` + +or appended to the hashpath + +```url +https://ci.kbase.us#data-search?q=coli +``` + +or, in the preferred form, appended to the hash-path with the dollar sign `$`. + +```url +https://ci.kbase.us#datasearch$q=coli +``` + +The latter is preferred, as the first method, search params, causes a page +reload when the it changes, and the second form works but is invalid url syntax. + +A note on the philosopy of hash paths. The "fragment identifier" is designed to +be used to navigate within the resource idenfied by the rest of the url. Thus, +it does seem perfectly appropriate to use the hash path to navigate within +kbase-ui, as it is the resource idenfied by the url and is only loaded one time. + +In this context, URL paths almost seem like a misuse, as they do not identify a +resource, but rather a navigation within a resource. Still, what is philosophy +in the fact of practicality? URL paths are very useful for server side +rendering, and are well supported now by the DOM history api. + +#### Europa legacy URL + +When Europa receives a "classic" kbase-ui URL, it simply reforms it as a +"legacy" URL. The transformation is pretty simple. + +- the base url is the origin and any base path; Europa does not have a base path + (it is on the root), although local development uses /dev. +- take the fragment identifier +- extract the appended params, if any +- extract the url params, if any +- create a query string from the combined params +- form a path by concatenating the legacy path prefix `legacy` and the hash path (sans + the initial octothorpe `#`) +- attach the params as standard search params + +For example + +```url +https://ci.kbase.us#people/bart +``` + +becomes + +```url +https://ci.kbase.us/legacy/people/bar +``` + +Or + +```url +https://ci.kbase.us#data-search$q=coli +``` + +becomes + +```url +https://ci.kbase.us/legacy/data-search?q=coli +``` + +#### kbase-ui connection URL + +kbase-ui is attached to Europa through an iframe, whose `scr` attribute is a url +to an instance of kbase-ui. In a deployment, this will be a deployed kbase-ui +instance. + +This url must have two parameters in the query string `sendChannelId` and +`receiveChannelId`. These correspond to the channel ids for the Europa/kbase-ui send +channel and receive channel. The values for these are independent uuids (v4). + +For instance: + +```url +https://legacy.ci.kbase.us?sendChannelId=FOO&receiveChannelId=BAR +``` + +kbase-ui will overwrite this url in order to remove the channel ids + +The url for the iframe never changes after this. All navigation from Europa into +kbase-ui is through the messaging api. All navigation within kbase-ui is via +changes to the fragment identifier (hash) of the window location. Due to the +fact that, as of present, kbase-ui is operating on a subdomain, cross-domain +restrictions kick in and the url changes are not reflected in the iframe src +attribute itself. (In fact, kbase-ui does not have any access to attributes of +the iframe that launched it, which is why we must pass the channel ids in the +url ... in a same-origin implementation we would prefer to use iframe element +attributes.) + +Europa and kbase-ui do provide support for hosting kbase-ui on the primary +domain and with a base path. This configuration provides some benefits: It +allows kbase-ui to operate with same-origin policy, which relaxes security, +simplifies deployments, and unlocks some capabilities (e.g. using dispatchEvent +over postMessage). + +```url +https://ci.kbase.us/legacy +``` + +### Window Messaging Implementation + +Due to the need to run kbase-ui, initially, on a subhost (e.g. legacy.ci.kbase.us), diff --git a/docs/development/development-scenarios.md b/docs/development/development-scenarios.md new file mode 100644 index 000000000..1ea5a0aca --- /dev/null +++ b/docs/development/development-scenarios.md @@ -0,0 +1,3 @@ +# Development Scenarios + +> TODO diff --git a/docs/development/development-setup.md b/docs/development/development-setup.md new file mode 100644 index 000000000..b003ba232 --- /dev/null +++ b/docs/development/development-setup.md @@ -0,0 +1,210 @@ +# `kbase-ui` Development Setup + +`kbase-ui` was designed to run against arbitrary deployment environments, +limited only by available configuration files. Traditionally, `kbase-ui` used +configuration environment files stored in KBase's gitlab. This approach served +well over the years, but suffered a few problems (described elsewhere.) The +current build uses environment variables instead. + +In both cases, kbase-ui configuration is made available to the runtime via a +json config file which is generated from a template, using environment +variables, during service startup. The config file is generated before the +entrypoint is run, with `dockerize`. + +During development, kbase-ui is run inside a devcontainer. Therefore, the +entrypoint configuration process is not run. Instead, before starting the +devcontainer, the developer sets the required environment variables, and builds +the config file with a script (`Taskfile render-templates`). + +So the steps are: + +- Generate env variables: + + - For the proxy: + + ```shell + DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env + ``` + + - For kbase-ui + + The kbase-ui development runtime (run via a _vite_ development server) does + not need any environment variables to control its behavior. Rather, all app + parameterization can be found in `config.json`. This file is normally built + by the container's entrypoint, based on environment variables, but for + development this file must be built first: + + ```shell + DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-config + ``` + +- start the devcontainer + +- launch kbase-ui: + + ```shell + cd vite-app + npm run dev + ``` + +## What Happens + +### Proxy Environment Variables + +The `generate-proxy-env` task creates an "env" file in `.devcontainer/proxy.env`. This +env file is used by the "kbase-ui-proxy" service in the devcontainer's docker-compose +configuration. + +Below is an mexample env file generated from the command using minimal environment +variables. This configuration is suitable for running under Europa, with all services +proxied to the CI environment: + +```shell +DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env +``` + +which produces the following env: + +```shell +# An env file for usage by the proxy service in the devcontainer. +KBASE_UI_HOST="kbase-ui" +EUROPA_UI_HOST="europa-ui" +KBASE_UI_BASE_PATH="" +UI_DOMAIN="ci.kbase.us" +KBASE_UI_HOSTNAME="legacy" +SERVICES_HOSTNAME="ci.kbase.us" +LOCAL_NARRATIVE="" +SERVICE_PROXIES="" +DYNAMIC_SERVICE_PROXIES="" +``` + +To support working with a local instance of the Narrative and a local instance of the +orcidlink service we can use this command line + +```shell +LOCAL_NARRATIVE=t SERVICE_PROXIES=orcidlink DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env +``` + +which produces the following env: + +```shell +# An env file for usage by the proxy service in the devcontainer. +KBASE_UI_HOST="kbase-ui" +EUROPA_UI_HOST="europa-ui" +KBASE_UI_BASE_PATH="" +UI_DOMAIN="ci.kbase.us" +KBASE_UI_HOSTNAME="legacy" +SERVICES_HOSTNAME="ci.kbase.us" +LOCAL_NARRATIVE="t" +SERVICE_PROXIES="orcidlink" +DYNAMIC_SERVICE_PROXIES="" +``` + +### Runtime Config Environment Variables + +`kbase-ui` traditionally relies upon a pair of configuration files, `deploy/config.json` +and `/etc/nginx/nginx.conf`, to determine configurable runtime behavior. In a deployment, +this file is generated by `dockerize` from environment variables supplied by an env file +served out of a private gitlab. + +The new incarnation of kbase-ui still utilizes this basic framework, but relies upon +environment variables set by the deployment platform rather than an env file out of +gitlab. + +The development support tools allow us to generate these environment variables from a +script. The script is essentialy an environment helper, as it contains logic specific to +different development environments. In a deploy environment, these environment variables +must be specified in the deployment tool (e.g. rancher.) + +To generate the runtine configuration environment variables, we just need to specify the +deploy environment tag and specify how it is to be run under Europa with either +`BASE_PATH` or `KBASE_UI_HOSTNAME`: + +```shell +DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-env +``` + +> TODO: update to note that we don't need the pre-built config.json for this + +This generates two files, an env file, and the JSON config file built by dockerize with +this env file. + +The env file is located in `.devcontainer/runtime.env` and looks like this: + +```shell +KBASE_UI_BASE_PATH="" +DEFAULT_PATH="narratives" +DEFAULT_PATH_TYPE="europaui" +UI_DOMAIN="ci.kbase.us" +KBASE_UI_HOSTNAME="legacy" +FEATURE_SWITCHES_ENABLED="search_features,re-lineage,linked-samples,sampleset-data-links,object-link-to-term" +FEATURE_SWITCHES_DISABLED="" +AUTH2_PROVIDERS="Google,Globus,OrcID" +KBASE_ENDPOINT="https://ci.kbase.us/services/" +NGINX_LOG_SYSLOG="" +NGINX_LOG_STDOUT="true" +NGINX_LOG_STDERR="true" +NGINX_LOG_LEVEL="error" +NGINX_LISTEN="80" +NGINX_SERVER_NAME="localhost" +``` + +These are the same environment variables that would be used in a deployment. So, in +fact, the "generate-runtime-config" task can be used to generate environment variables +for a deployment server (e.g. Rancher). + +The runtime config file is placed in `build/deploy/config.json`, and the nginx file in +`build/deploy/nginx.conf`. The nginx file is not used during development, as it is only +used to control the nginx front end to kbase-ui in KBase deployment environments. + +The JSON config file is made available to kbase-ui through the dev server's +proxy and the devcontainer's special "deploy proxy" - a small nginx server whose +job is to proxy assets normally built into the kbase-ui image, or made available +through dockerize-generated files. This includes: + +- `build/build-info.json` +- `build/git-info.json` +- `deploy/config.json` +- `plugins` + +## Running the development server + +To engage in a development session behind the usual kbase-ui development proxies: + +- start the devcontainer: on macOS `Shift`-`Command`-`P`, then search for "Dev + Containers: Reopen in Container", and select it. + +- a terminal should open in the devcontainer. The current directory will be the repo. + +- change into the vite directory `cd vite-app` + +- install npm dependencies `npm ci` + +- run the dev server `npm run dev` + +## environment variables + +Base + +```shell +export NGINX_LOG_STDOUT=true +export NGINX_LOG_STDERR=true +export NGINX_LOG_LEVEL=error +export NGINX_LISTEN=80 +export NGINX_SERVER_NAME=localhost +export DEFAULT_PATH="#about" +export BACKUP_COOKIE_DOMAIN= +export BACKUP_COOKIE_ENABLED=false +export FEATURE_SWITCHES_ENABLED= +export FEATURE_SWITCHES_DISABLED= +export AUTH2_PROVIDERS=Google,Globus,OrcID + +``` + +For CI running locally: + +```shell +export KBASE_ENDPOINT=https://ci.kbase.us/services/ +export UI_HOSTNAME=ci.kbase.us +export FEATURE_SWITCHES_ENABLED=search_features,system_alert_notification,new_provenance_widget,re-lineage,linked-samples,sampleset-data-links,object-link-to-term +``` diff --git a/docs/development/index.md b/docs/development/index.md new file mode 100644 index 000000000..47e3ceae4 --- /dev/null +++ b/docs/development/index.md @@ -0,0 +1,6 @@ +# Development + +## Contents + +- [Setup](./development-setup.md) +- [Local Deployment](./local-deployment.md) diff --git a/docs/development/integration-tests.md b/docs/development/integration-tests.md new file mode 100644 index 000000000..0efe78acf --- /dev/null +++ b/docs/development/integration-tests.md @@ -0,0 +1,3 @@ +# Integration Tests + +> TO BE WRITTEN diff --git a/docs/development/local-deploy-image.md b/docs/development/local-deploy-image.md new file mode 100644 index 000000000..9cae3a73d --- /dev/null +++ b/docs/development/local-deploy-image.md @@ -0,0 +1,45 @@ +# Local Deploy Image + +It can be very useful to use an image built at GitHub in a local workflow. +It helps one have confidence that the build is good. You can use it +with your browser to verify that expected changes are present. You can use it +with local simulated deployment environments with the kbase-ui proxy. You can +use it as the target of integration tests. + +## How To + +### Determine the image name at GitHub + +Visit [the kbase-ui packages at +GitHub](https://github.com/kbase/kbase-ui/pkgs/container/kbase-ui), and note the +image reference. + +The most recent image is listed at the top, and older ones below. + +You'll need to copy the bit that looks like `ghcr.io/kbase/kbase-ui:pr123`. + +### Start up local server with image specified + +```shell +IMAGE=ghcr.io/kbase/kbase-ui:pr123 ./Taskfile run-server +``` + +### Configure the local proxy for the desired environment + +This will generate the local proxy config for the local kbase-ui running with +the ci environment. + +```shell +DEPLOY_ENV=ci KBASE_UI_HOST=kbase-ui KBASE_UI_PORT=80 KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env +``` + +### Start up the local proxy + +```shell +./Taskfile run-proxy +``` + +## See Also + +- GHA support +- [Local development proxy](./local-proxy.md) diff --git a/docs/development/local-deployment.md b/docs/development/local-deployment.md new file mode 100644 index 000000000..040a0ebd6 --- /dev/null +++ b/docs/development/local-deployment.md @@ -0,0 +1,97 @@ +# Deployment Setup + +## Local Deployment Setup + +For local deployment, kbase-ui is operated just as in a real deployment - from a built +app, in a container built from the main Dockerfile, using dockerize to process the +kbase-ui and nginx config files using environment variables. + +### Generate configs + +This is the same procedure as for development, as some of the same files are utilized. + +- For local usage of a kbase-ui deployment, we still need to use the proxy in order to + operate on a deployment domain, and to use local services and Narrative. + + ```shell + SERVICE_PROXIES=orcidlink DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env + ``` + +- For kbase-ui + + For the deployed kbase-ui, we don't need to use the config.json file, as it is built + "on the fly" by the container via the dockerize entrypoint. However, we do utilize + the env file that is generated along with config.json, so we use the subtask + "generate-runtime-env" to create this env file. + + ```shell + DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-env + ``` + +### Build kbase-ui + +The kbase-ui build is automated via a Taskfile task `build-kbase-ui`. This task will +generate build and git info files, download and setup plugins, build the web app, and +assemble all of this into a docker image. + +```shell +KBASE_UI_BASE_PATH="" GH_TOKEN="PAT_HERE" ./Taskfile build-kbase-ui +``` + +The `KBASE_UI_BASE_PATH` is optional. It is only required if there is a base path. It is utilized +in the `vite` build to construct the root `index.html` file. `kbase-ui` itself doesn't +use this value, rather it will use the value provided in the configuration. So, yes, +this must match the configuration. + +The `GH_TOKEN` is used for a local build, because GitHub rate limits unauthenticated +access to github.com. With a GH_TOKEN set to a Personal Access Token (PAT), rate +limiting is much higher (I've never run into rate limiting when using a PAT). + +Not that the GH_TOKEN is not required in a build through Github Actions. + +> Note - it usually worthwhile to perform an `npm run build` while in the devcontainer, +> before attempting a full image build. This helps you catch build issues which are not +> revealed during development. + +### Run kbase-ui + +Once the image is successfully built, starting the local server is as simple as: + +```shell +./Taskfile start-local-server +``` + +Note that this is so simply because an env file is used to supply the runtime +environment variables. This env file is located at `.devcontainer/runtime.env`. + +If you get a message like: + +```shell +Error response from daemon: Conflict. The container name "/kbase-ui" is already in use by container "56b79f26b53079d32e03a45110affe8150a748ac8d63e792274fdf9bdb172fd9". You have to remove (or rename) +that container to be able to reuse that name. +``` + +you may already have a development container for kbase-ui. After exiting a VSC +devcontainer, the containers are not removed. + +### Run Proxy + +The docker-compose configuration will need to be run in order to pull up kbase-ui within +Europa. We assume you already have Europa up and running. + +The proxy is run separately because the process of evaluating a new image is done in two +parts. + +First you'll want to build and run it locally. Then you'll want to push up the changes +to your PR, or whatever, deploy to that environment, and then run the proxy without +specifying a kbase-ui host and port - in which case it will utilize the deployed one. + +This workflow is suitable for ci, ci-europa, narrative-dev -- any self-deployed, testing +and evaluation deployment. + +> We need to write up a short guide to getting all three running, in all scenarios! +> Well, we've done that, but we need to do it for the current methods. + +```shell +./Taskfile run-proxy +``` diff --git a/docs/development/local-proxy.md b/docs/development/local-proxy.md new file mode 100644 index 000000000..ec3b8190a --- /dev/null +++ b/docs/development/local-proxy.md @@ -0,0 +1,130 @@ +# KBase UI Proxy + +kbase-ui ships with an nginx-based proxy server, with support for proxying to +kbase-ui, Europa, Narrative, core services, and dynamic services to local +instances. If you don't specify a local instance to proxy to, the proxy will +contact the deployed instance. + +The proxy is used to set up a local configuration that mimics a deployment. This +is very useful for normal development workflows, multi-project workflows, as +well as to evaluate deployment configurations. + +This is all discussed in [Development Scenarios](./development-scenarios.md). + +For now, we are going to focus on just the proxy itself. + +## Quick Starts + +Here is how to start the proxy to run against CI, proxying to a local instance +of kbase-ui (see below): + +1. __Configure__ it + + ```shell + DEPLOY_ENV=ci KBASE_UI_HOST=kbase-ui KBASE_UI_PORT=80 KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env` + ``` + +2. Map environment __domain__ to it + + Add `127.0.0.1 ci.kbase.us legacy.ci.kbase.us legacy2.ci.kbase.us` to + `/etc/hosts` + +3. Start it + + `./Taskfile run-proxy` + +### Configuration + +The proxy server needs a configuration before it will run at all. A +configuration may be easily built using a task script. + +Here is how to build the proxy configuration for running kbase-ui locally in the +devcontainer in the ci deployment environment. + +```shell +DEPLOY_ENV=ci KBASE_UI_HOST=kbase-ui KBASE_UI_PORT=3000 KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env +``` + +The configuration is written as an "env file" to `.devcontainer/proxy.env`. This +same file will serve both usages of the proxy, as described below. + +### Mapping environment domain + +In order for the proxy to respond to urls of the form +`https://ci.kbase.us#about`, that is using the a KBase deployment environment +domain, you'll need to update your local "hosts" file. + +Edit `/etc/hosts` + +Add the line: + +```text +127.0.0.1 ci.kbase.us legacy.ci.kbase.us +``` + +### Starting + +#### Using the proxy in the devcontainer + +Most of the time, a developer will use the proxy through the VSC devcontainer. +The devcontainer has a docker compose configuration which starts up the +development container, a proxy container, and a deploy asset container. + +To start the devcontainer: + +- Prepare the kbase-ui config: + `DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-config` +- Open the kbase-ui repo in Visual Studio Code +- `[Shift][Command]P` +- search for "open in container" +- select "Dev Containers: Reopen in Container" +- the three container images should be built, if necessary, and launch. +- you'll be dropped into a shell inside the image; if not, open a VSC terminal + and you will be. +- start kbase-ui: + + ```shell + cd vite-app + npm run dev + ``` + +> A handy tip if you are a Docker Desktop user, is to open the Docker Desktop +> Dashboard to check that everything started up correctly. Forgetting to build +> the config, or making a mistake in it, can cause the proxy to fail. + +#### Using the proxy standalone + +When running a kbase-ui server outside of the devcontainer, you'll need to spin +up the standalone proxy service. + +- get kbase-ui going: + - sure, you can use the proxy without kbase-ui, but what is the point? + - Prepare the kbase-ui config: + `DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-config` + - start kbase-ui in [standalone configuration](./local-deployment.md) + `./Taskfile run-server` +- configure the proxy: + `DEPLOY_ENV=ci KBASE_UI_HOST=kbase-ui KBASE_UI_PORT=80 KBASE_UI_HOSTNAME=legacy ./Taskfile generate-proxy-env` + > note that here we use port `80`, since we are using the local deployment +- run the proxy + `./Taskfile run-proxy` + +## About the Proxy + +The proxy is implemented as a lightweight nginx container with a configuration +crafted according to the configuration provided. + +It is implemented in `tools/proxy`. + +## Recipes + +- proxy to local kbase-ui + - development server + - "production" server +- proxy to local Europa + - development server + - "production" server +- proxy to a local Narrative + - just the usual server +- proxy to local core service +- proxy to local dynamic service diff --git a/docs/development/using-deployed-kbase-ui.md b/docs/development/using-deployed-kbase-ui.md new file mode 100644 index 000000000..18a16a194 --- /dev/null +++ b/docs/development/using-deployed-kbase-ui.md @@ -0,0 +1 @@ +# Using a deployed kbase=-ui locally diff --git a/docs/diagrams/europa-startup-sequence.puml b/docs/diagrams/europa-startup-sequence.puml new file mode 100644 index 000000000..bdc4827ac --- /dev/null +++ b/docs/diagrams/europa-startup-sequence.puml @@ -0,0 +1,29 @@ +@startuml europa-kbase-ui-startup + +title Europa/kbase-ui startup sequence + +participant europa as "Europa" +entity timer as "Timeout Monitor" +participant kbaseui as "KBase UI" + +autonumber + +europa -> kbaseui: mount kbase-ui\nhttps://legacy.ENV.kbase.us +||| +europa -> timer: start\ntimes out after 60s +activate timer +||| +kbaseui -> kbaseui: load and start up +||| +europa <-- kbaseui: send __""kbase-ui.connect""__\nwith channel id +||| +europa --> kbaseui: send __""europa.connect""__ +||| +europa <-- kbaseui: send __""kbase-ui.connected""__ +europa -> timer: stop +deactivate timer +||| +europa --> kbaseui: send __""europa.authnavigate""__\nwith token, path, params +||| + +@enduml \ No newline at end of file diff --git a/docs/diagrams/out/europa-startup-sequence.png b/docs/diagrams/out/europa-startup-sequence.png new file mode 100644 index 000000000..929c4db3c Binary files /dev/null and b/docs/diagrams/out/europa-startup-sequence.png differ diff --git a/docs/environment-variables.md b/docs/environment-variables.md new file mode 100644 index 000000000..c018713a9 --- /dev/null +++ b/docs/environment-variables.md @@ -0,0 +1,295 @@ +# Environment Variables and Configuration + +`kbase-ui` relies upon a set of required and optional environment variables. It +depends upon them in a manner quite characteristic of KBase services, that is, +indirectly by using them to create a configuration file as it is started up. + +Upon startup (the Docker command), `kbase-ui` uses `dockerize` to generate two +files: `nginx.conf` for the `nginx` server, and `config.json`, for the +`kbase-ui` web app. The templates for these config files are located in +`deployment/templates`. They are golang templates, which utilize custom +functions provided by +[powerman/dockerize](https://github.com/powerman/dockerize) and +[sprig](http://masterminds.github.io/sprig/). + +## Catalog of Environment Variables + +Environment variables are divided into those supporting the kbase-ui web app, +and those supporting the nginx server. In addition, these are divided into +required environment variables without defaults and those with defaults, which +can be considered optional. + +The fulls set of environment variables, therefore, is the intersection. + +There is only one required environment variables: + +- `KBASE_DOMAIN` + +The remainder of the supported environment variables are optional, with default +values (shown below): + +- `AUTH2_PROVIDERS` +- `KBASE_UI_BASE_PATH` +- `DEFAULT_PATH_TYPE` +- `DEFAULT_PATH` +- `FEATURE_SWITCHES_DISABLED` +- `FEATURE_SWITCHES_ENABLED` +- `NGINX_LISTEN` +- `NGINX_LOG_LEVEL` +- `NGINX_LOG_STDERR` +- `NGINX_LOG_STDOUT` +- `NGINX_LOG_SYSLOG` +- `NGINX_SERVER_NAME` + +### Web App (kbase-ui) + +The environemnt variables in this section are used directly by kbase-ui. + +During container launch, these environment variables are applied to `/kb/deployment/templates/config.json.tmpl`, +which produces `/kb/deployment/app/deploy/config.json`. (See the [the deployment +quickstart](./quick-starts/deployment.md)) + +#### Required (no defaults) + +| Name | Description | +|--------------|-----------------------------------------------------------------------------------------| +| KBASE_DOMAIN | The domain at which Europa, and most KBase user interfaces, operate in this environment | + +#### Optional (with defaults) + +| Name | Default | Description | +|---------------------------|-----------------------|---------------------------------------------------------------------------------------------------| +| KBASE_UI_BASE_PATH | "" | The base, or prefix, path kbase-ui should expect; currently unused (but had been planned) | +| DEFAULT_PATH | "narratives" | When kbase-ui is asked to show the dashboard, go here [1] | +| DEFAULT_PATH_TYPE | "europaui" | The type of path for the above - either "europaui" or "kbaseui" | +| FEATURE_SWITCHES_ENABLED | "" | Used primarily in CI to enable features that are disabled by default (are under development) | +| FEATURE_SWITCHES_DISABLED | "" | Used primarily in non-CI environments to disable features not supported in the deploy environment | +| AUTH2_PROVIDERS | "Google,Globus,OrcID" | Which identity providers the auth service supports in the deploy environment | + +### Nginx Server + +These environment variables are applied to the nginx config template +`/kb/deployment/templates/nginx.conf.tmpl` to produce the nginx config file +`/etc/nginx/nginx.conf`. + +Note that the `nginx` configs and their defaults were established many years ago +by Steve C., and have not been touched since. They should be considered in the +purview of devops. Local development can take care of itself. + +#### Required (no defaults) + +| Name | Description | +|--------------|-----------------------------------------------------------------------------------------| +| KBASE_DOMAIN | The domain at which Europa, and most KBase user interfaces, operate in this environment | + +#### Optional (with defaults) + +| Name | Default | Description | +|-------------------|-------------|-----------------------------------------------------------------------------------------------------------------------------| +| KBASE_UI_HOSTNAME | "legacy" | The hostname component, if any, to be prefixed to KBASE_DOMAIN on which kbase-ui operates in this environment | +| NGINX_LOG_SYSLOG | "" | If provided, sets an `access_log NGINX_LOG_SYSLOG combined;` stanza, where the value is a valid syslog configuration string | +| NGINX_LOG_STDOUT | "true" | if "true", `access_log /dev/stdout;` | +| NGINX_LOG_STDERR | "true" | if "true", `access_log /dev/stderr;` | +| NGINX_LOG_LEVEL | "error" | adds given log level to stderr (if enabled) and `/var/log/nginx/error.log` | +| NGINX_LISTEN | "80" | The port on which to listen for requests | +| NGINX_SERVER_NAME | "localhost" | The host name on which to listen for requests. | + +> Note: Not setting `NGINX_LOG_SYSLOG`has the effect of disabling sylog output. +Therefore, it is required for syslog output, which has always been enabled in kbase-ui +since. + +## Usage in CI + +Here is an example of the current working configuration in the CI Rancher +service `kbase-ui`: + +![CI Rancher Environment Variables](./images/ci-rancher-env-vars.png) + +| Variable | Value | +|---------------------|-----------------------------------------------------------------| +| `KBASE_DOMAIN` | `ci.kbase.us` | +| `KBASE_UI_HOSTNAME` | `legacy2` | +| `NGINX_LOG_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=ci,severity=info` | + +We can see that: + +- The one required environment variable `KBASE_DOMAIN` is provided +- `KBASE_UI_HOSTNAME` is set to "legacy2" for testing; this overrides the + default value of "legacy". +- `NGINX_LOG_SYSLOG` is technically optional, because kbase-ui runs fine without + it, but provided it for a deployment enables nginx syslog logging output. + +## All Environments + +kbase-ui sports a handy tool to generate environment variables per environment. + +```shell +DEPLOY_ENV='ci' KBASE_UI_HOSTNAME='legacy' KBASE_UI_BASE_PATH='' ./Taskfile generate-runtime-env +``` + +or in the container + +```shell +DEPLOY_ENV='ci' KBASE_UI_HOSTNAME='legacy' KBASE_UI_BASE_PATH='' ./scripts/container/generate-runtime-env +``` + +The short form, omitting empty variables, would be + +```shell +DEPLOY_ENV='ci' KBASE_UI_HOSTNAME='legacy' ./Taskfile generate-runtime-env +``` + +where: + +- `DEPLOY_ENV` is one of the KBase deployment environments - ci, ci-europa, + narrative-dev, next, narrative. +- `KBASE_UI_HOSTNAME` is the hostname component of the kbase-ui domain; If + kbase-ui is operating on a subdomain; defaults to empty string which causes + kbase-ui to operate on the primary domain +- `KBASE_UI_BASE_PATH` is the url pathname to reach kbase-ui; defaults to empty string + and thus kbase-ui operates on the root path + +Note that the sister task `generate-runtime-config` will also generate the +kbase-ui and nginx config files, useful for development and debugging the +templates. + +Also note that this script generates environment variables suitable for running +kbase-ui locally and in production, with the caveat that with local usage +`NGINX_LOG_SYSLOG` is not utilized, and is empty in the examples below. + +The syslog settings we have been using from gitlab are: + +- ci: syslog:server=10.58.0.54,facility=local2,tag=ci,severity=info +- next: syslog:server=10.58.0.54,facility=local2,tag=next,severity=info +- appdev: syslog:server=10.58.0.54,facility=local2,tag=appdev,severity=info +- narrative-dev: syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info +- narrative: syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info + +I have no idea, other than CI and narrative-dev, if these are the settings +actually used. They are derived from the develop branch of the old kbase-ui +gitlab ini files; I don't have access to the master branch which has the ini +files used in non-ci deployments. + +### `ci` + +```shell +DEPLOY_ENV='ci' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='ci.kbase.us' +``` + +Note the usage of single quotes - we don't need string interpolation. + +Note also that this is not the full set of environment variables. Any missing +environment variables will have default variables provided by their respective templates. + +```shell +DEPLOY_ENV='ci-europa' ./Taskfile generate-runtime-env +``` + +However, we can also generate the full set of environment variables generated +with default values provided, by using the `USE_DEFAULTS` option: + +```shell +USE_DEFAULTS='t' DEPLOY_ENV='ci-europa' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +AUTH2_PROVIDERS='Google,Globus,OrcID' +KBASE_UI_BASE_PATH='' +KBASE_UI_HOSTNAME='legacy' +DEFAULT_PATH_TYPE='europaui' +DEFAULT_PATH='narratives' +FEATURE_SWITCHES_DISABLED='' +FEATURE_SWITCHES_ENABLED='' +NGINX_LISTEN='80' +NGINX_LOG_LEVEL='error' +NGINX_LOG_STDERR='true' +NGINX_LOG_STDOUT='true' +NGINX_LOG_SYSLOG='' +NGINX_SERVER_NAME='localhost' +KBASE_DOMAIN='ci-europa.kbase.us' +``` + +### `ci-europa` + +```shell +DEPLOY_ENV='ci-europa' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='ci-europa.kbase.us' +``` + +### `next` + +```shell +DEPLOY_ENV='next' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='next.kbase.us' +``` + +### `narrative-dev` + +```shell +DEPLOY_ENV='narrative-dev' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='narrative-dev.kbase.us' +``` + +### `appdev` + +```shell +DEPLOY_ENV='next' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell + +AUTH2_PROVIDERS='Google,Globus' +KBASE_DOMAIN='appdev.kbase.us' +``` + +Note that appdev has a custom setting for `AUTH2_PROVIDERS`, because `ORCID` +sign in is not supported. + +### `narrative2` + +```shell +DEPLOY_ENV='narrative2' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='narrative2.kbase.us' +``` + +### `narrative` (aka "prod" or "production") + +```shell +DEPLOY_ENV='narrative' ./Taskfile generate-runtime-env +``` + +which produces: + +```shell +KBASE_DOMAIN='narrative.kbase.us' +``` diff --git a/docs/images/ci-rancher-env-vars.png b/docs/images/ci-rancher-env-vars.png new file mode 100644 index 000000000..e8bf86c55 Binary files /dev/null and b/docs/images/ci-rancher-env-vars.png differ diff --git a/docs/index.md b/docs/index.md index 4d1bf9774..e55a124a1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,5 +2,13 @@ ## Contents -- Development - - \ No newline at end of file +- Quick Starts + - [Deployment](./quick-starts/deployment.md) + - [Development](./quick-starts/development.md) +- [Development](./development/index.md) + - [Setup](./development/development-setup.md) + - [Local Deployment](./development/local-deployment.md) +- Deployment + > TBD +- Design + - [Europa Integration](./design/europa-integration.md) diff --git a/docs/quick-starts/deployment.md b/docs/quick-starts/deployment.md index cc5f098e2..ad31944ce 100644 --- a/docs/quick-starts/deployment.md +++ b/docs/quick-starts/deployment.md @@ -1,60 +1,142 @@ # `kbase-ui` Deployment Quick Start +## Notable changes of interest for deployment + +`kbase-ui` now runs only in a hosted environment of `Europa`, rather than as a +standalone web app. However, it is still deployed as it has been for years - as +a web app hosted by it's own nginx server. + +We have also migrated from "ini file" environment variables, to direct usage of +environment variables. + ## Image -A production deployment image is tagged with the release semver 2.0 version. E.g. -`ghcr.io/kbase/kbase-ui:v1.2.3`. +Images are created from GHA workflows. + +Images are tagged in various ways. -Evaluation of pull requests in CI or some other environment can be achieved with images -built from pull request activity, which have the form -`ghcr.io/kbase/kbase-service-orcidlink-develop:pr-123`. Such images are often deployed -in CI. +The canonical image for deployment is a release image. A release image is +created from, well, a GitHub Release. a release receives a tag in the form +`v#.#.#` in semver 2.0 format. For example, for release "1.2.3" the image would +be `ghcr.io/kbase/kbase-ui:v1.2.3`. + +Images are also created for pull requests. It is not uncommon to deploy from +pull requests in CI, or perhaps narrative-dev, in order to evaluate upcoming changes. +Images built from pull request activity, have the form +`ghcr.io/kbase/kbase-ui:pr-123`. + +Occasionally an image will be manually built. In such cases it will be tagged +with the branch name, prefixed with "br-". For example, a manual build from +branch "foo" would be named `ghcr.io/kbase/kbase-ui:br-foo`. ## Docker Command -The image entrypoint is `dockerize`, so the image's `command` is overridden to supply command -line arguments to dockerize. +The image entrypoint is `dockerize`, with the command set to the arguments for +dockerize. The arguments are responsible for rendering two templates, the +primary configuration file for kbase-ui, and the nginx server configuration. +Ultimately, the command also starts the nginx server. + +The command built into the image is adequate for any normal deployment, and does +not need to be specified in the deployment service (e.g. Rancher.) -`dockerize` generates configuration files from a gitlab `.ini` file -identified in the `-env` option, using the authorization header identified by the -`-env-header` option, and the `-skip-tls-verify` option as the gitlab (at least at one -time) used a self-signed ssl certificate. The other options are the same as in the -kbase-ui `Dockerfile`. +The `dockerize` template rendering consumes ordinary environment variables supplied by +the deployment service. -This is the command for CI Rancher: +> In the previous deployment practice, the configuration environment variables +> were stored in a "ini" file in our private gitlab. -```shell --env https://gitlab.kbase.us/devops/kbase_ui_config/raw/develop/ci_config.ini -env-header /run/secrets/auth_data -skip-tls-verify -template /kb/deployment/templates/nginx.conf.tmpl:/etc/nginx/nginx.conf -template /kb/deployment/templates/config.json.tmpl:/kb/deployment/app/deploy/config.json bash -x /kb/deployment/scripts/start-server.bash -``` +**Note:** kbase-ui uses +[`powerman/dockerize`](https://github.com/powerman/dockerize), the successor to +the original `jwilder/dockerize`. It previously used a KBase fork of +`jwilder/dockerize`. Some command line options have changed, some templating +commads have a different syntax (notably "default"), and new templating commands +have been added. -> NOTE: kbase-ui uses `powermand/dockerize`, the successor to the original -> `jwilder/dockerize`, and not the (unmaintained) KBase fork of `jwilder/dockerize`. -> Some command line options are a bit different, as well as some of the custom -> templating commands. +## Environment Variables -## Config file data source (ini file) +As mentioned above, runtime parameterization is by means of environment +variables. -Configuration for kbase-ui has traditionally been provided by `.ini` environment files -stored in the KBase private gitlab service. These files are fetched over `https`. +The only required environment variables is: -There are two sources for gitlab `.ini` files - `develop` and `master` branch. The -develop branch is used for CI, and the master branch for next, appdev, and prod. +- KBASE_DOMAIN -Note that these files have not been changed in a long time, and probably never will be -again. KBase now prefers environment variables for service parameterization, and -additional configuration has been made by direct environment variables. At some point in -time, the environment files may be converted to plain environment variables. +Although it is recommended to also set -See [docs/deployment/configuration.md](docs/deployment/configuration.md) for details. +- NGINX_SYSLOG -## Environment Variables +because, although not required for kbase-ui to operate, it has traditionally +been set, and does vary between deployments enough that it cannot have a +default value. + +There are many more environment variables to control kbase-ui, but they have +sensible defaults that normally do not vary between deployments and, some cases, +have remained the same for many years. + +See [docs/environment-variables.md](../environment-variables.md) for a description +of all environment variables. + +See [docs/deployment/configuration.md](../deployment/configuration.md) for +details. + +Here are the variables that should be used per environment at the time of writing: + +### ci -As mentioned above, newer configuration has been moved to environment variables. All -have sensible defaults and can be omitted for normal operation. +| Variable | Value | +|-------------------|-----------------------------------------------------------------| +| `KBASE_DOMAIN` | `ci.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=ci,severity=info` | -See [docs/deployment/configuration.md](docs/deployment/configuration.md) for details. +### ci-europa + +| Variable | Value | +|-------------------|------------------------------------------------------------------------| +| `KBASE_DOMAIN` | `ci-europa.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=ci-europa,severity=info` | + +### next + +| Variable | Value | +|-------------------|-------------------------------------------------------------------| +| `KBASE_DOMAIN` | `next.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=next,severity=info` | + +### narrative-dev + +| Variable | Value | +|-------------------|----------------------------------------------------------------------------| +| `KBASE_DOMAIN` | `narrative-dev.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=narrative-dev,severity=info` | + +### appdev + +| Variable | Value | +|-------------------|---------------------------------------------------------------------| +| `KBASE_DOMAIN` | `appdev.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=appdev,severity=info` | + +### narrative (production) + +| Variable | Value | +|-------------------|-------------------------------------------------------------------| +| `KBASE_DOMAIN` | `narrative.kbase.us` | +| `NGINX_SYSLOG` | `syslog:server=10.58.0.54,facility=local2,tag=prod,severity=info` | ## Verifying deployment -After a deployment, you may visit `https://[env.]kbase.us#about` to confirm that the -expected version has been installed. +After a deployment, you can visit `https://[ENV].kbase.us#about/build` to +confirm that the expected version has been installed. + +Other related strategies are: + +- Run [integration](../development//integration-tests.md) tests against the deployment +- Before the deployment use the image locally to evaluate expected changes +- Run integration tests against a local deployment of the deploy image + +## Related Topics + +- [creating and using a local build](../development//local-deployment.md) +- using a GHCR image locally to verify it +- [environment variables](../environment-variables.md) +- [configuration design](../design//configuration.md) diff --git a/docs/tools/generate-build-env.md b/docs/tools/generate-build-env.md new file mode 100644 index 000000000..8ad744ab8 --- /dev/null +++ b/docs/tools/generate-build-env.md @@ -0,0 +1,3 @@ +# Generate Build Environment File + +> TODO \ No newline at end of file diff --git a/docs/tools/generate-proxy-env.md b/docs/tools/generate-proxy-env.md new file mode 100644 index 000000000..211ec8fd0 --- /dev/null +++ b/docs/tools/generate-proxy-env.md @@ -0,0 +1,9 @@ +# Generate Proxy Environment File + +> TODO + + + +```shell + DEPLOY_ENV=narrative KBASE_UI_HOSTNAME=legacy2 NARRATIVE_HOST=narrative NARRATIVE_PORT=8888 KBASE_UI_HOST=kbase-ui KBASE_UI_PORT="3000" EUROPA_UI_HOST=europa-ui EUROPA_UI_PORT=8080 ./Taskfile generate-proxy-env +``` \ No newline at end of file diff --git a/docs/tools/generate-runtime-config.md b/docs/tools/generate-runtime-config.md new file mode 100644 index 000000000..ecb628441 --- /dev/null +++ b/docs/tools/generate-runtime-config.md @@ -0,0 +1,73 @@ +# Generate Runtime Config + +Generate an env file + +## Assets + +### Tools + +- `Taskfile generate-runtime-env` +- `Taskfile generate-runtime-config` +- `scripts/container/generate-runtime-config` + +### Outputs + +- `.devcontainer/runtime.env` +- `build/deploy/config.json` + +## Using + +### Environment variables + +#### Required + +- `DEPLOY_ENV` + +#### Optional + +- `KBASE_UI_BASE_PATH` +- `KBASE_UI_HOSTNAME` + +#### Output + +Created env vars for config.json.tmpl: + +- `KBASE_UI_BASE_PATH` +- `KBASE_UI_HOSTNAME` +- `DEFAULT_PATH` +- `DEFAULT_PATH_TYPE` +- `KBASE_DOMAIN` +- `FEATURE_SWITCHES_ENABLED` +- `FEATURE_SWITCHES_DISABLED` +- `AUTH2_PROVIDERS` +- `NGINX_LOG_SYSLOG` +- `NGINX_LOG_STDOUT` +- `NGINX_LOG_STDERR` +- `NGINX_LOG_LEVEL` +- `NGINX_LISTEN` +- `NGINX_SERVER_NAME` + +### To Generate a build config file + +```shell +DEPLOY_ENV=ENV ./Taskfile generate-runtime-config +``` + +Where: + +- `ENV` is a deploy environment tag: ci, ci-europa, next, narrative-dev, appdev, narrative + +For example: + +```shell +DEPLOY_ENV=ci KBASE_UI_HOSTNAME=legacy ./Taskfile generate-runtime-config +``` + +Would generate a runtime config file suitable for running against the CI deployment +environment, with kbase-ui hosted on `legacy.ci.kbase.us`. + +### TO Generate a build env file + +```shell +DEPLOY_ENV=ci ./Taskfile generate-runtime-config +``` diff --git a/react-app-todo/Notifications/Notifications.css b/react-app-todo/Notifications/Notifications.css deleted file mode 100644 index a87f994dc..000000000 --- a/react-app-todo/Notifications/Notifications.css +++ /dev/null @@ -1,174 +0,0 @@ -.Notifications { - position: relative; - display: inline-block; - height: 100%; - vertical-align: top; - border: 1px silver solid; - font-size: 90%; - width: 80px -} - -.Notifications .-summary { - cursor: pointer; - font-size: 10px; - padding: 0; - margin: 0; -} - -.Notifications .-summary .-item { - padding: 0; - margin: 0; -} - -.Notifications .-summary .-item>.-count { - display: inline-block; - width: 30%; - text-align: right; - padding-right: 3px; - line-height: 1 -} - -.Notifications .-summary .-item>.-label { - display: inline-block; - width: 60%; -} - -.Notifications .-container { - background-color: white; - position: absolute; - top: 0; - left: 0; -} - -.Notifications .-notification-set { - padding: 3px; - position: relative; - background-color: silver; - - position: absolute; - top: 0px; - right: 20px; - z-index: 100; - width: 200px; - text-align: center -} - -.Notifications .-notification-set .-triangle { - position: absolute; - top: -3px; - left: 196px; - font-size: 25px; - color: silver; -} - -.Notifications .-notification-set .-pointer { - position: absolute; - top: 0px; - left: 200px; - height: 25px; - width: 25px; -} - -.Notifications .-notification-set .-notifications-container { - max-height: 50vh; - overflow-y: auto; - overflow-x: hidden; - text-align: left; -} - -.Notifications .-notification { - padding: 4px; - color: black; - margin: 2px; - position: relative; -} - -.Notifications .-notification .-message { - padding-right: 1em; -} - -.Notifications a.-button { - padding: 0 4px; - background-color: rgba(255, 255, 255, 0.5); - color: black; - user-select: none; -} - -.Notifications .-notification a.-close-button .fa::before { - color: rgb(143, 46, 46); -} - -.Notifications .-notification a.-close-button { - position: absolute; - right: 2px; - top: 2px; -} - -.Notifications a.-button { - text-decoration: none; - color: black; -} - -.Notifications a.-button:hover, -.Notifications a.-button:hover { - color: black; -} - -.Notifications a.-button:hover, -.Notifications a.-button:active { - background-color: rgba(255, 255, 255, 1); - color: black; -} - - -/* new */ - -.Notifications .-notification.-success { - /* bootstrap is dff0d8 */ - background-color: #dff0d8; -} - -.Notifications .-notification.-success:hover { - /* bootstrap is #c1e2b3 */ - background-color: #c1e2b3; -} - -.Notifications .-item.-success.-has-items { - background-color: #c1e2b3; -} - -.Notifications .-notification.-info { - background-color: #d9edf7; -} - -.Notifications .-notification.-info:hover { - background-color: #afd9ee; -} - -.Notifications .-item.-info.-has-items { - background-color: #afd9ee; -} - -.Notifications .-notification.-warning { - background-color: #fcf8e3; -} - -.Notifications .-notification.-warning:hover { - background-color: #f7ecb5; -} - -.Notifications .-item.-warning.-has-items { - background-color: #f7ecb5; -} - -.Notifications .-notification.-error { - background-color: #f2dede; -} - -.Notifications .-notification.-error:hover { - background-color: #e4b9b9; -} - -.Notifications .-item.-error.-has-items { - background-color: #e4b9b9; -} \ No newline at end of file diff --git a/react-app-todo/Notifications/Notifications.tsx b/react-app-todo/Notifications/Notifications.tsx deleted file mode 100644 index 373539cef..000000000 --- a/react-app-todo/Notifications/Notifications.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { Component } from 'react'; -import './Notifications.css'; -// define([ -// 'preact', -// 'htm', - -// 'css!./Notifications.css' -// ], ( -// preact, -// htm -// ) => { - -export interface NotificationsProps { - closeNotifications: () => void; -} - -interface NotificationsState { - -} - - -export default class Notifications extends Component { - renderSummaryItem(name: string) { - const summary = this.props.summary[name]; - const activeClass = summary ? ' -has-items' : ''; - return
-
- ${summary} -
-
- ${name} -
-
- } - - renderSummary() { - return
- {this.renderSummaryItem('success')} - {this.renderSummaryItem('info')} - {this.renderSummaryItem('warning')} - {this.renderSummaryItem('error')} -
- } - - doCloseNotifications() { - this.props.closeNotifications(); - } - - doClearNotification(notification) { - this.props.clearNotification(notification); - } - - doToggleNotifications() { - this.props.toggleNotifications(); - } - - renderNotifications() { - return this.props.notifications.map((notification) => { - const typeClass = (() => { - switch (notification.type) { - case 'success': return '-success'; - case 'info': return '-info'; - case 'warning': return '-warning'; - case 'error': return '-error'; - } - })(); - return
- -
- ${notification.message} -
-
- }); - } - - renderNotificationDisplay() { - const activeStyle = (this.props.show ? ' -active' : ''); - return
-
-
- - - - -
- -
- ${this.renderNotifications()} -
-
-
- `; - } - - render() { - if (!this.props.notifications || this.props.notifications.length === 0) { - return; - } - return html` -
- ${this.renderSummary()} - ${this.renderNotificationDisplay()} -
- `; - } -} \ No newline at end of file diff --git a/react-app-todo/Notifications/NotificationsMain.tsx b/react-app-todo/Notifications/NotificationsMain.tsx deleted file mode 100644 index cf9851cdd..000000000 --- a/react-app-todo/Notifications/NotificationsMain.tsx +++ /dev/null @@ -1,270 +0,0 @@ -import { Component } from 'react'; -import uuid from 'uuid'; - -// define([ -// 'preact', -// 'htm', -// 'uuid', -// './Notifications' -// ], ( -// preact, -// htm, -// {v4: uuidv4}, -// Notifications -// ) => { - -// const {h, Component} = preact; -// const html = htm.bind(h); - -const AUTODISMISSER_INTERVAL = 1000; - -export class Notification { - id: String; - constructor({ notification, parent }) { - const newNotification = notification; - this.id = newNotification.id || uuid.v4(); - this.message = newNotification.message; - this.description = newNotification.description; - this.autodismiss = newNotification.autodismiss; - this.icon = newNotification.icon; - this.autodismissStartedAt = newNotification.autodismiss - ? new Date().getTime() - : null; - this.type = newNotification.type; - this.parent = parent; - - // this.type.subscribeChanged((newVal, oldVal) => { - // this.parent.summary[oldVal].count(this.parent.summary[oldVal].count() - 1); - // this.parent.summary[newVal].count(this.parent.summary[newVal].count() + 1); - // }); - - // this.autodismiss.subscribe((newVal) => { - // if (newVal) { - // // TODO: this - // this.autodismissStartedAt = new Date().getTime(); - // this.parent.startAutoDismisser(); - // } - // }); - } -} - -class AutoDismisser { - constructor({ runner }) { - this.runner = runner; - } - - run() { - if (this.runner()) { - this.loop(); - } - } - - loop() { - this.autoDismisser = window.setTimeout(() => { - this.run(); - }, AUTODISMISSER_INTERVAL); - } - - startLoop(force) { - if (this.autoDismisser && !force) { - return; - } - this.run(); - } -} - -export default class NotificationsMain extends Component { - constructor(props) { - super(props); - - this.runtime = this.props.runtime; - this.sendingChannel = uuidv4(); - this.autoDismisser = new AutoDismisser({ - runner: this.autodismissRunner.bind(this), - }); - - this.state = { - notifications: [], - summary: { - info: 0, - success: 0, - warning: 0, - error: 0, - }, - show: false, - }; - } - - closeNotifications() { - this.setState({ - show: false, - }); - } - - showNotifications() { - this.setState({ - show: true, - }); - } - - toggleNotifications() { - this.setState({ - show: !this.state.show, - }); - } - - autodismissRunner() { - const toRemove = []; - const now = new Date().getTime(); - let autodismissLeft = 0; - this.state.notifications.forEach((item) => { - if (item.autodismiss) { - const elapsed = now - item.autodismissStartedAt; - if (item.autodismiss < elapsed) { - toRemove.push(item); - } else { - autodismissLeft += 1; - } - } - }); - - toRemove.forEach((item) => { - this.removeNotification(item); - }); - - // Return true to keep on truckin' - return autodismissLeft > 0; - } - - componentDidMount() { - this.runtime.send('notification', 'ready', { - channel: this.sendingChannel, - }); - - this.runtime.receive(this.sendingChannel, 'new', (message) => { - this.processMessage(message); - }); - } - - // TODO: without observables, we need to force the - // component to update when the notification is modified. - updateNotification(newMessage) { - const { summary, notifications } = this.state; - - const notification = notifications.filter((notification) => { - return notification.id === newMessage.id; - })[0]; - - if (!notification) { - // console.error('Cannot update message, not found: ' + newMessage.id, newMessage); - // return; - return false; - } - - if (notification.type !== newMessage.type) { - summary[notification.type] -= 1; - summary[newMessage.type] += 1; - } - - notification.type = newMessage.type; - notification.message = newMessage.message; - notification.autodismiss = newMessage.autodismiss; - if (newMessage.autodismiss) { - notification.autodismissStartedAt = new Date().getTime(); - } - - this.setState( - { - notifications, - summary, - }, - () => { - this.autoDismisser.run(); - } - ); - - return true; - } - - addNotification(newMessage) { - const notification = new Notification({ - notification: newMessage, - parent: this, - }); - const { summary, notifications } = this.state; - // const summaryItem = summary[notification.type]; - // if (summaryItem) { - // summaryItem.count += 1; - // } - - summary[notification.type] += 1; - - notifications.unshift(notification); - // this.notificationMap[notification.id] = notification; - this.setState({ - notifications, - summary, - }); - } - - removeNotification(notificationToRemove) { - const { summary, notifications: currentNotifications } = this.state; - const notifications = currentNotifications.filter((notification) => { - return notification.id !== notificationToRemove.id; - }); - // const summaryItem = summary[notificationToRemove.type]; - // if (summaryItem) { - // summaryItem.count -= 1; - // } - - summary[notificationToRemove.type] -= 1; - - this.setState({ - notifications, - summary, - }); - } - - clearNotification(notification) { - this.removeNotification(notification); - } - - processMessage(message) { - if (!message.type) { - console.error('Message not processed - no type', message); - return; - } - if ( - ['success', 'info', 'warning', 'error'].indexOf(message.type) === -1 - ) { - console.error('Message not processed - invalid type', message); - return; - } - - if (!this.updateNotification(message)) { - this.addNotification(message); - } - this.setState({ - show: true, - }); - } - - render() { - const props = { - notifications: this.state.notifications, - summary: this.state.summary, - show: this.state.show, - closeNotifications: this.closeNotifications.bind(this), - toggleNotifications: this.toggleNotifications.bind(this), - clearNotification: this.clearNotification.bind(this), - }; - return html` -
- <${Notifications} ...${props} /> -
- `; - } -} diff --git a/react-app-todo/Notifications/readme.md b/react-app-todo/Notifications/readme.md deleted file mode 100644 index 9e72ccc24..000000000 --- a/react-app-todo/Notifications/readme.md +++ /dev/null @@ -1,32 +0,0 @@ -Allows ui components to provide a notification to the user. - -Notifications are classified as info, warn, and error. - -Notifications are displayed as soon as the are received, and may be removed, or the container closed. - -Notification counts are displayed in the title bar until the notification is dismissed. - -Notifications are displayed in a container per type, closing the container does not remove the notification. - -Some notifications will auto-remove themselves after a period of time, because it is annoying to have to dismiss informational alerts. - -Notifications do though have a history which will reveal recently dismissed notifiations. - -Receives notification messages at ('notification', 'add', ) - -Notifications have ids. A notification received with the same id will update the notification and force it to be displayed. - -A notification looks like this: - -id: string -type: string (info, warn, error) -icon: string (a font awesome icon name -- the part of the class name following the "fa-") -title: string -description: string -dismissable: boolean -autodismiss: integer (time until auto dismiss) - -Implementation - -Notifications are implemented via a knockout viewmodel. -Subscriptions are via our mini-pub-sub system since it is included in the runtime available to all widgets via the runtime parameter (or in the global env sometimes) diff --git a/react-app-todo/SystemAlertBanner/data.tsx b/react-app-todo/SystemAlertBanner/data.tsx deleted file mode 100644 index be0710912..000000000 --- a/react-app-todo/SystemAlertBanner/data.tsx +++ /dev/null @@ -1,160 +0,0 @@ -// define([ -// 'preact', -// 'htm', -// 'kb_lib/poller', -// './view', -// 'css!./style.css' -// ], ( -// preact, -// htm, -// poller, -// SystemAlertBanner -// ) => { -import { Component } from 'react'; -import Poller, { Job, Task } from '../../lib/poller'; -import SystemAlertBanner from './view'; - -// const {h, Component } = preact; -// const html = htm.bind(h); - -const POLL_INTERVAL = 10000; - -export default class LoadNotificationsJob extends Job { - callback: () => void; - constructor({ callback }: { callback: () => void }) { - super({ - description: 'Load notifications', - }); - this.callback = callback; - // this.state = { - // alerts: null, - // showAlertBanner: false, - // error: null - // }; - } - run() { - return this.callback(); - } -} - -export interface Alert {} - -export interface SystemAlertsDataProps {} - -interface SystemAlertsDataState { - showAlertBanner: boolean; - alerts: Array; - error: string | null; - hideAlerts: boolean; -} - -export class SystemAlertData extends Component< - SystemAlertsDataProps, - SystemAlertsDataState -> { - newAlertsPoller: Poller; - constructor(props: SystemAlertsDataProps) { - super(props); - this.newAlertsPoller = this.setupPolling(); - this.state = { - showAlertBanner: false, - hideAlerts: true, - alerts: [], - error: null, - }; - } - - setupPolling() { - const job = new LoadNotificationsJob({ - callback: () => { - this.loadNotifications(); - }, - }); - - const task = new Task({ - interval: POLL_INTERVAL, - runInitially: true, - }); - task.addJob(job); - - return new Poller({ task }); - } - - componentDidMount() { - this.newAlertsPoller.start(); - - // TODO: the system alert should be a ui service, probably is, - // hook it up here... - - // this.props.runtime.receive('system-alert', 'toggle-banner', () => { - // this.setState({ - // showAlertBanner: !this.state.showAlertBanner, - // }); - // }); - // this.props.runtime.receive('system-alert', 'close-banner', () => { - // this.setState({ - // showAlertBanner: true, - // }); - // }); - // this.props.runtime.receive('system-alert', 'open-banner', () => { - // this.setState({ - // showAlertBanner: false, - // }); - // }); - } - - getActiveAlerts() { - return Promise.resolve([ - { - type: 'maintenance', - title: 'Maintenance sample 1', - startAt: new Date(), - endAt: new Date(Date.now() + 1000 * 60 * 60), - read: false, - }, - { - type: 'maintenance', - title: 'Maintenance sample 2', - startAt: new Date(Date.now() + 1000 * 60 * 60), - endAt: new Date(Date.now() + 1000 * 60 * 60 * 2), - read: false, - }, - ]); - // const client = this.props.runtime.service('rpc').newClient({ - // module: 'UIService' - // }); - - // return client.callFunc('get_active_alerts', []) - // .then(([result]) => { - // return result; - // }); - } - - loadNotifications() { - return this.getActiveAlerts() - .then((data) => { - this.setState({ - alerts: data, - error: null, - }); - }) - .catch((err) => { - console.error('ERROR', err); - this.setState({ - alerts: [], - error: err.message, - }); - }); - } - - render() { - if (this.state.showAlertBanner) { - const props = { - // runtime: this.props.runtime, - alerts: this.state.alerts, - hideAlerts: this.state.hideAlerts, - }; - return ; - } - } -} diff --git a/react-app-todo/SystemAlertBanner/style.css b/react-app-todo/SystemAlertBanner/style.css deleted file mode 100644 index 281710b62..000000000 --- a/react-app-todo/SystemAlertBanner/style.css +++ /dev/null @@ -1,60 +0,0 @@ -.SystemAlert {} - -.SystemAlert .wrapper { - margin: 4px 10px 10px 10px; - box-shadow: 4px 4px 4px silver; -} - -.SystemAlert .itemsWrapper { - border: 2px #f2dede solid; -} - -.SystemAlert .title1 { - background-color: rgba(169, 68, 68, 1); - color: white; -} - -.SystemAlert .title2 { - background-color: white; - color: rgba(169, 68, 68, 1); -} - -.SystemAlert .-header { - padding: 10px 15px; - position: relative; - display: flex; - flex-direction: row -} - -.SystemAlert .-alert { - border-radius: 0; - margin-bottom: 0; - border-top: 2px solid #f2dede; -} - -.SystemAlert .-alert>.-row { - display: flex; - flex-direction: row; -} - -.SystemAlert .-alert>.-row>.-col1 { - flex: 1 1 0px; - padding: 4px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.SystemAlert .-alert>.-row>.-col2 { - flex: 1 1 0px; - padding: 4px; - display: flex; - flex-direction: row; - align-items: center; -} - -.SystemAlert .-alert .-icon { - width: 1.5em; - font-size: 120%; - text-align: center; -} \ No newline at end of file diff --git a/react-app-todo/SystemAlertBanner/view.tsx b/react-app-todo/SystemAlertBanner/view.tsx deleted file mode 100644 index 218043653..000000000 --- a/react-app-todo/SystemAlertBanner/view.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import UserProfileClient from '@kbase/ui-lib/lib/comm/coreServices/UserProfile'; -import { Component } from 'react'; - -import CountdownClock from '../CountdownClock'; - -// define([ -// 'preact', -// 'htm', -// '../CountdownClock', -// 'css!./style.css' -// ], ( -// preact, -// htm, -// CountdownClock -// ) => { - -// const {h, Component } = preact; -// const html = htm.bind(h); - -function plural(amount: number, singular: string, plural: string) { - if (amount === 1) { - return singular; - } - return plural; -} - -export interface AlertInfo { - startAt: number; - endAt: number; - title: string; - message: string; - hash: string; - now: number; -} - -export class Alert { - startAt: Date; - endAt: Date | null; - title: string; - message: string; - hash: string; - now: number; - read: boolean; - showMessage: boolean; - constructor({ startAt, endAt, title, message, hash, now }: AlertInfo) { - this.startAt = new Date(startAt); - if (endAt === null || endAt === undefined) { - this.endAt = null; - } else { - this.endAt = new Date(endAt); - } - this.title = title; - this.message = message; - this.hash = hash; - this.now = now; - - this.read = false; - this.showMessage = false; - - this.countdownToStart = (() => { - if (!this.now()) { - return null; - } - return this.startAt - this.now(); - })(); - - this.countdownToEnd = (() => { - if (!this.now()) { - return null; - } - if (this.endAt === null) { - return Infinity; - } - return this.endAt - this.now(); - })(); - } - - toggleMessage() { - this.showMessage(!this.showMessage()); - } -} - -export default class SystemAlertBanner extends Component { - constructor(props) { - super(props); - this.state = {}; - } - - componentDidMount() {} - - doShowHidden() { - // this.props.alerts.forEach((alert) => { - // alert.read(false); - // }); - } - - doHide() {} - - renderHiddenCount() { - if (!this.props.hiddenAlertCount) { - return; - } - return ( - - ${this.props.hiddenAlertCount})$ hidden - - - ); - } - - renderHeader() { - return ( -
-
- - System${' '} - {plural(this.props.alerts.length, 'Alert', 'Alerts')} - -
-
- {this.props.alerts.length}{' '} - {plural(this.props.alerts.length, 'alert', 'alerts')}{' '} - {this.renderHiddenCount()} - -
-
- ); - } - - renderAlertIcon(alert) { - const now = Date.now(); - const startsIn = alert.startAt - now; - const endsIn = alert.endsAt === null ? Infinity : alert.endsAt - now; - const iconClass = (() => { - if (startsIn > 0) { - return 'fa-clock-o'; - } else if (startsIn <= 0 && endsIn > 0) { - return 'fa-exclamation-triangle'; - } - })(); - const iconColor = (() => { - if (startsIn > 0) { - return 'fa-color-warning'; - } else if (startsIn <= 0 && endsIn > 0) { - return 'fa-color-danger'; - } - })(); - return ( - - - - ); - } - - renderAlert(alert) { - return ( -
-
-
-
- {alert.title || '** untitled **'} -
-
-
- {this.renderAlertIcon(alert)} -
- -
-
-
-
- ); - } - - renderAlerts() { - if ( - !this.props.alerts.some((alert) => { - return !alert.read; - }) - ) { - return; - } - const alerts = this.props.alerts.map((alert) => { - return this.renderAlert(alert); - }); - return
{alerts}
; - } - - renderAlertsPanel() { - if (this.props.alerts && this.props.alerts.length > 0) { - return ( -
- {this.renderHeader()} - {this.renderAlerts()} -
- ); - } - } - - render() { - return ( -
- {this.renderAlertsPanel()} -
- ); - } -} diff --git a/react-app-todo/SystemAlertToggle/data.js b/react-app-todo/SystemAlertToggle/data.js deleted file mode 100644 index ac3c8b6bd..000000000 --- a/react-app-todo/SystemAlertToggle/data.js +++ /dev/null @@ -1,201 +0,0 @@ -define([ - 'bluebird', - 'knockout', - 'uuid', - '../../lib/searchApi', - 'yaml!../../data/stopWords.yml' -], function ( - Promise, - ko, - Uuid, - SearchAPI, - stopWordsDb -) { - 'use strict'; - - function isStopWord(word) { - if (stopWordsDb.warn.indexOf(word) >= 0) { - return true; - } - if (stopWordsDb.ignore.indexOf(word) >= 0) { - return true; - } - return false; - } - - // TODO: configure this somewhere - function isBlacklistedHighlightField(fieldName) { - return ['tags'].includes(fieldName); - } - - function encodeHTML(possibleHTML) { - const node = document.createElement('div'); - node.innerHTML = possibleHTML; - return node.innerText; - } - - - // For now, this fakes the search... - function factory(params) { - const maxSearchResults = params.maxSearchItems; - - const types = params.types; - - const searchConfig = { - // max number of search result items to hold in the buffer - // before we start removing those out of view - maxBufferSize: params.maxBufferSize || 100, - // number of search items to fetch at one time. - fetchSize: params.pageSize || 20 - }; - - function objectToViewModel(obj) { - const type = types.getTypeForObject(obj); - if (!type) { - console.error('ERROR cannot type object', obj); - throw new Error('Cannot type this object'); - } - - const icon = type.getIcon(type); - - const ref = type.getRef(); - const detail = type.detail(); - const detailMap = detail.reduce(function (m, field) { - m[field.id] = field; - return m; - }, {}); - - const matches = Object.keys(obj.highlight).reduce((matches, field) => { - if (isBlacklistedHighlightField(field)) { - console.warn('highlight field ' + field + ' ignored'); - return matches; - } - - let label = type.getSearchFieldLabel(field); - if (!label) { - label = field; - console.warn('highlight field ' + field + ' not found in type spec', obj); - } - - const emStart = new Uuid(4).format(); - const emFinish = new Uuid(4).format(); - - matches - .push({ - id: field, - label: label, - highlights: obj.highlight[field] - .map((highlight) => { - const safe1 = highlight.replace('', emStart).replace('', emFinish); - const safe2 = encodeHTML(safe1); - const safe3 = safe2.replace(emStart, '').replace(emFinish, ''); - return { - highlight: safe3 - }; - }) - }); - return matches; - }, []); - - // Uncomment to re-enable highlights merging into details - // detail.forEach(function (field) { - // if (matchMap[field.id]) { - // field.highlights = matchMap[field.id].highlights; - // } - // }); - - const vm = { - type: { - id: obj.type, - label: type.getLabel(), - icon: icon - }, - // TODO: I don't remember why I named this "matchClass", but it confuses me now. - matchClass: { - id: type.getUIClass(), - copyable: type.isCopyable(), - viewable: type.isViewable(), - ref - }, - - // Detail, type-specific - detail: detail, - - url: window.location.origin + '#dataview/' + ref.workspaceId + '/' + ref.objectId + '/' + ref.version, - - // should be different per object type? E.g. narrative - nice name, others object name?? - // Generic fields - name: obj.object_name, - date: new Date(obj.modified_at), - scientificName: detailMap.scientificName ? detailMap.scientificName.value || '' : '', - - matches: matches, - selected: ko.observable(), - showMatches: ko.observable(false), - showDetails: ko.observable(false), - active: ko.observable(false) - }; - return vm; - } - - function search(query) { - const searchApi = SearchAPI.make({ - runtime: params.runtime - }); - return Promise.all([ - searchApi.referenceObjectSearch({ - query: query.terms.join(' '), - page: query.start || 0, - pageSize: searchConfig.fetchSize - }), - searchApi.typeSearch({ - query: query.terms.join(' '), - withPrivateData: 0, - withPublicData: 1, - dataSource: 'referenceData' - }) - ]) - .then(([objectResults, typeResults]) => { - const objects = objectResults.objects.map((object) => { - return objectToViewModel(object); - }); - const totalByType = Object.keys(typeResults.type_to_count).map(function (typeName) { - return { - id: typeName.toLowerCase(), - count: typeResults.type_to_count[typeName] - }; - }); - let totalSearchHits; - if (objectResults.total > maxSearchResults) { - totalSearchHits = maxSearchResults; - } else { - totalSearchHits = objectResults.total; - } - return { - items: objects, - first: query.start, - isTruncated: true, - summary: { - totalByType: totalByType, - totalSearchHits: totalSearchHits, - totalSearchSpace: objectResults.total, - isTruncated: totalSearchHits < objectResults.total - }, - stats: { - objectSearch: objectResults.search_time, - typeSearch: typeResults.search_time - } - }; - }); - } - - return { - search, - isStopWord - }; - } - - return { - make: factory - }; -}); diff --git a/react-app-todo/SystemAlertToggle/style.css b/react-app-todo/SystemAlertToggle/style.css deleted file mode 100644 index 27ff300a5..000000000 --- a/react-app-todo/SystemAlertToggle/style.css +++ /dev/null @@ -1,12 +0,0 @@ -.SystemAlertToggle {} - -.SystemAlertToggle .-button { - border: 1px silver solid; - padding: 3px; - margin: 2px; - cursor: pointer -} - -.SystemAlertToggle .-button:hover { - background-color: rgba(200, 200, 200, 0.5); -} \ No newline at end of file diff --git a/react-app-todo/SystemAlertToggle/view.js b/react-app-todo/SystemAlertToggle/view.js deleted file mode 100644 index 7a1ee0c10..000000000 --- a/react-app-todo/SystemAlertToggle/view.js +++ /dev/null @@ -1,116 +0,0 @@ -define([ - 'preact', - 'htm' -], ( - preact, - htm -) => { - - const {h, Component } = preact; - const html = htm.bind(h); - - function plural(amount, singular, plural) { - if (amount === 1) { - return singular; - } - return plural; - } - - class SystemAlertToggle extends Component { - constructor(props) { - super(props); - } - - componentDidMount() { - } - - doToggle() { - this.props.runtime.send('system-alert', 'toggle-banner'); - } - - renderAlertCount() { - if (this.props.alerts && this.props.alerts.length > 0) { - return html` - ${this.props.alerts.length} - ${' '}${plural(this.props.alerts.length, 'alert', 'alerts')} - `; - } else { - return 'no alerts'; - } - } - - renderPresentAlerts() { - if (this.props.summary.present === 0) { - return; - } - return html` -
- -
- `; - } - - renderFutureAlerts() { - if (this.props.summary.future === 0) { - return; - } - return html` -
- -
- `; - } - - doClose() { - this.props.runtime.send('system-alert', 'close-banner'); - } - - renderSummary() { - if (!this.props.alerts || this.props.alerts.length === 0) { - return html` -
- -
- `; - } - - if (!this.props.summary) { - return; - } - return html` - - ${this.renderPresentAlerts()} - ${this.renderFutureAlerts()} - `; - } - - renderButton() { - // - return html` -
-
- ${this.renderAlertCount()} - ${this.renderSummary()} -
-
- `; - } - - render() { - // // We only show the toggle when - // if (!this.props.hideAlerts) { - // return; - // } - return html` -
- ${this.renderButton()} -
- `; - } - } - - return SystemAlertToggle; -}); \ No newline at end of file diff --git a/react-app-todo/services/feeds.ts b/react-app-todo/services/feeds.ts deleted file mode 100644 index 3025dd964..000000000 --- a/react-app-todo/services/feeds.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { DataState } from '../lib/DataState'; -import { Feeds } from '../lib/kb_lib/comm/coreServices/Feeds'; -import { tryPromise } from '../lib/kb_lib/Utils'; -import { Runtime } from '../lib/runtime'; -import { Config } from '../types/config'; - -const MONITORING_INTERVAL = 10000; - -interface FeedsServiceParams { - // params: { - // runtime: Runtime; - // }; - runtime: Runtime; - config: Config; -} - -export interface FeedsNotification { - unseenNotificationsCount?: number; - error?: string; -} - -export default class FeedsService { - runtime: Runtime; - monitoringInterval: number; - monitorRunning: boolean; - monitoringRunCount: number; - monitoringErrorCount: number; - disabled: boolean; - monitoringTimer: number | null; - state: DataState; - - constructor({ config, runtime }: FeedsServiceParams) { - this.runtime = runtime; - - // TODO: move to service config. - this.monitoringInterval = MONITORING_INTERVAL; - - this.monitorRunning = false; - this.monitoringRunCount = 0; - this.monitoringErrorCount = 0; - this.monitoringTimer = null; - - this.disabled = config.ui.coreServices.disabled.includes('Feeds'); - - this.state = new DataState({}); - } - - start() { - return tryPromise(() => { - this.runtime.db().set('feeds', { - notifications: null, - error: null, - }); - - if (this.disabled) { - console.warn( - 'Feeds service disabled; skipping monitoring hooks' - ); - return; - } - - // listen for login and out events... - this.runtime.on('session', 'loggedin', () => { - this.startFeedsMonitoring(); - }); - - this.runtime.on('session', 'loggedout', () => { - this.stopFeedsMonitoring(); - }); - - // if logged in, populate and start monitoring for feeds notifications - if (this.runtime.service('session').getAuthToken()) { - return this.startFeedsMonitoring(); - } - }); - } - - stop() { - return tryPromise(() => { - this.stopFeedsMonitoring(); - }); - } - - startFeedsMonitoring() { - if (this.monitorRunning) { - return; - } - this.monitorRunning = true; - this.monitoringLoop(); - } - - monitoringLoop() { - if (this.monitoringTimer) { - return; - } - - const monitoringJob = () => { - const feedsClient = new Feeds({ - url: this.runtime.config('services.Feeds.url', null), - token: this.runtime.service('session').getAuthToken(), - }); - return feedsClient - .getUnseenNotificationCount() - .then(({ unseen: { global, user } }) => { - const currentUnseen = global + user; - - // are notifications different than the last time? - const unseenNotificationsCount = this.runtime - .db() - .get('feeds.unseenNotificationsCount', 0); - - if (unseenNotificationsCount === currentUnseen) { - return; - } - - this.runtime.db().set('feeds', { - unseenNotificationsCount: currentUnseen, - error: null, - }); - }) - .catch((err) => { - console.error('ERROR', err.message); - this.runtime.db().set('feeds', { - error: err.message, - }); - }); - }; - - const loop = () => { - this.monitoringTimer = window.setTimeout(() => { - monitoringJob() - .then(() => { - this.monitoringRunCount += 1; - if (this.monitorRunning) { - loop(); - } - }) - .catch((err) => { - this.monitoringErrorCount += 1; - console.error('ERROR', err); - }); - }, this.monitoringInterval); - }; - - monitoringJob() - .then(() => { - loop(); - }) - .catch((err) => { - console.error('Error', err); - }); - } - - stopFeedsMonitoring() { - this.monitorRunning = false; - if (this.monitoringTimer !== null) { - window.clearTimeout(this.monitoringTimer); - } - this.monitoringTimer = null; - } - - // pluginHandler() {} -} - -export const ServiceClass = FeedsService; diff --git a/react-app-todo/session.ts b/react-app-todo/session.ts deleted file mode 100644 index 2c9a9e116..000000000 --- a/react-app-todo/session.ts +++ /dev/null @@ -1,210 +0,0 @@ -// define([ -// 'lib/kb_lib/Auth2Session', -// 'kb_lib/observed', -// 'kb_lib/html' -// ], ( -// { Auth2Session }, -// Observed, -// html -// ) => { -// const t = html.tag, -// div = t('div'), -// p = t('p'), -// a = t('a'); - -import { Auth2Session, CookieConfig } from '../lib/kb_lib/Auth2Session'; -import { Observed } from '../lib/kb_lib/observed'; -import { Runtime } from '../lib/runtime'; -import { Config } from '../types/config'; - -export interface SessionServiceState { - loggedIn: boolean; -} - -export class SessionService { - runtime: Runtime; - extraCookies: Array; - auth2Session: Auth2Session; - state: Observed; - constructor(runtime: Runtime, config: Config) { - this.runtime = runtime; - this.extraCookies = []; - if (config.ui.services.session.cookie.backup.enabled) { - this.extraCookies.push({ - name: config.ui.services.session.cookie.backup.name, - domain: config.ui.services.session.cookie.backup.domain, - }); - } - this.auth2Session = new Auth2Session({ - cookieName: config.ui.services.session.cookie.name, - extraCookies: this.extraCookies, - baseUrl: config.services.Auth2.url, - }); - - this.state = new Observed(null); - } - - getAuthToken() { - return this.auth2Session.getToken(); - } - - getUsername() { - return this.auth2Session.getUsername(); - } - - getEmail() { - return this.auth2Session.getEmail(); - } - - getRealname() { - return this.auth2Session.getRealname(); - } - - getRoles() { - return this.auth2Session.getRoles() || []; - } - - getCustomRoles() { - return this.auth2Session.getCustomRoles() || []; - } - - getTokenInfo() { - return this.auth2Session.getTokenInfo(); - } - - getMe() { - return this.auth2Session.getMe(); - } - - isLoggedIn() { - return this.auth2Session.isLoggedIn(); - } - - isAuthorized() { - return this.auth2Session.isAuthorized(); - } - - isAuthenticated() { - return this.auth2Session.isAuthorized(); - } - - getKbaseSession() { - return this.auth2Session.getKbaseSession(); - } - - getLastProvider() { - return this.auth2Session.getLastProvider(); - } - - getProviders() { - return this.auth2Session.getClient().getProviders(); - } - - // Session state change - loginStart(arg) { - // starts an auth login / signup redirect loop - // it _could_ be done inside an iframe ... - this.auth2Session.loginStart(arg); - } - - logout() { - return this.auth2Session.logout().then((result) => { - return result; - }); - } - - notifyError(message) { - this.runtime.send('ui', 'alert', { - type: 'warning', - message: message.message, - description: message.description, - icon: 'exclamation-triangle', - name: 'auth-connection', - }); - } - - notifyOk(message) { - this.runtime.send('ui', 'alert', { - type: 'success', - message: message.message, - description: message.description, - icon: 'check', - name: 'auth-connection', - timeout: 10000, - }); - } - - start() { - return this.auth2Session.start().then(() => { - if (this.auth2Session.isAuthorized()) { - this.state.setItem('loggedin', true); - this.runtime.send('session', 'loggedin'); - } else { - this.state.setItem('loggedin', false); - this.runtime.send('session', 'loggedout'); - } - this.auth2Session.onChange((change) => { - this.runtime.send('session', 'change', { - state: change, - }); - switch (change) { - case 'interrupted': - var description = div([ - p( - 'Your session cannot be verified because the authorization service is currently inaccessible' - ), - p([ - "You may patiently await it's recovery or ", - a( - { - href: '/#signout', - }, - 'signout' - ), - ' and try again later', - ]), - ]); - this.notifyError({ - message: 'Session cannot be verified', - description: description, - }); - return; - case 'restored': - this.notifyOk({ - message: - 'Communication restored -- session has been verified', - description: '', - }); - } - if (this.auth2Session.isAuthorized()) { - if (change === 'newuser') { - // TODO: do something special... - } - this.state.setItem('loggedin', true); - this.runtime.send('session', 'loggedin'); - } else { - this.state.setItem('loggedin', false); - this.runtime.send('session', 'loggedout'); - } - }); - }); - } - - stop() { - return this.auth2Session.stop().then(() => { - // session = null; - }); - } - - onChange(fun) { - this.state.listen('loggedin', { - onSet: (value) => { - fun(value); - }, - }); - } - - getClient() { - return this.auth2Session; - } -} diff --git a/scripts/container/generate-proxy-env b/scripts/container/generate-proxy-env new file mode 100755 index 000000000..3913ff91b --- /dev/null +++ b/scripts/container/generate-proxy-env @@ -0,0 +1,140 @@ +#!/usr/bin/env bash + +# Proxy Container +# +# See tools/proxy/contents/conf/nginx.conf.tmpl for usage +# +# Input environment variables: +# +# required: +# +# DEPLOY_ENV +# BASE_PATH +# KBASE_UI_HOSTNAME +# +# (either BASE_PATH, KBASE_UI_HOSTNAME or both must be provided) +# +# optional: +# +# KBASE_UI_HOST +# KBASE_UI_PORT +# EUROPA_UI_HOST +# EUROPA_UI_PORT +# NARRATIVE_HOST +# NARRATIVE_PORT +# SERVICE_PROXIES +# DYNAMIC_SERVICE_PROXIES +# +# Created environment variables: +# +# KBASE_UI_BASE_PATH +# KBASE_DOMAIN +# KBASE_UI_HOSTNAME +# SERVICES_DOMAIN +# KBASE_ENDPOINT +# KBASE_UI_HOST +# KBASE_UI_PORT +# EUROPA_UI_HOST +# EUROPA_UI_PORT +# NARRATIVE_HOST +# NARRATIVE_PORT +# SERVICE_PROXIES +# DYNAMIC_SERVICE_PROXIES + + +# +# Defaults +# +DEFAULT_KBASE_UI_BASE_PATH='' +DEFAULT_KBASE_UI_HOSTNAME='legacy' +DEFAULT_SERVICE_PROXIES='' +DEFAULT_DYNAMIC_SERVICE_PROXIES='' + +# +# Returns the environment variable setting line only if the variable has been +# defined and is non-blank. +# +# If USE_DEFAULTS is defined, the default values defined above will be used +# for any empty or undefined variable. +# +function env_var() { + local var_name="${1}" + if [[ -z "${!var_name}" ]] + then + if [[ -z "${USE_DEFAULTS}" ]] + then + echo '' + else + local default_var_name="DEFAULT_${var_name}" + + IFS= printf "\n%s='%s'" ${var_name} ${!default_var_name} + fi + else + IFS= printf "\n%s='%s'" ${var_name} ${!var_name} + fi +} + +echo +echo 'Creating proxy env vars...' + +if [ -z "${DEPLOY_ENV}" ] +then + echo 'The "DEPLOY_ENV" environment variable is required to generate config env' + exit 1 +fi + +echo +echo "DEPLOY_ENV is '${DEPLOY_ENV}'" + +# if [ -z "${KBASE_UI_BASE_PATH}" ] && [ -z "${KBASE_UI_HOSTNAME}" ] +# then +# echo 'Either the "KBASE_UI_BASE_PATH" or "KBASE_UI_HOSTNAME" environment variable is required to generate config env' +# exit 1 +# fi + +echo "KBASE_UI_BASE_PATH is '${KBASE_UI_BASE_PATH}'" +echo "KBASE_UI_HOSTNAME is '${KBASE_UI_HOSTNAME}'" +echo "LOCAL_KBASE_UI is '${LOCAL_KBASE_UI}'" +echo + +# +# These rarely, if ever, change +# + +# The proxy target for kbase-ui; the ip or host of the kbase-ui container. +# KBASE_UI_HOST="${KBASE_UI_HOST}" # kbase-ui +# EUROPA_UI_HOST="${EUROPA_UI_HOST}" # europa-ui +# NARRATIVE_HOST="${NARRATIVE_HOST}" # narrative + +KBASE_DOMAIN="${DEPLOY_ENV}.kbase.us" +SERVICES_DOMAIN="${KBASE_DOMAIN}" + +# +# These are controlled directly by the developer +# +# SERVICE_PROXIES="${SERVICE_PROXIES}" +# DYNAMIC_SERVICE_PROXIES="${DYNAMIC_SERVICE_PROXIES}" +# KBASE_UI_HOST="${KBASE_UI_HOST}" +# KBASE_UI_PORT="${KBASE_UI_PORT}" +# NARRATIVE_HOST="${NARRATIVE_HOST}" +# NARRATIVE_PORT="${NARRATIVE_PORT}" +# EUROPA_UI_HOST="${EUROPA_UI_HOST}" +# EUROPA_UI_PORT="${EUROPA_UI_PORT}" + +# Generates an env file for usage by the proxy service in the devcontainer. + +cat << EOF > ./.devcontainer/proxy.env +# An env file for usage by the proxy service in the devcontainer. +$(env_var KBASE_UI_BASE_PATH)\ +$(env_var KBASE_UI_HOSTNAME)\ +$(env_var KBASE_DOMAIN)\ +$(env_var SERVICES_DOMAIN)\ +$(env_var SERVICE_PROXIES)\ +$(env_var DYNAMIC_SERVICE_PROXIES)\ +$(env_var KBASE_UI_HOST)\ +$(env_var KBASE_UI_PORT)\ +$(env_var NARRATIVE_HOST)\ +$(env_var NARRATIVE_PORT)\ +$(env_var EUROPA_UI_HOST)\ +$(env_var EUROPA_UI_PORT) +EOF \ No newline at end of file diff --git a/scripts/container/generate-runtime-env b/scripts/container/generate-runtime-env new file mode 100755 index 000000000..f38bdb8fa --- /dev/null +++ b/scripts/container/generate-runtime-env @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +# KBase UI Config and Nginx Server Environment Variables +# +# Used to generate config.json and nginx.conf. +# +# Input environment variables: +# +# required: +# +# DEPLOY_ENV +# +# Created env vars for config.json.tmpl: +# +# BASE_PATH +# DEFAULT_PATH +# DEFAULT_PATH_TYPE +# KBASE_DOMAIN +# FEATURE_SWITCHES_ENABLED +# FEATURE_SWITCHES_DISABLED +# AUTH2_PROVIDERS +# + +if [ -z "${DEPLOY_ENV}" ] +then + echo 'The "DEPLOY_ENV" environment variable is required to generate config env' + exit 1 +fi + +# +# Defaults for all that support defaults. +# +DEFAULT_AUTH2_PROVIDERS='Google,Globus,OrcID' +DEFAULT_KBASE_UI_BASE_PATH='' +DEFAULT_KBASE_UI_HOSTNAME='legacy' +DEFAULT_DEFAULT_PATH_TYPE='europaui' +DEFAULT_DEFAULT_PATH='narratives' +DEFAULT_FEATURE_SWITCHES_DISABLED='' +DEFAULT_FEATURE_SWITCHES_ENABLED='' +DEFAULT_NGINX_LISTEN='80' +DEFAULT_NGINX_LOG_LEVEL='error' +DEFAULT_NGINX_LOG_STDERR='true' +DEFAULT_NGINX_LOG_STDOUT='true' +DEFAULT_NGINX_LOG_SYSLOG='' +DEFAULT_NGINX_SERVER_NAME='localhost' + +# +# These are generated - just documenting that fact here. +# +# DEFAULT_KBASE_UI_HOSTNAME +# DEFAULT_KBASE_DOMAIN + + +# +# These change per environment, with the special case for prod. +# + +# Domain all other user intefaces +KBASE_DOMAIN="${DEPLOY_ENV}.kbase.us" + +# Domain for kbase-ui +# TODO: is this used? if it is, we need the subdomain hostname; if not, remove. +# if [ -z "${KBASE_UI_HOSTNAME}" ] +# then +# KBASE_UI_DOMAIN=$KBASE_DOMAIN +# else +# KBASE_UI_DOMAIN="${KBASE_UI_HOSTNAME}.${KBASE_DOMAIN}" +# fi + +# Base URL for services +# KBASE_ENDPOINT="https://${DEPLOY_ENV}.kbase.us/services/" + +# +# Auth providers +# +if [ "$DEPLOY_ENV" = "appdev" ] +then + AUTH2_PROVIDERS="Google,Globus" +else + AUTH2_PROVIDERS="" +fi + +# +# Created env vars for nginx.json.tmpl: +# Note that these may not be used, but we generate them anyway. +# +# BASE_PATH +# NGINX_LOG_SYSLOG +# NGINX_LOG_STDOUT +# NGINX_LOG_STDERR +# NGINX_LOG_LEVEL +# NGINX_LISTEN +# NGINX_SERVER_NAME + +# +# Returns the environment variable setting line only if the variable has been +# defined and is non-blank. +# +function env_var() { + local var_name="${1}" + if [[ -z "${!var_name}" ]] + then + if [[ -z "${USE_DEFAULTS}" ]] + then + echo '' + else + local default_var_name="DEFAULT_${var_name}" + IFS= printf "\n%s='%s'" ${var_name} ${!default_var_name} + fi + else + IFS= printf "\n%s='%s'" ${var_name} ${!var_name} + fi +} + + +# Generates a temporary env file for usage in generating the runtime template +# config.json and nginx.conf + +cat << EOF > ./.devcontainer/runtime.env +# An env file to be used by to generate the deploy config for development, +# and to serve as an env file when running a local image. +$(env_var AUTH2_PROVIDERS)\ +$(env_var KBASE_UI_BASE_PATH)\ +$(env_var KBASE_UI_HOSTNAME)\ +$(env_var DEFAULT_PATH_TYPE)\ +$(env_var DEFAULT_PATH)\ +$(env_var FEATURE_SWITCHES_DISABLED)\ +$(env_var FEATURE_SWITCHES_ENABLED)\ +$(env_var NGINX_LISTEN)\ +$(env_var NGINX_LOG_LEVEL)\ +$(env_var NGINX_LOG_STDERR)\ +$(env_var NGINX_LOG_STDOUT)\ +$(env_var NGINX_LOG_SYSLOG)\ +$(env_var NGINX_SERVER_NAME)\ +$(env_var KBASE_DOMAIN) +EOF diff --git a/scripts/host/build-image.sh b/scripts/host/build-image.sh old mode 100644 new mode 100755 index 96596c06c..7df5df53b --- a/scripts/host/build-image.sh +++ b/scripts/host/build-image.sh @@ -1 +1,2 @@ +#!/usr/bin/env bash docker build . -t kbase/kbase-ui:dev \ No newline at end of file diff --git a/scripts/host/build-info.sh b/scripts/host/build-info.sh new file mode 100755 index 000000000..6654305b2 --- /dev/null +++ b/scripts/host/build-info.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +echo "------------------" +echo "build-plugins.sh" +echo "------------------" + +# The script we are running +export SCRIPT_MODULE="scripts.build-info" + +# Arguments for the script +export INSTALL_DEST="/app/build/build/build-info.json" + +# assume we are run from the root of the project. +cd tools/python + +echo +echo "Creating build info" +echo + +docker compose run --rm runner \ + python -m ${SCRIPT_MODULE} ${INSTALL_DEST} + +cd ../.. \ No newline at end of file diff --git a/scripts/host/build.sh b/scripts/host/build.sh index 91450c683..94bff80f3 100644 --- a/scripts/host/build.sh +++ b/scripts/host/build.sh @@ -1,4 +1,3 @@ cd tools/node -docker compose run --rm node npm uninstall * -docker compose run --rm node npm install -docker compose run --rm node npm run build \ No newline at end of file +docker compose run --rm node-tool npm ci +docker compose run -e KBASE_UI_BASE_PATH --rm node-tool npm run build \ No newline at end of file diff --git a/scripts/host/clean-build.sh b/scripts/host/clean-build.sh deleted file mode 100644 index 8107c7a0a..000000000 --- a/scripts/host/clean-build.sh +++ /dev/null @@ -1,2 +0,0 @@ -# ensure the target directory is empty (mostly for dev usage) -rm -rf build/dist diff --git a/scripts/host/extend-docker-compose.sh b/scripts/host/extend-docker-compose.sh deleted file mode 100644 index 3ed8abbf5..000000000 --- a/scripts/host/extend-docker-compose.sh +++ /dev/null @@ -1 +0,0 @@ -bash scripts/deno/docker-compose-override.sh \ No newline at end of file diff --git a/scripts/host/git-info.sh b/scripts/host/git-info.sh new file mode 100755 index 000000000..d3de0bdf3 --- /dev/null +++ b/scripts/host/git-info.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +echo "------------------" +echo "git-info.sh" +echo "------------------" + +# The script we are running +export SCRIPT_MODULE="scripts.git-info" + +# Arguments for the script +export INSTALL_DEST="/app/build/build/git-info.json" + +# assume we are run from the root of the project. +cd tools/python + +echo +echo "Creating git info in ${INSTALL_DEST}" +echo + +docker compose run --rm runner \ + python -m ${SCRIPT_MODULE} ${INSTALL_DEST} + +cd ../.. \ No newline at end of file diff --git a/scripts/host/install-plugins.sh b/scripts/host/install-plugins.sh old mode 100644 new mode 100755 index 9709a6aad..782e3f67f --- a/scripts/host/install-plugins.sh +++ b/scripts/host/install-plugins.sh @@ -1 +1,31 @@ -bash scripts/deno/install-plugins.sh \ No newline at end of file +#!/usr/bin/env bash + +echo "------------------" +echo "install-plugins.sh" +echo "------------------" +# The HOST_APP_DIR is volume mounted as /app in the container. +export HOST_APP_DIR=${PWD} + +# The script we are running +export SCRIPT_MODULE="scripts.install-plugins" + +# Arguments for the script +export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" +export PLUGINS_INSTALL_DEST="/app/build/plugins" + +export GH_TOKEN="${GH_TOKEN:?GH_TOKEN not set}" + +echo "GH_TOKEN is set" + +# assume we are run from the root of the project. +cd tools/python + +echo +echo "Installing plugins" +echo "HOST_APP_DIR=$HOST_APP_DIR" +echo + +docker compose run --rm runner \ + python -m ${SCRIPT_MODULE} ${PLUGINS_CONFIG_PATH} ${PLUGINS_INSTALL_DEST} ${GH_TOKEN} + +cd ../.. \ No newline at end of file diff --git a/scripts/host/re-build.sh b/scripts/host/re-build.sh deleted file mode 100644 index 17cadba9a..000000000 --- a/scripts/host/re-build.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd tools/deno -DIR=`pwd`/../../react-app docker compose run node npm run build \ No newline at end of file diff --git a/scripts/host/run-image.sh b/scripts/host/run-image.sh old mode 100644 new mode 100755 index 61abfb498..fc18df9a6 --- a/scripts/host/run-image.sh +++ b/scripts/host/run-image.sh @@ -1,9 +1,12 @@ +#!/usr/bin/env bash + docker network create kbase-dev -# -v `pwd`/build/app/modules/plugins/auth2-client:/kb/deployment/services/kbase-ui/dist/modules/plugins/auth2-client \ + export ENV=ci echo echo "Running kbase-ui production image in development, deploy env is '${ENV}'" echo + docker run \ -v `pwd`/dev/gitlab-config:/kb/deployment/config \ --network kbase-dev \ diff --git a/scripts/host/run-proxy.sh b/scripts/host/run-proxy.sh new file mode 100755 index 000000000..77404c797 --- /dev/null +++ b/scripts/host/run-proxy.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# +# A script to run the development proxy in standalone mode. +# +# To use it, you first need to generate the proxy.env file. +# + +if ! [ -f ./.devcontainer/proxy.env ] +then + echo "---------------------------------" + echo " ERROR: proxy env file not found " + echo "---------------------------------" + echo + echo "The .devcontainer/proxy.env file must exist in order to " + echo "run the development proxy." + echo "Please see docs/development.md and Taskfile" + echo + echo "To generate proxy.env:" + echo + echo "LOCAL_NARRATIVE='x' LOCAL_KBASE_UI='x' KBASE_UI_HOSTNAME='x' SERVICE_PROXIES=''x' ./Taskfile run-proxy" + echo + echo "where" + echo "LOCAL_NARRATIVES should be set to 't' to enable proxying to a local narrative, otherwise it will proxy to the deployment" + echo "LOCAL_KBASE_UI should be set to 't' to enable proxying to a local kbase-ui, otherwise it will proxy to KBASE_UI_DOMAIN" + echo "SERVICE_PROXIES should be set to a comma-separated list of local service container hostnames (which must be the same as" + echo " the service's path in the endpoint." + + echo + exit 1 +fi + +echo "okay, will do" +cd tools/proxy +docker compose up +docker compose rm -f \ No newline at end of file diff --git a/scripts/host/shell.sh b/scripts/host/shell.sh deleted file mode 100644 index 9a6d17822..000000000 --- a/scripts/host/shell.sh +++ /dev/null @@ -1,6 +0,0 @@ -cd tools/deno -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno bash \ No newline at end of file diff --git a/scripts/host/test.sh b/scripts/host/test.sh index 0a0f85d3d..28c636e16 100644 --- a/scripts/host/test.sh +++ b/scripts/host/test.sh @@ -2,5 +2,5 @@ echo "[test.sh] starting in ${PWD}, DIR=${DIR}" echo "" cd tools/node ls -docker compose run --rm node npm install -docker compose run --rm node npm run test \ No newline at end of file +docker compose run --rm node-tool npm ci +docker compose run --rm node-tool npm run test \ No newline at end of file diff --git a/tools/deno/cli/Dockerfile b/tools/deno/cli/Dockerfile deleted file mode 100644 index b23b21eac..000000000 --- a/tools/deno/cli/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM denoland/deno:alpine-1.35.1 - -RUN apk upgrade --update-cache --available && \ - apk add --update --no-cache bash git make - -WORKDIR /app - -# Prefer not to run as root. -# USER deno - -# Cache the dependencies as a layer (the following two steps are re-run only when deps.ts is modified). -# Ideally cache deps.ts will download and compile _all_ external files used in main.ts. -# COPY deps.ts . -# RUN deno cache deps.ts - -# These steps will be re-run upon each file change in your working directory: -# ADD . . -# Compile the main app so that it doesn't need to be compiled each startup/entry. -# RUN deno cache main.ts - -# CMD ["run", "--unstable", "--allow-run", "--alow-write", "--allow-read", "install-plugins.ts"] \ No newline at end of file diff --git a/tools/deno/cli/docker-compose.yml b/tools/deno/cli/docker-compose.yml deleted file mode 100644 index 1e656ec8c..000000000 --- a/tools/deno/cli/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '3.6' -services: - deno: - build: - # context is tools/deno; - # scripts are made available via the volume mount. - context: . - image: kbase/deno:dev - container_name: kbase-deno - dns: 8.8.8.8 - volumes: - - $HOST_APP_DIR:/app:rw diff --git a/tools/deno/scripts/build-info.sh b/tools/deno/scripts/build-info.sh deleted file mode 100644 index 8c28027f3..000000000 --- a/tools/deno/scripts/build-info.sh +++ /dev/null @@ -1,32 +0,0 @@ -# -# Set up and invoke the associated deno script. -# - -# The HOST_APP_DIR environment variable roots the deno cli (in the form of -# docker compose) in the host. -# The HOST_APP_DIR is volume mounted as /app in the container. -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="build-info.ts" - -# Arguments for the script -export INSTALL_DEST="/app/build/build/build-info.json" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Creating build info" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} ${INSTALL_DEST} diff --git a/tools/deno/scripts/build-info.ts b/tools/deno/scripts/build-info.ts deleted file mode 100644 index fce57136f..000000000 --- a/tools/deno/scripts/build-info.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { log } from "./common.ts"; - -async function getBuildInfo( - dir: string, -) { - return { - builtAt: new Date().toISOString(), - }; -} - -async function main() { - if (Deno.args.length !== 1) { - log("Usage: build-info.ts "); - Deno.exit(1); - } - const destinationFile = Deno.args[0]; - - log(`Saving build info info to ${destinationFile}`, "build-info.ts:main()"); - - const info = await getBuildInfo(destinationFile); - log(JSON.stringify(info, null, 4), "build-info.ts:main()"); - - await Deno.writeFile( - destinationFile, - new TextEncoder().encode(JSON.stringify(info, null, 4)), - ); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/cli.sh b/tools/deno/scripts/cli.sh deleted file mode 100644 index 36e0fee3f..000000000 --- a/tools/deno/scripts/cli.sh +++ /dev/null @@ -1,11 +0,0 @@ -cd tools/deno-cli -export REL_DIR=`pwd`/../.. -export DIR=$(cd ${REL_DIR}; pwd) -echo -echo "Installing plugins" -echo "REL_DIR=$REL_DIR" -echo "DIR=$DIR" -echo -ls $DIR -echo -docker-compose run sh \ No newline at end of file diff --git a/tools/deno/scripts/common.ts b/tools/deno/scripts/common.ts deleted file mode 100644 index e3043bc6e..000000000 --- a/tools/deno/scripts/common.ts +++ /dev/null @@ -1,194 +0,0 @@ -export function log(message: string, source?: string): void { - const timestamp = Intl.DateTimeFormat("en-US").format(Date.now()); - let prefix = `[${timestamp}]`; - if (source) { - prefix += ` [${source}]`; - } - console.log(`${prefix} ${message}`); -} - -export interface PluginConfig { - name: string; - globalName: string; - version: string; - source: { - github: { - account: string; - }; - }; -} - -export interface PluginsConfig { - plugins: Array; -} - -export class Runner { - directory: string; - constructor(directory: string) { - this.directory = directory; - } - - async run(cmd: string, args: Array, throwOnError: boolean = true) { - const commandOptions: Deno.CommandOptions = { - stderr: "piped", - stdout: "piped", - args, - cwd: this.directory - }; - // commandOptions.cwd = this.directory; - // console.log('[run] CWD is ' + this.directory) - // console.log('[run] cmd is ', cmd); - const command = new Deno.Command(cmd, commandOptions); - try { - const { code, stdout, stderr } = await command.output(); - if (code !== 0 && throwOnError) { - log("Run Failed!"); - log(String(code)); - // log(String(status.success)); - // log(String(status.signal)); - const errorText = new TextDecoder().decode(stderr); - log(errorText); - throw new Error('Run failed!'); - } - return new TextDecoder().decode(stdout); - // TODO: handle errors: - } catch (ex) { - console.error('[run] error', ex); - throw new Error(`[run] Error running command ${cmd}: ${ex.message}`) - } - } -} - -export type ISODateTimeString = string; - -export interface GitInfo { - hash: { - full: string; - abbreviated: string; - }; - subject: string; - notes: string; - author: { - name: string; - date: ISODateTimeString; - }; - committer: { - name: string; - date: ISODateTimeString; - }; - originURL: string; - account: string; - repoName: string; - branch: string; - tag?: string; - version?: string; -} - -export class Git { - directory: string; - runner: Runner; - constructor(directory: string) { - this.directory = directory; - this.runner = new Runner(directory); - } - async gitTag(): Promise<{ tag?: string; version?: string }> { - const rawTag = await this.runner.run('git', [ - "describe", - "--exact-match", - "--tags", - ], false); - const tag = rawTag.trim(); - if (/^fatal/.test(tag)) { - return { tag }; - } else { - const m = /^v([\d]+)\.([\d]+)\.([\d]+)$/.exec(tag); - if (m) { - return { tag, version: m.slice(1).join(".") }; - } else { - if (tag.length > 0) { - return { tag }; - } - return {}; - } - } - } - - async clone(url: string, name: string, branch: string) { - const args = [ - "clone", - // "--quiet", - "--depth", - "1", - "--branch", - branch, - url, - `${this.directory}/${name}`, - ]; - return this.runner.run('git', args); - } - - async getInfo(): Promise { - await this.runner.run('git', [ - "config", - "--global", - "--add", - "safe.directory", - "/app", - ]); - - const showOutput = await this.runner.run('git', [ - "show", - "--format=%H%n%h%n%an%n%at%n%cn%n%ct%n%d", - "--name-status", - ]); - const [ - commitHash, - commitAbbreviatedHash, - authorName, - authorDateEpoch, - committerName, - committerDateEpoch, - ] = showOutput.split("\n").slice(0, 6); - - const subject = await this.runner.run('git', ["log", "-1", "--pretty=%s"]); - const notes = await this.runner.run('git', ["log", "-1", "--pretty=%N"]); - let originURL = - (await this.runner.run('git', ["config", "--get", "remote.origin.url"])) - .trim(); - - if (originURL.endsWith(".git")) { - originURL = originURL.slice(0, -4); - } - - const url = new URL(originURL); - const path = url.pathname; - const [_ignore, account, repoName] = path.split("/"); - const branch = - (await this.runner.run('git', ["rev-parse", "--abbrev-ref", "HEAD"])) - .trim(); - const { tag, version } = await this.gitTag(); - - return { - hash: { - full: commitHash, - abbreviated: commitAbbreviatedHash, - }, - subject, - notes, - author: { - name: authorName, - date: new Date(parseInt(authorDateEpoch) * 1000).toISOString(), - }, - committer: { - name: committerName, - date: new Date(parseInt(committerDateEpoch) * 1000).toISOString(), - }, - originURL, - account, - repoName, - branch, - tag, - version, - }; - } -} diff --git a/tools/deno/scripts/docker-compose-override.md b/tools/deno/scripts/docker-compose-override.md deleted file mode 100644 index 723df9981..000000000 --- a/tools/deno/scripts/docker-compose-override.md +++ /dev/null @@ -1,5 +0,0 @@ -# Docker Compose Override - -This script prepares a `docker-compose-override.yml` file which works in conjunction with a base `dev/docker-compose.yml` file to augment its behavior. - -This docker compose configuration is used in development for various scenarios, such as using a set of configuration files (simulating the set of config files in gitlab), proxying to local services, dynamic services, narrative and navigator. diff --git a/tools/deno/scripts/docker-compose-override.sh b/tools/deno/scripts/docker-compose-override.sh deleted file mode 100644 index 5bfb4d4d4..000000000 --- a/tools/deno/scripts/docker-compose-override.sh +++ /dev/null @@ -1,34 +0,0 @@ -# cd tools/deno/cli -# DIR=`pwd`/../.. docker compose run deno run \ -# --unstable --allow-run --allow-write --allow-read \ -# /app/scripts/deno/docker-compose-override.ts /app/dev \ -# --config-dir `pwd`/../../../dev/gitlab-config - -# docker run -v `pwd`/../..:/app --rm deno run --unstable --allow-run --allow-write --allow-read /app/scripts/deno/docker-compose-override.ts /app/dev/docker-compose-override.yml --config-dir /app/dev/gitlab-config - -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="docker-compose-override.ts" - -# Arguments for the script -# export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" -# export PLUGINS_INSTALL_DEST="/app/build" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Creating docker compose override" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} /app/dev --config-dir ${HOST_APP_DIR}/dev/gitlab-config \ No newline at end of file diff --git a/tools/deno/scripts/docker-compose-override.ts b/tools/deno/scripts/docker-compose-override.ts deleted file mode 100644 index ba5a1555a..000000000 --- a/tools/deno/scripts/docker-compose-override.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { parse } from 'https://deno.land/std@0.109.0/flags/mod.ts'; -import { stringify } from 'https://deno.land/std@0.109.0/encoding/yaml.ts'; -import { exists } from 'https://deno.land/std@0.109.0/fs/mod.ts'; - -// const yargs = require('yargs'); -// const yaml = require('js-yaml'); -// const fs = require('fs'); -// const exec = require('child_process').execSync; - -// function getRoot() { -// const out = exec('git rev-parse --show-toplevel', { -// encoding: 'utf8' -// }); -// return out.trim(); -// } - -// function mergePlugins(root, config, args) { -// if (args.plugin) { -// let pluginSpecs; -// if (typeof args.plugin === 'string') { -// pluginSpecs = [args.plugin]; -// } else { -// pluginSpecs = args.plugin; -// } - -// const plugins = pluginSpecs.map((pluginSpec) => { -// const parts = pluginSpec.split(':'); -// if (parts.length === 1) { -// return { -// pluginName: parts[0], -// repoSuffix: parts[0] -// }; -// } -// return { -// pluginName: parts[0], -// repoSuffix: parts[1] -// }; -// }); - -// plugins.forEach(({ pluginName, repoSuffix }) => { -// const pluginRoot = `${root}/../kbase-ui-plugin-${repoSuffix}`; -// let pluginDir = `${pluginRoot}/dist/plugin`; - -// if (!fs.existsSync(pluginDir)) { -// pluginDir = `${pluginRoot}/src/plugin`; -// if (!fs.existsSync(pluginDir)) { -// pluginDir = `${pluginRoot}/plugin`; -// if (!fs.existsSync(pluginDir)) { -// throw new Error(`Plugin directory not found: ${pluginDir}`); -// } -// } -// } - -// config.services['kbase-ui'].volumes.push({ -// type: 'bind', -// source: pluginDir, -// target: `/kb/deployment/services/kbase-ui/dist/modules/plugins/${pluginName}` -// }); -// }); -// } -// } - -// function mountStatic(root, config, args) { -// if (args.mount_static) { -// config.services['kbase-ui'].volumes.push({ -// type: 'bind', -// source: `${root}/static`, -// target: `/kb/deployment/services/kbase-ui/dist` -// }); -// } -// } - -// function mergeLibs(root, config, args) { -// if (args.lib) { -// let libs; -// if (typeof args.lib === 'string') { -// libs = [args.lib]; -// } else { -// libs = args.lib; -// } -// libs.forEach((lib) => { -// const [libName, path, moduleName] = lib.split(':'); -// config.services['kbase-ui'].volumes.push({ -// type: 'bind', -// source: `${root}/../kbase-${libName}/${path}`, -// target: `/kb/deployment/services/kbase-ui/dist/modules/${moduleName}` -// }); -// }); -// } -// } - -async function mergeConfigDir(configDir: string, config: DockerComposeConfig) { - // const gitlabConfigDir = `${root}/dev/gitlab-config`; - // if (!(await exists(configDir))) { - // console.log(`Provided config dir ${configDir} does not exist`); - // Deno.exit(1); - // } - - console.log(`using config dir ${configDir}`); - config.services['kbase-ui'].volumes.push({ - type: 'bind', - source: configDir, - target: '/kb/deployment/config', - }); - return config; - - // } else { - // console.log("using local configs"); - // config.services["kbase-ui"].volumes.push({ - // type: "bind", - // source: `${root}/deployment/config`, - // target: "/kb/deployment/config", - // }); - // } -} - -// function mergeDynamicServices(root, config, args) { -// if (args.dynamic_services) { -// let services; -// if (typeof args.dynamic_services === 'string') { -// services = [args.dynamic_services]; -// } else { -// services = args.dynamic_services; -// } -// const proxy_env = `dynamic_service_proxies=${services.join(' ')}`; -// config.services['kbase-ui'].environment.push(proxy_env); -// config.services['kbase-ui-proxy'].environment.push(proxy_env); -// } -// } - -// function mergeServices(root, config, args) { -// if (args.services) { -// let services; -// if (typeof args.services === 'string') { -// services = [args.services]; -// } else { -// services = args.services; -// } -// const proxy_env = `service_proxies=${services.join(' ')}`; -// config.services['kbase-ui'].environment.push(proxy_env); -// config.services['kbase-ui-proxy'].environment.push(proxy_env); -// } -// } - -// function mergeLocalNarrative(root, config, args) { -// if (args.local_narrative) { -// config.services['kbase-ui-proxy'].environment.push('local_narrative=true'); -// } -// } - -// function mergeLocalNavigator(root, config, args) { -// if (args.local_navigator) { -// config.services['kbase-ui-proxy'].environment.push('local_navigator=true'); -// } -// } - -// function mergeLocalTests(root, config) { -// config.services['kbase-ui'].volumes.push({ -// type: 'volume', -// source: 'integration-tests', -// target: '/kb/deployment/services/kbase-ui/test' -// }); -// const integrationTestsHostDirectory = [root, 'dev', 'test'].join('/'); -// config.volumes['integration-tests'] = { -// driver: 'local', -// driver_opts: { -// type: 'none', -// o: 'bind', -// device: integrationTestsHostDirectory -// } -// }; -// } - -interface DockerComposeVolume { - type: string; - source: string; - target: string; -} - -interface DockerComposeConfig { - version: string; - services: { - 'kbase-ui': { - volumes: Array; - environment: Array; - }; - 'kbase-ui-proxy': { - environment: Array; - }; - }; - volumes: { [volumeName: string]: DockerComposeVolume }; -} - -async function main() { - const args = parse(Deno.args); - - if (args._.length !== 1) { - console.log('Usage: docker-compose-override.ts '); - Deno.exit(1); - } - - const [outputDir] = args._; - - // TODO: very strange that deno complains that outputDir is number. - // if (!(await exists(outputDir))) { - // console.log(`Output directory ${outputDir} does not exist`); - // Deno.exit(1); - // } - - // console.log('root: ', typeof root, root, root.length); - let config: DockerComposeConfig = { - version: '3.6', - services: { - 'kbase-ui': { - volumes: [], - environment: [], - }, - 'kbase-ui-proxy': { - environment: [], - }, - }, - volumes: {}, - }; - - // mergePlugins(root, config, args); - - // mergeDynamicServices(root, config, args); - - // mergeServices(root, config, args); - - // mergeLocalNarrative(root, config, args); - - // mergeLocalNavigator(root, config, args); - - if ('config-dir' in args) { - config = await mergeConfigDir(args['config-dir'], config); - } - - const outputPath = [outputDir, 'docker-compose.override.yml'].join('/'); - - const outputContents = new TextEncoder().encode( - stringify(config as unknown as Record) - ); - Deno.writeFile(outputPath, outputContents); -} - -// main(yargs.parse(process.argv.slice(2))); - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/generate-build-info.sh b/tools/deno/scripts/generate-build-info.sh deleted file mode 100644 index e3cc98461..000000000 --- a/tools/deno/scripts/generate-build-info.sh +++ /dev/null @@ -1,34 +0,0 @@ -# -# Set up and invoke the associated deno script. -# - -# The HOST_APP_DIR environment variable roots the deno cli (in the form of -# docker compose) in the host. -# The HOST_APP_DIR is volume mounted as /app in the container. -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="generage-build-info.ts" - -# Arguments for the script -# export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" -# export GIT_TARGET_DIR="/app" -export CONFIG_INSTALL_DEST="/app/build/deploy/build-info.json" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Creating git info" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} ${CONFIG_INSTALL_DEST} diff --git a/tools/deno/scripts/generate-build-info.ts b/tools/deno/scripts/generate-build-info.ts deleted file mode 100644 index 1571794b8..000000000 --- a/tools/deno/scripts/generate-build-info.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ensureDirSync } from "https://deno.land/std@0.125.0/fs/mod.ts"; -import { Git, log } from "./common.ts"; - -async function generateBuildInfo(targetDir: string, installDirectory: string) { - const info = await new Git(targetDir).getInfo(); - - const outputPath = [installDirectory, "build.json"].join("/"); - - const outputContents = new TextEncoder().encode( - JSON.stringify(info as unknown as Record, null, 4), - ); - Deno.writeFile(outputPath, outputContents); -} - -async function main() { - if (Deno.args.length !== 2) { - console.log("Usage: generate-build-info.ts "); - Deno.exit(1); - } - const targetDir = Deno.args[0]; - const destinationDir = Deno.args[1]; - // const here = new URL('', import.meta.url).pathname; - - log( - `Installing build info into ${destinationDir}`, - "generate-build-info.ts:main()", - ); - - ensureDirSync(destinationDir); - - await generateBuildInfo(targetDir, destinationDir); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/git-info.sh b/tools/deno/scripts/git-info.sh deleted file mode 100644 index 93c0d7f6b..000000000 --- a/tools/deno/scripts/git-info.sh +++ /dev/null @@ -1,34 +0,0 @@ -# -# Set up and invoke the associated deno script. -# - -# The HOST_APP_DIR environment variable roots the deno cli (in the form of -# docker compose) in the host. -# The HOST_APP_DIR is volume mounted as /app in the container. -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="git-info.ts" - -# Arguments for the script -# export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" -export GIT_TARGET_DIR="/app" -export GIT_INFO_INSTALL_DEST="/app/build/build/git-info.json" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Creating git info" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} ${GIT_TARGET_DIR} ${GIT_INFO_INSTALL_DEST} diff --git a/tools/deno/scripts/git-info.ts b/tools/deno/scripts/git-info.ts deleted file mode 100644 index 3afc00d61..000000000 --- a/tools/deno/scripts/git-info.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Git, log } from "./common.ts"; - -async function getGitInfo( - dir: string, -) { - const gitInfo = await new Git(dir).getInfo(); - return gitInfo; -} - -async function main() { - if (Deno.args.length !== 2) { - log("Usage: git-info.ts "); - Deno.exit(1); - } - const targetDir = Deno.args[0]; - const destinationFile = Deno.args[1]; - - log(`Getting git info from ${targetDir}`, "git-info.ts:main()"); - log(`Saving git info info to ${destinationFile}`, "git-info.ts:main()"); - - const info = await getGitInfo(targetDir); - log(JSON.stringify(info, null, 4), "git-info.ts:main()"); - - await Deno.writeFile( - destinationFile, - new TextEncoder().encode(JSON.stringify(info, null, 4)), - ); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/hello.ts b/tools/deno/scripts/hello.ts deleted file mode 100644 index 15a0dc971..000000000 --- a/tools/deno/scripts/hello.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Runner } from "./common.ts"; - - -async function main() { - // if (Deno.args.length !== 2) { - // log("Usage: git-info.ts "); - // Deno.exit(1); - // } - // const targetDir = Deno.args[0]; - // const destinationFile = Deno.args[1]; - - // log(`Getting git info from ${targetDir}`, "git-info.ts:main()"); - // log(`Saving git info info to ${destinationFile}`, "git-info.ts:main()"); - - // const info = await getGitInfo(targetDir); - // log(JSON.stringify(info, null, 4), "git-info.ts:main()"); - - // await Deno.writeFile( - // destinationFile, - // new TextEncoder().encode(JSON.stringify(info, null, 4)), - // ); - const runner = new Runner('/app'); - const result = await runner.run('cat', ['Taskfile']); - console.log('RESULT', result); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/info.ts b/tools/deno/scripts/info.ts deleted file mode 100644 index cd9a3a3fd..000000000 --- a/tools/deno/scripts/info.ts +++ /dev/null @@ -1,93 +0,0 @@ -export type ISODateTimeString = string; -export interface GitInfo { - hash: { - full: string, - abbreviated: string - }, - subject: string, - notes: string, - author: { - name: string, - date: ISODateTimeString - }, - committer: { - name: string, - date: ISODateTimeString - }, - originURL: string, - account: string, - repoName: string, - branch: string, - tag?: string, - version?: string -} - -export enum PluginInfoType { - GIT_REPO = 'GIT_REPO', - GITHUB_RELEASE = 'GITHUB_RELEASE' -} - -export interface PluginConfig { - package: { - name: string, - description: string - }, - services: { - route: { - autoload?: boolean; - routes: Array<{ - path: string; - view: string; - authorization?: boolean; - reentrant?: boolean; - }> - } - }, -} - -export interface PluginUIConfig { - name: string; - globalName: string; - version: string; - source: { - github: { - account: string; - release?: boolean; - }; - }; -} - -export interface UIPluginsConfig { - plugins: Array; -} - - -export interface PluginInfoBase { - type: PluginInfoType, - install: { - directory: string - }, - configs: { - plugin: PluginConfig, - ui: PluginUIConfig - }, -} - -export interface PluginInfoRepo extends PluginInfoBase { - type: PluginInfoType.GIT_REPO, - git: GitInfo -} - -export interface PluginInfoRelease extends PluginInfoBase { - type: PluginInfoType.GITHUB_RELEASE -} - -export type PluginInfo = - PluginInfoRepo | - PluginInfoRelease; - -export type PluginsInfo = Array; - -export interface BuildInfo { - builtAt: number -} diff --git a/tools/deno/scripts/install-plugin.sh b/tools/deno/scripts/install-plugin.sh deleted file mode 100644 index c08e85112..000000000 --- a/tools/deno/scripts/install-plugin.sh +++ /dev/null @@ -1,40 +0,0 @@ -# -# Set up and invoke the associated deno script. -# - -# The HOST_APP_DIR environment variable roots the deno cli (in the form of -# docker compose) in the host. -# The HOST_APP_DIR is volume mounted as /app in the container. -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="install-plugin.ts" - -# Arguments for the script -export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" -export PLUGINS_INSTALL_DEST="/app/build" - -export PLUGINS_FILTER="${2}" - -echo "Installing plugins with filter ${PLUGINS_FILTER}" - -export GH_TOKEN="${GH_TOKEN:?GH_TOKEN not set}" -echo "GH_TOKEN is set" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Installing plugins" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read --allow-net \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} ${PLUGINS_CONFIG_PATH} ${PLUGINS_INSTALL_DEST} ${GH_TOKEN} ${1} diff --git a/tools/deno/scripts/install-plugin.ts b/tools/deno/scripts/install-plugin.ts deleted file mode 100644 index 088d59e2c..000000000 --- a/tools/deno/scripts/install-plugin.ts +++ /dev/null @@ -1,352 +0,0 @@ -import * as fflate from 'https://cdn.skypack.dev/fflate?min'; -import { Untar } from 'https://deno.land/std@0.192.0/archive/untar.ts'; -import { parse } from 'https://esm.sh/yaml@2.3.1'; - -import { ensureDir, ensureDirSync, ensureFile } from 'https://deno.land/std@0.192.0/fs/mod.ts'; -import { Buffer } from 'https://deno.land/std@0.192.0/io/buffer.ts'; -import { copyN } from 'https://deno.land/std@0.192.0/io/copy_n.ts'; -import { readerFromStreamReader } from 'https://deno.land/std@0.192.0/streams/mod.ts'; -import { Git, log } from './common.ts'; -import { PluginConfig, PluginInfo, PluginInfoRepo, PluginInfoType, PluginUIConfig } from './info.ts'; - -const BUF_SIZE = 1000000; // 1MB buffer - -interface PluginsConfig { - plugins: Array; -} - -// TODO: clone with depth 1 -function fetchRepo(account: string, name: string, version: string, dest: string) { - return new Git(`${dest}`).clone( - `https://github.com/${account}/kbase-ui-plugin-${name}`, - name, - version - ); -} - -async function fetchPlugins(config: string, dest: string) { - const pluginsRaw = await Deno.readTextFile(config); - const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - for (const pluginConfig of pluginsConfig.plugins) { - if (pluginConfig.source.github.release === true) { - continue; - } - log( - `Fetching ${pluginConfig.source.github.account}/${pluginConfig.name}...`, - 'fetchPlugins' - ); - const branch = `v${pluginConfig.version}`; - try { - const result = await fetchRepo( - pluginConfig.source.github.account, - pluginConfig.name, - branch, - dest - ); - console.log(`fetch result: ${result}`); - } catch (ex) { - console.error('error fetching repo', ex.message, ex); - throw new Error(`Error fetching repo ${pluginConfig.name}: ${ex.message}`); - } - log('...done'); - } -} - -async function getPluginUIConfig(config: string, pluginName: string) { - const pluginsRaw = await Deno.readTextFile(config); - const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - const [pluginConfig] = pluginsConfig.plugins.filter((config) => { - return (config.name === pluginName); - }); - - if (!pluginConfig) { - throw new Error(`Plugin ${pluginName} not available`); - } - - return pluginConfig; -} - - -async function getPluginConfig(dest: string) { - const pluginInstallDir = `${dest}`; - // const pluginSourceDir = `${source}/${uiPluginConfig.name}`; - const configFileName = `${pluginInstallDir}/config.yml`; - let pluginConfigRaw; - try { - const raw = Deno.readFileSync(configFileName); - pluginConfigRaw = new TextDecoder().decode(raw); - } catch (ex) { - console.error('ERROR reading config file', configFileName); - } - return parse(pluginConfigRaw) as PluginConfig; -} - -async function fetchPluginReleaseDist(pluginConfig: PluginUIConfig, dest: string, ghToken: string) { - if (pluginConfig.source.github.release !== true) { - throw new Error('Not a "release" plugin'); - } - - log( - `Fetching ${pluginConfig.source.github.account}/${pluginConfig.name} ...`, - 'fetchPluginsReleaseDist' - ); - const tag = `v${pluginConfig.version}`; - try { - const result = await fetchReleaseDist( - pluginConfig.source.github.account, - pluginConfig.name, - dest, - tag, - ghToken - ); - log('...done'); - return result; - } catch (ex) { - console.log('error', ex); - throw new Error(`Error fetching plugin ${pluginConfig.name}: ${ex.message}`); - } - - -} - -async function fetchReleaseDist(gitAccount: string, pluginName: string, dest: string, tag: string, ghToken: string) { - const releaseURL = `https://api.github.com/repos/${gitAccount}/kbase-ui-plugin-${pluginName}/releases/tags/${tag}` - // TODO: github token - const headers = { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${ghToken}` - } - console.log('AUTH', ghToken); - const response = await fetch(releaseURL, { headers }); - - if (response.status !== 200) { - throw new Error(`[fetchReleaseDist] error response ${response.status}: ${response.statusText}`); - } - - const release = (await response.json()) as { assets: Array<{ name: string, url: string }> } - - if (!release) { - throw new Error(`[fetchReleaseDist] release returned is empty: ${response.status}, ${response.statusText}`) - } - - if (!release.assets) { - throw new Error(`[fetchReleaseDist] assets returned is empty: ${response.status}, ${response.statusText}`) - } - - const { url } = release.assets.filter(({ name }) => { - return name === 'dist.tgz'; - })[0]; - - log( - `fetch release dist url: ${url}`, - 'fetchReleaseDist' - ); - - const response2 = await fetch(url, { - headers: { - Accept: 'application/octet-stream' - } - }); - - log( - `fetch release dist response: ${response2.status}, ${response2.statusText}`, - 'fetchReleaseDist' - ); - - const rdr = response2.body?.getReader(); - if (rdr) { - await Deno.mkdir(`${dest}`, { recursive: true }) - const r = readerFromStreamReader(rdr); - const f = await Deno.open(`${dest}/dist.tgz`, { create: true, write: true }); - - let nread = null; - do { - nread = await copyN(r, f, BUF_SIZE); - } while (nread === BUF_SIZE) - f.close(); - } -} - -async function deleteDirectory(dir: string) { - try { - await Deno.remove(dir, { recursive: true }); - } catch (ex) { - if (ex instanceof Deno.errors.NotFound) { - return; - } - throw ex; - } -} - -async function unpackPlugin(source: string, dest: string) { - // This is where plugin was built into before archiving. - const pluginPathPrefix = 'dist/plugin'; - const installationPackage = `${source}/dist.tgz`; - log(`Unzipping installation package "${installationPackage}`); - const archive = await Deno.readFile(installationPackage); - const uncompressed = fflate.gunzipSync(archive); - const reader = new Buffer(uncompressed); - const untar = new Untar(reader); - log(` tar package: ${installationPackage}, size: ${archive.byteLength}`, 'unpackPlugins'); - for await (const entry of untar) { - // Handle directory entry - if (!entry.fileName.startsWith(pluginPathPrefix)) { - continue; - } - const adjustedName = entry.fileName.substring(pluginPathPrefix.length); - const destFileOrDir = `${dest}/${adjustedName}`; - if (entry.type === 'directory') { - await ensureDir(destFileOrDir); - continue; - } - // Handle file entry. - await ensureFile(destFileOrDir); - - const outputFile = await Deno.open(destFileOrDir, { write: true }); - - let nread = null; - do { - nread = await copyN(entry, outputFile, BUF_SIZE); - } while (nread === BUF_SIZE) - - } -} - -async function getYAML(path: string) { - const pluginsRaw = await Deno.readTextFile(path); - return parse(pluginsRaw); -} - -async function getJSON(path: string) { - const pluginsRaw = await Deno.readTextFile(path); - return JSON.parse(pluginsRaw); -} - -export enum PluginType { - GIT_REPO -} - - -async function updatePluginManifest( - pluginUIConfig: PluginUIConfig, - pluginConfig: PluginConfig, - source: string, - installDest: string -) { - // const dest = `${installDest}/${pluginUIConfig.name}`; - const manifestFileName = `${installDest}/plugin-manifest.json`; - - // const pluginsConfig = (await getYAML(uiConfig)) as unknown as UIPluginsConfig; - - const manifest = (await getJSON(manifestFileName) as unknown as Array); - - // const pluginsRaw = await Deno.readTextFile(uiConfig); - // const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - - log(`writing to manifest file ${manifestFileName}...`, 'generatePluginsManifest'); - - const pluginSourceDir = `${source}/${pluginUIConfig.name}`; - - if (pluginUIConfig.source.github.release === true) { - manifest.push({ - type: PluginInfoType.GITHUB_RELEASE, - install: { - directory: pluginSourceDir, - }, - configs: { - plugin: pluginConfig, - ui: pluginUIConfig, - }, - }); - } else { - // Need to get git info from the source. - log(`Getting git info from ${pluginSourceDir}`, 'generatePluginsManifest'); - const gitInfo = await new Git(pluginSourceDir).getInfo(); - manifest - .filter((entry) => { - return (entry.configs.ui.name !== pluginUIConfig.name); - }) - .push({ - type: PluginInfoType.GIT_REPO, - install: { - directory: pluginSourceDir, - }, - configs: { - plugin: pluginConfig, - ui: pluginUIConfig, - }, - git: gitInfo, - } as PluginInfoRepo); - } - // } - await Deno.writeFile( - manifestFileName, - new TextEncoder().encode(JSON.stringify(manifest, null, 4)) - ); - log('done!', 'updatePluginManifest'); -} - -// async function savePluginManifest(path) { -// const root = state.environment.path; -// const configDest = root.concat(['build', 'client', 'modules', 'config']); -// const manifestPath = configDest.concat(['plugins-manifest.json']); -// await mutant.saveJson(manifestPath, state.pluginsManifest); -// return state; -// } - -async function main() { - if (Deno.args.length < 4) { - log(`Incorrect number of args ${Deno.args.length}`) - log('Usage: install-plugins.ts '); - Deno.exit(1); - } - const config = Deno.args[0]; - const destinationDir = Deno.args[1]; - const ghToken = Deno.args[2]; - const pluginName = Deno.args[3]; - - log(`Parameters`, 'main'); - log(`config: ${config}`, 'main'); - log(`dest: ${destinationDir}`, 'main'); - log(`gh token: ${ghToken}`, 'main'); - log(`plugin: ${pluginName}`, 'main'); - - - const downloadDest = `${destinationDir}/download/${pluginName}`; - const installDest = `${destinationDir}/plugins`; - const pluginInstallDest = `${installDest}/${pluginName}` - - - // const here = new URL('', import.meta.url).pathname; - - // TODO: CHeck that plugin is defined. - const pluginUIConfig = await getPluginUIConfig(config, pluginName); - - console.log('GOT IT', pluginUIConfig); - - - log(`Downloading into ${downloadDest}`, 'main'); - log(`Installing into ${installDest}`, 'main'); - - // Ensure that any previously installed plugin is removed. - await deleteDirectory(downloadDest); - await deleteDirectory(pluginInstallDest); - - - ensureDirSync(downloadDest); - ensureDirSync(pluginInstallDest); - - - // await fetchPlugins(config, downloadDest); - await fetchPluginReleaseDist(pluginUIConfig, downloadDest, ghToken); - await unpackPlugin(downloadDest, pluginInstallDest); - - const pluginConfig = await getPluginConfig(pluginInstallDest); - - await updatePluginManifest(pluginUIConfig, pluginConfig, downloadDest, installDest); - await deleteDirectory(downloadDest); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/scripts/install-plugins.md b/tools/deno/scripts/install-plugins.md deleted file mode 100644 index cf17178e0..000000000 --- a/tools/deno/scripts/install-plugins.md +++ /dev/null @@ -1,76 +0,0 @@ -# install-plugins - -This is a Deno script which will fetch, unpack, and install into the build, all -specified kbase-ui plugins. - -It should be run through the Deno cli located in `tools/deno-cli`. - -E.g. - -```bash -GH_TOKEN=TTT HOST_APP_DIR=`PWD` docker compose run --rm deno run --unstable --allow-run --allow-write --allow-read /app/scripts/deno/install-plugins.ts /app/config/plugins.yml /app/build/app/modules/plugins -``` - -A rather long command line. Let's break it down! - -1. We first provided an environment variable for the Docker Compose file. The - `HOST_APP_DIR` variable is used to set a directory mapped to the container's - internal `/app` directory. We set it to the repo top level directory. `pwd` - returns the absolute path to the current directory, and since we need to run - this script from the `tools/deno-cli` directory (a constraint of docker - compose), we indicate two directories above. - - The volume mounting requires absolute directories. - - ```bash - DIR=`pwd`/../.. - ``` - -2. Next we run the Docker container using docker compose, specifying the `deno` - service defined in the docker compose file. - - The name of the service within the docker compose file can be anything, but - we've chosen `deno`, well, because it just makes sense. - - We use the `--rm` Docker Compose option in order to ensure the container is - removed when it completes. - - ```bash - docker compose run --rm deno - ``` - -3. Next we issue the Deno `run` command with a bunch of command line options. It - is important to know that within the container, the "entrypoint" is already - set up to run deno and expects that the Deno command ("run" in this case) and - all command line options to follow. - - ```bash - run --unstable --allow-run --allow-write --allow-read - ``` - -4. Finally, we provide the actual Deno script to run, followed by all of it's - command line arguments. In this case, the first argument is the plugins - config file, and the second is the directory into which to install the - plugins. - - Note that all files and directories are specified as absolute paths within - the container (remember that `/app` has been volume mounted to the entire - repo). - - The script `/app/scripts/deno/install-plugins.ts` resides in the home of all - deno scripts `/app/scripts/deno`. - - The `/app/config/plugins.yml` file lists all of the plugins, their locations, - and their versions. - - The `/app/build/app/modules` specifies in which directory the plugins - directory will be installed. - - ```bash - /app/scripts/deno/install-plugins.ts /app/config/plugins.yml /app/build/app/modules - ``` - ---- - -deno run --allow-run --allow-write --allow-read install-plugins.ts -${PWD}/../../../config/plugins.yml ${PWD}/temp diff --git a/tools/deno/scripts/install-plugins.sh b/tools/deno/scripts/install-plugins.sh deleted file mode 100644 index 2562d5c98..000000000 --- a/tools/deno/scripts/install-plugins.sh +++ /dev/null @@ -1,39 +0,0 @@ -# -# Set up and invoke the associated deno script. -# - -# The HOST_APP_DIR environment variable roots the deno cli (in the form of -# docker compose) in the host. -# The HOST_APP_DIR is volume mounted as /app in the container. -export HOST_APP_DIR=${PWD} - -# Should stay the same for all scripts -export DENO_SCRIPT_HOME="/app/tools/deno/scripts" - -# The script we are running -export DENO_SCRIPT="install-plugins.ts" - -# Arguments for the script -export PLUGINS_CONFIG_PATH="/app/config/plugins.yml" -export PLUGINS_INSTALL_DEST="/app/build" - -export PLUGINS_FILTER="${1}" -export GH_TOKEN="${GH_TOKEN:?GH_TOKEN not set}" - -echo "Installing plugins with filter ${PLUGINS_FILTER}" -echo "GH_TOKEN is set" - -# assume we are run from the root of the project. -cd tools/deno - -echo -echo "Installing plugins" -echo "HOST_APP_DIR=$HOST_APP_DIR" -echo -docker compose \ - -f cli/docker-compose.yml \ - run \ - --rm \ - deno run \ - --unstable --allow-run --allow-write --allow-read --allow-net \ - ${DENO_SCRIPT_HOME}/${DENO_SCRIPT} ${PLUGINS_CONFIG_PATH} ${PLUGINS_INSTALL_DEST} ${GH_TOKEN} diff --git a/tools/deno/scripts/install-plugins.ts b/tools/deno/scripts/install-plugins.ts deleted file mode 100644 index 6242102b1..000000000 --- a/tools/deno/scripts/install-plugins.ts +++ /dev/null @@ -1,352 +0,0 @@ -import * as fflate from 'https://cdn.skypack.dev/fflate?min'; -import { Untar } from 'https://deno.land/std@0.192.0/archive/untar.ts'; -import { parse } from 'https://esm.sh/yaml@2.3.1'; - -import { ensureDir, ensureDirSync, ensureFile } from 'https://deno.land/std@0.192.0/fs/mod.ts'; -import { Buffer } from 'https://deno.land/std@0.192.0/io/buffer.ts'; -import { copyN } from 'https://deno.land/std@0.192.0/io/copy_n.ts'; - -import { copy } from 'https://deno.land/std@0.192.0/fs/copy.ts'; -import { readerFromStreamReader } from 'https://deno.land/std@0.192.0/streams/mod.ts'; -import { Git, log } from './common.ts'; -import { PluginConfig, PluginInfoRelease, PluginInfoRepo, PluginInfoType, PluginUIConfig, PluginsInfo, UIPluginsConfig } from './info.ts'; - -const BUF_SIZE = 1000000; // 1MB buffer - -interface PluginsConfig { - plugins: Array; -} - -// TODO: clone with depth 1 -function fetchRepo(account: string, name: string, version: string, dest: string) { - return new Git(`${dest}`).clone( - `https://github.com/${account}/kbase-ui-plugin-${name}`, - name, - version - ); -} - -const exists = async (filename: string): Promise => { - try { - await Deno.stat(filename); - // successful, file or directory must exist - return true; - } catch (error) { - if (error instanceof Deno.errors.NotFound) { - // file or directory does not exist - return false; - } else { - // unexpected error, maybe permissions, pass it along - throw error; - } - } -}; - - -async function fetchPlugins(config: string, downloadDest: string, installDest: string, cacheDir: string) { - log('Fetching legacy plugins...', 'fetchPlugins'); - const pluginsRaw = await Deno.readTextFile(config); - const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - for (const pluginConfig of pluginsConfig.plugins) { - if (pluginConfig.source.github.release === true) { - continue; - } - log( - `Considering plugin "${pluginConfig.source.github.account}/${pluginConfig.name}" ...`, - 'fetchPluginsReleaseDist' - ); - - const cacheSource = `${cacheDir}/${pluginConfig.name}` - if (await exists(cacheSource)) { - log('Found in cache, copying...', 'fetchPlugins'); - await copy(cacheSource, `${installDest}/${pluginConfig.name}`) - continue - } else { - log('Not found in cache', 'fetchPlugins'); - } - - - log( - `Fetching ${pluginConfig.source.github.account}/${pluginConfig.name}...`, - 'fetchPlugins' - ); - const branch = `v${pluginConfig.version}`; - try { - const result = await fetchRepo( - pluginConfig.source.github.account, - pluginConfig.name, - branch, - downloadDest - ); - console.log(`fetch result: ${result}`); - } catch (ex) { - console.error('error fetching repo', ex.message, ex); - throw new Error(`Error fetching repo ${pluginConfig.name}: ${ex.message}`); - } - log('...done'); - } -} - -async function fetchPluginsReleaseDist(config: string, downloadDest: string, installDest: string, cacheDir: string, ghToken: string) { - log('Fetching release dist plugins...', 'fetchPluginsReleaseDist'); - const pluginsRaw = await Deno.readTextFile(config); - const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - for (const pluginConfig of pluginsConfig.plugins) { - if (pluginConfig.source.github.release !== true) { - continue; - } - - log( - `Considering plugin "${pluginConfig.source.github.account}/${pluginConfig.name}" ...`, - 'fetchPluginsReleaseDist' - ); - - const cacheSource = `${cacheDir}/${pluginConfig.name}` - if (await exists(cacheSource)) { - log('Found in cache, copying...', 'fetchPlugins'); - await copy(cacheSource, `${installDest}/${pluginConfig.name}`) - continue; - } else { - log('Not found in cache', 'fetchPlugins'); - } - - log( - `Fetching ${pluginConfig.source.github.account}/${pluginConfig.name} ...`, - 'fetchPluginsReleaseDist' - ); - const tag = `v${pluginConfig.version}`; - try { - const result = await fetchReleaseDist( - pluginConfig.source.github.account, - pluginConfig.name, - downloadDest, - tag, - ghToken - ); - } catch (ex) { - console.log('error', ex); - throw new Error(`Error fetching plugin ${pluginConfig.name}: ${ex.message}`); - } - log('...done'); - } -} - -async function fetchReleaseDist(gitAccount: string, pluginName: string, dest: string, tag: string, ghToken: string) { - const releaseURL = `https://api.github.com/repos/${gitAccount}/kbase-ui-plugin-${pluginName}/releases/tags/${tag}` - // TODO: github token - const headers = { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${ghToken}` - } - console.log('AUTH', ghToken); - const response = await fetch(releaseURL, { headers }); - - if (response.status !== 200) { - throw new Error(`[fetchReleaseDist] error response ${response.status}: ${response.statusText}`); - } - - const release = (await response.json()) as { assets: Array<{ name: string, url: string }> } - - if (!release) { - throw new Error(`[fetchReleaseDist] release returned is empty: ${response.status}, ${response.statusText}`) - } - - if (!release.assets) { - throw new Error(`[fetchReleaseDist] assets returned is empty: ${response.status}, ${response.statusText}`) - } - - const { url } = release.assets.filter(({ name }) => { - return name === 'dist.tgz'; - })[0]; - - log( - `fetch release dist url: ${url}`, - 'fetchReleaseDist' - ); - - const response2 = await fetch(url, { - headers: { - Accept: 'application/octet-stream' - } - }); - - log( - `fetch release dist response: ${response2.status}, ${response2.statusText}`, - 'fetchReleaseDist' - ); - - const rdr = response2.body?.getReader(); - if (rdr) { - await Deno.mkdir(`${dest}/${pluginName}`, { recursive: true }) - const r = readerFromStreamReader(rdr); - log('Opening...', 'fetchReleaseDist'); - const f = await Deno.open(`${dest}/${pluginName}/dist.tgz`, { create: true, write: true }); - log('Copying...', 'fetchReleaseDist'); - - let nread = null; - do { - nread = await copyN(r, f, BUF_SIZE); - } while (nread === BUF_SIZE) - log('Done...', 'fetchReleaseDist'); - f.close(); - } -} - -async function deleteDirectory(dir: string) { - try { - await Deno.remove(dir, { recursive: true }); - } catch (ex) { - if (ex instanceof Deno.errors.NotFound) { - return; - } - throw ex; - } -} - -async function unpackPlugins(source: string, dest: string) { - // This is where plugin was built into before archiving. - const pluginPathPrefix = 'dist/plugin'; - for await (const dirEntry of Deno.readDir(source)) { - const installationPackage = `${source}/${dirEntry.name}/dist.tgz`; - log(`Unzipping installation package "${installationPackage}`); - const archive = await Deno.readFile(installationPackage); - const uncompressed = fflate.gunzipSync(archive); - const reader = new Buffer(uncompressed); - const untar = new Untar(reader); - log(` tar package: ${installationPackage}, size: ${archive.byteLength}`, 'unpackPlugins'); - for await (const entry of untar) { - // Handle directory entry - if (!entry.fileName.startsWith(pluginPathPrefix)) { - continue; - } - const adjustedName = entry.fileName.substring(pluginPathPrefix.length); - const destFileOrDir = `${dest}/${dirEntry.name}/${adjustedName}`; - if (entry.type === 'directory') { - await ensureDir(destFileOrDir); - continue; - } - // Handle file entry. - await ensureFile(destFileOrDir); - - const outputFile = await Deno.open(destFileOrDir, { write: true }); - - let nread = null; - do { - nread = await copyN(entry, outputFile, BUF_SIZE); - } while (nread === BUF_SIZE) - - } - } -} - -async function getYAML(path: string) { - const pluginsRaw = await Deno.readTextFile(path); - return parse(pluginsRaw); -} - -export enum PluginType { - GIT_REPO -} - -async function generatePluginsManifest(uiConfig: string, source: string, dest: string) { - const manifestFileName = `${dest}/plugin-manifest.json`; - - const pluginsConfig = (await getYAML(uiConfig)) as unknown as UIPluginsConfig; - - // const pluginsRaw = await Deno.readTextFile(uiConfig); - // const pluginsConfig = parse(pluginsRaw) as unknown as PluginsConfig; - - log(`writing to manifest file ${manifestFileName}...`, 'generatePluginsManifest'); - const manifest: PluginsInfo = []; - for await (const uiPluginConfig of pluginsConfig.plugins) { - // Config is in the dest (also the source) - const pluginInstallDir = `${dest}/${uiPluginConfig.name}`; - const pluginSourceDir = `${source}/${uiPluginConfig.name}`; - const configFileName = `${pluginInstallDir}/config.yml`; - let pluginConfigRaw; - try { - const raw = Deno.readFileSync(configFileName); - pluginConfigRaw = new TextDecoder().decode(raw); - } catch (ex) { - console.error('ERROR reading config file', configFileName); - } - const pluginConfig = parse(pluginConfigRaw) as PluginConfig; - - if (uiPluginConfig.source.github.release === true) { - manifest.push({ - type: PluginInfoType.GITHUB_RELEASE, - install: { - directory: pluginSourceDir, - }, - configs: { - plugin: pluginConfig, - ui: uiPluginConfig, - }, - } as PluginInfoRelease); - } else { - // Need to get git info from the source. - log(`Getting git info from ${pluginSourceDir}`, 'generatePluginsManifest'); - const gitInfo = await new Git(pluginSourceDir).getInfo(); - manifest.push({ - type: PluginInfoType.GIT_REPO, - install: { - directory: pluginSourceDir, - }, - configs: { - plugin: pluginConfig, - ui: uiPluginConfig, - }, - git: gitInfo, - } as PluginInfoRepo); - } - } - await Deno.writeFile( - manifestFileName, - new TextEncoder().encode(JSON.stringify(manifest, null, 4)) - ); - log('done!', 'generatePluginsManifest'); -} - -// async function savePluginManifest(path) { -// const root = state.environment.path; -// const configDest = root.concat(['build', 'client', 'modules', 'config']); -// const manifestPath = configDest.concat(['plugins-manifest.json']); -// await mutant.saveJson(manifestPath, state.pluginsManifest); -// return state; -// } - -async function main() { - if (Deno.args.length < 3) { - log(`Incorrect number of args ${Deno.args.length}`) - log('Usage: install-plugins.ts '); - Deno.exit(1); - } - const config = Deno.args[0]; - const destinationDir = Deno.args[1]; - const ghToken = Deno.args[2]; - - const cacheDir = `${destinationDir}/cache/plugins`; - const downloadDest = `${destinationDir}/download`; - const installDest = `${destinationDir}/plugins`; - - log(`Downloading into ${downloadDest}`, 'main'); - log(`Installing into ${installDest}`, 'main'); - - await deleteDirectory(downloadDest); - await deleteDirectory(installDest); - - ensureDirSync(downloadDest); - ensureDirSync(installDest); - - - await fetchPlugins(config, downloadDest, installDest, cacheDir); - await fetchPluginsReleaseDist(config, downloadDest, installDest, cacheDir, ghToken); - - await unpackPlugins(downloadDest, installDest); - await generatePluginsManifest(config, downloadDest, installDest); - await deleteDirectory(downloadDest); -} - -if (import.meta.main) { - main(); -} diff --git a/tools/deno/x.json b/tools/deno/x.json deleted file mode 100644 index 3f2576321..000000000 --- a/tools/deno/x.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "hash": { - "full": "965dcd668189321bd368703f402256ff409dfa7a", - "abbreviated": "965dcd66" - }, - "author": { "name": "Erik Pearson", "date": "2022-01-05T22:54:15.000Z" }, - "committer": { "name": "Erik Pearson", "date": "2022-01-05T22:54:15.000Z" }, - "originURL": "ssh://git@github.com/kbase/kbase-ui", - "branch": "feature-crats-refactor", - "tag": "" -} diff --git a/tools/dockerize/docker-compose.yml b/tools/dockerize/docker-compose.yml index 2f064c0b0..aa95eb8cb 100644 --- a/tools/dockerize/docker-compose.yml +++ b/tools/dockerize/docker-compose.yml @@ -1,15 +1,11 @@ -version: '3.6' services: dockerize: working_dir: /app image: powerman/dockerize container_name: dockerize dns: 8.8.8.8 - environment: - - DEFAULT_PATH - - HIDE_HEADER - - HIDE_NAVIGATION - - INTEGRATED_HAMBURGER_AND_LOGO - - deploy_name + env_file: + - $ENV_FILE + # - ../../dev/templates-context.env volumes: - $DIR:/app \ No newline at end of file diff --git a/tools/dockerize/scripts/render-proxy-configs.sh b/tools/dockerize/scripts/render-proxy-configs.sh new file mode 100755 index 000000000..7244a463a --- /dev/null +++ b/tools/dockerize/scripts/render-proxy-configs.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# source "${DIR}/scripts/host/create-dev-proxy-env-vars.bash" +source "${DIR}/.devcontainer/proxy.env" + +set -e +echo "Render development proxy config files" +echo "Parameters (Environment Variables):" +echo "" +echo "KBASE_DOMAIN = ${KBASE_DOMAIN}" +echo "KBASE_UI_HOSTNAME = ${KBASE_UI_HOSTNAME}" +echo "" + + + +# Generate the deployment configs that are normally generated by the entrypoint in the +# Dockerfile. Note that for development we don't actually use nginx.conf, but we +# generate it here so we can inspect it. + # --env-file ${DIR}/.devcontainer/proxy.env \ +docker compose \ + -f ${DIR}/tools/dockerize/docker-compose.yml \ + run \ + --rm \ + dockerize \ + -template /app/tools/proxy/contents/conf/nginx.conf.tmpl:/app/build/deploy/proxy-nginx.conf + diff --git a/tools/dockerize/scripts/render-templates.sh b/tools/dockerize/scripts/render-templates.sh old mode 100644 new mode 100755 index eba413e55..f10490b44 --- a/tools/dockerize/scripts/render-templates.sh +++ b/tools/dockerize/scripts/render-templates.sh @@ -1,17 +1,48 @@ -set -e -echo "Rendering kbase-ui config file from template for environment '${ENV}' using base app dir '${DIR}'" -echo "Parameters (Environment Variables):" -echo " ENV=${ENV}" -echo " DIR=${DIR}" -echo " DEFAULT_PATH=${DEFAULT_PATH}" -echo " HIDE_HEADER=${HIDE_HEADER}" -echo " HIDE_NAVIGATION=${HIDE_NAVIGATION}" -echo " INTEGRATED_HAMBURGER_AND_LOGO=${INTEGRATED_HAMBURGER_AND_LOGO}" -echo "" +#!/usr/bin/env bash + +# source "${DIR}/scripts/host/development-env-vars.bash" + +# set -e +# echo "Rendering kbase-ui config file from template for environment '${DEPLOY_ENV}' using base app dir '${DIR}'" +# echo "Parameters (Environment Variables):" +# echo "" +# echo "Just for development" +# echo "--------------------" +# echo " DIR=${DIR}" +# echo "" +# echo "Required" +# echo "--------" +# echo "" +# echo "URL Bases" +# echo " UI_DOMAIN=${UI_DOMAIN}" +# echo "" +# echo "Feature Switches" +# echo " FEATURE_SWITCHES_ENABLED=${FEATURE_SWITCHES_ENABLED}" +# echo " FEATURE_SWITCHES_DISABLED=${FEATURE_SWITCHES_DISABLED}" +# echo "" + +if [ -z "$DIR" ] +then + echo "The environment variable 'DIR' must be set first" + exit 1 +fi + +export ENV_FILE="${DIR}/.devcontainer/runtime.env" + +if [ ! -f "$ENV_FILE" ] +then + echo "The env file '${ENV_FILE}' must be generated first" + exit 1 +fi + + +# Generate the deployment configs that are normally generated by the entrypoint in the +# Dockerfile. Note that for development we don't actually use nginx.conf, but we +# generate it here so we can inspect it. docker compose \ -f ${DIR}/tools/dockerize/docker-compose.yml \ run \ --rm \ dockerize \ -template /app/deployment/templates/config.json.tmpl:/app/build/deploy/config.json \ - -env /app/dev/gitlab-config/${ENV}_config.ini + -template /app/deployment/templates/nginx.conf.tmpl:/app/build/deploy/nginx.conf diff --git a/tools/make-dev-cert.sh b/tools/make-dev-cert.sh index cb5d03e9a..e7a0c52f2 100644 --- a/tools/make-dev-cert.sh +++ b/tools/make-dev-cert.sh @@ -1,4 +1,4 @@ cd temp -mkcert -cert-file test.crt --key-file test.key kbase.us "*.kbase.us" +mkcert -cert-file test.crt --key-file test.key kbase.us "*.kbase.us" "*.ci.kbase.us" "*.next.kbase.us" "*.appdev.kbase.us" "*.narrative2.kbase.us" "*.narrative.kbase.us" "*.narrative-dev.kbase.us" "*.ci-europa.kbase.us" mv test.* ../tools/proxy/contents/ssl \ No newline at end of file diff --git a/tools/node/Dockerfile b/tools/node/Dockerfile index ad67de5e8..7adf2861a 100644 --- a/tools/node/Dockerfile +++ b/tools/node/Dockerfile @@ -1,5 +1,5 @@ -FROM node:18-slim +FROM node:20-slim RUN apt-get update && \ apt-get install -y npm python3 git make bash && \ - npm install --location=global npm@10.2.0 + npm install --location=global npm@10.5.2 diff --git a/tools/node/docker-compose.yml b/tools/node/docker-compose.yml index 9a8023a10..5ff79d67b 100644 --- a/tools/node/docker-compose.yml +++ b/tools/node/docker-compose.yml @@ -1,11 +1,16 @@ -version: '3.6' +name: kbase-dev +networks: + kbase-dev: + name: kbase-dev services: - node: + node-tool: working_dir: /app build: context: . dockerfile: Dockerfile container_name: node-builder dns: 8.8.8.8 + networks: + - kbase-dev volumes: - $DIR:/app \ No newline at end of file diff --git a/tools/node/run b/tools/node/run new file mode 100755 index 000000000..5b5c48a2a --- /dev/null +++ b/tools/node/run @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +DIR="${PWD}" docker compose -f tools/node/docker-compose.yml run --rm node-tool "$@" \ No newline at end of file diff --git a/tools/proxy/Dockerfile b/tools/proxy/Dockerfile index 35086c347..eff6952e7 100644 --- a/tools/proxy/Dockerfile +++ b/tools/proxy/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.18.4 +FROM alpine:3.19.1 # Container designed to serve up static KBase UI contents # These ARGs values are passed in via the docker build command diff --git a/tools/proxy/README.md b/tools/proxy/README.md index 8c88a3e30..f41780070 100644 --- a/tools/proxy/README.md +++ b/tools/proxy/README.md @@ -23,4 +23,7 @@ optional: local_navigator local_narrative service_proxies -dynamic_service_proxies \ No newline at end of file +dynamic_service_proxies + +> NOTE: the standalone docker-compose.yml has not been used for a while; just the +> devcontainer one. It will need some work to ... work. \ No newline at end of file diff --git a/tools/proxy/conf/README.md b/tools/proxy/conf/README.md deleted file mode 100644 index eb1951928..000000000 --- a/tools/proxy/conf/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Configuration files - -Configuration files for the Proxy development image. - - - diff --git a/tools/proxy/conf/appdev.env b/tools/proxy/conf/appdev.env deleted file mode 100644 index 2432bb966..000000000 --- a/tools/proxy/conf/appdev.env +++ /dev/null @@ -1,16 +0,0 @@ -# Proxy Container - -deploy_hostname=appdev.kbase.us - -# disabled -#deploy_ui_hostname= - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ diff --git a/tools/proxy/conf/ci.env b/tools/proxy/conf/ci.env deleted file mode 100644 index e78792bf4..000000000 --- a/tools/proxy/conf/ci.env +++ /dev/null @@ -1,16 +0,0 @@ -# Proxy Container - -deploy_hostname=ci.kbase.us - -# disabled -#deploy_ui_hostname= - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ diff --git a/tools/proxy/conf/dev.env b/tools/proxy/conf/dev.env deleted file mode 100644 index 764f7d2f0..000000000 --- a/tools/proxy/conf/dev.env +++ /dev/null @@ -1,16 +0,0 @@ -# Proxy Container - -deploy_hostname=ci.kbase.us - -# disabled -#deploy_ui_hostname= - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=false - -base_path=/ diff --git a/tools/proxy/conf/narrative-dev.env b/tools/proxy/conf/narrative-dev.env deleted file mode 100644 index 1e87cffe0..000000000 --- a/tools/proxy/conf/narrative-dev.env +++ /dev/null @@ -1,16 +0,0 @@ -# Proxy Container -deploy_hostname=narrative-dev.kbase.us - -# disabled -# deploy_ui_hostname=narrative-dev.kbase.us - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ - diff --git a/tools/proxy/conf/narrative2.env b/tools/proxy/conf/narrative2.env deleted file mode 100644 index 3671fbc31..000000000 --- a/tools/proxy/conf/narrative2.env +++ /dev/null @@ -1,16 +0,0 @@ -# Proxy Container -deploy_hostname=narrative2.kbase.us - -# disabled -# deploy_ui_hostname=narrative-dev.kbase.us - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ - diff --git a/tools/proxy/conf/next.env b/tools/proxy/conf/next.env deleted file mode 100644 index 1116431ff..000000000 --- a/tools/proxy/conf/next.env +++ /dev/null @@ -1,18 +0,0 @@ -# Proxy Container - -deploy_hostname=next.kbase.us - -# disabled -#deploy_ui_hostname= - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ - - diff --git a/tools/proxy/conf/prod.env b/tools/proxy/conf/prod.env deleted file mode 100644 index 86e1e6cbf..000000000 --- a/tools/proxy/conf/prod.env +++ /dev/null @@ -1,17 +0,0 @@ -# Proxy Container - -deploy_hostname=kbase.us - -# for proxying to the narrative in this env. -deploy_ui_hostname=narrative.kbase.us - -# the ip or host of the kbase-ui container. This is required -# may need to override in the run command -kbase_ui_host=kbase-ui - -# true if actually deployed -# probably best to just override in the run command -deployed=true - -base_path=/ - diff --git a/tools/proxy/contents/conf/cors.conf.tmpl b/tools/proxy/contents/conf/cors.conf.tmpl index 0f33d757d..256ed827c 100644 --- a/tools/proxy/contents/conf/cors.conf.tmpl +++ b/tools/proxy/contents/conf/cors.conf.tmpl @@ -1,4 +1,3 @@ -{{ if .Env.deploy_ui_hostname }} proxy_hide_header 'Access-Control-Max-Age,'; proxy_hide_header 'Access-Control-Allow-Headers'; @@ -10,20 +9,17 @@ add_header 'Access-Control-Max-Age' 1728000; add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; - add_header 'Access-Control-Allow-Origin' 'https://{{ .Env.deploy_ui_hostname }}'; - # add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0 always; return 204; } - add_header 'Access-Control-Allow-Origin' 'https://{{ .Env.deploy_ui_hostname }}' always; - # add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Cookie' always; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; -{{ end }} \ No newline at end of file diff --git a/tools/proxy/contents/conf/nginx.conf.tmpl b/tools/proxy/contents/conf/nginx.conf.tmpl index 30d18dfdb..d7894a723 100644 --- a/tools/proxy/contents/conf/nginx.conf.tmpl +++ b/tools/proxy/contents/conf/nginx.conf.tmpl @@ -5,6 +5,33 @@ # Note that lower case environment variables are taken from conf/*.env, where * is the # deploy environment, taken from DEPLOY_ENV. +# Environment Variables: +# BASE_PATH = {{ or .Env.BASE_PATH "defaulting to ''" }} +# UI_DOMAIN = {{ .Env.KBASE_DOMAIN }} +# KBASE_UI_HOSTNAME = {{ .Env.KBASE_UI_HOSTNAME }} +# KBASE_UI_HOST = {{ or .Env.KBASE_UI_HOST "defaulting to ''" }} +# KBASE_UI_PORT = {{ or .Env.KBASE_UI_PORT "defaulting to ''" }} +# EUROPA_UI_HOST = {{ or .Env.EUROPA_UI_HOST "defaulting to ''" }} +# EUROPA_UI_PORT = {{ or .Env.EUROPA_UI_PORT "defaulting to ''" }} +# NARRATIVE_HOST = {{ or .Env.NARRATIVE_HOST "defaulting to ''" }} +# NARRATIVE_PORT = {{ or .Env.NARRATIVE_PORT "defaulting to ''" }} +# SERVICE_PROXIES = {{ or .Env.SERVICE_PROXIES "defaulting to ''" }} +# DYNAMIC_SERVICE_PROXIES = {{ or .Env.DYNAMIC_SERVICE_PROXIES "defaulting to ''" }} +# SERVICES_DOMAIN = {{ .Env.SERVICES_DOMAIN }} + +{{ $subhost := false }} +{{- $kbase_ui_domain := .Env.KBASE_DOMAIN -}} +{{- if .Env.KBASE_UI_HOSTNAME -}} + {{- $kbase_ui_domain = print .Env.KBASE_UI_HOSTNAME "." .Env.KBASE_DOMAIN -}} + {{- $subhost = true -}} +{{- end -}} + +{{ if $subhost }} +# Configured for SUBHOST {{ $kbase_ui_domain }} +{{ else }} +# Configured for SAME HOST +{{ end }} + daemon off; error_log /dev/stdout info; worker_processes auto; @@ -14,7 +41,6 @@ events { worker_connections 1024; } - http { sendfile on; tcp_nopush on; @@ -57,54 +83,7 @@ http { '' close; } - - # Define upstream servers, for convenience. - upstream kbase_ui { - # Use 80 for image; 3000 for devcontainer - # server {{ .Env.kbase_ui_host }}:80; - server {{ .Env.kbase_ui_host }}:3000; - # allows the proxy to start up even though the - # dev server may not be running yet - server {{ .Env.kbase_ui_host }}:80 backup; - keepalive 16; - } - - # upstream services { - # server {{ .Env.deploy_hostname }}; - # keepalive 16; - # } - - # upstream dynamic_services { - # server {{ .Env.deploy_hostname }}; - # keepalive 16; - # } - - upstream narrative { - {{ if .Env.local_narrative }} - server narrative:8888; - {{ else }} - {{ if .Env.deploy_ui_hostname }} - server {{ .Env.deploy_ui_hostname }}; - {{ else }} - server {{ .Env.deploy_hostname }}; - {{ end }} - {{ end }} - } - - upstream kbase_navigator { - {{ if .Env.local_navigator }} - server navigator:5000; - {{ else }} - {{ if .Env.deploy_ui_hostname }} - server {{ .Env.deploy_ui_hostname }}; - {{ else }} - server {{ .Env.deploy_hostname }}; - {{ end }} - {{ end }} - } - - log_format upstream_log '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time proxy_host $proxy_host upstream_status $upstream_status upstream_response_length $upstream_response_length upstream_http_location $upstream_http_location msec $msec request_time $request_time'; - + log_format upstream_log '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time proxy_host $proxy_host upstream_status $upstream_status upstream_response_length $upstream_response_length upstream_http_location $upstream_http_location msec $msec request_time $request_time http_origin $http_origin'; # Logging Settings access_log /var/log/nginx/access.log; @@ -114,166 +93,12 @@ http { server { listen 80 default_server; listen [::]:80 default_server; - server_name {{ default .Env.deploy_hostname .Env.deploy_ui_hostname }}; - return 301 https://{{ default .Env.deploy_hostname .Env.deploy_ui_hostname }}$request_uri; + server_name {{ .Env.KBASE_DOMAIN }}; + return 301 https://{{ .Env.KBASE_DOMAIN }}$request_uri; } - - - # If there is a separate ui hostname provided in the configuration, - # we need to listen for this separately. - # The only real usage of this is for production, in which kbase-ui and - # the narrative operate at narrative.kbase.us, but services at kbase.us. - {{ if .Env.deploy_ui_hostname }} - - # server { - # server_name {{ .Env.deploy_ui_hostname }}; - # listen 3000 ssl; - # ssl_certificate /kb/deployment/ssl/test.crt; - # ssl_certificate_key /kb/deployment/ssl/test.key; - # ssl_protocols TLSv1.2 TLSv1.1 TLSv1; - # location /ws/ { - # client_max_body_size 300M; - # proxy_connect_timeout 10s; - # proxy_pass http://kbase_ui/ws/; - # proxy_set_header Upgrade $http_upgrade; - # proxy_set_header Connection "Upgrade"; - # proxy_set_header Host {{ .Env.deploy_ui_hostname }}; - # } - # } - server { - listen 443 ssl; - server_name {{ .Env.deploy_ui_hostname }}; - ssl_certificate /kb/deployment/ssl/test.crt; - ssl_certificate_key /kb/deployment/ssl/test.key; - ssl_protocols TLSv1.2 TLSv1.1 TLSv1; - - location @request_entity_too_large { - default_type text/plain; - return 413 "Request entity is too large (> 5GB)"; - } - - location /__ping__ { - default_type "text/html"; - return 204; - } - - location /data/__perf__ { - gzip off; - gunzip on; - add_header Cache-Control 'no-cache, no-transform'; - proxy_pass http://kbase_ui; - } - - # Needed for running narratives - location /narrative/ { - access_log /var/log/nginx/narrative.log upstream_log; - - include /etc/nginx/cors.conf; - {{ if .Env.local_narrative }} - proxy_pass http://narrative/narrative/; - {{ else }} - {{ if .Env.deploy_ui_hostname }} - proxy_pass https://{{ .Env.deploy_ui_hostname }}/narrative/; - {{ else }} - proxy_pass https://{{ .Env.deploy_hostname }}/narrative/; - {{ end }} - # proxy_pass https://narrative/narrative/; - {{ end }} - - proxy_connect_timeout 10s; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Origin https://{{ .Env.deploy_ui_hostname }}; - proxy_set_header Host {{ .Env.deploy_ui_hostname }}; - } - - location /ui-assets/ { - proxy_pass https://{{ .Env.deploy_ui_hostname }}; - proxy_set_header Connection ""; - } - - location /sn/ { - proxy_pass https://{{ .Env.deploy_ui_hostname }}; - proxy_set_header Connection ""; - } - - location /narratives/ { - # {{ if .Env.local_navigator }} - # proxy_pass http://navigator/narratives/; - # {{ else }} - # proxy_pass https://kbase_navigator/narratives/; - # {{ end }} - - {{ if .Env.deploy_ui_hostname }} - proxy_pass https://{{ .Env.deploy_ui_hostname }}/narratives/; - {{ else }} - proxy_pass https://{{ .Env.deploy_hostname }}/narratives/; - {{ end }} - - access_log /var/log/nginx/navigator.log upstream_log; - - proxy_set_header Connection ""; - proxy_read_timeout 10m; - proxy_set_header Origin https://{{ .Env.deploy_ui_hostname }}; - proxy_set_header Host {{ .Env.deploy_ui_hostname }}; - } - - location /navigator/ { - # {{ if .Env.local_navigator }} - # proxy_pass http://navigator/narratives/; - # {{ else }} - # proxy_pass https://kbase_navigator/narratives/; - # {{ end }} - - {{ if .Env.deploy_ui_hostname }} - proxy_pass https://{{ .Env.deploy_ui_hostname }}/narratives/; - {{ else }} - proxy_pass https://{{ .Env.deploy_hostname }}/narratives/; - {{ end }} - - access_log /var/log/nginx/navigator.log upstream_log; - - proxy_set_header Connection ""; - proxy_read_timeout 10m; - proxy_set_header Origin https://{{ .Env.deploy_ui_hostname }}; - proxy_set_header Host {{ .Env.deploy_ui_hostname }}; - } - - location {{ .Env.BASE_PATH }} { - proxy_pass http://kbase_ui; - #proxy_set_header Cache-Control 'no-store'; - #proxy_set_header Cache-Control 'no-cache'; - #expires 0; - # proxy_set_header Connection ""; - # proxy_set_header Upgrade $http_upgrade; - # proxy_set_header Connection "upgrade"; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - } - } - - {{ end }} - - # server { - # server_name {{ .Env.deploy_hostname }}; - # listen 3000 ssl; - # ssl_certificate /kb/deployment/ssl/test.crt; - # ssl_certificate_key /kb/deployment/ssl/test.key; - # ssl_protocols TLSv1.2 TLSv1.1 TLSv1; - # proxy_http_version 1.1; - # location /ws/ { - # proxy_connect_timeout 10s; - # proxy_pass http://kbase_ui/ws/; - # proxy_set_header Upgrade $http_upgrade; - # proxy_set_header Connection "Upgrade"; - # proxy_set_header Host {{ .Env.deploy_hostname }}; - # } - # } - - server { - server_name {{ .Env.deploy_hostname }}; + server { + server_name {{ .Env.KBASE_DOMAIN }}; listen 443 ssl; ssl_certificate /kb/deployment/ssl/test.crt; ssl_certificate_key /kb/deployment/ssl/test.key; @@ -289,22 +114,25 @@ http { keepalive_timeout 0; proxy_socket_keepalive off; + # Include service and dynamic service proxying here if the ui host + # is the same as the service host. + # Service proxying # specified as a list of service modules # note should put the service module name in /etc/hosts and map to localhost - {{ if .Env.service_proxies }} - {{ range splitList " " .Env.service_proxies }} + {{ if .Env.SERVICE_PROXIES }} + {{ range splitList " " .Env.SERVICE_PROXIES }} {{ if eq . "searchapi2" }} location /services/searchapi2/legacy { - {{ if $.Env.deploy_ui_hostname }} + {{ if $subhost }} include /etc/nginx/cors.conf; {{ end }} proxy_pass http://searchapi2:5000/legacy; proxy_set_header Connection ""; } location /services/searchapi2/rpc { - {{ if $.Env.deploy_ui_hostname }} + {{ if $subhost }} include /etc/nginx/cors.conf; {{ end }} proxy_pass http://searchapi2:5000/rpc; @@ -321,16 +149,16 @@ http { # client_max_body_size 5000001000; error_page 413 @request_entity_too_large; - {{ if $.Env.deploy_ui_hostname }} - include /etc/nginx/cors.conf; - {{ end }} + + # include /etc/nginx/cors.conf; + proxy_pass http://{{ . }}:3000/; proxy_set_header Connection ""; proxy_read_timeout 10m; } {{ else }} location /services/{{ . }}/ { - {{ if $.Env.deploy_ui_hostname }} + {{ if $subhost }} include /etc/nginx/cors.conf; {{ end }} proxy_pass http://{{ . }}:5000/; @@ -338,7 +166,7 @@ http { proxy_read_timeout 10m; } location /services/{{ . }} { - {{ if $.Env.deploy_ui_hostname }} + {{ if $subhost }} include /etc/nginx/cors.conf; {{ end }} proxy_pass http://{{ . }}:5000; @@ -350,18 +178,20 @@ http { {{ end }} {{ end }} - # Proxy all service calls, including auth2, to the real CI location /services { access_log /var/log/nginx/services_proxy.log upstream_log; - # The cookie path rewriting is just for auth2 - {{ if .Env.deploy_ui_hostname }} + # need cors because kbase-ui will be on a different host. + + {{ if $subhost }} include /etc/nginx/cors.conf; {{ end }} + + # The cookie path rewriting is just for auth2 proxy_cookie_path /login /services/auth/login; proxy_cookie_path /link /services/auth/link; - proxy_pass https://{{ .Env.deploy_hostname }}/services; + proxy_pass https://{{ .Env.SERVICES_DOMAIN }}/services; proxy_set_header Connection ""; proxy_read_timeout 10m; } @@ -375,8 +205,8 @@ http { # where XXX is a random-appearing string component provided by the service wizard # and Module is the dynamic service module name. - {{ if .Env.dynamic_service_proxies }} - {{ range splitList " " .Env.dynamic_service_proxies }} + {{ if .Env.DYNAMIC_SERVICE_PROXIES }} + {{ range splitList " " .Env.DYNAMIC_SERVICE_PROXIES }} # note that the elements of the list must match the service path used in the ui call, # and also the hostname assigned to the docker container. @@ -384,8 +214,9 @@ http { # without punctuation will work, but if they contain a / or something, maybe not. location ~ ^/dynserv/[^.]+[.]{{ . }}.*$ { - {{ if $.Env.deploy_ui_hostname }} - include /etc/nginx/cors.conf; + # need cors if kbase-ui will be on a different host. + {{ if $subhost }} + include /etc/nginx/cors.conf; {{ end }} # This handles plain dynamic service calls, which don't have any path following the module name @@ -403,33 +234,25 @@ http { # Un-trapped dynamic service calls are routed to the real dynamic service # endpoints. location /dynserv { - {{ if .Env.deploy_ui_hostname }} - include /etc/nginx/cors.conf; + # need cors if kbase-ui will be on a different host. + {{ if $subhost }} + include /etc/nginx/cors.conf; {{ end }} - proxy_pass https://{{ .Env.deploy_hostname }}/dynserv; + + proxy_pass https://{{ .Env.SERVICES_DOMAIN }}/dynserv; proxy_set_header Connection ""; proxy_read_timeout 10m; } - # Repeat the ui proxying for the case in which they reside on the same - # host name as services. - {{ if not .Env.deploy_ui_hostname }} - - location /__ping__ { - default_type "text/html"; - return 204; - } - location /narrative/ { - {{ if .Env.local_narrative }} - proxy_pass http://narrative/narrative/; + {{ if .Env.NARRATIVE_HOST }} + proxy_pass http://{{ .Env.NARRATIVE_HOST }}:{{ or .Env.NARRATIVE_PORT "8888" }}/narrative/; {{ else }} - {{ if .Env.deploy_ui_hostname }} - proxy_pass https://{{ .Env.deploy_ui_hostname }}/narrative/; - {{ else }} - proxy_pass https://{{ .Env.deploy_hostname }}/narrative/; - {{ end }} - # proxy_pass https://narrative/narrative/; + proxy_pass https://{{ .Env.KBASE_DOMAIN }}/narrative/; + {{ end }} + + {{ if $subhost }} + include /etc/nginx/cors.conf; {{ end }} access_log /var/log/nginx/narrative.log upstream_log; @@ -437,61 +260,108 @@ http { proxy_connect_timeout 10s; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; - proxy_set_header Origin https://{{ .Env.deploy_hostname }}; - proxy_set_header Host {{ .Env.deploy_hostname }}; + proxy_set_header Origin https://{{ .Env.KBASE_DOMAIN }}; + proxy_set_header Host {{ .Env.KBASE_DOMAIN }}; } location /ui-assets/ { - proxy_pass https://{{ .Env.deploy_hostname }}; + proxy_pass https://{{ .Env.KBASE_DOMAIN }}; proxy_set_header Connection ""; } location /sn/ { - proxy_pass https://{{ .Env.deploy_hostname }}; + proxy_pass https://{{ .Env.KBASE_DOMAIN }}; proxy_set_header Connection ""; } location /n/ { - proxy_pass https://{{ .Env.deploy_hostname }}; + proxy_pass https://{{ .Env.KBASE_DOMAIN }}; proxy_set_header Connection ""; } - location /narratives/ { - # {{ if .Env.local_navigator }} - # proxy_pass http://navigator/narratives/; - # {{ else }} - # proxy_pass https://kbase_navigator/narratives/; - # {{ end }} - {{ if .Env.deploy_ui_hostname }} - proxy_pass https://{{ .Env.deploy_ui_hostname }}/narratives/; + # kbase-ui will be located on a path + # disable this if the subdomain is used instead. + # in this case, KBASE_UI_BASE_PATH had better not be empty or /. + {{ if not $subhost }} + + {{ if .Env.KBASE_UI_BASE_PATH }} + location /{{ .Env.KBASE_UI_BASE_PATH }}/ { + {{ if .Env.KBASE_UI_HOST }} + proxy_pass http://{{ .Env.KBASE_UI_HOST }}:{{ or .Env.KBASE_UI_PORT "3000" }}; + # allows the proxy to start up even though the + # target may not be running yet + # server {{ .Env.KBASE_UI_HOST }}:80 backup; + # keepalive 16; {{ else }} - proxy_pass https://{{ .Env.deploy_hostname }}/narratives/; + proxy_pass https://{{ $kbase_ui_domain }}; {{ end }} - access_log /var/log/nginx/navigator.log upstream_log; + proxy_set_header Connection ""; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + {{ else }} + + # not a valid configuration, because it will always conflict with Europa. + NOT VALID CONFIGURATION + + {{ end }} + + {{ end }} + + # Europa is always at the root. + location / { + {{ if .Env.EUROPA_UI_HOST }} + proxy_pass http://{{ .Env.EUROPA_UI_HOST }}:{{ or .Env.EUROPA_UI_PORT "8080" }}; + # allows the proxy to start up even though the + # target may not be running yet + # server {{ .Env.EUROPA_UI_HOST }}:80 backup; + # keepalive 16; + {{ else }} + proxy_pass https://{{ .Env.KBASE_DOMAIN }}; + {{ end }} + + # for the dev server, may need to turn on no-store. + #add_header Cache-Control "no-store"; + #add_header Cache-Control 'no-cache'; + #expires 0; proxy_set_header Connection ""; - proxy_read_timeout 10m; - proxy_set_header Origin https://{{ .Env.deploy_hostname }}; - proxy_set_header Host {{ .Env.deploy_hostname }}; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; } + } + + # This is invoked to run kbase-ui on a subdomain if specified + # This is de-facto always the case in the current Europa implementation. + {{ if $subhost }} + server { + server_name {{ $kbase_ui_domain }}; + listen 443 ssl; + ssl_certificate /kb/deployment/ssl/test.crt; + ssl_certificate_key /kb/deployment/ssl/test.key; + ssl_protocols TLSv1.2 TLSv1.1 TLSv1; - # location /vite_hms { - # proxy_pass http://{{ .Env.deploy_hostname }}:3001/vite_hms; - # proxy_http_version 1.1; - # proxy_set_header Upgrade $http_upgrade; - # proxy_set_header Connection "Upgrade"; - # proxy_set_header Host {{ .Env.deploy_hostname }}; - # } + location {{ or .Env.KBASE_UI_BASE_PATH ""}}/ { - location {{ .Env.BASE_PATH }} { - proxy_pass http://kbase_ui; + {{ if .Env.KBASE_UI_HOST }} + proxy_pass http://{{ .Env.KBASE_UI_HOST }}:{{ or .Env.KBASE_UI_PORT "3000" }}; + # allows the proxy to start up even though the + # target may not be running yet + # server {{ .Env.KBASE_UI_HOST }}:80 backup; + # keepalive 16; + {{ else }} + proxy_pass https://{{ $kbase_ui_domain }}; + {{ end }} + + include /etc/nginx/cors.conf; proxy_set_header Connection ""; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } - - {{ end }} } -} \ No newline at end of file + {{ end }} +} diff --git a/tools/proxy/docker-compose.yml b/tools/proxy/docker-compose.yml index 0edea586c..cce525bbb 100644 --- a/tools/proxy/docker-compose.yml +++ b/tools/proxy/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.6' +name: kbase-dev networks: kbase-dev: name: kbase-dev @@ -7,7 +7,7 @@ services: build: context: . # there is only one proxy image, for local development, so just call it :dev - image: kbase/kbase-ui-proxy:dev + image: local/kbase-ui-proxy:dev networks: - kbase-dev container_name: kbase-ui-proxy @@ -16,4 +16,7 @@ services: - '443:443' dns: 8.8.8.8 # note that this is really a docker env file and is relative to the docker-compose file - env_file: ./conf/${DEPLOY_ENV}.env + # env_file: ./conf/${DEPLOY_ENV}.env + env_file: + - ../../.devcontainer/proxy.env + diff --git a/tools/python/Dockerfile b/tools/python/Dockerfile new file mode 100644 index 000000000..f14f18e41 --- /dev/null +++ b/tools/python/Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.12.2-slim-bookworm + +MAINTAINER KBase Developer + +# ----------------------------------------- +# In this section, you can install any system dependencies required +# to run your App. For instance, you could place an apt-get update or +# install line here, a git checkout to download code, or run any other +# installation scripts. +# ----------------------------------------- + +# We need git for the git-info tool. +RUN apt-get update && apt-get install -y git openssh-client + +SHELL ["/bin/bash", "-c"] + +ENV PYTHONPATH="/app/tools/python" + +RUN mkdir -p /app && chmod -R a+rw /app + +WORKDIR /app + +COPY requirements.txt /app +RUN pip install -r requirements.txt + +ENTRYPOINT [ "tools/python/entrypoint.sh" ] + +CMD [ "bash" ] diff --git a/tools/python/docker-compose.yml b/tools/python/docker-compose.yml new file mode 100644 index 000000000..a30a9864c --- /dev/null +++ b/tools/python/docker-compose.yml @@ -0,0 +1,9 @@ +services: + runner: + build: + context: . + dockerfile: Dockerfile + volumes: + - ../..:/app + command: + - bash diff --git a/tools/python/entrypoint.sh b/tools/python/entrypoint.sh new file mode 100755 index 000000000..5da2fde91 --- /dev/null +++ b/tools/python/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +# Nice to set this up for all future python code being run. +# export PYTHONPATH="${PWD}/src" + +# +# This execs whatever is provided as a COMMAND to the container. By default, as established +# in the image via the Dockerfile, it is scripts/start-server.sh +# This mechanism, though, allows us to run anything inside the container. We use this +# for running tests, mypy, black, etc. through docker compose. +# Note that surrounding $@ with double quote causes the expansion (which starts with +# parameter 1 not 0) to result in each parameter being retained without splitting. +# Sort of like "$@" -> "$1" "$2" "$3" .. +# +exec "$@" diff --git a/tools/python/pyproject.toml b/tools/python/pyproject.toml new file mode 100644 index 000000000..2f509c9b5 --- /dev/null +++ b/tools/python/pyproject.toml @@ -0,0 +1,47 @@ +[tool.poetry] +name = "kbase-ui-tools" +version = "0.0.1" +description = "" +authors = ["Erik Pearson "] +package-mode = false + +[tool.poetry.dependencies] +python = "3.12.2" + +[tool.poetry.group.dev.dependencies] +autoflake = "2.3.1" +black = "24.4.0" +fastapi = { version = "0.110.1", extras = ["all"] } +isort = "5.13.2" +pipdeptree = "2.18.1" +pyfakefs = "5.4.1" +pyright = "1.1.358" +pytest = "8.1.1" +# pytest = "7.4.3" +pytest-asyncio = "0.23.6" +pytest-cov = "5.0.0" +types-cachetools = "5.3.0.7" +types-python-dateutil = "2.9.0.20240316" +types-PyYAML = "6.0.12.20240311" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.pytest.ini_options] +asyncio_mode = "auto" + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true +warn_untyped_fields = true + +[tool.isort] +profile = "black" + +# [tool.pyright] +# include = ["src"] +# reportMissingImports = true +# # reportMissingTypeStubs = false +# strict = ["src/orcidlink"] diff --git a/tools/python/requirements.txt b/tools/python/requirements.txt new file mode 100644 index 000000000..84ca1ea97 --- /dev/null +++ b/tools/python/requirements.txt @@ -0,0 +1,2 @@ +pyYAML==6.0.1 +requests==2.31.0 \ No newline at end of file diff --git a/tools/python/scripts/__init__.py b/tools/python/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/python/scripts/build-info.py b/tools/python/scripts/build-info.py new file mode 100644 index 000000000..cc49655c9 --- /dev/null +++ b/tools/python/scripts/build-info.py @@ -0,0 +1,16 @@ +import json +import sys +from datetime import datetime, timezone + + +def main(): + dest = sys.argv[1] + build_info = { + "builtAt": f"{datetime.now(tz=timezone.utc).replace(microsecond=0).isoformat()}" + } + with open(dest, "w", encoding="utf-8") as out: + json.dump(build_info, out, indent=4) + + +if __name__ == "__main__": + main() diff --git a/tools/python/scripts/common.py b/tools/python/scripts/common.py new file mode 100644 index 000000000..2490d984c --- /dev/null +++ b/tools/python/scripts/common.py @@ -0,0 +1,93 @@ +import os +import subprocess +import sys +from datetime import datetime, timezone +from typing import List +from urllib.parse import urlparse + + +def print_lines(prefix: str, lines: List[str]): + for index, line in enumerate(lines): + print(f"{prefix} {index}: {line}") + + +def run_command(command, ignore_error=False): + try: + process = subprocess.run(command, check=True, capture_output=True, text=True) + except subprocess.CalledProcessError as cpe: + if ignore_error: + return str(cpe), False + print("Error running git command:") + print(f"Command: {cpe.cmd}") + if cpe.stderr is not None: + print_lines("stderr", cpe.stderr.split("\n")) + print(str(cpe)) + sys.exit(1) + + return process.stdout, True + + +def utc_in_iso8601(timestamp): + return ( + datetime.fromtimestamp(timestamp, tz=timezone.utc) + .replace(microsecond=0) + .isoformat() + ) + + +def git_info(git_repo_directory=None): + current_directory = os.getcwd() + if git_repo_directory: + os.chdir(git_repo_directory) + + config1, config2 = run_command( + ["git", "config", "--global", "--add", "safe.directory", "/app"] + ) + + output, _ = run_command( + ["git", "show", "--format=%H%n%h%n%an%n%at%n%cn%n%ct%n%d", "--name-status"] + ) + + [ + commit_hash, + commit_hash_abbreviated, + author_name, + author_date, + committer_name, + committer_date, + *_, + ] = output.split("\n") + + subject, _ = run_command(["git", "log", "-1", "--pretty=%s"]) + + notes, _ = run_command(["git", "log", "-1", "--pretty=%N"]) + + origin_url, _ = run_command(["git", "config", "--get", "remote.origin.url"]) + + [_, account, repo_name] = urlparse(origin_url).path.split("/") + + branch, _ = run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"]) + + if git_repo_directory: + os.chdir(current_directory) + + return { + "hash": { + "full": commit_hash, + "abbreviated": commit_hash_abbreviated, + }, + "subject": subject.strip(), + "notes": notes.strip(), + "author": { + "name": author_name, + "date": utc_in_iso8601(int(author_date)), + }, + "committer": { + "name": committer_name, + "date": utc_in_iso8601(int(committer_date)), + }, + "originURL": origin_url.strip(), + "account": account, + "repoName": repo_name, + "branch": branch.strip(), + } diff --git a/tools/python/scripts/git-info.py b/tools/python/scripts/git-info.py new file mode 100644 index 000000000..22309d5a4 --- /dev/null +++ b/tools/python/scripts/git-info.py @@ -0,0 +1,19 @@ +import json +import sys + +from .common import git_info + + +def save_info(info, dest): + with open(dest, "w", encoding="utf-8") as fout: + json.dump(info, fout, indent=4) + + +def main(): + dest = sys.argv[1] + info = git_info() + save_info(info, dest) + sys.exit(0) + + +main() diff --git a/tools/python/scripts/install-plugins.py b/tools/python/scripts/install-plugins.py new file mode 100644 index 000000000..0c7645a07 --- /dev/null +++ b/tools/python/scripts/install-plugins.py @@ -0,0 +1,237 @@ +import glob +import gzip +import json +import os +import pathlib +import re +import shutil +import subprocess +import sys +import tarfile +import tempfile +from typing import List + +import requests +import yaml + +from .common import git_info + + +def print_lines(prefix: str, lines: List[str]): + for index, line in enumerate(lines): + print(f"{prefix} {index}: {line}") + + +def run_command(command, ignore_error=False): + try: + process = subprocess.run(command, check=True, capture_output=True, text=True) + except subprocess.CalledProcessError as cpe: + if ignore_error: + return str(cpe), False + print("Error running git command:") + print(f"Command: {cpe.cmd}") + if cpe.stderr is not None: + print_lines("stderr", cpe.stderr.split("\n")) + print(str(cpe)) + sys.exit(1) + + return process.stdout, True + + +def save_info(info, dest): + with open(dest, "w", encoding="utf-8") as fout: + json.dump(info, fout, indent=4) + + +def load_config(path): + with open(path, "r", encoding="utf-8") as config_in: + return yaml.safe_load(config_in) + + +def dig(obj, key, default_value=None): + path = key.split(".") + + def into(obj, path): + if len(path) == 0: + return obj + + [key, *rest] = path + if re.match(r"[0-9]+", key) is not None: + index = int(key) + if len(obj) > index: + return into(obj[index], rest) + else: + return default_value + elif key in obj: + return into(obj[key], rest) + else: + return default_value + + return into(obj, path) + + +def fetch_plugins_dist(config, dest): + current_directory = os.getcwd() + os.chdir(dest) + + for plugin in config["plugins"]: + if dig(plugin, "source.github.release"): + continue + + branch = f"v{plugin['version']}" + name = plugin["name"] + account = dig(plugin, "source.github.account") + + print(f'Fetching plugin "{name}" from branch {branch}...', end="", flush=True) + + run_command( + [ + "git", + "clone", + "-b", + branch, + f"https://github.com/{account}/kbase-ui-plugin-{name}", + name, + ] + ) + + print(" ...done!") + + os.chdir(current_directory) + + +def fetch_plugins_release_dist(config, dest, gh_token): + for plugin in config["plugins"]: + if not dig(plugin, "source.github.release"): + continue + + tag = f"v{plugin['version']}" + name = plugin["name"] + account = dig(plugin, "source.github.account") + + print(f'Fetching plugin release "{name}" from tag {tag}...', end="", flush=True) + + release_url = f"https://api.github.com/repos/{account}/kbase-ui-plugin-{name}/releases/tags/{tag}" + + response = requests.get( + release_url, + headers={ + "accept": "application/vnd.github+json", + "authorization": f"Bearer {gh_token}", + }, + ) + + result = response.json() + + assets = dig(result, "assets") + + asset_url = None + for asset in assets: + if asset["name"] == "dist.tgz": + asset_url = asset["url"] + break + + plugin_dir = f"{dest}/{name}" + pathlib.Path(plugin_dir).mkdir(exist_ok=True) + + response = requests.get( + asset_url, headers={"accept": "application/octet-stream"}, stream=True + ) + + with open(f"{plugin_dir}/dist.tgz", "wb") as dist_out: + shutil.copyfileobj(response.raw, dist_out) + + print("done!") + + +def unpack_plugins(source, dest): + for plugin_dir in glob.glob(f"{source}/*"): + filename = f"{plugin_dir}/dist.tgz" + plugin_name = pathlib.Path(plugin_dir).name + + with open(filename, "rb") as dist_in: + gzip_file = gzip.GzipFile(fileobj=dist_in) + tf = tarfile.TarFile(fileobj=gzip_file) + plugin_path = f"{dest}/{plugin_name}" + tf.extractall(plugin_path) + + # old style archives are of the full path "dist/plugin", + # which we want to undo. + if pathlib.Path(f"{plugin_path}/dist").is_dir(): + shutil.move(plugin_path, f"{plugin_path}.temp") + shutil.move(f"{plugin_path}.temp/dist/plugin", plugin_path) + shutil.rmtree(f"{plugin_path}.temp") + + +def create_plugin_manifest(plugin_ui_config, plugin_source_dir, plugin_install_dir): + plugin_name = plugin_ui_config["name"] + + with open(f"{plugin_install_dir}/config.yml", "r", encoding="utf-8") as config_in: + plugin_config = yaml.safe_load(config_in) + + if dig(plugin_ui_config, "source.github.release"): + return { + "type": "GITHUB_RELEASE", + "install": {"directory": plugin_source_dir}, + "configs": {"plugin": plugin_config, "ui": plugin_ui_config}, + } + else: + git = git_info(plugin_source_dir) + return { + "type": "GIT_REPO", + "install": {"directory": plugin_source_dir}, + "configs": {"plugin": plugin_config, "ui": plugin_ui_config}, + "git": git, + } + + +def generate_plugins_manifest(ui_config, source_dir, dest_dir): + plugins_manifest = [] + + for ui_plugin_config in ui_config["plugins"]: + plugin_name = ui_plugin_config["name"] + plugin_install_dir = f"{dest_dir}/{plugin_name}" + plugin_source_dir = f"{source_dir}/{plugin_name}" + + plugins_manifest.append( + create_plugin_manifest( + ui_plugin_config, plugin_source_dir, plugin_install_dir + ) + ) + + manifest_file_name = f"{dest_dir}/plugin-manifest.json" + manifest_file_path = pathlib.Path(manifest_file_name) + with open(manifest_file_path, "w", encoding="utf-8") as manifest_out: + json.dump(plugins_manifest, manifest_out) + + +def main(): + print("Installing plugins...") + + config_path = sys.argv[1] + dest = sys.argv[2] + gh_token = sys.argv[3] + + # TODO: Make sure destination directory does not exist yet. + + with tempfile.TemporaryDirectory() as temp_dir_name: + + config = load_config(config_path) + + pathlib.Path(dest).mkdir(exist_ok=True) + + fetch_plugins_dist(config, temp_dir_name) + + fetch_plugins_release_dist(config, temp_dir_name, gh_token) + + unpack_plugins(temp_dir_name, dest) + + generate_plugins_manifest(config, temp_dir_name, dest) + + sys.exit(0) + + print("Done installing plugins!") + + +main() +main() diff --git a/vite-app/.eslintignore b/vite-app/.eslintignore new file mode 100644 index 000000000..999c405a8 --- /dev/null +++ b/vite-app/.eslintignore @@ -0,0 +1,3 @@ +/node_modules/ +/dist/ +/coverage/ \ No newline at end of file diff --git a/vite-app/.eslintrc.cjs b/vite-app/.eslintrc.cjs deleted file mode 100644 index 4020bcbf4..000000000 --- a/vite-app/.eslintrc.cjs +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - parser: '@typescript-eslint/parser', - parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': 'warn', - }, -} diff --git a/vite-app/eslint.config.js b/vite-app/eslint.config.js new file mode 100644 index 000000000..07c8cb257 --- /dev/null +++ b/vite-app/eslint.config.js @@ -0,0 +1,31 @@ +import pluginJs from "@eslint/js"; +import pluginReactRuntime from "eslint-plugin-react/configs/jsx-runtime.js"; +import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + + +export default [ + {languageOptions: { + globals: globals.browser, + parserOptions: { + ecmaFeatures: { + jsx: true + } + } +}}, + { + settings: { + react: { + version: "18.2.0" + } + } + }, + // Basic JS + pluginJs.configs.recommended, + // Typescript + ...tseslint.configs.recommended, + // React + pluginReactConfig, + pluginReactRuntime, +]; \ No newline at end of file diff --git a/vite-app/index.html b/vite-app/index.html index d06ae8fe6..593ab0a3a 100644 --- a/vite-app/index.html +++ b/vite-app/index.html @@ -2,37 +2,31 @@ + + - - - - - - - - KBase
-
-
Loading KBase UI ...
- KBase animated logo +
+ KBase animated logo
-
+
-->
- + \ No newline at end of file diff --git a/vite-app/package-lock.json b/vite-app/package-lock.json index 9781b3ac5..874d9f18f 100644 --- a/vite-app/package-lock.json +++ b/vite-app/package-lock.json @@ -1,53 +1,74 @@ { - "name": "vite-app", + "name": "kbase-ui", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "vite-app", + "name": "kbase-ui", "version": "0.0.0", "dependencies": { - "@ant-design/icons": "5.2.6", - "antd": "5.10.1", - "bootstrap": "5.3.2", - "dompurify": "3.0.6", - "es-cookie": "1.4.0", + "@ant-design/icons": "5.3.6", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-regular-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", + "@fortawesome/react-fontawesome": "0.2.0", + "ajv": "8.12.0", + "antd": "5.16.4", + "bootstrap": "5.3.3", + "dompurify": "3.1.0", + "es-cookie": "1.5.0", "font-awesome": "4.7.0", - "marked": "9.1.2", + "formik": "2.4.5", + "highlight.js": "11.9.0", + "marked": "12.0.2", "react": "18.2.0", - "react-bootstrap": "2.9.0", - "react-bootstrap-icons": "1.10.3", + "react-bootstrap": "2.10.2", + "react-bootstrap-icons": "1.11.4", "react-dom": "18.2.0", - "react-router-dom": "6.17.0", - "react-select": "5.7.7", - "uuid": "9.0.1" + "react-router-dom": "6.23.0", + "react-select": "5.8.0", + "ts-md5": "1.3.1", + "uuid": "9.0.1", + "yup": "1.4.0" }, "devDependencies": { + "@eslint/js": "9.0.0", "@kbase/ui-lib": "0.7.1", - "@testing-library/jest-dom": "6.1.4", - "@testing-library/react": "14.0.0", - "@testing-library/user-event": "14.5.1", - "@types/dompurify": "3.0.4", - "@types/jest": "29.5.6", - "@types/react": "18.2.30", - "@types/react-dom": "18.2.14", + "@testing-library/jest-dom": "6.4.2", + "@testing-library/react": "15.0.4", + "@testing-library/user-event": "14.5.2", + "@types/dompurify": "3.0.5", + "@types/jest": "29.5.12", + "@types/react": "18.2.79", + "@types/react-dom": "18.2.25", "@types/react-router-dom": "5.3.3", - "@types/uuid": "9.0.6", - "@typescript-eslint/eslint-plugin": "6.8.0", - "@typescript-eslint/parser": "6.8.0", - "@vitejs/plugin-react": "4.1.0", - "@vitest/coverage-v8": "0.34.6", - "eslint": "8.51.0", + "@types/uuid": "9.0.8", + "@typescript-eslint/eslint-plugin": "7.7.1", + "@typescript-eslint/parser": "7.7.1", + "@vitejs/plugin-react": "4.2.1", + "@vitest/coverage-v8": "1.5.1", + "eslint": "8.57.0", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-import": "2.29.1", + "eslint-plugin-jsx-a11y": "6.8.0", + "eslint-plugin-prettier": "5.1.3", + "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-react-refresh": "0.4.3", - "jsdom": "22.1.0", - "prettier": "3.0.3", + "eslint-plugin-react-refresh": "0.4.6", + "globals": "15.0.0", + "jsdom": "24.0.0", + "lint-staged": "15.2.2", + "markdownlint": "0.34.0", + "prettier": "3.2.5", "sass": "1.64.", - "typescript": "5.2.2", - "vite": "4.5.0", - "vite-tsconfig-paths": "4.2.1", - "vitest": "0.34.6" + "simple-git-hooks": "2.11.1", + "standard": "17.1.0", + "typescript": "5.4.5", + "typescript-eslint": "7.7.1", + "vite": "5.2.10", + "vite-tsconfig-paths": "4.3.2", + "vitest": "1.5.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -60,9 +81,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", + "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -79,23 +100,23 @@ } }, "node_modules/@ant-design/colors": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.0.tgz", - "integrity": "sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.2.tgz", + "integrity": "sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==", "dependencies": { - "@ctrl/tinycolor": "^3.4.0" + "@ctrl/tinycolor": "^3.6.1" } }, "node_modules/@ant-design/cssinjs": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.17.2.tgz", - "integrity": "sha512-vu7lnfEx4Mf8MPzZxn506Zen3Nt4fRr2uutwvdCuTCN5IiU0lDdQ0tiJ24/rmB8+pefwjluYsbyzbQSbgfJy+A==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.18.5.tgz", + "integrity": "sha512-Ub4n3d+MAX/qtE5S9PM8iOn5ocU7GUAIC4Adc2X8UCMXnsRRfpJBHsBdtQ1qoAuaQ7lU2M1BTCuJ+fkv4fOWiw==", "dependencies": { "@babel/runtime": "^7.11.1", "@emotion/hash": "^0.8.0", "@emotion/unitless": "^0.7.5", "classnames": "^2.3.1", - "csstype": "^3.0.10", + "csstype": "^3.1.3", "rc-util": "^5.35.0", "stylis": "^4.0.13" }, @@ -115,12 +136,12 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" }, "node_modules/@ant-design/icons": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.2.6.tgz", - "integrity": "sha512-4wn0WShF43TrggskBJPRqCD0fcHbzTYjnaoskdiJrVHg86yxoZ8ZUqsXvyn4WUqehRiFKnaclOhqk9w4Ui2KVw==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.6.tgz", + "integrity": "sha512-JeWsgNjvkTTC73YDPgWOgdScRku/iHN9JU0qk39OSEmJSCiRghQMLlxGTCY5ovbRRoXjxHXnUKgQEgBDnQfKmA==", "dependencies": { "@ant-design/colors": "^7.0.0", - "@ant-design/icons-svg": "^4.3.0", + "@ant-design/icons-svg": "^4.4.0", "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", "rc-util": "^5.31.1" @@ -134,14 +155,14 @@ } }, "node_modules/@ant-design/icons-svg": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.3.0.tgz", - "integrity": "sha512-WOgvdH/1Wl8Z7VXigRbCa5djO14zxrNTzvrAQzhWiBQtEKT0uTc8K1ltjKZ8U1gPn/wXhMA8/jE39SJl0WNxSg==" + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.0.tgz", + "integrity": "sha512-71rcNssTaRL1ytvPLebKuc/8Bjqxs5V1YkTbqlSCvNa0Se+HmYJwWHhRTpsSHBh+sWFtc7xpGCTRW2Ta04XyHw==" }, "node_modules/@ant-design/react-slick": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.0.2.tgz", - "integrity": "sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", "dependencies": { "@babel/runtime": "^7.10.4", "classnames": "^2.2.5", @@ -154,11 +175,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -230,30 +251,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", - "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.0", - "@babel/parser": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -284,12 +305,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -299,14 +320,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -384,9 +405,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -436,9 +457,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } @@ -452,32 +473,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -552,9 +573,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -564,9 +585,9 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", - "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -579,9 +600,9 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", - "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -594,11 +615,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -619,20 +640,20 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -649,11 +670,11 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -778,10 +799,26 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", - "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -795,9 +832,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz", - "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -811,9 +848,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz", - "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -827,9 +864,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz", - "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -843,9 +880,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz", - "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -859,9 +896,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz", - "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -875,9 +912,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz", - "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -891,9 +928,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz", - "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -907,9 +944,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz", - "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -923,9 +960,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz", - "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -939,9 +976,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz", - "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -955,9 +992,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz", - "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -971,9 +1008,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz", - "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -987,9 +1024,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz", - "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -1003,9 +1040,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz", - "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -1019,9 +1056,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz", - "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -1035,9 +1072,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz", - "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -1051,9 +1088,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz", - "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -1067,9 +1104,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz", - "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -1083,9 +1120,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz", - "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -1099,9 +1136,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz", - "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -1115,9 +1152,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz", - "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -1146,18 +1183,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -1177,13 +1214,50 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz", + "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@floating-ui/core": { @@ -1199,14 +1273,71 @@ "@floating-ui/core": "^1.3.1" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", + "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -1227,9 +1358,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@istanbuljs/schema": { @@ -1321,21 +1452,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@kbase/ui-lib": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@kbase/ui-lib/-/ui-lib-0.7.1.tgz", @@ -1385,6 +1510,18 @@ "node": ">= 8" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -1395,14 +1532,14 @@ } }, "node_modules/@rc-component/color-picker": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz", - "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.3.tgz", + "integrity": "sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw==", "dependencies": { - "@babel/runtime": "^7.10.1", - "@ctrl/tinycolor": "^3.6.0", + "@babel/runtime": "^7.23.6", + "@ctrl/tinycolor": "^3.6.1", "classnames": "^2.2.6", - "rc-util": "^5.30.0" + "rc-util": "^5.38.1" }, "peerDependencies": { "react": ">=16.9.0", @@ -1468,13 +1605,13 @@ } }, "node_modules/@rc-component/tour": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.10.0.tgz", - "integrity": "sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.14.2.tgz", + "integrity": "sha512-A75DZ8LVvahBIvxooj3Gvf2sxe+CGOkmzPNX7ek0i0AJHyKZ1HXe5ieIGo3m0FMdZfVOlbCJ952Duq8VKAHk6g==", "dependencies": { "@babel/runtime": "^7.18.0", "@rc-component/portal": "^1.0.0-9", - "@rc-component/trigger": "^1.3.6", + "@rc-component/trigger": "^2.0.0", "classnames": "^2.3.2", "rc-util": "^5.24.4" }, @@ -1487,17 +1624,16 @@ } }, "node_modules/@rc-component/trigger": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.17.0.tgz", - "integrity": "sha512-KN+lKHCi7L4kjuA9DU2PnwZxtIyes6R1wsexp0/Rnjr/ITELsPuC9kpzDK1+7AZMarDXUAHUdDGS2zUNEx2P0g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.1.1.tgz", + "integrity": "sha512-UjHkedkgtEcgQu87w1VuWug1idoDJV7VUt0swxHXRcmei2uu1AuUzGBPEUlmOmXGJ+YtTgZfVLi7kuAUKoZTMA==", "dependencies": { - "@babel/runtime": "^7.18.3", + "@babel/runtime": "^7.23.2", "@rc-component/portal": "^1.1.0", "classnames": "^2.3.2", - "rc-align": "^4.0.0", "rc-motion": "^2.0.0", "rc-resize-observer": "^1.3.1", - "rc-util": "^5.33.0" + "rc-util": "^5.38.0" }, "engines": { "node": ">=8.x" @@ -1508,52 +1644,42 @@ } }, "node_modules/@react-aria/ssr": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz", - "integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.2.tgz", + "integrity": "sha512-0gKkgDYdnq1w+ey8KzG9l+H5Z821qh9vVjztk55rUg71vTk/Eaebeir+WtzcLLwTjw3m/asIjx8Y59y1lJZhBw==", "dependencies": { - "@swc/helpers": "^0.4.14" + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, - "node_modules/@react-aria/ssr/node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@react-aria/ssr/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, "node_modules/@remix-run/router": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", - "integrity": "sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.0.tgz", + "integrity": "sha512-Quz1KOffeEf/zwkCBM3kBtH4ZoZ+pT3xIXBG4PPW/XFtDP7EGhtTiC2+gpL9GnR7+Qdet5Oa6cYSvwKYg6kN9Q==", "engines": { "node": ">=14.0.0" } }, "node_modules/@restart/hooks": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", - "integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==", + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", "dependencies": { - "dequal": "^2.0.2" + "dequal": "^2.0.3" }, "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@restart/ui": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz", - "integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.8.tgz", + "integrity": "sha512-6ndCv3oZ7r9vuP1Ok9KH55TM1/UkdBnP/fSraW0DFDMbPMzWKhVKeFAIEUCRCSdzayjZDcFYK6xbMlipN9dmMA==", "dependencies": { "@babel/runtime": "^7.21.0", "@popperjs/core": "^2.11.6", @@ -1571,130 +1697,308 @@ } }, "node_modules/@restart/ui/node_modules/uncontrollable": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz", - "integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", "peerDependencies": { "react": ">=16.14.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@testing-library/dom": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", - "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", + "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@testing-library/jest-dom": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.4.tgz", - "integrity": "sha512-wpoYrCYwSZ5/AxcrjLxJmCU6I5QAJXslEeSiMQqaWmP2Kzpd1LvF/qxmAIW2qposULGWq2gw30GgVNFLSc2Jnw==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", + "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.3.1", - "@babel/runtime": "^7.9.2", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" - }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", + "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@testing-library/react": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", - "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", + "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@testing-library/user-event": { - "version": "14.5.1", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz", - "integrity": "sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", + "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", + "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", + "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", + "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", + "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", + "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", + "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", + "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", + "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.7.tgz", + "integrity": "sha512-BVvNZhx362+l2tSwSuyEUV4h7+jk9raNdoTSdLfwTshXJSaGmYKluGRJznziCI3KX02Z19DdsQrdfrpXAU3Hfg==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.0.0.tgz", + "integrity": "sha512-PmJPnogldqoVFf+EwbHvbBJ98MmqASV8kLrBYgsDNxQcFMeIS7JFL48sfyXvuMtgmWO/wMhh25odr+8VhDmn4g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.2.tgz", + "integrity": "sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==", "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" }, "peerDependencies": { - "@testing-library/dom": ">=7.21.4" + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/react": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.4.tgz", + "integrity": "sha512-Fw/LM1emOHKfCxv5R0tz+25TOtiMt0o5Np1zJmb4LbSacOagXQX4ooAaHiJfGUMe+OjUk504BX11W+9Z8CvyZA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, "node_modules/@types/aria-query": { @@ -1704,9 +2008,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -1717,18 +2021,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz", + "integrity": "sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -1736,9 +2040,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -1750,36 +2054,36 @@ "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", "dev": true }, - "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", - "dev": true - }, - "node_modules/@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", - "dev": true, - "dependencies": { - "@types/chai": "*" - } - }, "node_modules/@types/dompurify": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.4.tgz", - "integrity": "sha512-1Jk8S/IRzNSbwQRbuGuLFHviwxQ8pX81ZEW3INY9432Cwb4VedkBYan8gSIXVLOLHBtimOmUTEYphjRVmo+30g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", "dev": true, "dependencies": { "@types/trusted-types": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/history": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "dev": true }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -1805,9 +2109,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1853,9 +2157,15 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, "node_modules/@types/node": { @@ -1875,19 +2185,18 @@ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, "node_modules/@types/react": { - "version": "18.2.30", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.30.tgz", - "integrity": "sha512-OfqdJnDsSo4UNw0bqAjFCuBpLYQM7wvZidz0hVxHRjrEkzRlvZL1pJVyOSY55HMiKvRNEo9DUBRuEl7FNlJ/Vg==", + "version": "18.2.79", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", + "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "version": "18.2.25", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz", + "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==", "dev": true, "dependencies": { "@types/react": "*" @@ -1922,15 +2231,10 @@ "@types/react": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1946,15 +2250,15 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", - "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, "node_modules/@types/warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", - "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==" }, "node_modules/@types/yargs": { "version": "17.0.24", @@ -1972,33 +2276,33 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", + "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/type-utils": "7.7.1", + "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -2007,26 +2311,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", + "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -2035,16 +2339,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2052,25 +2356,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", + "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/utils": "7.7.1", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -2079,12 +2383,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2092,21 +2396,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -2118,100 +2423,132 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", + "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "semver": "^7.5.4" + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "semver": "^7.6.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.8.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.7.1", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-react": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.1.0.tgz", - "integrity": "sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", "dev": true, "dependencies": { - "@babel/core": "^7.22.20", - "@babel/plugin-transform-react-jsx-self": "^7.22.5", - "@babel/plugin-transform-react-jsx-source": "^7.22.5", - "@types/babel__core": "^7.20.2", + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^4.2.0" + "vite": "^4.2.0 || ^5.0.0" } }, "node_modules/@vitest/coverage-v8": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz", - "integrity": "sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.5.1.tgz", + "integrity": "sha512-Zx+dYEDcZg+44ksjIWvWosIGlPLJB1PPpN3O8+Xrh/1qa7WSFA6Y8H7lsZJTYrxu4G2unk9tvP5TgjIGDliF1w==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", "@bcoe/v8-coverage": "^0.2.3", - "istanbul-lib-coverage": "^3.2.0", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.1.5", - "magic-string": "^0.30.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.1.0" + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": ">=0.32.0 <1" + "vitest": "1.5.1" } }, "node_modules/@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.1.tgz", + "integrity": "sha512-w3Bn+VUMqku+oWmxvPhTE86uMTbfmBl35aGaIPlwVW7Q89ZREC/icfo2HBsEZ3AAW6YR9lObfZKPEzstw9tJOQ==", "dev": true, "dependencies": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", + "@vitest/spy": "1.5.1", + "@vitest/utils": "1.5.1", "chai": "^4.3.10" }, "funding": { @@ -2219,13 +2556,13 @@ } }, "node_modules/@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.1.tgz", + "integrity": "sha512-mt372zsz0vFR7L1xF/ert4t+teD66oSuXoTyaZbl0eJgilvyzCKP1tJ21gVa8cDklkBOM3DLnkE1ljj/BskyEw==", "dev": true, "dependencies": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", + "@vitest/utils": "1.5.1", + "p-limit": "^5.0.0", "pathe": "^1.1.1" }, "funding": { @@ -2233,15 +2570,15 @@ } }, "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, "dependencies": { "yocto-queue": "^1.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2260,14 +2597,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.1.tgz", + "integrity": "sha512-h/1SGaZYXmjn6hULRBOlqam2z4oTlEe6WwARRzLErAPBqljAs6eX7tfdyN0K+MpipIwSZ5sZsubDWkCPAiVXZQ==", "dev": true, "dependencies": { - "magic-string": "^0.30.1", + "magic-string": "^0.30.5", "pathe": "^1.1.1", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2306,26 +2643,27 @@ "dev": true }, "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.1.tgz", + "integrity": "sha512-vsqczk6uPJjmPLy6AEtqfbFqgLYcGBe9BTY+XL8L6y8vrGOhyE23CJN9P/hPimKXnScbqiZ/r/UtUSOQ2jIDGg==", "dev": true, "dependencies": { - "tinyspy": "^2.1.1" + "tinyspy": "^2.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.1.tgz", + "integrity": "sha512-92pE17bBXUxA0Y7goPcvnATMCuq4NQLOmqsG0e2BtzRi7KLwZB5jpiELi/8ybY8IQNWemKjSD5rMoO7xTdv8ug==", "dev": true, "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2363,16 +2701,10 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2391,35 +2723,34 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dev": true, "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -2427,6 +2758,18 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2452,57 +2795,57 @@ } }, "node_modules/antd": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.10.1.tgz", - "integrity": "sha512-alcBmeH4oAdmEdBs6EORH3onRFRjGYRkWtVjPyJxlTIfLILb/+S5Y+ZqisV3AobC8mlj6T3RV8aKG9ic6PgtzQ==", - "dependencies": { - "@ant-design/colors": "^7.0.0", - "@ant-design/cssinjs": "^1.17.2", - "@ant-design/icons": "^5.2.6", - "@ant-design/react-slick": "~1.0.2", - "@babel/runtime": "^7.18.3", + "version": "5.16.4", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.16.4.tgz", + "integrity": "sha512-H3LtVz5hiNgs0lL8U6pzi11rluR6RDRw1cm2pWX6CsvgZmybWsaTBV2h+d+zmgFfuch53TWs5uztLdAldIoYYw==", + "dependencies": { + "@ant-design/colors": "^7.0.2", + "@ant-design/cssinjs": "^1.18.5", + "@ant-design/icons": "^5.3.6", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.24.4", "@ctrl/tinycolor": "^3.6.1", - "@rc-component/color-picker": "~1.4.1", + "@rc-component/color-picker": "~1.5.3", "@rc-component/mutate-observer": "^1.1.0", - "@rc-component/tour": "~1.10.0", - "@rc-component/trigger": "^1.17.0", - "classnames": "^2.2.6", - "copy-to-clipboard": "^3.2.0", - "dayjs": "^1.11.1", + "@rc-component/tour": "~1.14.2", + "@rc-component/trigger": "^2.1.1", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.10", "qrcode.react": "^3.1.0", - "rc-cascader": "~3.18.1", - "rc-checkbox": "~3.1.0", - "rc-collapse": "~3.7.1", - "rc-dialog": "~9.3.3", - "rc-drawer": "~6.5.2", - "rc-dropdown": "~4.1.0", - "rc-field-form": "~1.39.0", - "rc-image": "~7.3.1", - "rc-input": "~1.2.1", - "rc-input-number": "~8.1.0", - "rc-mentions": "~2.8.0", - "rc-menu": "~9.12.2", + "rc-cascader": "~3.24.1", + "rc-checkbox": "~3.2.0", + "rc-collapse": "~3.7.3", + "rc-dialog": "~9.4.0", + "rc-drawer": "~7.1.0", + "rc-dropdown": "~4.2.0", + "rc-field-form": "~1.44.0", + "rc-image": "~7.6.0", + "rc-input": "~1.4.5", + "rc-input-number": "~9.0.0", + "rc-mentions": "~2.11.1", + "rc-menu": "~9.13.0", "rc-motion": "^2.9.0", - "rc-notification": "~5.2.0", - "rc-pagination": "~3.6.1", - "rc-picker": "~3.14.5", - "rc-progress": "~3.5.1", + "rc-notification": "~5.4.0", + "rc-pagination": "~4.0.4", + "rc-picker": "~4.4.1", + "rc-progress": "~4.0.0", "rc-rate": "~2.12.0", - "rc-resize-observer": "^1.3.1", - "rc-segmented": "~2.2.2", - "rc-select": "~14.9.1", - "rc-slider": "~10.3.0", + "rc-resize-observer": "^1.4.0", + "rc-segmented": "~2.3.0", + "rc-select": "~14.13.1", + "rc-slider": "~10.6.1", "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", - "rc-table": "~7.34.4", - "rc-tabs": "~12.12.1", - "rc-textarea": "~1.4.0", - "rc-tooltip": "~6.1.1", - "rc-tree": "~5.7.12", - "rc-tree-select": "~5.13.0", - "rc-upload": "~4.3.5", - "rc-util": "^5.38.0", - "scroll-into-view-if-needed": "^3.0.3", + "rc-table": "~7.45.4", + "rc-tabs": "~14.1.1", + "rc-textarea": "~1.6.3", + "rc-tooltip": "~6.2.0", + "rc-tree": "~5.8.5", + "rc-tree-select": "~5.19.0", + "rc-upload": "~4.5.2", + "rc-util": "^5.39.1", + "scroll-into-view-if-needed": "^3.1.0", "throttle-debounce": "^5.0.0" }, "funding": { @@ -2534,22 +2877,45 @@ "dev": true }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2569,6 +2935,129 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -2578,6 +3067,12 @@ "node": "*" } }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, "node_modules/async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", @@ -2590,10 +3085,13 @@ "dev": true }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2601,6 +3099,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -2637,9 +3153,9 @@ "dev": true }, "node_modules/bootstrap": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", - "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "funding": [ { "type": "github", @@ -2677,9 +3193,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", - "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -2696,9 +3212,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001539", - "electron-to-chromium": "^1.4.530", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -2708,6 +3224,15 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -2718,13 +3243,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2739,9 +3270,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001539", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001539.tgz", - "integrity": "sha512-hfS5tE8bnNiNvEOEkm8HElUHroYwlqMMENEzELymy77+tJ6m+gA2krtHl5hxJaj71OlpC2cHZbdSMX1/YEqEkA==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "dev": true, "funding": [ { @@ -2759,9 +3290,9 @@ ] }, "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", @@ -2859,9 +3390,40 @@ } }, "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/color-convert": { "version": "2.0.1", @@ -2881,6 +3443,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2893,10 +3461,19 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/compute-scroll-into-view": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", - "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", + "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -2953,34 +3530,90 @@ "dev": true }, "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", "dev": true, "dependencies": { "rrweb-cssom": "^0.6.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true }, "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/dayjs": { @@ -3023,53 +3656,44 @@ "node": ">=6" } }, - "node_modules/deep-equal": { + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", - "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.0", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -3098,9 +3722,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3136,11 +3760,6 @@ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, - "node_modules/dom-align": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", - "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==" - }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -3150,30 +3769,24 @@ "csstype": "^3.0.2" } }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/dompurify": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", - "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.0.tgz", + "integrity": "sha512-yoU4rhgPKCo+p5UrWWWNKiIq+ToGqmVVhk0PmMYBK4kRsR3/qhemNFL8f6CFmBd4gMwm3F4T7HBoydP5uY07fA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.530", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.530.tgz", - "integrity": "sha512-rsJ9O8SCI4etS8TBsXuRfHa2eZReJhnGf5MHZd3Vo05PukWHKXhk3VQGbHHnDLa8nZz9woPCpLCMQpLGgkGNRA==", + "version": "1.4.612", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.612.tgz", + "integrity": "sha512-dM8BMtXtlH237ecSMnYdYuCkib2QHq0kpWfUnavjdYsyr/6OsAwg5ZGUfnQ9KD1Ga4QgB2sqXlB2NT8zy2GnVg==", "dev": true }, - "node_modules/entities": { + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", @@ -3193,41 +3806,173 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-cookie": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.4.0.tgz", - "integrity": "sha512-V4bHxyGBmwwiV+CKTLUPLmwhcutTxGEC5n4HWaUDSnTvkNvfIjkMw8qIVTVgPeNCWojgR5IUzFnGenNvCoKQ5A==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.5.0.tgz", + "integrity": "sha512-fRv8TjgwY4/RmrP3kqQzfOwrQIMnAbQCHxSxqGVO1+3oWFsGYdIBOD8aqyALc/S4UY2wOIH894uvTDNP81tiyw==" }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/esbuild": { - "version": "0.18.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz", - "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -3237,28 +3982,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.11", - "@esbuild/android-arm64": "0.18.11", - "@esbuild/android-x64": "0.18.11", - "@esbuild/darwin-arm64": "0.18.11", - "@esbuild/darwin-x64": "0.18.11", - "@esbuild/freebsd-arm64": "0.18.11", - "@esbuild/freebsd-x64": "0.18.11", - "@esbuild/linux-arm": "0.18.11", - "@esbuild/linux-arm64": "0.18.11", - "@esbuild/linux-ia32": "0.18.11", - "@esbuild/linux-loong64": "0.18.11", - "@esbuild/linux-mips64el": "0.18.11", - "@esbuild/linux-ppc64": "0.18.11", - "@esbuild/linux-riscv64": "0.18.11", - "@esbuild/linux-s390x": "0.18.11", - "@esbuild/linux-x64": "0.18.11", - "@esbuild/netbsd-x64": "0.18.11", - "@esbuild/openbsd-x64": "0.18.11", - "@esbuild/sunos-x64": "0.18.11", - "@esbuild/win32-arm64": "0.18.11", - "@esbuild/win32-ia32": "0.18.11", - "@esbuild/win32-x64": "0.18.11" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/escalade": { @@ -3282,18 +4028,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3335,6 +4082,367 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-config-standard-jsx": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", + "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.8.0", + "eslint-plugin-react": "^7.28.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "dev": true, + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", @@ -3348,14 +4456,52 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.3.tgz", - "integrity": "sha512-Hh0wv8bUNY877+sI0BlCUlsS0TYYQqvzEwJsJJPM2WF4RnTStSnSR3zdJYa2nPOJgg3UghXi54lVyMSmpCalzA==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz", + "integrity": "sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==", "dev": true, "peerDependencies": { "eslint": ">=7" } }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -3372,18 +4518,91 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -3434,6 +4653,15 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3443,6 +4671,35 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/expect": { "version": "29.5.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", @@ -3462,13 +4719,18 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3560,12 +4822,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -3573,9 +4836,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/font-awesome": { @@ -3609,6 +4872,30 @@ "node": ">= 6" } }, + "node_modules/formik": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz", + "integrity": "sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3616,9 +4903,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3630,9 +4917,30 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -3652,6 +4960,18 @@ "node": ">=6.9.0" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -3662,15 +4982,60 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3709,18 +5074,30 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.0.0.tgz", + "integrity": "sha512-m/C/yR4mjO6pXDTm9/R/SpYTAIyaUB4EOzcaaMEl7mds7Mshct9GfejiJNQGjHHbdMPey13Kpu4TMbYi9ex1pw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "define-properties": "^1.1.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/globby": { @@ -3773,17 +5150,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -3803,21 +5169,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -3839,12 +5205,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -3853,6 +5219,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -3862,15 +5247,15 @@ } }, "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "dependencies": { - "whatwg-encoding": "^2.0.0" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/html-escaper": { @@ -3880,30 +5265,38 @@ "dev": true }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", "dev": true, "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dev": true, "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" } }, "node_modules/iconv-lite": { @@ -3919,9 +5312,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -3983,13 +5376,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -4004,14 +5397,14 @@ "loose-envify": "^1.0.0" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -4020,25 +5413,26 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -4091,21 +5485,84 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dependencies": { - "has": "^1.0.3" + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -4117,15 +5574,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4147,6 +5595,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -4212,17 +5672,32 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -4254,16 +5729,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4281,6 +5752,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakset": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", @@ -4294,6 +5777,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4301,9 +5790,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -4324,32 +5813,23 @@ } }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -4359,6 +5839,19 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/jest-diff": { "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", @@ -4558,40 +6051,38 @@ } }, "node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", + "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", "decimal.js": "^10.4.3", - "domexception": "^4.0.0", "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", + "nwsapi": "^2.2.7", "parse5": "^7.1.2", "rrweb-cssom": "^0.6.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", + "tough-cookie": "^4.1.3", + "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.16.0", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "peerDependencies": { - "canvas": "^2.5.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -4611,16 +6102,27 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4654,6 +6156,48 @@ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4667,16 +6211,141 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, "engines": { "node": ">=14" }, @@ -4702,8 +6371,12 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -4711,6 +6384,95 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4723,12 +6485,12 @@ } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/lru-cache": { @@ -4753,9 +6515,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", - "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -4764,6 +6526,17 @@ "node": ">=12" } }, + "node_modules/magicast": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.3.tgz", + "integrity": "sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "source-map-js": "^1.0.2" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -4773,28 +6546,85 @@ "semver": "^7.5.3" }, "engines": { - "node": ">=10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdownlint": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.34.0.tgz", + "integrity": "sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==", + "dev": true, + "dependencies": { + "markdown-it": "14.1.0", + "markdownlint-micromark": "0.1.9" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-micromark": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.9.tgz", + "integrity": "sha512-5hVs/DzAFa8XqYosbEAEg6ok6MF2smDj89ztn9pKkCtdKHVdPQuGMH7frFfYL9mLkvfFe4pTyAMffLbjf3/EyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" } }, "node_modules/marked": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.2.tgz", - "integrity": "sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 16" + "node": ">= 18" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4838,6 +6668,18 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -4859,6 +6701,15 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/mlly": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", @@ -4878,9 +6729,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -4902,9 +6753,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -4916,6 +6767,33 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", @@ -4931,22 +6809,33 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -4955,25 +6844,74 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { "node": ">= 0.4" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.hasown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4991,6 +6929,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -5038,6 +6991,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5151,6 +7113,101 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/pkg-types": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", @@ -5162,10 +7219,19 @@ "pathe": "^1.1.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -5182,9 +7248,9 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -5200,9 +7266,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -5214,6 +7280,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -5268,6 +7346,11 @@ "react": ">=0.14.0" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -5275,9 +7358,17 @@ "dev": true }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, "engines": { "node": ">=6" @@ -5317,33 +7408,17 @@ } ] }, - "node_modules/rc-align": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz", - "integrity": "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "dom-align": "^1.7.0", - "rc-util": "^5.26.0", - "resize-observer-polyfill": "^1.5.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, "node_modules/rc-cascader": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.18.1.tgz", - "integrity": "sha512-M7Xr5Fs/E87ZGustfObtBYQjsvBCET0UX2JYXB2GmOP+2fsZgjaRGXK+CJBmmWXQ6o4OFinpBQBXG4wJOQ5MEg==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.24.1.tgz", + "integrity": "sha512-RgKuYgEGPx+6wCgguYFHjMsDZdCyydZd58YJRCfYQ8FObqLnZW0x/vUcEyPjhWIj1EhjV958IcR+NFPDbbj9kg==", "dependencies": { "@babel/runtime": "^7.12.5", "array-tree-filter": "^2.1.0", "classnames": "^2.3.1", - "rc-select": "~14.9.0", - "rc-tree": "~5.7.0", - "rc-util": "^5.35.0" + "rc-select": "~14.13.0", + "rc-tree": "~5.8.1", + "rc-util": "^5.37.0" }, "peerDependencies": { "react": ">=16.9.0", @@ -5351,9 +7426,9 @@ } }, "node_modules/rc-checkbox": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.1.0.tgz", - "integrity": "sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.2.0.tgz", + "integrity": "sha512-8inzw4y9dAhZmv/Ydl59Qdy5tdp9CKg4oPVcRigi+ga/yKPZS5m5SyyQPtYSgbcqHRYOdUhiPSeKfktc76du1A==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.3.2", @@ -5365,9 +7440,9 @@ } }, "node_modules/rc-collapse": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.1.tgz", - "integrity": "sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz", + "integrity": "sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -5380,9 +7455,9 @@ } }, "node_modules/rc-dialog": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.3.3.tgz", - "integrity": "sha512-OpgzE0wq55ebN8TL/ZPc+MLY6qXswEuZg2/3uX3+lqjxUnVaH78PyntpJwqY+3BJdQkDj28XeXYRVY6gXQ8fNg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.4.0.tgz", + "integrity": "sha512-AScCexaLACvf8KZRqCPz12BJ8olszXOS4lKlkMyzDQHS1m0zj1KZMYgmMCh39ee0Dcv8kyrj8mTqxuLyhH+QuQ==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/portal": "^1.0.0-8", @@ -5396,15 +7471,15 @@ } }, "node_modules/rc-drawer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-6.5.2.tgz", - "integrity": "sha512-QckxAnQNdhh4vtmKN0ZwDf3iakO83W9eZcSKWYYTDv4qcD2fHhRAZJJ/OE6v2ZlQ2kSqCJX5gYssF4HJFvsEPQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.1.0.tgz", + "integrity": "sha512-nBE1rF5iZvpavoyqhSSz2mk/yANltA7g3aF0U45xkx381n3we/RKs9cJfNKp9mSWCedOKWt9FLEwZDaAaOGn2w==", "dependencies": { - "@babel/runtime": "^7.10.1", + "@babel/runtime": "^7.23.9", "@rc-component/portal": "^1.1.1", "classnames": "^2.2.6", "rc-motion": "^2.6.1", - "rc-util": "^5.36.0" + "rc-util": "^5.38.1" }, "peerDependencies": { "react": ">=16.9.0", @@ -5412,12 +7487,12 @@ } }, "node_modules/rc-dropdown": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.1.0.tgz", - "integrity": "sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz", + "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==", "dependencies": { "@babel/runtime": "^7.18.3", - "@rc-component/trigger": "^1.7.0", + "@rc-component/trigger": "^2.0.0", "classnames": "^2.2.6", "rc-util": "^5.17.0" }, @@ -5427,9 +7502,9 @@ } }, "node_modules/rc-field-form": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.39.0.tgz", - "integrity": "sha512-V7Wk7uji1jBsUGGgP788H9rpFy55HLiD4lywTlktUGjK7EgW5dt+mq1MPbtCpPRMzs83vZBW4SOChOmCACz4WA==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.44.0.tgz", + "integrity": "sha512-el7w87fyDUsca63Y/s8qJcq9kNkf/J5h+iTdqG5WsSHLH0e6Usl7QuYSmSVzJMgtp40mOVZIY/W/QP9zwrp1FA==", "dependencies": { "@babel/runtime": "^7.18.0", "async-validator": "^4.1.0", @@ -5444,14 +7519,14 @@ } }, "node_modules/rc-image": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.3.1.tgz", - "integrity": "sha512-Tu3vcUyMHa6zxTiQRzHt1glbGwuNWzeQBG9O6qIdy/+1ue0Qb70it+jUct1YPVNkJa/QfaTfUhmsNsqrw7mgsg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.6.0.tgz", + "integrity": "sha512-tL3Rvd1sS+frZQ01i+tkeUPaOeFz2iG9/scAt/Cfs0hyCRVA/w0Pu1J/JxIX8blalvmHE0bZQRYdOmRAzWu4Hg==", "dependencies": { "@babel/runtime": "^7.11.2", "@rc-component/portal": "^1.0.2", "classnames": "^2.2.6", - "rc-dialog": "~9.3.0", + "rc-dialog": "~9.4.0", "rc-motion": "^2.6.2", "rc-util": "^5.34.1" }, @@ -5461,9 +7536,9 @@ } }, "node_modules/rc-input": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.2.1.tgz", - "integrity": "sha512-nQRmBvEFoGi+SNRDavccZ8ueyhFgmxkWqIt4aDyuNJgUZF12HJKIwDhAafUM7N+g7PyuW9FH3pf3zPHzdiCWbA==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.4.5.tgz", + "integrity": "sha512-AjzykhwnwYTRSwwgCu70CGKBIAv6bP2nqnFptnNTprph/TF1BAs0Qxl91mie/BR6n827WIJB6ZjaRf9iiMwAfw==", "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", @@ -5475,14 +7550,14 @@ } }, "node_modules/rc-input-number": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.1.0.tgz", - "integrity": "sha512-bdHgduOxuN0lrhzgPmoKbhRD4GLIzVcddVz972/JHPHr7oLwPX5xDb9w4bXhuMzyT2VzQy7nggRCfH3yAl09oA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.0.0.tgz", + "integrity": "sha512-RfcDBDdWFFetouWFXBA+WPEC8LzBXyngr9b+yTLVIygfFu7HiLRGn/s/v9wwno94X7KFvnb28FNynMGj9XJlDQ==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/mini-decimal": "^1.0.1", "classnames": "^2.2.5", - "rc-input": "~1.2.1", + "rc-input": "~1.4.0", "rc-util": "^5.28.0" }, "peerDependencies": { @@ -5491,16 +7566,16 @@ } }, "node_modules/rc-mentions": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.8.0.tgz", - "integrity": "sha512-LBMkO6bSGhEvS1CvMK978qGN82tI+mzk7l/uTiQJH+UDiwpvq+pxK4DxU5b6Q1T5LW6bn2pSua9RaZKZrDoBOw==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.11.1.tgz", + "integrity": "sha512-upb4AK1SRFql7qGnbLEvJqLMugVVIyjmwBJW9L0eLoN9po4JmJZaBzmKA4089fNtsU8k6l/tdZiVafyooeKnLw==", "dependencies": { "@babel/runtime": "^7.22.5", - "@rc-component/trigger": "^1.5.0", + "@rc-component/trigger": "^2.0.0", "classnames": "^2.2.6", - "rc-input": "~1.2.1", - "rc-menu": "~9.12.0", - "rc-textarea": "~1.4.0", + "rc-input": "~1.4.0", + "rc-menu": "~9.13.0", + "rc-textarea": "~1.6.1", "rc-util": "^5.34.1" }, "peerDependencies": { @@ -5509,12 +7584,12 @@ } }, "node_modules/rc-menu": { - "version": "9.12.2", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.12.2.tgz", - "integrity": "sha512-NzloFH2pRUYmQ3S/YbJAvRkgCZaLvq0sRa5rgJtuIHLfPPprNHNyepeSlT64+dbVqI4qRWL44VN0lUCldCbbfg==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.13.0.tgz", + "integrity": "sha512-1l8ooCB3HcYJKCltC/s7OxRKRjgymdl9htrCeGZcXNaMct0RxZRK6OPV3lPhVksIvAGMgzPd54ClpZ5J4b8cZA==", "dependencies": { "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^1.17.0", + "@rc-component/trigger": "^2.0.0", "classnames": "2.x", "rc-motion": "^2.4.3", "rc-overflow": "^1.3.1", @@ -5540,9 +7615,9 @@ } }, "node_modules/rc-notification": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.2.0.tgz", - "integrity": "sha512-HwUSypEW4mfOpiakJ7dm6TAKf+3zuSR2xm0I0XMes493rtA3n4EVMvQyldrp23hUwCE3RFj8oncyU1E8iNC4ag==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.4.0.tgz", + "integrity": "sha512-li19y9RoYJciF3WRFvD+DvWS70jdL8Fr+Gfb/OshK+iY6iTkwzoigmSIp76/kWh5tF5i/i9im12X3nsF85GYdA==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -5573,13 +7648,13 @@ } }, "node_modules/rc-pagination": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.6.1.tgz", - "integrity": "sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.0.4.tgz", + "integrity": "sha512-GGrLT4NgG6wgJpT/hHIpL9nELv27A1XbSZzECIuQBQTVSf4xGKxWr6I/jhpRPauYEWEbWVw22ObG6tJQqwJqWQ==", "dependencies": { "@babel/runtime": "^7.10.1", - "classnames": "^2.2.1", - "rc-util": "^5.32.2" + "classnames": "^2.3.2", + "rc-util": "^5.38.0" }, "peerDependencies": { "react": ">=16.9.0", @@ -5587,14 +7662,16 @@ } }, "node_modules/rc-picker": { - "version": "3.14.5", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-3.14.5.tgz", - "integrity": "sha512-h0O8b5AYfWwHSRUUH/9F2oBXB5gZerHIyGG6z2r5rn/kfSQodyCXEO4GNqrG30iUC1qkvLFIOn/JqI4XaO0+2A==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.4.2.tgz", + "integrity": "sha512-MdbAXvwiGyhb+bHe66qPps8xPQivzEgcyCp3/MPK4T+oER0gOmVRCEDxaD4FhYG/7GLH3rDrHpu79BvEn2JFTQ==", "dependencies": { "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^1.5.0", + "@rc-component/trigger": "^2.0.0", "classnames": "^2.2.1", - "rc-util": "^5.30.0" + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.38.1" }, "engines": { "node": ">=8.x" @@ -5623,9 +7700,9 @@ } }, "node_modules/rc-progress": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.5.1.tgz", - "integrity": "sha512-V6Amx6SbLRwPin/oD+k1vbPrO8+9Qf8zW1T8A7o83HdNafEVvAxPV5YsgtKFP+Ud5HghLj33zKOcEHrcrUGkfw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", @@ -5654,13 +7731,13 @@ } }, "node_modules/rc-resize-observer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz", - "integrity": "sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", + "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==", "dependencies": { "@babel/runtime": "^7.20.7", "classnames": "^2.2.1", - "rc-util": "^5.27.0", + "rc-util": "^5.38.0", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { @@ -5669,9 +7746,9 @@ } }, "node_modules/rc-segmented": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.2.2.tgz", - "integrity": "sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.3.0.tgz", + "integrity": "sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==", "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", @@ -5684,12 +7761,12 @@ } }, "node_modules/rc-select": { - "version": "14.9.2", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.9.2.tgz", - "integrity": "sha512-VQ15sRFgPURHb8ZcZNSDtb2rAw3+C9xlL0nDziwNHTEW1KvEpZ8y+0v5w24X/Bpl9b3cW1BOyW1F5UqSAq+7Dg==", + "version": "14.13.1", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.13.1.tgz", + "integrity": "sha512-A1VHqjIOemxLnUGRxLGVqXBs8jGcJemI5NXxOJwU5PQc1wigAu1T4PRLgMkTPDOz8gPhlY9dwsPzMgakMc2QjQ==", "dependencies": { "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^1.5.0", + "@rc-component/trigger": "^2.1.1", "classnames": "2.x", "rc-motion": "^2.0.1", "rc-overflow": "^1.3.1", @@ -5705,13 +7782,13 @@ } }, "node_modules/rc-slider": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.3.0.tgz", - "integrity": "sha512-kt8ehfvPLoZFYJS3Caaf3l+9OF8JUyexC84qy878vf9rOy9IulO/PEdha8E90i8mnj4mtJMSxojk1fJGkYWjpQ==", + "version": "10.6.2", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz", + "integrity": "sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", - "rc-util": "^5.27.0" + "rc-util": "^5.36.0" }, "engines": { "node": ">=8.x" @@ -5753,15 +7830,15 @@ } }, "node_modules/rc-table": { - "version": "7.34.4", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.34.4.tgz", - "integrity": "sha512-os+i88Y2AO/6dNkOgJkKSHgXYaZZGnuOEEe+nyaq5IRgvAQNhLysUjXt2objtBeFDEZR8TqXrajwBNRUwunmdw==", + "version": "7.45.4", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.45.4.tgz", + "integrity": "sha512-6aSbGrnkN2GLSt3s1x+wa4f3j/VEgg1uKPpaLY5qHH1/nFyreS2V7DFJ0TfUb18allf2FQl7oVYEjTixlBXEyQ==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/context": "^1.4.0", "classnames": "^2.2.5", "rc-resize-observer": "^1.1.0", - "rc-util": "^5.36.0", + "rc-util": "^5.37.0", "rc-virtual-list": "^3.11.1" }, "engines": { @@ -5773,14 +7850,14 @@ } }, "node_modules/rc-tabs": { - "version": "12.12.1", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.12.1.tgz", - "integrity": "sha512-e10VBjEkECdPl4XZSs9to81SE+mgclBTM7J8/LMsFqmJoi05Tci91bRnmeeDtrcOCx2PuZdJv57XUlC4d8PEIw==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-14.1.1.tgz", + "integrity": "sha512-5nOr9PVpJy2SWHTLgv1+kESDOb0tFzl0cYU9r9d8LfL0Wg9i/n1B558rmkxdQHgBwMqxmwoyPSAbQROxMQe8nw==", "dependencies": { "@babel/runtime": "^7.11.2", "classnames": "2.x", - "rc-dropdown": "~4.1.0", - "rc-menu": "~9.12.0", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.13.0", "rc-motion": "^2.6.2", "rc-resize-observer": "^1.0.0", "rc-util": "^5.34.1" @@ -5794,13 +7871,13 @@ } }, "node_modules/rc-textarea": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.4.0.tgz", - "integrity": "sha512-CiqK+uyoJlnfufbC0kwfHJpfElhQacuDSNyNQ/xGnA/QMaJLDbgmqRT8QmX0T0KD/ws/hy6qqRaGJSsrRR5uiQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.6.3.tgz", + "integrity": "sha512-8k7+8Y2GJ/cQLiClFMg8kUXOOdvcFQrnGeSchOvI2ZMIVvX5a3zQpLxoODL0HTrvU63fPkRmMuqaEcOF9dQemA==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", - "rc-input": "~1.2.1", + "rc-input": "~1.4.0", "rc-resize-observer": "^1.0.0", "rc-util": "^5.27.0" }, @@ -5810,12 +7887,12 @@ } }, "node_modules/rc-tooltip": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.1.1.tgz", - "integrity": "sha512-YoxL0Ev4htsX37qgN23eKr0L5PIRpZaLVL9GX6aJ4x6UEnwgXZYUNCAEHfKlKT3eD1felDq3ob4+Cn9lprLDBw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.0.tgz", + "integrity": "sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==", "dependencies": { "@babel/runtime": "^7.11.2", - "@rc-component/trigger": "^1.17.0", + "@rc-component/trigger": "^2.0.0", "classnames": "^2.3.1" }, "peerDependencies": { @@ -5824,9 +7901,9 @@ } }, "node_modules/rc-tree": { - "version": "5.7.12", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.12.tgz", - "integrity": "sha512-LXA5nY2hG5koIAlHW5sgXgLpOMz+bFRbnZZ+cCg0tQs4Wv1AmY7EDi1SK7iFXhslYockbqUerQan82jljoaItg==", + "version": "5.8.5", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.5.tgz", + "integrity": "sha512-PRfcZtVDNkR7oh26RuNe1hpw11c1wfgzwmPFL0lnxGnYefe9lDAO6cg5wJKIAwyXFVt5zHgpjYmaz0CPy1ZtKg==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -5843,14 +7920,14 @@ } }, "node_modules/rc-tree-select": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.13.0.tgz", - "integrity": "sha512-g01JU9EdE7j/9KfDKtmvFqJ7ZDNIYDzkpmAXllbTBFoRNhWJBjW1x/dCZLVG+IdZeIz8SKJkgZzCf1CUZrzV/Q==", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.19.0.tgz", + "integrity": "sha512-f4l5EsmSGF3ggj76YTzKNPY9SnXfFaer7ZccTSGb3urUf54L+cCqyT+UsPr+S5TAr8mZSxJ7g3CgkCe+cVQ6sw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", - "rc-select": "~14.9.0", - "rc-tree": "~5.7.0", + "rc-select": "~14.13.0", + "rc-tree": "~5.8.1", "rc-util": "^5.16.1" }, "peerDependencies": { @@ -5859,9 +7936,9 @@ } }, "node_modules/rc-upload": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.5.tgz", - "integrity": "sha512-EHlKJbhkgFSQHliTj9v/2K5aEuFwfUQgZARzD7AmAPOneZEPiCNF3n6PEWIuqz9h7oq6FuXgdR67sC5BWFxJbA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.5.2.tgz", + "integrity": "sha512-QO3ne77DwnAPKFn0bA5qJM81QBjQi0e0NHdkvpFyY73Bea2NfITiotqJqVjHgeYPOJu5lLVR32TNGP084aSoXA==", "dependencies": { "@babel/runtime": "^7.18.3", "classnames": "^2.2.5", @@ -5873,9 +7950,9 @@ } }, "node_modules/rc-util": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.38.0.tgz", - "integrity": "sha512-yV/YBNdFn+edyBpBdCqkPE29Su0jWcHNgwx2dJbRqMrMfrUcMJUjCRV+ZPhcvWyKFJ63GzEerPrz9JIVo0zXmA==", + "version": "5.39.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.39.1.tgz", + "integrity": "sha512-OW/ERynNDgNr4y0oiFmtes3rbEamXw7GHGbkbNd9iRr7kgT03T6fT0b9WpJ3mbxKhyOcAHnGcIoh5u/cjrC2OQ==", "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" @@ -5891,9 +7968,9 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/rc-virtual-list": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.11.2.tgz", - "integrity": "sha512-MTFLL2LOHr3+/+r+WjTIs6j8XmJE6EqdOsJvCH8SWig7qyik3aljCEImUtw5tdWR0tQhXUfbv7P7nZaLY91XPg==", + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.11.4.tgz", + "integrity": "sha512-NbBi0fvyIu26gP69nQBiWgUMTPX3mr4FcuBQiVqagU0BnuX8WQkiivnMs105JROeuUIFczLrlgUhLQwTWV1XDA==", "dependencies": { "@babel/runtime": "^7.20.0", "classnames": "^2.2.6", @@ -5904,8 +7981,8 @@ "node": ">=8.x" }, "peerDependencies": { - "react": "*", - "react-dom": "*" + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, "node_modules/react": { @@ -5920,13 +7997,13 @@ } }, "node_modules/react-bootstrap": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.9.0.tgz", - "integrity": "sha512-dGh6fGjqR9MBzPOp2KbXJznt1Zy6SWepXYUdxMT18Zu/wJ73HCU8JNZe9dfzjmVssZYsJH9N3HHE4wAtQvNz7g==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.2.tgz", + "integrity": "sha512-UvB7mRqQjivdZNxJNEA2yOQRB7L9N43nBnKc33K47+cH90/ujmnMwatTCwQLu83gLhrzAl8fsa6Lqig/KLghaA==", "dependencies": { "@babel/runtime": "^7.22.5", "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.6.6", + "@restart/ui": "^1.6.8", "@types/react-transition-group": "^4.4.6", "classnames": "^2.3.2", "dom-helpers": "^5.2.1", @@ -5949,9 +8026,9 @@ } }, "node_modules/react-bootstrap-icons": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/react-bootstrap-icons/-/react-bootstrap-icons-1.10.3.tgz", - "integrity": "sha512-j4hSby6gT9/enhl3ybB1tfr1slZNAYXDVntcRrmVjxB3//2WwqrzpESVqKhyayYVaWpEtnwf9wgUQ03cuziwrw==", + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/react-bootstrap-icons/-/react-bootstrap-icons-1.11.4.tgz", + "integrity": "sha512-lnkOpNEZ/Zr7mNxvjA9efuarCPSgtOuGA55XiRj7ASJnBjb1wEAdtJOd2Aiv9t07r7FLI1IgyZPg9P6jqWD/IA==", "dependencies": { "prop-types": "^15.7.2" }, @@ -5971,6 +8048,11 @@ "react": "^18.2.0" } }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5991,11 +8073,11 @@ } }, "node_modules/react-router": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.17.0.tgz", - "integrity": "sha512-YJR3OTJzi3zhqeJYADHANCGPUu9J+6fT5GLv82UWRGSxu6oJYCKVmxUcaBQuGm9udpWmPsvpme/CdHumqgsoaA==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.0.tgz", + "integrity": "sha512-wPMZ8S2TuPadH0sF5irFGjkNLIcRvOSaEe7v+JER8508dyJumm6XZB1u5kztlX0RVq6AzRVndzqcUh6sFIauzA==", "dependencies": { - "@remix-run/router": "1.10.0" + "@remix-run/router": "1.16.0" }, "engines": { "node": ">=14.0.0" @@ -6005,12 +8087,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.17.0.tgz", - "integrity": "sha512-qWHkkbXQX+6li0COUUPKAUkxjNNqPJuiBd27dVwQGDNsuFBdMbrS6UZ0CLYc4CsbdLYTckn4oB4tGDuPZpPhaQ==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.0.tgz", + "integrity": "sha512-Q9YaSYvubwgbal2c9DJKfx6hTNoBp3iJDsl+Duva/DwxoJH+OTXkxGpql4iUK2sla/8z4RpjAm6EWx1qUDuopQ==", "dependencies": { - "@remix-run/router": "1.10.0", - "react-router": "6.17.0" + "@remix-run/router": "1.16.0", + "react-router": "6.23.0" }, "engines": { "node": ">=14.0.0" @@ -6021,9 +8103,9 @@ } }, "node_modules/react-select": { - "version": "5.7.7", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.7.tgz", - "integrity": "sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.0.tgz", + "integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==", "dependencies": { "@babel/runtime": "^7.12.0", "@emotion/cache": "^11.4.0", @@ -6077,23 +8159,45 @@ "strip-indent": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -6102,6 +8206,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -6137,6 +8261,52 @@ "node": ">=4" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6147,6 +8317,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6163,18 +8339,34 @@ } }, "node_modules/rollup": { - "version": "3.27.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.27.2.tgz", - "integrity": "sha512-YGwmHf7h2oUHkVBT248x0yt6vZkYQ3/rvE5iQuVBh3WO8GcJ6BNeOkpoX1yMHIiBm18EMLjBPIoUDkhgnyxGOQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", + "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.13.0", + "@rollup/rollup-android-arm64": "4.13.0", + "@rollup/rollup-darwin-arm64": "4.13.0", + "@rollup/rollup-darwin-x64": "4.13.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", + "@rollup/rollup-linux-arm64-gnu": "4.13.0", + "@rollup/rollup-linux-arm64-musl": "4.13.0", + "@rollup/rollup-linux-riscv64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-musl": "4.13.0", + "@rollup/rollup-win32-arm64-msvc": "4.13.0", + "@rollup/rollup-win32-ia32-msvc": "4.13.0", + "@rollup/rollup-win32-x64-msvc": "4.13.0", "fsevents": "~2.3.2" } }, @@ -6207,6 +8399,41 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -6251,17 +8478,17 @@ } }, "node_modules/scroll-into-view-if-needed": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", - "integrity": "sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6273,6 +8500,38 @@ "node": ">=10" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6295,14 +8554,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6314,6 +8577,28 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-git-hooks": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/simple-git-hooks/-/simple-git-hooks-2.11.1.tgz", + "integrity": "sha512-tgqwPUMDcNDhuf1Xf6KTUsyeqGdgKMhzaH4PAZZuzguOgTl5uuyeYe/8mWgAr6IBxB5V06uqEf6Dy37gIWDtDg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "simple-git-hooks": "cli.js" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6323,6 +8608,34 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -6332,9 +8645,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -6367,29 +8680,217 @@ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, + "node_modules/standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", + "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "eslint": "^8.41.0", + "eslint-config-standard": "17.1.0", + "eslint-config-standard-jsx": "^11.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.32.2", + "standard-engine": "^15.0.0", + "version-guard": "^1.1.1" + }, + "bin": { + "standard": "bin/cmd.cjs" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/standard-engine": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", + "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.6", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/std-env": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz", - "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", + "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, + "node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "internal-slot": "^1.0.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6402,6 +8903,27 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -6427,17 +8949,23 @@ } }, "node_modules/strip-literal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", - "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", + "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", "dev": true, "dependencies": { - "acorn": "^8.8.2" + "js-tokens": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "dev": true + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -6472,6 +9000,22 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -6500,25 +9044,35 @@ "node": ">=12.22" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "node_modules/tinybench": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", - "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", "dev": true }, "node_modules/tinypool": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", - "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.3.tgz", + "integrity": "sha512-Ud7uepAklqRH1bvwy22ynrliC7Dljz7Tm8M/0RBUW+YRa4YHhZ6e4PpgE+fu1zr/WqB1kbeuVrdfeuyIBpy4tw==", "dev": true, "engines": { "node": ">=14.0.0" } }, "node_modules/tinyspy": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", - "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", "dev": true, "engines": { "node": ">=14.0.0" @@ -6549,6 +9103,11 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, "node_modules/tough-cookie": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", @@ -6565,42 +9124,50 @@ } }, "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "dependencies": { - "punycode": "^2.3.0" + "punycode": "^2.3.1" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" } }, + "node_modules/ts-md5": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-1.3.1.tgz", + "integrity": "sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg==", + "engines": { + "node": ">=12" + } + }, "node_modules/tsconfck": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-2.1.1.tgz", - "integrity": "sha512-ZPCkJBKASZBmBUNqGHmRhdhM8pJYDdOXp4nRgj/O0JwUwsMq50lCDRQP/M5GBNAA0elPrq4gAeu4dkaVCuKWww==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.0.3.tgz", + "integrity": "sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==", "dev": true, "bin": { "tsconfck": "bin/tsconfck.js" }, "engines": { - "node": "^14.13.1 || ^16 || >=18" + "node": "^18 || >=20" }, "peerDependencies": { - "typescript": "^4.3.5 || ^5.0.0" + "typescript": "^5.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -6608,6 +9175,35 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6641,10 +9237,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6654,12 +9323,59 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.7.1.tgz", + "integrity": "sha512-ykEBfa3xx3odjZy6GRED4SCPrjo0rgHwstLlEgLX4EMEuv7QeIDSmfV+S6Kk+XkbsYn4BDEcPvsci1X26lRpMQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.7.1", + "@typescript-eslint/parser": "7.7.1", + "@typescript-eslint/utils": "7.7.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, "node_modules/ufo": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", - "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "dev": true }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/uncontrollable": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", @@ -6717,7 +9433,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -6757,44 +9472,39 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "node_modules/version-guard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.2.tgz", + "integrity": "sha512-D8d+YxCUpoqtCnQzDxm6SF7DLU3gr2535T4khAtMq4osBahsQnmSxuwXFdrbAdDGG8Uokzfis/jvyeFPdmlc7w==", "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, "engines": { - "node": ">=10.12.0" + "node": ">=0.10.48" } }, "node_modules/vite": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", - "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", + "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", @@ -6827,37 +9537,36 @@ } }, "node_modules/vite-node": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", - "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.1.tgz", + "integrity": "sha512-HNpfV7BrAsjkYVNWIcPleJwvJmydJqqJRrRbpoQ/U7QDwJKyEzNa4g5aYg8MjXJyKsk29IUCcMLFRcsEvqUIsA==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", - "mlly": "^1.4.0", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": ">=v14.18.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/vite-tsconfig-paths": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.1.tgz", - "integrity": "sha512-GNUI6ZgPqT3oervkvzU+qtys83+75N/OuDaQl7HmOqFTb0pjZsuARrRipsyJhJ3enqV8beI1xhGbToR4o78nSQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", + "integrity": "sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==", "dev": true, "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", - "tsconfck": "^2.1.0" + "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" @@ -6869,59 +9578,56 @@ } }, "node_modules/vitest": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", - "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.1.tgz", + "integrity": "sha512-3GvBMpoRnUNbZRX1L3mJCv3Ou3NAobb4dM48y8k9ZGwDofePpclTOyO+lqJFKSQpubH1V8tEcAEw/Y3mJKGJQQ==", "dev": true, "dependencies": { - "@types/chai": "^4.3.5", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.34.6", - "@vitest/runner": "0.34.6", - "@vitest/snapshot": "0.34.6", - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "acorn": "^8.9.0", - "acorn-walk": "^8.2.0", - "cac": "^6.7.14", + "@vitest/expect": "1.5.1", + "@vitest/runner": "1.5.1", + "@vitest/snapshot": "1.5.1", + "@vitest/spy": "1.5.1", + "@vitest/utils": "1.5.1", + "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.1", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "strip-literal": "^1.0.1", - "tinybench": "^2.5.0", - "tinypool": "^0.7.0", - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", - "vite-node": "0.34.6", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.5.1", "why-is-node-running": "^2.2.2" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": ">=v14.18.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.5.1", + "@vitest/ui": "1.5.1", "happy-dom": "*", - "jsdom": "*", - "playwright": "*", - "safaridriver": "*", - "webdriverio": "*" + "jsdom": "*" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@types/node": { + "optional": true + }, "@vitest/browser": { "optional": true }, @@ -6933,28 +9639,19 @@ }, "jsdom": { "optional": true - }, - "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true } } }, "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "dependencies": { - "xml-name-validator": "^4.0.0" + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/warning": { @@ -6975,37 +9672,37 @@ } }, "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "dependencies": { - "tr46": "^4.1.1", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/which": { @@ -7039,6 +9736,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", @@ -7055,17 +9778,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7090,6 +9812,62 @@ "node": ">=8" } }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -7097,9 +9875,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "dev": true, "engines": { "node": ">=10.0.0" @@ -7117,13 +9895,22 @@ } } }, - "node_modules/xml-name-validator": { + "node_modules/xdg-basedir": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true, "engines": { - "node": ">=12" + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" } }, "node_modules/xmlchars": { @@ -7157,6 +9944,28 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/vite-app/package.json b/vite-app/package.json index f3eceb8b4..ee82b6de3 100644 --- a/vite-app/package.json +++ b/vite-app/package.json @@ -1,5 +1,5 @@ { - "name": "vite-app", + "name": "kbase-ui", "private": true, "version": "0.0.0", "type": "module", @@ -11,45 +11,76 @@ "test": "vitest run --coverage " }, "dependencies": { - "@ant-design/icons": "5.2.6", - "antd": "5.10.1", - "bootstrap": "5.3.2", - "dompurify": "3.0.6", - "es-cookie": "1.4.0", + "@ant-design/icons": "5.3.6", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-regular-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", + "@fortawesome/react-fontawesome": "0.2.0", + "ajv": "8.12.0", + "antd": "5.16.4", + "bootstrap": "5.3.3", + "dompurify": "3.1.0", + "es-cookie": "1.5.0", "font-awesome": "4.7.0", - "marked": "9.1.2", + "formik": "2.4.5", + "highlight.js": "11.9.0", + "marked": "12.0.2", "react": "18.2.0", - "react-bootstrap": "2.9.0", - "react-bootstrap-icons": "1.10.3", + "react-bootstrap": "2.10.2", + "react-bootstrap-icons": "1.11.4", "react-dom": "18.2.0", - "react-router-dom": "6.17.0", - "react-select": "5.7.7", - "uuid": "9.0.1" + "react-router-dom": "6.23.0", + "react-select": "5.8.0", + "ts-md5": "1.3.1", + "uuid": "9.0.1", + "yup": "1.4.0" }, "devDependencies": { + "@eslint/js": "9.0.0", "@kbase/ui-lib": "0.7.1", - "@testing-library/jest-dom": "6.1.4", - "@testing-library/react": "14.0.0", - "@testing-library/user-event": "14.5.1", - "@types/dompurify": "3.0.4", - "@types/jest": "29.5.6", - "@types/react": "18.2.30", - "@types/react-dom": "18.2.14", + "@testing-library/jest-dom": "6.4.2", + "@testing-library/react": "15.0.4", + "@testing-library/user-event": "14.5.2", + "@types/dompurify": "3.0.5", + "@types/jest": "29.5.12", + "@types/react": "18.2.79", + "@types/react-dom": "18.2.25", "@types/react-router-dom": "5.3.3", - "@types/uuid": "9.0.6", - "@typescript-eslint/eslint-plugin": "6.8.0", - "@typescript-eslint/parser": "6.8.0", - "@vitejs/plugin-react": "4.1.0", - "@vitest/coverage-v8": "0.34.6", - "eslint": "8.51.0", + "@types/uuid": "9.0.8", + "@typescript-eslint/eslint-plugin": "7.7.1", + "@typescript-eslint/parser": "7.7.1", + "@vitejs/plugin-react": "4.2.1", + "@vitest/coverage-v8": "1.5.1", + "eslint": "8.57.0", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-import": "2.29.1", + "eslint-plugin-jsx-a11y": "6.8.0", + "eslint-plugin-prettier": "5.1.3", + "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-react-refresh": "0.4.3", - "jsdom": "22.1.0", - "prettier": "3.0.3", + "eslint-plugin-react-refresh": "0.4.6", + "globals": "15.0.0", + "jsdom": "24.0.0", + "lint-staged": "15.2.2", + "markdownlint": "0.34.0", + "prettier": "3.2.5", "sass": "1.64.", - "typescript": "5.2.2", - "vite": "4.5.0", - "vite-tsconfig-paths": "4.2.1", - "vitest": "0.34.6" + "simple-git-hooks": "2.11.1", + "standard": "17.1.0", + "typescript": "5.4.5", + "typescript-eslint": "7.7.1", + "vite": "5.2.10", + "vite-tsconfig-paths": "4.3.2", + "vitest": "1.5.1" + }, + "lint-staged": { + "src/**/*.{js,jsx,ts,tsx}": [ + "eslint", + "prettier", + "vitest --passWithNoTests" + ] + }, + "simple-git-hooks": { + "pre-commit": "cd vite-app && npx lint-staged" } -} \ No newline at end of file +} diff --git a/vite-app/public/css/kb-icons.css b/vite-app/public/css/kb-icons.css index a7b854cfa..d455fbf8c 100644 --- a/vite-app/public/css/kb-icons.css +++ b/vite-app/public/css/kb-icons.css @@ -1,6 +1,7 @@ /* ICONS FROM NARRATIVE kbaseIcons.css */ @charset "UTF-8"; + @font-face { font-family: "kbase-icons"; src: url("icons/kbase-icons.eot"); @@ -16,7 +17,6 @@ font-weight: normal !important; font-variant: normal !important; text-transform: none !important; - speak: none; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -30,7 +30,6 @@ font-variant: normal !important; text-transform: none !important; vertical-align: top; - speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } diff --git a/vite-app/public/data/__perf__/0b.txt b/vite-app/public/data/__perf__/0b.txt new file mode 100644 index 000000000..e69de29bb diff --git a/vite-app/public/js/gtagSupport.js b/vite-app/public/js/gtagSupport.js deleted file mode 100644 index 9e78f0bbf..000000000 --- a/vite-app/public/js/gtagSupport.js +++ /dev/null @@ -1,443 +0,0 @@ -/** - * Google Analytics (GA) app implementation - * - * The GA mechanism for sending data to the GA collection service - * consists of a very simple, small web app. - * - * Upon loading the primary kbase-ui SPA index.html page, an embedded - * script call to Google loads a GA app which loads necessary support - * files and begins to monitor a global variable "window.dataLayer". - * - * (Why Goggle didn't pick something namespaced to their app like - * GoogleDataLayer, or GoogleAnalyticsDataQueue, I don't know.) - * - * Then, when data is to be sent to GA for a page load (all that we use it for), - * this script below pushes (in the sense of "array push") the appropriate - * data in the appropriate format into the global data queue "dataLayer". - * - * On the next polling call, the GA app pulls the data off the queue and sends it - * to the GA collection service. - * - * Quite straightforward. - * - * Now for our implementation. - * - * First, there is no good reason for the code to be in a standalone file, afaik, - * and it is a bit complicated by the fact that it has to replicate functionality - * in kbase-ui, but here it is. - * - * The script has the general task of sending, for the initial page load and every - * subsequent navigation, the: - * - current url - * - current page path - * - current page title - * - username if there is a valid kbase auth token - * - * There a few complications in this otherwise relatively straightforward task. - * - * Since this script is independent of kbase-ui, it must be configured manually, - * including the auth token name, urls, Google GA ids, and other. - * - * Fetching the username requires a call to the auth service. Since this - * script is independent of kbase-ui, it must perform this logic separately. - * To prevent calling the auth service with every navigation, the token is - * cached for 10 minutes. - * - * The page title is not available until the view code associated with the page load - * or navigation has run and determined and set the title. In other words, it is - * asynchronous, and may take even up to a few seconds. To accommodate this fact, - * the script will monitor the page title and only set the GA data when the title - * has been stable for some period of time (TITLE_STABILIZATION_PERIOD). If navigation - * occurs before the title has stabilized, the GA data is sent anyway - * - * References: - * https://developers.google.com/tag-platform/gtagjs/reference - * https://developers.google.com/analytics/devguides/collection/gtagjs/single-page-applications#measure_virtual_pageviews - */ - -function main() { - // Configuration - // These should be in a separate configuration, but, to be honest, some of these values have never changed, and others, - // like the Google tags, only every few years. - const SESSION_COOKIE_NAME = 'kbase_session'; - const PROD_UI_ORIGIN = 'https://narrative.kbase.us'; - const PROD_SERVICE_ORIGIN = 'https://kbase.us'; - const GOOGLE_GTAG = 'G-KXZCE6YQFZ'; - const GOOGLE_AD_TAG = 'AW-753507180'; - - // The sending of the page hit is delayed until the page title stops change for the duration - // set here. - const TITLE_STABILIZATION_PERIOD = 3000; - - // Keep the auth token cached for up to 10 minutes. - const KBASE_AUTH_TOKEN_TTL = 600000; - let KBASE_AUTH_INFO_EXPIRES_AT = null; - let KBASE_AUTH_INFO = null; - let KBASE_AUTH_TOKEN = null; - - /** - * GTag processing states. - * - * Due to the asynchronous nature of loading page titles, and generally the fact that this code - * runs independently of the kbase-ui, which is of course asynchronous in nature, we use a - * little state model to manage this. - * - */ - const WAITING = 'WAITING'; - const PENDING = 'PENDING'; - const SEND_NOW = 'SEND_NOW'; - const SENDING = 'SENDING'; - let GTAG_STATE = WAITING; - - // Simply ensures that the data layer exists. - window.dataLayer = window.dataLayer || []; - - /** - * Sets a new status value, which should be one of WAITING, PENDING, SEND_NOW, or SENDING. - * - * @param {string} newState The new value for the gtag support status - */ - function setState(newState) { - GTAG_STATE = newState; - } - - /** - * Simply compares the provided value to the current status value, returning whether they are the same. - * - * @param {string} state - * @returns {boolean} Whether the provided value is the same as the current status - */ - function isState(state) { - return GTAG_STATE === state; - } - - /** - * Returns a promise that does not resolve until the given status is active. - * - * - * @param {*} status A status value, as defined above: WAITING, PENDING, SEND_NOW, SENDING - * @returns {Promise} A Promise with no important value - */ - // TODO there should be a timeout - async function waitUntilStatus(status, timeout) { - const started = Date.now(); - const timeoutAfter = started + timeout; - return new Promise((resolve) => { - const loop = () => { - if (Date.now() >= timeoutAfter) { - throw new Error(`Timed out after ${Date.now() - started}`); - } - window.setTimeout(() => { - if (isState(status)) { - loop(); - } - resolve(); - }, 100); - }; - loop(); - }); - } - - /** - * Returns the KBase service origin. - * - * In all but production, the service origin is the same as the document origin - * for the ui. In production, the ui origin is https://narrative.kbase.us but the - * service origin is https://kbase.us - this adjustment is made. - * - * @returns {string} The KBase service "origin" (protocol and hostname, e.g. https://ci.kbase.us) - */ - function getServiceOrigin() { - if (document.location.origin === PROD_UI_ORIGIN) { - return PROD_SERVICE_ORIGIN; - } - return document.location.origin; - } - - /** - * The canonical function name for queuing messages for the Google gtag app. - * - * Note that the function relies up on the usage of the magic "arguments" variable - * provided to all functions. - * - * @returns {void} - Nothing - */ - function pushGTag() { - //developers.google.com/tag-platform/tag-manager/datalayer - window.dataLayer.push(arguments); - } - - /** - * Get and return the current hash path as a path with a leading - * forward slash (/). - * - * Note that this code is could be a one-liner but for the fact that - * some usages of kbase-ui hash-paths place the search query string - * on the hash itself. - * - * @returns {string} - The current navigation path in kbase-ui - */ - function getHashPath() { - const hash = document.location.hash; - let path; - if (hash) { - const m = hash.match(/#[/]?([^?]*)/); - if (m) { - path = m[1]; - } else { - path = ''; - } - } else { - path = ''; - } - return `/${path}`; - } - - /** - * Find KBase auth token from document cookie. - * - * If a token is not found in the cookie, null is returned. - * - * @returns {string|null} A KBase auth token, if any, stored in the browser. - */ - function getToken() { - if (!document.cookie) { - return null; - } - const cookies = document.cookie.split(';').map((item) => { - return item.trim(); - }); - - for (const cookie of cookies) { - const [name, value] = cookie.split('='); - if (name === SESSION_COOKIE_NAME) { - return value; - } - } - return null; - } - - /** - * Returns the username associated with the given KBase auth token. - * - * If there is no token, or an error is encountered interacting with - * the auth service, null is returned. - * - * @param {string} token - KBase auth token - * @returns {string|null} - A kbase username - */ - async function fetchAuth(token) { - if ( - KBASE_AUTH_INFO !== null && - KBASE_AUTH_INFO_EXPIRES_AT > Date.now() && - token === KBASE_AUTH_TOKEN - ) { - return KBASE_AUTH_INFO.user; - } - KBASE_AUTH_TOKEN = token; - const url = `${getServiceOrigin()}/services/auth/api/V2/me`; - try { - const response = await fetch(url, { - method: 'GET', - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - Authorization: token, - }, - }); - if (response.status !== 200) { - console.warn('[gtagSupport] bad auth response, user not available', response); - return null; - } - KBASE_AUTH_INFO = await response.json(); - KBASE_AUTH_INFO_EXPIRES_AT = Date.now() + KBASE_AUTH_TOKEN_TTL; - return KBASE_AUTH_INFO; - } catch (error) { - console.error('[gtagSupport] error occurred in call to auth service', error); - return null; - } - } - - /** - * Get the username associated with the current KBase auth token. - * - * If there is no valid KBase auth token available, or an error is - * encountered with the auth service call, null is returned instead. - * - * - * @returns {string|null} username - */ - async function getAuth() { - const token = getToken(); - if (token) { - try { - const auth = fetchAuth(token); - if (auth) { - return auth; - } - } catch (ex) { - console.error('[gtagSupport] Error fetching username', ex); - } - } - KBASE_AUTH_INFO = null; - KBASE_AUTH_TOKEN = null; - return null; - } - - /** - * - * - * @returns {void} - Nothing - */ - async function sendGTag() { - setState(SENDING); - - // The "path" for a view in the ui is determined by - // the url hash. This will change one day. - const path = getHashPath(); - - // Simply ensures that the data layer exists. The data layer - // is just an array placed into a "dataLayer" property on the global - // window. Nothing special about the name "dataLayer", other than that - // is where the google scripts expect to see - window.dataLayer = window.dataLayer || []; - - // See google docs for the api and field definitions. - // E.g. https://developers.google.com/analytics/devguides/collection/gtagjs/pages - // Queue up date for GA - const pageView = { - page_location: document.location.href, - page_path: path, - page_title: LAST_PAGE_TITLE, - }; - - const auth = await getAuth(); - if (auth) { - pageView.user_id = auth.anonid; - } - - pushGTag('event', 'page_view', pageView); - - setState(WAITING); - } - - /** - * The ever-popular "sleep" function, which returns a promise that resolves with the given period of time elapsed. - * - * @param {number} until The amount of time, in milliseconds, after which the promise should resolve. - * @returns {Promise} - */ - async function sleep(until) { - return new Promise((resolve) => { - window.setTimeout(() => { - resolve(); - }, until); - }); - } - - /** - * Ensures that if the next page hit is being sent, if the current one has not yet - * been sent, that it send immediately. - * - * Remember, that upon initiating a gtag request, we first wait for the page title - * to stabilize, and then the gtag event is registered. So if a new navigation event - * occurs during the waiting period, this function will be called in order to just - * send the gtag event even if the page title is not yet stabilized. - * - * @returns {Promise} - */ - async function sendPendingGTag() { - if (isState(PENDING)) { - // Here we set the status to SEND_NOW, which causes the loop monitoring the - // page title to terminate, which returns a promise, and causes the gtag - // event to be pushed. - setState(SEND_NOW); - - // And here we wait until the message is sent and we are back in the WAITING state. - // This should be sent very quickly, so a 2 second timeout should be plenty. - return await waitUntilStatus(WAITING, 2000); - } - } - - // Stores the current page title, which is really the last one recorded - // in the async loop below. - let LAST_PAGE_TITLE = null; - - /** - * When called, will return a Promise that will only resolve when the page title - * has not changed for some amount of time. - * - * This amount of time is set at top of the file as TITLE_STABILIZATION_PERIOD), but - * should be on the order of 2-3 seconds. - * - * @returns {Promise} - */ - - async function sendGTagAfterTitleSettles() { - setState(PENDING); - - let lastChanged = Date.now(); - LAST_PAGE_TITLE = document.title; - - // This is where we "wait" for the page title to stabilize, - // i.e. stop changing. - const loop = async () => { - if (isState(SEND_NOW)) { - return; - } - const now = Date.now(); - if (now >= lastChanged + TITLE_STABILIZATION_PERIOD) { - return; - } - if (document.title !== LAST_PAGE_TITLE) { - lastChanged = Date.now(); - LAST_PAGE_TITLE = document.title; - } - await sleep(100); - await loop(); - }; - await loop(); - - // And ... finally we trigger the pushing up data for gtag. - sendGTag(); - - // This signals that the status of this little gtag engine - // is waiting for a navigation event. - setState(WAITING); - } - - /** - * Send a ping to GA whenever the history state changes, i.e., url navigation - */ - window.onpopstate = async () => { - await sendPendingGTag(); - sendGTagAfterTitleSettles(); - }; - - /** - * Sets up gtag support to a known state, and sets up some gtag data that - * will not change over this session. - */ - function initialize() { - setState(WAITING); - pushGTag('js', new Date()); - pushGTag('config', GOOGLE_GTAG, { - send_page_view: false, - }); - pushGTag('config', GOOGLE_AD_TAG, { - send_page_view: false, - }); - } - - /** - * Initializes the state, and schedules the first page hit to be sent to GA. - * - * After this, navigation triggers the page hit. - */ - window.addEventListener('load', () => { - initialize(); - sendGTagAfterTitleSettles(); - }); -} - -main(); diff --git a/vite-app/src/antd.css b/vite-app/src/antd.css index 5312ac762..9a2e2333d 100644 --- a/vite-app/src/antd.css +++ b/vite-app/src/antd.css @@ -55,7 +55,9 @@ margin-right: 10px; } -.FullHeight-tabs.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab:not(.ant-tabs-tab-active) { +.FullHeight-tabs.ant-tabs.ant-tabs-card + .ant-tabs-card-bar + .ant-tabs-tab:not(.ant-tabs-tab-active) { background-color: transparent; border-color: transparent; } @@ -64,7 +66,6 @@ border-color: inherit; } */ - .FullHeight-tabPaneToolbar { text-align: center; margin-bottom: 10px; @@ -84,73 +85,102 @@ min-height: 0; } -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading { +.ScrollingFlexTable.ant-table-wrapper > .ant-spin-nested-loading { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; } -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container { +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; } -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table { +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; } -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container { +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-container { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; } - -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container>.ant-table-header { +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-container + > .ant-table-header { flex: 0 0 auto; } -.ScrollingFlexTable.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container>.ant-table-body { +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-container + > .ant-table-body { flex: 1 1 0px; overflow-y: auto; } - .AntTable-FullHeight.ant-table-wrapper, -.AntTable-FullHeight.ant-table-wrapper>.ant-spin-nested-loading, -.AntTable-FullHeight.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container, -.AntTable-FullHeight.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table, -.AntTable-FullHeight.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container { +.AntTable-FullHeight.ant-table-wrapper > .ant-spin-nested-loading, +.AntTable-FullHeight.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container, +.AntTable-FullHeight.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table, +.AntTable-FullHeight.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-container { flex: 1 1 0px; display: flex; flex-direction: column; min-height: 0; } -.AntTable-FullHeight.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container>.ant-table-header { +.AntTable-FullHeight.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-container + > .ant-table-header { overflow: unset !important; } - - -.InfoTable.UserMetadata>div>div:nth-child(1) { +.InfoTable.UserMetadata > div > div:nth-child(1) { flex: 0 0 20em; } -.InfoTable.UserMetadata>div>div:nth-child(2) { +.InfoTable.UserMetadata > div > div:nth-child(2) { flex: 0 0 20em; color: gray; font-style: italic; } -.InfoTable.ControlledMetadata>div>div:nth-child(1) { +.InfoTable.ControlledMetadata > div > div:nth-child(1) { flex: 0 0 20em; } @@ -160,17 +190,17 @@ font-style: italic; } */ -.InfoTable.TemplateMetadata>div>div:nth-child(1) { +.InfoTable.TemplateMetadata > div > div:nth-child(1) { flex: 0 0 20em; text-align: left; } -.InfoTable.TemplateMetadata>div>div:nth-child(2) { +.InfoTable.TemplateMetadata > div > div:nth-child(2) { flex: 0 0 10em; text-align: left; } -.InfoTable.TemplateMetadata>div>div:nth-child(3) { +.InfoTable.TemplateMetadata > div > div:nth-child(3) { /* flex: 0 0 20em; */ flex: 1 1 0px; text-align: left; @@ -180,7 +210,6 @@ display: inline-flex; } - /* Helps tame antd buttons ... should not be necessary */ .ButtonBar { @@ -203,4 +232,4 @@ .ButtonBar .ant-btn { display: inline-flex; align-items: center; -} \ No newline at end of file +} diff --git a/vite-app/src/applets/about/AboutBuild/AboutBuild.tsx b/vite-app/src/applets/about/AboutBuild/AboutBuild.tsx index 9dbd56534..b7558b81c 100644 --- a/vite-app/src/applets/about/AboutBuild/AboutBuild.tsx +++ b/vite-app/src/applets/about/AboutBuild/AboutBuild.tsx @@ -1,3 +1,4 @@ +import Well from 'components/Well'; import { Component } from 'react'; import { BuildInfo, GitInfo } from '../../../types/info'; @@ -6,13 +7,7 @@ export interface AboutBuildProps { buildInfo: BuildInfo; } -interface AboutBuildState { } - -export default class AboutBuild extends Component< - AboutBuildProps, - AboutBuildState -> { - +export default class AboutBuild extends Component { renderCommit() { return ( @@ -37,7 +32,7 @@ export default class AboutBuild extends Component< @@ -58,7 +53,7 @@ export default class AboutBuild extends Component< @@ -98,7 +93,11 @@ export default class AboutBuild extends Component< - + @@ -111,17 +110,15 @@ export default class AboutBuild extends Component< render() { return ( -
-
-

Build

- {this.renderBuildInfo()} -
- -
-

Dependencies

- ...not yet... -
-
+ + +
+
+ {this.renderBuildInfo()} +
+
+
+
); } } diff --git a/vite-app/src/applets/about/AboutBuild/index.tsx b/vite-app/src/applets/about/AboutBuild/index.tsx index afb883f54..e24cb5bc5 100644 --- a/vite-app/src/applets/about/AboutBuild/index.tsx +++ b/vite-app/src/applets/about/AboutBuild/index.tsx @@ -1,6 +1,6 @@ import { Component } from 'react'; import Loading from '../../../components/Loading'; -import { ConfigState, ConfigContext } from '../../../contexts/ConfigContext'; +import { ConfigContext, ConfigState } from '../../../contexts/ConfigContext'; import { AsyncProcessStatus } from '../../../lib/AsyncProcess2'; import AboutBuild from './AboutBuild'; @@ -8,35 +8,39 @@ export interface AboutBuildWrapperProps { setTitle: (title: string) => void; } -interface AboutBuildWrapperState { } +interface AboutBuildWrapperState {} export default class AboutBuildWrapper extends Component< AboutBuildWrapperProps, AboutBuildWrapperState > { render() { - return - {(configValue: ConfigState) => { - switch (configValue.status) { - case AsyncProcessStatus.NONE: - case AsyncProcessStatus.PENDING: - return ( - - ); - case AsyncProcessStatus.ERROR: - return
Error! {configValue.error}
; - case AsyncProcessStatus.SUCCESS: - this.props.setTitle('About the kbase-ui build'); - return + {(configValue: ConfigState) => { + switch (configValue.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ( + + ); + case AsyncProcessStatus.ERROR: + return
Error! {configValue.error}
; + case AsyncProcessStatus.SUCCESS: + this.props.setTitle('About the kbase-ui build'); + return ( + - } - }} -
+ ); + } + }} + + ); } } diff --git a/vite-app/src/applets/about/AboutCoreServices.tsx b/vite-app/src/applets/about/AboutCoreServices.tsx index 675f85fca..e4e049e12 100644 --- a/vite-app/src/applets/about/AboutCoreServices.tsx +++ b/vite-app/src/applets/about/AboutCoreServices.tsx @@ -1,5 +1,5 @@ import { Component } from 'react'; -import { AuthenticationState } from '../../contexts/Auth'; +import { AuthenticationState } from '../../contexts/EuropaContext'; import { Config } from '../../types/config'; import AboutService from './AboutService/AboutServiceMain'; import { SERVICES } from './ServiceDescription'; diff --git a/vite-app/src/applets/about/AboutKBaseUI/AboutKBaseUI.tsx b/vite-app/src/applets/about/AboutKBaseUI/AboutKBaseUI.tsx index 85a6143d9..bc6d72993 100644 --- a/vite-app/src/applets/about/AboutKBaseUI/AboutKBaseUI.tsx +++ b/vite-app/src/applets/about/AboutKBaseUI/AboutKBaseUI.tsx @@ -1,3 +1,4 @@ +import UILink from 'components/UILink2'; import { Component } from 'react'; import { Config } from '../../../types/config'; import { BuildInfo, GitInfo } from '../../../types/info'; @@ -6,14 +7,10 @@ export interface AboutKBaseUIProps { config: Config; gitInfo: GitInfo; buildInfo: BuildInfo; + uiURL: (path: string, params?: Record) => URL; } -interface AboutKBaseUIState { } - -export default class AboutKBaseUI extends Component< - AboutKBaseUIProps, - AboutKBaseUIState -> { +export default class AboutKBaseUI extends Component { renderHub() { return ( @@ -23,7 +20,6 @@ export default class AboutKBaseUI extends Component< } renderWelcome() { - // const docSiteUrl = this.props.config.ui.urls. return (

@@ -37,13 +33,14 @@ export default class AboutKBaseUI extends Component<

  • The{' '} - - Narrative Interface - + NarrativeInterface + , a tool for creating, editing, running and publishing active scientific documents called Narratives. New to the Narrative? Perhaps you would like to check out the{' '} @@ -81,11 +78,15 @@ export default class AboutKBaseUI extends Component<
); } - - renderGitInfo(): [JSX.Element, string, string] { + // [githubContent, githubUrl, relNotesUrl] + renderGitInfo(): { + githubContent: JSX.Element; + githubUrl: string; + relNotesUrl: string; + } { const gitInfo = this.props.gitInfo; - let repoUrl = gitInfo.originURL; // 'https://github.com/kbase/kbase-ui'; + let repoUrl = gitInfo.originURL; const hash = gitInfo.hash.full; if (/^ssh:/.test(repoUrl)) { const m = /^ssh:\/\/git@(.*?)\/(.*?)$/.exec(repoUrl); @@ -94,7 +95,7 @@ export default class AboutKBaseUI extends Component< } } - const commitHash = gitInfo.hash.full + const commitHash = gitInfo.hash.full; let relNotesUrl; let githubUrl; @@ -108,22 +109,24 @@ export default class AboutKBaseUI extends Component< ].join('/'); githubUrl = [repoUrl, 'tree', gitInfo.tag].join('/'); - return [ -

- You are currently using version{' '} - - {gitInfo.version} - {' '} - of {this.renderHub()}. -

, + return { + githubContent: ( +

+ You are currently using version{' '} + + {gitInfo.version} + {' '} + of {this.renderHub()}. +

+ ), githubUrl, relNotesUrl, - ]; + }; } else { relNotesUrl = [ repoUrl, @@ -133,26 +136,27 @@ export default class AboutKBaseUI extends Component< 'index.md', ].join('/'); githubUrl = [repoUrl, 'tree', hash].join('/'); - return [ -

- This build is not located at a tagged commit. The current - commit is{' '} - - {commitHash} - - . -

, + return { + githubContent: ( +

+ This build is not located at a tagged commit. The + current commit is{' '} + + {commitHash} + + . +

+ ), githubUrl, relNotesUrl, - ]; + }; } } - renderVersionInfo() { const buildInfo = this.props.buildInfo; @@ -179,7 +183,7 @@ export default class AboutKBaseUI extends Component< 'http://kbaseincubator.github.io/kbase-ui-docs'; const documentationURL = this.props.config.ui.urls.documentation.url; - const [githubContent, githubUrl,relNotesUrl] = this.renderGitInfo(); + const { githubContent, githubUrl, relNotesUrl } = this.renderGitInfo(); const kbaseGithubOrgURL = 'https://github.com/kbase'; diff --git a/vite-app/src/applets/about/AboutKBaseUI/index.tsx b/vite-app/src/applets/about/AboutKBaseUI/index.tsx index 3710c3ee9..7fac399b6 100644 --- a/vite-app/src/applets/about/AboutKBaseUI/index.tsx +++ b/vite-app/src/applets/about/AboutKBaseUI/index.tsx @@ -1,6 +1,6 @@ import { Component } from 'react'; import Loading from '../../../components/Loading'; -import { ConfigState, ConfigContext } from '../../../contexts/ConfigContext'; +import { ConfigContext, ConfigState } from '../../../contexts/ConfigContext'; import { AsyncProcessStatus } from '../../../lib/AsyncProcess2'; import AboutKBaseUI from './AboutKBaseUI'; @@ -8,38 +8,38 @@ export interface AboutBuildWrapperProps { setTitle: (title: string) => void; } -interface AboutBuildWrapperState { } - -export default class AboutBuildWrapper extends Component< - AboutBuildWrapperProps, - AboutBuildWrapperState -> { +export default class AboutBuildWrapper extends Component { componentDidMount() { this.props.setTitle('About the KBase User Interface'); } render() { - return - {(configValue: ConfigState) => { - switch (configValue.status) { - case AsyncProcessStatus.NONE: - case AsyncProcessStatus.PENDING: - return ( - - ); - case AsyncProcessStatus.ERROR: - return
Error! {configValue.error}
; - case AsyncProcessStatus.SUCCESS: - return - } - }} -
+ return ( + + {(configValue: ConfigState) => { + switch (configValue.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ( + + ); + case AsyncProcessStatus.ERROR: + return
Error! {configValue.error}
; + case AsyncProcessStatus.SUCCESS: + return ( + + ); + } + }} +
+ ); } } diff --git a/vite-app/src/applets/about/AboutMenu.tsx b/vite-app/src/applets/about/AboutMenu.tsx new file mode 100644 index 000000000..cefa7751c --- /dev/null +++ b/vite-app/src/applets/about/AboutMenu.tsx @@ -0,0 +1,91 @@ +import { + AuthenticationState, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { navigate2 } from 'lib/navigation'; +import { Component } from 'react'; +import { Nav } from 'react-bootstrap'; + +export interface AboutMenuProps { + tab: string; + + authState: AuthenticationState; +} + +export default class AboutMenu extends Component { + onSelect(eventKey: string | null) { + navigate2({ type: 'kbaseui', path: `about/${eventKey || 'kbase-ui'}` }); + } + + renderAboutBuild() { + if ( + this.props.authState.status === + AuthenticationStatus.AUTHENTICATED && + this.props.authState.authInfo.account.roles.some(({ id }) => + ['DevToken', 'ServToken', 'Admin'].includes(id), + ) + ) { + return ( + + build + + ); + } + } + + renderConnectionStatus() { + if ( + this.props.authState.status === + AuthenticationStatus.AUTHENTICATED && + this.props.authState.authInfo.account.roles.some(({ id }) => + ['DevToken', 'ServToken', 'Admin'].includes(id), + ) + ) { + return ( + + connection + + ); + } + } + + render() { + return ( +
+
+ About +
+ +
+ ); + } +} diff --git a/vite-app/src/applets/about/AboutPlugins/AboutPlugins.tsx b/vite-app/src/applets/about/AboutPlugins/AboutPlugins.tsx index 29a2a7d83..1486a1f1f 100644 --- a/vite-app/src/applets/about/AboutPlugins/AboutPlugins.tsx +++ b/vite-app/src/applets/about/AboutPlugins/AboutPlugins.tsx @@ -1,19 +1,13 @@ +import Well from 'components/Well'; import { Component } from 'react'; -import DataBrowser, { - ColumnDef -} from '../../../components/DataBrowser'; -import { PluginsInfo, PluginInfo } from '../../../types/info'; +import DataBrowser, { ColumnDef } from '../../../components/DataBrowser'; +import { PluginInfo, PluginsInfo } from '../../../types/info'; export interface AboutPluginsProps { pluginsInfo: PluginsInfo; } -interface AboutPluginsState { } - -export default class AboutPlugins extends Component< - AboutPluginsProps, - AboutPluginsState -> { +export default class AboutPlugins extends Component { renderPlugins() { const columns: Array> = [ { @@ -35,7 +29,9 @@ export default class AboutPlugins extends Component< return {plugin.configs.ui.version}; }, sorter: (a: PluginInfo, b: PluginInfo) => { - return a.configs.ui.version.localeCompare(b.configs.ui.version); + return a.configs.ui.version.localeCompare( + b.configs.ui.version, + ); }, }, // { @@ -63,10 +59,14 @@ export default class AboutPlugins extends Component< label: 'GitHub Account', style: {}, render: (plugin: PluginInfo) => { - return {plugin.configs.ui.source.github.account}; + return ( + {plugin.configs.ui.source.github.account} + ); }, sorter: (a: PluginInfo, b: PluginInfo) => { - return a.configs.ui.source.github.account.localeCompare(b.configs.ui.source.github.account); + return a.configs.ui.source.github.account.localeCompare( + b.configs.ui.source.github.account, + ); }, }, { @@ -75,22 +75,27 @@ export default class AboutPlugins extends Component< style: {}, render: (plugin: PluginInfo) => { return ( - + {plugin.configs.ui.globalName} ); }, sorter: (a: PluginInfo, b: PluginInfo) => { - return a.configs.ui.globalName.localeCompare(b.configs.ui.globalName); + return a.configs.ui.globalName.localeCompare( + b.configs.ui.globalName, + ); }, }, ]; - const data: Array = this.props.pluginsInfo.map( - (value) => { - return value; - } - ); + const data: Array = this.props.pluginsInfo.map((value) => { + return value; + }); return ( -
- {this.renderPlugins()} -
- ; + return ( + + {this.renderPlugins()} + + ); } } diff --git a/vite-app/src/applets/about/AboutPlugins/index.tsx b/vite-app/src/applets/about/AboutPlugins/index.tsx index ab2574f68..0dc84f7b7 100644 --- a/vite-app/src/applets/about/AboutPlugins/index.tsx +++ b/vite-app/src/applets/about/AboutPlugins/index.tsx @@ -1,6 +1,6 @@ import { Component } from 'react'; import Loading from '../../../components/Loading'; -import { ConfigState, ConfigContext } from '../../../contexts/ConfigContext'; +import { ConfigContext, ConfigState } from '../../../contexts/ConfigContext'; import { AsyncProcessStatus } from '../../../lib/AsyncProcess2'; import AboutPlugins from './AboutPlugins'; @@ -8,36 +8,35 @@ export interface AboutBuildWrapperProps { setTitle: (title: string) => void; } -interface AboutBuildWrapperState { } - -export default class AboutBuildWrapper extends Component< - AboutBuildWrapperProps, - AboutBuildWrapperState -> { +export default class AboutBuildWrapper extends Component { componentDidMount() { this.props.setTitle('About kbase-ui Plugins'); } render() { - return - {(configValue: ConfigState) => { - switch (configValue.status) { - case AsyncProcessStatus.NONE: - case AsyncProcessStatus.PENDING: - return ( - - ); - case AsyncProcessStatus.ERROR: - return
Error! {configValue.error}
; - case AsyncProcessStatus.SUCCESS: - return + {(configValue: ConfigState) => { + switch (configValue.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ( + + ); + case AsyncProcessStatus.ERROR: + return
Error! {configValue.error}
; + case AsyncProcessStatus.SUCCESS: + return ( + - } - }} -
+ ); + } + }} + + ); } } diff --git a/vite-app/src/applets/about/AboutService/AboutService.tsx b/vite-app/src/applets/about/AboutService/AboutService.tsx index 808acb629..a9c09884d 100644 --- a/vite-app/src/applets/about/AboutService/AboutService.tsx +++ b/vite-app/src/applets/about/AboutService/AboutService.tsx @@ -6,12 +6,7 @@ export interface AboutServiceProps { average: number; } -interface AboutServiceState {} - -export default class AboutService extends Component< - AboutServiceProps, - AboutServiceState -> { +export default class AboutService extends Component { render() { return ( diff --git a/vite-app/src/applets/about/AboutService/AboutServiceMain.tsx b/vite-app/src/applets/about/AboutService/AboutServiceMain.tsx index 496abb4b9..2d988c6b5 100644 --- a/vite-app/src/applets/about/AboutService/AboutServiceMain.tsx +++ b/vite-app/src/applets/about/AboutService/AboutServiceMain.tsx @@ -1,4 +1,5 @@ import { isJSONObject, traverse } from 'lib/json'; +import { resultOrThrow } from 'lib/kb_lib/comm/JSONRPC20/JSONRPC20'; import { Component } from 'react'; import ErrorAlert from '../../../components/ErrorAlert'; import Loading from '../../../components/Loading'; @@ -45,14 +46,8 @@ export default class AboutServiceMain extends Component< AboutServiceMainProps, AboutServiceMainState > { - // method : string; constructor(props: AboutServiceMainProps) { super(props); - // const method = props.service.statusMethod || props.service.versionMethod; - // if (typeof method === 'undefined') { - // throw new Error('Neither status nor version method provided') - // } - // this.method = method; this.state = { load: { status: AsyncProcessStatus.NONE, @@ -152,7 +147,8 @@ export default class AboutServiceMain extends Component< prefix: false, }); return async () => { - const result = await client.callFunc(service.method); + const response = await client.callFunc(service.method); + const result = resultOrThrow(response); if (service.versionKey) { if (isJSONObject(result)) { const result2 = traverse(result, service.versionKey); diff --git a/vite-app/src/applets/about/AboutServices.tsx b/vite-app/src/applets/about/AboutServices.tsx index 008015220..468cd2d54 100644 --- a/vite-app/src/applets/about/AboutServices.tsx +++ b/vite-app/src/applets/about/AboutServices.tsx @@ -1,25 +1,291 @@ +import Well from 'components/Well'; +import { NA } from 'components/helpers'; +import { SimpleError } from 'lib/SimpleError'; import { Component } from 'react'; -import { AuthenticationState } from '../../contexts/Auth'; +import DataBrowser, { ColumnDef } from '../../components/DataBrowser'; +import ErrorAlert from '../../components/ErrorAlert'; +import Loading from '../../components/Loading'; +import { AuthenticationState } from '../../contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from '../../lib/AsyncProcess'; import { Config } from '../../types/config'; -import AboutCoreServices from './AboutCoreServices'; +import { SERVICES, ServiceDescription } from './ServiceDescription'; +import ServicePerformance, { + PerformanceMeasurementsStatus, +} from './ServicePerformance'; -export interface AboutKBaseUIProps { +const ITERATIONS = 5; + +export interface AboutServicesProps { config: Config; setTitle: (title: string) => void; authState: AuthenticationState; } -interface AboutKBaseUIState { } +export enum ServiceMeasurementSummaryStatus { + OK = 'OK', + ERROR = 'ERROR', +} + +export interface ServiceMeasurementSummaryBase { + status: ServiceMeasurementSummaryStatus; + description: ServiceDescription; +} -export default class AboutKBaseUI extends Component< - AboutKBaseUIProps, - AboutKBaseUIState +export interface ServiceMeasurementSummaryOK + extends ServiceMeasurementSummaryBase { + status: ServiceMeasurementSummaryStatus.OK; + version: string; + average: number; + measures: Array; +} + +export interface ServiceMeasurementSummaryError + extends ServiceMeasurementSummaryBase { + status: ServiceMeasurementSummaryStatus.ERROR; + message: string; +} + +export type ServiceMeasurementSummary = + | ServiceMeasurementSummaryOK + | ServiceMeasurementSummaryError; + +interface AboutServicesState { + loadState: AsyncProcess, SimpleError>; +} + +export default class AboutServices extends Component< + AboutServicesProps, + AboutServicesState > { + constructor(props: AboutServicesProps) { + super(props); + this.state = { + loadState: { + status: AsyncProcessStatus.NONE, + }, + }; + } + componentDidMount() { this.props.setTitle('About KBase Core Services'); + + this.performMeasurements(); + } + + async performMeasurements() { + try { + const measurements: Array = + await Promise.all( + SERVICES.map(async (service) => { + const measurer = new ServicePerformance({ + config: this.props.config, + service, + iterations: ITERATIONS, + }); + const result = await measurer.measure(); + switch (result.status) { + case PerformanceMeasurementsStatus.SUCCESS: { + const { version, measurements } = result; + return { + status: ServiceMeasurementSummaryStatus.OK, + description: service, + version, + ...measurements, + }; + } + case PerformanceMeasurementsStatus.ERROR: + return { + status: ServiceMeasurementSummaryStatus.ERROR, + description: service, + message: result.message, + }; + } + }), + ); + this.setState({ + loadState: { + status: AsyncProcessStatus.SUCCESS, + value: measurements, + }, + }); + } catch (ex) { + this.setState({ + loadState: { + status: AsyncProcessStatus.ERROR, + error: { + message: + ex instanceof Error ? ex.message : 'Unknown error', + }, + }, + }); + } + } + + renderServices(services: Array) { + const columns: Array> = [ + { + id: 'module', + label: 'Module', + style: {}, + render: (service: ServiceMeasurementSummary) => { + // TODO: should manage to get the service's git url + return ( + + {service.description.module} + + ); + }, + sorter: ( + a: ServiceMeasurementSummary, + b: ServiceMeasurementSummary, + ) => { + return a.description.module.localeCompare( + b.description.module, + ); + }, + }, + { + id: 'version', + label: 'Version', + style: {}, + render: (service: ServiceMeasurementSummary) => { + if ( + service.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return ( +
{service.message}
+ ); + } + return {service.version}; + }, + sorter: ( + a: ServiceMeasurementSummary, + b: ServiceMeasurementSummary, + ) => { + if (a.status === ServiceMeasurementSummaryStatus.ERROR) { + if ( + b.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return 0; + } else { + return -1; + } + } else { + if ( + b.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return 1; + } else { + return a.version.localeCompare(b.version); + } + } + }, + }, + { + id: 'type', + label: 'Type', + style: {}, + render: (service: ServiceMeasurementSummary) => { + return {service.description.type}; + }, + sorter: ( + a: ServiceMeasurementSummary, + b: ServiceMeasurementSummary, + ) => { + return a.description.type.localeCompare(b.description.type); + }, + }, + { + id: 'perf', + label: 'Perf (ms/call)', + style: {}, + render: (service: ServiceMeasurementSummary) => { + if ( + service.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return NA(); + } + return ( + + {Intl.NumberFormat('en-US', { + useGrouping: true, + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }).format(service.average)} + + ); + }, + sorter: ( + a: ServiceMeasurementSummary, + b: ServiceMeasurementSummary, + ) => { + if (a.status === ServiceMeasurementSummaryStatus.ERROR) { + if ( + b.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return 0; + } else { + return -1; + } + } else { + if ( + b.status === ServiceMeasurementSummaryStatus.ERROR + ) { + return 1; + } else { + return a.average - b.average; + } + } + }, + }, + ]; + + return ( + + ); + } + + renderLoading() { + return ( + + ); + } + + renderError({ message }: SimpleError) { + return ; + } + + renderState() { + switch (this.state.loadState.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return this.renderLoading(); + case AsyncProcessStatus.ERROR: + return this.renderError(this.state.loadState.error); + case AsyncProcessStatus.SUCCESS: + return this.renderServices(this.state.loadState.value); + } } render() { - return ; + const stretch = + this.state.loadState.status === AsyncProcessStatus.SUCCESS; + return ( + + {this.renderState()} + + ); } } diff --git a/vite-app/src/applets/about/AboutServices2.tsx b/vite-app/src/applets/about/AboutServices2.tsx deleted file mode 100644 index b21858a22..000000000 --- a/vite-app/src/applets/about/AboutServices2.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { Component } from 'react'; -import DataBrowser, { ColumnDef } from '../../components/DataBrowser'; -import ErrorAlert from '../../components/ErrorAlert'; -import Loading from '../../components/Loading'; -import { AuthenticationState } from '../../contexts/Auth'; -import { AsyncProcess, AsyncProcessError, AsyncProcessStatus } from '../../lib/AsyncProcess'; -import { Config } from '../../types/config'; -import { SERVICES, ServiceDescription } from './ServiceDescription'; -import ServicePerformance from './ServicePerformance'; - -const ITERATIONS = 5; - -export interface AboutServicesProps { - config: Config; - setTitle: (title: string) => void; - authState: AuthenticationState; -} - -export interface ServiceDescriptionWithPerformance { - description: ServiceDescription; - version: string; - average: number; - measures: Array; -} - -interface AboutServicesState { - loadState: AsyncProcess, string> -} - -export default class AboutServices extends Component< - AboutServicesProps, - AboutServicesState -> { - - constructor(props: AboutServicesProps) { - super(props); - this.state = { - loadState: { - status: AsyncProcessStatus.NONE - } - } - } - componentDidMount() { - this.props.setTitle('About KBase Core Services'); - this.performMeasurements(); - } - - async performMeasurements() { - const measurements = await Promise.all(SERVICES.map(async (service) => { - const measurer = new ServicePerformance({ - config: this.props.config, - service, - iterations: ITERATIONS - }); - const [version, measurement] = await measurer.measure(); - return { - description: service, - version, - ...measurement - } - })); - this.setState({ - loadState: { - status: AsyncProcessStatus.SUCCESS, - value: measurements - } - }); - } - - renderServices(services: Array) { - const columns: Array> = [ - { - id: 'module', - label: 'Module', - style: {}, - render: (service: ServiceDescriptionWithPerformance) => { - // TODO: should manage to get the service's git url - return {service.description.module}; - }, - sorter: (a: ServiceDescriptionWithPerformance, b: ServiceDescriptionWithPerformance) => { - return a.description.module.localeCompare(b.description.module); - }, - }, - { - id: 'version', - label: 'Version', - style: {}, - render: (service: ServiceDescriptionWithPerformance) => { - return {service.version}; - }, - sorter: (a: ServiceDescriptionWithPerformance, b: ServiceDescriptionWithPerformance) => { - return a.version.localeCompare(b.version); - }, - }, - { - id: 'type', - label: 'Type', - style: {}, - render: (service: ServiceDescriptionWithPerformance) => { - return {service.description.type}; - }, - sorter: (a: ServiceDescriptionWithPerformance, b: ServiceDescriptionWithPerformance) => { - return a.description.type.localeCompare(b.description.type); - }, - }, - { - id: 'perf', - label: 'Perf (ms/call)', - style: {}, - render: (service: ServiceDescriptionWithPerformance) => { - return {Intl.NumberFormat('en-US', { - useGrouping: true, - minimumFractionDigits: 1, - maximumFractionDigits: 1, - }).format(service.average)}; - }, - sorter: (a: ServiceDescriptionWithPerformance, b: ServiceDescriptionWithPerformance) => { - return a.average - b.average; - }, - } - ]; - - return ( - - ); - } - - renderLoading() { - return ( - - ); - } - - renderError(state: AsyncProcessError) { - return ; - } - - renderState() { - switch (this.state.loadState.status) { - case AsyncProcessStatus.NONE: - case AsyncProcessStatus.PENDING: - return this.renderLoading(); - case AsyncProcessStatus.ERROR: - return this.renderError(this.state.loadState); - case AsyncProcessStatus.SUCCESS: - return this.renderServices(this.state.loadState.value); - } - } - - render() { - return
-
- {this.renderState()} -
-
- } -} diff --git a/vite-app/src/applets/about/AboutSession/index.tsx b/vite-app/src/applets/about/AboutSession/index.tsx new file mode 100644 index 000000000..afcc35504 --- /dev/null +++ b/vite-app/src/applets/about/AboutSession/index.tsx @@ -0,0 +1,149 @@ +import Empty from 'components/Empty'; +import Well, { Variant } from 'components/Well'; +import { + AuthenticationState, + AuthenticationStateAuthenticated, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { Role } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Table } from 'react-bootstrap'; + +export interface AboutSessionControllerProps { + authState: AuthenticationState; + setTitle: (title: string) => void; +} + +export default class AboutSessionController extends Component { + componentDidMount() { + this.props.setTitle('About Your Session'); + } + + renderRoles(roles: Array) { + if (roles.length === 0) { + return ; + } + const rows = roles.map(({ id, desc }) => { + return ( +
+ + + + ); + }); + + return ( +
date {new Date( - this.props.gitInfo.committer.date + this.props.gitInfo.committer.date, ).toLocaleString()}
authorDate {new Date( - this.props.gitInfo.author.date + this.props.gitInfo.author.date, ).toLocaleString()}
builtAt{new Date(this.props.buildInfo.builtAt).toLocaleString()} + {new Date( + this.props.buildInfo.builtAt, + ).toLocaleString()} +
git
{id}{desc}
+ + + + + + + {rows} +
Role IdDescription
+ ); + } + + renderCustomRoles(roles: Array) { + if (roles.length === 0) { + return ; + } + return roles.map((roleId) => { + return
{roleId}
; + }); + } + + renderAuthenticated(authState: AuthenticationStateAuthenticated) { + const { + authInfo: { + token, + tokenInfo: { user, expires }, + account: { roles, customroles }, + }, + } = authState; + + const loginToken = (() => { + if ( + authState.authInfo.account.roles.some(({ id }) => { + return id === 'DevToken'; + }) + ) { + return ( + + Login Token + {token} + + ); + } + })(); + + return ( + + + {loginToken} + + + + + + + + + + + + + + + + + +
Expires + {Intl.DateTimeFormat('en-US', { + dateStyle: 'medium', + timeStyle: 'medium', + }).format(expires)} +
Username{user}
Roles{this.renderRoles(roles)}
Custom Roles{this.renderCustomRoles(customroles)}
+ ); + } + + renderUnauthenticated() { + return ( + + You are not signed in, and therefore do not have a KBase + Session. + + ); + } + + renderState() { + switch (this.props.authState.status) { + case AuthenticationStatus.NONE: + return ; + case AuthenticationStatus.UNAUTHENTICATED: + return this.renderUnauthenticated(); + case AuthenticationStatus.AUTHENTICATED: + return this.renderAuthenticated(this.props.authState); + } + } + + renderVariant(): Variant { + switch (this.props.authState.status) { + case AuthenticationStatus.NONE: + return 'secondary'; + case AuthenticationStatus.UNAUTHENTICATED: + return 'warning'; + case AuthenticationStatus.AUTHENTICATED: + return 'secondary'; + } + } + + render() { + return ( + + {this.renderState()} + + ); + } +} diff --git a/vite-app/src/applets/about/ConnectionStatus/ConnectionStatus.tsx b/vite-app/src/applets/about/ConnectionStatus/ConnectionStatus.tsx index be77e5438..064f08920 100644 --- a/vite-app/src/applets/about/ConnectionStatus/ConnectionStatus.tsx +++ b/vite-app/src/applets/about/ConnectionStatus/ConnectionStatus.tsx @@ -1,10 +1,11 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Well from 'components/Well'; import { Component } from 'react'; +import { Table } from 'react-bootstrap'; import { AsyncProcess, AsyncProcessStatus } from '../../../lib/AsyncProcess'; import ConnectionMonitor from '../../../lib/ConnectionMonitor'; -import styles from './ConnectionStatus.module.css'; -export interface ConnectionStatusProps { -} +export interface ConnectionStatusProps {} export interface Measure { measure: number; @@ -13,10 +14,11 @@ export interface Measure { export interface ConnectionStats { lastCheck: number; + noFile: Measure; stats: Array<{ - size: number, - measure: Measure - }> + size: number; + measure: Measure; + }>; // ping: Measure // speed1k: Measure // speed5k: Measure @@ -31,51 +33,67 @@ interface Config { size: number; } -export class ConnectionStatus extends Component { +export class ConnectionStatus extends Component< + ConnectionStatusProps, + ConnectionStatusState +> { monitor: ConnectionMonitor; pingCount: number; configs: Array; + constructor(props: ConnectionStatusProps) { super(props); this.monitor = new ConnectionMonitor({ interval: 10000, callback: async () => { - await this.ping(); - } + return this.ping(); + }, }); this.pingCount = 0; - this.configs = [{ - color: 'black', - size: 0 - }, { - color: 'red', - size: 1 - }, { - color: 'blue', - size: 10000 - }, { - color: 'pink', - size: 100000 - }, { - color: 'silver', - size: 1000000 - }] + this.configs = [ + { + color: 'black', + size: 0, + }, + { + color: 'red', + size: 1, + }, + { + color: 'purple', + size: 1000, + }, + { + color: 'blue', + size: 10000, + }, + { + color: 'orange', + size: 100000, + }, + { + color: 'green', + size: 1000000, + }, + ]; this.state = { connectionStats: { - status: AsyncProcessStatus.NONE - } - } + status: AsyncProcessStatus.NONE, + }, + }; } - async measure(url: string) { + async measureElapsed(url: string) { const start = Date.now(); - await fetch(url, { - cache: 'no-store', headers: { + const response = await fetch(url, { + cache: 'no-store', + headers: { 'Accept-Encoding': 'identity;q=0', - 'Cache-Control': 'no-cache, no-transform' - } + 'Cache-Control': 'no-cache, no-transform', + }, }); - return Date.now() - start; + const content = await response.text(); + return [Date.now() - start, content.length]; } async pause(time: number) { @@ -96,66 +114,88 @@ export class ConnectionStatus extends Component { - if (size == 0) { - return '/__ping__'; + if (size === 0) { + return '/data/__perf__/0b.txt'; } if (size >= 1000) { - return `/data/__perf__/${size / 1000}k.txt` + return `/data/__perf__/${size / 1000}k.txt`; } - return `/data/__perf__/${size}b.txt` + return `/data/__perf__/${size}b.txt`; })(); - const pingElapsed = await this.measure(path); + const [pingElapsed] = await this.measureElapsed(path); results.push(pingElapsed); } + const [noFileMeasurement] = await this.measureElapsed('__ping__'); + // const [latency, speed] = results.reduce(([latency, speed], result) => { // }, [0, 0]); - if (this.state.connectionStats.status !== AsyncProcessStatus.SUCCESS) { - this.setState({ - connectionStats: { - status: AsyncProcessStatus.SUCCESS, - value: { - lastCheck, - stats: results.map((measure, index) => { - return { - size: this.configs[index].size, - measure: { - measure, - totalMeasure: measure - } - } - }) - } - } - }, () => { - this.pingCount++; - }); + if ( + this.state.connectionStats.status !== AsyncProcessStatus.SUCCESS + ) { + this.setState( + { + connectionStats: { + status: AsyncProcessStatus.SUCCESS, + value: { + lastCheck, + noFile: { + measure: noFileMeasurement, + totalMeasure: noFileMeasurement, + }, + stats: results.map((measure, index) => { + return { + size: this.configs[index].size, + measure: { + measure, + totalMeasure: measure, + }, + }; + }), + }, + }, + }, + () => { + this.pingCount++; + }, + ); } else { const x = this.state.connectionStats.value; - this.setState({ - connectionStats: { - status: AsyncProcessStatus.SUCCESS, - value: { - lastCheck, - stats: results.map((measure, index) => { - return { - size: this.configs[index].size, - measure: { - measure, - totalMeasure: x.stats[index].measure.totalMeasure + measure - } - } - }) - } - } - }, () => { - this.pingCount++; - }); + this.setState( + { + connectionStats: { + status: AsyncProcessStatus.SUCCESS, + value: { + lastCheck, + noFile: { + measure: noFileMeasurement, + totalMeasure: + this.state.connectionStats.value.noFile + .totalMeasure + noFileMeasurement, + }, + stats: results.map((measure, index) => { + return { + size: this.configs[index].size, + measure: { + measure, + totalMeasure: + x.stats[index].measure + .totalMeasure + measure, + }, + }; + }), + }, + }, + }, + () => { + this.pingCount++; + }, + ); } } catch (ex) { const message = (() => { @@ -167,20 +207,23 @@ export class ConnectionStatus extends Component { - this.monitor.start(); - }); + this.setState( + { + connectionStats: { + status: AsyncProcessStatus.PENDING, + }, + }, + () => { + this.monitor.start(); + }, + ); } componentWillUnmount() { @@ -197,9 +240,15 @@ export class ConnectionStatus extends Component - {Intl.NumberFormat('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 }).format(ping.totalMeasure / this.pingCount)} ms avg - + return ( + + {Intl.NumberFormat('en-US', { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }).format(ping.totalMeasure / this.pingCount)}{' '} + ms avg + + ); } // renderRate(rate: number) { @@ -227,34 +276,48 @@ export class ConnectionStatus extends ComponentCalculating first time...; + } // rate is bytes / sec ping // const rate = 1000 / (speed.measure / 1000); // const averageRate = (1000 * this.pingCount) / (speed.totalMeasure / 1000); // {speed.measure} ms --- // {this.formatBytesPerSecond(rate)} --- - const downloadTime = ping.totalMeasure / this.pingCount - base; + const downloadTime = ping.totalMeasure / this.pingCount; // rate is bytes / sec; size is already bytes, downloadTime is ms const rate = size / (downloadTime / 1000); - return - {Intl.NumberFormat('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 }).format(downloadTime)}ms ~ - {this.renderSize(rate)}/s - + return ( +
+
+ {Intl.NumberFormat('en-US', { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }).format(downloadTime)} + ms ~ +
+
{ping.totalMeasure}ms
+
{this.renderSize(rate)}/s
+
+ ); } niceNumber(value: number) { - return Intl.NumberFormat('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 }).format(value); + return Intl.NumberFormat('en-US', { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }).format(value); } renderSpeed(speed: Measure) { // rate is bytes / sec // const rate = 1000 / (speed.measure / 1000); - const averageRate = (1000 * this.pingCount) / (speed.totalMeasure / 1000); + const averageRate = + (1000 * this.pingCount) / (speed.totalMeasure / 1000); // {speed.measure} ms --- // {this.formatBytesPerSecond(rate)} --- - return - {this.formatBytesPerSecond(averageRate)} avg - + return {this.formatBytesPerSecond(averageRate)} avg; } // renderSize(size: number) { @@ -264,35 +327,90 @@ export class ConnectionStatus extends Component { + return ( + + + {this.renderSize(size)} + + + {this.renderPing2(overhead, size, measure)} + + + ); + }); + + return ( + + + + + + + + + + + + + + + {rows} + + {/* [{this.pingCount}] P {this.niceNumber(ping)}ms: */} + {/* OH {this.niceNumber(overhead)}ms: */} + {/* {content} */} +
Pings{this.pingCount}
Overhead + {this.pingCount === 0 + ? 'Calculating first time...' + : `${this.niceNumber(overhead)}ms`} +
none +
+
+ {Intl.NumberFormat('en-US', { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }).format(noFile.measure)} + ms ~ +
+
+ {noFile.totalMeasure}ms +
+
+
+ ); + } + renderState() { switch (this.state.connectionStats.status) { case AsyncProcessStatus.NONE: case AsyncProcessStatus.PENDING: return; case AsyncProcessStatus.ERROR: - return
{this.state.connectionStats.error}
+ return ( + + ); case AsyncProcessStatus.SUCCESS: - const stats = this.state.connectionStats.value.stats; - const ping = stats[0].measure.totalMeasure / this.pingCount; - const overhead = stats[1].measure.totalMeasure / this.pingCount - ping; - - const content = stats.slice(2).map(({ size, measure }, index) => { - return - {this.renderSize(size)} = {this.renderPing2(ping + overhead, size, measure)} - ; - }); - return
- [{this.pingCount}] P {this.niceNumber(ping)}ms: - OH {this.niceNumber(overhead)}ms: - {content} -
+ return this.renderSuccess(this.state.connectionStats.value); } } render() { - return
- {this.renderState()} -
+ return ( + + {this.renderState()} + + ); } -} \ No newline at end of file +} diff --git a/vite-app/src/applets/about/ServiceDescription.ts b/vite-app/src/applets/about/ServiceDescription.ts index 7c5e7f710..e4a5aae80 100644 --- a/vite-app/src/applets/about/ServiceDescription.ts +++ b/vite-app/src/applets/about/ServiceDescription.ts @@ -32,14 +32,14 @@ export const SERVICES: Array = [ type: 'rest', module: 'Auth2', path: '/', - repoURL: "https://github.com/kbase/auth2", + repoURL: 'https://github.com/kbase/auth2', versionKey: 'version', }, { title: 'Catalog', module: 'Catalog', type: 'jsonrpc11', - repoURL: "https://github.com/kbase/catalog", + repoURL: 'https://github.com/kbase/catalog', method: 'version', }, { diff --git a/vite-app/src/applets/about/ServicePerformance.ts b/vite-app/src/applets/about/ServicePerformance.ts index 552ac444b..52ed63ea0 100644 --- a/vite-app/src/applets/about/ServicePerformance.ts +++ b/vite-app/src/applets/about/ServicePerformance.ts @@ -1,4 +1,5 @@ import { isJSONObject, traverse } from '@kbase/ui-lib/lib/json'; +import { resultOrThrow } from 'lib/kb_lib/comm/JSONRPC20/JSONRPC20'; import GenericClient11 from '../../lib/kb_lib/comm/JSONRPC11/GenericClient'; import GenericClient20 from '../../lib/kb_lib/comm/JSONRPC20/GenericClient'; import { Config } from '../../types/config'; @@ -27,8 +28,34 @@ export interface PerformanceMetrics { average: number; } +export enum PerformanceMeasurementsStatus { + SUCCESS = 'SUCCESS', + ERROR = 'ERROR', +} + +export interface PerformanceMeasurementsBase { + status: PerformanceMeasurementsStatus; +} + +export interface PerformanceMeasurementsSuccess + extends PerformanceMeasurementsBase { + status: PerformanceMeasurementsStatus.SUCCESS; + version: string; + measurements: PerformanceMetrics; +} + +export interface PerformanceMeasurementsError + extends PerformanceMeasurementsBase { + status: PerformanceMeasurementsStatus.ERROR; + message: string; +} + +export type PerformanceMeasurements = + | PerformanceMeasurementsSuccess + | PerformanceMeasurementsError; + export default class ServicePerformance { - params: ServicePerformanceParams + params: ServicePerformanceParams; constructor(params: ServicePerformanceParams) { this.params = params; } @@ -45,7 +72,9 @@ export default class ServicePerformance { return total; } - async measurePerformance(call: () => Promise): Promise { + async measurePerformance( + call: () => Promise, + ): Promise { const measures: Array = []; const next = async (itersLeft: number): Promise => { if (itersLeft === 0) { @@ -63,7 +92,7 @@ export default class ServicePerformance { return await next(itersLeft - 1); // return null; } catch (ex) { - console.error('ERROR', expect); + console.error('ERROR', ex); return await next(itersLeft - 1); } }; @@ -121,7 +150,8 @@ export default class ServicePerformance { prefix: false, }); return async () => { - const result = await client.callFunc(service.method); + const response = await client.callFunc(service.method); + const result = resultOrThrow(response); if (service.versionKey) { if (isJSONObject(result)) { const result2 = traverse(result, service.versionKey); @@ -184,8 +214,23 @@ export default class ServicePerformance { } } - async measure() { + async measure(): Promise { const ver = this.getAPICall(); - return await Promise.all([ver(), this.measurePerformance(ver)]); + try { + const [version, measurements] = await Promise.all([ + ver(), + this.measurePerformance(ver), + ]); + return { + status: PerformanceMeasurementsStatus.SUCCESS, + version, + measurements, + }; + } catch (ex) { + return { + status: PerformanceMeasurementsStatus.ERROR, + message: ex instanceof Error ? ex.message : 'Unknown error', + }; + } } } diff --git a/vite-app/src/applets/about/index.module.css b/vite-app/src/applets/about/index.module.css new file mode 100644 index 000000000..d505c7b61 --- /dev/null +++ b/vite-app/src/applets/about/index.module.css @@ -0,0 +1,16 @@ +.main { + flex: 1 1 0; + display: flex; + flex-direction: column; +} + +.menu { + flex: 0 0 auto; +} + +.body { + flex: 1 1 0; + display: flex; + flex-direction: column; + overflow-y: hidden; +} diff --git a/vite-app/src/applets/about/index.tsx b/vite-app/src/applets/about/index.tsx index ec1329245..f01d10738 100644 --- a/vite-app/src/applets/about/index.tsx +++ b/vite-app/src/applets/about/index.tsx @@ -1,14 +1,18 @@ +import { SignIn } from 'apps/Auth2/SignIn/SignIn'; import { Component } from 'react'; import NotFound from '../../components/NotFound/NotFound'; import { RouteProps, Router } from '../../components/Router2'; -import { AuthenticationState } from '../../contexts/Auth'; +import { AuthenticationState } from '../../contexts/EuropaContext'; import { Route } from '../../lib/Route'; import { Config } from '../../types/config'; import AboutBuild from './AboutBuild'; import AboutKBaseUI from './AboutKBaseUI'; +import AboutMenu from './AboutMenu'; import AboutPlugins from './AboutPlugins'; -import AboutServices from './AboutServices2'; +import AboutServices from './AboutServices'; +import AboutSessionController from './AboutSession'; import { ConnectionStatus } from './ConnectionStatus/ConnectionStatus'; +import styles from './index.module.css'; export interface AboutProps extends RouteProps { config: Config; @@ -16,49 +20,97 @@ export interface AboutProps extends RouteProps { setTitle: (title: string) => void; } -interface AboutState { -} +interface AboutState {} export default class About extends Component { render() { - const routes: Array = [ new Route('about', { authenticationRequired: false }, () => { - return ( - - ); - }), - new Route('about/services', { authenticationRequired: false }, () => { - return ( - - ); + return ; }), + new Route( + 'about/kbase-ui', + { authenticationRequired: false }, + () => { + return ; + }, + ), + new Route( + 'about/services', + { authenticationRequired: false }, + () => { + return ; + }, + ), new Route('about/build', { authenticationRequired: false }, () => { - return ( - - ); + return ; }), - new Route('about/plugins', { authenticationRequired: false }, () => { - return ( - - ); - }), - new Route('about/connection', { authenticationRequired: false }, () => { - return ( - - ); - }), - new Route('about/*', { authenticationRequired: false }, (props: RouteProps) => { + new Route( + 'about/plugins', + { authenticationRequired: false }, + () => { + return ; + }, + ), + new Route( + 'about/connection', + { authenticationRequired: false }, + () => { + return ; + }, + ), + new Route( + 'about/session', + { authenticationRequired: false }, + () => { + return ; + }, + ), + new Route( + 'about/*', + { authenticationRequired: false }, + (props: RouteProps) => { + return ( + + ); + }, + ), + ]; + + const authRoute = new Route( + '^login|signin|signup$', + { authenticationRequired: false }, + (props: RouteProps) => { return ( - ); - }), - ]; + }, + ); - return + return ( +
+
+ +
+
+ +
+
+ ); // return ( // diff --git a/vite-app/src/applets/developer/ConfigEditor.css b/vite-app/src/applets/developer/ConfigEditor.module.css similarity index 55% rename from vite-app/src/applets/developer/ConfigEditor.css rename to vite-app/src/applets/developer/ConfigEditor.module.css index bf903e067..efac2925a 100644 --- a/vite-app/src/applets/developer/ConfigEditor.css +++ b/vite-app/src/applets/developer/ConfigEditor.module.css @@ -1,7 +1,7 @@ -.ConfigEditor { +.main { overflow-y: auto; } -.ConfigEditor .path { +.main .path { font-style: italic; -} \ No newline at end of file +} diff --git a/vite-app/src/applets/developer/ConfigEditor.tsx b/vite-app/src/applets/developer/ConfigEditor.tsx index ac2d170fd..6d14171d4 100644 --- a/vite-app/src/applets/developer/ConfigEditor.tsx +++ b/vite-app/src/applets/developer/ConfigEditor.tsx @@ -7,7 +7,7 @@ import { JSONValue, } from '../../lib/json'; import { Config } from '../../types/config'; -import './ConfigEditor.css'; +import styles from './ConfigEditor.module.css'; type Path = Array; @@ -16,7 +16,7 @@ export interface ConfigEditorProps { config: Config; } -interface ConfigEditorState { } +interface ConfigEditorState {} export default class ConfigEditor extends Component< ConfigEditorProps, @@ -40,7 +40,7 @@ export default class ConfigEditor extends Component< /> -
{path.join('.')}
+
{path.join('.')}
); } @@ -50,7 +50,7 @@ export default class ConfigEditor extends Component<
-
{path.join('.')}
+
{path.join('.')}
); } @@ -67,7 +67,7 @@ export default class ConfigEditor extends Component< -
{path.join('.')}
+
{path.join('.')}
); } @@ -77,7 +77,7 @@ export default class ConfigEditor extends Component<
-
{path.join('.')}
+
{path.join('.')}
); } @@ -141,7 +141,7 @@ export default class ConfigEditor extends Component< } render() { return ( -
+
{this.renderEditor()}
); diff --git a/vite-app/src/applets/developer/Features.module.css b/vite-app/src/applets/developer/Features.module.css index 97182421d..176406db8 100644 --- a/vite-app/src/applets/developer/Features.module.css +++ b/vite-app/src/applets/developer/Features.module.css @@ -1,3 +1,3 @@ -.Main { +.main { padding: 10px; -} \ No newline at end of file +} diff --git a/vite-app/src/applets/developer/Features.tsx b/vite-app/src/applets/developer/Features.tsx index 85962ff08..0f3f655c6 100644 --- a/vite-app/src/applets/developer/Features.tsx +++ b/vite-app/src/applets/developer/Features.tsx @@ -4,11 +4,11 @@ import styles from './Features.module.css'; import { FeatureState } from './FeaturesController'; export interface FeaturesProps { - features: Array + features: Array; toggleFeature: (id: string) => void; } -interface FeaturesState { } +interface FeaturesState {} export default class Features extends Component { onClick(id: string) { @@ -16,64 +16,51 @@ export default class Features extends Component { } renderFeatures() { - const rows = this.props.features.map(({ id, label, description, status }) => { - return - - {id} - - - {label} - - - {description} - - - {status} - - - { this.onClick(id); }} - /> - - - }); - - return - - - - - - - + + + + + + + ); + }, + ); - - - - - {rows} - -
- ID - - Label - - Description - - Status - + const rows = this.props.features.map( + ({ id, label, description, status }) => { + return ( +
{id}{label}{description}{status} + { + this.onClick(id); + }} + /> +
+ return ( + + + + + + + + + + + {rows} +
IDLabelDescriptionStatus
+ ); } render() { return ( -
+

Welcome to the Features Editor

-
- {this.renderFeatures()} -
+
{this.renderFeatures()}
); } diff --git a/vite-app/src/applets/developer/FeaturesController.tsx b/vite-app/src/applets/developer/FeaturesController.tsx index 870a6331f..c85d4ea22 100644 --- a/vite-app/src/applets/developer/FeaturesController.tsx +++ b/vite-app/src/applets/developer/FeaturesController.tsx @@ -1,8 +1,8 @@ +import * as Cookie from 'es-cookie'; import { Component } from 'react'; import Features from './Features'; -import * as Cookie from 'es-cookie'; -// Just for now; +// Just for now; // TODO: move into config. export interface Feature { @@ -11,11 +11,14 @@ export interface Feature { description: string; } -const FEATURES: Array = [{ - id: 'ce-new-policy', - label: 'Credit Engine - New Policy Updated', - description: 'Enables the new Use Policy (T&C), expires the current ones, which affects signup, signin, and account manager' -}] +const FEATURES: Array = [ + { + id: 'ce-new-policy', + label: 'Credit Engine - New Policy Updated', + description: + 'Enables the new Use Policy (T&C), expires the current ones, which affects signup, signin, and account manager', + }, +]; export interface FeaturesControllerProps { setTitle: (title: string) => void; @@ -26,18 +29,20 @@ export interface FeatureState extends Feature { } interface FeaturesControllerState { - features: Array - + features: Array; } const FEATURE_COOKIE_SEPARATOR = /s*,s*/; -export default class FeaturesController extends Component { +export default class FeaturesController extends Component< + FeaturesControllerProps, + FeaturesControllerState +> { constructor(props: FeaturesControllerProps) { super(props); this.state = { - features: [] - } + features: [], + }; } componentDidMount() { this.props.setTitle('Developer Tools - Features'); @@ -45,56 +50,67 @@ export default class FeaturesController extends Component((feature: Feature) => { - const status = cookieFeatures.includes(feature.id) ? 'enabled' : 'disabled'; + const status = cookieFeatures.includes(feature.id) + ? 'enabled' + : 'disabled'; return { ...feature, status }; }); this.setState({ - features + features, }); } // Actions - getFeatures() { - - } + getFeatures() {} toggleFeature(featureId: string) { const features = this.state.features.map((feature) => { if (featureId === feature.id) { - feature.status = feature.status === 'disabled' ? 'enabled' : 'disabled' + feature.status = + feature.status === 'disabled' ? 'enabled' : 'disabled'; } return feature; }); - this.setState({ - features - }, () => { - const enabledFeatures = features - .filter(({ status }) => { - return status === 'enabled'; - }) - .map(({ id }) => { - return id; - }) - .join(','); - if (enabledFeatures.length > 0) { - Cookie.set('kbase_features', enabledFeatures, { expires: 60, secure: true, path: '/', sameSite: 'strict' }); - } else { - Cookie.remove('kbase_features'); - } - }) + this.setState( + { + features, + }, + () => { + const enabledFeatures = features + .filter(({ status }) => { + return status === 'enabled'; + }) + .map(({ id }) => { + return id; + }) + .join(','); + if (enabledFeatures.length > 0) { + Cookie.set('kbase_features', enabledFeatures, { + expires: 60, + secure: true, + path: '/', + sameSite: 'strict', + }); + } else { + Cookie.remove('kbase_features'); + } + }, + ); } - // Renderers render() { return ( + toggleFeature={this.toggleFeature.bind(this)} + /> ); } } diff --git a/vite-app/src/applets/developer/Main.module.css b/vite-app/src/applets/developer/Main.module.css index 97182421d..176406db8 100644 --- a/vite-app/src/applets/developer/Main.module.css +++ b/vite-app/src/applets/developer/Main.module.css @@ -1,3 +1,3 @@ -.Main { +.main { padding: 10px; -} \ No newline at end of file +} diff --git a/vite-app/src/applets/developer/Main.tsx b/vite-app/src/applets/developer/Main.tsx index 28b27fee8..9d54a24ca 100644 --- a/vite-app/src/applets/developer/Main.tsx +++ b/vite-app/src/applets/developer/Main.tsx @@ -14,7 +14,7 @@ export default class Main extends Component { render() { return ( -
+

Welcome to the Developer Tools.

Currently this tool just lets you edit the runtime config. diff --git a/vite-app/src/applets/developer/config.yml b/vite-app/src/applets/developer/config.yml index a895552af..4f1296e2a 100644 --- a/vite-app/src/applets/developer/config.yml +++ b/vite-app/src/applets/developer/config.yml @@ -1,22 +1,22 @@ ## Welcome Panel --- package: - name: developer - title: Developer Tools - description: A developer tool - type: legacy + name: developer + title: Developer Tools + description: A developer tool + type: legacy services: - route: - routes: - - path: "{{name}}" - component: views/Developer - view: main - menu: - items: - - name: developer - type: internal - path: "{{name}}" - section: developer - allowedRoles: [DevToken] - label: Developer - icon: cogs + route: + routes: + - path: '{{name}}' + component: views/Developer + view: main + menu: + items: + - name: developer + type: internal + path: '{{name}}' + section: developer + allowedRoles: [DevToken] + label: Developer + icon: cogs diff --git a/vite-app/src/applets/developer/index.css b/vite-app/src/applets/developer/index.module.css similarity index 67% rename from vite-app/src/applets/developer/index.css rename to vite-app/src/applets/developer/index.module.css index 5d653a708..01a30b165 100644 --- a/vite-app/src/applets/developer/index.css +++ b/vite-app/src/applets/developer/index.module.css @@ -1,21 +1,21 @@ -.Developer { +.main { flex: 1 1 0; display: flex; flex-direction: column; min-height: 0; - margin: 0 10px; + margin: 0 1rem 1rem 1rem; } -.Developer .tab-content { +.main :global .tab-content { flex: 1 1 0; display: flex; flex-direction: column; min-height: 0; } -.Developer .tab-content .tab-pane.active { +.main :global .tab-content :global .tab-pane.active { flex: 1 1 0; display: flex; flex-direction: column; min-height: 0; -} \ No newline at end of file +} diff --git a/vite-app/src/applets/developer/index.tsx b/vite-app/src/applets/developer/index.tsx index e053be1d8..71457ac6c 100644 --- a/vite-app/src/applets/developer/index.tsx +++ b/vite-app/src/applets/developer/index.tsx @@ -2,9 +2,9 @@ import { Component } from 'react'; import { Tab, Tabs } from 'react-bootstrap'; import { Config } from '../../types/config'; import ConfigEditor from './ConfigEditor'; -import Main from './Main'; -import './index.css'; import Features from './FeaturesController'; +import Main from './Main'; +import styles from './index.module.css'; export interface DeveloperProps { tab?: string; @@ -12,12 +12,7 @@ export interface DeveloperProps { setTitle: (title: string) => void; } -interface DeveloperState { } - -export default class Developer extends Component< - DeveloperProps, - DeveloperState -> { +export default class Developer extends Component { componentDidMount() { this.props.setTitle('Developer Tools ;)'); } @@ -36,8 +31,7 @@ export default class Developer extends Component< /> - + ); @@ -45,7 +39,7 @@ export default class Developer extends Component< render() { return ( -

+
{this.renderTabs()}
); diff --git a/vite-app/src/applets/developer/test/main.yaml b/vite-app/src/applets/developer/test/main.yaml index 1d312fd0b..0b13aa78b 100644 --- a/vite-app/src/applets/developer/test/main.yaml +++ b/vite-app/src/applets/developer/test/main.yaml @@ -1,17 +1,17 @@ --- description: Welcome plugin specs: - - description: '' - baseSelector: - - type: plugin - value: welcome - tasks: - - action: navigate - path: bulk-ui - - wait: forText - timeout: 5000 - text: Bulk Import - DEPRECATED - selector: - - type: raw - name: data-element - value: title + - description: '' + baseSelector: + - type: plugin + value: welcome + tasks: + - action: navigate + path: bulk-ui + - wait: forText + timeout: 5000 + text: Bulk Import - DEPRECATED + selector: + - type: raw + name: data-element + value: title diff --git a/vite-app/src/applets/development/DevelopmentAuth.tsx b/vite-app/src/applets/development/DevelopmentAuth.tsx deleted file mode 100644 index c113b8202..000000000 --- a/vite-app/src/applets/development/DevelopmentAuth.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { Component } from 'react'; -import Loading from '../../components/Loading'; -import { - AuthenticationState, - AuthenticationStateAuthenticated, - AuthenticationStateUnauthenticated, - AuthenticationStatus, -} from '../../contexts/Auth'; -import { Config } from '../../types/config'; -import DevelopmentLogin from './DevelopmentLogin'; -import DevelopmentLogout from './DevelopmentLogout'; - -export interface DevelopmentAuthProps { - config: Config; - authState: AuthenticationState; -} - -interface DevelopmentAuthState {} - -export default class DevelopmentAuth extends Component< - DevelopmentAuthProps, - DevelopmentAuthState -> { - renderLoading() { - return ( - - ); - } - - renderUnauthenticated(authState: AuthenticationStateUnauthenticated) { - return ( - - ); - } - - renderAuthenticated(authState: AuthenticationStateAuthenticated) { - return ( - - ); - } - renderState() { - switch (this.props.authState.status) { - case AuthenticationStatus.NONE: - return this.renderLoading(); - case AuthenticationStatus.UNAUTHENTICATED: - return this.renderUnauthenticated(this.props.authState); - case AuthenticationStatus.AUTHENTICATED: - return this.renderAuthenticated(this.props.authState); - } - } - - render() { - return ( -
-

- DEVELOPMENT MODE -

-
- {this.renderState()} -
-
- ); - } -} diff --git a/vite-app/src/applets/development/DevelopmentLogin.tsx b/vite-app/src/applets/development/DevelopmentLogin.tsx deleted file mode 100644 index e51e82f9d..000000000 --- a/vite-app/src/applets/development/DevelopmentLogin.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { Component } from 'react'; -import AlertMessage from '../../components/AlertMessage'; -import ErrorAlert from '../../components/ErrorAlert'; -import Loading from '../../components/Loading'; -import { AuthenticationStateUnauthenticated } from '../../contexts/Auth'; -import { AsyncProcess, AsyncProcessStatus } from '../../lib/AsyncProcess'; -import { Auth2 } from '../../lib/kb_lib/Auth2'; -import { Config } from '../../types/config'; -import DevelopmentLoginForm from './DevelopmentLoginForm'; - -export interface DevelopmentLoginProps { - config: Config; - authState: AuthenticationStateUnauthenticated; -} - -interface DevelopmentLoginState { - loginState: AsyncProcess< - { - token: string; - username: string; - realname: string; - }, - string - >; -} - -export default class DevelopmentLogin extends Component< - DevelopmentLoginProps, - DevelopmentLoginState -> { - constructor(props: DevelopmentLoginProps) { - super(props); - this.state = { - loginState: { - status: AsyncProcessStatus.NONE, - }, - }; - } - renderLoading() { - return ( - - ); - } - - async doSetToken(token: string) { - // check token; - const auth = new Auth2({ - baseUrl: this.props.config.services.Auth2.url, - }); - try { - // const tokenInfo = await auth.getTokenInfo(token); - const meInfo = await auth.getMe(token); - this.setState({ - loginState: { - status: AsyncProcessStatus.SUCCESS, - value: { - token, - username: meInfo.user, - realname: meInfo.display, - }, - }, - }); - } catch (ex) { - this.setState({ - loginState: { - status: AsyncProcessStatus.ERROR, - error: ex instanceof Error ? ex.message : 'Unknown error', - }, - }); - } - } - - setToken(token: string) { - this.props.authState.login(token, 0); - } - - renderLoginStatus() { - const loginState = this.state.loginState; - switch (loginState.status) { - case AsyncProcessStatus.NONE: - return ( - - ); - case AsyncProcessStatus.PENDING: - return ( - - ); - case AsyncProcessStatus.ERROR: - return ; - case AsyncProcessStatus.SUCCESS: - return ( -
- -
- -
-
- ); - } - } - - render() { - return ( -
- -
- {this.renderLoginStatus()} -
-
- ); - } -} diff --git a/vite-app/src/applets/development/DevelopmentLoginForm.tsx b/vite-app/src/applets/development/DevelopmentLoginForm.tsx deleted file mode 100644 index 657b947cc..000000000 --- a/vite-app/src/applets/development/DevelopmentLoginForm.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { Component, FormEvent } from 'react'; - -export interface DevelopmentLoginFormProps { - onLogin: (token: string) => void; -} - -interface DevelopmentLoginFormState { - token: string | null; -} - -export default class DevelopmentLoginForm extends Component< - DevelopmentLoginFormProps, - DevelopmentLoginFormState -> { - constructor(props: DevelopmentLoginFormProps) { - super(props); - this.state = { - token: null, - }; - } - doLoginSubmit(ev: FormEvent) { - ev.preventDefault(); - if (this.state.token) { - this.props.onLogin(this.state.token); - } - return false; - } - - onTokenInput(ev: FormEvent) { - this.setState({ - token: ev.currentTarget.value, - }); - } - - isValidToken() { - const token = this.state.token; - if (!token) { - return false; - } - if (token.length !== 32) { - return false; - } - return true; - } - - render() { - return ( -
-

Development Mode Login

-

Please Enter a KBase Login Token Below:

-
-
- -
-
- -
-
-
- -
-
- ); - } -} diff --git a/vite-app/src/applets/development/DevelopmentLogout.tsx b/vite-app/src/applets/development/DevelopmentLogout.tsx deleted file mode 100644 index b734e4c82..000000000 --- a/vite-app/src/applets/development/DevelopmentLogout.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { Component } from 'react'; -import AlertMessage from '../../components/AlertMessage'; -import ErrorAlert from '../../components/ErrorAlert'; -import Loading from '../../components/Loading'; -import { AuthenticationStateAuthenticated } from '../../contexts/Auth'; -import { AsyncProcess, AsyncProcessStatus } from '../../lib/AsyncProcess'; -import { Config } from '../../types/config'; - -export interface DevelopmentLogoutProps { - config: Config; - authState: AuthenticationStateAuthenticated; -} - -interface DevelopmentLogoutState { - logoutState: AsyncProcess; -} - -export default class DevelopmentLogout extends Component< - DevelopmentLogoutProps, - DevelopmentLogoutState -> { - constructor(props: DevelopmentLogoutProps) { - super(props); - this.state = { - logoutState: { - status: AsyncProcessStatus.NONE, - }, - }; - } - - async doLogout(authState: AuthenticationStateAuthenticated) { - this.setState({ - logoutState: { - status: AsyncProcessStatus.PENDING, - }, - }); - try { - await authState.logout(); - this.setState({ - logoutState: { - status: AsyncProcessStatus.SUCCESS, - value: null, - }, - }); - } catch (ex) { - this.setState({ - logoutState: { - status: AsyncProcessStatus.ERROR, - error: ex instanceof Error ? ex.message : 'Unknown error', - }, - }); - } - } - - renderLogoutForm() { - return ( -
-

Please use the button below to log out of KBase:

-
- -
-
- ); - } - - renderLoginStatus() { - const logoutState = this.state.logoutState; - switch (logoutState.status) { - case AsyncProcessStatus.NONE: - return ( -
- -
- ); - case AsyncProcessStatus.PENDING: - return ( - - ); - case AsyncProcessStatus.ERROR: - return ; - case AsyncProcessStatus.SUCCESS: - return ( -
- -
- ); - } - } - - render() { - return ( -
- {this.renderLogoutForm()} - {this.renderLoginStatus()} -
- ); - } -} diff --git a/vite-app/src/applets/narrativeLoader/index.tsx b/vite-app/src/applets/narrativeLoader/index.tsx index 92bd9a8d8..74c58c37c 100644 --- a/vite-app/src/applets/narrativeLoader/index.tsx +++ b/vite-app/src/applets/narrativeLoader/index.tsx @@ -1,12 +1,12 @@ +import { navigationPathToURL } from 'contexts/RouterContext'; import { Component } from 'react'; -import { AuthenticationState } from '../../contexts/Auth'; -import { Config } from '../../types/config'; -// import { RouteComponentProps } from 'react-router'; import { Alert, ProgressBar } from 'react-bootstrap'; import AlertMessage from '../../components/AlertMessage'; import ErrorMessage from '../../components/ErrorMessage'; import Loading from '../../components/Loading'; import { RouteProps } from '../../components/Router2'; +import { AuthenticationState } from '../../contexts/EuropaContext'; +import { Config } from '../../types/config'; const MAX_TRIES = 20; const TIMEOUT = 60000; @@ -39,9 +39,9 @@ export class LoadingHttpError extends Error { } } -export class UnauthenticatedError extends Error { } +export class UnauthenticatedError extends Error {} -export class UIError extends Error { } +export class UIError extends Error {} export class TimeoutError extends Error { elapsed: number; @@ -57,7 +57,8 @@ export enum LoadStatus { NONE = 'NONE', POKING = 'POKING', OK = 'OK', - ERROR = 'ERROR', + INIT_ERROR = 'INIT_ERROR', + CHECK_ERROR = 'CHECK_ERROR', TIMED_OUT = 'TIMED_OUT', STRUCK_OUT = 'STRUCK_OUT', } @@ -72,43 +73,55 @@ export interface LoadStateNone extends LoadStateBase { export interface LoadStatePoking extends LoadStateBase { status: LoadStatus.POKING; - url: string; + narrativeId: number; + url: URL; tries: number; } export interface LoadStateOk extends LoadStateBase { status: LoadStatus.OK; - url: string; narrativeId: number; + url: URL; } -export interface LoadStateError extends LoadStateBase { - status: LoadStatus.ERROR; +export interface LoadStateInitError extends LoadStateBase { + status: LoadStatus.INIT_ERROR; // url: string; title: string; message: string; } +export interface LoadStateCheckError extends LoadStateBase { + status: LoadStatus.CHECK_ERROR; + title: string; + message: string; + narrativeId: number; + url: URL; +} + export interface LoadStateTimedOut extends LoadStateBase { status: LoadStatus.TIMED_OUT; tries: number; timeout: number; elapsed: number; - url: string; + narrativeId: number; + url: URL; } export interface LoadStateStruckOut extends LoadStateBase { status: LoadStatus.STRUCK_OUT; tries: number; elapsed: number; - url: string; + narrativeId: number; + url: URL; } export type LoadState = | LoadStateNone | LoadStatePoking | LoadStateOk - | LoadStateError + | LoadStateInitError + | LoadStateCheckError | LoadStateStruckOut | LoadStateTimedOut; @@ -133,18 +146,28 @@ export default class NarrativeLoader extends Component< }; urlToCheck() { - return `${document.location.origin}/narrative/static/kbase/config/config.json?check=true`; + return navigationPathToURL({ + path: `narrative/static/kbase/config/config.json`, + type: 'europaui', + }); + } + + narrativeURL(narrativeId: number) { + return navigationPathToURL({ + path: `/narrative/${narrativeId}`, + type: 'europaui', + }); } componentDidMount() { this.props.setTitle('Narrative Loader'); - const searchParams = this.props.hashPath.query; - const narrativeIdRaw = searchParams.get('n'); + const searchParams = this.props.hashPath.params || {}; + const narrativeIdRaw = searchParams['n']; if (!narrativeIdRaw) { this.setState({ loadState: { - status: LoadStatus.ERROR, - title: "Missing Parameter", + status: LoadStatus.INIT_ERROR, + title: 'Missing Parameter', message: "The Narrative Loader requires the 'n' search parameter, which was not provided in the URL.", }, @@ -155,8 +178,8 @@ export default class NarrativeLoader extends Component< if (!/^[1-9][0-9]*$/.test(narrativeIdRaw)) { this.setState({ loadState: { - status: LoadStatus.ERROR, - title: "Invalid Parameter", + status: LoadStatus.INIT_ERROR, + title: 'Invalid Parameter', message: `The "n" search parameter in the URL is not an integer > 0: It is "${narrativeIdRaw}".`, }, }); @@ -170,12 +193,13 @@ export default class NarrativeLoader extends Component< loadState: { status: LoadStatus.POKING, tries: 0, - url: this.urlToCheck() + narrativeId, + url: this.urlToCheck(), }, }, () => { this.tryLoading(narrativeId); - } + }, ); } @@ -183,12 +207,9 @@ export default class NarrativeLoader extends Component< // return Promise.resolve(true); // } - renderProgress() { } + renderProgress() {} async tryLoading(narrativeId: number) { - const narrativeURL = - document.location.origin + '/narrative/' + narrativeId; - if (this.state.loadState.status !== LoadStatus.POKING) { return; } @@ -196,23 +217,25 @@ export default class NarrativeLoader extends Component< const start = Date.now(); for (let tries = 1; tries <= MAX_TRIES; tries += 1) { const retry = await this.checkNarrative( - this.state.loadState.url + this.state.loadState.url, ); if (retry) { - await waitFor(RETRY_PAUSE); this.setState({ loadState: { status: LoadStatus.POKING, tries, + narrativeId, url: this.urlToCheck(), }, }); + + await waitFor(RETRY_PAUSE); } else { this.setState({ loadState: { status: LoadStatus.OK, - url: narrativeURL, - narrativeId + narrativeId, + url: this.urlToCheck(), }, }); @@ -226,50 +249,62 @@ export default class NarrativeLoader extends Component< status: LoadStatus.STRUCK_OUT, tries: MAX_TRIES, elapsed: Date.now() - start, - url: narrativeURL - } - }) + narrativeId, + url: this.urlToCheck(), + }, + }); resolve(); }, RETRY_PAUSE); }); } catch (ex) { + console.error('ERROR', ex); if (ex) if (ex instanceof LoadingError) { this.setState({ loadState: { - status: LoadStatus.ERROR, - title: "Error waiting for Narrative to start", - message: ex.message - } + status: LoadStatus.CHECK_ERROR, + title: 'Error waiting for Narrative to start', + message: ex.message, + narrativeId, + url: this.urlToCheck(), + }, }); } else if (ex instanceof TimeoutError) { this.setState({ loadState: { - status: LoadStatus.ERROR, - title: "Error waiting for Narrative to start", - message: ex.message - } + status: LoadStatus.CHECK_ERROR, + title: 'Error waiting for Narrative to start', + message: ex.message, + narrativeId, + url: this.urlToCheck(), + }, }); } else if (ex instanceof Error) { this.setState({ loadState: { - status: LoadStatus.ERROR, - title: "Error waiting for Narrative to start", - message: ex.message - } + status: LoadStatus.CHECK_ERROR, + title: 'Error waiting for Narrative to start', + message: ex.message, + narrativeId, + url: this.urlToCheck(), + }, }); } else { this.setState({ loadState: { - status: LoadStatus.ERROR, + status: LoadStatus.CHECK_ERROR, title: 'Unknown Error', - message: 'An unknown error occurred waiting for the Narrative to start' + message: + 'An unknown error occurred waiting for the Narrative to start', + narrativeId, + url: this.urlToCheck(), }, }); } } } - checkNarrative(url: string) { + + checkNarrative(url: URL) { const startTime = new Date().getTime(); return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); @@ -291,15 +326,15 @@ export default class NarrativeLoader extends Component< // properties. try { - var config = JSON.parse(xhr.responseText); + const config = JSON.parse(xhr.responseText); if (config && config.version) { resolve(false); } else { reject( new LoadingError( 'Error in Narrative check response', - 'check' - ) + 'check', + ), ); } } catch (ex) { @@ -324,8 +359,8 @@ export default class NarrativeLoader extends Component< new LoadingHttpError( xhr.status, xhr.statusText, - xhr.responseText - ) + xhr.responseText, + ), ); } }; @@ -349,60 +384,101 @@ export default class NarrativeLoader extends Component< } try { - xhr.withCredentials = false; + xhr.withCredentials = true; xhr.send(); } catch (ex) { reject( - new LoadingError('Error sending data in request', 'sending') + new LoadingError( + 'Error sending data in request', + 'sending', + ), ); } }); } renderOK(loadingState: LoadStateOk) { - const url: URL = new URL(window.location.href); - // Nuke the hash and search - for (const key of Array.from(url.searchParams.keys())) { - url.searchParams.delete(key); - } - url.hash = ''; - url.pathname = `/narrative/${loadingState.narrativeId}`; + // const url: URL = new URL(window.location.href); + // // Nuke the hash and search + // for (const key of Array.from(url.searchParams.keys())) { + // url.searchParams.delete(key); + // } + // url.hash = ''; + const url = navigationPathToURL({ + path: `narrative/${loadingState.narrativeId}`, + type: 'europaui', + }); + window.setTimeout(() => { - document.location.href = url.toString(); - }, SLIGHT_DELAY_BEFORE_REDIRECT) - - return - Your Narrative service instance has been detected, redirecting to Narrative {loadingState.narrativeId}... - + window.open(url, '_top'); + }, SLIGHT_DELAY_BEFORE_REDIRECT); + + return ( + + Your Narrative service instance has been detected, redirecting + to Narrative {loadingState.narrativeId}... + + ); } - - renderState() { + render() { switch (this.state.loadState.status) { case LoadStatus.NONE: return ; case LoadStatus.POKING: return ( - +

Starting a new Narrative session for you.

Please wait.

-

{this.state.loadState.tries} {this.state.loadState.tries === 1 ? "try" : "tries"} out of {MAX_TRIES}

- +

+ {this.state.loadState.tries}{' '} + {this.state.loadState.tries === 1 ? 'try' : 'tries'}{' '} + out of {MAX_TRIES} +

+
); case LoadStatus.OK: return this.renderOK(this.state.loadState); - case LoadStatus.ERROR: - return ; + case LoadStatus.INIT_ERROR: + return ( + + ); + case LoadStatus.CHECK_ERROR: + return ( + + ); case LoadStatus.STRUCK_OUT: - return ; + return ( + + ); case LoadStatus.TIMED_OUT: - return ; + return ( + + ); } } - render() { - return this.renderState(); - } } diff --git a/vite-app/src/apps/Auth.tsx b/vite-app/src/apps/Auth.tsx deleted file mode 100644 index a044c1243..000000000 --- a/vite-app/src/apps/Auth.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { Component } from 'react'; -import ErrorMessage from '../components/ErrorMessage'; -import PluginWrapper2 from '../components/PluginWrapper/PluginWrapper2'; -import { RouteProps, Router } from '../components/Router2'; -import { AuthenticationState } from '../contexts/Auth'; -import { RouterContext } from '../contexts/RouterContext'; -import { AsyncProcessStatus } from '../lib/AsyncProcess2'; -import { Route, SimplePluginRouteSpec } from '../lib/Route'; -import { Config } from '../types/config'; - -export interface AuthProps extends RouteProps { - config: Config; - authState: AuthenticationState; - setTitle: (title: string) => void; -} - -interface AuthState { -} - -export default class Catalog extends Component { - makePath(extraPath?: string) { - if (extraPath) { - return `${this.props.hashPath.path}/${extraPath}`; - } else { - return this.props.hashPath.path; - } - } - - render() { - const common = { - name: "auth2-client", - setTitle: this.props.setTitle, - authState: this.props.authState, - config: this.props.config - }; - - const routeSpecs: Array = [ - { - path: 'account', - auth: true, - view: 'account' - }, - { - path: 'auth2/account', - auth: true, - view: 'account' - }, - { - path: 'login', - auth: false, - view: 'login' - }, - { - path: 'signup', - auth: false, - view: 'signup' - }, - { - path: 'auth2/signedout', - auth: false, - view: 'signedout' - }, - { - path: 'auth2/login/continue', - auth: false, - view: 'loginContinue' - }, - { - path: 'auth2/link/continue', - auth: true, - view: 'linkContinue' - }, - ] - - const routes = routeSpecs.map(({path, view, auth}) => { - return new Route(path, {authenticationRequired: auth}, (props: RouteProps) => { - return - }); - }); - - return ( - - {(value) => { - switch (value.status) { - case AsyncProcessStatus.NONE: - return
; - case AsyncProcessStatus.PENDING: - return
; - case AsyncProcessStatus.ERROR: - return ; - case AsyncProcessStatus.SUCCESS: - return ; - } - }} - - ); - // return ; - // 1 - // return ( - // - // { - // return ( - // - // ); - // }} - // /> - // { - // return ( - // - // ); - // }} - // /> - // { - // return ( - // - // ); - // }} - // /> - // { - // return ( - // - // ); - // }} - // /> - - // { - // return ( - // - // ); - // }} - // /> - - // { - // return ( - // - // ); - // }} - // /> - // { - // return ( - // - // ); - // }} - // /> - // - // ); - } -} diff --git a/vite-app/src/apps/Auth2/AccountManager/Account/AccountEditor/view.tsx b/vite-app/src/apps/Auth2/AccountManager/Account/AccountEditor/view.tsx new file mode 100644 index 000000000..c71aabe2b --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/Account/AccountEditor/view.tsx @@ -0,0 +1,141 @@ +import { notifySuccess } from 'contexts/EuropaContext'; +import * as formik from 'formik'; +import { FormikHelpers } from 'formik'; +import { Component } from 'react'; +import { Button, Col, Container, Form, InputGroup, Row } from 'react-bootstrap'; +import * as yup from 'yup'; +import { AccountEditorFields } from '../controller'; + +export interface AccountEditorViewProps { + fields: AccountEditorFields; + save: (fields: AccountEditorFields) => Promise; +} + +interface AccountEditorViewState {} + +export default class AccountEditorView extends Component< + AccountEditorViewProps, + AccountEditorViewState +> { + async onSubmit( + fields: AccountEditorFields, + { resetForm }: FormikHelpers, + ) { + await this.props.save(fields); + + // Okay, this "resets" the form, but keeping the data changed and saved above, + // thus it doesn't "reset" to the previous state, it just effectively clears the + // dirty and possibly other flags. + resetForm({ values: fields }); + + notifySuccess('Successfully saved changes to your account and profile'); + } + + render() { + const { Formik } = formik; + + const schema = yup.object().shape({ + realname: yup.string().required().min(2).max(100), + email: yup.string().required().email(), + }); + + return ( + + {({ + handleSubmit, + handleChange, + values, + errors, + dirty, + isValid, + }) => { + return ( +
{ + handleSubmit(e); + }} + > + + + + + Your Name + + + + + {errors.realname} + + + + + Your real name, displayed to other KBase + users + + + + + + E-Mail Address + + + + + {errors.email} + + + + + Your email address; may be used by KBase + staff to contact you. + + + + + + + + +
+ ); + }} +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/Account/AccountInfo/view.tsx b/vite-app/src/apps/Auth2/AccountManager/Account/AccountInfo/view.tsx new file mode 100644 index 000000000..5435f9c50 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/Account/AccountInfo/view.tsx @@ -0,0 +1,88 @@ +import { Account } from 'lib/kb_lib/Auth2'; +import { niceRelativeTime, niceTime } from 'lib/time'; +import { Component } from 'react'; +import { Col, Container, Form, Row } from 'react-bootstrap'; + +export interface AccountInfoViewProps { + account: Account; +} + +export default class AccountInfoView extends Component { + render() { + const { user, created, lastlogin } = this.props.account; + return ( + + + + + Username + +
{user}
+ + + Your permanent identifier within KBase + +
+ {/* + + Name +
{display}
+ + k + + The name you provided at signup to show to other users. + + +
*/} + {/* + + E-Mail +
{email}
+ + + + The email address you provided at signup. + + +
*/} + + + + Account Created + +
{niceTime(new Date(created))}
+ + + When you signed up for KBase + +
+ + + + Last Sign In + +
+ {niceRelativeTime(new Date(lastlogin))} ( + {niceTime(new Date(lastlogin))}) +
+ + + When you last signed in to KBase + +
+
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/Account/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/Account/controller.tsx new file mode 100644 index 000000000..c2760413c --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/Account/controller.tsx @@ -0,0 +1,209 @@ +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { Component } from 'react'; +import { Config } from 'types/config'; +import AccountEditorView from './view'; + +export interface AccountEditorControllerProps { + authState: AuthenticationStateAuthenticated; + config: Config; + setTitle: (title: string) => void; +} + +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +// import { AsyncProcess, AsyncProcessStatus } from "lib/AsyncProcess"; +import { SimpleError } from 'lib/SimpleError'; +import { Account, Auth2 } from 'lib/kb_lib/Auth2'; +import UserProfile from 'lib/kb_lib/comm/coreServices/UserProfile'; + +import { + RepeatAsyncProcess, + RepeatAsyncProcessStatus, +} from 'lib/RepeatableAsyncProcess'; +import { Md5 } from 'ts-md5'; + +export interface AccountEditorFields { + realname: string; + email: string; +} + +export interface AccountEditor { + fields: AccountEditorFields; + account: Account; +} + +type AccountEditorControllerState = RepeatAsyncProcess< + AccountEditor, + SimpleError +>; + +export default class AccountEditorController extends Component< + AccountEditorControllerProps, + AccountEditorControllerState +> { + constructor(props: AccountEditorControllerProps) { + super(props); + this.state = { + status: RepeatAsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.props.setTitle('Account Manager - Update Your Account'); + this.loadData(); + } + + async save({ email, realname }: AccountEditorFields) { + const { + authInfo: { + token, + account: { user: username }, + }, + } = this.props.authState; + const { + services: { + Auth2: { url: authURL }, + UserProfile: { url: userProfileURL }, + }, + } = this.props.config; + const userProfileClient = new UserProfile({ + url: userProfileURL, + token, + timeout: 1000, // TODO: get from config + }); + const authClient = new Auth2({ + baseUrl: authURL, + }); + + const profile = ( + await userProfileClient.get_user_profile([username]) + )[0]; + + // Extract field values from form + + const hashedEmail = Md5.hashStr(email.trim().toLowerCase()); + profile.profile.synced.gravatarHash = hashedEmail; + profile.user.realname = realname; + + // Auth2 params + const meData = { + email, + display: realname, + }; + + await Promise.all([ + authClient.putMe(token, meData), + userProfileClient.set_user_profile({ + profile, + }), + ]); + + await this.reloadData(); + + // return {email: account?.email, realname: account?.display}; + + // TODO: is this still implemented? + // this.props.runtime.send('profile', 'reload'); + + // this.props.runtime.notifySuccess( + // 'Successfully updated your account and user profile', + // 3000 + // ); + } + + async fetchData() { + const { + authInfo: { token }, + } = this.props.authState; + const { + services: { + Auth2: { url: authURL }, + }, + } = this.props.config; + const auth2 = new Auth2({ + baseUrl: authURL, + }); + const account = await auth2.getMe(token); + return account; + } + + async loadData() { + this.setState({ + status: RepeatAsyncProcessStatus.PENDING, + }); + + try { + const account = await this.fetchData(); + const { display, email } = await this.fetchData(); + this.setState({ + status: RepeatAsyncProcessStatus.SUCCESS, + value: { + fields: { + realname: display, + email, + }, + account, + }, + }); + } catch (ex) { + this.setState({ + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + async reloadData() { + this.setState({ + status: RepeatAsyncProcessStatus.SUCCESS_PENDING, + }); + + try { + const account = await this.fetchData(); + const { display, email } = await this.fetchData(); + this.setState({ + status: RepeatAsyncProcessStatus.SUCCESS, + value: { + fields: { + realname: display, + email, + }, + account, + }, + }); + // return account; + } catch (ex) { + this.setState({ + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + renderSuccess(value: AccountEditor) { + return ( + + ); + } + + render() { + switch (this.state.status) { + case RepeatAsyncProcessStatus.NONE: + case RepeatAsyncProcessStatus.PENDING: + return ; + case RepeatAsyncProcessStatus.SUCCESS: + case RepeatAsyncProcessStatus.SUCCESS_PENDING: + return this.renderSuccess(this.state.value); + case RepeatAsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/Account/view.tsx b/vite-app/src/apps/Auth2/AccountManager/Account/view.tsx new file mode 100644 index 000000000..d711380d2 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/Account/view.tsx @@ -0,0 +1,44 @@ +import Well from 'components/Well'; +import { Account } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import AccountEditor from './AccountEditor/view'; +import AccountInfo from './AccountInfo/view'; +import { AccountEditorFields } from './controller'; + +export interface AccountEditorViewProps { + account: Account; + fields: AccountEditorFields; + save: (fields: AccountEditorFields) => Promise; +} + +interface AccountEditorViewState {} + +export default class AccountEditorView extends Component< + AccountEditorViewProps, + AccountEditorViewState +> { + renderAccountEditor() { + return ( + + ); + } + + renderAccountInfo() { + return ; + } + + render() { + return ( +
+ + Edit Account + {this.renderAccountEditor()} + + + Account Info + {this.renderAccountInfo()} + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/AddTokenForm.tsx b/vite-app/src/apps/Auth2/AccountManager/AddTokenForm.tsx new file mode 100644 index 000000000..34f8e7b45 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/AddTokenForm.tsx @@ -0,0 +1,70 @@ +import { Component } from 'react'; +import { Button, Col, Form, Row } from 'react-bootstrap'; + +export interface AddTokenFormProps { + createToken: (tokenName: string) => void; +} + +interface AddTokenFormState { + tokenName: string | null; +} + +export default class AddTokenForm extends Component< + AddTokenFormProps, + AddTokenFormState +> { + constructor(props: AddTokenFormProps) { + super(props); + // this.ref = createRef(); + this.state = { + tokenName: null, + }; + } + onSubmit() { + // e.preventDefault(); + if (this.state.tokenName === null) { + return; + } + this.props.createToken(this.state.tokenName); + this.setState({ + tokenName: null, + }); + } + render() { + return ( +
{ + e.preventDefault(); + this.onSubmit(); + }} + > + + + Token Name + + + { + this.setState({ tokenName: e.target.value }); + }} + > + + + + + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/DevToken/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/DevToken/controller.tsx new file mode 100644 index 000000000..ed4440d28 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/DevToken/controller.tsx @@ -0,0 +1,216 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { notifySuccess } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Auth2, Role, TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import ActiveTokensView from './view'; + +export interface DevTokensControllerProps { + token: string; + roles: Array; + authURL: string; + setTitle: (title: string) => void; +} + +export interface DevTokens { + tokens: Array; + newToken: TokenInfoFull | null; + serverTimeBias: number; +} + +type DevTokensControllerState = AsyncProcess; + +export default class DevTokensController extends Component< + DevTokensControllerProps, + DevTokensControllerState +> { + constructor(props: DevTokensControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + componentDidMount() { + this.props.setTitle('Account Manager - Developer Tokens'); + this.loadData(); + } + + async revokeToken(tokenToRevoke: string, name: string) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + try { + await auth2.revokeToken(this.props.token, tokenToRevoke); + const { tokens } = await auth2.getTokens(this.props.token); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Developer'; + }), + }, + }); + notifySuccess(`Dev token "${name}" as been revoked`); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async revokeAllTokens() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + try { + const { tokens: currentTokens } = await auth2.getTokens(authToken); + + // All others + await Promise.all( + currentTokens + .filter(({ type }) => { + return type === 'Developer'; + }) + .map(({ id }) => { + return auth2.revokeToken(authToken, id); + }), + ); + + const { tokens } = await auth2.getTokens(authToken); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Developer'; + }), + }, + }); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async getServerTimeBias() { + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const { servertime } = await auth2.root(); + return servertime - Date.now(); + } + + async loadData() { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + + try { + const { tokens } = await auth2.getTokens(this.props.token); + + const serverTimeBias = await this.getServerTimeBias(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + tokens: tokens.filter((token) => { + return token.type === 'Developer'; + }), + newToken: null, + serverTimeBias, + }, + }); + } catch (ex) { + console.error(ex); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + async createDeveloperToken(name: string) { + const state = this.state; + if (state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + try { + const newToken = await auth2.createToken(authToken, { + name, + type: 'developer', + }); + + this.setState({ + ...state, + value: { + ...state.value, + newToken, + tokens: state.value.tokens.concat([newToken]), + }, + }); + + notifySuccess(`New dev token named "${name}" has been created`); + } catch (ex) { + console.error(ex); + // what to do - notification? + } + } + + clearNewToken() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + this.setState({ + ...this.state, + value: { + ...this.state.value, + newToken: null, + }, + }); + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: { + const { tokens, newToken, serverTimeBias } = this.state.value; + return ( + + ); + } + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/DevToken/view.module.css b/vite-app/src/apps/Auth2/AccountManager/DevToken/view.module.css new file mode 100644 index 000000000..056ab60b4 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/DevToken/view.module.css @@ -0,0 +1,5 @@ +.main { + flex: 1 1 0; + display: flex; + flex-direction: column; +} diff --git a/vite-app/src/apps/Auth2/AccountManager/DevToken/view.tsx b/vite-app/src/apps/Auth2/AccountManager/DevToken/view.tsx new file mode 100644 index 000000000..99209c3ce --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/DevToken/view.tsx @@ -0,0 +1,286 @@ +import Empty from 'components/Empty'; +import Well from 'components/Well'; +import { notifySuccess } from 'contexts/EuropaContext'; +import { TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { niceDuration, niceTime } from 'lib/time'; +import { Component } from 'react'; +import { Button, ButtonGroup, ButtonToolbar } from 'react-bootstrap'; +import AddTokenForm from '../AddTokenForm'; +import TokenCopy from '../TokenCopy'; +import styles from './view.module.css'; + +const TOKEN_VIEWER_EXPIRES_IN = 300000; + +export interface DevTokensViewProps { + tokens: Array; + newToken: TokenInfoFull | null; + serverTimeBias: number; + revokeToken: (token: string, name: string) => void; + revokeAllTokens: () => void; + createDeveloperToken: (name: string) => void; + clearNewToken: () => void; +} + +interface DevTokensViewState { + newTokenCopied?: boolean; +} + +export default class DevTokensView extends Component< + DevTokensViewProps, + DevTokensViewState +> { + doRevokeToken(tokenId: string, name: string) { + this.props.revokeToken(tokenId, name); + } + + doRevokeAllTokens() { + this.props.revokeAllTokens(); + } + + renderTokenBrowser(tokens: Array, removeVerb: string) { + const revokeAllButton = (() => { + if (tokens.length > 1) { + return ( + + ); + } + })(); + const rows = tokens.map( + ({ + name, + id, + created, + expires, + os, + osver, + agent, + agentver, + ip, + }) => { + const renderBrowser = () => { + if (agent === null) { + // } || agent.agent === 0) { // TODO: what is this actual type??? + return ( + + n/a + + ); + } + return ( + + {agent} + + {agentver} + + + ); + }; + const renderOS = () => { + if (os === null) { + // } || os.agent === 0) { // TODO: is that supposed to be "length"? + return ( + + n/a + + ); + } + return ( + + {os} + + {osver} + + + ); + }; + + return ( + + {name} + {niceTime(new Date(created))} + + {niceDuration( + expires - + (Date.now() - this.props.serverTimeBias), + )} + + {renderBrowser()} + {renderOS()} + {ip} + + + + + ); + }, + ); + return ( + + + + + + + + + + + + + {rows} +
NameCreatedExpiresBrowserOperating SystemIP Address{revokeAllButton}
+ ); + } + + renderDevTokens() { + if (this.props.tokens.length > 0) { + return this.renderTokenBrowser(this.props.tokens, 'Remove'); + } + return ( + + ); + } + + renderRemoveAll() { + return ( + + + + + + ); + } + + renderTokens() { + return ( + + Dev Tokens + {this.renderDevTokens()} + {this.renderRemoveAll()} + + ); + } + + renderHelp() { + return ( +
+

+ a sign-in session is created when you sign in to + KBase. A sign-in session is removed when you logout. + However, if you do not logout, your sign-in session will + remain active for two weeks. At the end of two weeks, the + sign-in session will become invalid, and you will need to + sign-in again. +

+
+ ); + } + + renderNewToken() { + if (!this.props.newToken) { + return; + } + + const onCopied = () => { + notifySuccess('Token copied to clipboard', 3000); + }; + + const onCopyError = (message: string) => { + // TODO: implement notification + console.warn('message ignored', message); + // this.props.runtime.notifyError( + // `Error copying token to clipboard: ${message}` + // ); + }; + + const onDone = () => { + this.props.clearNewToken(); + }; + + return ( + + ); + } + + renderNewTokenForm() { + return ( + + Create Dev Token + + + {this.renderNewToken()} + + + ); + } + + render() { + return ( +
+ {this.renderNewTokenForm()} + {this.renderTokens()} +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/controller.tsx new file mode 100644 index 000000000..99eed5c2e --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/controller.tsx @@ -0,0 +1,184 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Auth2, Identity } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import LinkedIdProvidersView from './view'; + +import { Providers } from 'apps/Auth2/Providers'; +import AutoPostForm from 'pluginSupport/AutoPostForm'; +import ReactDOM from 'react-dom/client'; +import { Config, IDProvider } from 'types/config'; + +export interface LinkedIdProvidersControllerProps { + config: Config; + token: string; + authURL: string; + // params: Record; + setTitle: (title: string) => void; +} + +export interface LinkedIdProviders { + identities: Array; + providers: Array; +} + +type LinkedIdProvidersControllerState = AsyncProcess< + LinkedIdProviders, + SimpleError +>; + +export default class LinkedIdProvidersController extends Component< + LinkedIdProvidersControllerProps, + LinkedIdProvidersControllerState +> { + constructor(props: LinkedIdProvidersControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.props.setTitle('Account Manager - Linked Sign-In Accounts'); + this.loadData(); + } + + async unlinkIdentity(identityId: string) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + try { + await auth2.removeLink(this.props.token, { + identityId, + }); + // this.props.runtime.notifySuccess( + // 'Successfully unlinked identity', + // 3000 + // ); + const identities = await this.fetchIdentities(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + identities, + }, + }); + } catch (ex) { + console.error(ex); + // this.props.runtime.notifyError( + // `Error unlinking: ${ex.message}` + // ); + } + } + + formPost({ + action, + params, + }: { + action: string; + params: Record; + }) { + const donorNode = document.createElement('div'); + document.body.appendChild(donorNode); + const props = { + action, + params, + }; + const root = ReactDOM.createRoot(donorNode); + root.render(); + } + + linkIdentity(providerId: string) { + try { + // TODO: routing back into here. + const params: Record = { + provider: providerId, + token: this.props.token, + }; + const action = `${this.props.authURL}/link/start`; + + // this.props.runtime.send('app', 'post-form', { + // action, + // params + // }); + + this.formPost({ action, params }); + + // this.auth2.linkStart(this.currentUserToken, { + // provider: providerId, + // node: this.container + // }); + } catch (ex) { + console.error(ex); + // this.props.runtime.notifyError( + // `Error starting the linking process: ${ex.message}` + // ); + } + } + + async fetchIdentities() { + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + + const { idents } = await auth2.getMe(authToken); + return idents; + } + + async loadData() { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + try { + const identities = await this.fetchIdentities(); + const providers = new Providers({ + supportedProviders: + this.props.config.services.Auth2.supportedProviders, + providers: this.props.config.services.Auth2.providers, + }).get(); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + identities, + providers, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ( + + ); + case AsyncProcessStatus.SUCCESS: + return ( + + ); + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.module.css b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.module.css new file mode 100644 index 000000000..44472c32a --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.module.css @@ -0,0 +1,26 @@ +.main { + flex: 1 1 0; + display: flex; + flex-direction: column; +} + +.providerLabel { + display: flex; + flex-direction: row; +} + +.logo { + flex: 0 0 3em; + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; +} + +.label { + flex: 1 1 0; + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.tsx b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.tsx new file mode 100644 index 000000000..49e6715df --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LinkedIDProviders/view.tsx @@ -0,0 +1,185 @@ +import { providerLabel, providerLogoSrc } from 'apps/Auth2/Providers'; +import TextSpan from 'apps/Auth2/TextSpan'; +import Well from 'components/Well'; +import { Identity } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Alert, Button, Dropdown, Form } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import styles from './view.module.css'; + +export interface LinkedIdProvidersViewProps { + providers: Array; + identities: Array; + linkIdentity: (id: string) => void; + unlinkIdentity: (id: string) => void; +} + +interface LinkedIdProvidersViewState { + canUnlink: boolean; + selectedProvider: IDProvider | null; +} + +export default class LinkedIdProvidersView extends Component< + LinkedIdProvidersViewProps, + LinkedIdProvidersViewState +> { + constructor(props: LinkedIdProvidersViewProps) { + super(props); + this.state = { + canUnlink: this.props.identities.length > 1, + selectedProvider: null, + }; + } + + renderProviderLabel(providerId: string) { + return ( +
+
+ +
+
{providerLabel(providerId)}
+
+ ); + } + + renderLinkedAccounts() { + const rows = this.props.identities.map((identity) => { + const tooltip = (() => { + if (this.state.canUnlink) { + return `Unlink this ${identity.provider} account from your KBase account`; + } + return 'Since this is the only external sign-in account linked to your KBase account, you cannot unlink it'; + })(); + return ( + + {this.renderProviderLabel(identity.provider)} + {identity.provusername} + + + + + ); + }); + return ( + + + + + + + + + {rows} +
ProviderUsernameAction
+ ); + } + + doSubmitLinkRequest() { + if (this.state.selectedProvider === null) { + return; + } + this.props.linkIdentity(this.state.selectedProvider.id); + } + + selectProvider(provider: IDProvider) { + this.setState({ + selectedProvider: provider, + }); + } + + renderAccountLinker() { + const availableProviders = this.props.providers.filter(({ id }) => { + return !this.props.identities.some(({ provider }) => { + return provider === id; + }); + }); + + if (availableProviders.length === 0) { + return ( + + All available id providers have been linked + + ); + } + + return ( +
{ + e.preventDefault(); + this.doSubmitLinkRequest(); + }} + > +
+ + an account from the identity provider +
+ + + Select a Provider + + + {availableProviders.map((provider) => { + return ( + { + this.selectProvider(provider); + }} + > + {this.renderProviderLabel( + provider.id, + )} + + ); + })} + + +
+
+
+ ); + } + + render() { + return ( +
+ + Currently Linked Accounts + {this.renderLinkedAccounts()} + + + + + Link an additional sign-in account to this KBase Account + + {this.renderAccountLinker()} + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LoginTokens/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/controller.tsx new file mode 100644 index 000000000..df503b581 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/controller.tsx @@ -0,0 +1,208 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { $GlobalMessenger, notifySuccess } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Auth2, Role, TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import ActiveTokensView from './view'; + +export interface LoginTokensControllerProps { + token: string; + roles: Array; + authURL: string; + setTitle: (title: string) => void; +} + +export interface LoginTokens { + tokens: Array; + current: TokenInfoFull; + serverTimeBias: number; +} + +type LoginTokensControllerState = AsyncProcess; + +export default class LoginTokensController extends Component< + LoginTokensControllerProps, + LoginTokensControllerState +> { + constructor(props: LoginTokensControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + componentDidMount() { + this.props.setTitle('Account Manager - Active Sign-In Sessions'); + this.loadData(); + } + + logout() { + $GlobalMessenger.send('session', 'logout', null); + } + + async revokeToken(tokenToRevoke: string) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + try { + await auth2.revokeToken(this.props.token, tokenToRevoke); + const { tokens } = await auth2.getTokens(this.props.token); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Login'; + }), + }, + }); + + notifySuccess('Login token successfully removed'); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async revokeAllTokens() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + try { + const { tokens: currentTokens } = await auth2.getTokens(authToken); + + // All others + await Promise.all( + currentTokens + .filter(({ type }) => { + return type === 'Login'; + }) + .map(({ id }) => { + return auth2.revokeToken(authToken, id); + }), + ); + + const { tokens } = await auth2.getTokens(authToken); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Login'; + }), + }, + }); + + notifySuccess('All Login tokens removed'); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async revokeAllTokensAndLogout() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + await this.revokeAllTokens(); + + await this.revokeCurrentTokenAndLogout(); + } + + async revokeCurrentTokenAndLogout() { + // const authToken = this.props.token + // const auth2Client = new Auth2({ baseUrl: this.props.authURL }) + try { + // TODO: compatibility with Europa! + // If this signs out here, it will leave Europa hanging, as it does not + // appear to monitor the cookie very frequently. + // await auth2Client.logout(authToken); + this.logout(); + + // notifySuccess('Successfully removed current Login token'); + + // navigate('auth2/signedout'); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alertpruntim e + } + } + + async getServerTimeBias() { + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const { servertime } = await auth2.root(); + return servertime - Date.now(); + } + + async loadData() { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + + try { + const { tokens, current } = await auth2.getTokens(this.props.token); + + const serverTimeBias = await this.getServerTimeBias(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + tokens: tokens.filter((token) => { + return token.type === 'Login'; + }), + current, + serverTimeBias, + }, + }); + } catch (ex) { + console.error(ex); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: { + const { tokens, current, serverTimeBias } = this.state.value; + return ( + + ); + } + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.module.css b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.module.css new file mode 100644 index 000000000..77b5687fc --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.module.css @@ -0,0 +1,10 @@ +.main { + flex: 1 1 0; + display: flex; + flex-direction: column; +} + +/* Middle vertical align table cells in this module. */ +.main :global .table td { + vertical-align: middle; +} diff --git a/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.tsx b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.tsx new file mode 100644 index 000000000..f3ca6a5ec --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/LoginTokens/view.tsx @@ -0,0 +1,262 @@ +import Empty from 'components/Empty'; +import Well from 'components/Well'; +import { TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { niceDuration, niceTime } from 'lib/time'; +import { Component } from 'react'; +import { Button, ButtonGroup, ButtonToolbar, Table } from 'react-bootstrap'; +import styles from './view.module.css'; + +export interface LoginTokensViewProps { + tokens: Array; + currentToken: TokenInfoFull; + serverTimeBias: number; + revokeCurrentTokenAndLogout: () => void; + revokeAllTokensAndLogout: () => void; + revokeToken: (token: string) => void; + revokeAllTokens: () => void; +} + +interface LoginTokensViewState {} + +export default class LoginTokensView extends Component< + LoginTokensViewProps, + LoginTokensViewState +> { + doRevokeToken(tokenId: string) { + if (tokenId === this.props.currentToken.id) { + this.props.revokeCurrentTokenAndLogout(); + } else { + this.props.revokeToken(tokenId); + } + } + + doRevokeAllTokens() { + this.props.revokeAllTokens(); + } + + doRevokeAllTokensAndLogout() { + this.props.revokeAllTokensAndLogout(); + } + + renderTokenBrowser(tokens: Array, removeVerb: string) { + const revokeAllButton = (() => { + if (tokens.length > 1) { + return ( + + ); + } + })(); + const rows = tokens.map( + ({ id, created, expires, os, osver, agent, agentver, ip }) => { + const renderBrowser = () => { + if (agent === null) { + // } || agent.agent === 0) { // TODO: what is this actual type??? + return ( + + n/a + + ); + } + return ( + + {agent} + + {agentver} + + + ); + }; + const renderOS = () => { + if (os === null) { + // } || os.agent === 0) { // TODO: is that supposed to be "length"? + return ( + + n/a + + ); + } + return ( + + {os} + + {osver} + + + ); + }; + + return ( + + {niceTime(new Date(created))} + + {niceDuration( + expires - + (Date.now() - this.props.serverTimeBias), + )} + + {renderBrowser()} + {renderOS()} + {ip} + + + + + ); + }, + ); + return ( + + + + + + + + + + + + {rows} +
CreatedExpiresBrowserOperating SystemIP Address{revokeAllButton}
+ ); + } + + renderCurrentToken() { + return this.renderTokenBrowser([this.props.currentToken], 'Logout'); + } + + renderOtherTokens() { + if (this.props.tokens.length > 0) { + return this.renderTokenBrowser(this.props.tokens, 'Remove'); + } + return ( + + You do not have any additional active sign-in sessions. + + ); + } + + renderRemoveAll() { + return ( + + + + + + ); + } + + renderRemoveAllAndLogout() { + return ( + + + + + + ); + } + + renderCurrentSession() { + return ( + + Your Current Login Session + {this.renderCurrentToken()} + + ); + } + + renderOtherSessions() { + return ( + + Other Login Sessions + {this.renderOtherTokens()} + {this.renderRemoveAll()} + + ); + } + + renderHelp() { + return ( +
+

+ a sign-in session is created when you sign in to + KBase. A sign-in session is removed when you logout. + However, if you do not logout, your sign-in session will + remain active for two weeks. At the end of two weeks, the + sign-in session will become invalid, and you will need to + sign-in again. +

+
+ ); + } + + render() { + return ( +
+ {this.renderRemoveAllAndLogout()} + {this.renderCurrentSession()} + {this.renderOtherSessions()} +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/ServToken/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/ServToken/controller.tsx new file mode 100644 index 000000000..9be722eed --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/ServToken/controller.tsx @@ -0,0 +1,217 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { notifySuccess } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Auth2, Role, TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import ActiveTokensView from './view'; + +export interface ServTokensControllerProps { + token: string; + roles: Array; + authURL: string; + setTitle: (title: string) => void; +} + +export interface ServTokens { + tokens: Array; + newToken: TokenInfoFull | null; + serverTimeBias: number; +} + +type ServTokensControllerState = AsyncProcess; + +export default class ServTokensController extends Component< + ServTokensControllerProps, + ServTokensControllerState +> { + constructor(props: ServTokensControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + componentDidMount() { + this.props.setTitle('Account Manager - Service Tokens'); + this.loadData(); + } + + async revokeToken(tokenToRevoke: string, name: string) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + try { + await auth2.revokeToken(this.props.token, tokenToRevoke); + const { tokens } = await auth2.getTokens(this.props.token); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Service'; + }), + }, + }); + + notifySuccess(`Service token "${name}" as been revoked`); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async revokeAllTokens() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + try { + const { tokens: currentTokens } = await auth2.getTokens(authToken); + + // All others + await Promise.all( + currentTokens + .filter(({ type }) => { + return type === 'Service'; + }) + .map(({ id }) => { + return auth2.revokeToken(authToken, id); + }), + ); + + const { tokens } = await auth2.getTokens(authToken); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + ...this.state.value, + tokens: tokens.filter((token) => { + return token.type === 'Service'; + }), + }, + }); + + notifySuccess(`All service tokens have been revoked`); + } catch (ex) { + console.error(ex); + // TODO: what now? probably send an alert + } + } + + async getServerTimeBias() { + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const { servertime } = await auth2.root(); + return servertime - Date.now(); + } + + async loadData() { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + + try { + const { tokens } = await auth2.getTokens(this.props.token); + + const serverTimeBias = await this.getServerTimeBias(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + tokens: tokens.filter((token) => { + return token.type === 'Service'; + }), + newToken: null, + serverTimeBias, + }, + }); + } catch (ex) { + console.error(ex); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + async createServiceToken(name: string) { + const state = this.state; + if (state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + + const auth2 = new Auth2({ + baseUrl: this.props.authURL, + }); + const authToken = this.props.token; + try { + const newToken = await auth2.createToken(authToken, { + name, + type: 'service', + }); + + this.setState({ + ...state, + value: { + ...state.value, + newToken, + tokens: state.value.tokens.concat([newToken]), + }, + }); + + notifySuccess(`New service token named "${name}" has been created`); + } catch (ex) { + console.error(ex); + // what to do - notification? + } + } + + clearNewToken() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + this.setState({ + ...this.state, + value: { + ...this.state.value, + newToken: null, + }, + }); + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: { + const { tokens, newToken, serverTimeBias } = this.state.value; + return ( + + ); + } + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/ServToken/view.module.css b/vite-app/src/apps/Auth2/AccountManager/ServToken/view.module.css new file mode 100644 index 000000000..056ab60b4 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/ServToken/view.module.css @@ -0,0 +1,5 @@ +.main { + flex: 1 1 0; + display: flex; + flex-direction: column; +} diff --git a/vite-app/src/apps/Auth2/AccountManager/ServToken/view.tsx b/vite-app/src/apps/Auth2/AccountManager/ServToken/view.tsx new file mode 100644 index 000000000..acbef04c1 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/ServToken/view.tsx @@ -0,0 +1,290 @@ +import Empty from 'components/Empty'; +import Well from 'components/Well'; +import { notifySuccess } from 'contexts/EuropaContext'; +import { TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { niceDuration, niceTime } from 'lib/time'; +import { Component } from 'react'; +import { Button, ButtonGroup, ButtonToolbar } from 'react-bootstrap'; +import AddTokenForm from '../AddTokenForm'; +import TokenCopy from '../TokenCopy'; +import styles from './view.module.css'; + +const TOKEN_VIEWER_EXPIRES_IN = 300000; + +export interface ServTokensViewProps { + tokens: Array; + newToken: TokenInfoFull | null; + serverTimeBias: number; + revokeToken: (token: string, name: string) => void; + revokeAllTokens: () => void; + createServiceToken: (name: string) => void; + clearNewToken: () => void; +} + +interface ServTokensViewState {} + +export default class ServTokensView extends Component< + ServTokensViewProps, + ServTokensViewState +> { + doRevokeToken(tokenId: string, name: string) { + this.props.revokeToken(tokenId, name); + } + + doRevokeAllTokens() { + this.props.revokeAllTokens(); + } + + renderTokenBrowser(tokens: Array, removeVerb: string) { + const revokeAllButton = (() => { + if (tokens.length > 1) { + return ( + + ); + } + })(); + const rows = tokens.map( + ({ + name, + id, + created, + expires, + os, + osver, + agent, + agentver, + ip, + }) => { + const renderBrowser = () => { + if (agent === null) { + // } || agent.agent === 0) { // TODO: what is this actual type??? + return ( + + n/a + + ); + } + return ( + + {agent} + + {agentver} + + + ); + }; + const renderOS = () => { + if (os === null) { + // } || os.agent === 0) { // TODO: is that supposed to be "length"? + return ( + + n/a + + ); + } + return ( + + {os} + + {osver} + + + ); + }; + + return ( + + {name} + {niceTime(new Date(created))} + + {niceDuration( + expires - + (Date.now() - this.props.serverTimeBias), + )} + + {renderBrowser()} + {renderOS()} + {ip} + + + + + ); + }, + ); + return ( + + + + + + + + + + + + + {rows} +
NameCreatedExpiresBrowserOperating SystemIP Address{revokeAllButton}
+ ); + } + + renderServTokens() { + if (this.props.tokens.length > 0) { + return this.renderTokenBrowser(this.props.tokens, 'Remove'); + } + return ( + + ); + } + + renderRemoveAll() { + return ( + + + + + + ); + } + + renderTokens() { + return ( + + Service Tokens + {this.renderServTokens()} + {this.renderRemoveAll()} + + ); + } + + renderHelp() { + return ( +
+

+ a sign-in session is created when you sign in to + KBase. A sign-in session is removed when you logout. + However, if you do not logout, your sign-in session will + remain active for two weeks. At the end of two weeks, the + sign-in session will become invalid, and you will need to + sign-in again. +

+
+ ); + } + + renderNewToken() { + if (!this.props.newToken) { + return; + } + + const onCopied = () => { + notifySuccess('Token copied to clipboard', 3000); + }; + + const onCopyError = (message: string) => { + console.error('message', message); + // this.props.runtime.notifyError( + // `Error copying token to clipboard: ${message}` + // ); + }; + + const onDone = () => { + this.props.clearNewToken(); + + // this.props.runtime.send('notification', 'notify', { + // type: 'warning', + // id: 'devtoken', + // icon: 'ban', + // message: 'The Developer Token session has been canceled', + // description: 'The Developer Token session has been canceled', + // autodismiss: 10000 + // }); + }; + + return ( + + ); + } + + renderNewTokenForm() { + return ( + + Create Service Token + + + {this.renderNewToken()} + + + ); + } + + render() { + return ( +
+ {this.renderNewTokenForm()} + {this.renderTokens()} +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/controller.tsx new file mode 100644 index 000000000..e605125f6 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/controller.tsx @@ -0,0 +1,92 @@ +import PolicyAndAgreement, { + PolicyAgreement, +} from 'apps/Auth2/SignInContinue/PolicyAndAgreement'; +import ErrorMessage from 'components/ErrorMessage'; +import Loading from 'components/Loading'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Auth2 } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import TermsAndConditionsView from './view'; + +export interface TermsAndConditionsControllerProps { + authURL: string; + token: string; + // authState: AuthenticationState, + // config: Config, + setTitle: (title: string) => void; +} + +export interface TermsAndConditions { + agreement: PolicyAgreement; +} + +type TermsAndConditionsControllerState = AsyncProcess< + TermsAndConditions, + SimpleError +>; + +export default class TermsAndConditionsController extends Component< + TermsAndConditionsControllerProps, + TermsAndConditionsControllerState +> { + constructor(props: TermsAndConditionsControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.props.setTitle('Account Manager - Terms and Conditions'); + this.loadData(); + } + + async loadData() { + const auth2 = new Auth2({ baseUrl: this.props.authURL }); + + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + try { + const { policyids } = await auth2.getMe(this.props.token); + + const policies = new PolicyAndAgreement({ + policyids, + }); + + const policyAgreement = policies.getPolicyAgreement(); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + agreement: policyAgreement, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.ERROR: + return ; + case AsyncProcessStatus.SUCCESS: + return ( + + ); + } + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/view.tsx b/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/view.tsx new file mode 100644 index 000000000..0d8f195ed --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/TermsAndConditions/view.tsx @@ -0,0 +1,138 @@ +import { PolicyAgreement } from 'apps/Auth2/SignInContinue/PolicyAndAgreement'; +import Well from 'components/Well'; +import { niceTime } from 'lib/time'; +import { Component } from 'react'; +import { Button, Col, Container, Form, Row } from 'react-bootstrap'; + +export interface TermsAndConditionsViewProps { + agreement: PolicyAgreement; +} + +interface TermsAndConditionsViewState {} + +export default class TermsAndConditionsView extends Component< + TermsAndConditionsViewProps, + TermsAndConditionsViewState +> { + renderInfo() { + return ( + + + + + View the Terms and Conditions + +
+ +
+ + + + View the current Terms and Conditions on the KBase + website. + + +
+ + + + Version + +
+ {this.props.agreement.currentPolicy.version} +
+ + + + The KBase Terms and Conditions is updated from time + to time; each updated has a new version. + + +
+ + + + Published At + +
+ {niceTime( + this.props.agreement.currentPolicy.publishedAt, + )} +
+ + + + The KBase Terms and Conditions is updated from time + to time; each updated has a new publication date. + + +
+ + + + Agreed At + +
+ {niceTime(this.props.agreement.agreement!.agreedAt)} +
+ + + + When you sign up for KBase, and the first time you + sign in after a new Terms and Conditions has been + published, you will need to agree to the new + T&C. We record this agreement date and time in + your KBase account. + + +
+ {/* + +
+ +
+
{niceRelativeTime(new Date(lastlogin))} ({niceTime(new Date(lastlogin))})
+ + + + When you last signed in to KBase + + +
*/} +
+ ); + } + render() { + return ( +
+ + Terms and Conditions + {this.renderInfo()} + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/TokenCopy.tsx b/vite-app/src/apps/Auth2/AccountManager/TokenCopy.tsx new file mode 100644 index 000000000..85d9a9558 --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/TokenCopy.tsx @@ -0,0 +1,95 @@ +import Well from 'components/Well'; +import { TokenInfoFull } from 'lib/kb_lib/Auth2'; +import { niceDuration } from 'lib/time'; +import { Component } from 'react'; +import { Button, ButtonToolbar } from 'react-bootstrap'; +import CountdownAlarmClock from '../CountdownAlarmClock'; + +const DEFAULT_EXPIRES_IN = 300000; + +export interface TokenCopyProps { + newToken: TokenInfoFull; + expiresIn: number; + onCopied: () => void; + onDone: () => void; + onCopyError: (message: string) => void; +} + +export default class TokenCopy extends Component { + render() { + let clipboardButton = null; + if (navigator && navigator.clipboard) { + const copyNewToken = async () => { + try { + await navigator.clipboard.writeText( + this.props.newToken.token, + ); + this.props.onCopied(); + } catch (ex) { + console.error(ex); + this.props.onCopyError( + ex instanceof Error ? ex.message : 'Unknown Error', + ); + } + }; + clipboardButton = ( + + ); + } + return ( + + +

+ New {this.props.newToken.type} token named{' '} + {this.props.newToken.name} successfully created +

+

+ Please copy it to a secure location and remove this + message. +

+

+ This message will self-destruct in{' '} + + { + return ( + {niceDuration(timeLeft)} + ); + }} + /> + + . +

+

+ New Token{' '} + + {this.props.newToken.token} + +

+ + {clipboardButton} + + +
+
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/controller.tsx b/vite-app/src/apps/Auth2/AccountManager/controller.tsx new file mode 100644 index 000000000..6194c92fe --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/controller.tsx @@ -0,0 +1,31 @@ +import { RouteProps } from 'components/Router2'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { Component } from 'react'; +import { Config } from 'types/config'; +import AccountManagerView from './view'; + +export interface AccountManagerControllerProps extends RouteProps { + authState: AuthenticationStateAuthenticated; + config: Config; + setTitle: (title: string) => void; + // logout: () => void; +} + +interface AccountManagerControllerState {} + +export default class AccountManagerController extends Component< + AccountManagerControllerProps, + AccountManagerControllerState +> { + render() { + return ( + + ); + } +} diff --git a/vite-app/src/apps/Auth2/AccountManager/view.tsx b/vite-app/src/apps/Auth2/AccountManager/view.tsx new file mode 100644 index 000000000..0a409747e --- /dev/null +++ b/vite-app/src/apps/Auth2/AccountManager/view.tsx @@ -0,0 +1,319 @@ +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { navigate2 } from 'lib/navigation'; +import { Component } from 'react'; +import { Nav, Tab, TabContainer } from 'react-bootstrap'; +import { Config } from 'types/config'; +import AccountEditorController from './Account/controller'; +import DevTokensController from './DevToken/controller'; +import LinkedIdProvidersController from './LinkedIDProviders/controller'; +import LoginTokensController from './LoginTokens/controller'; +import ServTokensController from './ServToken/controller'; +import TermsAndConditionsController from './TermsAndConditions/controller'; + +export interface AccountManagerViewProps { + config: Config; + authState: AuthenticationStateAuthenticated; + tab?: string; + setTitle: (title: string) => void; + // logout: () => void; +} + +export default class AccountManagerView extends Component { + renderDevTokenTab() { + if ( + !this.props.authState.authInfo.account.roles.find(({ id }) => { + return id === 'DevToken'; + }) + ) { + return; + } + return ( + +
+ +
+
+ ); + } + + renderServerTokenTab() { + if ( + !this.props.authState.authInfo.account.roles.find(({ id }) => { + return id === 'ServToken'; + }) + ) { + return; + } + return ( + +
+ +
+
+ ); + } + + // renderx() { + // return { + // if (eventKey === null) { + // eventKey = 'account'; + // } + // // navigate(`account/${eventKey}`, {params: {tab: eventKey}}); + // navigate(`account&tab=${eventKey}`); + // }} + // unmountOnExit> + // + //
+ // + //
+ //
+ // + //
+ // + //
+ //
+ // + //
+ // + //
+ //
+ // {this.renderDevTokenTab()} + // {this.renderServerTokenTab()} + // + //
+ // + //
+ //
+ //
+ // } + + render() { + const hasServToken = this.props.authState.authInfo.account.roles.find( + ({ id }) => { + return id === 'ServToken'; + }, + ); + const hasDevToken = this.props.authState.authInfo.account.roles.find( + ({ id }) => { + return id === 'DevToken'; + }, + ); + return ( + { + if (eventKey === null) { + eventKey = 'account'; + } + navigate2({ + path: `account`, + params: { tab: eventKey }, + type: 'kbaseui', + }); + // navigate(`account&tab=${eventKey}`); + }} + unmountOnExit + > +
+
+ +
+
+ + + + + + + + + + + + {(() => { + if (!hasServToken) { + return; + } + return ( + + + + ); + })()} + + {(() => { + if (!hasDevToken) { + return; + } + return ( + + + + ); + })()} + + + + + +
+
+
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/Collapsible.css b/vite-app/src/apps/Auth2/Collapsible.css new file mode 100644 index 000000000..35dd41c18 --- /dev/null +++ b/vite-app/src/apps/Auth2/Collapsible.css @@ -0,0 +1,2 @@ +.Collapsible { +} diff --git a/vite-app/src/apps/Auth2/Collapsible.tsx b/vite-app/src/apps/Auth2/Collapsible.tsx new file mode 100644 index 000000000..e5d37b653 --- /dev/null +++ b/vite-app/src/apps/Auth2/Collapsible.tsx @@ -0,0 +1,52 @@ +import Well, { Variant } from 'components/Well'; +import { CSSProperties, Component, PropsWithChildren, ReactNode } from 'react'; +import { Button, Collapse } from 'react-bootstrap'; +import './Collapsible.css'; + +export interface CollapsibleProps extends PropsWithChildren { + title: ReactNode; + variant: Variant; + style?: CSSProperties; + // Annoying to need a render prop; but the Collapse component does not take the + // standard react children prop. + render: () => JSX.Element; +} + +interface CollapsibleState { + open: boolean; +} + +export default class Collapsible extends Component< + CollapsibleProps, + CollapsibleState +> { + constructor(props: CollapsibleProps) { + super(props); + this.state = { + open: false, + }; + } + + render() { + return ( +
+ + + + {this.props.render()} + + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/CountdownAlarmClock.tsx b/vite-app/src/apps/Auth2/CountdownAlarmClock.tsx new file mode 100644 index 000000000..090e0dbcd --- /dev/null +++ b/vite-app/src/apps/Auth2/CountdownAlarmClock.tsx @@ -0,0 +1,76 @@ +import { Component } from 'react'; +import CountdownClock from './CountdownClock'; + +export interface CountdownAlarmClockProps { + expiresIn?: number; + expiresAt?: number; + onExpired: () => void; + render: (remaining: number) => JSX.Element; +} + +enum CountdownAlarmClockStatus { + NONE = 'NONE', + RUNNING = 'RUNNING', + DONE = 'DONE', +} + +interface CountdownAlarmClockState { + status: CountdownAlarmClockStatus; + remaining: number; +} + +export default class CountdownAlarmClock extends Component< + CountdownAlarmClockProps, + CountdownAlarmClockState +> { + clock: CountdownClock; + constructor(props: CountdownAlarmClockProps) { + super(props); + this.clock = new CountdownClock({ + // tick: 1000, + expiresIn: this.props.expiresIn, + expiresAt: this.props.expiresAt, + onTick: this.onTick.bind(this), + onExpired: this.onExpired.bind(this), + }); + this.state = { + status: CountdownAlarmClockStatus.NONE, + remaining: this.clock.remaining(), + }; + } + + componentDidMount() { + this.clock.start(); + } + + componentWillUnmount() { + if (this.clock === null) { + return; + } + this.clock.stop(); + } + + onTick(remaining: number) { + this.setState({ + status: CountdownAlarmClockStatus.RUNNING, + remaining, + }); + } + + onExpired() { + this.props.onExpired(); + this.setState({ + status: CountdownAlarmClockStatus.DONE, + }); + } + + render() { + switch (this.state.status) { + case 'NONE': + case 'RUNNING': + return this.props.render(this.state.remaining); + case 'DONE': + return this.props.render(0); + } + } +} diff --git a/vite-app/src/apps/Auth2/CountdownClock.tsx b/vite-app/src/apps/Auth2/CountdownClock.tsx new file mode 100644 index 000000000..fea4f8f5c --- /dev/null +++ b/vite-app/src/apps/Auth2/CountdownClock.tsx @@ -0,0 +1,90 @@ +const DEFAULT_TICK_INTERVAL = 250; + +export interface CountdownClockParams { + expiresAt?: number; + expiresIn?: number; + tick?: number; + onTick: (remaining: number) => void; + onExpired: () => void; +} + +enum CountdownClockStatus { + NONE = 'NONE', + RUNNING = 'RUNNING', + STOPPED = 'STOPPED', +} + +export default class CountdownClock { + params: CountdownClockParams; + targetTime: number; + tickInterval: number; + timer: number | null; + status: CountdownClockStatus; + constructor(params: CountdownClockParams) { + this.params = params; + const { expiresAt, expiresIn, tick } = params; + // Either countdown until a specific time ... + if (expiresAt) { + this.targetTime = expiresAt; + // ... or for a quantity of time. + } else if (expiresIn) { + this.targetTime = new Date().getTime() + expiresIn; + } else { + console.error; + throw new Error( + 'Either "expiresAt" or "expiresIn" must be provided', + ); + } + this.tickInterval = tick || DEFAULT_TICK_INTERVAL; + // this.onTick = onTick; + // this.onExpired = onExpired; + this.timer = null; + this.status = CountdownClockStatus.NONE; + } + + remaining() { + const now = new Date().getTime(); + return this.targetTime - now; + } + + tick() { + if (this.status !== 'RUNNING') { + return; + } + const remaining = this.remaining(); + try { + this.params.onTick(remaining); + } catch (ex) { + console.error( + `clock onRun: ${ex instanceof Error ? ex.message : 'Unknown Error'}`, + ); + } + if (remaining > 0) { + this.tock(); + } else { + this.params.onExpired(); + } + } + + tock() { + this.timer = window.setTimeout(() => { + if (!this.timer) { + return; + } + this.tick(); + }, this.tickInterval); + } + + start() { + this.status = CountdownClockStatus.RUNNING; + this.tick(); + } + + stop() { + this.status = CountdownClockStatus.STOPPED; + if (this.timer) { + window.clearTimeout(this.timer); + this.timer = null; + } + } +} diff --git a/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.css b/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.css new file mode 100644 index 000000000..fa35a000b --- /dev/null +++ b/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.css @@ -0,0 +1,21 @@ +.ContinueHeader { + flex: 0 0 auto; + display: flex; + flex-direction: row; + padding-bottom: 0.25em; + margin-bottom: 0.25em; + /* border-bottom: 1px solid rgba(200, 200, 200, 0.5); */ +} + +.ContinueHeader .-col1 { + flex: 1 1 0; + font-weight: bold; + font-size: 120%; + display: flex; + flex-direction: row; + align-items: center; +} + +.ContinueHeader .-col2 { + flex: 0 0 auto; +} diff --git a/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.tsx b/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.tsx new file mode 100644 index 000000000..f0ded77ef --- /dev/null +++ b/vite-app/src/apps/Auth2/LinkContinue/ContinueHeader.tsx @@ -0,0 +1,38 @@ +import CountdownClock from 'components/CountdownClock'; +import { LinkChoice } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Alert } from 'react-bootstrap'; +import TextSpan from '../TextSpan'; +import './ContinueHeader.css'; + +export interface ContinueHeaderProps { + choice: LinkChoice; + serverTimeOffset: number; + name: string; + cancelChoiceSession: () => void; +} + +export default class ContinueHeader extends Component { + render() { + if (this.props.choice === null) { + return; + } + + return ( + + You have{' '} + + + {' '} + to complete linking. + + ); + } +} diff --git a/vite-app/src/apps/Auth2/LinkContinue/controller.tsx b/vite-app/src/apps/Auth2/LinkContinue/controller.tsx new file mode 100644 index 000000000..630c510e7 --- /dev/null +++ b/vite-app/src/apps/Auth2/LinkContinue/controller.tsx @@ -0,0 +1,334 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { + AuthenticationStateAuthenticated, + notifySuccess, +} from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { Auth2, LinkChoice } from 'lib/kb_lib/Auth2'; +import { AuthError } from 'lib/kb_lib/Auth2Error'; +import { navigate } from 'lib/navigation'; +import { Component } from 'react'; +import { Button } from 'react-bootstrap'; +import { Config } from 'types/config'; +import { AlmostSimpleError } from '../SignInContinue/SignInContinue'; +import TextSpan from '../TextSpan'; +import LinkContinueView from './view'; + +export interface LinkContinueControllerProps { + authState: AuthenticationStateAuthenticated; + config: Config; + setTitle: (title: string) => void; +} + +export interface LinkController { + linkChoice: LinkChoice; + serverTimeOffset: number; +} + +type LinkContinueControllerState = AsyncProcess< + LinkController, + AlmostSimpleError +>; + +export default class LinkContinueController extends Component< + LinkContinueControllerProps, + LinkContinueControllerState +> { + constructor(props: LinkContinueControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + componentDidMount() { + this.start(); + } + + async cancelLink(message: string) { + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + try { + await auth2Client.linkCancel(); + notifySuccess(message, 3000); + this.returnToLinkingTab(); + } catch (ex) { + console.error(ex); + // if (ex instanceof AuthError) { + // if (ex.code === '10010') { + // // simply continue + // } else { + // throw ex; + // } + // } + } + } + + returnToLinkingTab() { + navigate('account', { + params: { + tab: 'links', + }, + }); + } + + async linkIdentity() { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + const authToken = this.props.authState.authInfo.token; + const auth2 = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + try { + await auth2.linkPick(authToken, this.state.value.linkChoice.id); + // this.props.runtime.notifySuccess('Successfully linked identity', 3000); + navigate('account', { + params: { + tab: 'links', + }, + }); + } catch (ex) { + console.error(ex); + // this.props.runtime.notifyError( + // `Error linking: ${ex.message}` + // ); + } + } + + renderCancelAndReturnButton() { + return ( + + ); + } + + renderReturnButton() { + return ( + + ); + } + + async start() { + try { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + this.props.setTitle('Link a Provider'); + + const authToken = this.props.authState.authInfo.token; + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + const root = await auth2Client.root(); + + const serverTimeOffset = new Date().getTime() - root.servertime; + + const linkChoice = await auth2Client.getLinkChoice(authToken); + const { canlink, linkeduser, provider, provusername } = linkChoice; + + const currentUsername = this.props.authState.authInfo.account.user; + + if (!canlink) { + if (linkeduser === currentUsername) { + const message = ( +
+

+ Sorry, you have already linked your current + KBase account + + {currentUsername} + + to this + {provider} + sign-in account + {provusername} +

+

+ A sign-in account may only be linked once to any + KBase account. +

+

+ You may {this.renderCancelAndReturnButton()} + and start again, this time choosing a different + sign-in account to link to. +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Sign-in account already linked', + message, + }, + }); + return; + } + const message = ( +
+

+ Sorry, you have already linked this + {provider} + sign-in account + {provusername} + to the KBase account + {linkeduser} +

+

+ A sign-in account may only be linked once to any + KBase account. +

+

+ You may {this.renderCancelAndReturnButton()} and + start again, this time choosing a different sign-in + account to link to. +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Sign-in account already linked', + message, + }, + }); + return; + } + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + linkChoice, + serverTimeOffset, + }, + }); + } catch (ex) { + console.error(ex); + if (ex instanceof AuthError) { + if (ex.code === '10010') { + const message = ( +
+

+ A linking session was not found. This may be due + to the expiration of the linking session, which + is valid for 10 minutes. Or it may be because + you have visited this path from your browser + history. +

+

+ You may {this.renderReturnButton()} and try to + link again. +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Link Session Expired or Missing', + message, + }, + }); + } else if (ex.code === '10020') { + const message = ( +
+

+ The linking session has expired. A linking + session is valid for 30 minutes. +

+

+ +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Linking Session Expired', + message, + }, + }); + } else { + const message = ( +
+

+ The linking session has experienced an error ( + {ex.code}) +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Linking Session Error', + message, + }, + }); + } + } else { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Error', + message: + ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: { + const { linkChoice, serverTimeOffset } = this.state.value; + return ( + + ); + } + // case AsyncProcessStatus.ERROR: + // return html` + // <${Alert} variant="warning" title=${this.state.title} showIcon=${true} showTitle=${true} message=${this.state.message} /> + // `; + case AsyncProcessStatus.ERROR: + return ( + + {this.state.error.message} + + ); + } + } +} diff --git a/vite-app/src/apps/Auth2/LinkContinue/view.css b/vite-app/src/apps/Auth2/LinkContinue/view.css new file mode 100644 index 000000000..f03e4dd45 --- /dev/null +++ b/vite-app/src/apps/Auth2/LinkContinue/view.css @@ -0,0 +1,5 @@ +.LinkContinue { + flex: 1 1 0; + display: flex; + flex-direction: column; +} diff --git a/vite-app/src/apps/Auth2/LinkContinue/view.tsx b/vite-app/src/apps/Auth2/LinkContinue/view.tsx new file mode 100644 index 000000000..56192955d --- /dev/null +++ b/vite-app/src/apps/Auth2/LinkContinue/view.tsx @@ -0,0 +1,79 @@ +import Well from 'components/Well'; +import { LinkChoice } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Button, ButtonToolbar } from 'react-bootstrap'; +import { providerLabel } from '../Providers'; +import TextSpan from '../TextSpan'; +import ContinueHeader from './ContinueHeader'; + +export interface LinkContinueViewProps { + linkChoice: LinkChoice; + serverTimeOffset: number; + cancelLink: (message: string) => void; + linkIdentity: () => void; +} + +interface LinkContinueViewState {} + +export default class LinkContinueView extends Component< + LinkContinueViewProps, + LinkContinueViewState +> { + renderContinueDialog() { + return ( +
+

+ You have requested to link the + + {providerLabel(this.props.linkChoice.provider)} + {' '} + account + + {this.props.linkChoice.provusername} + {' '} + to your KBase account + {this.props.linkChoice.user} +

+ + + + +
+ ); + } + render() { + return ( +
+ { + this.props.cancelLink( + 'Your Linking session has expired', + ); + }} + serverTimeOffset={this.props.serverTimeOffset} + /> + + + Ready to Link + + {this.renderContinueDialog()} + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/Providers.ts b/vite-app/src/apps/Auth2/Providers.ts new file mode 100644 index 000000000..33f33cd7d --- /dev/null +++ b/vite-app/src/apps/Auth2/Providers.ts @@ -0,0 +1,78 @@ +import { IDProvider } from 'types/config'; + +import globusButtonLogo from './resources/providers/globus/logo.png'; +import googleButtonLogo from './resources/providers/google/logo.png'; +import orcidButtonLogo from './resources/providers/orcid/logo.png'; + +// Unfortunately the auth service does not have a concept of the +// "official label" for an id provider. +export function renderProviderLabel(providerId: string) { + return ( + { + OrcID: 'ORCID', + Google: 'Google', + Globus: 'Globus', + }[providerId] || 'Unknown' + ); +} + +export function providerLogoSrc(providerId: string) { + switch (providerId) { + case 'Google': + return googleButtonLogo; + case 'Globus': + return globusButtonLogo; + case 'OrcID': + return orcidButtonLogo; + default: + return null; + } +} + +export function providerLabel(providerId: string) { + switch (providerId) { + case 'Google': + return 'Google'; + case 'Globus': + return 'Globus'; + case 'OrcID': + return 'ORCiD'; + default: + return null; + } +} + +export interface ProvidersParams { + supportedProviders: Array; + providers?: Array; +} + +export class Providers { + providers: Array; + constructor({ supportedProviders, providers }: ProvidersParams) { + this.providers = supportedProviders.filter((provider) => { + if (providers) { + return providers.includes(provider.id); + } + return true; + }); + this.sortByPriority(); + } + + sortByPriority() { + this.providers.sort((a, b) => { + const priorityOrder = a.priority - b.priority; + if (priorityOrder !== 0) { + return priorityOrder; + } + + const labelOrder = + a.label < b.label ? -1 : a.label > b.label ? 0 : 1; + return labelOrder; + }); + } + + get() { + return this.providers; + } +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignIn.tsx b/vite-app/src/apps/Auth2/SignIn/SignIn.tsx new file mode 100644 index 000000000..134ea9477 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignIn.tsx @@ -0,0 +1,185 @@ +import ErrorMessage from 'components/ErrorMessage'; +import Loading from 'components/Loading'; +import { RouteProps } from 'components/Router2'; +import { + AuthenticationState, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { NextRequestObject } from 'lib/NextRequest'; +import { SimpleError } from 'lib/SimpleError'; +import { navigate2 } from 'lib/navigation'; +import { Component } from 'react'; +import { Config } from 'types/config'; +import { SignInSource, SignInView } from './SignInView'; + +export interface SignInParams { + nextrequest: string; +} + +export interface SignInProps extends RouteProps { + // params: SignInParams + // nextrequest: string, + authState: AuthenticationState; + config: Config; + source: SignInSource; + setTitle: (title: string) => void; +} + +export interface SignInSuccessState { + nextRequest: NextRequestObject | null; +} + +export type SignInState = AsyncProcess; + +export class SignIn extends Component { + constructor(props: SignInProps) { + super(props); + + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.prepare(); + } + + /** + * We use this lifecycle call because the sign-in component may be invoked + * repeatedly without any inetervening route if the user clicks on buttons or links + * which cause the signin compnent to be rendered for different target paths. + * + * The incoming prop for the hash path will have changed, but this will not + * naturally cause the re-rendering of the sign in component. We need it to + * re-render as part of the ui represents the "sign in required" notification which + * reflects the route the user intended to invoke w/o auth. + * + * Actually, the other approach is now used -- to place a key on the invocation of + * this component - with that key being the hash path of the target route. That + * causes this component to be remounted when the hash path changes. + * + * @param prevProps + * @param prevState + */ + // componentDidUpdate(prevProps: SignInProps, _: SignInState) { + // // TODO: should also compare params. + // if (prevProps.hashPath.hash !== this.props.hashPath.hash) { + // this.prepare(); + // } + // } + + getNextRequest(): NextRequestObject | null { + if ( + this.props.hashPath.params && + Object.keys(this.props.hashPath.params).includes('nextrequest') + ) { + return JSON.parse(this.props.hashPath.params['nextrequest']!); + } + return null; + } + + // ?source=authorization&nextrequest=%7B%22realPath%22%3A%22%2F%22%2C%22path%22%3A%5B%22feeds%22%5D%2C%22original%22%3A%22feeds%22%2C%22query%22%3A%7B%7D%7D#login + async prepare() { + try { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + // If we land here and are logged in already, + // just go to the "dashboard" + const nextRequest = this.getNextRequest(); + + if ( + this.props.authState.status === + AuthenticationStatus.AUTHENTICATED + ) { + if (nextRequest) { + // navigate(nextRequest.hash, nextRequest.params); + navigate2(nextRequest.path); + } else { + // TODO: navigate to default path... + navigate2({ path: 'narratives', type: 'europaui' }); + } + return; + } + + // await this.cancelLogin(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + nextRequest, + }, + }); + } catch (ex) { + const message = ex instanceof Error ? ex.message : 'Unknown error'; + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message, + }, + }); + } + } + + // async cancelLogin() { + // const auth2Client = new auth2.Auth2({ + // baseUrl: this.props.runtime.config('services.auth.url') + // }); + // try { + // await await auth2Client.loginCancel(); + // } catch (ex) { + // if (ex instanceof Auth2Error.AuthError) { + // if (ex.code !== '10010') { + // throw ex; + // } + // } + // } + // } + + renderPending() { + return ; + } + + renderError(message: string) { + return ; + } + + renderSuccess({ nextRequest }: SignInSuccessState) { + const whitelistedProviders = this.props.config.services.Auth2.providers; + const supportedProviders = + this.props.config.services.Auth2.supportedProviders; + const providers = supportedProviders.filter(({ id }) => { + return whitelistedProviders.includes(id); + }); + + // TRY OUR origin + // const url = new URL(this.props.config.deploy.ui.origin); + // url.hostname = `legacy.${url.hostname}`; + // url.hostname = `FOO.${url.hostname}`; + // const origin = url.origin; + + return ( + + ); + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return this.renderPending(); + case AsyncProcessStatus.SUCCESS: + return this.renderSuccess(this.state.value); + case AsyncProcessStatus.ERROR: + return this.renderError(this.state.error.message); + } + } +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignInButton.css b/vite-app/src/apps/Auth2/SignIn/SignInButton.css new file mode 100644 index 000000000..850f3ef39 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignInButton.css @@ -0,0 +1,25 @@ +.SignInButton { + text-align: center; + margin: 4px; + padding: 4px; + position: relative; +} + +.SignInButton img { + cursor: pointer; +} + +.SignInButton .-loading { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + padding-top: 4px; + pointer-events: none; +} + +.SignInButton .-loading > fa { + color: #fff; +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignInButton.tsx b/vite-app/src/apps/Auth2/SignIn/SignInButton.tsx new file mode 100644 index 000000000..c370cd132 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignInButton.tsx @@ -0,0 +1,101 @@ +import { Component } from 'react'; +import { Button } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import globusButtonLogo from '../resources/providers/globus/logo.png'; +import googleButtonLogo from '../resources/providers/google/logo.png'; +import orcidButtonLogo from '../resources/providers/orcid/logo.png'; + +import './SignInButton.css'; + +export interface SignInButtonProps { + provider: IDProvider; + doSignIn: () => void; +} + +interface SignInButtonState { + loading: boolean; + imageState: string; +} + +export default class SignInButton extends Component< + SignInButtonProps, + SignInButtonState +> { + constructor(props: SignInButtonProps) { + super(props); + this.state = { + loading: false, + imageState: 'normal', + }; + } + + renderSpinner() { + if (this.state.loading) { + return ( +
+ +
+ ); + } + } + + doSignIn() { + this.setState( + { + loading: true, + imageState: 'disabled', + }, + () => { + this.props.doSignIn(); + }, + ); + } + + providerLogoSrc() { + switch (this.props.provider.id) { + case 'Google': + return googleButtonLogo; + case 'Globus': + return globusButtonLogo; + case 'OrcID': + return orcidButtonLogo; + default: + return null; + } + } + + renderProviderButtonLogo() { + const logoSrc = this.providerLogoSrc(); + if (logoSrc) { + return {this.props.provider.label}; + } else { + return {this.props.provider.label}; + } + } + + render() { + const buttonLabel = `Sign In button for the ${this.props.provider.label} identity provider`; + return ( + + ); + } +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignInControls.css b/vite-app/src/apps/Auth2/SignIn/SignInControls.css new file mode 100644 index 000000000..1a3bb04d5 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignInControls.css @@ -0,0 +1,65 @@ +.SignInControls { +} + +.SignInControls .-row { + display: flex; + flex-direction: row; +} + +.SignInControls .-col { + flex: 1 1 0; + display: flex; + flex-direction: column; +} + +.SignInControls .-col .-header { + text-align: center; + font-weight: bold; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + height: 30px; +} + +.SignInControls .-col .-header .-icon { + margin: 0 0.25rem; +} + +.SignInControls .-col .-header .-label { + margin: 0 0.25rem; + font-size: 120%; +} + +.SignInControls .-col .-body { + flex: 1 1 0; + /* margin-bottom: 20px; */ + padding: 4px; + text-align: center; + display: flex; + flex-direction: column; +} + +.SignInControls .-col .-row-fill-height { + flex: 1 1 0; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; +} + +.SignInControls .-signup-button { + text-align: center; + margin-top: 10px; + width: 180px; + + font-weight: bold; + display: inline-flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.SignInControls .-signup-button > .-label { + margin-left: 0.5em; +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignInControls.tsx b/vite-app/src/apps/Auth2/SignIn/SignInControls.tsx new file mode 100644 index 000000000..e9096d17f --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignInControls.tsx @@ -0,0 +1,315 @@ +import Well from 'components/Well'; +import { NextRequestObject } from 'lib/NextRequest'; +import { Component } from 'react'; +import { Button, Col, Container, Row } from 'react-bootstrap'; +import { QuestionCircle } from 'react-bootstrap-icons'; +import { IDProvider } from 'types/config'; +import SignInButton from './SignInButton'; +import './SignInControls.css'; +import { SignInMode } from './SignInView'; + +export interface SignInControlsProps { + authRequired: boolean; + nextRequest?: NextRequestObject; + providers: Array; + // assetsPath: string; + mode: SignInMode; + chooseSignUp: () => void; + chooseSignIn: () => void; + go: (provider: IDProvider) => void; +} + +interface SignInControlsState {} + +export default class SignInControls extends Component< + SignInControlsProps, + SignInControlsState +> { + renderWillRedirect() { + const nextRequest = this.props.nextRequest; + if (typeof nextRequest === 'undefined' || nextRequest === null) { + return; + } + const { + path: { path }, + label, + } = nextRequest; + const pathLabel = ( + + {' '} + {label || path} + + ); + + return ( + + Redirect after Sign In + +

+ After signing in, your browser will be redirected back + to {pathLabel}. +

+
+
+ ); + } + + renderAuthorizationRequired() { + const nextRequest = this.props.nextRequest; + if (typeof nextRequest === 'undefined' || nextRequest === null) { + return; + } + const { + path: { path }, + label, + } = nextRequest; + const pathLabel = ( + + {' '} + {label || path} + + ); + + return ( + + Sign In Required + +

Sign In is required to access {pathLabel}.

+

+ After signing in, your browser will be redirected back + to {pathLabel}. +

+
+
+ ); + } + + renderProviders() { + const buttons = this.props.providers.map((provider) => { + return ( + + { + this.props.go(provider); + }} + /> + + ); + }); + return ( + + {buttons} + + ); + } + + renderSignupButton() { + switch (this.props.mode) { + case 'signin': + return ( + + ); + case 'signup': + return ( + + ); + } + } + + renderHelpLink() { + return ( + + ); + } + + renderSignInOrUpHeader() { + return ( +
+ + Sign In + + or + + + Sign Up +
+ ); + } + + renderPromptx() { + switch (this.props.mode) { + case 'signin': + return ( +
+
+ + New to KBase? +
+
+
+ {this.renderSignupButton()} +
+
+
+ ); + case 'signup': + return ( +
+
+ + + Have a KBase Account? + +
+
+
+ {this.renderSignupButton()} +
+
+
+ ); + } + } + + renderPrompt() { + return ( +
+

+ Whether you have a KBase account or not, your next step is + to choose an "Identity Provider" on the left. We + currently support sign in in with Google,ORCiD + , and Globus +

+ +

+ If you are signing up, you will first sign in with + one of the ID Providers, give permission to KBase, then + complete the KBase sign up form. After signing up, you may + continue to sign in to KBase using the ID Provider you + originally selected. +

+ +

+ If you are signing in, you should choose the ID + Provider you originally signed up with, or subsequently + linked to your account. +

+
+ ); + } + + renderLoginControls() { + // TODO: switch to bootstrap grid here. + return ( +
+
+ {this.renderSignInOrUpHeader()} +
+ with one of our Identity Provider partners +
+
+
+ {this.renderProviders()} +
+
+
+ {this.renderPrompt()} +
+ ); + } + + render() { + return ( +
+ {this.props.authRequired + ? this.renderAuthorizationRequired() + : this.renderWillRedirect()} + + {this.renderLoginControls()} + + {this.renderHelpLink()} + + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/SignIn/SignInView.tsx b/vite-app/src/apps/Auth2/SignIn/SignInView.tsx new file mode 100644 index 000000000..fea623fe4 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignIn/SignInView.tsx @@ -0,0 +1,365 @@ +import { + AuthenticationState, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { Auth2 } from 'lib/kb_lib/Auth2'; +import { AuthError } from 'lib/kb_lib/Auth2Error'; +import { navigate2 } from 'lib/navigation'; +import AutoPostForm from 'pluginSupport/AutoPostForm'; +import { Component } from 'react'; +import { IDProvider } from 'types/config'; + +import { navigationPathToURL } from 'contexts/RouterContext'; +import { NextRequestObject } from 'lib/NextRequest'; +import kbaseLogo from '../resources/images/kbase-logo-99.png'; +import SignInControls from './SignInControls'; + +/** + * Sign in can be triggered in two scenarios. + * + * - login - the user clicks the login button + * - authentication - the user attempts to access a resource which requires authentication. + */ +export type SignInSource = 'login' | 'authorization'; + +export interface SignInViewProps { + source: SignInSource; + providers: Array; + authURL: string; + authState: AuthenticationState; + nextRequest?: NextRequestObject; + setTitle: (title: string) => void; +} + +export type SignInMode = 'signup' | 'signin'; +export type SignInStatus = 'choosing' | 'go'; + +export interface SignInStateBase { + mode: SignInMode; + status: SignInStatus; +} + +export interface SignInStateChoosing extends SignInStateBase { + status: 'choosing'; +} + +export interface SignInStateSignIn extends SignInStateBase { + mode: 'signin'; + status: 'go'; + provider: IDProvider; +} + +export interface SignInStateSignUp extends SignInStateBase { + mode: 'signup'; + status: 'go'; + provider: IDProvider; +} + +export type SignInState = + | SignInStateChoosing + | SignInStateSignIn + | SignInStateSignUp; + +interface SignInViewState { + signInState: SignInState; +} + +export class SignInView extends Component { + constructor(props: SignInViewProps) { + super(props); + this.state = { + signInState: { mode: 'signin', status: 'choosing' }, + }; + } + + componentDidMount() { + if (!this.possiblyRedirect()) { + const { mode, status } = this.state.signInState; + switch (status) { + case 'choosing': + switch (mode) { + case 'signin': + this.props.setTitle('KBase Sign In'); + break; + case 'signup': + this.props.setTitle('Sign Up for KBase'); + break; + } + } + } + } + + componentDidUpdate() { + this.possiblyRedirect(); + } + + async cancelLogin() { + const auth2Client = new Auth2({ + baseUrl: this.props.authURL, + }); + try { + await await auth2Client.loginCancel(); + } catch (ex) { + if (ex instanceof AuthError) { + if (ex.code !== '10010') { + throw ex; + } + } + } + } + + doRedirect(nextRequest?: NextRequestObject) { + if (nextRequest) { + try { + navigate2(nextRequest.path); + } catch (ex) { + // TODO: get the default path from the props. + navigate2({ path: 'narratives', type: 'europaui' }); + } + } else { + navigate2({ path: 'narratives', type: 'europaui' }); + } + } + + possiblyRedirect() { + // if is logged in, just redirect to the nextrequest, + // or the nexturl, or dashboard. + if ( + this.props.authState.status === AuthenticationStatus.AUTHENTICATED + ) { + this.doRedirect(this.props.nextRequest); + return true; + } + return false; + } + + /** + * Create a "redirect url" to be provided to the auth service. + * + * This url is not actually used as the target of redirection - rather it must + * match the redirect url base URL registered for the auth environment (determined + * by the auth service hostname we call). The state param is extracted from the + * redirect url and placed onto the configured redirect url actually used. + */ + makeRedirectURL() { + const params: Record = { + state: JSON.stringify({ + nextrequest: this.props.nextRequest, + origin, + }), + }; + + // const search = Object.keys(query) + // .map((key) => { + // return [key, encodeURIComponent(query[key])].join('='); + // }) + // .join('&'); + + // The logical app origin is now provided by configuration, as the + // plugin/kbase-ui is probably running on a sub-domain host. + + // const appOrigin = this.props.origin; + + // return `${appOrigin}?${search}`; + + return navigationPathToURL( + { path: '', type: 'europaui', params }, + false, + ).toString(); + } + + async doSignIn(provider: IDProvider) { + const auth2Client = new Auth2({ + baseUrl: this.props.authURL, + }); + + try { + await auth2Client.loginCancel(); + } catch (ex) { + if (ex instanceof AuthError) { + // ignore this specific error... + if (ex.code !== '10010') { + // TODO: set error state + throw ex; + } + } else { + // TODO: show error. + console.error('Skipping error', ex); + } + } + + this.setState({ + signInState: { + mode: 'signin', + status: 'go', + provider, + }, + }); + } + + async doSignUp(provider: IDProvider) { + const auth2Client = new Auth2({ + baseUrl: this.props.authURL, + }); + + try { + await auth2Client.loginCancel(); + } catch (ex) { + if (ex instanceof AuthError) { + // ignore this specific error... + if (ex.code !== '10010') { + // TODO: set error state + throw ex; + } + } else { + // TODO: show error. + console.error('Skipping error', ex); + } + } + + this.setState({ + signInState: { + mode: 'signup', + status: 'go', + provider, + }, + }); + } + + chooseSignIn() { + this.setState({ + signInState: { + ...this.state.signInState, + mode: 'signin', + }, + }); + } + + chooseSignUp() { + this.setState({ + signInState: { + ...this.state.signInState, + mode: 'signup', + }, + }); + } + + doGo(provider: IDProvider) { + this.setState({ + signInState: { + ...this.state.signInState, + status: 'go', + provider, + }, + }); + } + + renderSigninChoosing() { + const source = this.props.source; + return ( +
+
+
+ +

+ Welcome to KBase +

+
+
+

+ A collaborative, open environment for systems + biology of plants, microbes and their communities +

+
+
+ +
+ ); + } + + renderSignInSignIn(provider: IDProvider) { + const redirectURL = this.makeRedirectURL(); + + const params: Record = { + provider: provider.id, + redirecturl: redirectURL, + }; + + const action = `${this.props.authURL}/login/start`; + + return ; + } + + renderSignInSignUp(provider: IDProvider) { + const redirectURL = this.makeRedirectURL(); + + const params: Record = { + provider: provider.id, + redirecturl: redirectURL, + }; + + const action = `${this.props.authURL}/login/start`; + + return ; + } + + render() { + const { mode, status } = this.state.signInState; + switch (status) { + case 'choosing': + return this.renderSigninChoosing(); + case 'go': + switch (mode) { + case 'signin': + return this.renderSignInSignIn( + this.state.signInState.provider, + ); + case 'signup': + return this.renderSignInSignUp( + this.state.signInState.provider, + ); + } + } + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/CheckUsernameField.tsx b/vite-app/src/apps/Auth2/SignInContinue/CheckUsernameField.tsx new file mode 100644 index 000000000..3a4abe1e1 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/CheckUsernameField.tsx @@ -0,0 +1,75 @@ +import { Button } from 'antd'; +import { Component } from 'react'; + +export interface CheckUsernameFieldProps { + disabled: boolean; + value?: CheckState; + username?: string; + onChange?: (newValue: string) => void; // (event: ChangeEvent) => void + checkUsername: (username: string) => Promise; +} + +export type CheckState = 'na' | 'required' | 'available' | 'unavailable'; + +interface CheckUsernameFieldState {} + +export default class CheckUsernameField extends Component< + CheckUsernameFieldProps, + CheckUsernameFieldState +> { + renderStatus() { + switch (this.props.value) { + case 'na': + return ''; + case 'required': + return Please check if this username is available; + case 'available': + return ( + + Username {this.props.username} available for you + to use + + ); + case 'unavailable': + return ( + + Username {this.props.username} is not available + + ); + } + } + + render() { + return ( +
+ {/* */} + {' '} + {this.renderStatus()} +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/Policy.ts b/vite-app/src/apps/Auth2/SignInContinue/Policy.ts new file mode 100644 index 000000000..4a53ae9bf --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/Policy.ts @@ -0,0 +1,85 @@ +import policyData from '../resources/agreements/terms-and-conditions.json'; + +/** + * These interfaces model the policy data stored in policies.json. + * Note that this is a long-term stopgap -- the policies should be served + * up by a service, like the auth service. + */ + +export interface PolicyDataVersion { + version: number; + publishedAt: string; + url: string; +} + +export interface PolicyData { + id: string; + title: string; + versions: Array; +} + +export interface TermsAndConditionsPolicyVersion { + version: number; + publishedAt: Date; + url: URL; +} + +export interface TermsAndConditionsPolicy { + id: string; + title: string; + versions: Array; +} + +export interface CurrentTermsAndConditionsPolicy { + id: string; + title: string; + version: number; + publishedAt: Date; + url: URL; +} + +const POLICY: TermsAndConditionsPolicy = { + id: policyData.id, + title: policyData.title, + versions: policyData.versions.map(({ version, publishedAt, url }) => { + return { + version, + url: new URL(url), + publishedAt: new Date(publishedAt), + }; + }), +}; + +export default class Policy { + _policy: TermsAndConditionsPolicy = POLICY; + + currentPolicy(): CurrentTermsAndConditionsPolicy { + const now = Date.now(); + let currentVersion: TermsAndConditionsPolicyVersion | null = null; + for (const policyVersion of this._policy.versions) { + // If the publication of the T&C is in the future, we are done. + if (policyVersion.publishedAt.getTime() > now) { + break; + } + + // Otherwise, we continue marching through the T&C, bookmarking + // as we go. + + currentVersion = policyVersion; + } + + if (!currentVersion) { + throw new Error('No current T&C policy'); + } + + return { + id: this._policy.id, + title: this._policy.title, + ...currentVersion, + }; + } + + policy(): TermsAndConditionsPolicy { + return this._policy; + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement copy.ts b/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement copy.ts new file mode 100644 index 000000000..26f270cfa --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement copy.ts @@ -0,0 +1,326 @@ +// define([ +// 'bluebird', +// 'marked', +// 'lib/utils', +// 'kb_common_ts/Auth2', +// 'lib/Features' +// ], ( +// Promise, +// marked, +// Utils, +// auth2, +// Features +// ) => { + +import { UserPolicy } from 'lib/kb_lib/Auth2'; + +import policiesData from '../resources/agreements/policies.json'; + +const policies = policiesData as unknown as Policies; + +/** + * These interfaces model the policy data stored in policies.json. + * Note that this is a long-term stopgap -- the policies should be served + * up by a service, like the auth service. + */ + +export interface PolicyVersionBase { + version: number; + begin: string; + end?: string; +} + +export interface PolicyVersionWithDocument extends PolicyVersionBase { + document: string; +} + +export interface PolicyVersionWithURL extends PolicyVersionBase { + url: string; +} + +export type PolicyVersion = PolicyVersionWithDocument | PolicyVersionWithURL; + +export interface Policy { + id: string; + title: string; + versions: Array; +} + +export type Policies = Array; + +export interface UserPolicyAgrement { + id: string; + version: number; + agreedAt: Date; +} + +/** + * This structure represents a policy and version in relation to the + * current user, and helps answer the question - which policies have been agreed to, + * which not yet, which are not yet effective, which are expired, etc. + */ + +export type PolicyAgreementStatus = 'expired' | 'new' | 'current' | 'updated'; + +export interface PolicyAgreement { + id: string; + version: number; + title: string; + publishedAt: Date; + expiredAt: Date | null; + agreedAt: Date | null; + status: PolicyAgreementStatus; + statusSort: number; + url: string | null; + document: string | null; +} + +/** + * Differentiated from a "UserPolicy" (probablyl better named "PolicyAgreement") because + * this one does not have an agreement timestamp, and the id and version or separated (!). + * The latter is a quirk of the auth2 api. The reason for the lack of timestamp is that + * the timestamp is added when the login "choice" is submitted, along with any "pending" + * new policy agreements. + */ +export interface PendingPolicyAgreement { + id: string; + version: number; +} + +export interface PolicyAndAgreementParams { + // authURL: string; + // authorization: string; + policyids: Array; // from the auth service user record +} + +export default class PolicyAndAgreement { + // auth2Client: Auth2; + policyAgreements: Array; + constructor({ policyids }: PolicyAndAgreementParams) { + // this.runtime = runtime; + const userAgreements = this.parsePolicyAgreements(policyids); + this.policyAgreements = this.getPolicyAgreements(userAgreements); + // this.useAgreements = null; + + // this.auth2Client = new Auth2({ + // baseUrl: authURL + // }); + } + + // getLatestPolicies() { + // return policies.map(({id, title, versions}) => { + // const latestVersionId = Math.max.apply( + // null, + // versions.map((version) => { + // return version.version; + // }) + // ); + // const {version, begin, end, document} = versions.filter((version) => { + // return version.version === latestVersionId; + // })[0]; + + // return { + // id, title, version, begin, end, document + // }; + // }); + // } + + /** + * Returns all policies. + * The policy versions are modified to add a flag indicating whether + * the policy is covered by an agreement (isAgreedTo). + * + * @returns + */ + // getPolicies() { + // return policies.map(({id, title, versions}) => { + // const latestVersionId = Math.max.apply( + // null, + // versions.map((version) => { + // return version.version; + // }) + // ); + // const {version, begin, end, document} = versions.filter((version) => { + // return version.version === latestVersionId; + // })[0]; + + // return { + // id, title, version, begin, end, document + // }; + // }); + // } + + getPolicy(id: string) { + return policies.filter((policy) => { + return policy.id === id; + })[0]; + } + + getPolicyVersion(id: string, version: number) { + const policy = this.getPolicy(id); + if (!policy) { + throw new Error(`Policy does not exist ${id}`); + } + + const policyVersion = policy.versions.filter((ver) => { + return version === ver.version; + })[0]; + if (!policyVersion) { + throw new Error(`Policy version does not exist ${id}.${version}`); + } + + return policyVersion; + } + + /** + * Converts the policy agreements into something more directly usable. + * + * @param policyIds + * @returns + */ + parsePolicyAgreements( + policyIds: Array, + ): Array { + return policyIds.map(({ id, agreedon }) => { + const [policyId, policyVersion] = id.split('.'); + return { + id: policyId, + version: parseInt(policyVersion, 10), + agreedAt: new Date(agreedon), + }; + }); + } + + // getUseAgreements() { + // return this.useAgreements; + // } + + // async loadUseAgremements() { + + // // if (!policyIds) { + // // const me = await this.auth2Client.getMe(this.authorization); + // // const policyIds = me.policyids; + // // } + + // const agreements = this.parsePolicyAgreements(policyIds); + // // this.agreements = agreements; + + // // Now add the policy information to the use agreements + // // TODO: ideally the auth service knows about policies themselves! + // const useAgreements = agreements.map(({date: agreedAt, id, version}) => { + // try { + // const {title} = this.getPolicy(id); + // const {begin: publishedAt, end: expiredAt} = this.getPolicyVersion(id, version); + // return { + // agreedAt, id, version, + // title, publishedAt, expiredAt + // }; + // } catch (ex) { + // console.error('Error fetching policy or version, skipped', ex); + // return null; + // } + // }) + // .filter((useAgreement) => {return !!useAgreement;}); + + // this.useAgreements = useAgreements; + // } + + getPolicyAgreements( + userPolicyAgreements: Array, + ): Array { + const now = Date.now(); + return policies.reduce>( + (policyAgreements, { id, title, versions }) => { + versions.forEach((policyVersion) => { + const document = + 'document' in policyVersion + ? policyVersion.document + : null; + const url = + 'url' in policyVersion ? policyVersion.url : null; + const { version, begin, end } = policyVersion; + // Simply gets the agreement time, if present for this user in their + // "policyids" list. + const agreedAt = + userPolicyAgreements + .map( + ({ + id: idAgreed, + version: versionAgreed, + agreedAt, + }) => { + if ( + idAgreed === id && + versionAgreed === version + ) { + return agreedAt; + } + }, + ) + .filter((agreedAt) => { + return !!agreedAt; + })[0] || null; + + // Similar to above, but this is a boolean indicating whether the + // previous version of the current agreement was agreed to. This is used + // to differentiate between a totally new policy and a policy which has + // been updated. + // TODO: THIS IS WRONG! Fix! + const previouslyAgreedTo = userPolicyAgreements.some( + ({ id: idAgreed, version: versionAgreed }) => { + return ( + id == idAgreed && version == versionAgreed + 1 + ); + }, + ); + + const expiredAt = end ? new Date(end) : null; + + const [status, statusSort]: [ + PolicyAgreementStatus, + number, + ] = (() => { + if (expiredAt) { + if (expiredAt.getTime() <= now) { + // We don't care whether it was agreed to or not. + return ['expired', 3]; + } + // otherwise, this agreement version has not yet expired and is + // still effective. + } + if (agreedAt) { + return ['current', 2]; + } + return [previouslyAgreedTo ? 'updated' : 'new', 1]; + })(); + + policyAgreements.push({ + id, + version, + title, + publishedAt: new Date(begin), + expiredAt, + agreedAt, + status, + statusSort, + document, + url, + }); + }); + return policyAgreements; + }, + [], + ); + } + + /** + * Returns all policies which are "new" -- the user has never agreed to. + * + * @returns + */ + getNewPolicies() { + return this.policyAgreements.filter(({ status }) => { + return ['new', 'updated'].includes(status); + }); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement.ts b/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement.ts new file mode 100644 index 000000000..eeb4ffb6a --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/PolicyAndAgreement.ts @@ -0,0 +1,286 @@ +import { UserPolicy } from 'lib/kb_lib/Auth2'; +import Policy, { CurrentTermsAndConditionsPolicy } from './Policy'; + +// import policyData from '../resources/agreements/terms-and-conditions.json'; + +// const POLICY = policyData as unknown as Policy; + +/** + * These interfaces model the policy data stored in policies.json. + * Note that this is a long-term stopgap -- the policies should be served + * up by a service, like the auth service. + */ + +// export interface PolicyVersion { +// version: number; +// begin: string; +// url: string; +// end?: string; +// } + +// export interface PolicyVersionWithDocument extends PolicyVersionBase { +// document: string; +// } + +// export interface PolicyVersionWithURL extends PolicyVersionBase { +// url: string; +// } + +// export type PolicyVersion = PolicyVersionWithDocument | PolicyVersionWithURL; + +// export interface Policy { +// id: string; +// title: string; +// versions: Array +// } + +// export type Policy = Array; + +export interface UserPolicyAgrement { + id: string; + version: number; + agreedAt: Date; +} + +/** + * This structure represents a policy and version in relation to the + * current user, and helps answer the question - which policies have been agreed to, + * which not yet, which are not yet effective, which are expired, etc. + */ + +export type PolicyAgreementStatus = 'expired' | 'new' | 'current' | 'updated'; + +// export interface PolicyAgreement { +// id: string; +// version: number; +// title: string; +// publishedAt: Date; +// expiredAt: Date | null; +// agreedAt: Date | null; +// status: PolicyAgreementStatus; +// statusSort: number; +// url: URL; +// } + +export interface PolicyAgreement { + currentPolicy: CurrentTermsAndConditionsPolicy; + agreement: UserPolicyAgrement | null; + hasPreviousAgreements: boolean; +} + +/** + * A policy agreement that only exists in memory - it is not committed to the user's + * account yet so does not have an "agreed at" timestamp. This is the form that is + * submitted to the auth service to signify an agreement to the indicated policy and version. + * + * Differentiated from a "UserPolicy" (probablyl better named "PolicyAgreement") because + * this one does not have an agreement timestamp, and the id and version or separated (!). + * The latter is a quirk of the auth2 api. The reason for the lack of timestamp is that + * the timestamp is added when the login "choice" is submitted, along with any "pending" + * new policy agreements. + */ +export interface PendingPolicyAgreement { + id: string; + version: number; +} + +export interface PolicyAndAgreementParams { + policyids: Array; // from the auth service user record +} + +export default class PolicyAndAgreement { + policy: Policy = new Policy(); + userAgreements: Array; + // policyAgreements: Array; + constructor({ policyids }: PolicyAndAgreementParams) { + this.userAgreements = this.parsePolicyAgreements(policyids); + // this.policyAgreements = this.getPolicyAgreements(this.userAgreements); + } + + // getPolicy(id: string) { + // return policies.filter((policy) => { + // return policy.id === id; + // })[0]; + // } + + // getPolicyVersion(id: string, version: number) { + // const policy = this.getPolicy(id); + // if (!policy) { + // throw new Error(`Policy does not exist ${id}`); + // } + + // const policyVersion = policy.versions.filter((ver) => { + // return version === ver.version; + // })[0]; + // if (!policyVersion) { + // throw new Error(`Policy version does not exist ${id}.${version}`); + // } + + // return policyVersion; + // } + + /** + * Converts the policy agreements (from a user's account) into something more directly usable. + * + * @param policyIds + * @returns + */ + parsePolicyAgreements( + policyIds: Array, + ): Array { + return policyIds.map(({ id, agreedon }) => { + const [policyId, policyVersion] = id.split('.'); + return { + id: policyId, + version: parseInt(policyVersion, 10), + agreedAt: new Date(agreedon), + }; + }); + } + + /** + * Gets a list of "policy agreements" which are aligned to the current set of user + * agreements (as defined in "terms-and-conditions.json"). + * + * Note: Ideally, this logic would reside in the auth service. + * + * @param userPolicyAgreements + * @returns + */ + // getPolicyAgreements(userPolicyAgreements: Array): Array { + // const now = Date.now(); + // const agreements: Array = []; + // const policy = this.policy.policy(); + // // return POLICY.reduce>((policyAgreements, {begin, end, version, url}) => { + // policy.versions.forEach(({begin, end, version, url}) => { + // // const document = 'document' in policyVersion ? policyVersion.document : null; + // // const url = 'url' in policyVersion ? policyVersion.url : null; + // // const {version, begin, end} = policyVersion; + // // Simply gets the agreement time, if present for this user in their + // // "policyids" list. + // const agreedAt = userPolicyAgreements + // .map(({id: idAgreed, version: versionAgreed, agreedAt}) => { + // if (idAgreed === policy.id && versionAgreed === version) { + // return agreedAt; + // } + // }) + // .filter((agreedAt) => { + // return !!agreedAt; + // })[0] || null; + + // // Similar to above, but this is a boolean indicating whether the + // // previous version of the current agreement was agreed to. This is used + // // to differentiate between a totally new policy and a policy which has + // // been updated. + // const previouslyAgreedTo = userPolicyAgreements + // .some(({id: idAgreed, version: versionAgreed}) => { + // return (policy.id == idAgreed && version < versionAgreed); + // }); + + // const expiredAt = end ? new Date(end) : null; + + // const [status, statusSort]: [PolicyAgreementStatus, number] = (() => { + // if (expiredAt) { + // if (expiredAt.getTime() <= now) { + // // We don't care whether it was agreed to or not. + // return ['expired', 3]; + // } + // // otherwise, this agreement version has not yet expired and is + // // still effective. + // } + // if (agreedAt) { + // return ['current', 2]; + // } + // return [previouslyAgreedTo ? 'updated' : 'new', 1]; + // })(); + + // agreements.push({ + // id: policy.id, version, title: policy.title, + // publishedAt: new Date(begin), expiredAt, agreedAt, + // status, statusSort, url + // }); + // }); + // return agreements; + // } + + /** + * Returns all policies which are "new" -- the user has never agreed to. + * + * @returns + */ + // getNewPolicies() { + // return this.policyAgreements + // .filter(({status}) => { + // return ['new', 'updated'].includes(status); + // }); + // } + + /** + * Returns the current active policy, and whether the user has agreed to it yet or not. + * + * @returns + */ + getPolicyAgreement(): PolicyAgreement { + const currentPolicy = this.policy.currentPolicy(); + + const agreements = this.userAgreements.filter(({ id, version }) => { + return currentPolicy.id === id && currentPolicy.version === version; + }); + + return { + currentPolicy: currentPolicy, + agreement: agreements.length > 0 ? agreements[0] : null, + hasPreviousAgreements: this.userAgreements.length > 0, + }; + + // policy.versions.forEach(({begin, end, version, url}) => { + // // const document = 'document' in policyVersion ? policyVersion.document : null; + // // const url = 'url' in policyVersion ? policyVersion.url : null; + // // const {version, begin, end} = policyVersion; + // // Simply gets the agreement time, if present for this user in their + // // "policyids" list. + // const agreedAt = userPolicyAgreements + // .map(({id: idAgreed, version: versionAgreed, agreedAt}) => { + // if (idAgreed === policy.id && versionAgreed === version) { + // return agreedAt; + // } + // }) + // .filter((agreedAt) => { + // return !!agreedAt; + // })[0] || null; + + // // Similar to above, but this is a boolean indicating whether the + // // previous version of the current agreement was agreed to. This is used + // // to differentiate between a totally new policy and a policy which has + // // been updated. + // const previouslyAgreedTo = userPolicyAgreements + // .some(({id: idAgreed, version: versionAgreed}) => { + // return (policy.id == idAgreed && version < versionAgreed); + // }); + + // const expiredAt = end ? new Date(end) : null; + + // const [status, statusSort]: [PolicyAgreementStatus, number] = (() => { + // if (expiredAt) { + // if (expiredAt.getTime() <= now) { + // // We don't care whether it was agreed to or not. + // return ['expired', 3]; + // } + // // otherwise, this agreement version has not yet expired and is + // // still effective. + // } + // if (agreedAt) { + // return ['current', 2]; + // } + // return [previouslyAgreedTo ? 'updated' : 'new', 1]; + // })(); + + // agreements.push({ + // id: policy.id, version, title: policy.title, + // publishedAt: new Date(begin), expiredAt, agreedAt, + // status, statusSort, url + // }); + // }); + // return agreements; + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInContinue.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignInContinue.tsx new file mode 100644 index 000000000..9fb859de5 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInContinue.tsx @@ -0,0 +1,1019 @@ +import ErrorMessage from 'components/ErrorMessage'; +import Loading from 'components/Loading'; +import { RouteProps } from 'components/Router2'; +import { + AuthenticationState, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { NextRequestObject } from 'lib/NextRequest'; +import { + Auth2, + PolicyAgreement as AuthPolicyAgreement, + LoginChoice, +} from 'lib/kb_lib/Auth2'; +import { AuthError } from 'lib/kb_lib/Auth2Error'; +import { JSONRPC11Exception } from 'lib/kb_lib/comm/JSONRPC11/JSONRPC11'; +import UserProfile from 'lib/kb_lib/comm/coreServices/UserProfile'; +import { Messenger } from 'lib/messenger'; +import { navigate2 } from 'lib/navigation'; +import { Component, ReactNode } from 'react'; +import { Button } from 'react-bootstrap'; +import { Md5 } from 'ts-md5'; +import { Config, IDProvider } from 'types/config'; +import { Providers } from '../Providers'; +import PolicyAndAgreement, { + PendingPolicyAgreement, + PolicyAgreement, +} from './PolicyAndAgreement'; +import SignInContinueView from './SignInContinueView'; + +export type ErrorDetail = Array; + +export interface AlmostSimpleError { + title: string; + message: ReactNode; +} + +export interface UIErrorParams { + code: string; + message: string; + detail: ErrorDetail; + data: unknown; +} + +class UIError extends Error { + code: string; + detail: ErrorDetail; + data: unknown; + constructor({ code, message, detail, data }: UIErrorParams) { + super(message); + this.code = code; + this.detail = detail; + this.data = data; + } +} + +export enum SignInStatus { + NONE = 'NONE', + PREPARING = 'PREPARING', + READY = 'READY', + SIGNING_IN = 'SIGNING_IN', + SIGNED_IN = 'SIGNED_IN', + ERROR = 'ERROR', +} + +export interface SignInStateBase { + status: SignInStatus; +} + +export interface SignInStateNone extends SignInStateBase { + status: SignInStatus.NONE; +} + +export interface SignInStatePreparing extends SignInStateBase { + status: SignInStatus.PREPARING; +} + +export interface SignInStateReady extends SignInStateBase { + status: SignInStatus.READY; +} + +export interface SignInStateSigningIn extends SignInStateBase { + status: SignInStatus.SIGNING_IN; +} + +export interface SignInStateSignedIn extends SignInStateBase { + status: SignInStatus.SIGNED_IN; +} + +export interface SignInStateError extends SignInStateBase { + status: SignInStatus.ERROR; + message: string; +} + +export type SignInState = + | SignInStateNone + | SignInStatePreparing + | SignInStateReady + | SignInStateSigningIn + | SignInStateSignedIn + | SignInStateError; + +export enum AuthSessionCancellationType { + USER = 'CancellationType_USER', + TIMEOUT = 'CancellationType_TIMEOUT', +} + +export enum AuthSessionType { + SIGNUP = 'AuthSession_SIGNUP', + SIGNIN = 'AuthSession_SIGNIN', +} + +export interface StateParam { + nextrequest?: NextRequestObject; + origin: string; +} + +function getStateParam(choice: LoginChoice): StateParam { + if (!choice.redirecturl) { + throw new UIError({ + code: 'parse-error', + message: 'Redirect url is missing or falsy.', + // data: null, + detail: [ + 'This is an error using the KBase auth flow.', + 'The choice object should have a property named "redirecturl", but it is either missing or falsy.', + ], + data: { + choice, + }, + }); + } + + let url; + try { + url = new URL(choice.redirecturl); + } catch (ex) { + const message = ex instanceof Error ? ex.message : 'Unknown Error'; + console.error(ex, choice.redirecturl); + throw new UIError({ + code: 'parse-error', + message: 'Error parsing redirecturl', + detail: [ + 'This is an error parsing the redirecturl in choice.redirecturl', + `The original error message is: ${message}`, + ], + data: { + choice, + }, + }); + } + + // we just expect a state param. + if (!url.searchParams.has('state')) { + throw new UIError({ + code: 'missing-state', + message: 'State query parameter missing from choice.redirecturl', + detail: [ + 'This is an error using the KBase auth flow.', + [ + 'The choice object should have a property named "redirecturl" which ', + 'should be a valid url with a query param named "state", which is in JSON format.', + ], + ], + data: { + choice, + }, + }); + } + + try { + return JSON.parse(url.searchParams.get('state')!); + } catch (ex) { + console.error('Error parsing state in redirect url', ex); + const message = ex instanceof Error ? ex.message : 'Unknown Error'; + throw new UIError({ + code: 'parse-error', + message: 'Error parsing state in redirect url', + detail: [ + 'This is an error parsing the KBase auth flow.', + [ + 'The choice object should have a property named "redirecturl" which ', + 'should be a valid url with a query param named "state", which is in JSON format.', + ], + ['The original error message is: ', message], + ], + data: { + choice, + }, + }); + } +} + +export interface SurveyItem { + question: string; + response: Record; +} + +// export interface SignUpInfo { +// // For account creation +// username: string; +// realname: string; +// email: string; +// agreements: Array + +// // For profile +// organization: string; +// department: string; +// hearAbout: SurveyItem +// } + +export interface SignUpFormInfo { + // For account creation + username: string; + realname: string; + email: string; + + // For profile + organization: string; + department: string; + hearAbout: SurveyItem; + agreement: AuthPolicyAgreement; +} + +export interface AccountCreationParams { + username: string; + realname: string; + email: string; + agreement: AuthPolicyAgreement; +} + +export interface ProfileCreationParams { + username: string; + realname: string; + organization: string; + department: string; + hearAbout: SurveyItem; +} + +export interface LoginContinueProps extends RouteProps { + // params: SignInParams + // nextrequest: string, + authState: AuthenticationState; + config: Config; + messenger: Messenger; + setTitle: (title: string) => void; +} + +export type LoginContinueLoginState = AsyncProcess; + +// TODO: finish definiing +interface LoginContinueSuccess { + nextRequest?: NextRequestObject; + // TODO: maybe this is typed correctly... + choice: LoginChoice; + provider: IDProvider; + // TODO: type this. + policyAgreement: PolicyAgreement; + serverTimeOffset: number; + loginState: LoginContinueLoginState; +} +type LoginContinueState = AsyncProcess; + +export default class LoginContinue extends Component< + LoginContinueProps, + LoginContinueState +> { + constructor(props: LoginContinueProps) { + super(props); + + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.startItUp(); + } + + async doSignIn(agreement?: PendingPolicyAgreement) { + // Can only sign in if we are in SUCCESS state. + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + // OR ?? + return; + } + + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + const { + nextRequest, + choice: { + login: [{ id: identityId }], + }, + } = this.state.value; + + try { + if ( + this.props.authState.status !== + AuthenticationStatus.UNAUTHENTICATED + ) { + // TODO: refactor to either: + // handle authenticated state nicely (e.g. sign out, sign in) + // only have the signin continue operate under unauthenticated + // for now, it will work, but not for edge cases. + throw new Error('Must be unauthenticated to sign in'); + } + + const { token: tokenInfo } = await auth2Client.loginPick({ + identityId, + linkAll: false, + agreements: agreement ? [agreement] : [], + }); + + // TODO: replace with direct call of a function provided by the + // EuropaContext. + this.props.messenger.send('session', 'loggedin', { + token: tokenInfo.token, + expires: tokenInfo.expires, + nextRequest, + }); + } catch (ex) { + console.error('ERROR', ex); + } + } + + async doSignInDirect(value: LoginContinueSuccess) { + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + const { + nextRequest, + choice: { + login: [{ id: identityId }], + }, + } = value; + + try { + if ( + this.props.authState.status !== + AuthenticationStatus.UNAUTHENTICATED + ) { + // TODO: refactor to either: + // handle authenticated state nicely (e.g. sign out, sign in) + // only have the signin continue operate under unauthenticated + // for now, it will work, but not for edge cases. + throw new Error('Must be unauthenticated to sign in'); + } + + const { token: tokenInfo } = await auth2Client.loginPick({ + identityId, + linkAll: false, + agreements: [], + }); + + // TODO: replace with direct call of a function provided by the + // EuropaContext. + this.props.messenger.send('session', 'loggedin', { + token: tokenInfo.token, + expires: tokenInfo.expires, + nextRequest, + }); + } catch (ex) { + console.error('ERROR', ex); + } + } + + gravatarHash(emailAddress: string) { + return Md5.hashStr(emailAddress.trim().toLowerCase()); + } + + async createProfile( + token: string, + { + username, + realname, + organization, + department, + hearAbout: { question, response }, + }: ProfileCreationParams, + ) { + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + const accountInfo = await auth2Client.getMe(token); + + const userProfileClient = new UserProfile({ + url: this.props.config.services.UserProfile.url, + token, + timeout: this.props.config.ui.constants.clientTimeout, + }); + const newProfile = { + user: { + username, + realname, + }, + profile: { + metadata: { + createdBy: 'userprofile_ui_service', + created: new Date().toISOString(), + }, + // was globus info, no longer used + preferences: {}, + // when auto-creating a profile, there is nothing to put here yet. + userdata: { + organization, + department, + avatarOption: 'gravatar', + gravatarDefault: 'identicon', + }, + synced: { + gravatarHash: this.gravatarHash(accountInfo.email), + }, + surveydata: { + referralSources: { + question, + response, + }, + }, + }, + }; + + try { + return userProfileClient.set_user_profile({ + profile: newProfile, + }); + } catch (ex) { + if (ex instanceof JSONRPC11Exception) { + // TODO: return fancy error. + throw new Error(`Profile creation failed: ${ex.error.message}`); + } else { + throw ex; + } + } + } + + createAccount( + choiceId: string, + { username, realname, email, agreement }: AccountCreationParams, + ) { + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + const params = { + id: choiceId, + user: username, + display: realname, + email, + linkall: false, + policyids: [`${agreement.id}.${agreement.version}`], + }; + return auth2Client.loginCreate(params); + } + + // async doSignUp({username, realname, email, agreements}: SignUpFormInfo) { + // try { + // const {token: tokenInfo} = await this.createAccount({ + + // }); + + // // await this.createProfile(tokenInfo.token, account.realname, profile, survey); + + // // const nextRequest = this.getNextRequest(); + // // if (nextRequest) { + // // this.props.runtime.send('app', 'auth-navigate', {nextRequest, tokenInfo}); + // // } else { + // // this.props.runtime.send('app', 'auth-navigate', {nextRequest: {path: 'dashboard'}, tokenInfo}); + // // } + // } catch (ex) { + // console.error(ex); + // } + // } + + // TODO: wow, add more error handling, etc. + + async doSignUp({ + username, + realname, + email, + agreement, + organization, + department, + hearAbout, + }: SignUpFormInfo) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + // TODO: should be impossible, but runtime. + throw new Error('Invalid state for signup'); + } + const choiceId = this.state.value.choice.create[0].id; + try { + const createAccountResult = await this.createAccount(choiceId, { + username, + realname, + email, + agreement, + }); + + const { + token: { token, expires }, + } = createAccountResult; + + await this.createProfile(token, { + username, + realname, + organization, + department, + hearAbout, + }); + + // TODO: this should not be possible here ... move this method and others to + // the signup continue controller. + if ( + this.props.authState.status !== + AuthenticationStatus.UNAUTHENTICATED + ) { + // TODO: refactor to either: + // handle authenticated state nicely (e.g. sign out, sign in) + // only have the signin continue operate under unauthenticated + // for now, it will work, but not for edge cases. + throw new Error('Must be unauthenticated to sign in'); + } + + this.props.messenger.send('session', 'loggedin', { + token, + expires, + nextRequest: this.state.value.nextRequest, + }); + + return; + + // this.props.authState.login(token, expires); + + // if (this.state.value.nextRequest) { + // try { + // // since the plugin is operating inside of the iframe, it needs + // // to send the token with the navigation path so the parent + // // window can also set the cookie. + + // // TODO: ***** + // // Here is where we change the behavior from a message to kbase-ui + // // to directly executing the auth and navigation! + // // + // // this.props.runtime.send('app', 'auth-navigate', { + // // nextRequest, + // // tokenInfo: pickResult.token + // // }); + + // // TODO: next request can also handle non-hash paths. + // // const {hash, params} = this.state.value.nextRequest; + // // navigate(hash, {params}); + // navigate2(this.state.value.nextRequest.path); + // } catch (ex) { + // console.error('[doSignIn] ERROR parsing next request', this.state.value.nextRequest, ex); + // // this.props.runtime.send('app', 'navigate', ''); + // // TODO: the default path can be external or internal, but + // // navigate doesn't handle this logic. + + // // TODO: wrong! + // const defaultPath = this.props.config.ui.defaults.path; + // navigate2(defaultPath); + // } + // } else { + // const defaultPath = this.props.config.ui.defaults.path; + // navigate2(defaultPath); + // } + } catch (ex) { + console.error(ex); + } + } + + async checkUsername(username: string): Promise { + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + try { + const { availablename } = + await auth2Client.loginUsernameSuggest(username); + if (availablename === username) { + return null; + } + return `This username is not available: a suggested available username is ${availablename}`; + } catch (ex) { + return 'error looking up username in auth'; + } + } + + onDone() { + // TODO: Currently handled by the view, but should be handled here. + } + + async startItUp() { + try { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + if ( + this.props.authState.status === + AuthenticationStatus.AUTHENTICATED + ) { + // navigate2(this.props.config.ui.defaults.path); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Invalid State', + message: 'This view only valid if not logged in.', + }, + }); + return; + } + + const providers = new Providers({ + supportedProviders: + this.props.config.services.Auth2.supportedProviders, + providers: this.props.config.services.Auth2.providers, + }).get(); + + const providersMap: Record = providers.reduce< + Record + >((accum, provider) => { + accum[provider.id] = provider; + return accum; + }, {}); + + this.props.setTitle('KBase'); + + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + // Do a root request to synchronize our clocks, as signin continue enforces + // a time limit (determined by the server) + const root = await auth2Client.root(); + + const serverTimeOffset = new Date().getTime() - root.servertime; + + const choice = await auth2Client.getLoginChoice(); + + const stateParams = getStateParam(choice); + + // The "choice" may be of the "create" or "login" subtype. + // These are only distinguishable by which of these properties is a non-zero + // length array. + // + // TODO: here we seem to use the state parameter rather than the the choice + // itself... + + // TODO: Remove this logic; signin and signup are really the same thing + // now, without any redirections. + // HMM ... I don't think this flow is supported any longer. + + // if (stateParams.origin === 'signup' && this.props.match.params.get('override-source') !== 'signin') { + // const params: Record = {}; + // // The next request is pulled out of the state param. + // // It needs to be turned back into a JSON string in order to + // // pass it as a query param value. + + // if (stateParams.nextrequest) { + // params.nextrequest = JSON.stringify(stateParams.nextrequest); + // } + + // navigate('signup', {params}); + // return null; + // } + + // At this point, we have a "login" , not "signup". + + // Prove it! + + // All we care about for policies are which ones the user has not yet agreed + // to. + + // TODO: disabled; re-enable for policy resolution. + + // Here we "prove" that this is a login choice and if so extract the policyids. + const policyids = await (async () => { + if (choice.login && choice.login.length === 1) { + return choice.login[0].policyids; + } else if (choice.create && choice.create.length === 1) { + // just pass empty policy ids, since this user has none yet. + return []; + } + // should never get here. + throw new Error( + 'Neither login nor signup available for this sign-up account', + ); + })(); + + const policies = new PolicyAndAgreement({ + policyids, + }); + + const policyAgreement = policies.getPolicyAgreement(); + + const choiceProvider = providersMap[choice.provider]; + + const value: LoginContinueSuccess = { + nextRequest: stateParams.nextrequest, + choice, + provider: choiceProvider, + policyAgreement, + serverTimeOffset, + loginState: { + status: AsyncProcessStatus.NONE, + }, + }; + + // If current policy is agreed to and auth provider does not require signin + // confirmation, then just auto-signin. + // TODO: This does not currently work. + if (policyAgreement.agreement && !choiceProvider.confirmSignin) { + await this.doSignInDirect(value); + return; + } + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value, + }); + } catch (ex) { + if (ex instanceof AuthError) { + console.error('Error starting up sign-in session', ex); + if (ex.code && ex.code === '10010') { + const message = ( +
+

+ A sign-in session was not found. This may be due + to the expiration of the sign-in or sign-up + session, which is valid for 30 minutes. Or it + may be because you have visited this path from + your browser history. +

+

+ If you wish to sign-in or sign-up, please{' '} + {this.renderSignInButton( + 'visit the sign in page', + )} + . +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Sign-In Session Expired', + message, + }, + }); + } else if (ex.code && ex.code === '10020') { + const message = ( +
+

+ The sign in session has expired. A sign in + session is valid for 30 minutes. +

+

+ If you wish to sign-in or sign-up, please{' '} + {this.renderSignInButton( + 'visit the sign in page', + )} + . +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Sign-In Session Expired', + message, + }, + }); + } else { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Error', + message: + ex instanceof Error + ? ex.message + : 'Unknown Error', + }, + }); + } + } else { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Error', + message: + ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + } + + returnToSignIn() { + navigate2({ path: 'login', type: 'kbaseui' }); + } + + renderSignInButton(message: string) { + return ( + + ); + } + + /** + * Called if the user explicitly cancels their sign in via a user control (e.g. Cancel + * button), or it times out. + * + * @param cancelMessage + */ + async cancelSignInOrUp( + cancellationType: AuthSessionCancellationType, + cancelMessage: string, + sessionType: AuthSessionType, + ) { + // TODO: use the cancel message! + + console.warn('cancellation message ignored', cancelMessage); + + const auth2Client = new Auth2({ + baseUrl: this.props.config.services.Auth2.url, + }); + + const [sessionNoun, sessionLabel] = (() => { + switch (sessionType) { + case AuthSessionType.SIGNIN: + return ['sign in', 'Sign In']; + case AuthSessionType.SIGNUP: + return ['sign up', 'Sign Up']; + } + })(); + + this.props.setTitle(`KBase ${sessionLabel} - Canceled`); + + const message = (() => { + switch (cancellationType) { + case AuthSessionCancellationType.USER: + return ( +
+

+ You have successfully cancelled your{' '} + {sessionNoun} session. +

+

+ If you wish to sign in or sign up, please{' '} + {this.renderSignInButton( + 'visit the sign in page', + )} + . +

+
+ ); + + case AuthSessionCancellationType.TIMEOUT: + return ( +
+

+ Your {sessionNoun} session has been canceled due + to too much time elapsing. A {sessionNoun}{' '} + session is valid for 30 minutes. +

+

+ If you wish to sign in or sign up, please{' '} + {this.renderSignInButton( + 'visit the sign in page', + )} + . +

+
+ ); + } + })(); + + const title = (() => { + switch (cancellationType) { + case AuthSessionCancellationType.USER: + return `${sessionLabel} Session Canceled`; + + case AuthSessionCancellationType.TIMEOUT: + return `${sessionLabel} Session Expired`; + } + })(); + + try { + await auth2Client.loginCancel(); + // TODO: hook up notifications here... + // this.props.runtime.send('notification', 'notify', { + // type: 'error', + // id: 'signin', + // icon: 'ban', + // message: cancelMessage || 'The Sign In session has been canceled', + // description: cancelMessage || 'The Sign In session has been canceled', + // autodismiss: 10000 + // }); + + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title, + message, + }, + }); + } catch (ex) { + // const errorMessage = (() => { + // if (ex instanceof Auth2Error.AuthError) { + // console.error(ex); + // // TODO: do something + // } else { + // console.error(ex); + // } + // })(); + console.error('Error canceling auth session', ex); + // TODO: add notification back here. + // this.props.runtime.send('notification', 'notify', { + // type: 'error', + // id: 'signin', + // icon: 'ban', + // message: cancelMessage || 'The Sign In session has been canceled', + // description: cancelMessage || 'The Sign In session has been canceled', + // autodismiss: 10000 + // }); + const message = ( +
+

+ An error was encountered canceling your {sessionNoun}{' '} + session. +

+

+ The {sessionNoun} session will be automatically removed + from the system after 30 minutes,{' '} +

+

+ If you wish to sign in or sign up again, please{' '} + {this.renderSignInButton('visit the sign in page')}. +

+

+ The error is:{' '} + {ex instanceof Error ? ex.message : 'Unknown Error'} +

+
+ ); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + title: 'Sign-In Session Expired', + message, + }, + }); + } + } + + cancelSignIn( + cancelationType: AuthSessionCancellationType, + cancelMessage: string, + ) { + return this.cancelSignInOrUp( + cancelationType, + cancelMessage, + AuthSessionType.SIGNIN, + ); + } + + cancelSignUp( + cancelationType: AuthSessionCancellationType, + cancelMessage: string, + ) { + return this.cancelSignInOrUp( + cancelationType, + cancelMessage, + AuthSessionType.SIGNUP, + ); + } + + renderLoading() { + return ; + } + + renderError(error: AlmostSimpleError) { + return ; + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return this.renderLoading(); + case AsyncProcessStatus.SUCCESS: { + return ( + + ); + } + case AsyncProcessStatus.ERROR: + return this.renderError(this.state.error); + } + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.css b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.css new file mode 100644 index 000000000..f46f42e96 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.css @@ -0,0 +1,6 @@ +.SignInContinueForm { +} + +.SignInContinueForm .-textSpan { + margin: 0 0.25em; +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.tsx new file mode 100644 index 000000000..e3c8d8db6 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueForm.tsx @@ -0,0 +1,325 @@ +import CountdownClock from 'components/CountdownClock'; +import Loading from 'components/Loading'; +import Well from 'components/Well'; +import { NextRequestObject } from 'lib/NextRequest'; +import { LoginChoice } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Alert, Button, Col, Row, Stack } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import { renderProviderLabel } from '../Providers'; +import TextSpan from '../TextSpan'; +import UseAgreements from '../UseAgreements'; +import { CurrentTermsAndConditionsPolicy } from './Policy'; +import { PendingPolicyAgreement, PolicyAgreement } from './PolicyAndAgreement'; +import { SignInState } from './SignInContinue'; +import SignInOops from './SignInOops'; + +// TODO: what type is choice? +function providerUserName(choice: LoginChoice): string { + // if ('provusername' in choice.login[0]) { + // return choice.login[0].provusername; + // } + return choice.login[0].provusernames.join(', '); +} + +// TODO: okay, need to resolve next request! + +export interface SignInContinueProps { + signInState: SignInState; + source: string; + choice: LoginChoice; + provider: IDProvider; + nextRequest?: NextRequestObject; + policyAgreement: PolicyAgreement; + serverTimeOffset: number; + // doSignInSubmit: () => void; + setTitle: (title: string) => void; + doSignIn: (agreement?: PendingPolicyAgreement) => void; + doCancel: () => void; +} + +export enum SignInContinueStatus { + NEED_POLICY_AGREEMENT = 'NEED_POLICY_AGREEMENT', + POLICY_AGREED_TO = 'POLICY_AGREED_TO', + READY = 'READY', +} + +export interface SignInContinueBase { + status: SignInContinueStatus; +} + +export interface SignInContinueNeedPolicyAgreement extends SignInContinueBase { + status: SignInContinueStatus.NEED_POLICY_AGREEMENT; + policy: CurrentTermsAndConditionsPolicy; +} + +export interface SignInContinuePolicyAgreedTo extends SignInContinueBase { + status: SignInContinueStatus.POLICY_AGREED_TO; + agreement: PendingPolicyAgreement; + isSubmitting: boolean; +} + +export interface SignInContinueReady extends SignInContinueBase { + status: SignInContinueStatus.READY; + isSubmitting: boolean; +} + +export type SignInContinueState = + | SignInContinueNeedPolicyAgreement + | SignInContinuePolicyAgreedTo + | SignInContinueReady; + +// interface SignInContinueState { +// canSignIn: boolean; +// agreement: PendingPolicyAgreement | null; +// } + +export default class SignInContinue extends Component< + SignInContinueProps, + SignInContinueState +> { + constructor(props: SignInContinueProps) { + super(props); + + if (props.policyAgreement.agreement) { + this.state = { + status: SignInContinueStatus.READY, + isSubmitting: false, + }; + } else { + this.state = { + status: SignInContinueStatus.NEED_POLICY_AGREEMENT, + policy: props.policyAgreement.currentPolicy, + }; + } + } + + componentDidMount() { + this.props.setTitle('Sign In'); + } + + onAgreed(agreedTo: boolean) { + if (agreedTo) { + const { id, version } = this.props.policyAgreement.currentPolicy; + this.setState({ + status: SignInContinueStatus.POLICY_AGREED_TO, + agreement: { id, version }, + isSubmitting: false, + }); + } else { + this.setState({ + status: SignInContinueStatus.NEED_POLICY_AGREEMENT, + policy: this.props.policyAgreement.currentPolicy, + }); + } + } + + renderNextRequestMessagex() { + if (!this.props.nextRequest) { + return; + } + const { + path: { path }, + label, + } = this.props.nextRequest; + return ( + + After signing in, you will returned to the{' '} + {label || path} page. + + ); + } + + renderNextRequestMessage() { + if (!this.props.nextRequest) { + return; + } + const { + path: { path }, + label, + } = this.props.nextRequest; + return ( + + Post Sign-in + +

+ After signing in, you will be returned to the{' '} + {label || path} page. +

+
+
+ ); + } + + renderAgreementRequiredMessage() { + if (this.state.status !== SignInContinueStatus.NEED_POLICY_AGREEMENT) { + return; + } + return ( + + Please read and agree to the "KBase Use Agreement" + above in order to complete Sign-In to KBase. + + ); + } + + renderHeader() { + if (this.props.choice === null) { + return; + } + + return ( + + + + Ready to sign into KBase account{' '} + {this.props.choice.login[0].user}, via the linked{' '} + {renderProviderLabel(this.props.choice.provider)}{' '} + account {providerUserName(this.props.choice)}. + + + + + + + {' '} + left to complete sign-in. + + + + ); + } + + renderSignInControl() { + const canSignIn = + this.state.status === SignInContinueStatus.READY || + this.state.status === SignInContinueStatus.POLICY_AGREED_TO; + // const variant: Variant = canSignIn ? 'primary' : 'secondary'; + + const isSubmitting = (() => { + switch (this.state.status) { + case SignInContinueStatus.READY: + case SignInContinueStatus.POLICY_AGREED_TO: + return this.state.isSubmitting; + default: + return false; + } + })(); + + return ( + + Sign In to KBase + + {this.renderAgreementRequiredMessage()} +
{ + e.preventDefault(); + this.doSigninSubmit(); + }} + > + + + + {isSubmitting ? ( + + ) : ( + '' + )} + +
+
+
+ ); + } + + async doSigninSubmit() { + switch (this.state.status) { + case SignInContinueStatus.NEED_POLICY_AGREEMENT: + break; + case SignInContinueStatus.POLICY_AGREED_TO: + this.setState({ + ...this.state, + isSubmitting: true, + }); + this.props.doSignIn(this.state.agreement); + break; + case SignInContinueStatus.READY: + this.setState({ + ...this.state, + isSubmitting: true, + }); + this.props.doSignIn(); + } + return false; + } + + renderUseAgreement() { + if (this.state.status === SignInContinueStatus.READY) { + return; + } + return ( + + ); + } + + render() { + return ( + + {this.renderHeader()} + + + +
+ + {this.renderUseAgreement()} + + {this.renderNextRequestMessage()} + + {this.renderSignInControl()} + + ); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.css b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.css new file mode 100644 index 000000000..085922d80 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.css @@ -0,0 +1,26 @@ +.SignInContinueView { + flex: 1 1 0px; + display: flex; + flex-direction: column; + overflow-y: auto; + margin: 0 1rem; +} + +.SignInContinueView .-header { + flex: 0 0 auto; + display: flex; + flex-direction: row; +} + +.SignInContinueView .-header .-col1 { + flex: 1 1 0; + font-weight: bold; +} + +.SignInContinueView .-header .-col2 { + flex: 0 0 auto; +} + +.SignInContinueView .-body { + flex: 1 1 0; +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.tsx new file mode 100644 index 000000000..7cedf4b08 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInContinueView.tsx @@ -0,0 +1,216 @@ +import CountdownClock from 'components/CountdownClock'; +import { NextRequestObject } from 'lib/NextRequest'; +import { LoginChoice } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Alert, Col, Row } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import { renderProviderLabel } from '../Providers'; +import TextSpan from '../TextSpan'; +import { PendingPolicyAgreement, PolicyAgreement } from './PolicyAndAgreement'; +import { + AuthSessionCancellationType, + SignInStatus, + SignUpFormInfo, +} from './SignInContinue'; +import SignInContinueForm from './SignInContinueForm'; +import './SignInContinueView.css'; +import SignUpContinue from './SignUpContinue'; + +// function provisionalUserName(choice: LoginChoice) { +// if (choice.create.length > 0) { +// return choice.create![0].provusername; +// } +// return choice.login![0].provusernames.join(', '); +// } + +export interface SignInContinueViewProps { + choice: LoginChoice; + provider: IDProvider; + source: string; + serverTimeOffset: number; + nextRequest?: NextRequestObject; + //TODO: type this + policyAgreement: PolicyAgreement; + setTitle: (title: string) => void; + onDone: () => void; + doSignIn: (agreement?: PendingPolicyAgreement) => void; + doSignUp: (signUpInfo: SignUpFormInfo) => void; + cancelSignIn: (type: AuthSessionCancellationType, message: string) => void; + cancelSignUp: (type: AuthSessionCancellationType, message: string) => void; + checkUsername: (username: string) => Promise; +} + +export default class SignInContinueView extends Component { + getUIState() { + const choice = this.props.choice; + if (choice) { + return { + auth: true, + signin: choice.login.length > 0, + signup: choice.create.length > 0, + }; + } + return { + auth: false, + signin: false, + signup: false, + }; + } + + renderStep2Inactive() { + return
Step 2 Inactive
; + } + + renderOopsExplanation(provider: IDProvider) { + if (this.props.source === 'signin') { + return ( +
+

+ If this browser is already signed in to {provider.label} + , a sign-in attempt from KBase will route you to{' '} + {provider.label} and back again without any warning. +

+

+ If this just happened to you, and the account you see + above is not the one you want, you should use the logout + link below to log out of + {provider.label}, and then try again. +

+
+ ); + } + return ( +
+

+ If this browser is already signed in to {provider.label}, a + sign-in attempt from KBase will route you to{' '} + {provider.label} and back again without any warning. +

+

+ If this just happened to you, and the account you see above + is not the one you want, you should use the link below to + log out of {provider.label}, and then try again. +

+
+ ); + } + + renderSignUp() { + return ( + { + this.props.cancelSignUp( + AuthSessionCancellationType.USER, + message, + ); + }} + onSignUp={this.props.doSignUp} + nextRequest={this.props.nextRequest} + /> + ); + } + + renderSignIn() { + return ( + { + this.props.cancelSignIn( + AuthSessionCancellationType.USER, + 'User canceled sign in', + ); + }} + /> + ); + } + + renderSignupState() { + const uiState = this.getUIState(); + if (uiState.auth === false) { + return this.renderStep2Inactive(); + } else if (uiState.signin) { + return this.renderSignIn(); + } else if (uiState.signup) { + return this.renderSignUp(); + } + return
Invalid state
; + } + + renderHeader() { + if (this.props.choice === null) { + return; + } + + function providerUserName(choice: LoginChoice): string { + return choice.create[0].provusername; + } + + // const progress = ((this.props.choice.expires + this.props.serverTimeOffset) - Date.now())/3000 + + return ( + + + + You are ready to + sign in to KBase account + + {this.props.choice.login[0].user} + + via the linked + + {renderProviderLabel(this.props.choice.provider)} + + account + + {providerUserName(this.props.choice)} + + + + + + You have{' '} + + { + this.props.cancelSignIn( + AuthSessionCancellationType.TIMEOUT, + 'Sign In canceled due to timeout', + ); + }} + /> + {' '} + to complete Sign In. + + {/* */} + + + ); + } + + render() { + return ( +
+
{this.renderSignupState()}
+
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignInOops.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignInOops.tsx new file mode 100644 index 000000000..823da9f35 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignInOops.tsx @@ -0,0 +1,166 @@ +import { NextRequestObject } from 'lib/NextRequest'; +import { urlToKBaseUI } from 'lib/navigation'; +import { Component, Fragment } from 'react'; +import { Button } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import Collapsible from '../Collapsible'; +import TextSpan from '../TextSpan'; + +export interface SignInOopsProps { + provider: IDProvider; + source: string; + nextRequest?: NextRequestObject; +} + +export default class SignInOops extends Component { + renderOopsExplanation() { + const provider = this.props.provider; + if (this.props.source === 'signin') { + return ( + +

+ If this browser is already signed in to{' '} + {provider.label}, a sign-in attempt from KBase + will route you to {provider.label} and back again + without any warning. +

+

+ If this just happened to you, and the account you see + above is not the one you want, you should use the logout + link below to log out of {provider.label}, and + then try again. +

+
+ ); + } + return ( + +

+ If this browser is already signed in to{' '} + {provider.label}, a sign-in attempt from KBase will + route you to {provider.label} and back again without + any warning. +

+

+ If this just happened to you, and the account you see above + is not the one you want, you should use the link below to + log out of {provider.label}, and then try again. +

+ {/*

+ If you have signed in with a {provider.label} account already linked to a KBase account, + you will be unable to create a new KBase account using that {provider.label} account. +

*/} +
+ ); + } + + render() { + const explanation = this.renderOopsExplanation(); + + const params: Record = {}; + if (this.props.nextRequest) { + params['nextrequest'] = JSON.stringify(this.props.nextRequest); + } + + const signInURL = urlToKBaseUI({ path: 'login', params }); + + const provider = this.props.provider; + + // return + // + // + // Not the account you were expecting? + // + // + + // {explanation} + //
+ // + //
+ //

+ // After signing out from + // {provider.label} + // you will need to + // + // again. + //

+ //
+ //
+ //
+ + // TODO: improve source with a enum + const label = (() => { + switch (this.props.source) { + case 'signin': + return 'Sign In'; + case 'signup': + return 'Sign Up'; + default: + return 'Sign In'; + } + })(); + + return ( + + Didn't mean to {label} with this{' '} + {provider.label} account? +
+ } + render={() => { + return ( + <> + {explanation} +
+ +
+

+ After signing out from + {provider.label} + you will need to + + again. +

+ + ); + }} + /> + ); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignUpContinue.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignUpContinue.tsx new file mode 100644 index 000000000..debf577ca --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignUpContinue.tsx @@ -0,0 +1,177 @@ +import CountdownClock from 'components/CountdownClock'; +import Well from 'components/Well'; +import { NextRequestObject } from 'lib/NextRequest'; +import { LoginChoice } from 'lib/kb_lib/Auth2'; +import { Component } from 'react'; +import { Alert, Col, Container, Row } from 'react-bootstrap'; +import { IDProvider } from 'types/config'; +import TextSpan from '../TextSpan'; +import { SignUpFormInfo } from './SignInContinue'; +import SignInOops from './SignInOops'; +import SignUpForm from './SignUpForm'; + +/** + * Now we use ant design forms. Don't reinvent the wheel (yet again!) + */ + +export interface OptionItem { + value: string; + label: string; +} +export interface SignUpContinueProps { + choice: LoginChoice; + serverTimeOffset: number; + provider: IDProvider; + checkUsername: (username: string) => Promise; + cancelSignUp: (message: string) => void; + onSignUp: (signUpInfo: SignUpFormInfo) => void; + setTitle: (title: string) => void; + nextRequest?: NextRequestObject; +} + +export default class SignUpContinue extends Component { + componentDidMount() { + this.props.setTitle('Sign Up for KBase'); + } + + renderNextRequestMessage() { + if (!this.props.nextRequest) { + return; + } + const { + path: { path }, + label, + } = this.props.nextRequest; + return ( + + Post Sign-in + +

+ After signing in, you will be returned to the{' '} + {label || path} page. +

+
+
+ ); + } + + renderHeader() { + if (this.props.choice === null) { + return; + } + + // function providerUserName(choice: LoginChoice): string { + // return choice.create[0].provusername; + // } + + return ( + + + + {/* You are ready to + sign up + for a KBase account via the linked + {renderProviderLabel(this.props.choice.provider)} + account + {providerUserName(this.props.choice)} */} + Hi, it looks like this is your first time using KBase + with your + {this.props.choice.provider} + account + + {this.props.choice.create![0].provusername} + + . +
+ You may sign up for a free KBase account below., after + which you may sign in using this Globus account. +
+ + + + You have{' '} + + { + this.props.cancelSignUp( + 'Signup canceled due to timeout', + ); + }} + /> + {' '} + to complete sign-up. + + {/* */} + +
+ ); + } + + render() { + return ( + + {this.renderHeader()} + + + + + + + {this.renderNextRequestMessage()} + + + {/* + + + + Sign Up for KBase + + +

+ Hi, it looks like this is your first time using KBase with your + {this.props.choice.provider} + account + {this.props.choice.create![0].provusername}. +

+ +

+ You may sign up for a free KBase account below. +

+
+
+ +
*/} + + + + + Sign Up for KBase + + { + this.props.cancelSignUp(message); + }} + onSignUp={this.props.onSignUp} + /> + + + + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/SignInContinue/SignUpForm.tsx b/vite-app/src/apps/Auth2/SignInContinue/SignUpForm.tsx new file mode 100644 index 000000000..2347bbfc5 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignInContinue/SignUpForm.tsx @@ -0,0 +1,525 @@ +import CloseOutlined from '@ant-design/icons/lib/icons/CloseOutlined'; +import SaveOutlined from '@ant-design/icons/lib/icons/SaveOutlined'; +import { Button, Checkbox, Form, FormInstance, Input, Space } from 'antd'; +import { FieldData, FieldName } from 'apps/UserProfile/Profile/ProfileEditor'; +import Organization from 'apps/UserProfile/Profile/fields/Organization'; +import { LoginChoice } from 'lib/kb_lib/Auth2'; +import { Component, ReactNode, createRef } from 'react'; +import { Button as BSButton } from 'react-bootstrap'; +import { Asterisk } from 'react-bootstrap-icons'; +import referralSourcesData from '../resources/data/referralSources.json'; +import CheckUsernameField from './CheckUsernameField'; +import Policy, { CurrentTermsAndConditionsPolicy } from './Policy'; +import { SignUpFormInfo } from './SignInContinue'; + +/** + * Now we use ant design forms. Don't reinvent the wheel (yet again!) + */ + +export interface OptionItem { + value: string; + label: string; +} +const referralSources = referralSourcesData as unknown as Array; + +const HEAR_ABOUT_QUESTION = 'How did you hear about us?'; + +export interface SignUpFormProps { + choice: LoginChoice; + serverTimeOffset: number; + checkUsername: (username: string) => Promise; + cancelSignUp: (message: string) => void; + onSignUp: (signUpInfo: SignUpFormInfo) => void; +} + +interface SignUpFormState { + ready: boolean; + hearAboutOther: boolean; + canCheckUsername: boolean; + isUsernameAvailable: boolean; + termsAndConditionsOpened: boolean; + isFormValid: boolean; +} + +function fieldNameEqual(fieldName: FieldName, value: string) { + if (typeof fieldName === 'string') { + return fieldName === value; + } else if (Array.isArray(fieldName) && fieldName.length === 1) { + return fieldName[0] === value; + } + return false; +} + +export interface FormData { + realname: string; + username: string; + email: string; + organization: string; + department: string; + hearAbout: Array; + hearAboutOther?: string; +} + +export default class SignUpForm extends Component< + SignUpFormProps, + SignUpFormState +> { + formRef = createRef(); + policy: CurrentTermsAndConditionsPolicy = new Policy().currentPolicy(); + constructor(props: SignUpFormProps) { + super(props); + + this.state = { + ready: true, + hearAboutOther: false, + canCheckUsername: false, + isUsernameAvailable: false, + termsAndConditionsOpened: false, + isFormValid: false, + }; + } + + componentDidMount() { + const { realname, email } = (() => { + const createChoice = this.props.choice.create[0]; + if (!createChoice) { + return { realname: '', email: '' }; + } + return { + realname: createChoice.provfullname, + email: createChoice.provemail, + }; + })(); + + this.formRef.current?.setFieldsValue({ realname, email }); + } + + checkForm(allFields: Array) { + const isValid = (() => { + const hearAboutField = allFields.filter(({ name }) => { + if (typeof name === 'string') { + return name === 'hearAbout'; + } else if (Array.isArray(name)) { + return name[0] === 'hearAbout'; + } + })[0]; + const needHearAboutOther = + hearAboutField.touched && + hearAboutField.errors?.length === 0 && + hearAboutField.value === 'other'; + + // for the "heard about other" field, only consider it if + // the username is not empty + const fields = allFields.filter((field) => { + if ( + fieldNameEqual(field.name, 'hearAboutOther') && + !needHearAboutOther + ) { + return false; + } + return true; + }); + + if (fields) { + // Invalid if there all fields are touched and have no errors. + const allValid = fields.every(({ errors, touched }) => { + return !errors || (errors.length === 0 && touched); + }); + return allValid; + } + const fieldsError = this.formRef.current?.getFieldsError(); + if (!fieldsError) { + return true; + } + return fieldsError.every(({ errors }) => { + return errors.length === 0; + }); + })(); + + const isTouched = this.formRef.current?.isFieldsTouched(); + + return { isValid, isTouched }; + } + + saveForm() { + const rawFormData = this.formRef.current?.getFieldsValue(); + + if (typeof rawFormData !== 'object' || rawFormData === null) { + throw new Error('The update is not an object'); + } + + const formData = rawFormData as FormData; + + const formInfo: SignUpFormInfo = { + realname: formData.realname, + username: formData.username, + email: formData.email, + organization: formData.organization, + department: formData.organization, + hearAbout: { + question: HEAR_ABOUT_QUESTION, + response: formData.hearAbout.reduce>( + (accum, value) => { + if (value === 'other') { + accum[value] = formData.hearAboutOther!; + } else { + accum[value] = ''; + } + return accum; + }, + {}, + ), + }, + agreement: { + id: this.policy.id, + version: this.policy.version, + }, + }; + + this.props.onSignUp(formInfo); + } + + onFieldsChange(changedFields: FieldData[], allFields: Array) { + const newState = { ...this.state }; + + // Sets the "hearAboutOther" state flag if the hearAbout field is set to + // the value "other" + const hearAbout = changedFields.filter(({ name }) => { + if (Array.isArray(name)) { + return name.includes('hearAbout'); + } + return false; + })[0]; + if (hearAbout) { + // TODO: assert this? but what then? it is, by definition, an array of + // strings since it comes from a checkbox group. + const hearAboutValue = hearAbout.value as Array; + newState.hearAboutOther = hearAboutValue.includes('other'); + } + + // Sets the "canCheckUsername" state flag if the username is set to a valid + // value. + // Also esets the "check username availability" flag to "none" if the username was changed. + const username = changedFields.filter(({ name }) => { + if (Array.isArray(name)) { + return name.includes('username'); + } else if (typeof name === 'string') { + return name === 'username'; + } + return false; + }); + + if (username.length > 0) { + newState.canCheckUsername = true; + this.formRef.current?.setFieldsValue({ + usernameavailable: 'required', + }); + } + + // Get the global form validation state, and set the "isFormValid" state flag + // appropriately. + const { isValid } = this.checkForm(allFields); + newState.isFormValid = isValid; + + this.setState(newState); + } + + requiredMark(labelNode: ReactNode, { required }: { required: boolean }) { + if (required) { + return ( + + {labelNode} + + ); + } + return labelNode; + } + + openTermsAndConditions() { + const url = this.policy.url; + this.setState({ + termsAndConditionsOpened: true, + }); + window.open(url, '_blank'); + } + + renderForm() { + return ( +
+ + + + + + + + + { + if (/^\d+/.test(rawValue)) { + throw new Error( + 'A username may not begin with a number', + ); + } + if (/^_+/.test(rawValue)) { + throw new Error( + 'A username may not start with the underscore character', + ); + } + if (/\s/.test(rawValue)) { + throw new Error( + 'A username may not contain spaces', + ); + } + }, + }, + ]} + > + + + + { + switch (value) { + case 'na': + throw new Error( + 'Can check when supply a valid username', + ); + case 'required': + throw new Error( + 'Need to check if username is available', + ); + case 'unavailable': + throw new Error( + 'Username not available', + ); + } + }, + }, + // { + // validator: async(_, value: string) => { + // const username = this.formRef.current?.getFieldValue('username'); + // if (username.length === 0) { + + // } + // } + // } + ]} + > + + + + + + + + + + + + {referralSources.map(({ value, label }) => { + return ( +
+ {label} +
+ ); + })} +
+
+ + + + + Open and review the{' '} + + Terms and Conditions (v{this.policy.version},{' '} + {Intl.DateTimeFormat('en-US', {}).format( + this.policy.publishedAt, + )} + ) + +
+ (After opening the link above, you can agree to the terms + below) +
+ + { + if (!value) { + throw new Error( + 'You must agree to the Terms and Conditions in order Sign Up', + ); + } + }, + }, + ]} + > + + I have read and agree to the KBase Terms and Conditions + + + + ); + } + + render() { + return ( +
+ {this.renderForm()} + + + + +
+ ); + } +} diff --git a/vite-app/src/apps/Auth2/SignedOut/controller.tsx b/vite-app/src/apps/Auth2/SignedOut/controller.tsx new file mode 100644 index 000000000..401a0db5c --- /dev/null +++ b/vite-app/src/apps/Auth2/SignedOut/controller.tsx @@ -0,0 +1,105 @@ +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { + AuthenticationState, + AuthenticationStatus, +} from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { navigate2 } from 'lib/navigation'; +import { Component } from 'react'; +import { Config, IDProvider } from 'types/config'; +import { Providers } from '../Providers'; +import SignedOutView from './view'; + +export interface SignedOutControllerProps { + authState: AuthenticationState; + config: Config; + setTitle: (title: string) => void; +} + +export interface SignedOutControllerSuccess { + providers: Array; +} + +type SignedOutControllerState = AsyncProcess< + SignedOutControllerSuccess, + SimpleError +>; + +export default class SignedOutController extends Component< + SignedOutControllerProps, + SignedOutControllerState +> { + constructor(props: SignedOutControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.start(); + } + + componentDidUpdate(prevProps: SignedOutControllerProps) { + if (prevProps.authState.status !== this.props.authState.status) { + this.start(); + } + } + + async start() { + try { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + if ( + this.props.authState.status !== + AuthenticationStatus.UNAUTHENTICATED + ) { + // Rather than show an error message, let us take the browser somewhere + // interesting, like the default view. + navigate2({ path: 'narratives', type: 'europaui' }); + + return; + } + + this.props.setTitle('Signed Out'); + + const providers = new Providers({ + supportedProviders: + this.props.config.services.Auth2.supportedProviders, + providers: this.props.config.services.Auth2.providers, + }).get(); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + providers, + }, + }); + } catch (ex) { + console.error(ex); + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: { + return ; + } + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/Auth2/SignedOut/view.tsx b/vite-app/src/apps/Auth2/SignedOut/view.tsx new file mode 100644 index 000000000..93e3a5e26 --- /dev/null +++ b/vite-app/src/apps/Auth2/SignedOut/view.tsx @@ -0,0 +1,55 @@ +import Well from 'components/Well'; +import { Component } from 'react'; +import { IDProvider } from 'types/config'; + +export interface SignedOutViewProps { + providers: Array; +} + +export default class SignedOutView extends Component { + render() { + const providerLinksList = this.props.providers.map( + ({ id, logoutUrl, label }) => { + return ( +
  • + + Log out from {label} + +
  • + ); + }, + ); + return ( + + You are signed out of KBase. + +

    + Although signed out of KBase, you may still be logged + into an identity provider you have recently used to sign + in to KBase in this browser. This could allow your KBase + account to be accessed merely by using the Sign In + button and choosing the sign-in provider. +

    +

    + If you wish to ensure that your KBase account is + inaccessible from this browser, you should sign out of + any accounts you have used to access KBase as well. +

    +
      {providerLinksList}
    +

    Additional security measures include:

    +
      +
    • Remove all browser cookies
    • +
    • + Use your browser's private-browsing feature +
    • +
    +
    +
    + ); + } +} diff --git a/vite-app/src/apps/Auth2/Signout/controller.tsx b/vite-app/src/apps/Auth2/Signout/controller.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/vite-app/src/apps/Auth2/Signout/view.tsx b/vite-app/src/apps/Auth2/Signout/view.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/vite-app/src/apps/Auth2/TextSpan.tsx b/vite-app/src/apps/Auth2/TextSpan.tsx new file mode 100644 index 000000000..17067362e --- /dev/null +++ b/vite-app/src/apps/Auth2/TextSpan.tsx @@ -0,0 +1,23 @@ +import { CSSProperties, Component, PropsWithChildren } from 'react'; + +export interface TextSpanProps extends PropsWithChildren { + bold?: boolean; + last?: boolean; + style?: CSSProperties; +} + +export default class TextSpan extends Component { + render() { + const style: CSSProperties = this.props.style ? this.props.style : {}; + + if (this.props.bold) { + style.fontWeight = 'bold'; + } + if (this.props.last) { + style.margin = '0 0 0 0.25em'; + } else { + style.margin = '0 0.25em'; + } + return {this.props.children}; + } +} diff --git a/vite-app/src/apps/Auth2/UseAgreements.css b/vite-app/src/apps/Auth2/UseAgreements.css new file mode 100644 index 000000000..122500d64 --- /dev/null +++ b/vite-app/src/apps/Auth2/UseAgreements.css @@ -0,0 +1,8 @@ +.UseAgreements { +} + +.UseAgreements .-agreementMessage { + font-style: 'italic'; + text-align: 'center'; + margin-top: '20px'; +} diff --git a/vite-app/src/apps/Auth2/UseAgreements.tsx b/vite-app/src/apps/Auth2/UseAgreements.tsx new file mode 100644 index 000000000..959019b51 --- /dev/null +++ b/vite-app/src/apps/Auth2/UseAgreements.tsx @@ -0,0 +1,268 @@ +import Well from 'components/Well'; +import { Component } from 'react'; +import { Alert, Button } from 'react-bootstrap'; +import { ExclamationTriangle } from 'react-bootstrap-icons'; +import { CurrentTermsAndConditionsPolicy } from './SignInContinue/Policy'; + +export interface UseAgreementsProps { + policyToResolve: CurrentTermsAndConditionsPolicy; + hasPreviousAgreements: boolean; + onAgreed: (agreedTo: boolean) => void; +} + +interface PolicyResolution { + policy: CurrentTermsAndConditionsPolicy; + isViewed: boolean; + isAgreedTo: boolean; +} + +interface UseAgreementState { + policyResolution: PolicyResolution; +} + +export default class UseAgreements extends Component< + UseAgreementsProps, + UseAgreementState +> { + constructor(props: UseAgreementsProps) { + super(props); + + this.state = { + policyResolution: { + policy: props.policyToResolve, + isViewed: false, + isAgreedTo: false, + }, + }; + } + + onViewPolicy() { + const { policy, isViewed } = this.state.policyResolution; + if (isViewed) { + return; + } + this.setState({ + policyResolution: { + ...this.state.policyResolution, + isViewed: true, + }, + }); + window.open(policy.url.toString(), '_blank'); + } + + toggleIsAgreedTo() { + const { isAgreedTo } = this.state.policyResolution; + this.setState( + { + policyResolution: { + ...this.state.policyResolution, + isAgreedTo: !isAgreedTo, + }, + }, + () => { + this.props.onAgreed(!isAgreedTo); + }, + ); + } + + render() { + const { policy, isViewed, isAgreedTo } = this.state.policyResolution; + + const agreementLabel = (() => { + if (isViewed) { + if (isAgreedTo) { + return ( +
    { + this.toggleIsAgreedTo(); + }} + className="text-success" + style={{ fontWeight: 'bold', cursor: 'pointer' }} + > + I have read and agree to this policy +
    + ); + } + return ( +
    { + this.toggleIsAgreedTo(); + }} + className="text-danger" + style={{ fontWeight: 'bold', cursor: 'pointer' }} + > + I have read and agree to this policy +
    + ); + } + return ( +
    + I have read and agree to this policy +
    + ); + })(); + + const mustViewMessage = (() => { + if (isViewed) { + if (isAgreedTo) { + return ( + + You have agreed to this policy. + + ); + } + return ( + + You have opened the policy document and must agree to it + in order to complete sign in. + + ); + } + return ( + + You must open the {policy.title} before you may agree + to it. + + ); + })(); + + const openPolicyMessage = (() => { + if (isViewed) { + return ( +

    + You have opened the{' '} + + . +

    + ); + } + return ( +

    + Please open and review the{' '} + + . +

    + ); + })(); + + // const phrase = (() => { + // if (this.props.hasPreviousAgreements) { + // return 'has been updated'; + // } + // return 'has not yet been agreed to by this account'; + // })(); + + return ( +
    + + {' '} + KBase Terms and Conditions (T&C) have been updated. The + new T&C was published on{' '} + {Intl.DateTimeFormat('en-US', {}).format( + this.props.policyToResolve.publishedAt, + )} + + {/*

    + The following KBase use policy {phrase}. +

    +

    + You may sign in to this account after you have agreed to this policy by checking the box next to it. +

    */} + + KBase Terms and Conditions + +
    +
    + {openPolicyMessage} + {mustViewMessage} +
    +
    +
    +
    + { + this.toggleIsAgreedTo(); + }} + /> +
    +
    + {agreementLabel} +
    +
    +
    +
    +
    +
    +
    +
    +
    + ); + } +} diff --git a/vite-app/src/apps/Auth2/resources/agreements/policies.json b/vite-app/src/apps/Auth2/resources/agreements/policies.json new file mode 100644 index 000000000..30202de93 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/agreements/policies.json @@ -0,0 +1,31 @@ +[ + { + "id": "kbase-user", + "title": "KBase Use Agreement", + "versions": [ + { + "version": 1, + "begin": "2015-01-01T08:00:00Z", + "end": "2024-01-01T00:00:00Z", + "document": "# Terms and Conditions\n\n## Prohibited Behavior\n\nAs a condition of your use of KBase (the DOE Systems Biology Knowledgebase) you agree not to upload any type of human data or personally identifiable information.\n\n> Improper use of KBase, including uploading human data, may result in the termination of KBase access privileges.\n\n## Data Sharing\n\nKBase conforms to the Information and Data Sharing Policy of the Genomic Science Program of the Office of Biological and Environmental Research within the Office of Science. Please see the KBase Data Policy page for more information.\n\n## Responsibility for Data\n\nAs a condition of your use of KBase you accept sole responsibility for all files you upload or transfer through use of KBase. You recognize and accept that KBase does not guarantee long-term retention of user uploaded data, and will not be responsible for any failure to store or transfer, or deletion, corruption or loss for any data, information or content contained in your files. It is strongly recommended that you back up all files prior to using KBase.

    \n\n## Use Agreement\n\nBy using KBase, including its websites and services or via published APIs, you are agreeing to the terms stated in our Use Agreement. Please read them carefully. They include limitations on what is acceptable user behavior, accountability, availability, data retention, and conditions for account termination. If you do not agree, do not access or use KBase.\n\n## Privacy Policy\n\nKBase is provided as a public service. KBase reserves the right to monitor any and all use of kbase.us. KBase never collects information for commercial marketing or any purpose unrelated to KBase functions. The Privacy Policy describes the ways KBase collects, stores, uses, discloses and protects the personal information about users and how they use KBase.\n\n## Open Source License\n\nAll software developed by the KBase project team, and any contributed by you to KBase, is stored and maintained in the public KBase GitHub code repository under the MIT Open Source License (“License”). By contributing to or using KBase, you acknowledge having read and understood the License and agree to abide by it.\n" + }, + { + "version": 2, + "url": "https://www.kbase.us/about/terms-and-conditions-v2", + "begin": "2024-01-01T00:00:00Z" + } + ] + }, + { + "id": "data-policy", + "title": "KBase Data Policy", + "versions": [ + { + "version": 1, + "begin": "2015-01-01T08:00:00Z", + "end": "2024-01-01T00:00:00Z", + "document": "# Data Policy\n\n## Data Policies\n\nKBase conforms to the Information and Data Sharing Policy of the Genomic Science Program of the Office of Biological and Environmental Research within the Office of Science. This requires that all publishable data, metadata, and software resulting from research funded by the Genomic Science program must conform to community-recognized standard formats when they exist; be clearly attributable; and be deposited within a community-recognized public database(s) appropriate for the research.\n\nData publicly available in KBase comes from the sources listed on this page. Additionally, users can upload their own data to KBase to analyze it, and can choose how widely their data should be shared. (All data uploaded by users is private to them unless they choose to share it.)\n\n> NOTICE: KBase does not guarantee long-term retention of user-uploaded data. Please take appropriate precautions in storing and backing up your data locally.\n\n> WARNING: Improper use of KBase, including uploading human data, may result in the termination of KBase access privileges. Please see the Terms and Conditions page for more information.\n" + } + ] + } +] diff --git a/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions copy.json b/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions copy.json new file mode 100644 index 000000000..a07a9155d --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions copy.json @@ -0,0 +1,21 @@ +{ + "id": "kbase-user", + "title": "KBase Use Agreement", + "versions": [ + { + "version": 1, + "publishedAt": "2015-01-01T08:00:00Z", + "url": "https://www.kbase.us/about/terms-and-conditions-v1" + }, + { + "version": 2, + "url": "https://www.kbase.us/about/terms-and-conditions-v2", + "publishedAt": "2023-04-01T07:00:00Z" + }, + { + "version": 3, + "url": "https://www.kbase.us/about/terms-and-conditions-v2", + "publishedAt": "2023-05-01T07:00:00Z" + } + ] +} diff --git a/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions.json b/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions.json new file mode 100644 index 000000000..a8386bd49 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/agreements/terms-and-conditions.json @@ -0,0 +1,16 @@ +{ + "id": "kbase-user", + "title": "KBase Use Agreement", + "versions": [ + { + "version": 1, + "publishedAt": "2015-01-01T08:00:00Z", + "url": "https://www.kbase.us/about/terms-and-conditions-v1" + }, + { + "version": 2, + "url": "https://www.kbase.us/about/terms-and-conditions-v2", + "publishedAt": "2023-04-01T07:00:00Z" + } + ] +} diff --git a/vite-app/src/apps/Auth2/resources/css/flex-tabs.css b/vite-app/src/apps/Auth2/resources/css/flex-tabs.css new file mode 100644 index 000000000..4f824eb6d --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/css/flex-tabs.css @@ -0,0 +1,93 @@ +.flex-tabs { + display: flex; + flex-direction: column; + flex: 1 1 0px; +} + +.flex-tabs > .-tabs { + flex: 0 0 2.8em; + text-align: bottom; + display: flex; + flex-direction: row; + /* padding-left: 2em; */ + /* border-bottom: 1px rgba(200, 200, 200, 0.5) solid; */ + overflow: hidden; + text-overflow: ellipsis; +} + +.flex-tabs > .-tabs > .-tab { + cursor: pointer; + padding: 0 8px 0 8px; + background-color: transparent; + user-select: none; + border: 1px transparent solid; + border-radius: 4px 4px 0 0; + line-height: 2.8em; + border-bottom: 1px solid #ddd; +} + +.flex-tabs > .-tabs > .-tab-rest { + flex: 1 1 0px; + border-bottom: 1px solid #ddd; +} + +/* .flex-tabs>.-tabs>.-tab:nth-child(1) { + padding-left: 0px; +} */ + +.flex-tabs > .-tabs > .-tab > .-label { + line-height: 2.8em; + padding: 0 8px; + /* display: inline-block; +vertical-align: middle; */ + white-space: nowrap; + color: #337ab7; +} + +.flex-tabs > .-tabs > .-tab:hover { + background-color: #eeeeee; +} + +.flex-tabs > .-tabs > .-tab.-active:hover { + background-color: transparent; +} + +.flex-tabs > .-tabs > .-tab.-active > .-label { + color: #555555; +} + +.flex-tabs > .-tabs > .-tab.-active { + /*border: 2px rgba(200, 200, 200, 0.5) solid;*/ + /* background-color: rgba(200, 200, 200, 0.5); */ + color: #000; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +/* .flex-tabs>.-tabs>.-tab.-inactive { + background-color: transparent; +} */ + +/* Panels */ + +.flex-tabs > .-panels { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.flex-tabs .-panel { + padding: 3px; + background-color: transparent; + flex: 1 1 0px; + display: flex; + flex-direction: column; + overflow-y: auto; +} + +.flex-tabs > .-panels > .-panel.-inactive { + display: none; +} + +.flex-tabs > .-panels > .-panel.-active { +} diff --git a/vite-app/src/apps/Auth2/resources/css/main.css b/vite-app/src/apps/Auth2/resources/css/main.css new file mode 100644 index 000000000..e0e606e61 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/css/main.css @@ -0,0 +1,109 @@ +@import url('flex-tabs.css'); + +.form-row:hover { + background-color: #ccc; +} + +.form-sub-row { + border: 1px transparent solid; + padding: 3px; + box-sizing: border-box; +} + +.form-sub-row:nth-last-child() { +} + +.form-sub-row:hover { + border: 1px #eee solid; +} + +.form-row { + padding: 4px; +} + +.field-doc { + margin-bottom: 4px; + color: #aaa; +} + +.form-row:hover .field-doc { + color: #000; +} + +/* Policy resolver component styles */ + +.policy-markdown { + font-family: Arial, sans-serif; +} + +.policy-markdown h1 { + font-family: Arial, sans-serif; + margin-top: 0; + margin-bottom: 0; + font-weight: bold; + font-size: 150%; +} + +.policy-markdown h2 { + font-family: Arial, sans-serif; + margin-top: 1em; + margin-bottom: 0; + font-weight: bold; + font-size: 135%; +} + +.policy-markdown h3 { + font-family: Arial, sans-serif; + margin-top: 1em; + margin-bottom: 0; + font-weight: bold; + font-size: 120%; +} + +.policy-markdown h4 { + font-family: Arial, sans-serif; + margin-top: 1em; + margin-bottom: 0; + font-weight: bold; + font-size: 100%; +} + +.policy-markdown p { + margin-top: 0.5em; +} + +.policy-markdown blockquote { + font-size: inherit; + margin-left: 1em; + padding-left: 1em; + border-left: 3px silver solid; +} + +.policy-markdown a { +} + +.policy-markdown a:link, +.policy-markdown a:visited { +} + +.policy-markdown a:hover, +.policy-markdown a:active { +} + +/* responsive youtube */ + +.embed-container { + position: relative; + padding-bottom: 56.25%; + height: 0; + overflow: hidden; + max-width: 100%; +} + +.embed-container iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} diff --git a/vite-app/src/apps/Auth2/resources/data/config.yml b/vite-app/src/apps/Auth2/resources/data/config.yml new file mode 100644 index 000000000..d787d5c7b --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/config.yml @@ -0,0 +1,3 @@ +# Config +--- +auth2-launch-date: '6/9/17' diff --git a/vite-app/src/apps/Auth2/resources/data/globus-providers.json b/vite-app/src/apps/Auth2/resources/data/globus-providers.json new file mode 100644 index 000000000..2276eea5e --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/globus-providers.json @@ -0,0 +1,1474 @@ +[ + { + "id": "aalborg_university", + "label": "Aalborg University" + }, + { + "id": "aarhus_basic_health_care_college", + "label": "Aarhus Basic Health Care College" + }, + { + "id": "aarhus_school_of_marine_and_technical_engineering", + "label": "Aarhus School of Marine and Technical Engineering" + }, + { + "id": "aarhus_university", + "label": "Aarhus University" + }, + { + "id": "academic_computer_center_task_in_gdansk", + "label": "Academic Computer Center TASK in Gdansk" + }, + { + "id": "aconet_team", + "label": "ACOnet Team" + }, + { + "id": "alexander_stuart_test_idp_yin", + "label": "Alexander Stuart test IdP (yin)" + }, + { + "id": "anton_bruckner_private_university", + "label": "Anton Bruckner Private University" + }, + { + "id": "alcf", + "label": "Argonne LCF" + }, + { + "id": "argonne_national_laboratory", + "label": "Argonne National Laboratory" + }, + { + "id": "aristotle_university_of_thessaloniki", + "label": "Aristotle University of Thessaloniki" + }, + { + "id": "arizona_state_university", + "label": "Arizona State University" + }, + { + "id": "auburn_university", + "label": "Auburn University" + }, + { + "id": "augusta_university", + "label": "Augusta University" + }, + { + "id": "basic_health_care_college_silkeborg", + "label": "Basic Health Care College Silkeborg" + }, + { + "id": "bates_college", + "label": "Bates College" + }, + { + "id": "baylor_college_of_medicine", + "label": "Baylor College of Medicine" + }, + { + "id": "baylor_university", + "label": "Baylor University" + }, + { + "id": "bbfc", + "label": "BBFC" + }, + { + "id": "bfh_berner_fachhochschule", + "label": "BFH - Berner Fachhochschule" + }, + { + "id": "blekinge_tekniska_hogskola", + "label": "Blekinge Tekniska Högskola" + }, + { + "id": "boise_state_university", + "label": "Boise State University" + }, + { + "id": "boston_college", + "label": "Boston College" + }, + { + "id": "boston_university", + "label": "Boston University" + }, + { + "id": "brandeis_university", + "label": "Brandeis University" + }, + { + "id": "brookhaven_national_laboratory", + "label": "Brookhaven National Laboratory" + }, + { + "id": "brown_university", + "label": "Brown University" + }, + { + "id": "business_academy_aarhus", + "label": "Business Academy Aarhus" + }, + { + "id": "business_academy_southwest_easv", + "label": "Business Academy SouthWest (EASV)" + }, + { + "id": "california_institute_of_technology", + "label": "California Institute of Technology" + }, + { + "id": "california_state_polytechnic_university_pomona", + "label": "California State Polytechnic University, Pomona" + }, + { + "id": "california_state_university_fresno", + "label": "California State University, Fresno" + }, + { + "id": "california_state_university_fullerton", + "label": "California State University, Fullerton" + }, + { + "id": "california_state_university_san_bernardino", + "label": "California State University, San Bernardino" + }, + { + "id": "cardiff_university", + "label": "Cardiff University" + }, + { + "id": "carleton_college", + "label": "Carleton College" + }, + { + "id": "carnegie_mellon_university", + "label": "Carnegie Mellon University" + }, + { + "id": "case_western_reserve_university", + "label": "Case Western Reserve University" + }, + { + "id": "cern", + "label": "CERN" + }, + { + "id": "clemson_university", + "label": "Clemson University" + }, + { + "id": "cnr_institute_of_informatics_and_telematics", + "label": "CNR Institute of Informatics and Telematics" + }, + { + "id": "coleg_sir_gar", + "label": "Coleg Sir Gar" + }, + { + "id": "colorado_school_of_mines", + "label": "Colorado School of Mines" + }, + { + "id": "colorado_state_university", + "label": "Colorado State University" + }, + { + "id": "columbia_university", + "label": "Columbia University" + }, + { + "id": "computecanada", + "label": "Compute Canada" + }, + { + "id": "copenhagen_business_school", + "label": "Copenhagen Business School" + }, + { + "id": "copenhagen_hospitality_college", + "label": "Copenhagen Hospitality College" + }, + { + "id": "copenhagen_school_of_marine_engineering_and_technology_management", + "label": "Copenhagen School of Marine Engineering and Technology Management" + }, + { + "id": "cornell_university", + "label": "Cornell University" + }, + { + "id": "cphbusiness", + "label": "Cphbusiness" + }, + { + "id": "dania_danish_academy_of_business_and_technology", + "label": "Dania – Danish Academy of Business and Technology" + }, + { + "id": "danish_defence_library", + "label": "Danish Defence Library" + }, + { + "id": "danish_research_centre_for_magnetic_resonance", + "label": "Danish Research Centre for Magnetic Resonance" + }, + { + "id": "danish_school_of_media_and_journalism", + "label": "Danish School of Media and Journalism" + }, + { + "id": "democritus_university_of_thrace", + "label": "Democritus University of Thrace" + }, + { + "id": "design_school_kolding", + "label": "Design School Kolding" + }, + { + "id": "dfn_verein_deutsches_forschungsnetz", + "label": "DFN-Verein - Deutsches Forschungsnetz" + }, + { + "id": "dronninglund_gymnasium", + "label": "Dronninglund Gymnasium" + }, + { + "id": "dublin_business_school", + "label": "Dublin Business School" + }, + { + "id": "dublin_institute_of_technology", + "label": "Dublin Institute of Technology" + }, + { + "id": "duke_university", + "label": "Duke University" + }, + { + "id": "ehb_iffp_iuffp_das_eidgenossische_hochschulinstitut_fur_berufsbildung", + "label": "EHB / IFFP / IUFFP - Das eidgenössische Hochschulinstitut für Berufsbildung" + }, + { + "id": "epfl_epf_lausanne", + "label": "EPFL - EPF Lausanne" + }, + { + "id": "erhvervsakademi_midtvest", + "label": "Erhvervsakademi MidtVest" + }, + { + "id": "esnet", + "label": "ESnet" + }, + { + "id": "ethz_eth_zurich", + "label": "ETHZ - ETH Zürich" + }, + { + "id": "euc_nord", + "label": "EUC Nord" + }, + { + "id": "eupathdb", + "label": "EuPathDB" + }, + { + "id": "euresearch_head_office", + "label": "Euresearch Head Office" + }, + { + "id": "fachhochschule_karnten", + "label": "Fachhochschule Kärnten" + }, + { + "id": "fachhochschule_vorarlberg", + "label": "Fachhochschule Vorarlberg" + }, + { + "id": "feide", + "label": "Feide" + }, + { + "id": "fermi_national_accelerator_laboratory", + "label": "Fermi National Accelerator Laboratory" + }, + { + "id": "fh_joanneum", + "label": "FH Joanneum" + }, + { + "id": "fhnw_fachhochschule_nordwestschweiz", + "label": "FHNW - Fachhochschule Nordwestschweiz" + }, + { + "id": "fhs_st_gallen", + "label": "FHS St. Gallen" + }, + { + "id": "fh_wiener_neustadt", + "label": "FH Wiener Neustadt" + }, + { + "id": "florida_atlantic_university", + "label": "Florida Atlantic University" + }, + { + "id": "florida_international_university", + "label": "Florida International University" + }, + { + "id": "fredericia_maskinmesterskole", + "label": "Fredericia Maskinmesterskole" + }, + { + "id": "frederikshavn_upper_secondary_school_and_hf_course", + "label": "Frederikshavn upper secondary school and HF-Course" + }, + { + "id": "frederikssund_gymnasium", + "label": "Frederikssund Gymnasium" + }, + { + "id": "ftl_facolta_di_teologia_di_lugano", + "label": "FTL - Facoltà di Teologia di Lugano" + }, + { + "id": "george_mason_university", + "label": "George Mason University" + }, + { + "id": "georgetown_university", + "label": "Georgetown University" + }, + { + "id": "georgia_institute_of_technology", + "label": "Georgia Institute of Technology" + }, + { + "id": "georgia_state_university", + "label": "Georgia State University" + }, + { + "id": "gesellschaft_fur_wissenschaftliche_datenverarbeitung_mbh", + "label": "Gesellschaft für wissenschaftliche Datenverarbeitung mbH" + }, + { + "id": "gettysburg_college", + "label": "Gettysburg College" + }, + { + "id": "globusid", + "label": "Globus ID" + }, + { + "id": "google", + "label": "Google" + }, + { + "id": "goucher_college", + "label": "Goucher College" + }, + { + "id": "gpn_great_plains_network", + "label": "GPN (Great Plains Network)" + }, + { + "id": "graz_university_of_technology", + "label": "Graz University of Technology" + }, + { + "id": "greek_research_and_technology_network", + "label": "Greek Research and Technology Network" + }, + { + "id": "grenaa_gymnasium", + "label": "Grenaa Gymnasium" + }, + { + "id": "harvey_mudd_college", + "label": "Harvey Mudd College" + }, + { + "id": "haverford_college", + "label": "Haverford College" + }, + { + "id": "heanet", + "label": "HEAnet" + }, + { + "id": "hep_bejune_padagogische_hochschule_bejune", + "label": "HEP-BEJUNE – Pädagogische Hochschule - BEJUNE" + }, + { + "id": "hep_ph_fr_university_of_teacher_education_fribourg", + "label": "HEP-PH FR - University of Teacher Education Fribourg" + }, + { + "id": "hep_vaud_haute_ecole_pedagogique_du_canton_de_vaud", + "label": "HEP Vaud - Haute école pédagogique du canton de Vaud" + }, + { + "id": "hes_so_uas_western_switzerland", + "label": "HES-SO : UAS Western Switzerland" + }, + { + "id": "hochschule_osnabruck", + "label": "Hochschule Osnabrück" + }, + { + "id": "hogskolan_kristianstad", + "label": "Högskolan Kristianstad" + }, + { + "id": "hslu_hochschule_luzern", + "label": "HSLU - Hochschule Luzern" + }, + { + "id": "hsr_hochschule_fur_technik_rapperswil", + "label": "HSR - Hochschule für Technik Rapperswil" + }, + { + "id": "htw_chur_hochschule_fur_technik_und_wirtschaft", + "label": "HTW Chur - Hochschule für Technik und Wirtschaft" + }, + { + "id": "ian_a_young", + "label": "Ian A. Young" + }, + { + "id": "iba_international_business_academy", + "label": "IBA International Business Academy" + }, + { + "id": "iccu_central_institute_for_the_union_catalogue", + "label": "ICCU - Central Institute for the Union Catalogue" + }, + { + "id": "icer_mali", + "label": "ICER - Mali" + }, + { + "id": "icer_uganda", + "label": "ICER - Uganda" + }, + { + "id": "idiap_research_institute", + "label": "Idiap Research Institute" + }, + { + "id": "indiana_university", + "label": "Indiana University" + }, + { + "id": "indiana_university_of_pennsylvania", + "label": "Indiana University of Pennsylvania" + }, + { + "id": "infn_istituto_nazionale_di_fisica_nucleare", + "label": "INFN - Istituto Nazionale di Fisica Nucleare" + }, + { + "id": "insel_gruppe", + "label": "Insel Gruppe" + }, + { + "id": "institute_of_science_and_technology_austria", + "label": "Institute of Science and Technology Austria" + }, + { + "id": "institut_fur_hohere_studien_ihs", + "label": "Institut für Höhere Studien (IHS)" + }, + { + "id": "international_business_college", + "label": "International Business College" + }, + { + "id": "internet2", + "label": "Internet2" + }, + { + "id": "iowa_state_university", + "label": "Iowa State University" + }, + { + "id": "irccs_cro_di_aviano", + "label": "IRCCS CRO di Aviano" + }, + { + "id": "istat_istituto_nazionale_di_statistica", + "label": "ISTAT - Istituto Nazionale di Statistica" + }, + { + "id": "istituto_nazionale_di_astrofisica_inaf", + "label": "Istituto Nazionale di Astrofisica - INAF" + }, + { + "id": "it_department_of_the_ministry_of_higher_education", + "label": "IT Department of the Ministry of Higher Education" + }, + { + "id": "its_it_support_centre", + "label": "ITS (IT Support Centre)" + }, + { + "id": "it_university_of_copenhagen", + "label": "IT University of Copenhagen" + }, + { + "id": "izs_sicilia", + "label": "IZS Sicilia" + }, + { + "id": "johannes_kepler_universitat_linz", + "label": "Johannes Kepler Universität Linz" + }, + { + "id": "johns_hopkins", + "label": "Johns Hopkins" + }, + { + "id": "kansas_state_university", + "label": "Kansas State University" + }, + { + "id": "kaunas_university_of_technology", + "label": "Kaunas University of Technology" + }, + { + "id": "kea_copenhagen_school_of_design_and_technology", + "label": "KEA – Copenhagen School of Design and Technology" + }, + { + "id": "kielce_university_of_technology", + "label": "Kielce University of Technology" + }, + { + "id": "koebenhavn_nord", + "label": "Koebenhavn Nord" + }, + { + "id": "korea_institute_of_science_and_technology_information", + "label": "Korea Institute of Science and Technology Information" + }, + { + "id": "lafayette_college", + "label": "Lafayette College" + }, + { + "id": "lamar_university", + "label": "Lamar University" + }, + { + "id": "lawrence_berkeley_national_laboratory", + "label": "Lawrence Berkeley National Laboratory" + }, + { + "id": "lehigh_university", + "label": "Lehigh University" + }, + { + "id": "leibniz_rechenzentrum_der_bayerischen_akademie_der_wissenschaften", + "label": "Leibniz-Rechenzentrum der Bayerischen Akademie der Wissenschaften" + }, + { + "id": "ligo_scientific_collaboration", + "label": "LIGO Scientific Collaboration" + }, + { + "id": "lillebaelt_academy", + "label": "Lillebaelt Academy" + }, + { + "id": "linkopings_universitet", + "label": "Linköpings Universitet" + }, + { + "id": "lodz_university_of_technology", + "label": "Lodz University of Technology" + }, + { + "id": "louisiana_state_university", + "label": "Louisiana State University" + }, + { + "id": "loyola_university_of_chicago", + "label": "Loyola University of Chicago" + }, + { + "id": "ludwig_maximilians_universitat_munchen", + "label": "Ludwig-Maximilians-Universität München" + }, + { + "id": "lunds_universitet", + "label": "Lunds universitet" + }, + { + "id": "malmo_hogskola", + "label": "Malmö högskola" + }, + { + "id": "marine_biological_laboratory", + "label": "Marine Biological Laboratory" + }, + { + "id": "marselisborg_gymnasium", + "label": "Marselisborg Gymnasium" + }, + { + "id": "marshall_university", + "label": "Marshall University" + }, + { + "id": "massachusetts_institute_of_technology", + "label": "Massachusetts Institute of Technology" + }, + { + "id": "mcnc", + "label": "MCNC" + }, + { + "id": "medical_university_of_south_carolina", + "label": "Medical University of South Carolina" + }, + { + "id": "metropolitan_university_college", + "label": "Metropolitan University College" + }, + { + "id": "michigan_state_university", + "label": "Michigan State University" + }, + { + "id": "mississippi_state_university", + "label": "Mississippi State University" + }, + { + "id": "montana_state_university_bozeman", + "label": "Montana State University - Bozeman" + }, + { + "id": "moss_landing_marine_laboratories", + "label": "Moss Landing Marine Laboratories" + }, + { + "id": "national_institutes_of_health", + "label": "National Institutes of Health" + }, + { + "id": "naval_postgraduate_school", + "label": "Naval Postgraduate School" + }, + { + "id": "rda", + "label": "NCAR RDA" + }, + { + "id": "ncsa", + "label": "NCSA" + }, + { + "id": "nersc", + "label": "NERSC" + }, + { + "id": "new_york_university", + "label": "New York University" + }, + { + "id": "nicolaus_copernicus_university_in_torun", + "label": "Nicolaus Copernicus University in Torun" + }, + { + "id": "nikhef", + "label": "Nikhef" + }, + { + "id": "north_carolina_state_university", + "label": "North Carolina State University" + }, + { + "id": "northern_illinois_university", + "label": "Northern Illinois University" + }, + { + "id": "northwestern_university", + "label": "Northwestern University" + }, + { + "id": "ntb_hochschule_fur_technik_buchs", + "label": "NTB - Hochschule für Technik Buchs" + }, + { + "id": "oak_ridge_national_laboratory", + "label": "Oak Ridge National Laboratory" + }, + { + "id": "ohio_state_university", + "label": "Ohio State University" + }, + { + "id": "ohio_technology_consortium_oh_tech", + "label": "Ohio Technology Consortium (OH-TECH)" + }, + { + "id": "ohio_university_main_campus", + "label": "Ohio University Main Campus" + }, + { + "id": "oklahoma_state_university_system", + "label": "Oklahoma State University System" + }, + { + "id": "old_dominion_university", + "label": "Old Dominion University" + }, + { + "id": "opole_university", + "label": "Opole University" + }, + { + "id": "orcid", + "label": "ORCID" + }, + { + "id": "oregon_state_university", + "label": "Oregon State University" + }, + { + "id": "paderup_gymnasium", + "label": "Paderup Gymnasium" + }, + { + "id": "penn_state", + "label": "Penn State" + }, + { + "id": "pharmakon", + "label": "Pharmakon" + }, + { + "id": "phgr_padagogische_hochschule_graubunden", + "label": "PHGR - Pädagogische Hochschule Graubünden" + }, + { + "id": "phlu_padagogische_hochschule_luzern", + "label": "PHLU - Pädagogische Hochschule Luzern" + }, + { + "id": "phsg_padagogische_hochschule_st_gallen", + "label": "PHSG - Pädagogische Hochschule St.Gallen" + }, + { + "id": "phtg_padagogische_hochschule_thurgau", + "label": "PHTG - Pädagogische Hochschule Thurgau" + }, + { + "id": "phvs_padagogische_hochschule_wallis", + "label": "PHVS - Pädagogische Hochschule Wallis" + }, + { + "id": "ph_zug_padagogische_hochschule_zug", + "label": "PH Zug - Pädagogische Hochschule Zug" + }, + { + "id": "ph_zurich_padagogische_hochschule_zurich", + "label": "PH Zürich - Pädagogische Hochschule Zürich" + }, + { + "id": "pmod_wrc_observatorium_davos", + "label": "PMOD/WRC - Observatorium Davos" + }, + { + "id": "pomona_college", + "label": "Pomona College" + }, + { + "id": "portland_state_university", + "label": "Portland State University" + }, + { + "id": "princeton_university", + "label": "Princeton University" + }, + { + "id": "protectnetwork", + "label": "ProtectNetwork" + }, + { + "id": "psi_paul_scherrer_institut", + "label": "PSI - Paul Scherrer Institut" + }, + { + "id": "purdue_university_main_campus", + "label": "Purdue University Main Campus" + }, + { + "id": "reed_college", + "label": "Reed College" + }, + { + "id": "region_zealand", + "label": "Region Zealand" + }, + { + "id": "rice_university", + "label": "Rice University" + }, + { + "id": "rockefeller_university", + "label": "Rockefeller University" + }, + { + "id": "rosborg_gymnasium_hf", + "label": "Rosborg Gymnasium & HF" + }, + { + "id": "roskilde_university", + "label": "Roskilde University" + }, + { + "id": "royal_academy_of_music_aarhus_aalborg_rama", + "label": "Royal Academy of Music Aarhus/Aalborg (RAMA)" + }, + { + "id": "royal_college_of_physicians_of_ireland", + "label": "Royal College of Physicians of Ireland" + }, + { + "id": "rungsted_high_school", + "label": "Rungsted High School" + }, + { + "id": "rutgers_the_state_university_of_new_jersey", + "label": "Rutgers, The State University of New Jersey" + }, + { + "id": "san_diego_state_university", + "label": "San Diego State University" + }, + { + "id": "schools_of_architecture_design_and_conservation", + "label": "Schools of Architecture, Design and Conservation" + }, + { + "id": "second_university_of_naplesi", + "label": "Second University of Naplesi" + }, + { + "id": "silkeborg_business_college", + "label": "Silkeborg Business College" + }, + { + "id": "simac", + "label": "SIMAC" + }, + { + "id": "sissa", + "label": "SISSA" + }, + { + "id": "smithsonian_institution", + "label": "Smithsonian Institution" + }, + { + "id": "southern_illinois_university", + "label": "Southern Illinois University" + }, + { + "id": "southern_methodist_university", + "label": "Southern Methodist University" + }, + { + "id": "sscol_soprintendenza_speciale_per_il_colosseo", + "label": "SSCOL - Soprintendenza Speciale per il Colosseo" + }, + { + "id": "stanford_university", + "label": "Stanford University" + }, + { + "id": "state_and_university_library_employees", + "label": "State and University Library - employees" + }, + { + "id": "statens_museum_for_kunst_smk", + "label": "Statens Museum for Kunst – SMK" + }, + { + "id": "stevens_institute_of_technology", + "label": "Stevens Institute of Technology" + }, + { + "id": "stockholms_universitet", + "label": "Stockholms universitet" + }, + { + "id": "stony_brook_university", + "label": "Stony Brook University" + }, + { + "id": "switch", + "label": "SWITCH" + }, + { + "id": "syddansk_erhvervsskole", + "label": "Syddansk Erhvervsskole" + }, + { + "id": "syracuse_university", + "label": "Syracuse University" + }, + { + "id": "technical_university_of_denmark", + "label": "Technical University of Denmark" + }, + { + "id": "technische_universitat_wien", + "label": "Technische Universität Wien" + }, + { + "id": "texas_a_m_university", + "label": "Texas A & M University" + }, + { + "id": "texas_a_m_university_corpus_christi", + "label": "Texas A&M University-Corpus Christi" + }, + { + "id": "texas_state_university_san_marcos", + "label": "Texas State University - San Marcos" + }, + { + "id": "texas_tech_university", + "label": "Texas Tech University" + }, + { + "id": "the_broad_institute_of_mit_and_harvard", + "label": "The Broad Institute of MIT and Harvard" + }, + { + "id": "the_christian_gymnasium", + "label": "The Christian Gymnasium" + }, + { + "id": "the_george_washington_university", + "label": "The George Washington University" + }, + { + "id": "the_state_university_of_new_york_at_buffalo", + "label": "The State University of New York at Buffalo" + }, + { + "id": "the_university_of_arizona", + "label": "The University of Arizona" + }, + { + "id": "the_university_of_memphis", + "label": "The University of Memphis" + }, + { + "id": "towson_university", + "label": "Towson University" + }, + { + "id": "tufts_university", + "label": "Tufts University" + }, + { + "id": "united_id", + "label": "United ID" + }, + { + "id": "universita_degli_studi_di_perugia", + "label": "Università degli studi di Perugia" + }, + { + "id": "universita_di_modena_e_reggio_emilia", + "label": "Università di Modena e Reggio Emilia" + }, + { + "id": "universita_di_trieste", + "label": "Università di Trieste" + }, + { + "id": "universita_di_urbino", + "label": "Università di Urbino" + }, + { + "id": "universita_politecnica_delle_marche", + "label": "Universita Politecnica delle Marche" + }, + { + "id": "universitare_fernstudien_schweiz", + "label": "Universitäre Fernstudien Schweiz" + }, + { + "id": "universitat_basel", + "label": "Universität Basel" + }, + { + "id": "universitat_bern", + "label": "Universität Bern" + }, + { + "id": "universitat_freiburg", + "label": "Universität Freiburg" + }, + { + "id": "universitat_genf", + "label": "Universität Genf" + }, + { + "id": "universitat_liechtenstein", + "label": "Universität Liechtenstein" + }, + { + "id": "universitat_luzern", + "label": "Universität Luzern" + }, + { + "id": "universitat_st_gallen", + "label": "Universität St. Gallen" + }, + { + "id": "universitat_zurich", + "label": "Universität Zürich" + }, + { + "id": "universite_de_lausanne", + "label": "Université de Lausanne" + }, + { + "id": "universite_de_neuchatel", + "label": "Université de Neuchâtel" + }, + { + "id": "university_at_albany_state_university_of_new_york", + "label": "University At Albany, State University of New York" + }, + { + "id": "university_college_capital", + "label": "University College Capital" + }, + { + "id": "university_college_cork", + "label": "University College Cork" + }, + { + "id": "university_college_dublin", + "label": "University College Dublin" + }, + { + "id": "university_college_lillebaelt", + "label": "University College Lillebaelt" + }, + { + "id": "university_college_of_northern_denmark", + "label": "University College of Northern Denmark" + }, + { + "id": "university_college_of_teacher_education_in_lower_austria", + "label": "University College of Teacher Education in Lower Austria" + }, + { + "id": "university_college_of_teacher_education_styria", + "label": "University College of Teacher Education Styria" + }, + { + "id": "university_college_south_denmark", + "label": "University College South Denmark" + }, + { + "id": "university_college_zealand", + "label": "University College Zealand" + }, + { + "id": "university_of_alabama_at_birmingham", + "label": "University of Alabama at Birmingham" + }, + { + "id": "university_of_alabama_the", + "label": "University of Alabama, The" + }, + { + "id": "university_of_alaska_statewide_system", + "label": "University of Alaska Statewide System" + }, + { + "id": "university_of_arkansas", + "label": "University of Arkansas" + }, + { + "id": "university_of_california_berkeley", + "label": "University of California, Berkeley" + }, + { + "id": "university_of_california_davis", + "label": "University of California, Davis" + }, + { + "id": "university_of_california_irvine", + "label": "University of California-Irvine" + }, + { + "id": "university_of_california_los_angeles", + "label": "University of California-Los Angeles" + }, + { + "id": "university_of_california_office_of_the_president", + "label": "University of California - Office of the President" + }, + { + "id": "university_of_california_riverside", + "label": "University of California, Riverside" + }, + { + "id": "university_of_california_san_diego", + "label": "University of California-San Diego" + }, + { + "id": "university_of_california_san_francisco", + "label": "University of California, San Francisco" + }, + { + "id": "university_of_california_santa_barbara", + "label": "University of California-Santa Barbara" + }, + { + "id": "university_of_california_santa_cruz", + "label": "University of California, Santa Cruz" + }, + { + "id": "university_of_central_florida", + "label": "University of Central Florida" + }, + { + "id": "uchicago", + "label": "University of Chicago" + }, + { + "id": "university_of_cincinnati_main_campus", + "label": "University of Cincinnati Main Campus" + }, + { + "id": "university_of_colorado_at_boulder", + "label": "University of Colorado at Boulder" + }, + { + "id": "university_of_copenhagen", + "label": "University of Copenhagen" + }, + { + "id": "university_of_dayton", + "label": "University of Dayton" + }, + { + "id": "university_of_delaware", + "label": "University of Delaware" + }, + { + "id": "exeter", + "label": "University of Exeter" + }, + { + "id": "university_of_florida", + "label": "University of Florida" + }, + { + "id": "university_of_glasgow", + "label": "University of Glasgow" + }, + { + "id": "university_of_hawaii", + "label": "University of Hawaii" + }, + { + "id": "university_of_helsinki", + "label": "University of Helsinki" + }, + { + "id": "university_of_houston_libraries", + "label": "University of Houston Libraries" + }, + { + "id": "university_of_iceland", + "label": "University of Iceland" + }, + { + "id": "university_of_illinois_at_chicago", + "label": "University of Illinois at Chicago" + }, + { + "id": "university_of_illinois_at_springfield", + "label": "University of Illinois At Springfield" + }, + { + "id": "university_of_illinois_at_urbana_champaign", + "label": "University of Illinois at Urbana-Champaign" + }, + { + "id": "university_of_iowa", + "label": "University of Iowa" + }, + { + "id": "university_of_kansas", + "label": "University of Kansas" + }, + { + "id": "university_of_kansas_medical_center", + "label": "University of Kansas Medical Center" + }, + { + "id": "university_of_maryland_baltimore", + "label": "University of Maryland Baltimore" + }, + { + "id": "university_of_maryland_baltimore_county", + "label": "University of Maryland Baltimore County" + }, + { + "id": "university_of_maryland_college_park", + "label": "University of Maryland College Park" + }, + { + "id": "university_of_massachusetts_amherst", + "label": "University of Massachusetts Amherst" + }, + { + "id": "university_of_miami", + "label": "University of Miami" + }, + { + "id": "university_of_michigan", + "label": "University of Michigan" + }, + { + "id": "university_of_minnesota", + "label": "University of Minnesota" + }, + { + "id": "university_of_mississippi", + "label": "University of Mississippi" + }, + { + "id": "university_of_missouri_system", + "label": "University of Missouri System" + }, + { + "id": "university_of_nebraska_lincoln", + "label": "University of Nebraska-Lincoln" + }, + { + "id": "university_of_nebraska_medical_center", + "label": "University of Nebraska Medical Center" + }, + { + "id": "university_of_nevada_reno", + "label": "University of Nevada, Reno" + }, + { + "id": "university_of_new_mexico", + "label": "University of New Mexico" + }, + { + "id": "university_of_north_carolina_at_chapel_hill", + "label": "University of North Carolina at Chapel Hill" + }, + { + "id": "university_of_north_carolina_at_charlotte", + "label": "University of North Carolina At Charlotte" + }, + { + "id": "university_of_north_carolina_at_greensboro", + "label": "University of North Carolina at Greensboro" + }, + { + "id": "university_of_notre_dame", + "label": "University of Notre Dame" + }, + { + "id": "university_of_oklahoma", + "label": "University of Oklahoma" + }, + { + "id": "university_of_oregon", + "label": "University of Oregon" + }, + { + "id": "university_of_padova", + "label": "University of Padova" + }, + { + "id": "university_of_pennsylvania", + "label": "University of Pennsylvania" + }, + { + "id": "university_of_pittsburgh", + "label": "University of Pittsburgh" + }, + { + "id": "university_of_rochester", + "label": "University of Rochester" + }, + { + "id": "university_of_science_and_technology_in_bydgoszcz", + "label": "University of Science and Technology in Bydgoszcz" + }, + { + "id": "university_of_south_carolina", + "label": "University of South Carolina" + }, + { + "id": "university_of_south_dakota", + "label": "University of South Dakota" + }, + { + "id": "university_of_southern_california", + "label": "University of Southern California" + }, + { + "id": "university_of_southern_denmark", + "label": "University of Southern Denmark" + }, + { + "id": "university_of_south_florida", + "label": "University of South Florida" + }, + { + "id": "university_of_texas_at_austin", + "label": "University of Texas at Austin" + }, + { + "id": "university_of_texas_at_dallas", + "label": "University of Texas at Dallas" + }, + { + "id": "university_of_texas_m_d_anderson_cancer_center", + "label": "University of Texas M.D. Anderson Cancer Center" + }, + { + "id": "university_of_utah", + "label": "University of Utah" + }, + { + "id": "university_of_vermont", + "label": "University of Vermont" + }, + { + "id": "university_of_virginia", + "label": "University of Virginia" + }, + { + "id": "university_of_washington", + "label": "University of Washington" + }, + { + "id": "university_of_west_florida", + "label": "University of West Florida" + }, + { + "id": "university_of_wisconsin_madison", + "label": "University of Wisconsin-Madison" + }, + { + "id": "university_of_wisconsin_milwaukee", + "label": "University of Wisconsin-Milwaukee" + }, + { + "id": "university_of_wyoming", + "label": "University of Wyoming" + }, + { + "id": "uppsala_universitet", + "label": "Uppsala universitet" + }, + { + "id": "utah_state_university", + "label": "Utah State University" + }, + { + "id": "utah_valley_university", + "label": "Utah Valley University" + }, + { + "id": "vanderbilt_university", + "label": "Vanderbilt University" + }, + { + "id": "veterinarmedizinische_universitat_wien", + "label": "Veterinärmedizinische Universität Wien" + }, + { + "id": "via_university_college", + "label": "VIA University College" + }, + { + "id": "virginia_polytechnic_institute_and_state_university", + "label": "Virginia Polytechnic Institute and State University" + }, + { + "id": "vordingborg_gymnasium_and_higher_prep_exam", + "label": "Vordingborg Gymnasium and Higher Prep Exam" + }, + { + "id": "wayf_orphanage", + "label": "WAYF Orphanage" + }, + { + "id": "wayne_state_university", + "label": "Wayne State University" + }, + { + "id": "weill_cornell_medical_college", + "label": "Weill Cornell Medical College" + }, + { + "id": "western_michigan_university", + "label": "Western Michigan University" + }, + { + "id": "westgrid", + "label": "WestGrid" + }, + { + "id": "west_virginia_university", + "label": "West Virginia University" + }, + { + "id": "wheaton_college_ma", + "label": "Wheaton College (MA)" + }, + { + "id": "woods_hole_oceanographic_institution", + "label": "Woods Hole Oceanographic Institution" + }, + { + "id": "wsl_eidg_forschungsanstalt_fur_wald_schnee_und_landschaft", + "label": "WSL - Eidg. Forschungsanstalt für Wald, Schnee und Landschaft" + }, + { + "id": "xsede", + "label": "XSEDE" + }, + { + "id": "yale_university", + "label": "Yale University" + }, + { + "id": "zealand_business_college", + "label": "Zealand Business College" + }, + { + "id": "zentral_und_hochschulbibliothek_luzern", + "label": "Zentral- und Hochschulbibliothek Luzern" + }, + { + "id": "zhaw_zurcher_hochschule_fur_angewandte_wissenschaften", + "label": "ZHAW - Zürcher Hochschule für Angewandte Wissenschaften" + } +] diff --git a/vite-app/src/apps/Auth2/resources/data/institutions.csv b/vite-app/src/apps/Auth2/resources/data/institutions.csv new file mode 100644 index 000000000..67ede2fb1 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/institutions.csv @@ -0,0 +1,4666 @@ +UNITID,NAME,CITY,STABBR +177834,A T Still University of Health Sciences,Kirksville,MO +180203,Aaniiih Nakoda College,Harlem,MT +222178,Abilene Christian University,Abilene,TX +138558,Abraham Baldwin Agricultural College,Tifton,GA +172866,Academy College,Minneapolis,MN +451079,Academy for Five Element Acupuncture,Gainesville,FL +457271,Academy for Jewish Religion-California,Los Angeles,CA +412173,Academy for Nursing and Health Occupations,West Palm Beach,FL +108232,Academy of Art University,San Francisco,CA +108269,Academy of Chinese Culture and Health Sciences,Oakland,CA +475635,Academy of Couture Art,Beverly Hills,CA +449454,Academy of Natural Therapy Inc,Greeley,CO +384306,Acupuncture and Integrative Medicine College-Berkeley,Berkeley,CA +439969,Acupuncture and Massage College,Miami,FL +126182,Adams State University,Alamosa,CO +188429,Adelphi University,Garden City,NY +188438,Adirondack Community College,Queensbury,NY +374024,Adler Graduate School,Richfield,MN +142832,Adler University,Chicago,IL +168528,Adrian College,Adrian,MI +444343,Advanced College,South Gate,CA +481234,Advanced Computing Institute,Los Angeles,CA +231411,Advanced Technology Institute,Virginia Beach,VA +444361,Advanced Training Associates,El Cajon,CA +133872,Adventist University of Health Sciences,Orlando,FL +205391,Advertising Art Educational Services DBA School of Advertising Art,Kettering,OH +138600,Agnes Scott College,Decatur,GA +134811,AI Miami International University of Art and Design,Miami,FL +152822,AIB College of Business,Des Moines,IA +217615,Aiken Technical College,Graniteville,SC +126207,Aims Community College,Greeley,CO +200697,Air Force Institute of Technology-Graduate School of Engineering & Management,Wright-Patterson AFB,OH +200785,Akron Institute of Herzing University,Akron,OH +100654,Alabama A & M University,Normal,AL +101949,Alabama Southern Community College,Monroeville,AL +100724,Alabama State University,Montgomery,AL +199786,Alamance Community College,Graham,NC +102580,Alaska Bible College,Palmer,AK +103501,Alaska Career College,Anchorage,AK +442523,Alaska Christian College,Soldotna,AK +102669,Alaska Pacific University,Anchorage,AK +188526,Albany College of Pharmacy and Health Sciences,Albany,NY +188535,Albany Law School,Albany,NY +188580,Albany Medical College,Albany,NY +138716,Albany State University,Albany,GA +138682,Albany Technical College,Albany,GA +128498,Albertus Magnus College,New Haven,CT +168546,Albion College,Albion,MI +210571,Albright College,Reading,PA +175342,Alcorn State University,Alcorn State,MS +237118,Alderson Broaddus University,Philippi,WV +172918,Alexandria Technical & Community College,Alexandria,MN +188641,Alfred University,Alfred,NY +156189,Alice Lloyd College,Pippa Passes,KY +108807,Allan Hancock College,Santa Maria,CA +161688,Allegany College of Maryland,Cumberland,MD +210669,Allegheny College,Meadville,PA +200873,Allegheny Wesleyan College,Salem,OH +152798,Allen College,Waterloo,IA +154642,Allen County Community College,Iola,KS +217624,Allen University,Columbia,SC +110468,Alliant International University-San Diego,San Diego,CA +460729,Allied American University,Laguna Hills,CA +168591,Alma College,Alma,MI +168607,Alpena Community College,Alpena,MI +210775,Alvernia University,Reading,PA +238193,Alverno College,Milwaukee,WI +222567,Alvin Community College,Alvin,TX +222576,Amarillo College,Amarillo,TX +222628,Amberton University,Garland,TX +457527,Ambria College of Nursing,Hoffman Estates,IL +188687,American Academy McAllister Institute of Funeral Service,New York,NY +446002,American Academy of Acupuncture and Oriental Medicine,Roseville,MN +142887,American Academy of Art,Chicago,IL +108852,American Academy of Dramatic Arts-Los Angeles,Los Angeles,CA +188678,American Academy of Dramatic Arts-New York,New York,NY +219505,American Baptist College,Nashville,TN +108861,American Baptist Seminary of the West,Berkeley,CA +457688,American Business and Technology University,St Joseph,MO +441052,American Career College-Anaheim,Anaheim,CA +109040,American Career College-Los Angeles,Los Angeles,CA +447768,American Career College-Ontario,Ontario,CA +461005,American College for Medical Careers,Orlando,FL +429085,American College of Acupuncture and Oriental Med,Houston,TX +449889,American College of Education,Indianapolis,IN +210809,American College of Financial Services,Bryn Mawr,PA +443599,American College of Healthcare Sciences,Portland,OR +430591,American College of Traditional Chinese Medicine,San Francisco,CA +109086,American Conservatory Theater,San Francisco,CA +108870,American Film Institute Conservatory,Los Angeles,CA +103787,American Indian College Inc,Phoenix,AZ +441636,American Institute of Alternative Medicine,Columbus,OH +438586,American InterContinental University-Atlanta,Atlanta,GA +445133,American InterContinental University-Houston,Houston,TX +445027,American InterContinental University-Online,Schaumburg,IL +438601,American InterContinental University-South Florida,Weston,FL +164447,American International College,Springfield,MA +116846,American Jewish University,Los Angeles,CA +475714,American Medical Academy,Miami,FL +188854,American Musical and Dramatic Academy,New York,NY +232797,American National University,Salem,VA +449339,American Public University System,Charles Town,WV +109208,American River College,Sacramento,CA +240736,American Samoa Community College,Pago Pago,AS +460738,American Sentinel University,Aurora,CO +131159,American University,Washington,DC +433004,American University of Health Sciences,Signal Hill,CA +241100,American University of Puerto Rico-Bayamon,Bayamon,PR +241128,American University of Puerto Rico-Manati,Manati,PR +447263,AmeriTech College-Draper,Draper,UT +164465,Amherst College,Amherst,MA +100690,Amridge University,Montgomery,AL +151865,Anabaptist Mennonite Biblical Seminary,Elkhart,IN +150048,Ancilla College,Donaldson,IN +150066,Anderson University-Anderson,Anderson,IN +217633,Anderson University-Anderson,Anderson,SC +164474,Andover Newton Theological School,Newton Centre,MA +138761,Andrew College,Cuthbert,GA +168740,Andrews University,Berrien Springs,MI +457299,Angeles College,Los Angeles,CA +222822,Angelina College,Lufkin,TX +222831,Angelo State University,San Angelo,TX +164492,Anna Maria College,Paxton,MA +161767,Anne Arundel Community College,Arnold,MD +172954,Anoka Technical College,Anoka,MN +172963,Anoka-Ramsey Community College,Coon Rapids,MN +109350,Antelope Valley College,Lancaster,CA +245838,Antioch University-Los Angeles,Culver City,CA +245892,Antioch University-Midwest,Yellow Springs,OH +245865,Antioch University-New England,Keene,NH +442392,Antioch University-PhD Program in Leadership and Change,Yellow Springs,OH +245847,Antioch University-Santa Barbara,Santa Barbara,CA +245883,Antioch University-Seattle,Seattle,WA +201016,Antonelli College-Cincinnati,Cincinnati,OH +383950,Antonelli College-Hattiesburg,Hattiesburg,MS +175528,Antonelli College-Jackson,Jackson,MS +210890,Antonelli Institute,Erdenheim,PA +429094,AOMA Graduate School of Integrative Medicine,Austin,TX +441511,Apex School of Theology,Durham,NC +237136,Appalachian Bible College,Mount Hope,WV +449922,Appalachian College of Pharmacy,Oakwood,VA +432348,Appalachian School of Law,Grundy,VA +197869,Appalachian State University,Boone,NC +168786,Aquinas College-Grand Rapids,Grand Rapids,MI +219578,Aquinas College-Nashville,Nashville,TN +176600,Aquinas Institute of Theology,Saint Louis,MO +126289,Arapahoe Community College,Littleton,CO +211088,Arcadia University,Glenside,PA +367936,Argosy University-Atlanta,Atlanta,GA +145770,Argosy University-Chicago,Chicago,IL +442222,Argosy University-Dallas,Farmers Branch,TX +448734,Argosy University-Denver,Denver,CO +366748,Argosy University-Hawaii,Honolulu,HI +450526,Argosy University-Inland Empire,Ontario,CA +447272,Argosy University-Los Angeles,Los Angeles,CA +450535,Argosy University-Nashville,Nashville,TN +436438,Argosy University-Orange County,Orange,CA +436094,Argosy University-Phoenix,Phoenix,AZ +456348,Argosy University-Phoenix Online Division,Phoenix,AZ +452090,Argosy University-Salt Lake City,Draper,UT +450544,Argosy University-San Diego,San Diego,CA +121983,Argosy University-San Francisco Bay Area,Alameda,CA +137148,Argosy University-Sarasota,Sarasota,FL +420866,Argosy University-Schaumburg,Schaumburg,IL +439057,Argosy University-Seattle,Seattle,WA +428268,Argosy University-Tampa,Tampa,FL +410502,Argosy University-The Art Institute of California-Hollywood,North Hollywood,CA +448576,Argosy University-The Art Institute of California-Inland Empire,San Bernardino,CA +432533,Argosy University-The Art Institute of California-Los Angeles,Santa Monica,CA +441973,Argosy University-The Art Institute of California-Orange County,Santa Ana,CA +450094,Argosy University-The Art Institute of California-Sacramento,Sacramento,CA +117113,Argosy University-The Art Institute of California-San Diego,San Diego,CA +117928,Argosy University-The Art Institute of California-San Francisco,San Francisco,CA +451848,Argosy University-The Art Institute of California-Silicon Valley,Sunnyvale,CA +173984,Argosy University-Twin Cities,Eagan,MN +419457,Argosy University-Washington DC,Arlington,VA +105899,Arizona Christian University,Phoenix,AZ +421708,Arizona College-Glendale,Glendale,AZ +482990,Arizona College-Mesa,Mesa,AZ +446039,Arizona School of Acupuncture and Oriental Medicine,Tucson,AZ +448886,Arizona State University-Downtown Phoenix,Phoenix,AZ +420574,Arizona State University-Polytechnic,Mesa,AZ +483124,Arizona State University-Skysong,Scottsdale,AZ +104151,Arizona State University-Tempe,Tempe,AZ +407009,Arizona State University-West,Glendale,AZ +450942,Arizona Summit Law School,Phoenix,AZ +104160,Arizona Western College,Yuma,AZ +106306,Arkansas Baptist College,Little Rock,AR +107327,Arkansas Northeastern College,Blytheville,AR +106449,Arkansas State University-Beebe,Beebe,AR +106458,Arkansas State University-Main Campus,Jonesboro,AR +107318,Arkansas State University-Mid-South,West Memphis,AR +420538,Arkansas State University-Mountain Home,Mountain Home,AR +440402,Arkansas State University-Newport,Newport,AR +106467,Arkansas Tech University,Russellville,AR +222877,Arlington Baptist College,Arlington,TX +138789,Armstrong State University,Savannah,GA +201061,Art Academy of Cincinnati,Cincinnati,OH +109651,Art Center College of Design,Pasadena,CA +404994,ASA College,Brooklyn,NY +156222,Asbury Theological Seminary,Wilmore,KY +156213,Asbury University,Wilmore,KY +461777,Ashdown College of Health Sciences,Redlands,CA +447777,Asher College,Sacramento,CA +197887,Asheville-Buncombe Technical Community College,Asheville,NC +154022,Ashford University,San Diego,CA +156231,Ashland Community and Technical College,Ashland,KY +201104,Ashland University,Ashland,OH +128577,Asnuntuck Community College,Enfield,CT +454829,Aspen University,Denver,CO +176619,Assemblies of God Theological Seminary,Springfield,MO +164562,Assumption College,Worcester,MA +183600,Assumption College for Sisters,Mendham,NJ +446127,ATA Career Education,Spring Hill,FL +447935,ATA College,Louisville,KY +440651,Atenas College,Manati,PR +201140,Athenaeum of Ohio,Cincinnati,OH +100812,Athens State University,Athens,AL +246813,Athens Technical College,Athens,GA +138901,Atlanta Metropolitan State College,Atlanta,GA +138840,Atlanta Technical College,Atlanta,GA +138929,Atlanta's John Marshall Law School,Atlanta,GA +183655,Atlantic Cape Community College,Mays Landing,NJ +439446,Atlantic Institute of Oriental Medicine,Fort Lauderdale,FL +241216,Atlantic University College,Guaynabo,PR +100858,Auburn University,Auburn University,AL +100830,Auburn University at Montgomery,Montgomery,AL +173045,Augsburg College,Minneapolis,MN +138956,Augusta Technical College,Augusta,GA +482149,Augusta University,Augusta,GA +143084,Augustana College-Rock Island,Rock Island,IL +219000,Augustana University,Sioux Falls,SD +201177,Aultman College of Nursing and Health Sciences,Canton,OH +143118,Aurora University,Aurora,IL +222983,Austin College,Sherman,TX +222992,Austin Community College District,Austin,TX +247825,Austin Graduate School of Theology,Austin,TX +219602,Austin Peay State University,Clarksville,TN +223001,Austin Presbyterian Theological Seminary,Austin,TX +442295,Ave Maria School of Law,Naples,FL +446048,Ave Maria University,Ave Maria,FL +231420,Averett University,Danville,VA +449931,Averett University-Non-Traditional Programs,Danville,VA +447847,Aviator College of Aeronautical Science and Technology,Fort Pierce,FL +176628,Avila University,Kansas City,MO +102711,AVTEC-Alaska's Institute of Technology,Seward,AK +483762,Azure College,Miami Gardens,FL +109785,Azusa Pacific University,Azusa,CA +474863,Azusa Pacific University College,Glendora,CA +164580,Babson College,Wellesley,MA +206817,Bacone College,Muskogee,OK +139010,Bainbridge State College,Bainbridge,GA +476601,Bais HaMedrash and Mesivta of Baltimore,Baltimore,MD +245777,Bais Medrash Elyon,Monsey,NY +449658,Bais Medrash Toras Chesed,Lakewood,NJ +168847,Baker College,Flint,MI +414708,Baker College Center for Graduate Studies,Flint,MI +444167,Baker College of Allen Park,Allen Park,MI +404073,Baker College of Auburn Hills,Auburn Hills,MI +404648,Baker College of Cadillac,Cadillac,MI +404082,Baker College of Clinton Township,Clinton Township,MI +414160,Baker College of Jackson,Jackson,MI +171298,Baker College of Muskegon,Muskegon,MI +168838,Baker College of Owosso,Owosso,MI +381617,Baker College of Port Huron,Port Huron,MI +154688,Baker University,Baldwin City,KS +109819,Bakersfield College,Bakersfield,CA +420705,Bakke Graduate University,Dallas,TX +201195,Baldwin Wallace University,Berea,OH +150136,Ball State University,Muncie,IN +161864,Baltimore City Community College,Baltimore,MD +189015,Bank Street College of Education,New York,NY +176664,Baptist Bible College,Springfield,MO +211024,Clarks Summit University,Clarks Summit,PA +223083,Baptist Health System School of Health Professions,San Antonio,TX +219639,Baptist Memorial College of Health Sciences,Memphis,TN +223117,Baptist Missionary Association Theological Seminary,Jacksonville,TX +366793,Baptist Theological Seminary at Richmond,Henrico,VA +444398,Baptist University of the Americas,San Antonio,TX +155070,Barclay College,Haviland,KS +189088,Bard College,Annandale-On-Hudson,NY +167792,Bard College at Simon's Rock,Great Barrington,MA +189097,Barnard College,New York,NY +177719,Barnes-Jewish College Goldfarb School of Nursing,Saint Louis,MO +132471,Barry University,Miami,FL +109907,Barstow Community College,Barstow,CA +197911,Barton College,Wilson,NC +154697,Barton County Community College,Great Bend,KS +235547,Bastyr University,Kenmore,WA +160977,Bates College,Lewiston,ME +235671,Bates Technical College,Tacoma,WA +437103,Baton Rouge Community College,Baton Rouge,LA +158343,Baton Rouge School of Computers,Baton Rouge,LA +139074,Bauder College,Atlanta,GA +168883,Bay de Noc Community College,Escanaba,MI +380359,Bay Mills Community College,Brimley,MI +164632,Bay Path University,Longmeadow,MA +164641,Bay State College,Boston,MA +223223,Baylor College of Medicine,Houston,TX +223232,Baylor University,Waco,TX +384254,Beacon College,Leesburg,FL +160995,Beal College,Bangor,ME +197966,Beaufort County Community College,Washington,NC +164720,Becker College,Worcester,MA +247065,Beckfield College-Florence,Florence,KY +452373,Beckfield College-Tri-County,Springdale,OH +476717,Be'er Yaakov Talmudic Seminary,Spring Valley,NY +444413,Beis Medrash Heichal Dovid,Far Rockaway,NY +190956,Belanger School of Nursing,Schenectady,NY +175421,Belhaven University,Jackson,MS +156286,Bellarmine University,Louisville,KY +234669,Bellevue College,Bellevue,WA +180814,Bellevue University,Bellevue,NE +238324,Bellin College,Green Bay,WI +234696,Bellingham Technical College,Bellingham,WA +197984,Belmont Abbey College,Belmont,NC +201283,Belmont College,Saint Clairsville,OH +219709,Belmont University,Nashville,TN +238333,Beloit College,Beloit,WI +126359,Bel-Rea Institute of Animal Technology,Denver,CO +173124,Bemidji State University,Bemidji,MN +217721,Benedict College,Columbia,SC +154712,Benedictine College,Atchison,KS +145619,Benedictine University,Lisle,IL +165884,Benjamin Franklin Institute of Technology,Boston,MA +197993,Bennett College,Greensboro,NC +230816,Bennington College,Bennington,VT +164739,Bentley University,Waltham,MA +156295,Berea College,Berea,KY +183743,Bergen Community College,Paramus,NJ +461643,Bergin University of Canine Studies,Rohnert Park,CA +125170,Berkeley City College,Berkeley,CA +189228,Berkeley College-New York,New York,NY +183789,Berkeley College-Woodland Park,Woodland Park,NJ +164748,Berklee College of Music,Boston,MA +213534,Berks Technical Institute,Wyomissing,PA +164775,Berkshire Community College,Pittsfield,MA +139144,Berry College,Mount Berry,GA +189273,Beth Hamedrash Shaarei Yosher Institute,Brooklyn,NY +189264,Beth Hatalmud Rabbinical College,Brooklyn,NY +183804,Beth Medrash Govoha,Lakewood,NJ +237181,Bethany College-Bethany,Bethany,WV +154721,Bethany College-Lindsborg,Lindsborg,KS +173142,Bethany Lutheran College,Mankato,MN +143233,Bethany Theological Seminary,Richmond,IN +458113,Bethel College,Hampton,VA +150145,Bethel College-Indiana,Mishawaka,IN +154749,Bethel College-North Newton,North Newton,KS +262022,Bethel Seminary-San Diego,San Diego,CA +173179,Bethel Seminary-St Paul,Saint Paul,MN +219718,Bethel University-McKenzie,McKenzie,TN +173160,Bethel University-Saint Paul,Saint Paul,MN +110060,Bethesda University,Anaheim,CA +132602,Bethune-Cookman University,Daytona Beach,FL +139153,Beulah Heights University,Atlanta,GA +102429,Bevill State Community College,Jasper,AL +148724,Bexley Hall Seabury Western Theological Seminary Federation,Chicago,IL +443702,Bexley Hall Seabury Western Theological Seminary Federation ,Columbus,OH +211130,Biblical Theological Seminary,Hatfield,PA +211149,Bidwell Training Center Inc,Pittsburgh,PA +234711,Big Bend Community College,Moses Lake,WA +157553,Big Sandy Community and Technical College,Prestonsburg,KY +110097,Biola University,La Mirada,CA +100937,Birmingham Southern College,Birmingham,AL +442949,Birthingway College of Midwifery,Portland,OR +102030,Bishop State Community College,Mobile,AL +200022,Bismarck State College,Bismarck,ND +143279,Black Hawk College,Moline,IL +219046,Black Hills State University,Spearfish,SD +106625,Black River Technical College,Pocahontas,AR +143288,Blackburn College,Carlinville,IL +180054,Blackfeet Community College,Browning,MT +238397,Blackhawk Technical College,Janesville,WI +198011,Bladen Community College,Dublin,NC +143297,Blessing Rieman College of Nursing,Quincy,IL +223427,Blinn College,Brenham,TX +183822,Bloomfield College,Bloomfield,NJ +211158,Bloomsburg University of Pennsylvania,Bloomsburg,PA +441502,Blue Cliff College-Gulfport,Gulfport,MS +175430,Blue Mountain College,Blue Mountain,MS +208275,Blue Mountain Community College,Pendleton,OR +446774,Blue Ridge Community and Technical College,Martinsburg,WV +198039,Blue Ridge Community College-Flat Rock,Flat Rock,NC +231536,Blue Ridge Community College-Weyers Cave,Weyers Cave,VA +231554,Bluefield College,Bluefield,VA +237215,Bluefield State College,Bluefield,WV +156392,Bluegrass Community and Technical College,Lexington,KY +201371,Bluffton University,Bluffton,OH +217749,Bob Jones University,Greenville,SC +142090,Boise Bible College,Boise,ID +142115,Boise State University,Boise,ID +233356,Bon Secours Memorial College of Nursing,Richmond,VA +189413,Boricua College,New York,NY +158431,Bossier Parish Community College,Bossier City,LA +164872,Boston Architectural College,Boston,MA +164614,Boston Baptist College,Boston,MA +164924,Boston College,Chestnut Hill,MA +164915,Boston Graduate School of Psychoanalysis Inc,Brookline,MA +164988,Boston University,Boston,MA +161004,Bowdoin College,Brunswick,ME +162007,Bowie State University,Bowie,MD +201432,Bowling Green State University-Firelands,Huron,OH +201441,Bowling Green State University-Main Campus,Bowling Green,OH +202161,Bradford School-Columbus,Columbus,OH +211200,Bradford School-Pittsburgh,Pittsburgh,PA +143358,Bradley University,Peoria,IL +189422,Bramson ORT College,Forest Hills,NY +165015,Brandeis University,Waltham,MA +262086,Brandman University,Irvine,CA +223506,Brazosport College,Lake Jackson,TX +139199,Brenau University,Gainesville,GA +156356,Brescia University,Owensboro,KY +198066,Brevard College,Brevard,NC +139205,Brewton-Parker College,Mount Vernon,GA +152992,Briar Cliff University,Sioux City,IA +189459,Briarcliffe College,Bethpage,NY +231581,Bridgewater College,Bridgewater,VA +165024,Bridgewater State University,Bridgewater,MA +230047,Brigham Young University-Hawaii,Laie,HI +142522,Brigham Young University-Idaho,Rexburg,ID +230038,Brigham Young University-Provo,Provo,UT +215646,Brightwood Career Institute-Broomall,Broomall,PA +251075,Brightwood Career Institute-Harrisburg,Harrisburg,PA +214254,Brightwood Career Institute-Philadelphia,Philadelphia,PA +211617,Brightwood Career Institute-Philadelphia Mills,Philadelphia,PA +213002,Brightwood Career Institute-Pittsburgh,Pittsburgh,PA +458690,Brightwood College-Arlington,Arlington,TX +447102,Brightwood College-Bakersfield,Bakersfield,CA +163736,Brightwood College-Baltimore,Baltimore,MD +440323,Brightwood College-Beaumont,Beaumont,TX +164058,Brightwood College-Beltsville,Beltsville,MD +443827,Brightwood College-Brownsville,Brownsville,TX +458706,Brightwood College-Charlotte,Charlotte,NC +458186,Brightwood College-Chula Vista,Chula Vista,CA +443836,Brightwood College-Corpus Christi,Corpus Christi,TX +382896,Brightwood College-Dallas,Dallas,TX +204626,Brightwood College-Dayton,Dayton,OH +246266,Brightwood College-El Paso,El Paso,TX +445328,Brightwood College-Fort Worth,Fort Worth,TX +447120,Brightwood College-Fresno,Clovis,CA +458283,Brightwood College-Indianapolis,Indianapolis,IN +440332,Brightwood College-Laredo,Laredo,TX +374875,Brightwood College-Las Vegas,Las Vegas,NV +227836,Brightwood College-McAllen,McAllen,TX +366960,Brightwood College-Modesto,Salida,CA +246202,Brightwood College-Nashville,Nashville,TN +447634,Brightwood College-Palm Springs,Palm Springs,CA +432302,Brightwood College-Riverside,Riverside,CA +118259,Brightwood College-Sacramento,Sacramento,CA +431886,Brightwood College-San Antonio-Ingram,San Antonio,TX +364955,Brightwood College-San Antonio-San Pedro,San Antonio,TX +118277,Brightwood College-San Diego,San Diego,CA +161776,Brightwood College-Towson,Towson,MD +118286,Brightwood College-Vista,Vista,CA +165033,Bristol Community College,Fall River,MA +397270,Bristol University,Anaheim,CA +450304,Brite Divinity School,Fort Worth,TX +459091,Broadview Entertainment Arts University,Salt Lake City,UT +467793,Broadview University-Boise,Meridian,ID +450429,Broadview University-Layton,Layton,UT +454591,Broadview University-Orem,Orem,UT +230056,Broadview University-West Jordan,West Jordan,UT +183859,Brookdale Community College,Lincroft,NJ +223524,Brookhaven College,Farmers Branch,TX +444088,Brookline College-Albuquerque,Albuquerque,NM +104090,Brookline College-Phoenix,Phoenix,AZ +404055,Brookline College-Tempe,Tempe,AZ +438179,Brookline College-Tucson,Tucson,AZ +189501,Brooklyn Law School,Brooklyn,NY +110185,Brooks Institute,Ventura,CA +132709,Broward College,Fort Lauderdale,FL +205647,Brown Mackie College-Akron,Akron,OH +460039,Brown Mackie College-Albuquerque,Albuquerque,NM +410283,Brown Mackie College-Atlanta,Atlanta,GA +470162,Brown Mackie College-Birmingham,Birmingham,AL +455600,Brown Mackie College-Boise,Boise,ID +205610,Brown Mackie College-Cincinnati,Cincinnati,OH +482954,Brown Mackie College-Dallas,Bedford,TX +375489,Brown Mackie College-Findlay,Findlay,OH +408039,Brown Mackie College-Fort Wayne,Fort Wayne,IN +456791,Brown Mackie College-Greenville,Greenville,SC +421513,Brown Mackie College-Hopkinsville,Hopkinsville,KY +451699,Brown Mackie College-Indianapolis,Indianapolis,IN +154767,Brown Mackie College-Kansas City,Lenexa,KS +157599,Brown Mackie College-Louisville,Louisville,KY +151616,Brown Mackie College-Merrillville,Merrillville,IN +447290,Brown Mackie College-Miami,Miramar,FL +151625,Brown Mackie College-Michigan City,Michigan City,IN +204316,Brown Mackie College-North Canton,Canton,OH +157696,Brown Mackie College-Northern Kentucky,Fort Mitchell,KY +475042,Brown Mackie College-Oklahoma City,Oklahoma City,OK +456612,Brown Mackie College-Phoenix,Phoenix,AZ +373085,Brown Mackie College-Quad Cities,Bettendorf,IA +154776,Brown Mackie College-Salina,Salina,KS +460613,Brown Mackie College-San Antonio,San Antonio,TX +151944,Brown Mackie College-South Bend,South Bend,IN +460048,Brown Mackie College-St Louis,Fenton,MO +104364,Brown Mackie College-Tucson,Tucson,AZ +455619,Brown Mackie College-Tulsa,Tulsa,OK +217156,Brown University,Providence,RI +198084,Brunswick Community College,Bolivia,NC +180878,Bryan College of Health Sciences,Lincoln,NE +219790,Bryan College-Dayton,Dayton,TN +439826,Bryan College-Gold River,Gold River,CA +475583,Bryan University-Columbia,Columbia,MO +110219,Bryan University-Los Angeles,Los Angeles,CA +454458,Bryan University-Rogers,Rogers,AR +369516,Bryan University-Springfield,Springfield,MO +154794,Bryan University-Topeka,Topeka,KS +475699,Bryant & Stratton College-Akron,Copley,OH +188517,Bryant & Stratton College-Albany,Albany,NY +189556,Bryant & Stratton College-Amherst,Getzville,NY +458502,Bryant & Stratton College-Bayshore,Glendale,WI +189583,Bryant & Stratton College-Buffalo,Buffalo,NY +202684,Bryant & Stratton College-Cleveland,Cleveland,OH +369905,Bryant & Stratton College-Eastlake,Eastlake,OH +189592,Bryant & Stratton College-Greece,Rochester,NY +459107,Bryant & Stratton College-Hampton,Hampton,VA +410496,Bryant & Stratton College-Henrietta,Rochester,NY +239929,Bryant & Stratton College-Milwaukee,Milwaukee,WI +480091,Bryant & Stratton College-Online,Orchard Park,NY +201469,Bryant & Stratton College-Parma,Parma,OH +231828,Bryant & Stratton College-Richmond,North Chesterfield,VA +374972,Bryant & Stratton College-Southtowns,Orchard Park,NY +189574,Bryant & Stratton College-Syracuse,Syracuse,NY +189565,Bryant & Stratton College-Syracuse North,Liverpool,NY +231785,Bryant & Stratton College-Virginia Beach,Virginia Beach,VA +451750,Bryant & Stratton College-Wauwatosa,Wauwatosa,WI +217165,Bryant University,Smithfield,RI +210492,Bryn Athyn College of the New Church,Bryn Athyn,PA +211273,Bryn Mawr College,Bryn Mawr,PA +211291,Bucknell University,Lewisburg,PA +211307,Bucks County Community College,Newtown,PA +211316,Bucks County School of Beauty Culture Inc,Feasterville,PA +153001,Buena Vista University,Storm Lake,IA +165112,Bunker Hill Community College,Boston,MA +230825,Burlington College,Burlington,VT +484181,Burnett International College,Boynton Beach,FL +189653,Business Informatics Center Inc,Valley Stream,NY +154800,Butler Community College,El Dorado,KS +211343,Butler County Community College,Butler,PA +150163,Butler University,Indianapolis,IN +110246,Butte College,Oroville,CA +444103,Byzantine Catholic Seminary of Saints Cyril and Methodius,Pittsburgh,PA +198109,Cabarrus College of Health Sciences,Concord,NC +110334,Cabrillo College,Aptos,CA +211352,Cabrini University,Radnor,PA +215114,Cairn University-Langhorne,Langhorne,PA +198118,Caldwell Community College and Technical Institute,Hudson,NC +183910,Caldwell University,Caldwell,NJ +110361,California Baptist University,Riverside,CA +110918,California Christian College,Fresno,CA +110370,California College of the Arts,San Francisco,CA +485263,California College San Diego-San Diego,San Diego,CA +478634,California College San Diego-San Marcos,San Marcos,CA +110316,California Institute of Integral Studies,San Francisco,CA +110404,California Institute of Technology,Pasadena,CA +111081,California Institute of the Arts,Valencia,CA +110413,California Lutheran University,Thousand Oaks,CA +480781,California Miramar University,San Diego,CA +110422,California Polytechnic State University-San Luis Obispo,San Luis Obispo,CA +110529,California State Polytechnic University-Pomona,Pomona,CA +110486,California State University-Bakersfield,Bakersfield,CA +441937,California State University-Channel Islands,Camarillo,CA +110538,California State University-Chico,Chico,CA +110547,California State University-Dominguez Hills,Carson,CA +110574,California State University-East Bay,Hayward,CA +110556,California State University-Fresno,Fresno,CA +110565,California State University-Fullerton,Fullerton,CA +110583,California State University-Long Beach,Long Beach,CA +110592,California State University-Los Angeles,Los Angeles,CA +409698,California State University-Monterey Bay,Seaside,CA +110608,California State University-Northridge,Northridge,CA +110617,California State University-Sacramento,Sacramento,CA +110510,California State University-San Bernardino,San Bernardino,CA +366711,California State University-San Marcos,San Marcos,CA +110495,California State University-Stanislaus,Turlock,CA +460075,California University of Management and Sciences,Anaheim,CA +211361,California University of Pennsylvania,California,PA +111391,California Western School of Law,San Diego,CA +150172,Calumet College of Saint Joseph,Whiting,IN +176789,Calvary Bible College and Theological Seminary,Kansas City,MO +169080,Calvin College,Grand Rapids,MI +169099,Calvin Theological Seminary,Grand Rapids,MI +428329,Cambria-Rowe Business College-Indiana,Indiana,PA +211398,Cambria-Rowe Business College-Johnstown,Johnstown,PA +165167,Cambridge College,Cambridge,MA +454865,Cambridge College of Healthcare & Technology,Delray Beach,FL +446093,Cambridge Junior College-Yuba City,Yuba City,CA +183938,Camden County College,Blackwood,NJ +158440,Cameron College,New Orleans,LA +206914,Cameron University,Lawton,OK +198136,Campbell University,Buies Creek,NC +156365,Campbellsville University,Campbellsville,KY +111434,Canada College,Redwood City,CA +189705,Canisius College,Buffalo,NY +200208,Cankdeska Cikana Community College,Fort Totten,ND +165194,Cape Cod Community College,West Barnstable,MA +198154,Cape Fear Community College,Wilmington,NC +413413,Capella University,Minneapolis,MN +158352,Capital Area Technical College,Baton Rouge,LA +129367,Capital Community College,Hartford,CT +201548,Capital University,Columbus,OH +162061,Capitol Technology University,Laurel,MD +238430,Cardinal Stritch University,Milwaukee,WI +181941,Career College of Northern Nevada,Sparks,NV +224439,Career Point College-San Antonio,San Antonio,TX +246008,Career Point College-Tulsa,Tulsa,OK +454306,Career Quest Learning Centers-Jackson,Jackson,MI +446136,Career Quest Learning Centers-Lansing,Lansing,MI +367112,Career Technical College-Monroe,Monroe,LA +446880,Career Technical College-Shreveport,Shreveport,LA +210951,Career Training Academy-Lower Burrell,New Kensington,PA +408312,Career Training Academy-Monroeville,Monroeville,PA +440174,Career Training Academy-Pittsburgh,Pittsburgh,PA +448239,Careers Unlimited,Orem,UT +241377,Caribbean University-Bayamon,Bayamon,PR +241386,Caribbean University-Carolina,Carolina,PR +363907,Caribbean University-Ponce,Ponce,PR +363916,Caribbean University-Vega Baja,Vega Baja,PR +206923,Carl Albert State College,Poteau,OK +143613,Carl Sandburg College,Galesburg,IL +173258,Carleton College,Northfield,MN +132842,Carlos Albizu University-Miami,Miami,FL +241331,Carlos Albizu University-San Juan,San Juan,PR +211431,Carlow University,Pittsburgh,PA +211440,Carnegie Mellon University,Pittsburgh,PA +199971,Carolina Christian College,Winston Salem,NC +461032,Carolina College of Biblical Studies,Fayetteville,NC +433174,Carolinas College of Health Sciences,Charlotte,NC +442602,Carrington College-Albuquerque,Albuquerque,NM +142054,Carrington College-Boise,Boise,ID +450702,Carrington College-Citrus Heights,Citrus Heights,CA +457101,Carrington College-Las Vegas,Las Vegas,NV +103909,Carrington College-Mesa,Mesa,AZ +103893,Carrington College-Phoenix,Phoenix,AZ +438258,Carrington College-Pleasant Hill,Pleasant Hill,CA +467368,Carrington College-Pomona,Pomona,CA +246035,Carrington College-Portland,Portland,OR +457110,Carrington College-Reno,Reno,NV +125532,Carrington College-Sacramento,Sacramento,CA +437936,Carrington College-San Jose,San Jose,CA +246974,Carrington College-San Leandro,San Leandro,CA +439118,Carrington College-Spokane,Spokane,WA +450696,Carrington College-Stockton,Stockton,CA +103927,Carrington College-Tucson,Tucson,AZ +250601,Carrington College-Westside,Phoenix,AZ +180106,Carroll College,Helena,MT +405872,Carroll Community College,Westminster,MD +238458,Carroll University,Waukesha,WI +219806,Carson-Newman University,Jefferson City,TN +198206,Carteret Community College,Morehead City,NC +238476,Carthage College,Kenosha,WI +139287,Carver Bible College,Atlanta,GA +430795,Carver Career Center,Charleston,WV +111638,Casa Loma College-Van Nuys,Van Nuys,CA +439190,Cascadia College,Bothell,WA +201645,Case Western Reserve University,Cleveland,OH +240505,Casper College,Casper,WY +230834,Castleton State College,Castleton,VT +198215,Catawba College,Salisbury,NC +198233,Catawba Valley Community College,Hickory,NC +475398,Catholic Distance University,Hamilton,VA +143659,Catholic Theological Union at Chicago,Chicago,IL +131283,Catholic University of America,Washington,DC +189839,Cayuga County Community College,Auburn,NY +189848,Cazenovia College,Cazenovia,NY +162104,Cecil College,North East,MD +211468,Cedar Crest College,Allentown,PA +223773,Cedar Valley College,Lancaster,TX +201654,Cedarville University,Cedarville,OH +183974,Centenary College,Hackettstown,NJ +158477,Centenary College of Louisiana,Shreveport,LA +379782,Center for Advanced Legal Studies,Houston,TX +241793,Center for Advanced Studies On Puerto Rico and the Caribbean,San Juan,PR +232618,Centra College of Nursing,Lynchburg,VA +100760,Central Alabama Community College,Alexander City,AL +104346,Central Arizona College,Coolidge,AZ +106713,Central Baptist College,Conway,AR +154837,Central Baptist Theological Seminary,Shawnee,KS +198251,Central Carolina Community College,Sanford,NC +218858,Central Carolina Technical College,Sumter,SC +154855,Central Christian College of Kansas,McPherson,KS +176910,Central Christian College of the Bible,Moberly,MO +153108,Central College,Pella,IA +180902,Central Community College,Grand Island,NE +128771,Central Connecticut State University,New Britain,CT +439525,Central Florida Institute,Palm Harbor,FL +483045,Central Georgia Technical College,Warner Robins,GA +173203,Central Lakes College-Brainerd,Brainerd,MN +158088,Central Louisiana Technical Community College,Alexandria,LA +161077,Central Maine Community College,Auburn,ME +445267,Central Methodist University-College of Graduate and Extended Studies,Fayette,MO +176947,Central Methodist University-College of Liberal Arts and Sciences,Fayette,MO +169248,Central Michigan University,Mount Pleasant,MI +187532,Central New Mexico Community College,Albuquerque,NM +201672,Central Ohio Technical College,Newark,OH +208318,Central Oregon Community College,Bend,OR +211477,Central Penn College,Summerdale,PA +198260,Central Piedmont Community College,Charlotte,NC +201690,Central State University,Wilberforce,OH +223816,Central Texas College,Killeen,TX +231697,Central Virginia Community College,Lynchburg,VA +234827,Central Washington University,Ellensburg,WA +240514,Central Wyoming College,Riverton,WY +189857,Central Yeshiva Tomchei Tmimim Lubavitz,Brooklyn,NY +234845,Centralia College,Centralia,WA +156408,Centre College,Danville,KY +451741,Centro de Estudios Multidisciplinarios-Bayamon,Bayamón,PR +376224,Centro de Estudios Multidisciplinarios-Humacao,Humacao,PR +241517,Centro de Estudios Multidisciplinarios-San Juan,San Juan,PR +420024,Centura College-Chesapeake,Chesapeake,VA +444972,Centura College-Columbia,Columbia,SC +377449,Centura College-Newport News,Newport News,VA +377458,Centura College-Norfolk,Norfolk,VA +427982,Centura College-Richmond Main,Richmond,VA +232016,Centura College-Virginia Beach,Virginia Beach,VA +175315,Century College-White Bear Lake,White Bear Lake,MN +111887,Cerritos College,Norwalk,CA +111896,Cerro Coso Community College,Ridgecrest,CA +111920,Chabot College,Hayward,CA +180948,Chadron State College,Chadron,NE +111939,Chaffey College,Rancho Cucamonga,CA +454245,Chamberlain College of Nursing-Arizona,Phoenix,AZ +457129,Chamberlain College of Nursing-Florida,Jacksonville,FL +475732,Chamberlain College of Nursing-Georgia,Atlanta,GA +454227,Chamberlain College of Nursing-Illinois,Addison,IL +466921,Chamberlain College of Nursing-Missouri,St. Louis,MO +454236,Chamberlain College of Nursing-Ohio,Columbus,OH +466930,Chamberlain College of Nursing-Texas,Houston,TX +460871,Chamberlain College of Nursing-Virginia,Arlington,VA +141486,Chaminade University of Honolulu,Honolulu,HI +230852,Champlain College,Burlington,VT +364025,Chandler-Gilbert Community College,Chandler,AZ +111948,Chapman University,Orange,CA +111966,Charles R Drew University of Medicine and Science,Los Angeles,CA +451510,Charleston School of Law,Charleston,SC +217688,Charleston Southern University,Charleston,SC +444778,Charlotte Christian College and Theological Seminary,Charlotte,NC +455169,Charlotte School of Law,Charlotte,NC +102845,Charter College-Anchorage,Anchorage,AK +434317,Charter College-Canyon Country,Canyon Country,CA +128780,Charter Oak State College,New Britain,CT +201751,Chatfield College,Saint Martin,OH +211556,Chatham University,Pittsburgh,PA +140331,Chattahoochee Technical College,Marietta,GA +101028,Chattahoochee Valley Community College,Phenix City,AL +220118,Chattanooga College Medical Dental and Technical Careers,Chattanooga,TN +219824,Chattanooga State Community College,Chattanooga,TN +208390,Chemeketa Community College,Salem,OR +162168,Chesapeake College,Wye Mills,MD +437769,Chester Career College,CHESTER,VA +211583,Chestnut Hill College,Philadelphia,PA +211608,Cheyney University of Pennsylvania,Cheyney,PA +181145,CHI Health School of Radiologic Technology,Omaha,NE +393180,Chicago ORT Technical Institute,Skokie,IL +144005,Chicago State University,Chicago,IL +144014,Chicago Theological Seminary,Chicago,IL +180160,Chief Dull Knife College,Lame Deer,MT +133021,Chipola College,Marianna,FL +240116,Chippewa Valley Technical College,Eau Claire,WI +198303,Chowan University,Murfreesboro,NC +189981,Christ the King Seminary,East Aurora,NY +219833,Christian Brothers University,Memphis,TN +260947,Christian Life College,Mount Prospect,IL +150215,Christian Theological Seminary,Indianapolis,IN +475510,Christie's Education,New York,NY +231712,Christopher Newport University,Newport News,VA +112127,Church Divinity School of the Pacific,Berkeley,CA +201858,Cincinnati Christian University,Cincinnati,OH +201867,Cincinnati College of Mortuary Science,Cincinnati,OH +201928,Cincinnati State Technical and Community College,Cincinnati,OH +223898,Cisco College,Cisco,TX +217864,Citadel Military College of South Carolina,Charleston,SC +112172,Citrus College,Glendora,CA +112190,City College of San Francisco,San Francisco,CA +417327,City College-Altamonte Springs,Altamonte Springs,FL +244233,City College-Fort Lauderdale,Fort Lauderdale,FL +406547,City College-Gainesville,Gainesville,FL +475477,City College-Hollywood,Hollywood,FL +434539,City College-Miami,Miami,FL +144209,City Colleges of Chicago-Harold Washington College,Chicago,IL +144184,City Colleges of Chicago-Harry S Truman College,Chicago,IL +144157,City Colleges of Chicago-Kennedy-King College,Chicago,IL +144166,City Colleges of Chicago-Malcolm X College,Chicago,IL +144175,City Colleges of Chicago-Olive-Harvey College,Chicago,IL +144193,City Colleges of Chicago-Richard J Daley College,Chicago,IL +144218,City Colleges of Chicago-Wilbur Wright College,Chicago,IL +234915,City University of Seattle,Seattle,WA +457697,City Vision University,Kansas City,MO +208406,Clackamas Community College,Oregon City,OR +217873,Claflin University,Orangeburg,SC +112251,Claremont Graduate University,Claremont,CA +112260,Claremont McKenna College,Claremont,CA +124283,Claremont School of Theology,Claremont,CA +223922,Clarendon College,Clarendon,TX +211644,Clarion University of Pennsylvania,Clarion,PA +138947,Clark Atlanta University,Atlanta,GA +234933,Clark College,Vancouver,WA +201973,Clark State Community College,Springfield,OH +165334,Clark University,Worcester,MA +153126,Clarke University,Dubuque,IA +180832,Clarkson College,Omaha,NE +190044,Clarkson University,Potsdam,NY +450401,Clary Sage College,Tulsa,OK +208415,Clatsop Community College,Astoria,OR +139311,Clayton State University,Morrow,GA +156417,Clear Creek Baptist Bible College,Pineville,KY +133085,Clearwater Christian College,Clearwater,FL +169327,Cleary University,Ann Arbor,MI +217882,Clemson University,Clemson,SC +198321,Cleveland Community College,Shelby,NC +202046,Cleveland Institute of Art,Cleveland,OH +202073,Cleveland Institute of Music,Cleveland,OH +219879,Cleveland State Community College,Cleveland,TN +202134,Cleveland State University,Cleveland,OH +177038,Cleveland University-Kansas City,Overland Park,KS +217891,Clinton College,Rock Hill,SC +190053,Clinton Community College,Plattsburgh,NY +154907,Cloud County Community College,Concordia,KS +234951,Clover Park Technical College,Lakewood,WA +187639,Clovis Community College,Clovis,NM +175519,Coahoma Community College,Clarksdale,MS +223320,Coastal Bend College,Beeville,TX +198330,Coastal Carolina Community College,Jacksonville,NC +218724,Coastal Carolina University,Conway,SC +485458,Coastal Pines Technical College-Waycross,Waycross,GA +112385,Coastline Community College,Fountain Valley,CA +104425,Cochise County Community College District,Douglas,AZ +190071,Cochran School of Nursing,Yonkers,NY +404426,Coconino Community College,Flagstaff,AZ +153144,Coe College,Cedar Rapids,IA +154925,Coffeyville Community College,Coffeyville,KS +112394,Cogswell College,Sunnyvale,CA +217907,Coker College,Hartsville,SC +161086,Colby College,Waterville,ME +154934,Colby Community College,Colby,KS +182634,Colby-Sawyer College,New London,NH +430935,Colegio de Cinematografía Artes y Television,Bayamon,PR +241720,Colegio Universitario de San Juan,San Juan,PR +112446,Coleman University,San Diego,CA +190080,Colgate Rochester Crozer Divinity School,Rochester,NY +190099,Colgate University,Hamilton,NY +169442,College for Creative Studies,Detroit,MI +108667,College of Alameda,Alameda,CA +388520,College of Biblical Studies-Houston,Houston,TX +456977,College of Business and Technology-Cutler Bay,Cutler Bay,FL +449083,College of Business and Technology-Flagler,Miami,FL +449092,College of Business and Technology-Hialeah,Hialeah,FL +417318,College of Business and Technology-Kendall,Miami,FL +482024,College of Business and Technology-Miami Gardens,Miami Gardens,FL +132851,College of Central Florida,Ocala,FL +217819,College of Charleston,Charleston,SC +139250,College of Coastal Georgia,Brunswick,GA +150251,College of Court Reporting Inc,Hobart,IN +144865,College of DuPage,Glen Ellyn,IL +392257,College of Health Care Professions-Northwest,Houston,TX +146472,College of Lake County,Grayslake,IL +118347,College of Marin,Kentfield,CA +413617,College of Menominee Nation,Keshena,WI +243638,College of Micronesia-FSM,Pohnpei,FM +193399,College of Mount Saint Vincent,Bronx,NY +167394,College of Our Lady of the Elms,Chicopee,MA +174747,College of Saint Benedict,Saint Joseph,MN +186618,College of Saint Elizabeth,Morristown,NJ +181604,College of Saint Mary,Omaha,NE +122791,College of San Mateo,San Mateo,CA +142559,College of Southern Idaho,Twin Falls,ID +162122,College of Southern Maryland,La Plata,MD +182005,College of Southern Nevada,Las Vegas,NV +231077,College of St Joseph,Rutland,VT +190558,College of Staten Island CUNY,Staten Island,NY +197814,College of the Albemarle,Elizabeth City,NC +160959,College of the Atlantic,Bar Harbor,ME +111461,College of the Canyons,Santa Clarita,CA +113573,College of the Desert,Palm Desert,CA +166124,College of the Holy Cross,Worcester,MA +226408,College of the Mainland,Texas City,TX +376695,College of the Marshall Islands,Majuro,MH +480967,College of the Muscogee Nation,Okmulgee,OK +107521,College of the Ouachitas,Malvern,AR +178697,College of the Ozarks,Point Lookout,MO +121707,College of the Redwoods,Eureka,CA +123217,College of the Sequoias,Visalia,CA +123484,College of the Siskiyous,Weed,CA +455114,College of Western Idaho,Nampa,ID +231624,College of William and Mary,Williamsburg,VA +451705,CollegeAmerica-Cheyenne,Cheyenne,WY +448752,CollegeAmerica-Colorado Springs,Colorado Springs,CO +126872,CollegeAmerica-Denver,Denver,CO +103945,CollegeAmerica-Flagstaff,Flagstaff,AZ +448761,CollegeAmerica-Fort Collins,Fort Collins,CO +474890,CollegeAmerica-Phoenix,Phoenix,AZ +247834,Collin County Community College District,McKinney,TX +103723,Collins College,Phoenix,AZ +461953,Colorado Academy of Veterinary Technology,Colorado Springs,CO +126669,Colorado Christian University,Lakewood,CO +126678,Colorado College,Colorado Springs,CO +367839,Colorado Heights University,Denver,CO +127556,Colorado Mesa University,Grand Junction,CO +126711,Colorado Mountain College,Glenwood Springs,CO +126748,Colorado Northwestern Community College,Rangely,CO +381732,Colorado School of Healing Arts,Lakewood,CO +126775,Colorado School of Mines,Golden,CO +126784,Colorado School of Trades,Lakewood,CO +381352,Colorado School of Traditional Chinese Medicine,Denver,CO +126818,Colorado State University-Fort Collins,Fort Collins,CO +476975,Colorado State University-Global Campus,Greenwood Village,CO +128106,Colorado State University-Pueblo,Pueblo,CO +126827,Colorado Technical University-Colorado Springs,Colorado Springs,CO +430087,Colorado Technical University-Greenwood Village,Aurora,CO +444158,Colorado Technical University-Online,Colorado Springs,CO +402615,Colorado Technical University-Sioux Falls,Sioux Falls,SD +234979,Columbia Basin College,Pasco,WA +241304,Columbia Central University-Caguas,Caguas,PR +404806,Columbia Central University-Yauco,Yauco,PR +238573,Columbia College of Nursing,Glendale,WI +144281,Columbia College-Chicago,Chicago,IL +177065,Columbia College-Columbia,Columbia,MO +217934,Columbia College-Columbia,Columbia,SC +455983,Columbia College-Fairfax,Fairfax,VA +112570,Columbia College-Hollywood,Tarzana,CA +112561,Columbia College-Sonora,Sonora,CA +420556,Columbia Gorge Community College,The Dalles,OR +217925,Columbia International University,Columbia,SC +450933,Columbia Southern University,Orange Beach,AL +219888,Columbia State Community College,Columbia,TN +139348,Columbia Theological Seminary,Decatur,GA +190150,Columbia University in the City of New York,New York,NY +190169,Columbia-Greene Community College,Hudson,NY +202170,Columbus College of Art and Design,Columbus,OH +202222,Columbus State Community College,Columbus,OH +139366,Columbus State University,Columbus,GA +139357,Columbus Technical College,Columbus,GA +483522,Comanche Nation College,Lawton,OK +366261,Commonwealth Institute of Funeral Service,Houston,TX +212975,Commonwealth Technical Institute,Johnstown,PA +439570,Community Care College,Tulsa,OK +446163,Community Christian College,Redlands,CA +210605,Community College of Allegheny County,Pittsburgh,PA +126863,Community College of Aurora,Aurora,CO +211079,Community College of Beaver County,Monaca,PA +126942,Community College of Denver,Denver,CO +215239,Community College of Philadelphia,Philadelphia,PA +217475,Community College of Rhode Island,Warwick,RI +230861,Community College of Vermont,Winooski,VT +459417,Compass College of Cinematic Arts,Grand Rapids,MI +177083,Conception Seminary College,Conception,MO +237330,Concord University,Athens,WV +126687,Concorde Career College-Aurora,Aurora,CO +460181,Concorde Career College-Dallas,Dallas,TX +123679,Concorde Career College-Garden Grove,Garden Grove,CA +441742,Concorde Career College-Grand Prairie,Grand Prairie,TX +155283,Concorde Career College-Kansas City,Kansas City,MO +219903,Concorde Career College-Memphis,Memphis,TN +124937,Concorde Career College-North Hollywood,North Hollywood,CA +208479,Concorde Career College-Portland,Portland,OR +460206,Concorde Career College-San Antonio,San Antonio,TX +124706,Concorde Career College-San Bernardino,San Bernardino,CA +120661,Concorde Career College-San Diego,San Diego,CA +133845,Concorde Career Institute-Jacksonville,Jacksonville,FL +133854,Concorde Career Institute-Miramar,Miramar,FL +460190,Concorde Career Institute-Orlando,Orlando,FL +133863,Concorde Career Institute-Tampa,Tampa,FL +101073,Concordia College Alabama,Selma,AL +173300,Concordia College at Moorhead,Moorhead,MN +190248,Concordia College-New York,Bronxville,NY +177092,Concordia Seminary,Saint Louis,MO +150288,Concordia Theological Seminary,Fort Wayne,IN +169363,Concordia University-Ann Arbor,Ann Arbor,MI +144351,Concordia University-Chicago,River Forest,IL +112075,Concordia University-Irvine,Irvine,CA +180984,Concordia University-Nebraska,Seward,NE +208488,Concordia University-Portland,Portland,OR +173328,Concordia University-Saint Paul,Saint Paul,MN +224004,Concordia University-Texas,Austin,TX +238616,Concordia University-Wisconsin,Mequon,WI +128902,Connecticut College,New London,CT +206996,Connors State College,Warner,OK +260354,Consolidated School of Business-Lancaster,Lancaster,PA +211820,Consolidated School of Business-York,York,PA +112826,Contra Costa College,San Pablo,CA +217961,Converse College,Spartanburg,SC +165495,Conway School of Landscape Design,Conway,MA +190372,Cooper Union for the Advancement of Science and Art,New York,NY +175573,Copiah-Lincoln Community College,Wesson,MS +395362,Copper Mountain Community College,Joshua Tree,CA +162283,Coppin State University,Baltimore,MD +210331,Corban University,Salem,OR +153162,Cornell College,Mount Vernon,IA +190415,Cornell University,Ithaca,NY +170037,Cornerstone University,Grand Rapids,MI +190442,Corning Community College,Corning,NY +235024,Cornish College of the Arts,Seattle,WA +106795,Cossatot Community College of the University of Arkansas,De Queen,AR +113096,Cosumnes River College,Sacramento,CA +177117,Cottey College,Nevada,MO +184180,County College of Morris,Randolph,NJ +224183,Court Reporting Institute of Dallas,Dallas,TX +139393,Covenant College,Lookout Mountain,GA +177126,Covenant Theological Seminary,Saint Louis,MO +154952,Cowley County Community College,Arkansas City,KS +176770,Cox College,Springfield,MO +144485,Coyne College,Chicago,IL +113111,Crafton Hills College,Yucaipa,CA +169424,Cranbrook Academy of Art,Bloomfield Hills,MI +198367,Craven Community College,New Bern,NC +181002,Creighton University,Omaha,NE +475608,Criswell College,Dallas,TX +439613,Crossroads Bible College,Indianapolis,IN +174206,Crossroads College,Rochester,MN +177135,Crowder College,Neosho,MO +106810,Crowley's Ridge College,Paragould,AR +174862,Crown College,Saint Bonifacius,MN +113193,Cuesta College,San Luis Obispo,CA +444565,Culinary Institute Inc,Houston,TX +190503,Culinary Institute of America,Hyde Park,NY +177144,Culver-Stockton College,Canton,MO +184205,Cumberland County College,Vineland,NJ +219949,Cumberland University,Lebanon,TN +190512,CUNY Bernard M Baruch College,New York,NY +190521,CUNY Borough of Manhattan Community College,New York,NY +190530,CUNY Bronx Community College,Bronx,NY +190549,CUNY Brooklyn College,Brooklyn,NY +190567,CUNY City College,New York,NY +190576,CUNY Graduate School and University Center,New York,NY +190585,CUNY Hostos Community College,Bronx,NY +190594,CUNY Hunter College,New York,NY +190600,CUNY John Jay College of Criminal Justice,New York,NY +190619,CUNY Kingsborough Community College,Brooklyn,NY +190628,CUNY LaGuardia Community College,Long Island City,NY +190637,CUNY Lehman College,Bronx,NY +190646,CUNY Medgar Evers College,Brooklyn,NY +190655,CUNY New York City College of Technology,Brooklyn,NY +190664,CUNY Queens College,Flushing,NY +190673,CUNY Queensborough Community College,Bayside,NY +190682,CUNY School of Law,Long Island City,NY +190691,CUNY York College,Jamaica,NY +165529,Curry College,Milton,MA +211893,Curtis Institute of Music,Philadelphia,PA +202356,Cuyahoga Community College District,Cleveland,OH +113218,Cuyamaca College,El Cajon,CA +113236,Cypress College,Cypress,CA +231873,Dabney S Lancaster Community College,Clifton Forge,VA +458797,Dade Medical College-Hollywood,Hollywood,FL +458247,Dade Medical College-Homestead,Homestead,FL +476391,Dade Medical College-Jacksonville,Jacksonville,FL +444574,Dade Medical College-Miami,Miami,FL +454175,Dade Medical College-Miami Lakes,Miami Lakes,FL +476382,Dade Medical College-West Palm Beach,West Palm Beach,FL +190725,Daemen College,Amherst,NY +200314,Dakota College at Bottineau,Bottineau,ND +173416,Dakota County Technical College,Rosemount,MN +219082,Dakota State University,Madison,SD +219091,Dakota Wesleyan University,Mitchell,SD +224226,Dallas Baptist University,Dallas,TX +224244,Dallas Christian College,Dallas,TX +224271,Dallas Institute of Funeral Service,Dallas,TX +437732,Dallas Nursing Institute,Dallas,TX +224305,Dallas Theological Seminary,Dallas,TX +139463,Dalton State College,Dalton,GA +182661,Daniel Webster College,Nashua,NH +144564,Danville Area Community College,Danville,IL +231882,Danville Community College,Danville,VA +455178,Daoist Traditions College of Chinese Medical Arts,Asheville,NC +182670,Dartmouth College,Hanover,NH +138691,Darton State College,Albany,GA +169479,Davenport University,Grand Rapids,MI +198385,Davidson College,Davidson,NC +198376,Davidson County Community College,Thomasville,NC +237358,Davis & Elkins College,Elkins,WV +194569,Davis College-Johnson City,Johnson City,NY +202435,Davis College-Toledo,Toledo,OH +180151,Dawson Community College,Glendive,MT +447476,Daymar College-Bellevue,Bellevue,KY +363439,Daymar College-Bowling Green,Bowling Green,KY +205568,Daymar College-Chillicothe,Chillicothe,OH +205531,Daymar College-Jackson,Jackson,OH +205559,Daymar College-Lancaster,Lancaster,OH +406219,Daymar College-Louisville-Louisville,Louisville,KY +449302,Daymar College-Madisonville,Madisonville,KY +205522,Daymar College-New Boston,New Boston,OH +458557,Daymar College-Online,Louisville,KY +157465,Daymar College-Owensboro,Owensboro,KY +156903,Daymar College-Paducah Main,Paducah,KY +368443,Daymar Institute-Clarksville,Clarksville,TN +444255,Daymar Institute-Murfreesboro,Murfreesboro,TN +220002,Daymar Institute-Nashville,Nashville,TN +447014,Daytona College,Ormond Beach,FL +133386,Daytona State College,Daytona Beach,FL +113333,De Anza College,Cupertino,CA +165574,Dean College,Franklin,MA +211909,Dean Institute of Technology,Pittsburgh,PA +202514,Defiance College,Defiance,OH +224350,Del Mar College,Corpus Christi,TX +432524,Delaware College of Art and Design,Wilmington,DE +211927,Delaware County Community College,Media,PA +130934,Delaware State University,Dover,DE +130891,Delaware Technical Community College-Owens,Georgetown,DE +130916,Delaware Technical Community College-Stanton/Wilmington,Wilmington,DE +130907,Delaware Technical Community College-Terry,Dover,DE +211981,Delaware Valley University,Doylestown,PA +158662,Delgado Community College,New Orleans,LA +113537,Dell'Arte International School of Physical Theatre,Blue Lake,CA +169521,Delta College,University Center,MI +366270,Delta College of Arts & Technology,Baton Rouge,LA +158723,Delta School of Business and Technology,Lake Charles,LA +175616,Delta State University,Cleveland,MS +202523,Denison University,Granville,OH +217989,Denmark Technical College,Denmark,SC +454856,Denver School of Nursing,Denver,CO +126979,Denver Seminary,Littleton,CO +144740,DePaul University,Chicago,IL +150400,DePauw University,Greencastle,IN +153214,Des Moines Area Community College,Ankeny,IA +154156,Des Moines University-Osteopathic Medical Center,Des Moines,IA +210739,DeSales University,Center Valley,PA +113582,Design Institute of San Diego,San Diego,CA +482413,DeVry College of New York,New York,NY +482422,DeVry University-Arizona,Phoenix,AZ +482431,DeVry University-California,Pomona,CA +482440,DeVry University-Colorado,Westminster,CO +482459,DeVry University-Florida,Miramar,FL +482468,DeVry University-Georgia,Decatur,GA +482477,DeVry University-Illinois,Chicago,IL +482486,DeVry University-Indiana,Indianapolis,IN +482501,DeVry University-Maryland,Bethesda,MD +482510,DeVry University-Michigan,Southfield,MI +482529,DeVry University-Minnesota,Edina,MN +482538,DeVry University-Missouri,Kansas City,MO +482547,DeVry University-Nevada,Henderson,NV +482556,DeVry University-New Jersey,North Brunswick,NJ +482565,DeVry University-North Carolina,Charlotte,NC +482574,DeVry University-Ohio,Columbus,OH +482583,DeVry University-Oklahoma,Oklahoma City,OK +482592,DeVry University-Oregon,Portland,OR +482608,DeVry University-Pennsylvania,Fort Washington,PA +482617,DeVry University-Tennessee,Memphis,TN +482635,DeVry University-Texas,Irving,TX +482644,DeVry University-Utah,Sandy,UT +482653,DeVry University-Virginia,Arlington,VA +482662,DeVry University-Washington,Federal Way,WA +482671,DeVry University-Wisconsin,Milwaukee,WI +443562,Dewey University-Hato Rey-Hato Rey,Hato Rey,PR +113634,Diablo Valley College,Pleasant Hill,CA +212009,Dickinson College,Carlisle,PA +200059,Dickinson State University,Dickinson,ND +443410,DigiPen Institute of Technology,Redmond,WA +451060,Digital Media Arts College,Boca Raton,FL +158802,Dillard University,New Orleans,LA +105297,Dine College,Tsaile,AZ +153241,Divine Word College,Epworth,IA +230171,Dixie State University,Saint George,UT +181020,Doane University-Arts & Sciences,Crete,NE +448284,Doane University-Graduate and Professional Studies,Lincoln,NE +154998,Dodge City Community College,Dodge City,KS +190761,Dominican College of Blauvelt,Orangeburg,NY +113704,Dominican School of Philosophy & Theology,Berkeley,CA +148496,Dominican University,River Forest,IL +113698,Dominican University of California,San Rafael,CA +122117,Dongguk University-Los Angeles,Los Angeles,CA +155007,Donnelly College,Kansas City,KS +153250,Dordt College,Sioux Center,IA +212045,Douglas Education Center,Monessen,PA +190770,Dowling College,Oakdale,NY +153269,Drake University,Des Moines,IA +184348,Drew University,Madison,NJ +212054,Drexel University,Philadelphia,PA +177214,Drury University,Springfield,MO +212072,Du Bois Business College-Du Bois,Du Bois,PA +439303,Du Bois Business College-Huntingdon,Huntingdon,PA +439312,Du Bois Business College-Oil City,Oil City,PA +198419,Duke University,Durham,NC +173489,Duluth Business University,Duluth,MN +175227,Dunwoody College of Technology,Minneapolis,MN +212106,Duquesne University,Pittsburgh,PA +198455,Durham Technical Community College,Durham,NC +190840,Dutchess Community College,Poughkeepsie,NY +220057,Dyersburg State Community College,Dyersburg,TN +190716,D'Youville College,Buffalo,NY +447421,Eagle Gate College-Layton,Layton,UT +230366,Eagle Gate College-Murray,Murray,UT +447625,Eagle Gate College-Salt Lake City,Salt Lake City,UT +150455,Earlham College,Richmond,IN +106883,East Arkansas Community College,Forrest City,AR +198464,East Carolina University,Greenville,NC +177250,East Central College,Union,MO +175643,East Central Community College,Decatur,MS +207041,East Central University,Ada,OK +139621,East Georgia State College,Swainsboro,GA +113856,East Los Angeles College,Monterey Park,CA +175652,East Mississippi Community College,Scooba,MS +413802,East San Gabriel Valley Regional Occupational Program,West Covina,CA +212115,East Stroudsburg University of Pennsylvania,East Stroudsburg,PA +220075,East Tennessee State University,Johnson City,TN +224527,East Texas Baptist University,Marshall,TX +439394,East West College of Natural Medicine,Sarasota,FL +104577,Eastern Arizona College,Thatcher,AZ +129215,Eastern Connecticut State University,Willimantic,CT +132693,Eastern Florida State College,Cocoa,FL +203331,Eastern Gateway Community College,Steubenville,OH +142179,Eastern Idaho Technical College,Idaho Falls,ID +144892,Eastern Illinois University,Charleston,IL +448354,Eastern International College-Belleville,Belleville,NJ +421878,Eastern International College-Jersey City,Jersey City,NJ +153311,Eastern Iowa Community College District,Davenport,IA +156620,Eastern Kentucky University,Richmond,KY +161138,Eastern Maine Community College,Bangor,ME +232043,Eastern Mennonite University,Harrisonburg,VA +169798,Eastern Michigan University,Ypsilanti,MI +165644,Eastern Nazarene College,Quincy,MA +187648,Eastern New Mexico University-Main Campus,Portales,NM +187666,Eastern New Mexico University-Roswell Campus,Roswell,NM +383996,Eastern New Mexico University-Ruidoso Campus,Ruidoso,NM +207050,Eastern Oklahoma State College,Wilburton,OK +208646,Eastern Oregon University,La Grande,OR +232052,Eastern Shore Community College,Melfa,VA +212133,Eastern University,Saint Davids,PA +441858,Eastern Virginia Career College,Fredericksburg,VA +231970,Eastern Virginia Medical School,Norfolk,VA +235097,Eastern Washington University,Cheney,WA +438708,Eastern West Virginia Community and Technical College,Moorefield,WV +240596,Eastern Wyoming College,Torrington,WY +224572,Eastfield College,Mesquite,TX +144883,East-West University,Chicago,IL +183488,Eastwick College-Hackensack,Hackensack,NJ +184959,Eastwick College-Ramsey,Ramsey,NJ +446233,Ecclesia College,Springdale,AR +133492,Eckerd College,Saint Petersburg,FL +460215,Ecotech Institute,Aurora,CO +248934,ECPI University,Virginia Beach,VA +247162,Ecumenical Theological Seminary,Detroit,MI +177278,Eden Theological Seminary,Webster Groves,MO +198491,Edgecombe Community College,Tarboro,NC +238661,Edgewood College,Madison,WI +376321,EDIC College,Caguas,PR +212160,Edinboro University of Pennsylvania,Edinboro,PA +202648,Edison State Community College,Piqua,OH +235103,Edmonds Community College,Lynnwood,WA +243832,EDP Univeristy of Puerto Rico Inc-San Juan,San Juan,PR +241836,EDP University of Puerto Rico Inc-San Sebastian,San Sebastian,PR +442806,Edward Via College of Osteopathic Medicine,Blacksburg,VA +133526,Edward Waters College,Jacksonville,FL +112686,El Camino College-Compton Center,Compton,CA +113980,El Camino Community College District,Torrance,CA +224615,El Centro College,Dallas,TX +224642,El Paso Community College,El Paso,TX +144944,Elgin Community College,Elgin,IL +198507,Elizabeth City State University,Elizabeth City,NC +212197,Elizabethtown College,Elizabethtown,PA +480134,Elizabethtown College School of Continuing and Professional Studies,Elizabethtown,PA +156648,Elizabethtown Community and Technical College,Elizabethtown,KY +153296,Ellsworth Community College,Iowa Falls,IA +144962,Elmhurst College,Elmhurst,IL +190974,Elmira Business Institute,Elmira,NY +190983,Elmira College,Elmira,NY +198516,Elon University,Elon,NC +133553,Embry-Riddle Aeronautical University-Daytona Beach,Daytona Beach,FL +104586,Embry-Riddle Aeronautical University-Prescott,Prescott,AZ +426314,Embry-Riddle Aeronautical University-Worldwide,Daytona Beach,FL +165662,Emerson College,Boston,MA +220136,Emmanuel Christian Seminary,Johnson City,TN +165671,Emmanuel College-Boston,Boston,MA +139630,Emmanuel College-Franklin Springs,Franklin Springs,GA +153302,Emmaus Bible College,Dubuque,IA +232025,Emory & Henry College,Emory,VA +139658,Emory University,Atlanta,GA +114114,Emperor's College of Traditional Oriental Medicine,Santa Monica,CA +114123,Empire College,Santa Rosa,CA +155025,Emporia State University,Emporia,KS +165699,Endicott College,Beverly,MA +101143,Enterprise State Community College,Enterprise,AL +124487,Epic Bible College,Sacramento,CA +165705,Episcopal Divinity School,Cambridge,MA +224712,Episcopal Theological Seminary of the Southwest,Austin,TX +191083,Erie Community College,Buffalo,NY +212434,Erie Institute of Technology Inc,Erie,PA +409254,Erikson Institute,Chicago,IL +217998,Erskine College,Due West,SC +241951,Escuela de Artes Plasticas de Puerto Rico,San Juan,PR +184481,Essex County College,Newark,NJ +384333,Estrella Mountain Community College,Avondale,AZ +200590,ETI Technical College,Niles,OH +144971,Eureka College,Eureka,IL +177339,Evangel University,Springfield,MO +212443,Evangelical Theological Seminary,Myerstown,PA +371982,Everest College-Anaheim,Anaheim,CA +443854,Everest College-Arlington,Arlington,TX +366544,Everest College-Aurora,Aurora,CO +234739,Everest College-Bremerton,Bremerton,WA +438647,Everest College-Chesapeake,Chesapeake,VA +372037,Everest College-City of Industry,City of Industry,CA +126401,Everest College-Colorado Springs,Colorado Springs,CO +442790,Everest College-Dallas,Dallas,TX +363590,Everest College-Everett,Everett,WA +445197,Everest College-Fort Worth,Fort Worth,TX +460358,Everest College-Fort Worth South,Ft Worth,TX +182148,Everest College-Henderson,Henderson,NV +445470,Everest College-McLean,Vienna,VA +447236,Everest College-Mesa,Mesa,AZ +232502,Everest College-Newport News,Newport News,VA +440299,Everest College-Ontario Metro,Ontario,CA +103644,Everest College-Phoenix,Phoenix,AZ +210359,Everest College-Portland,Portland,OR +119359,Everest College-Reseda,Reseda,CA +230472,Everest College-Salt Lake City,West Valley City,UT +119508,Everest College-San Bernardino,San Bernardino,CA +179070,Everest College-Springfield,Springfield,MO +444024,Everest College-Tacoma,Tacoma,WA +127787,Everest College-Thornton,Thornton,CO +236993,Everest College-Vancouver,Vancouver,WA +368805,Everest College-West Los Angeles,Los Angeles,CA +237604,Everest Institute-Cross Lanes,Cross Lanes,WV +409670,Everest Institute-Kendall,Miami,FL +443748,Everest Institute-Norcross,Norcross,GA +135957,Everest Institute-North Miami,Miami,FL +212090,Everest Institute-Pittsburgh,Pittsburgh,PA +194967,Everest Institute-Rochester,Rochester,NY +260293,Everest University-Brandon,Tampa,FL +438902,Everest University-Jacksonville,Jacksonville,FL +367909,Everest University-Lakeland,Lakeland,FL +137810,Everest University-Largo,Largo,FL +420006,Everest University-Melbourne,Melbourne,FL +136288,Everest University-North Orlando,Orlando,FL +445434,Everest University-Orange Park,Orange Park,FL +134149,Everest University-Pompano Beach,Pompano Beach,FL +390701,Everest University-South Orlando,Orlando,FL +137801,Everest University-Tampa,Tampa,FL +235149,Everett Community College,Everett,WA +385619,Everglades University,Boca Raton,FL +114266,Evergreen Valley College,San Jose,CA +196680,Excelsior College,Albany,NY +447458,Expression College for Digital Arts,Emeryville,CA +129242,Fairfield University,Fairfield,CT +184694,Fairleigh Dickinson University-College at Florham,Madison,NJ +184603,Fairleigh Dickinson University-Metropolitan Campus,Teaneck,NJ +237367,Fairmont State University,Fairmont,WV +153320,Faith Baptist Bible College and Theological Seminary,Ankeny,IA +443049,Faith Evangelical College & Seminary,Tacoma,WA +212452,Faith Theological Seminary,Baltimore,MD +443058,Family of Faith College,Shawnee,OK +196042,Farmingdale State College,Farmingdale,NY +114354,Fashion Institute of Design & Merchandising-Los Angeles,Los Angeles,CA +248846,Fashion Institute of Design & Merchandising-San Diego,San Diego,CA +114390,Fashion Institute of Design & Merchandising-San Francisco,San Francisco,CA +191126,Fashion Institute of Technology,New York,NY +101189,Faulkner University,Montgomery,AL +198543,Fayetteville State University,Fayetteville,NC +198534,Fayetteville Technical Community College,Fayetteville,NC +114433,Feather River Community College District,Quincy,CA +184612,Felician University,Lodi,NJ +169910,Ferris State University,Big Rapids,MI +232089,Ferrum College,Ferrum,VA +114549,Fielding Graduate University,Santa Barbara,CA +436599,FINE Mortuary College,Norwood,MA +191199,Finger Lakes Community College,Canandaigua,NY +475422,Finger Lakes Health College of Nursing,Geneva,NY +172440,Finlandia University,Hancock,MI +165802,Fisher College,Boston,MA +220181,Fisk University,Nashville,TN +165820,Fitchburg State University,Fitchburg,MA +114585,Five Branches University,Santa Cruz,CA +191205,Five Towns College,Dix Hills,NY +133711,Flagler College-St Augustine,Saint Augustine,FL +444990,Flagler College-Tallahassee,Tallahassee,FL +180197,Flathead Valley Community College,Kalispell,MT +160481,Fletcher Technical Community College,Schriever,LA +155052,Flint Hills Technical College,Emporia,KS +218025,Florence-Darlington Technical College,Florence,SC +133650,Florida Agricultural and Mechanical University,Tallahassee,FL +133669,Florida Atlantic University,Boca Raton,FL +133997,Florida Career College-Miami,Miami,FL +434715,Florida Coastal School of Law,Jacksonville,FL +133809,Florida College,Temple Terrace,FL +434441,Florida College of Integrative Medicine,Orlando,FL +438294,Florida College of Natural Health-Bradenton,Bradenton,FL +438285,Florida College of Natural Health-Maitland,Maitland,FL +420103,Florida College of Natural Health-Miami,Miami,FL +387925,Florida College of Natural Health-Pompano Beach,Pompano Beach,FL +135160,Florida Gateway College,Lake City,FL +433660,Florida Gulf Coast University,Fort Myers,FL +133881,Florida Institute of Technology,Melbourne,FL +480569,Florida Institute of Technology-Online,Melbourne,FL +133951,Florida International University,Miami,FL +133960,Florida Keys Community College,Key West,FL +133979,Florida Memorial University,Miami Gardens,FL +408844,Florida National University-Main Campus,Hialeah,FL +134079,Florida Southern College,Lakeland,FL +133508,Florida SouthWestern State College,Fort Myers,FL +133702,Florida State College at Jacksonville,Jacksonville,FL +134097,Florida State University,Tallahassee,FL +134112,Florida Technical College,Orlando,FL +444219,Folsom Lake College,Folsom,CA +380368,Fond du Lac Tribal and Community College,Cloquet,MN +177418,Fontbonne University,Saint Louis,MO +114716,Foothill College,Los Altos Hills,CA +191241,Fordham University,Bronx,NY +177427,Forest Institute of Professional Psychology,Springfield,MO +218043,Forrest College,Anderson,SC +198552,Forsyth Technical Community College,Winston Salem,NC +155061,Fort Hays State University,Hays,KS +127185,Fort Lewis College,Durango,CO +180212,Fort Peck Community College,Poplar,MT +155098,Fort Scott Community College,Fort Scott,KS +139719,Fort Valley State University,Fort Valley,GA +439738,Fortis College-Baton Rouge,Baton Rouge,LA +205179,Fortis College-Centerville,Centerville,OH +450067,Fortis College-Cincinnati,Cincinnati,OH +460020,Fortis College-Columbia,Columbia,SC +450058,Fortis College-Columbus,Westerville,OH +480143,Fortis College-Cutler Bay,Cutler Bay,FL +204307,Fortis College-Cuyahoga Falls,Cuyahoga Falls,OH +458681,Fortis College-Indianapolis,Indianapolis,IN +451909,Fortis College-Landover,Landover,MD +447360,Fortis College-Largo,Largo,FL +371052,Fortis College-Mobile,Mobile,AL +455488,Fortis College-Montgomery-Montgomery,Montgomery,AL +233329,Fortis College-Norfolk,Norfolk,VA +439792,Fortis College-Orange Park,Orange Park,FL +456180,Fortis College-Phoenix,Phoenix,AZ +201399,Fortis College-Ravenna,Ravenna,OH +382957,Fortis College-Richmond,Richmond,VA +456454,Fortis College-Salt Lake City,Salt Lake City,UT +372921,Fortis College-Smyrna,Smyrna,GA +132806,Fortis College-Winter Park,Winter Park,FL +442745,Fortis Institute,Palm Springs,FL +455628,Fortis Institute-Birmingham,Birmingham,AL +418870,Fortis Institute-Cookeville,Cookeville,TN +216418,Fortis Institute-Erie,Erie,PA +443438,Fortis Institute-Fort Lauderdale,Lauderdale Lakes,FL +249609,Fortis Institute-Forty Fort,Forty Fort,PA +445753,Fortis Institute-Miami,Miami,FL +452124,Fortis Institute-Nashville,Nashville,TN +455479,Fortis Institute-Pensacola,Pensacola,FL +445744,Fortis Institute-Port Saint Lucie,Port Saint Lucie,FL +385503,Fortis Institute-Scranton,Scranton,PA +221795,Fountainhead College of Technology,Knoxville,TN +415774,Four-D College,Colton,CA +145239,Fox College,Bedford Park,IL +238722,Fox Valley Technical College,Appleton,WI +165866,Framingham State University,Framingham,MA +218061,Francis Marion University,Florence,SC +114734,Franciscan School of Theology,Oceanside,CA +205957,Franciscan University of Steubenville,Steubenville,OH +104665,Frank Lloyd Wright School of Architecture,Scottsdale,AZ +224891,Frank Phillips College,Borger,TX +212577,Franklin and Marshall College,Lancaster,PA +150604,Franklin College,Franklin,IN +182795,Franklin Pierce University,Rindge,NH +202806,Franklin University,Columbus,OH +441982,Franklin W Olin College of Engineering,Needham,MA +162557,Frederick Community College,Frederick,MD +220215,Freed-Hardeman University,Henderson,TN +372073,Fremont College,Cerritos,CA +114789,Fresno City College,Fresno,CA +114813,Fresno Pacific University,Fresno,CA +155089,Friends University,Wichita,KS +127200,Front Range Community College,Westminster,CO +403469,Frontier Community College,Fairfield,IL +156727,Frontier Nursing University,Hyden,KY +162584,Frostburg State University,Frostburg,MD +134237,Full Sail University,Winter Park,FL +114840,Fuller Theological Seminary in California,Pasadena,CA +114859,Fullerton College,Fullerton,CA +191302,Fulton-Montgomery Community College,Johnstown,NY +218070,Furman University,Greenville,SC +481030,Future Generations Graduate School,Franklin,WV +101240,Gadsden State Community College,Gadsden,AL +452948,Galen College of Nursing-Cincinnati,Cincinnati,OH +156471,Galen College of Nursing-Louisville,Louisville,KY +406033,Galen College of Nursing-San Antonio,San Antonio,TX +406024,Galen College of Nursing-Tampa Bay,Saint Petersburg,FL +131450,Gallaudet University,Washington,DC +205513,Gallipolis Career College,Gallipolis,OH +224961,Galveston College,Galveston,TX +212601,Gannon University,Erie,PA +155104,Garden City Community College,Garden City,KS +198561,Gardner-Webb University,Boiling Springs,NC +162609,Garrett College,McHenry,MD +145275,Garrett-Evangelical Theological Seminary,Evanston,IL +198570,Gaston College,Dallas,NC +157438,Gateway Community and Technical College,Florence,KY +130396,Gateway Community College-New Haven,New Haven,CT +105145,GateWay Community College-Phoenix,Phoenix,AZ +238759,Gateway Technical College,Kenosha,WI +114938,Gavilan College,Gilroy,CA +191339,Genesee Community College,Batavia,NY +212656,Geneva College,Beaver Falls,PA +101286,George C Wallace State Community College-Dothan,Dothan,AL +101295,George C Wallace State Community College-Hanceville,Hanceville,AL +101301,George C Wallace State Community College-Selma,Selma,AL +208822,George Fox University,Newberg,OR +232186,George Mason University,Fairfax,VA +131469,George Washington University,Washington,DC +156745,Georgetown College,Georgetown,KY +131496,Georgetown University,Washington,DC +461236,Georgia Christian University,Atlanta,GA +139861,Georgia College and State University,Milledgeville,GA +447689,Georgia Gwinnett College,Lawrenceville,GA +139700,Georgia Highlands College,Rome,GA +139755,Georgia Institute of Technology-Main Campus,Atlanta,GA +485111,Georgia Military College-Milledgeville,Milledgeville,GA +139384,Georgia Northwestern Technical College,Rome,GA +244437,Georgia Perimeter College,Decatur,GA +244446,Georgia Piedmont Technical College,Clarkston,GA +139931,Georgia Southern University,Statesboro,GA +139764,Georgia Southwestern State University,Americus,GA +139940,Georgia State University,Atlanta,GA +184773,Georgian Court University,Lakewood,NJ +232195,Germanna Community College,Locust Grove,VA +212674,Gettysburg College,Gettysburg,PA +169974,Glen Oaks Community College,Centreville,MI +104708,Glendale Community College-Glendale,Glendale,AZ +115001,Glendale Community College-Glendale,Glendale,CA +237385,Glenville State College,Glenville,WV +455390,Global Health College,Alexandria,VA +188465,Globe Institute of Technology,New York,NY +466514,Globe University-Appleton,Grand Chute,WI +456816,Globe University-Eau Claire,Eau Claire,WI +458751,Globe University–Green Bay,Green Bay,WI +458991,Globe University-La Crosse,Onalaska,WI +458733,Globe University-Madison East,Madison,WI +458760,Globe University–Madison West,Middleton,WI +456834,Globe University-Minneapolis,Minneapolis,MN +456807,Globe University-Sioux Falls,Sioux Falls,SD +458779,Globe University–Wausau,Rothschild,WI +173629,Globe University-Woodbury,Woodbury,MN +230889,Goddard College,Plainfield,VT +202903,Gods Bible School and College,Cincinnati,OH +169992,Gogebic Community College,Ironwood,MI +115083,Golden Gate University-San Francisco,San Francisco,CA +115126,Golden West College,Huntington Beach,CA +130989,Goldey-Beacom College,Wilmington,DE +430157,Golf Academy of America-Altamonte Springs,Apopka,FL +122366,Golf Academy of America-Carlsbad,Carlsbad,CA +476337,Golf Academy of America-Farmers Branch,Farmers Branch,TX +434690,Golf Academy of America-Myrtle Beach,Myrtle Beach,SC +430166,Golf Academy of America-Phoenix,Chandler,AZ +235316,Gonzaga University,Spokane,WA +202912,Good Samaritan College of Nursing and Health Science,Cincinnati,OH +132523,Gooding Institute of Nurse Anesthesia,Panama City,FL +129154,Goodwin College,East Hartford,CT +165936,Gordon College,Wenham,MA +139968,Gordon State College,Barnesville,GA +165945,Gordon-Conwell Theological Seminary,South Hamilton,MA +150668,Goshen College,Goshen,IN +162654,Goucher College,Baltimore,MD +145336,Governors State University,University Park,IL +170000,Grace Bible College,Wyoming,MI +150677,Grace College and Theological Seminary,Winona Lake,IN +461528,Grace College of Divinity,Fayetteville,NC +481058,Grace Mission University,Fullerton,CA +481401,Grace School of Theology,Conroe,TX +181093,Grace University,Omaha,NE +153366,Graceland University-Lamoni,Lamoni,IA +483285,Graduate School USA,Washington,DC +115214,Graduate Theological Union,Berkeley,CA +159009,Grambling State University,Grambling,LA +104717,Grand Canyon University,Phoenix,AZ +170055,Grand Rapids Community College,Grand Rapids,MI +170082,Grand Valley State University,Allendale,MI +153375,Grand View University,Des Moines,IA +183257,Granite State College,Concord,NH +442569,Grantham University,Lenexa,KS +212771,Gratz College,Melrose Park,PA +235334,Grays Harbor College,Aberdeen,WA +225070,Grayson College,Denison,TX +182306,Great Basin College,Elko,NV +183150,Great Bay Community College,Portsmouth,NH +180249,Great Falls College Montana State University,Great Falls,MT +170091,Great Lakes Christian College,Lansing,MI +213181,Great Lakes Institute of Technology,Erie,PA +230898,Green Mountain College,Poultney,VT +235343,Green River College,Auburn,WA +165981,Greenfield Community College,Greenfield,MA +198598,Greensboro College,Greensboro,NC +145372,Greenville College,Greenville,IL +218113,Greenville Technical College,Greenville,SC +153384,Grinnell College,Grinnell,IA +115296,Grossmont College,El Cajon,CA +212805,Grove City College,Grove City,PA +240745,Guam Community College,Mangilao,GU +198613,Guilford College,Greensboro,NC +198622,Guilford Technical Community College,Jamestown,NC +134343,Gulf Coast State College,Panama City,FL +139995,Gupton Jones College of Funeral Service,Decatur,GA +173647,Gustavus Adolphus College,Saint Peter,MN +140003,Gwinnett College-Lilburn,Lilburn,GA +140012,Gwinnett Technical College,Lawrenceville,GA +212832,Gwynedd Mercy University,Gwynedd Valley,PA +102313,H Councill Trenholm State Community College,Montgomery,AL +162690,Hagerstown Community College,Hagerstown,MD +198640,Halifax Community College,Weldon,NC +225201,Hallmark University,San Antonio,TX +191515,Hamilton College,Clinton,NY +153427,Hamilton Technical College,Davenport,IA +173665,Hamline University,Saint Paul,MN +232256,Hampden-Sydney College,Hampden-Sydney,VA +166018,Hampshire College,Amherst,MA +232265,Hampton University,Hampton,VA +177542,Hannibal-LaGrange University,Hannibal,MO +150756,Hanover College,Hanover,IN +212869,Harcum College,Bryn Mawr,PA +107044,Harding University,Searcy,AR +225247,Hardin-Simmons University,Abilene,TX +162706,Harford Community College,Bel Air,MD +145460,Harrington College of Design,Chicago,IL +212878,Harrisburg Area Community College-Harrisburg,Harrisburg,PA +446640,Harrisburg University of Science and Technology,Harrisburg,PA +458432,Harrison College-Grove City,Grove City,OH +151166,Harrison College-Indianapolis,Indianapolis,IN +468398,Harrison College-Morrisville,Morrisville,NC +177551,Harris-Stowe State University,Saint Louis,MO +129491,Hartford Seminary,Hartford,CT +115393,Hartnell College,Salinas,CA +191533,Hartwick College,Oneonta,NY +166027,Harvard University,Cambridge,MA +115409,Harvey Mudd College,Claremont,CA +155140,Haskell Indian Nations University,Lawrence,KS +181127,Hastings College,Hastings,NE +212911,Haverford College,Haverford,PA +383190,Hawaii Community College,Hilo,HI +141644,Hawaii Pacific University,Honolulu,HI +153445,Hawkeye Community College,Waterloo,IA +198668,Haywood Community College,Clyde,NC +156790,Hazard Community and Technical College,Hazard,KY +173683,Hazelden Betty Ford Graduate School of Addiction Studies,Center City,MN +115533,Heald College-Concord,Concord,CA +115472,Heald College-Fresno,Fresno,CA +371779,Heald College-Hayward,Hayward,CA +141468,Heald College-Honolulu,Honolulu,HI +459930,Heald College-Modesto,Salida,CA +430148,Heald College-Portland,Portland,OR +115454,Heald College-Rancho Cordova,Rancho Cordova,CA +363387,Heald College-Roseville,Roseville,CA +409874,Heald College-Salinas,Salinas,CA +115515,Heald College-San Francisco,San Francisco,CA +115490,Heald College-San Jose,Milpitas,CA +371760,Heald College-Stockton,Stockton,CA +384342,Heartland Community College,Normal,IL +166045,Hebrew College,Newton Centre,MA +145497,Hebrew Theological College,Skokie,IL +203067,Hebrew Union College-Jewish Institute of Religion,New York,NY +203085,Heidelberg University,Tiffin,OH +180276,Helena College University of Montana,Helena,MT +191597,Helene Fuld College of Nursing,New York,NY +166054,Hellenic College-Holy Cross Greek Orthodox School of Theology,Brookline,MA +156851,Henderson Community College,Henderson,KY +107071,Henderson State University,Arkadelphia,AR +107080,Hendrix College,Conway,AR +173708,Hennepin Technical College,Brooklyn Park,MN +170240,Henry Ford College,Dearborn,MI +198677,Heritage Bible College,Dunn,NC +101453,Heritage Christian University,Florence,AL +262509,Heritage College-Denver,Denver,CO +445814,Heritage College-Kansas City,Kansas City,MO +410070,Heritage College-Oklahoma City,Oklahoma City,OK +456320,Heritage College-Wichita,Wichita,KS +135124,Heritage Institute-Ft Myers,Fort Myers,FL +372772,Heritage Institute-Jacksonville,Jacksonville,FL +235422,Heritage University,Toppenish,WA +191612,Herkimer County Community College,Herkimer,NY +140340,Herzing University-Atlanta,Atlanta,GA +101365,Herzing University-Birmingham,Birmingham,AL +459851,Herzing University-Brookfield,Brookfield,WI +433536,Herzing University-Kenner,Kenner,LA +459842,Herzing University-Kenosha,Kenosha,WI +240392,Herzing University-Madison,Madison,WI +174154,Herzing University-Minneapolis,Minneapolis,MN +457022,Herzing University-Toledo,Toledo,OH +386472,Herzing University-Winter Park,Winter Park,FL +155177,Hesston College,Hesston,KS +173735,Hibbing Community College,Hibbing,MN +177579,Hickey College,Saint Louis,MO +198695,High Point University,High Point,NC +145521,Highland Community College-Freeport,Freeport,IL +155186,Highland Community College-Highland,Highland,KS +180081,Highlands College of Montana Tech,Butte,MT +235431,Highline College,Des Moines,WA +191621,Hilbert College,Hamburg,NY +225371,Hill College,Hillsboro,TX +134495,Hillsborough Community College,Tampa,FL +170286,Hillsdale College,Hillsdale,MI +207157,Hillsdale Free Will Baptist College,Moore,OK +175786,Hinds Community College,Raymond,MS +203128,Hiram College,Hiram,OH +220312,Hiwassee College,Madisonville,TN +191630,Hobart William Smith Colleges,Geneva,NY +134510,Hobe Sound Bible College,Hobe Sound,FL +203155,Hocking College,Nelsonville,OH +367884,Hodges University,Naples,FL +191649,Hofstra University,Hempstead,NY +232308,Hollins University,Roanoke,VA +175810,Holmes Community College,Goodman,MS +129534,Holy Apostles College and Seminary,Cromwell,CT +150774,Holy Cross College,Notre Dame,IN +212984,Holy Family University,Philadelphia,PA +115728,Holy Names University,Oakland,CA +166133,Holyoke Community College,Holyoke,MA +203386,Hondros College,Westerville,OH +141680,Honolulu Community College,Honolulu,HI +162760,Hood College,Frederick,MD +443076,Hood Theological Seminary,Salisbury,NC +170301,Hope College,Holland,MI +120537,Hope International University,Fullerton,CA +156860,Hopkinsville Community College,Hopkinsville,KY +457226,Horizon University,San Diego,CA +218140,Horry-Georgetown Technical College,Conway,SC +191676,Houghton College,Houghton,NY +129543,Housatonic Community College,Bridgeport,CT +225399,Houston Baptist University,Houston,TX +225423,Houston Community College,Houston,TX +246345,Houston Graduate School of Theology,Houston,TX +225520,Howard College,Big Spring,TX +162779,Howard Community College,Columbia,MD +225548,Howard Payne University,Brownwood,TX +131520,Howard University,Washington,DC +184995,Hudson County Community College,Jersey City,NJ +191719,Hudson Valley Community College,Troy,NY +242112,Huertas College,Caguas,PR +164368,Hult International Business School,Cambridge,MA +242121,Humacao Community College,Humacao,PR +115755,Humboldt State University,Arcata,CA +115773,Humphreys College-Stockton and Modesto Campuses,Stockton,CA +101435,Huntingdon College,Montgomery,AL +237437,Huntington Junior College,Huntington,WV +150941,Huntington University,Huntington,IN +449348,Huntsville Bible College,Huntsville,AL +212993,Hussian College School of Art,Philadelphia,PA +161165,Husson University,Bangor,ME +225575,Huston-Tillotson University,Austin,TX +155195,Hutchinson Community College,Hutchinson,KS +127839,IBMC College,Colorado Springs,CO +372329,IBMC College,Fort Collins,CO +193405,Icahn School of Medicine at Mount Sinai,New York,NY +437662,ICDC College,Huntington Park,CA +242130,ICPR Junior College-Arecibo,Arecibo,PR +243841,ICPR Junior College-General Institutional,Hato Rey,PR +460677,ICPR Junior College-Manati,Manatí,PR +242149,ICPR Junior College-Mayaguez,Mayaguez,PR +142276,Idaho State University,Pocatello,ID +483780,IGlobal University,Annandale,VA +127273,Iliff School of Theology,Denver,CO +434584,Ilisagvik College,Barrow,AK +145682,Illinois Central College,East Peoria,IL +145691,Illinois College,Jacksonville,IL +145628,Illinois College of Optometry,Chicago,IL +145725,Illinois Institute of Technology,Chicago,IL +145813,Illinois State University,Normal,IL +145831,Illinois Valley Community College,Oglesby,IL +145646,Illinois Wesleyan University,Bloomington,IL +213011,Immaculata University,Immaculata,PA +115861,Imperial Valley College,Imperial,CA +155201,Independence Community College,Independence,KS +465812,Independence University,Salt Lake City,UT +153472,Indian Hills Community College,Ottumwa,IA +134608,Indian River State College,Fort Pierce,FL +151290,Indiana Institute of Technology,Fort Wayne,IN +151324,Indiana State University,Terre Haute,IN +213020,Indiana University of Pennsylvania-Main Campus,Indiana,PA +151351,Indiana University-Bloomington,Bloomington,IN +151388,Indiana University-East,Richmond,IN +151333,Indiana University-Kokomo,Kokomo,IN +151360,Indiana University-Northwest,Gary,IN +151102,Indiana University-Purdue University-Fort Wayne,Fort Wayne,IN +151111,Indiana University-Purdue University-Indianapolis,Indianapolis,IN +151342,Indiana University-South Bend,South Bend,IN +151379,Indiana University-Southeast,New Albany,IN +151801,Indiana Wesleyan University,Marion,IN +145886,Institute for Clinical Social Work,Chicago,IL +462044,Institute for Doctoral Studies in the Visual Arts,Portland,ME +445869,Institute for the Psychological Sciences,Arlington,VA +187745,Institute of American Indian and Alaska Native Culture,Santa Fe,NM +444699,Institute of Clinical Acupuncture & Oriental Med,Honolulu,HI +191764,Institute of Design and Construction,Brooklyn,NY +454616,Institute of Production and Recording,Minneapolis,MN +454838,Institute of Taoist Education and Acupuncture,Louisville,CO +431141,Institute of Technology Inc-Clovis,Clovis,CA +455804,Institute of World Politics,Washington,DC +242422,Instituto de Banca y Comercio Inc,Guaynabo,PR +242556,Instituto Tecnologico de Puerto Rico-Recinto de Guayama,Guayama,PR +242042,Instituto Tecnologico de Puerto Rico-Recinto de Manati,Manati,PR +242565,Instituto Tecnologico de Puerto Rico-Recinto de Ponce,Ponce,PR +242583,Instituto Tecnologico de Puerto Rico-Recinto de San Juan,San Juan,PR +128179,Intellitec College-Colorado Springs,Colorado Springs,CO +128188,Intellitec College-Grand Junction,Grand Junction,CO +242626,Inter American University of Puerto Rico-Aguadilla,Aguadilla,PR +242635,Inter American University of Puerto Rico-Arecibo,Arecibo,PR +242644,Inter American University of Puerto Rico-Barranquitas,Barranquitas,PR +242705,Inter American University of Puerto Rico-Bayamon,Bayamon,PR +242680,Inter American University of Puerto Rico-Fajardo,Fajardo,PR +242699,Inter American University of Puerto Rico-Guayama,Guayama,PR +242653,Inter American University of Puerto Rico-Metro,San Juan,PR +242662,Inter American University of Puerto Rico-Ponce,Mercedita,PR +242617,Inter American University of Puerto Rico-San German,San German,PR +242723,Inter American University of Puerto Rico-School of Law,San Juan,PR +404222,Inter American University of Puerto Rico-School of Optometry,Bayamon,PR +138655,Interactive College of Technology-Chamblee,Chamblee,GA +442435,Interactive College of Technology-Gainesville,Gainesville,GA +367361,Interactive College of Technology-Houston,Houston,TX +443696,Interactive College of Technology-Houston,Houston,TX +138664,Interactive College of Technology-Morrow,Morrow,GA +367103,Interactive College of Technology-Newport,Newport,KY +440776,Interactive College of Technology-Pasadena,Pasadena,TX +366289,InterCoast Colleges-Orange,Orange,CA +140146,Interdenominational Theological Center,Atlanta,GA +235495,Interface College-Spokane,Spokane,WA +116226,Interior Designers Institute,Newport Beach,CA +446817,International Academy of Design and Technology-Nashville,Nashville,TN +450447,International Academy of Design and Technology-Sacramento,Sacramento,CA +445124,International Academy of Design and Technology-Troy,Troy,MI +436614,International Baptist College and Seminary,Chandler,AZ +225779,International Business College-El Paso-El Paso,El Paso,TX +225788,International Business College-El Paso-El Paso,El Paso,TX +151458,International Business College-Fort Wayne,Fort Wayne,IN +151467,International Business College-Indianapolis,Indianapolis,IN +203289,International College of Broadcasting,Dayton,OH +448691,International Institute for Restorative Practices,Bethlehem,PA +454740,International Professional School of Bodywork,San Diego,CA +443128,International Technological University,San Jose,CA +173799,Inver Hills Community College,Inver Grove Heights,MN +191931,Iona College,New Rochelle,NY +153524,Iowa Central Community College,Fort Dodge,IA +153533,Iowa Lakes Community College,Estherville,IA +153603,Iowa State University,Ames,IA +153621,Iowa Wesleyan University,Mount Pleasant,IA +153630,Iowa Western Community College,Council Bluffs,IA +441238,Irell & Manella Graduate School of Biological Sciences at City of Hope,Duarte,CA +116439,Irvine Valley College,Irvine,CA +191959,Island Drafting and Technical Institute,Amityville,NY +198710,Isothermal Community College,Spindale,NC +173805,Itasca Community College,Grand Rapids,MN +175829,Itawamba Community College,Fulton,MS +191968,Ithaca College,Ithaca,NY +159197,ITI Technical College,Baton Rouge,LA +459611,ITT Technical Institute-Akron,Akron,OH +434566,ITT Technical Institute-Albany,Albany,NY +369084,ITT Technical Institute-Albuquerque,Albuquerque,NM +225849,ITT Technical Institute-Arlington,Arlington,TX +260974,ITT Technical Institute-Arlington Heights,Arlington Heights,IL +434548,ITT Technical Institute-Arnold,Arnold,MO +450243,ITT Technical Institute-Atlanta,Atlanta,GA +459675,ITT Technical Institute-Aurora,Aurora,CO +366678,ITT Technical Institute-Austin,Austin,TX +450216,ITT Technical Institute-Baton Rouge,Baton Rouge,LA +414568,ITT Technical Institute-Bessemer,Bessemer,AL +142337,ITT Technical Institute-Boise,Boise,ID +470852,ITT Technical Institute-Bradenton,Bradenton,FL +470870,ITT Technical Institute-Brooklyn Center,Brooklyn Center,MN +442338,ITT Technical Institute-Canton,Canton,MI +451936,ITT Technical Institute-Cary,Cary,NC +441964,ITT Technical Institute-Chantilly,Chantilly,VA +456445,ITT Technical Institute-Charlotte North,Charlotte,NC +448442,ITT Technical Institute-Charlotte South,Charlotte,NC +450261,ITT Technical Institute-Chattanooga,Chattanooga,TN +451954,ITT Technical Institute-Clive,Clive,IA +448451,ITT Technical Institute-Clovis,Clovis,CA +450225,ITT Technical Institute-Columbia,Columbia,SC +451963,ITT Technical Institute-Columbus,Columbus,OH +456427,ITT Technical Institute-Concord,Concord,CA +413884,ITT Technical Institute-Cordova,Cordova,TN +459639,ITT Technical Institute-Corona,Corona,CA +459693,ITT Technical Institute-Culver City,Culver City,CA +203313,ITT Technical Institute-Dayton,Dayton,OH +459709,ITT Technical Institute-Dearborn,Dearborn,MI +479619,ITT Technical Institute-Deerfield Beach,Fort Lauderdale,FL +459657,ITT Technical Institute-DeSoto,DeSoto,TX +479637,ITT Technical Institute-Douglasville,Douglasville,GA +443526,ITT Technical Institute-Duluth,Duluth,GA +448460,ITT Technical Institute-Dunmore,Dunmore,PA +462363,ITT Technical Institute-Durham,Durham,NC +176637,ITT Technical Institute-Earth City,Earth City,MO +445081,ITT Technical Institute-Eden Prairie,Eden Prairie,MN +414531,ITT Technical Institute-Everett,Everett,WA +409069,ITT Technical Institute-Fort Lauderdale,Fort Lauderdale,FL +456436,ITT Technical Institute-Fort Myers,Fort Myers,FL +151500,ITT Technical Institute-Fort Wayne,Fort Wayne,IN +479567,ITT Technical Institute-Germantown,Greenfield,WI +420404,ITT Technical Institute-Getzville,Getzville,NY +440165,ITT Technical Institute-Green Bay,Green Bay,WI +238892,ITT Technical Institute-Greenfield,Greenfield,WI +413866,ITT Technical Institute-Greenville,Greenville,SC +462372,ITT Technical Institute-Hanover,Hanover,MD +430351,ITT Technical Institute-Harrisburg,Harrisburg,PA +429599,ITT Technical Institute-Henderson,Henderson,NV +430263,ITT Technical Institute-Hialeah,Hialeah,FL +451990,ITT Technical Institute-High Point,High Point,NC +443535,ITT Technical Institute-Hilliard,Hilliard,OH +366696,ITT Technical Institute-Houston North,Houston,TX +225858,ITT Technical Institute-Houston West,Houston,TX +456418,ITT Technical Institute-Huntington,Huntington,WV +151519,ITT Technical Institute-Indianapolis,Indianapolis,IN +479628,ITT Technical Institute-Indianapolis East,Indianapolis,IN +407063,ITT Technical Institute-Jacksonville,Jacksonville,FL +459648,ITT Technical Institute-Johnson City,Johnson City,TN +446899,ITT Technical Institute-Kansas City,Kansas City,MO +446905,ITT Technical Institute-Kennesaw,Kennesaw,GA +366650,ITT Technical Institute-Knoxville,Knoxville,TN +372578,ITT Technical Institute-Lake Mary,Lake Mary,FL +459718,ITT Technical Institute-Las Vegas,North Las Vegas,NV +437219,ITT Technical Institute-Lathrop,Lathrop,CA +440642,ITT Technical Institute-Levittown,Levittown,PA +448488,ITT Technical Institute-Lexington,Lexington,KY +413839,ITT Technical Institute-Little Rock,Little Rock,AR +434575,ITT Technical Institute-Liverpool,Liverpool,NY +413857,ITT Technical Institute-Louisville,Louisville,KY +451945,ITT Technical Institute-Madison-Madison,Madison,AL +451981,ITT Technical Institute-Madison-Madison,Madison,WI +456393,ITT Technical Institute-Madison-Madison,Madison,MS +479558,ITT Technical Institute-Marlton,Marlton,NJ +448497,ITT Technical Institute-Maumee,Maumee,OH +459587,ITT Technical Institute-Merrillville,Merrillville,IN +450252,ITT Technical Institute-Mobile,Mobile,AL +230384,ITT Technical Institute-Murray,Murray,UT +470904,ITT Technical Institute-Myrtle Beach,Myrtle Beach,SC +151494,ITT Technical Institute-Nashville,Nashville,TN +116466,ITT Technical Institute-National City,National City,CA +251251,ITT Technical Institute-Newburgh,Newburgh,IN +368601,ITT Technical Institute-Norfolk,Norfolk,VA +459666,ITT Technical Institute-North Charleston,North Charleston,SC +366580,ITT Technical Institute-Norwood-Norwood,Norwood,MA +430379,ITT Technical Institute-Norwood-Norwood,Norwood,OH +434557,ITT Technical Institute-Oak Brook,Oak Brook,IL +467058,ITT Technical Institute-Oakland,Oakland,CA +448503,ITT Technical Institute-Oklahoma City,Oklahoma City,OK +407319,ITT Technical Institute-Omaha,Omaha,NE +116484,ITT Technical Institute-Orange,Orange,CA +414586,ITT Technical Institute-Orland Park,Orland Park,IL +470889,ITT Technical Institute-Orlando,Lake Mary,FL +479646,ITT Technical Institute-Overland Park,Overland Park,KS +446914,ITT Technical Institute-Owings Mills,Owings Mills,MD +413848,ITT Technical Institute-Oxnard,Oxnard,CA +479549,ITT Technical Institute-Philadelphia,Philadelphia,PA +451972,ITT Technical Institute-Phoenix,Phoenix,AZ +470861,ITT Technical Institute-Phoenix West,Phoenix,AZ +414841,ITT Technical Institute-Pittsburgh,Pittsburgh,PA +442347,ITT Technical Institute-Plymouth Meeting,Plymouth Meeting,PA +208965,ITT Technical Institute-Portland,Portland,OR +108250,ITT Technical Institute-Rancho Cordova,Rancho Cordova,CA +434052,ITT Technical Institute-Richardson,Richardson,TX +437051,ITT Technical Institute-Richmond,Richmond,VA +437042,ITT Technical Institute-Saint Rose,Saint Rose,LA +459602,ITT Technical Institute-Salem-Salem,Salem,VA +479600,ITT Technical Institute-Salem-Salem,Salem,OR +377069,ITT Technical Institute-San Antonio,San Antonio,TX +481623,ITT Technical Institute-San Antonio East,San Antonio,TX +381909,ITT Technical Institute-San Bernardino,San Bernardino,CA +116475,ITT Technical Institute-San Dimas,San Dimas,CA +235510,ITT Technical Institute-Seattle,Seattle,WA +450270,ITT Technical Institute-South Bend,South Bend,IN +479585,ITT Technical Institute-Southfield,Troy,MI +235529,ITT Technical Institute-Spokane Valley,Spokane Valley,WA +441955,ITT Technical Institute-Springfield-Springfield,Springfield,VA +456409,ITT Technical Institute-Springfield-Springfield,Springfield,MO +479655,ITT Technical Institute-Springfield-Springfield,Springfield,IL +450207,ITT Technical Institute-St Petersburg,Tampa,FL +430388,ITT Technical Institute-Strongsville,Strongsville,OH +448479,ITT Technical Institute-Swartz Creek,Swartz Creek,MI +244011,ITT Technical Institute-Sylmar,Sylmar,CA +459596,ITT Technical Institute-Tallahassee,Tallahassee,FL +134909,ITT Technical Institute-Tampa,Tampa,FL +430360,ITT Technical Institute-Tarentum,Tarentum,PA +105172,ITT Technical Institute-Tempe,Tempe,AZ +378406,ITT Technical Institute-Torrance,Torrance,CA +261472,ITT Technical Institute-Troy,Troy,MI +105163,ITT Technical Institute-Tucson,Tucson,AZ +448512,ITT Technical Institute-Tulsa,Tulsa,OK +470898,ITT Technical Institute-Waco,Waco,TX +446923,ITT Technical Institute-Warrensville Heights,Warrensville Heights,OH +427663,ITT Technical Institute-Webster,Webster,TX +479664,ITT Technical Institute-West Chester,Norwood,OH +459684,ITT Technical Institute-West Covina,San Dimas,CA +479594,ITT Technical Institute-West Palm Beach,West Palm Beach,FL +244154,ITT Technical Institute-Westminster,Westminster,CO +450234,ITT Technical Institute-Wichita,Wichita,KS +439136,ITT Technical Institute-Wilmington,Wilmington,MA +170417,ITT Technical Institute-Wyoming,Wyoming,MI +206631,ITT Technical Institute-Youngstown,Youngstown,OH +150987,Ivy Tech Community College,Indianapolis,IN +101462,J F Drake State Community and Technical College,Huntsville,AL +101471,J F Ingram State Technical College,Deatsville,AL +232414,J Sargeant Reynolds Community College,Richmond,VA +170444,Jackson College,Jackson,MI +220400,Jackson State Community College,Jackson,TN +175856,Jackson State University,Jackson,MS +225876,Jacksonville College-Main Campus,Jacksonville,TX +101480,Jacksonville State University,Jacksonville,AL +134945,Jacksonville University,Jacksonville,FL +203678,James A Rhodes State College,Lima,OH +101161,James H Faulkner State Community College,Bay Minette,AL +232423,James Madison University,Harrisonburg,VA +198729,James Sprunt Community College,Kenansville,NC +192004,Jamestown Business College,Jamestown,NY +191986,Jamestown Community College,Jamestown,NY +225885,Jarvis Christian College,Hawkins,TX +177676,Jefferson College,Hillsboro,MO +231837,Jefferson College of Health Sciences,Roanoke,VA +156921,Jefferson Community and Technical College,Louisville,KY +192022,Jefferson Community College,Watertown,NY +101499,Jefferson Davis Community College,Brewton,AL +101505,Jefferson State Community College,Birmingham,AL +455196,Jersey College,Teterboro,NJ +192040,Jewish Theological Seminary of America,New York,NY +419341,Jna Institute of Culinary Arts,Philadelphia,PA +220464,John A Gupton College,Nashville,TN +146205,John A Logan College,Carterville,IL +107141,John Brown University,Siloam Springs,AR +101514,John C Calhoun State Community College,Tanner,AL +203368,John Carroll University,University Heights,OH +116712,John F. Kennedy University,Pleasant Hill,CA +462354,John Paul the Great Catholic University,Escondido,CA +232450,John Tyler Community College,Chester,VA +146278,John Wood Community College,Quincy,IL +162928,Johns Hopkins University,Baltimore,MD +445708,Johnson & Wales University-Charlotte,Charlotte,NC +439288,Johnson & Wales University-Denver,Denver,CO +414823,Johnson & Wales University-North Miami,North Miami,FL +460349,Johnson & Wales University-Online,Providence,RI +217235,Johnson & Wales University-Providence,Providence,RI +198756,Johnson C Smith University,Charlotte,NC +213233,Johnson College,Scranton,PA +155210,Johnson County Community College,Overland Park,KS +230913,Johnson State College,Johnson,VT +220473,Johnson University,Knoxville,TN +132879,Johnson University Florida,Kissimmee,FL +198774,Johnston Community College,Smithfield,NC +146296,Joliet Junior College,Joliet,IL +135063,Jones College-Jacksonville,Jacksonville,FL +175883,Jones County Junior College,Ellisville,MS +444723,Jones International University,Centennial,CO +461281,Jose Maria Vargas University,Pembroke Pines,FL +101541,Judson College,Marion,AL +146339,Judson University,Elgin,IL +461139,Jung Tao School of Classical Chinese Medicine,Sugar Grove,NC +213251,Juniata College,Huntingdon,PA +170532,Kalamazoo College,Kalamazoo,MI +170541,Kalamazoo Valley Community College,Kalamazoo,MI +146348,Kankakee Community College,Kankakee,IL +177746,Kansas City Art Institute,Kansas City,MO +155308,Kansas City College & Bible School,Overland Park,KS +155292,Kansas City Kansas Community College,Kansas City,KS +179812,Kansas City University of Medicine and Biosciences,Kansas City,MO +155399,Kansas State University,Manhattan,KS +155414,Kansas Wesleyan University,Salina,KS +141796,Kapiolani Community College,Honolulu,HI +458715,Kaplan College-Jacksonville,Jacksonville,FL +445346,Kaplan College-Lubbock,Lubbock,TX +480064,Kaplan University-Augusta Campus,Augusta,ME +260910,Kaplan University-Cedar Falls Campus,Cedar Falls,IA +153418,Kaplan University-Cedar Rapids Campus,Cedar Rapids,IA +260901,Kaplan University-Davenport Campus,Davenport,IA +367024,Kaplan University-Des Moines Campus,Urbandale,IA +162681,Kaplan University-Hagerstown Campus,Hagerstown,MD +181242,Kaplan University-Lincoln Campus,Lincoln,NE +160940,Kaplan University-Maine Campus,S Portland,ME +153409,Kaplan University-Mason City Campus,Mason City,IA +181400,Kaplan University-Omaha Campus,Omaha,NE +146366,Kaskaskia College,Centralia,IL +141802,Kauai Community College,Lihue,HI +225991,KD College Conservatory of Film and Dramatic Arts,Dallas,TX +185262,Kean University,Union,NJ +440031,Keck Graduate Institute,Claremont,CA +183062,Keene State College,Keene,NH +192165,Kehilath Yakov Rabbinical Seminary,Ossining,NY +135081,Keiser University-Ft Lauderdale,Fort Lauderdale,FL +170550,Kellogg Community College,Battle Creek,MI +146393,Kendall College,Chicago,IL +161192,Kennebec Valley Community College,Fairfield,ME +140164,Kennesaw State University,Kennesaw,GA +177816,Kenrick Glennon Seminary,Saint Louis,MO +203447,Kent State University at Ashtabula,Ashtabula,OH +203456,Kent State University at East Liverpool,East Liverpool,OH +203526,Kent State University at Geauga,Burton,OH +203517,Kent State University at Kent,Kent,OH +203492,Kent State University at Salem,Salem,OH +203465,Kent State University at Stark,Canton,OH +203474,Kent State University at Trumbull,Warren,OH +203483,Kent State University at Tuscarawas,New Philadelphia,OH +157100,Kentucky Christian University,Grayson,KY +157030,Kentucky Mountain Bible College,Vancleve,KY +157058,Kentucky State University,Frankfort,KY +157076,Kentucky Wesleyan College,Owensboro,KY +203535,Kenyon College,Gambier,OH +203544,Kettering College,Kettering,OH +169983,Kettering University,Flint,MI +192192,Keuka College,Keuka Park,NY +461315,Keweenaw Bay Ojibwa Community College,Baraga,MI +134422,Key College,Dania Beach,FL +213303,Keystone College,La Plume,PA +210483,Keystone Technical Institute,Harrisburg,PA +226019,Kilgore College,Kilgore,TX +219055,Kilian Community College,Sioux Falls,SD +220516,King University,Bristol,TN +382504,King's College-Charlotte,Charlotte,NC +213321,King's College-Wilkes-Barre,Wilkes-Barre,PA +153737,Kirkwood Community College,Cedar Rapids,IA +170587,Kirtland Community College,Roscommon,MI +146418,Kishwaukee College,Malta,IL +428392,Klamath Community College,Klamath Falls,OR +260956,Knowledge Systems Institute,Skokie,IL +146427,Knox College,Galesburg,IL +484288,Knox Theological Seminary,Fort Lauderdale,FL +213349,Kutztown University of Pennsylvania,Kutztown,PA +171881,Kuyper College,Grand Rapids,MI +213358,La Roche College,Pittsburgh,PA +213367,La Salle University,Philadelphia,PA +117627,La Sierra University,Riverside,CA +155450,Labette Community College,Parsons,KS +165264,Laboure College,Milton,MA +260372,Lac Courte Oreilles Ojibwa Community College,Hayward,WI +213376,Lackawanna College,Scranton,PA +213385,Lafayette College,Easton,PA +140234,LaGrange College,Lagrange,GA +117168,Laguna College of Art and Design,Laguna Beach,CA +219143,Lake Area Technical Institute,Watertown,SD +203580,Lake Erie College,Painesville,OH +407629,Lake Erie College of Osteopathic Medicine,Erie,PA +146481,Lake Forest College,Lake Forest,IL +146490,Lake Forest Graduate School of Management,Lake Forest,IL +146506,Lake Land College,Mattoon,IL +170620,Lake Michigan College,Benton Harbor,MI +200192,Lake Region State College,Devils Lake,ND +173461,Lake Superior College,Duluth,MN +170639,Lake Superior State University,Sault Ste Marie,MI +117195,Lake Tahoe Community College,South Lake Tahoe,CA +235699,Lake Washington Institute of Technology,Kirkland,WA +238980,Lakeland College,Plymouth,WI +203599,Lakeland Community College,Kirtland,OH +183123,Lakes Region Community College,Laconia,NH +239008,Lakeshore Technical College,Cleveland,WI +135188,Lake-Sumter State College,Leesburg,FL +146533,Lakeview College of Nursing,Danville,IL +127389,Lamar Community College,Lamar,CO +441760,Lamar Institute of Technology,Beaumont,TX +226107,Lamar State College-Orange,Orange,TX +226116,Lamar State College-Port Arthur,Port Arthur,TX +226091,Lamar University,Beaumont,TX +213400,Lancaster Bible College,Lancaster,PA +418533,Lancaster County Career and Technology Center,Willow Street,PA +213446,Lancaster Theological Seminary,Lancaster,PA +218229,Lander University,Greenwood,SC +247649,Landmark College,Putney,VT +220598,Lane College,Jackson,TN +209038,Lane Community College,Eugene,OR +117247,Laney College,Oakland,CA +207209,Langston University,Langston,OK +140243,Lanier Technical College,Oakwood,GA +213473,Lansdale School of Business,North Wales,PA +170657,Lansing Community College,Lansing,MI +240620,Laramie County Community College,Cheyenne,WY +226134,Laredo Community College,Laredo,TX +366401,Las Positas College,Livermore,CA +166391,Lasell College,Newton,MA +117274,Lassen Community College,Susanville,CA +230418,Latter-day Saints Business College,Salt Lake City,UT +250027,Laurel Business Institute,Uniontown,PA +408729,Laurel Technical Institute-MEADVILLE,MEADVILLE,PA +215992,Laurel Technical Institute-Sharon,Sharon,PA +198747,Laurel University,High Point,NC +166407,Lawrence Memorial Hospital School of Nursing,Medford,MA +170675,Lawrence Technological University,Southfield,MI +239017,Lawrence University,Appleton,WI +101569,Lawson State Community College-Birmingham Campus,Birmingham,AL +443623,Le Cordon Bleu College of Culinary Arts-Atlanta,Tucker,GA +364973,Le Cordon Bleu College of Culinary Arts-Austin,Austin,TX +452054,Le Cordon Bleu College of Culinary Arts-Cambridge,Cambridge,MA +144467,Le Cordon Bleu College of Culinary Arts-Chicago,Chicago,IL +452063,Le Cordon Bleu College of Culinary Arts-Dallas,Dallas,TX +445115,Le Cordon Bleu College of Culinary Arts-Las Vegas,Las Vegas,NV +446835,Le Cordon Bleu College of Culinary Arts-Miami,Miramar,FL +446844,Le Cordon Bleu College of Culinary Arts-Minneapolis,Mendota Heights,MN +442231,Le Cordon Bleu College of Culinary Arts-Orlando,Orlando,FL +423980,Le Cordon Bleu College of Culinary Arts-Pasadena,Pasadena,CA +375841,Le Cordon Bleu College of Culinary Arts-Portland,Portland,OR +111009,Le Cordon Bleu College of Culinary Arts-San Francisco,San Francisco,CA +262332,Le Cordon Bleu College of Culinary Arts-Scottsdale,Scottsdale,AZ +192323,Le Moyne College,Syracuse,NY +220604,Le Moyne-Owen College,Memphis,TN +213507,Lebanon Valley College,Annville,PA +456940,L'Ecole Culinaire-Memphis,Cordova,TN +445726,L'Ecole Culinaire-St Louis,St. Louis,MO +226204,Lee College,Baytown,TX +220613,Lee University,Cleveland,TN +413626,Leech Lake Tribal College,Cass Lake,MN +198808,Lees-McRae College,Banner Elk,NC +141811,Leeward Community College,Pearl City,HI +213525,Lehigh Carbon Community College,Schnecksville,PA +213543,Lehigh University,Bethlehem,PA +198817,Lenoir Community College,Kinston,NC +198835,Lenoir-Rhyne University,Hickory,NC +218265,Lenoir-Rhyne University-Lutheran Theological Southern Seminary,Columbia,SC +166452,Lesley University,Cambridge,MA +226231,LeTourneau University,Longview,TX +209056,Lewis & Clark College,Portland,OR +146603,Lewis and Clark Community College,Godfrey,IL +146612,Lewis University,Romeoville,IL +142328,Lewis-Clark State College,Lewiston,ID +157207,Lexington Theological Seminary,Lexington,KY +232557,Liberty University,Lynchburg,VA +117520,Life Chiropractic College West,Hayward,CA +117104,Life Pacific College,San Dimas,CA +140252,Life University,Marietta,GA +192271,LIM College,New York,NY +218238,Limestone College,Gaffney,SC +146667,Lincoln Christian University,Lincoln,IL +146676,Lincoln College,Lincoln,IL +128683,Lincoln College of New England-Southington,Southington,CT +163028,Lincoln College of Technology-Columbia,Columbia,MD +126951,Lincoln College of Technology-Denver,Denver,CO +151661,Lincoln College of Technology-Indianapolis,Indianapolis,IN +434159,Lincoln College of Technology-Marietta,Marietta,GA +146700,Lincoln College of Technology-Melrose Park,Melrose Park,IL +221148,Lincoln College of Technology-Nashville,Nashville,TN +136066,Lincoln College of Technology-West Palm Beach,West Palm Beach,FL +146685,Lincoln Land Community College,Springfield,IL +220631,Lincoln Memorial University,Harrogate,TN +213570,Lincoln Technical Institute-Allentown,Allentown,PA +442037,Lincoln Technical Institute-Northeast Philadelphia,Philadelphia,PA +213589,Lincoln Technical Institute-Philadelphia,Philadelphia,PA +403478,Lincoln Trail College,Robinson,IL +177940,Lincoln University-Jefferson City,Jefferson City,MO +117557,Lincoln University-Oakland,Oakland,CA +177968,Lindenwood University,Saint Charles,MO +157216,Lindsey Wilson College,Columbia,KY +437325,Linfield College-Adult Degree Program,McMinnville,OR +209065,Linfield College-McMinnville Campus,McMinnville,OR +437316,Linfield College-School of Nursing,Portland,OR +209074,Linn-Benton Community College,Albany,OR +219976,Lipscomb University,Nashville,TN +180328,Little Big Horn College,Crow Agency,MT +434016,Little Priest Tribal College,Winnebago,NE +192563,LIU Brentwood,Brentwood,NY +192439,LIU Brooklyn,Brooklyn,NY +192554,LIU Hudson at Rockland,Orangeburg,NY +432357,LIU Hudson at Westchester,Purchase,NY +192448,LIU Post,Brookville,NY +450766,LIU Riverhead,Riverhead,NY +421832,Living Arts College,Raleigh,NC +198862,Livingstone College,Salisbury,NC +213613,Lock Haven University,Lock Haven,PA +177986,Logan University,Chesterfield,MO +117636,Loma Linda University,Loma Linda,CA +227182,Lone Star College System,The Woodlands,TX +117645,Long Beach City College,Long Beach,CA +192509,Long Island Business Institute,Flushing,NY +232566,Longwood University,Farmville,VA +166489,Longy School of Music of Bard College,Cambridge,MA +203748,Lorain County Community College,Elyria,OH +153825,Loras College,Dubuque,IA +232575,Lord Fairfax Community College,Middletown,VA +117788,Los Angeles City College,Los Angeles,CA +446385,Los Angeles College of Music,Pasadena,CA +117803,Los Angeles County College of Nursing and Allied Health,Los Angeles,CA +436429,Los Angeles Film School,Hollywood,CA +117690,Los Angeles Harbor College,Wilmington,CA +117867,Los Angeles Mission College,Sylmar,CA +368780,Los Angeles ORT College-Los Angeles Campus,Los Angeles,CA +381945,Los Angeles ORT College-Van Nuys Campus,Van Nuys,CA +117706,Los Angeles Pierce College,Woodland Hills,CA +117715,Los Angeles Southwest College,Los Angeles,CA +117724,Los Angeles Trade Technical College,Los Angeles,CA +117733,Los Angeles Valley College,Valley Glen,CA +117894,Los Medanos College,Pittsburg,CA +198871,Louisburg College,Louisburg,NC +159568,Louisiana College,Pineville,LA +449612,Louisiana Culinary Institute,Baton Rouge,LA +483212,Louisiana Delta Community College,Monroe,LA +159391,Louisiana State University and Agricultural & Mechanical College,Baton Rouge,LA +159373,Louisiana State University Health Sciences Center-New Orleans,New Orleans,LA +435000,Louisiana State University Health Sciences Center-Shreveport,Shreveport,LA +159382,Louisiana State University-Alexandria,Alexandria,LA +159407,Louisiana State University-Eunice,Eunice,LA +159416,Louisiana State University-Shreveport,Shreveport,LA +159647,Louisiana Tech University,Ruston,LA +157298,Louisville Presbyterian Theological Seminary,Louisville,KY +203757,Lourdes University,Sylvania,OH +235750,Lower Columbia College,Longview,WA +117946,Loyola Marymount University,Los Angeles,CA +146719,Loyola University Chicago,Chicago,IL +163046,Loyola University Maryland,Baltimore,MD +159656,Loyola University New Orleans,New Orleans,LA +226383,Lubbock Christian University,Lubbock,TX +363633,Luna Community College,Las Vegas,NM +101602,Lurleen B Wallace Community College,Andalusia,AL +153834,Luther College,Decorah,IA +135364,Luther Rice University & Seminary,Lithonia,GA +173896,Luther Seminary,Saint Paul,MN +146728,Lutheran School of Theology at Chicago,Chicago,IL +213631,Lutheran Theological Seminary at Gettysburg,Gettysburg,PA +213640,Lutheran Theological Seminary at Philadelphia,Philadelphia,PA +213659,Luzerne County Community College,Nanticoke,PA +213668,Lycoming College,Williamsport,PA +232609,Lynchburg College,Lynchburg,VA +230931,Lyndon State College,Lyndonville,VT +132657,Lynn University,Boca Raton,FL +106342,Lyon College,Batesville,AR +173902,Macalester College,Saint Paul,MN +146816,MacCormac College,Chicago,IL +192624,Machzikei Hadath Rabbinical College,Brooklyn,NY +146825,MacMurray College,Jacksonville,IL +170790,Macomb Community College,Warren,MI +238263,Madison Area Technical College,Madison,WI +364168,Madison Media Institute,Madison,WI +148399,Madison Media Institute-Rockford Career College,Rockford,IL +157304,Madisonville Community College,Madisonville,KY +170806,Madonna University,Livonia,MI +153861,Maharishi University of Management,Fairfield,IA +161509,Maine College of Art,Portland,ME +161022,Maine College of Health Professions,Lewiston,ME +161299,Maine Maritime Academy,Castine,ME +203775,Malone University,Canton,OH +451103,Management Resources College,Miami,FL +129695,Manchester Community College-Manchester,Manchester,CT +183132,Manchester Community College-Manchester,Manchester,NH +151777,Manchester University,North Manchester,IN +192688,Mandl School-The College of Allied Health,New York,NY +155487,Manhattan Area Technical College,Manhattan,KS +155496,Manhattan Christian College,Manhattan,KS +192703,Manhattan College,Riverdale,NY +192712,Manhattan School of Music,New York,NY +192749,Manhattanville College,Purchase,NY +213774,Manor College,Jenkintown,PA +213783,Mansfield University of Pennsylvania,Mansfield,PA +446394,Maple Springs Baptist Bible College and Seminary,Capitol Heights,MD +239071,Maranatha Baptist University,Watertown,WI +192785,Maria College of Albany,Albany,NY +166601,Marian Court College,Swampscott,MA +239080,Marian University-Fond Du Lac,Fond Du Lac,WI +151786,Marian University-Indianapolis,Indianapolis,IN +203845,Marietta College,Marietta,OH +101648,Marion Military Institute,Marion,AL +203881,Marion Technical College,Marion,OH +192819,Marist College,Poughkeepsie,NY +230940,Marlboro College,Marlboro,VT +440411,Marlboro College Graduate & Professional Studies,Brattleboro,VT +239105,Marquette University,Milwaukee,WI +198899,Mars Hill University,Mars Hill,NC +123943,Marshall B Ketchum University,Fullerton,CA +237525,Marshall University,Huntington,WV +153922,Marshalltown Community College,Marshalltown,IA +198905,Martin Community College,Williamston,NC +173452,Martin Luther College,New Ulm,MN +220701,Martin Methodist College,Pulaski,TN +151810,Martin University,Indianapolis,IN +232672,Mary Baldwin College,Staunton,VA +170842,Marygrove College,Detroit,MI +163295,Maryland Institute College of Art,Baltimore,MD +164085,Maryland University of Integrative Health,Laurel,MD +209108,Marylhurst University,Marylhurst,OR +118541,Marymount California University,Rancho Palos Verdes,CA +192864,Marymount Manhattan College,New York,NY +232706,Marymount University,Arlington,VA +220710,Maryville College,Maryville,TN +178059,Maryville University of Saint Louis,Saint Louis,MO +213826,Marywood University,Scranton,PA +166647,Massachusetts Bay Community College,Wellesley Hills,MA +166674,Massachusetts College of Art and Design,Boston,MA +167288,Massachusetts College of Liberal Arts,North Adams,MA +166683,Massachusetts Institute of Technology,Cambridge,MA +166692,Massachusetts Maritime Academy,Buzzards Bay,MA +369002,Massachusetts School of Law,Andover,MA +166823,Massasoit Community College,Brockton,MA +436702,Mattia College,Miami,FL +454698,Mayfield College,Cathedral City,CA +198914,Mayland Community College,Spruce Pine,NC +365426,Mayo Graduate School,Rochester,MN +173957,Mayo Medical School,Rochester,MN +173966,Mayo School of Health Sciences,Rochester,MN +157331,Maysville Community and Technical College,Maysville,KY +200226,Mayville State University,Mayville,ND +438212,McCann School of Business & Technology,Pottsville,PA +146977,McCormick Theological Seminary,Chicago,IL +164270,McDaniel College,Westminster,MD +198923,McDowell Technical Community College,Marion,NC +147004,McHenry County College,Crystal Lake,IL +147013,McKendree University,Lebanon,IL +226578,McLennan Community College,Waco,TX +226587,McMurry University,Abilene,TX +367194,McNally Smith College of Music,Saint Paul,MN +159717,McNeese State University,Lake Charles,LA +155511,McPherson College,McPherson,KS +166656,MCPHS University,Boston,MA +147031,Meadville Lombard Theological School,Chicago,IL +414461,Mech-Tech College,Caguas,PR +192925,Medaille College,Buffalo,NY +239169,Medical College of Wisconsin,Milwaukee,WI +218335,Medical University of South Carolina,Charleston,SC +448415,MedTech College,Indianapolis,IN +456366,MedTech College-Ft Wayne Campus,Ft. Wayne,IN +456357,MedTech College-Greenwood Campus,Greenwood,IN +456375,MedTech College-Lexington Campus,Lexington,KY +131742,Medtech Institute,Falls Church,VA +444714,MedTech Institute-Atlanta Campus,Atlanta,GA +220792,Meharry Medical College,Nashville,TN +192961,Memorial School of Nursing,Albany,NY +220808,Memphis College of Art,Memphis,TN +220871,Memphis Theological Seminary,Memphis,TN +118684,Mendocino College,Ukiah,CA +118693,Menlo College,Atherton,CA +118718,Merced College,Merced,CA +185509,Mercer County Community College,West Windsor,NJ +140447,Mercer University,Macon,GA +193016,Mercy College,Dobbs Ferry,NY +153977,Mercy College of Health Sciences,Des Moines,IA +203960,Mercy College of Ohio,Toledo,OH +213987,Mercyhurst University,Erie,PA +480189,Mercyhurst University-North East Campus,North East,PA +198950,Meredith College,Raleigh,NC +244279,Meridian College,Sarasota,FL +175935,Meridian Community College,Meridian,MS +166850,Merrimack College,North Andover,MA +118772,Merritt College,Oakland,CA +105154,Mesa Community College,Mesa,AZ +173993,Mesabi Range College,Virginia,MN +188261,Mesalands Community College,Tucumcari,NM +461847,Mesivta Keser Torah,Belmar,NJ +193061,Mesivta of Eastern Parkway-Yeshiva Zichron Meilech,Brooklyn,NY +193052,Mesivta Torah Vodaath Rabbinical Seminary,Brooklyn,NY +193070,Mesivtha Tifereth Jerusalem of America,New York,NY +417752,Messenger College,Euless,TX +213996,Messiah College,Mechanicsburg,PA +147129,Methodist College,Peoria,IL +203997,Methodist Theological School in Ohio,Delaware,OH +198969,Methodist University,Fayetteville,NC +455673,Metro Business College-Arnold,Arnold,MO +178110,Metro Business College-Cape Girardeau,Cape Girardeau,MO +245430,Metro Business College-Jefferson City,Jefferson City,MO +245421,Metro Business College-Rolla,Rolla,MO +214023,Metropolitan Career Center Computer Technology Institute,Philadelphia,PA +190114,Metropolitan College of New York,New York,NY +181303,Metropolitan Community College Area,Omaha,NE +177995,Metropolitan Community College-Kansas City-Kansas City,Kansas City,MO +174020,Metropolitan State University,Saint Paul,MN +127565,Metropolitan State University of Denver,Denver,CO +166869,MGH Institute of Health Professions,Boston,MA +135717,Miami Dade College,Miami,FL +204006,Miami University-Hamilton,Hamilton,OH +204015,Miami University-Middletown,Middletown,OH +204024,Miami University-Oxford,Oxford,OH +369862,Miami-Jacobs Career College-Columbus,Columbus,OH +204060,Miami-Jacobs Career College-Dayton,Dayton,OH +200633,Miami-Jacobs Career College-Independence,Independence,OH +441201,Miami-Jacobs Career College-Sharonville,Sharonville,OH +449126,Miami-Jacobs Career College-Springboro,Springboro,OH +450003,Miami-Jacobs Career College-Troy,Troy,OH +169655,MIAT College of Technology,Canton,MI +434414,Michigan Jewish Institute,W Bloomfield,MI +169220,Michigan School of Professional Psychology,Farmington Hills,MI +171100,Michigan State University,East Lansing,MI +169628,Michigan State University-College of Law,East Lansing,MI +171128,Michigan Technological University,Houghton,MI +171155,Mid Michigan Community College,Harrison,MI +245953,Mid-America Christian University,Oklahoma City,OK +151962,Mid-America College of Funeral Service,Jeffersonville,IN +155520,MidAmerica Nazarene University,Olathe,KS +199458,Mid-Atlantic Christian University,Elizabeth City,NC +482158,Middle Georgia State College,Macon,GA +220996,Middle Tennessee School of Anesthesia Inc,Madison,TN +220978,Middle Tennessee State University,Murfreesboro,TN +230959,Middlebury College,Middlebury,VT +166887,Middlesex Community College-Bedford,Bedford,MA +129756,Middlesex Community College-Middletown,Middletown,CT +185536,Middlesex County College,Edison,NJ +226806,Midland College,Midland,TX +181330,Midland University,Fremont,NE +218353,Midlands Technical College,West Columbia,SC +181312,Mid-Plains Community College,North Platte,NE +481225,Mid-South Christian College,Memphis,TN +147165,Midstate College,Peoria,IL +239220,Mid-State Technical College,Wisconsin Rapids,WI +157377,Midway College,Midway,KY +439020,Midwest College of Oriental Medicine-Chicago,Chicago,IL +383020,Midwest College of Oriental Medicine-Racine,Racine,WI +178183,Midwest Institute,Fenton,MO +178208,Midwestern Baptist Theological Seminary,Kansas City,MO +226833,Midwestern State University,Wichita Falls,TX +143853,Midwestern University-Downers Grove,Downers Grove,IL +423643,Midwestern University-Glendale,Glendale,AZ +480985,Midwives College of Utah,Salt Lake City,UT +193201,Mildred Elley School-Albany Campus,Albany,NY +461014,Mildred Elley-New York Campus,New York,NY +101675,Miles College,Fairfield,AL +180373,Miles Community College,Miles City,MT +461883,Millennia Atlantic University,Doral,FL +449117,Miller-Motte College-Cary,Cary,NC +458405,Miller-Motte College-Fayetteville,Fayetteville,NC +455655,Miller-Motte College-Greenville,Greenville,NC +460817,Miller-Motte College-Jacksonville,Jacksonville,NC +456205,Miller-Motte College-Raleigh,Raleigh,NC +198978,Miller-Motte College-Wilmington,Wilmington,NC +460826,Miller-Motte Technical College-Augusta,Augusta,GA +441025,Miller-Motte Technical College-Charleston,Charleston,SC +443650,Miller-Motte Technical College-Chattanooga,Chattanooga,TN +382771,Miller-Motte Technical College-Clarksville,Clarksville,TN +458441,Miller-Motte Technical College-Columbus,Columbus,GA +460835,Miller-Motte Technical College-Conway,Conway,SC +475079,Miller-Motte Technical College-Gulfport,Gulfport,MS +233091,Miller-Motte Technical College-Lynchburg,Lynchburg,VA +475060,Miller-Motte Technical College-Macon,Macon,GA +448664,Miller-Motte Technical College-Madison,Madison,TN +475194,Miller-Motte Technical College-Roanoke,Roanoke,VA +214041,Millersville University of Pennsylvania,Millersville,PA +221014,Milligan College,Milligan College,TN +147244,Millikin University,Decatur,IL +118888,Mills College,Oakland,CA +175980,Millsaps College,Jackson,MS +239248,Milwaukee Area Technical College,Milwaukee,WI +239309,Milwaukee Institute of Art & Design,Milwaukee,WI +239318,Milwaukee School of Engineering,Milwaukee,WI +178217,Mineral Area College,Park Hills,MO +174118,Minneapolis Business College,Roseville,MN +174127,Minneapolis College of Art and Design,Minneapolis,MN +174136,Minneapolis Community and Technical College,Minneapolis,MN +474881,Minneapolis Media Institute,Edina,MN +451769,Minnesota School of Business-Blaine,Blaine,MN +407285,Minnesota School of Business-Brooklyn Center,Brooklyn Center,MN +456782,Minnesota School of Business-Elk River,Elk River,MN +458742,Minnesota School of Business-Lakeville,Lakeville,MN +455585,Minnesota School of Business-Moorhead,Moorhead,MN +442578,Minnesota School of Business-Plymouth,Plymouth,MN +174279,Minnesota School of Business-Richfield,Richfield,MN +447670,Minnesota School of Business-Rochester,Rochester,MN +445920,Minnesota School of Business-Waite Park,Waite Park,MN +175263,Minnesota State College-Southeast Technical,Winona,MN +173559,Minnesota State Community and Technical College,Fergus Falls,MN +174358,Minnesota State University Moorhead,Moorhead,MN +173920,Minnesota State University-Mankato,Mankato,MN +173638,Minnesota West Community and Technical College,Granite Falls,MN +200253,Minot State University,Minot,ND +118912,MiraCosta College,Oceanside,CA +193247,Mirrer Yeshiva Cent Institute,Brooklyn,NY +214069,Misericordia University,Dallas,PA +118930,Mission College,Santa Clara,CA +176053,Mississippi College,Clinton,MS +176008,Mississippi Delta Community College,Moorhead,MS +176071,Mississippi Gulf Coast Community College,Perkinston,MS +176080,Mississippi State University,Mississippi State,MS +176035,Mississippi University for Women,Columbus,MS +176044,Mississippi Valley State University,Itta Bena,MS +178244,Missouri Baptist University,Saint Louis,MO +178305,Missouri College,Brentwood,MO +178341,Missouri Southern State University,Joplin,MO +179566,Missouri State University-Springfield,Springfield,MO +179344,Missouri State University-West Plains,West Plains,MO +178350,Missouri Tech,Saint Charles,MO +178411,Missouri University of Science and Technology,Rolla,MO +178369,Missouri Valley College,Marshall,MO +178387,Missouri Western State University,Saint Joseph,MO +129774,Mitchell College,New London,CT +198987,Mitchell Community College,Statesville,NC +219189,Mitchell Technical Institute,Mitchell,SD +178448,Moberly Area Community College,Moberly,MO +118976,Modesto Junior College,Modesto,CA +105206,Mohave Community College,Kingman,AZ +193283,Mohawk Valley Community College,Utica,NY +193292,Molloy College,Rockville Centre,NY +147341,Monmouth College,Monmouth,IL +185572,Monmouth University,West Long Branch,NJ +193308,Monroe College,Bronx,NY +193326,Monroe Community College,Rochester,NY +171225,Monroe County Community College,Monroe,MI +262165,Montana Bible College,Bozeman,MT +180461,Montana State University,Bozeman,MT +180179,Montana State University-Billings,Billings,MT +180522,Montana State University-Northern,Havre,MT +180416,Montana Tech of the University of Montana,Butte,MT +171234,Montcalm Community College,Sidney,MI +185590,Montclair State University,Montclair,NJ +119058,Monterey Institute of International Studies,Monterey,CA +119067,Monterey Peninsula College,Monterey,CA +163426,Montgomery College,Rockville,MD +199023,Montgomery Community College,Troy,NC +214111,Montgomery County Community College,Blue Bell,PA +199032,Montreat College,Montreat,NC +166911,Montserrat College of Art,Beverly,MA +147369,Moody Bible Institute,Chicago,IL +214148,Moore College of Art and Design,Philadelphia,PA +119137,Moorpark College,Moorpark,CA +239372,Moraine Park Technical College,Fond du Lac,WI +147378,Moraine Valley Community College,Palos Hills,IL +214157,Moravian College,Bethlehem,PA +157386,Morehead State University,Morehead,KY +140553,Morehouse College,Atlanta,GA +140562,Morehouse School of Medicine,Atlanta,GA +460394,Moreno Valley College,Moreno Valley,CA +127617,Morgan Community College,Fort Morgan,CO +163453,Morgan State University,Baltimore,MD +154004,Morningside College,Sioux City,IA +218399,Morris College,Sumter,SC +147396,Morrison Institute of Technology,Morrison,IL +196051,Morrisville State College,Morrisville,NY +147411,Morton College,Cicero,IL +221096,Motlow State Community College,Tullahoma,TN +169275,Mott Community College,Flint,MI +140599,Moultrie Technical College,Moultrie,GA +214166,Mount Aloysius College,Cresson,PA +209241,Mount Angel Seminary,Saint Benedict,OR +204176,Mount Carmel College of Nursing,Columbus,OH +166939,Mount Holyoke College,South Hadley,MA +166948,Mount Ida College,Newton,MA +219198,Mount Marty College,Yankton,SD +239390,Mount Mary University,Milwaukee,WI +154013,Mount Mercy University,Cedar Rapids,IA +204200,Mount Saint Joseph University,Cincinnati,OH +193353,Mount Saint Mary College,Newburgh,NY +119173,Mount Saint Mary's University,Los Angeles,CA +163462,Mount St Mary's University,Emmitsburg,MD +204194,Mount Vernon Nazarene University,Mount Vernon,OH +166957,Mount Wachusett Community College,Gardner,MA +182865,Mount Washington College,Manchester,NH +232788,Mountain Empire Community College,Big Stone Gap,VA +237598,Mountain State College,Parkersburg,WV +226930,Mountain View College,Dallas,TX +444954,Mountwest Community and Technical College,Huntington,WV +209250,Mt Hood Community College,Gresham,OR +119164,Mt San Antonio College,Walnut,CA +119216,Mt San Jacinto Community College District,San Jacinto,CA +398130,Mt Sierra College,Monrovia,CA +118198,MTI College,Sacramento,CA +214175,Muhlenberg College,Allentown,PA +209287,Multnomah University,Portland,OR +207236,Murray State College,Tishomingo,OK +157401,Murray State University,Murray,KY +119270,Musicians Institute,Hollywood,CA +171304,Muskegon Community College,Muskegon,MI +204264,Muskingum University,New Concord,OH +434432,Myotherapy Institute,Lincoln,NE +119331,Napa Valley College,Napa,CA +127653,Naropa University,Boulder,CO +199087,Nash Community College,Rocky Mount,NC +239424,Nashotah House,Nashotah,WI +183141,Nashua Community College,Nashua,NH +221184,Nashville State Community College,Nashville,TN +193478,Nassau Community College,Garden City,NY +248882,National American University-Albuquerque,Albuquerque,NM +440758,National American University-Albuquerque West,Albuquerque,NM +451875,National American University-Austin,Austin,TX +482307,National American University-Austin South,Austin,TX +477996,National American University-Bellevue,Bellevue,NE +436483,National American University-Bloomington,Bloomington,MN +440767,National American University-Brooklyn Center,Brooklyn Center,MN +478005,National American University-Burnsville,Burnsville,MN +466161,National American University-Centennial,Centennial,CO +127680,National American University-Colorado Springs,Colorado Springs,CO +466189,National American University-Colorado Springs South,Colorado Springs,CO +127699,National American University-Denver,Denver,CO +440749,National American University-Ellsworth AFB Extension,Ellsworth Air Force Base,SD +482325,National American University-Georgetown,Georgetown,TX +485290,National American University-Harold D. Buckingham Graduate School,Austin,TX +247700,National American University-Independence,Independence,MO +482370,National American University-Indianapolis,Indianapolis,IN +466170,National American University-Lee's Summit,Lee's Summit,MO +482316,National American University-Lewisville,Lewisville,TX +442718,National American University-Overland Park,Overland Park,KS +219204,National American University-Rapid City,Rapid City,SD +482343,National American University-Rochester,Rochester,MN +174385,National American University-Roseville,Roseville,MN +219213,National American University-Sioux Falls,Sioux Falls,SD +466152,National American University-Tulsa,Tulsa,OK +482352,National American University-Weldon Spring,Weldon Spring,MO +451884,National American University-Wichita,Wichita,KS +482361,National American University-Wichita West,Wichita,KS +448585,National American University-Zona Rosa,Kansas City,MO +209296,National College of Natural Medicine,Portland,OR +480480,National College-Canton,Canton,OH +453473,National College-Cincinnati,Cincinnati,OH +457004,National College-Columbus,Columbus,OH +453455,National College-Dayton,Kettering,OH +157021,National College-Lexington,Lexington,KY +388043,National College-Nashville,Nashville,TN +453482,National College-Stow,Stow,OH +459833,National College-Willoughby Hills,Willoughby Hills,OH +453464,National College-Youngstown,Youngstown,OH +441478,National Graduate School of Quality Management,Falmouth,MA +412003,National Institute of Massotherapy,Akron,OH +147536,National Louis University,Chicago,IL +448114,National Massage Therapy Institute,Philadelphia,PA +461023,National Paralegal College,Phoenix,AZ +106980,National Park Community College,Hot Springs,AR +119605,National University,La Jolla,CA +242981,National University College-Arecibo,Arecibo,PR +242972,National University College-Bayamon,Bayamon,PR +468723,National University College-Caguas,Caguas,PR +458469,National University College-Ponce,Ponce,PR +444042,National University College-Rio Grande,Rio Grande,PR +147590,National University of Health Sciences,Lombard,IL +129729,Naugatuck Valley Community College,Waterbury,CT +187596,Navajo Technical University,Crownpoint,NM +119678,Naval Postgraduate School,Monterey,CA +227146,Navarro College,Corsicana,TX +127714,Nazarene Bible College,Colorado Springs,CO +178518,Nazarene Theological Seminary,Kansas City,MO +193584,Nazareth College,Rochester,NY +181376,Nebraska Christian College,Papillion,NE +181765,Nebraska College of Technical Agriculture,Curtis,NE +181419,Nebraska Indian Community College,Macy,NE +181297,Nebraska Methodist College of Nursing & Allied Health,Omaha,NE +181446,Nebraska Wesleyan University,Lincoln,NE +155566,Neosho County Community College,Chanute,KS +163532,Ner Israel Rabbinical College,Baltimore,MD +214272,Neumann University,Aston,PA +445692,Neumont University,Salt Lake City,UT +441900,Nevada State College,Henderson,NV +185758,New Brunswick Theological Seminary,New Brunswick,NJ +214290,New Castle School of Trades,New Castle,PA +262129,New College of Florida,Sarasota,FL +182980,New England College,Henniker,NH +164438,New England College of Business and Finance,Boston,MA +167093,New England College of Optometry,Boston,MA +230977,New England Culinary Institute,Montpelier,VT +217305,New England Institute of Technology,East Greenwich,RI +167215,New England Law-Boston,Boston,MA +167181,New England School of Acupuncture,Newton,MA +430810,New Hampshire Institute of Art,Manchester,NH +208725,New Hope Christian College-Eugene,Eugene,OR +185129,New Jersey City University,Jersey City,NJ +185828,New Jersey Institute of Technology,Newark,NJ +187897,New Mexico Highlands University,Las Vegas,NM +187967,New Mexico Institute of Mining and Technology,Socorro,NM +187903,New Mexico Junior College,Hobbs,NM +187912,New Mexico Military Institute,Roswell,NM +187994,New Mexico State University-Alamogordo,Alamogordo,NM +188003,New Mexico State University-Carlsbad,Carlsbad,NM +187620,New Mexico State University-Dona Ana,Las Cruces,NM +188021,New Mexico State University-Grants,Grants,NM +188030,New Mexico State University-Main Campus,Las Cruces,NM +159948,New Orleans Baptist Theological Seminary,New Orleans,LA +447582,New River Community and Technical College,Beaver,WV +232867,New River Community College,Dublin,VA +366368,New York Academy of Art,New York,NY +195845,New York Career Institute,New York,NY +193751,New York Chiropractic College,Seneca Falls,NY +418126,New York College of Health Professions,Syosset,NY +194073,New York College of Podiatric Medicine,New York,NY +439783,New York College of Traditional Chinese Medicine,Mineola,NY +421841,New York Conservatory for Dramatic Arts,New York,NY +461148,New York Film Academy,Burbank,CA +194091,New York Institute of Technology,Old Westbury,NY +193821,New York Law School,New York,NY +193830,New York Medical College,Valhalla,NY +194116,New York School of Interior Design,New York,NY +193894,New York Theological Seminary,New York,NY +193900,New York University,New York,NY +218414,Newberry College,Newberry,SC +167251,Newbury College,Brookline,MA +155335,Newman University,Wichita,KS +119775,Newschool of Architecture and Design,San Diego,CA +183099,NHTI-Concord's Community College,Concord,NH +193946,Niagara County Community College,Sanborn,NY +193973,Niagara University,Niagara University,NY +159966,Nicholls State University,Thibodaux,LA +167260,Nichols College,Dudley,MA +239442,Nicolet Area Technical College,Rhinelander,WI +444787,Nightingale College,Ogden,UT +460464,Norco College,Norco,CA +232937,Norfolk State University,Norfolk,VA +174428,Normandale Community College,Bloomington,MN +461795,North American University,Houston,TX +107460,North Arkansas College,Harrison,AR +199102,North Carolina A & T State University,Greensboro,NC +199157,North Carolina Central University,Durham,NC +199193,North Carolina State University at Raleigh,Raleigh,NC +199209,North Carolina Wesleyan College,Rocky Mount,NC +147660,North Central College,Naperville,IL +418889,North Central Institute,Clarksville,TN +155593,North Central Kansas Technical College,Beloit,KS +171395,North Central Michigan College,Petoskey,MI +179715,North Central Missouri College,Trenton,MO +204422,North Central State College,Mansfield,OH +224110,North Central Texas College,Gainesville,TX +174437,North Central University,Minneapolis,MN +194028,North Country Community College,Saranac Lake,NY +200305,North Dakota State College of Science,Wahpeton,ND +200332,North Dakota State University-Main Campus,Fargo,ND +136145,North Florida Community College,Madison,FL +140678,North Georgia Technical College,Clarkesville,GA +218441,North Greenville University,Tigerville,SC +174376,North Hennepin Community College,Brooklyn Park,MN +142443,North Idaho College,Coeur d'Alene,ID +154059,North Iowa Area Community College,Mason City,IA +227191,North Lake College,Irving,TX +147679,North Park University,Chicago,IL +236072,North Seattle College,Seattle,WA +167312,North Shore Community College,Danvers,MA +214379,Northampton County Area Community College,Bethlehem,PA +239460,Northcentral Technical College,Wausau,WI +444130,Northcentral University,Prescott Valley,AZ +101897,Northeast Alabama Community College,Rainsville,AL +182917,Northeast Catholic College,Warner,NH +181491,Northeast Community College,Norfolk,NE +154110,Northeast Iowa Community College,Calmar,IA +176169,Northeast Mississippi Community College,Booneville,MS +204477,Northeast Ohio Medical University,Rootstown,OH +221908,Northeast State Community College,Blountville,TN +227225,Northeast Texas Community College,Mount Pleasant,TX +239488,Northeast Wisconsin Technical College,Green Bay,WI +147776,Northeastern Illinois University,Chicago,IL +127732,Northeastern Junior College,Sterling,CO +207290,Northeastern Oklahoma A&M College,Miami,OK +439817,Northeastern Seminary,Rochester,NY +207263,Northeastern State University,Tahlequah,OK +217837,Northeastern Technical College,Cheraw,SC +167358,Northeastern University,Boston,MA +482705,Northeastern University Global Network,Boston,MA +105330,Northern Arizona University,Flagstaff,AZ +147697,Northern Baptist Theological Seminary,Lombard,IL +167376,Northern Essex Community College,Haverhill,MA +147703,Northern Illinois University,Dekalb,IL +157447,Northern Kentucky University,Highland Heights,KY +161484,Northern Maine Community College,Presque Isle,ME +240790,Northern Marianas College,Saipan,MP +171456,Northern Michigan University,Marquette,MI +188058,Northern New Mexico College,Espanola,NM +207281,Northern Oklahoma College,Tonkawa,OK +219259,Northern State University,Aberdeen,SD +232946,Northern Virginia Community College,Annandale,VA +239512,Northland College,Ashland,WI +174473,Northland Community and Technical College,Thief River Falls,MN +239503,Northland International University,Dunbar,WI +105349,Northland Pioneer College,Holbrook,AZ +217606,Northpoint Bible College,Haverhill,MA +160667,Northshore Technical Community College,Bogalusa,LA +367459,NorthWest Arkansas Community College,Bentonville,AR +445948,Northwest Career College,Las Vegas,NV +209409,Northwest Christian University,Eugene,OR +240657,Northwest College,Powell,WY +377546,Northwest College of Art & Design,Poulsbo,WA +136233,Northwest Florida State College,Niceville,FL +380377,Northwest Indian College,Bellingham,WA +460941,Northwest Institute of Literary Arts,Langley,WA +154129,Northwest Iowa Community College,Sheldon,IA +155618,Northwest Kansas Technical College,Goodland,KS +160010,Northwest Louisiana Technical College,Minden,LA +176178,Northwest Mississippi Community College,Senatobia,MS +178624,Northwest Missouri State University,Maryville,MO +142461,Northwest Nazarene University,Nampa,ID +458140,Northwest School of Wooden Boat Building,Port Hadlock,WA +204440,Northwest State Community College,Archbold,OH +173115,Northwest Technical College,Bemidji,MN +236133,Northwest University,Kirkland,WA +420398,Northwest Vista College,San Antonio,TX +154101,Northwestern College,Orange City,IA +147749,Northwestern College-Chicago Campus,Chicago,IL +260992,Northwestern College-Southwestern Campus,Bridgeview,IL +130040,Northwestern Connecticut Community College,Winsted,CT +174507,Northwestern Health Sciences University,Bloomington,MN +171483,Northwestern Michigan College,Traverse City,MI +207306,Northwestern Oklahoma State University,Alva,OK +160038,Northwestern State University of Louisiana,Natchitoches,LA +147767,Northwestern University,Evanston,IL +101736,Northwest-Shoals Community College,Muscle Shoals,AL +136206,Northwood University-Florida,West Palm Beach,FL +171492,Northwood University-Michigan,Midland,MI +227243,Northwood University-Texas,Cedar Hill,TX +130004,Norwalk Community College,Norwalk,CT +230995,Norwich University,Northfield,VT +368452,Nossi College of Art,Madison,TN +204468,Notre Dame College,Cleveland,OH +120184,Notre Dame de Namur University,Belmont,CA +163578,Notre Dame of Maryland University,Baltimore,MD +160029,Notre Dame Seminary Graduate School of Theology,New Orleans,LA +136215,Nova Southeastern University,Fort Lauderdale,FL +200086,Nueta Hidatsa Sahnish College,New Town,ND +158884,Nunez Community College,Chalmette,LA +194161,Nyack College,Nyack,NY +174525,Oak Hills Christian College,Bemidji,MN +152099,Oakland City University,Oakland City,IN +171535,Oakland Community College,Bloomfield Hills,MI +171571,Oakland University,Rochester Hills,MI +147800,Oakton Community College,Des Plaines,IL +101912,Oakwood University,Huntsville,AL +204501,Oberlin College,Oberlin,OH +227289,Oblate School of Theology,San Antonio,TX +120254,Occidental College,Los Angeles,CA +185873,Ocean County College,Toms River,NJ +420431,Oconee Fall Line Technical College,Sandersville,GA +227304,Odessa College,Odessa,TX +366465,Ogeechee Technical College,Statesboro,GA +219277,Oglala Lakota College,Kyle,SD +140696,Oglethorpe University,Atlanta,GA +453747,Ohio Business College-Hilliard,Columbu,OH +203739,Ohio Business College-Sandusky,Sandusky,OH +203720,Ohio Business College-Sheffield,Sheffield Village,OH +201964,Ohio Christian University,Circleville,OH +204592,Ohio College of Massotherapy Inc,Akron,OH +204617,Ohio Dominican University,Columbus,OH +206002,Ohio Mid-Western College,Cincinnati,OH +204635,Ohio Northern University,Ada,OH +204662,Ohio State University Agricultural Technical Institute,Wooster,OH +204671,Ohio State University-Lima Campus,Lima,OH +204796,Ohio State University-Main Campus,Columbus,OH +204680,Ohio State University-Mansfield Campus,Mansfield,OH +204699,Ohio State University-Marion Campus,Marion,OH +204705,Ohio State University-Newark Campus,Newark,OH +204608,Ohio Technical College,Cleveland,OH +453817,Ohio Technical College-PowerSport Institute,North Randall,OH +204820,Ohio University-Chillicothe Campus,Chillicothe,OH +204802,Ohio University-Eastern Campus,Saint Clairsville,OH +204848,Ohio University-Lancaster Campus,Lancaster,OH +204857,Ohio University-Main Campus,Athens,OH +204839,Ohio University-Southern Campus,Ironton,OH +204866,Ohio University-Zanesville Campus,Zanesville,OH +204884,Ohio Valley College of Technology,East Liverpool,OH +237640,Ohio Valley University,Vienna,WV +204909,Ohio Wesleyan University,Delaware,OH +120290,Ohlone College,Fremont,CA +194189,Ohr Hameir Theological Seminary,Peekskill,NY +207403,Oklahoma Baptist University,Shawnee,OK +207324,Oklahoma Christian University,Edmond,OK +207449,Oklahoma City Community College,Oklahoma City,OK +207458,Oklahoma City University,Oklahoma City,OK +207351,Oklahoma Panhandle State University,Goodwell,OK +207315,Oklahoma State University Center for Health Sciences,Tulsa,OK +207564,Oklahoma State University Institute of Technology,Okmulgee,OK +207388,Oklahoma State University-Main Campus,Stillwater,OK +207397,Oklahoma State University-Oklahoma City,Oklahoma City,OK +469629,Oklahoma Technical College,Tulsa,OK +206835,Oklahoma Wesleyan University,Bartlesville,OK +232982,Old Dominion University,Norfolk,VA +171599,Olivet College,Olivet,MI +147828,Olivet Nazarene University,Bourbonnais,IL +145707,Olney Central College,Olney,IL +236188,Olympic College,Bremerton,WA +407328,Omaha School of Massage and Healthcare of Herzing University,Omaha,NE +221254,O'More College of Design,Franklin,TN +194222,Onondaga Community College,Syracuse,NY +207582,Oral Roberts University,Tulsa,OK +120342,Orange Coast College,Costa Mesa,CA +194240,Orange County Community College,Middletown,NY +218487,Orangeburg Calhoun Technical College,Orangeburg,SC +423652,Oregon Coast Community College,Newport,OR +209533,Oregon College of Art and Craft,Portland,OR +369659,Oregon College of Oriental Medicine,Portland,OR +209490,Oregon Health & Science University,Portland,OR +209506,Oregon Institute of Technology,Klamath Falls,OR +209542,Oregon State University,Corvallis,OR +454883,Orion College,Plantation,FL +214528,Orleans Technical Institute,Philadelphia,PA +127778,Otero Junior College,La Junta,CO +120403,Otis College of Art and Design,Los Angeles,CA +442897,Ottawa University-Jeffersonville,Jeffersonville,IN +155636,Ottawa University-Kansas City,Overland Park,KS +428259,Ottawa University-Milwaukee,Brookfield,WI +454582,Ottawa University-Online,Ottawa,KS +155627,Ottawa University-Ottawa,Ottawa,KS +105367,Ottawa University-Phoenix,Phoenix,AZ +204936,Otterbein University,Westerville,OH +107512,Ouachita Baptist University,Arkadelphia,AR +160074,Our Lady of the Lake College,Baton Rouge,LA +227331,Our Lady of the Lake University,San Antonio,TX +204945,Owens Community College,Perrysburg,OH +247940,Owensboro Community and Technical College,Owensboro,KY +461120,Oxford Graduate School,Dayton,TN +120421,Oxnard College,Oxnard,CA +178679,Ozark Christian College,Joplin,MO +107549,Ozarka College,Melbourne,AR +177472,Ozarks Technical Community College,Springfield,MO +214838,Pace Institute,Reading,PA +194310,Pace University-New York,New York,NY +422695,Pacific College,Costa Mesa,CA +442842,Pacific College of Oriental Medicine-Chicago,Chicago,IL +414595,Pacific College of Oriental Medicine-New York,New York,NY +378576,Pacific College of Oriental Medicine-San Diego,San Diego,CA +439862,Pacific Islands University,Mangilao,GU +120740,Pacific Lutheran Theological Seminary,Berkeley,CA +236230,Pacific Lutheran University,Tacoma,WA +209603,Pacific Northwest College of Art,Portland,OR +455406,Pacific Northwest University of Health Sciences,Yakima,WA +120768,Pacific Oaks College,Pasadena,CA +457484,Pacific Rim Christian University,Honolulu,HI +120795,Pacific School of Religion,Berkeley,CA +120838,Pacific States University,Los Angeles,CA +120865,Pacific Union College,Angwin,CA +209612,Pacific University,Forest Grove,OR +115746,Pacifica Graduate Institute,Carpinteria,CA +130110,Paier College of Art Inc,Hamden,CT +140720,Paine College,Augusta,GA +243647,Palau Community College,Koror,PW +136330,Palm Beach Atlantic University,West Palm Beach,FL +136358,Palm Beach State College,Lake Worth,FL +154174,Palmer College of Chiropractic,Davenport,IA +246354,Palo Alto College,San Antonio,TX +120698,Palo Alto University,Palo Alto,CA +120953,Palo Verde College,Blythe,CA +120971,Palomar College,San Marcos,CA +199263,Pamlico Community College,Grantsboro,NC +227386,Panola College,Carthage,TX +364016,Paradise Valley Community College,Phoenix,AZ +121628,Pardee RAND Graduate School,Santa Monica,CA +227401,Paris Junior College,Paris,TX +178721,Park University,Parkville,MO +243823,Parker University,Dallas,TX +147916,Parkland College,Champaign,IL +121044,Pasadena City College,Pasadena,CA +136400,Pasco-Hernando State College,New Port Richey,FL +186034,Passaic County Community College,Paterson,NJ +666666,Patrick Henry College,Purcellville,VA +233019,Patrick Henry Community College,Martinsville,VA +233037,Paul D Camp Community College,Franklin,VA +227429,Paul Quinn College,Dallas,TX +194392,Paul Smiths College of Arts and Science,Paul Smiths,NY +204990,Payne Theological Seminary,Wilberforce,OH +176239,Pearl River Community College,Poplarville,MS +214883,Peirce College,Philadelphia,PA +221643,Pellissippi State Community College,Knoxville,TN +236258,Peninsula College,Port Angeles,WA +214892,Penn Commercial Business/Technical School,Washington,PA +214944,Pennco Tech-Bristol,Bristol,PA +214971,Pennsylvania Academy of the Fine Arts,Philadelphia,PA +215053,Pennsylvania College of Art and Design,Lancaster,PA +442356,Pennsylvania College of Health Sciences,Lancaster,PA +366252,Pennsylvania College of Technology,Williamsport,PA +414911,Pennsylvania Highlands Community College,Johnstown,PA +261861,Pennsylvania Institute of Health and Technology,Mount Braddock,PA +214582,Pennsylvania Institute of Technology,Media,PA +214616,Pennsylvania State University-College of Medicine,Hershey,PA +212018,Pennsylvania State University-Dickinson Law,Carlisle,PA +214777,Pennsylvania State University-Main Campus,University Park,PA +214801,Pennsylvania State University-Penn State Abington,Abington,PA +214689,Pennsylvania State University-Penn State Altoona,Altoona,PA +214698,Pennsylvania State University-Penn State Beaver,Monaca,PA +214704,Pennsylvania State University-Penn State Berks,Reading,PA +214731,Pennsylvania State University-Penn State Brandywine,Media,PA +214740,Pennsylvania State University-Penn State DuBois,DuBois,PA +214591,Pennsylvania State University-Penn State Erie-Behrend College,Erie,PA +214759,Pennsylvania State University-Penn State Fayette- Eberly,Lemont Furnace,PA +214607,Pennsylvania State University-Penn State Great Valley,Malvern,PA +214786,Pennsylvania State University-Penn State Greater Allegheny,McKeesport,PA +214713,Pennsylvania State University-Penn State Harrisburg,Middletown,PA +214768,Pennsylvania State University-Penn State Hazleton,Hazleton,PA +214670,Pennsylvania State University-Penn State Lehigh Valley,Center Valley,PA +214795,Pennsylvania State University-Penn State Mont Alto,Mont Alto,PA +214625,Pennsylvania State University-Penn State New Kensington,New Kensington,PA +214810,Pennsylvania State University-Penn State Schuylkill,Schuylkill Haven,PA +214634,Pennsylvania State University-Penn State Shenango,Sharon,PA +214643,Pennsylvania State University-Penn State Wilkes-Barre,Lehman,PA +214652,Pennsylvania State University-Penn State Worthington Scranton,Dunmore,PA +214829,Pennsylvania State University-Penn State York,York,PA +479956,Pennsylvania State University-World Campus,University Park,PA +136473,Pensacola State College,Pensacola,FL +219842,Pentecostal Theological Seminary,Cleveland,TN +121150,Pepperdine University,Malibu,CA +181534,Peru State College,Peru,NE +199306,Pfeiffer University,Misenheimer,NC +215123,Philadelphia College of Osteopathic Medicine,Philadelphia,PA +215099,Philadelphia University,Philadelphia,PA +107600,Philander Smith College,Little Rock,AR +189282,Phillips Beth Israel School of Nursing,New York,NY +107619,Phillips Community College of the University of Arkansas,Helena,AR +110307,Phillips Graduate Institute,Chatsworth,CA +414966,Phillips Theological Seminary,Tulsa,OK +105428,Phoenix College,Phoenix,AZ +447698,Phoenix Institute of Herbal Medicine & Acupuncture,Phoenix,AZ +381459,Phoenix Seminary,Phoenix,AZ +140818,Piedmont College,Demorest,GA +199324,Piedmont Community College,Roxboro,NC +199315,Piedmont International University,Winston Salem,NC +218520,Piedmont Technical College,Greenwood,SC +233116,Piedmont Virginia Community College,Charlottesville,VA +235237,Pierce College-Fort Steilacoom,Lakewood,WA +439145,Pierce College-Puyallup,Puyallup,WA +443492,Pierpont Community and Technical College,Fairmont,WV +127820,Pikes Peak Community College,Colorado Springs,CO +440794,Pillar College,Newark,NJ +105525,Pima Community College,Tucson,AZ +105543,Pima Medical Institute-Albuquerque,Albuquerque,NM +461689,Pima Medical Institute-Aurora,Aurora,CO +434140,Pima Medical Institute-Chula Vista,Chula Vista,CA +442134,Pima Medical Institute-Colorado Springs,Colorado Springs,CO +404912,Pima Medical Institute-Denver,Denver,CO +456038,Pima Medical Institute-East Valley,Mesa,AZ +460136,Pima Medical Institute-Houston,Houston,TX +445230,Pima Medical Institute-Las Vegas,Las Vegas,NV +260691,Pima Medical Institute-Mesa,Mesa,AZ +449074,Pima Medical Institute-Renton,Renton,WA +368629,Pima Medical Institute-Seattle,Seattle,WA +105534,Pima Medical Institute-Tucson,Tucson,AZ +458159,Pinchot University,Seattle,WA +167455,Pine Manor College,Chestnut Hill,MA +174570,Pine Technical & Community College,Pine City,MN +367097,Pinnacle Career Institute-Lawrence,Lawrence,KS +453109,Pinnacle Career Institute-North Kansas City,Kansas City,MO +177302,Pinnacle Career Institute-South Kansas City,Kansas City,MO +210076,Pioneer Pacific College,Wilsonville,OR +199333,Pitt Community College,Winterville,NC +155681,Pittsburg State University,Pittsburg,KS +216782,Pittsburgh Career Institute,Pittsburgh,PA +215381,Pittsburgh Institute of Aeronautics,West Mifflin,PA +215390,Pittsburgh Institute of Mortuary Science Inc,Pittsburgh,PA +215415,Pittsburgh Technical Institute,Oakdale,PA +215424,Pittsburgh Theological Seminary,Pittsburgh,PA +121257,Pitzer College,Claremont,CA +260813,Platt College-Aurora,Aurora,CO +207625,Platt College-Central OKC,Oklahoma City,OK +260789,Platt College-Los Angeles,Alhambra,CA +447379,Platt College-Moore,Moore,OK +445258,Platt College-North OKC,Oklahoma City,OK +432384,Platt College-Ontario,Ontario,CA +480204,Platt College-Riverside,Riverside,CA +121275,Platt College-San Diego,San Diego,CA +245962,Platt College-Tulsa,Tulsa,OK +194499,Plaza College,Forest Hills,NY +183080,Plymouth State University,Plymouth,NH +121309,Point Loma Nazarene University,San Diego,CA +215442,Point Park University,Pittsburgh,PA +138868,Point University,West Point,GA +136516,Polk State College,Winter Haven,FL +456481,Polytechnic University of Puerto Rico-Miami,Miami,FL +456490,Polytechnic University of Puerto Rico-Orlando,Orlando,FL +190451,Pomeroy College of Nursing at Crouse Hospital,Syracuse,NY +121345,Pomona College,Claremont,CA +243081,Ponce Health Sciences University,Ponce,PR +243072,Ponce Paramedical College Inc,Ponce,PR +241395,Pontifical Catholic University of Puerto Rico-Arecibo,Arecibo,PR +243586,Pontifical Catholic University of Puerto Rico-Mayaguez,Mayaguez,PR +241410,Pontifical Catholic University of Puerto Rico-Ponce,Ponce,PR +205027,Pontifical College Josephinum,Columbus,OH +131405,Pontifical Faculty of the Immaculate Conception at the Dominican House of Studies,Washington,DC +455813,Pontifical John Paul II Institute for Studies on Marriage and Family,Washington,DC +167464,Pope St John XXIII National Seminary,Weston,MA +121363,Porterville College,Porterville,CA +209746,Portland Community College,Portland,OR +209807,Portland State University,Portland,OR +130183,Post University,Waterbury,CT +237701,Potomac State College of West Virginia University,Keyser,WV +148007,Prairie State College,Chicago Heights,IL +227526,Prairie View A & M University,Prairie View,TX +155715,Pratt Community College,Pratt,KS +194578,Pratt Institute-Main,Brooklyn,NY +218539,Presbyterian College,Clinton,SC +105589,Prescott College,Prescott,AZ +219295,Presentation College,Aberdeen,SD +163657,Prince George's Community College,Largo,MD +101958,Prince Institute-Southeast,Montgomery,AL +186122,Princeton Theological Seminary,Princeton,NJ +186131,Princeton University,Princeton,NJ +148016,Principia College,Elsah,IL +215433,Prism Career Institute-Upper Darby,Upper Darby,PA +437750,Professional Golfers Career College,Temecula,CA +205054,Professional Skills Institute,Maumee,OH +455770,Providence Christian College,Pasadena,CA +217402,Providence College,Providence,RI +380438,Provo College,Provo,UT +127884,Pueblo Community College,Pueblo,CO +241766,Puerto Rico Conservatory of Music,San Juan,PR +107664,Pulaski Technical College,North Little Rock,AR +152248,Purdue University-Calumet Campus,Hammond,IN +243780,Purdue University-Main Campus,West Lafayette,IN +152266,Purdue University-North Central Campus,Westville,IN +199412,Queens University of Charlotte,Charlotte,NC +167525,Quincy College,Quincy,MA +148131,Quincy University,Quincy,IL +130217,Quinebaug Valley Community College,Danielson,CT +130226,Quinnipiac University,Hamden,CT +167534,Quinsigamond Community College,Worcester,MA +384421,Rabbi Jacob Joseph School,Edison,NJ +194657,Rabbinical Academy Mesivta Rabbi Chaim Berlin,Brooklyn,NY +194693,Rabbinical College Beth Shraga,Monsey,NY +194666,Rabbinical College Bobover Yeshiva Bnei Zion,Brooklyn,NY +186186,Rabbinical College of America,Morristown,NJ +194675,Rabbinical College of Ch'san Sofer New York,Brooklyn,NY +194736,Rabbinical College of Long Island,Long Beach,NY +405854,Rabbinical College of Ohr Shimon Yisroel,Brooklyn,NY +484871,Rabbinical College Ohr Yisroel,Brooklyn,NY +205124,Rabbinical College Telshe,Wickliffe,OH +194763,Rabbinical Seminary of America,Flushing,NY +233277,Radford University,Radford,VA +481119,Radians College,Washington,DC +174604,Rainy River Community College,International Falls,MN +186201,Ramapo College of New Jersey,Mahwah,NJ +233301,Randolph College,Lynchburg,VA +199421,Randolph Community College,Asheboro,NC +233295,Randolph-Macon College,Ashland,VA +227687,Ranger College,Ranger,TX +178891,Ranken Technical College,Saint Louis,MO +233310,Rappahannock Community College,Glenns,VA +186645,Raritan Valley Community College,Branchburg,NJ +138309,Rasmussen College-Florida,Ocala,FL +448673,Rasmussen College-Illinois,Rockford,IL +175014,Rasmussen College-Minnesota,St. Cloud,MN +200013,Rasmussen College-North Dakota,Fargo,ND +450571,Rasmussen College-Wisconsin,Green Bay,WI +215585,Reading Area Community College,Reading,PA +215619,Reconstructionist Rabbinical College,Wyncote,PA +127909,Red Rocks Community College,Lakewood,CO +207069,Redlands Community College,El Reno,OK +126605,Redstone College,Broomfield,CO +209922,Reed College,Portland,OR +117052,Reedley College,Reedley,CA +215628,Reformed Presbyterian Theological Seminary,Pittsburgh,PA +105659,Refrigeration School Inc,Phoenix,AZ +231651,Regent University,Virginia Beach,VA +167598,Regis College,Weston,MA +127918,Regis University,Denver,CO +101994,Reid State Technical College,Evergreen,AL +140872,Reinhardt University,Waleska,GA +475033,Relay Graduate School of Education,New York,NY +457183,Remington College of Nursing Orlando,Lake Mary,FL +440271,Remington College-Baton Rouge Campus,Baton Rouge,LA +375416,Remington College-Cleveland Campus,Cleveland,OH +223463,Remington College-Dallas Campus,Garland,TX +377111,Remington College-Fort Worth Campus,Fort Worth,TX +460783,Remington College-Heathrow Campus,Heathrow,FL +372958,Remington College-Honolulu Campus,Honolulu,HI +380094,Remington College-Houston Campus,Houston,TX +160524,Remington College-Lafayette Campus,Lafayette,LA +438869,Remington College-Little Rock Campus,Little Rock,AR +412599,Remington College-Memphis Campus,Memphis,TN +366535,Remington College-Mobile Campus,Mobile,AL +445249,Remington College-Nashville Campus,Nashville,TN +445203,Remington College-North Houston Campus,Houston,TX +451866,Remington College-Shreveport Campus,Shreveport,LA +135939,Remington College-Tampa Campus,Tampa,FL +148256,Rend Lake College,Ina,IL +129428,Rensselaer Hartford Graduate Center Inc,Hartford,CT +194824,Rensselaer Polytechnic Institute,Troy,NY +236382,Renton Technical College,Renton,WA +178989,Research College of Nursing,Kansas City,MO +149763,Resurrection University,Chicago,IL +217420,Rhode Island College,Providence,RI +217493,Rhode Island School of Design,Providence,RI +221351,Rhodes College,Memphis,TN +227757,Rice University,Houston,TX +107743,Rich Mountain Community College,Mena,AR +233338,Richard Bland College of the College of William and Mary,Petersburg,VA +227766,Richland College,Dallas,TX +148292,Richland Community College,Decatur,IL +199449,Richmond Community College,Hamlet,NC +441104,Richmont Graduate University,Chattanooga,TN +186283,Rider University,Lawrenceville,NJ +175236,Ridgewater College,Willmar,MN +136774,Ringling College of Art and Design,Sarasota,FL +475185,Rio Grande Bible Institute,Edinburg,TX +121886,Rio Hondo College,Whittier,CA +105668,Rio Salado College,Tempe,AZ +239628,Ripon College,Ripon,WI +436304,River Parishes Community College,Gonzales,LA +183114,River Valley Community College,Claremont,NH +173063,Riverland Community College,Austin,MN +121901,Riverside City College,Riverside,CA +233408,Riverside College of Health Careers,Newport News,VA +183211,Rivier University,Nashua,NH +221397,Roane State Community College,Harriman,TN +233426,Roanoke College,Salem,VA +199467,Roanoke-Chowan Community College,Ahoskie,NC +215655,Robert Morris University,Moon Township,PA +148335,Robert Morris University Illinois,Chicago,IL +194958,Roberts Wesleyan College,Rochester,NY +199476,Robeson Community College,Lumberton,NC +170967,Rochester College,Rochester Hills,MI +174738,Rochester Community and Technical College,Rochester,MN +195003,Rochester Institute of Technology,Rochester,NY +148380,Rock Valley College,Rockford,IL +195049,Rockefeller University,New York,NY +148405,Rockford University,Rockford,IL +179043,Rockhurst University,Kansas City,MO +199485,Rockingham Community College,Wentworth,NC +195058,Rockland Community College,Suffern,NY +180595,Rocky Mountain College,Billings,MT +127945,Rocky Mountain College of Art and Design,Lakewood,CO +475495,Rocky Mountain University of Health Professions,Provo,UT +480790,Rocky Vista University,Parker,CO +217518,Roger Williams University,Bristol,RI +409616,Roger Williams University School of Law,Bristol,RI +207661,Rogers State University,Claremore,OK +209940,Rogue Community College,Grants Pass,OR +136950,Rollins College,Winter Park,FL +148487,Roosevelt University,Chicago,IL +145558,Rosalind Franklin University of Medicine and Science,North Chicago,IL +207670,Rose State College,Midwest City,OK +439899,Rosedale Bible College,Irwin,OH +215682,Rosedale Technical Institute,Pittsburgh,PA +152318,Rose-Hulman Institute of Technology,Terre Haute,IN +445735,Roseman University of Health Sciences,Henderson,NV +215691,Rosemont College,Rosemont,PA +452081,Ross College-Sylvania,Sylvania,OH +183877,Rowan College at Burlington County,Pemberton,NJ +184791,Rowan College at Gloucester County,Sewell,NJ +184782,Rowan University,Glassboro,NJ +199494,Rowan-Cabarrus Community College,Salisbury,NC +167631,Roxbury Community College,Roxbury Crossing,MA +148511,Rush University,Chicago,IL +176318,Rust College,Holly Springs,MS +186371,Rutgers University-Camden,Camden,NJ +186380,Rutgers University-New Brunswick,New Brunswick,NJ +186399,Rutgers University-Newark,Newark,NJ +449506,SABER College,Miami,FL +122180,Sacramento City College,Sacramento,CA +172033,Sacred Heart Major Seminary,Detroit,MI +239637,Sacred Heart School of Theology,Franklin,WI +130253,Sacred Heart University,Fairfield,CT +122205,Saddleback College,Mission Viejo,CA +476948,SAE Institute of Technology-Atlanta,Atlanta,GA +446525,SAE Institute of Technology-Nashville,Nashville,TN +410520,Sage College,Moreno Valley,CA +441070,Saginaw Chippewa Tribal College,Mount Pleasant,MI +172051,Saginaw Valley State University,University Center,MI +154235,Saint Ambrose University,Davenport,IA +183239,Saint Anselm College,Manchester,NH +149028,Saint Anthony College of Nursing,Rockford,IL +148876,Saint Augustine College,Chicago,IL +199582,Saint Augustine's University,Raleigh,NC +157632,Saint Catharine College,Saint Catharine,KY +216047,Saint Charles Borromeo Seminary-Overbrook,Wynnewood,PA +174783,Saint Cloud State University,Saint Cloud,MN +227845,Saint Edward's University,Austin,TX +195702,Saint Elizabeth College of Nursing-Utica,Utica,NY +148575,Saint Francis Medical Center College of Nursing,Peoria,IL +215743,Saint Francis University,Loretto,PA +195720,Saint John Fisher College,Rochester,NY +137272,Saint John Vianney College Seminary,Miami,FL +137281,Saint Johns River State College,Palatka,FL +167677,Saint John's Seminary,Brighton,MA +174792,Saint Johns University,Collegeville,MN +160409,Saint Joseph Seminary College,St. Benedict,LA +152363,Saint Josephs College,Rensselaer,IN +161518,Saint Joseph's College of Maine,Standish,ME +195544,Saint Joseph's College-New York,Brooklyn,NY +215770,Saint Joseph's University,Philadelphia,PA +137032,Saint Leo University,Saint Leo,FL +179256,Saint Louis Christian College,Florissant,MO +179308,Saint Louis Community College,Saint Louis,MO +179159,Saint Louis University,Saint Louis,MO +179450,Saint Luke's College of Health Sciences,Kansas City,MO +236452,Saint Martin's University,Lacey,WA +152381,Saint Mary-of-the-Woods College,Saint Mary of the Woods,IN +152390,Saint Mary's College,Notre Dame,IN +123554,Saint Mary's College of California,Moraga,CA +174817,Saint Mary's University of Minnesota,Winona,MN +152451,Saint Meinrad School of Theology,St. Meinrad,IN +231059,Saint Michael's College,Colchester,VT +239716,Saint Norbert College,De Pere,WI +175041,Saint Paul College,Saint Paul,MN +179317,Saint Paul School of Theology,Leawood,KS +186432,Saint Peter's University,Jersey City,NJ +215798,Saint Vincent College,Latrobe,PA +136701,Saint Vincent de Paul Regional Seminary,Boynton Beach,FL +215813,Saint Vincent Seminary,Latrobe,PA +195580,Saint Vladimirs Orthodox Theological Seminary,Yonkers,NY +148627,Saint Xavier University,Chicago,IL +199607,Salem College,Winston Salem,NC +186469,Salem Community College,Carneys Point,NJ +237783,Salem International University,Salem,WV +167729,Salem State University,Salem,MA +155830,Salina Area Technical College,Salina,KS +163851,Salisbury University,Salisbury,MD +180647,Salish Kootenai College,Pablo,MT +230746,Salt Lake Community College,Salt Lake City,UT +466523,Salter College-Chicopee,Chicopee,MA +167738,Salter College-West Boylston,West Boylston,MA +214564,Salus University,Elkins Park,PA +217536,Salve Regina University,Newport,RI +227881,Sam Houston State University,Huntsville,TX +195289,Samaritan Hospital School of Nursing,Troy,NY +102049,Samford University,Birmingham,AL +199625,Sampson Community College,Clinton,NC +122296,Samuel Merritt University,Oakland,CA +227924,San Antonio College,San Antonio,TX +123527,San Bernardino Valley College,San Bernardino,CA +112084,San Diego Christian College,Santee,CA +122339,San Diego City College,San Diego,CA +122375,San Diego Mesa College,San Diego,CA +122384,San Diego Miramar College,San Diego,CA +122409,San Diego State University,San Diego,CA +122454,San Francisco Art Institute,San Francisco,CA +122506,San Francisco Conservatory of Music,San Francisco,CA +122597,San Francisco State University,San Francisco,CA +122603,San Francisco Theological Seminary,San Anselmo,CA +227979,San Jacinto Community College,Pasadena,TX +122649,San Joaquin College of Law,Clovis,CA +122658,San Joaquin Delta College,Stockton,CA +122685,San Joaquin Valley College-Visalia,Visalia,CA +122746,San Jose City College,San Jose,CA +122755,San Jose State University,San Jose,CA +430670,San Juan Bautista School of Medicine,Caguas,PR +188100,San Juan College,Farmington,NM +199634,Sandhills Community College,Pinehurst,NC +481535,Sanford Burnham Prybis Medical Discovery Institute,La Jolla,CA +420495,Sanford-Brown College-Atlanta,Atlanta,GA +475291,Sanford-Brown College-Brooklyn Center,Brooklyn Center,MN +146010,Sanford-Brown College-Chicago,Chicago,IL +404514,Sanford-Brown College-Dallas,Dallas,TX +179201,Sanford-Brown College-Fenton,Fenton,MO +404499,Sanford-Brown College-Houston,Houston,TX +446792,Sanford-Brown College-Las Vegas,Henderson,NV +174394,Sanford-Brown College-Mendota Heights,Mendota Heights,MN +420501,Sanford-Brown College-Middleburg Heights,Middleburg Heights,OH +456296,Sanford-Brown College-Online,Tampa,FL +440925,Sanford-Brown College-Orlando,Orlando,FL +450465,Sanford-Brown College-San Antonio-San Antonio,San Antonio,TX +446808,Sanford-Brown College-Seattle,Tukwila,WA +134680,Sanford-Brown College-Tampa,Tampa,FL +234216,Sanford-Brown College-Tysons Corner,McLean,VA +385008,Sanford-Brown Institute-Ft Lauderdale,Fort Lauderdale,FL +404505,Sanford-Brown Institute-Jacksonville,Jacksonville,FL +121619,Santa Ana College,Santa Ana,CA +122834,Santa Barbara Business College-Bakersfield,Bakersfield,CA +122852,Santa Barbara Business College-Santa Maria,Santa Maria,CA +433420,Santa Barbara Business College-Ventura,Ventura,CA +122889,Santa Barbara City College,Santa Barbara,CA +122931,Santa Clara University,Santa Clara,CA +137096,Santa Fe College,Gainesville,FL +188137,Santa Fe Community College,Santa Fe,NM +188146,Santa Fe University of Art and Design,Santa Fe,NM +122977,Santa Monica College,Santa Monica,CA +123013,Santa Rosa Junior College,Santa Rosa,CA +399212,Santiago Canyon College,Orange,CA +195304,Sarah Lawrence College,Bronxville,NY +148672,Sauk Valley Community College,Dixon,IL +140951,Savannah College of Art and Design,Savannah,GA +140960,Savannah State University,Savannah,GA +140942,Savannah Technical College,Savannah,GA +123095,Saybrook University,Oakland,CA +192156,SBI Campus-An Affiliate of Sanford-Brown,Melville,NY +195322,Schenectady County Community College,Schenectady,NY +404338,Schiller International University,Largo,FL +143048,School of the Art Institute of Chicago,Chicago,IL +166984,School of the Museum of Fine Arts-Boston,Boston,MA +197151,School of Visual Arts,New York,NY +172200,Schoolcraft College,Livonia,MI +228042,Schreiner University,Kerrville,TX +105747,Scottsdale Community College,Scottsdale,AZ +123165,Scripps College,Claremont,CA +236513,Seattle Central College,Seattle,WA +439914,Seattle Institute of Oriental Medicine,Seattle,WA +236577,Seattle Pacific University,Seattle,WA +236595,Seattle University,Seattle,WA +102058,Selma University,Selma,AL +243498,Seminario Evangelico de Puerto Rico,San Juan,PR +207740,Seminole State College,Seminole,OK +137209,Seminole State College of Florida,Sanford,FL +232885,Sentara College of Health Sciences,Chesapeake,VA +475839,Sessions College for Professional Design,Tempe,AZ +186584,Seton Hall University,South Orange,NJ +215947,Seton Hill University,Greensburg,PA +221519,Sewanee-The University of the South,Sewanee,TN +155858,Seward County Community College and Area Technical School,Liberal,KS +123280,Shasta Bible College and Graduate School,Redding,CA +123299,Shasta College,Redding,CA +199643,Shaw University,Raleigh,NC +148821,Shawnee Community College,Ullin,IL +205443,Shawnee State University,Portsmouth,OH +102067,Shelton State Community College,Tuscaloosa,AL +233541,Shenandoah University,Winchester,VA +237792,Shepherd University,Shepherdstown,WV +461485,Shepherds Theological Seminary,Cary,NC +240666,Sheridan College,Sheridan,WY +218751,Sherman College of Straight Chiropractic,Spartanburg,SC +480499,Shiloh University,Kalona,IA +148849,Shimer College,Chicago,IL +216010,Shippensburg University of Pennsylvania,Shippensburg,PA +195438,Sh'or Yoshuv Rabbinical College,Lawrence,NY +236610,Shoreline Community College,Shoreline,WA +107840,Shorter College,N Little Rock,AR +140988,Shorter University,Rome,GA +448309,Shorter University-College of Adult & Professional Programs,Marietta,GA +195474,Siena College,Loudonville,NY +172264,Siena Heights University,Adrian,MI +123341,Sierra College,Rocklin,CA +182458,Sierra Nevada College,Incline Village,NV +239743,Silver Lake College of the Holy Family,Manitowoc,WI +167783,Simmons College,Boston,MA +461759,Simmons College of Kentucky,Louisville,KY +154350,Simpson College,Indianola,IA +123457,Simpson University,Redding,CA +205470,Sinclair Community College,Dayton,OH +219374,Sinte Gleska University,Mission,SD +219240,Sioux Falls Seminary,Sioux Falls,SD +219408,Sisseton Wahpeton College,Sisseton,SD +231068,SIT Graduate Institute,Brattleboro,VT +200466,Sitting Bull College,Fort Yates,ND +236638,Skagit Valley College,Mount Vernon,WA +195526,Skidmore College,Saratoga Springs,NY +123509,Skyline College,San Bruno,CA +261931,Skyline College-Roanoke,Roanoke,VA +216038,Slippery Rock University of Pennsylvania,Slippery Rock,PA +167835,Smith College,Northampton,MA +102076,Snead State Community College,Boaz,AL +230597,Snow College,Ephraim,UT +110778,Sofia University,Palo Alto,CA +163921,Sojourner-Douglass College,Baltimore,MD +399911,Soka University of America,Aliso Viejo,CA +123563,Solano Community College,Fairfield,CA +459356,SOLEX College,Wheeling,IL +157711,Somerset Community College,Somerset,KY +123572,Sonoma State University,Rohnert Park,CA +481094,Sotheby's Institute of Art-NY,New York,NY +107974,South Arkansas Community College,El Dorado,AR +123633,South Baylo University,Anaheim,CA +218733,South Carolina State University,Orangeburg,SC +173911,South Central College,North Mankato,MN +160913,South Central Louisiana Technical College-Young Memorial Campus,Morgan City,LA +123642,South Coast College,Orange,CA +220552,South College,Knoxville,TN +198242,South College-Asheville,Asheville,NC +219347,South Dakota School of Mines and Technology,Rapid City,SD +219356,South Dakota State University,Brookings,SD +366003,South Florida Bible College and Theological Seminary,Deerfield Beach,FL +137315,South Florida State College,Avon Park,FL +482699,South Georgia State College,Douglas,GA +141006,South Georgia Technical College,Americus,GA +216083,South Hills School of Business & Technology,State College,PA +434061,South Louisiana Community College,Lafayette,LA +105792,South Mountain Community College,Phoenix,AZ +197850,South Piedmont Community College,Polkton,NC +228158,South Plains College,Levelland,TX +236656,South Puget Sound Community College,Olympia,WA +236504,South Seattle College,Seattle,WA +149365,South Suburban College,South Holland,IL +409315,South Texas College,McAllen,TX +228194,South Texas College of Law,Houston,TX +468006,South University-Accelerated Graduate Programs,Atlanta,GA +480073,South University-Austin,Austin,TX +480082,South University-Cleveland,Cleveland,OH +251312,South University-Columbia,Columbia,SC +481720,South University-High Point,High Point,NC +101116,South University-Montgomery,Montgomery,AL +468024,South University-Novi,Novi,MI +459259,South University–Richmond,Glen Allen,VA +139579,South University-Savannah,Savannah,GA +475121,South University–Savannah Online,Savannah,GA +449898,South University-Tampa,Tampa,FL +224776,South University-The Art Institute of Dallas,Dallas,TX +468015,South University-The Art Institute of Fort Worth,Fort Worth,TX +459268,South University–Virginia Beach,Virginia Beach,VA +133465,South University-West Palm Beach,Royal Palm Beach,FL +156338,Southcentral Kentucky Community and Technical College,Bowling Green,KY +107637,Southeast Arkansas College,Pine Bluff,AR +181640,Southeast Community College Area,Lincoln,NE +157739,Southeast Kentucky Community and Technical College,Cumberland,KY +417734,Southeast Missouri Hospital College of Nursing and Health Sciences,Cape Girardeau,MO +179557,Southeast Missouri State University,Cape Girardeau,MO +219426,Southeast Technical Institute,Sioux Falls,SD +176336,Southeastern Baptist College,Laurel,MS +199759,Southeastern Baptist Theological Seminary,Wake Forest,NC +102261,Southeastern Bible College,Birmingham,AL +443270,Southeastern College-Jacksonville,Jacksonville,FL +428170,Southeastern College-West Palm Beach,Greenacres,FL +154378,Southeastern Community College-West Burlington,West Burlington,IA +199722,Southeastern Community College-Whiteville,Whiteville,NC +148937,Southeastern Illinois College,Harrisburg,IL +160612,Southeastern Louisiana University,Hammond,LA +207847,Southeastern Oklahoma State University,Durant,OK +368911,Southeastern Technical College,Vidalia,GA +137564,Southeastern University,Lakeland,FL +221661,Southern Adventist University,Collegedale,TN +107983,Southern Arkansas University Main Campus,Magnolia,AR +107992,Southern Arkansas University Tech,Camden,AR +123952,Southern California Institute of Architecture,Los Angeles,CA +399869,Southern California Institute of Technology,Anaheim,CA +117575,Southern California Seminary,El Cajon,CA +117672,Southern California University of Health Sciences,Whittier,CA +459222,Southern California University SOMA,Los Angeles,CA +221670,Southern College of Optometry,Memphis,TN +130493,Southern Connecticut State University,New Haven,CT +139986,Southern Crescent Technical College,Griffin,GA +149222,Southern Illinois University-Carbondale,Carbondale,IL +149231,Southern Illinois University-Edwardsville,Edwardsville,IL +161545,Southern Maine Community College,South Portland,ME +228246,Southern Methodist University,Dallas,TX +206862,Southern Nazarene University,Bethany,OK +183026,Southern New Hampshire University,Manchester,NH +210146,Southern Oregon University,Ashland,OR +141097,Southern Polytechnic State University,Marietta,GA +205966,Southern State Community College,Hillsboro,OH +366553,Southern Technical College-Fort Myers,Fort Myers,FL +446552,Southern Technical College-Orlando,Orlando,FL +251260,Southern Union State Community College,Wadley,AL +160621,Southern University and A & M College,Baton Rouge,LA +160630,Southern University at New Orleans,New Orleans,LA +160649,Southern University at Shreveport,Shreveport,LA +440916,Southern University Law Center,Baton Rouge,LA +230603,Southern Utah University,Cedar City,UT +231086,Southern Vermont College,Bennington,VT +233611,Southern Virginia University,Buena Vista,VA +217776,Southern Wesleyan University,Central,SC +237817,Southern West Virginia Community and Technical College,Mount Gay,WV +233082,Southside Regional Medical Center Professional Schools,Colonial Heights,VA +233639,Southside Virginia Community College,Alberta,VA +413644,Southwest Acupuncture College-Albuquerque,Albuquerque,NM +436261,Southwest Acupuncture College-Boulder,Boulder,CO +366605,Southwest Acupuncture College-Santa Fe,Santa Fe,NM +179326,Southwest Baptist University,Bolivar,MO +420246,Southwest College of Naturopathic Medicine & Health Sciences,Tempe,AZ +382911,Southwest Collegiate Institute for the Deaf,Big Spring,TX +141158,Southwest Georgia Technical College,Thomasville,GA +442879,Southwest Institute of Healing Arts,Tempe,AZ +175078,Southwest Minnesota State University,Marshall,MN +176354,Southwest Mississippi Community College,Summit,MS +221485,Southwest Tennessee Community College,Memphis,TN +228316,Southwest Texas Junior College,Uvalde,TX +451556,Southwest University at El Paso,El Paso,TX +402776,Southwest University of Visual Arts-Albuquerque,Albuquerque,NM +104188,Southwest University of Visual Arts-Tucson,Tucson,AZ +233648,Southwest Virginia Community College,Richlands,VA +239910,Southwest Wisconsin Technical College,Fennimore,WI +228468,Southwestern Adventist University,Keene,TX +228325,Southwestern Assemblies of God University,Waxahachie,TX +228486,Southwestern Christian College,Terrell,TX +207856,Southwestern Christian University,Bethany,OK +123800,Southwestern College-Chula Vista,Chula Vista,CA +188207,Southwestern College-Santa Fe,Santa Fe,NM +155900,Southwestern College-Winfield,Winfield,KS +154396,Southwestern Community College-Creston,Creston,IA +199731,Southwestern Community College-Sylva,Sylva,NC +143215,Southwestern Illinois College,Belleville,IL +188216,Southwestern Indian Polytechnic Institute,Albuquerque,NM +123970,Southwestern Law School,Los Angeles,CA +172307,Southwestern Michigan College,Dowagiac,MI +207865,Southwestern Oklahoma State University,Weatherford,OK +210155,Southwestern Oregon Community College,Coos Bay,OR +228343,Southwestern University,Georgetown,TX +160579,SOWELA Technical Community College,Lake Charles,LA +157757,Spalding University,Louisville,KY +207254,Spartan College of Aeronautics and Technology,Tulsa,OK +218830,Spartanburg Community College,Spartanburg,SC +218821,Spartanburg Methodist College,Spartanburg,SC +141060,Spelman College,Atlanta,GA +433563,Spencerian College-Lexington,Lexington,KY +157766,Spencerian College-Louisville,Louisville,KY +148982,Spertus College,Chicago,IL +236692,Spokane Community College,Spokane,WA +236708,Spokane Falls Community College,Spokane,WA +148991,Spoon River College,Canton,IL +172334,Spring Arbor University,Spring Arbor,MI +102234,Spring Hill College,Mobile,AL +167899,Springfield College,Springfield,MA +475273,Springfield College-School of Professional and Continuing Studies,Springfield,MA +167905,Springfield Technical Community College,Springfield,MA +199698,St Andrews University,Laurinburg,NC +195155,St Bernard's School of Theology and Ministry,Rochester,NY +195164,St Bonaventure University,Saint Bonaventure,NY +175005,St Catherine University,Saint Paul,MN +262031,St Charles Community College,Cottleville,MO +172291,St Clair County Community College,Port Huron,MI +174756,St Cloud Technical and Community College,Saint Cloud,MN +195173,St Francis College,Brooklyn Heights,NY +163976,St John's College,Annapolis,MD +123855,St John's Seminary,Camarillo,CA +195809,St John's University-New York,Queens,NY +183248,St Joseph School of Nursing-Nashua,Nashua,NH +195191,St Joseph's College of Nursing at St Joseph's Hospital Health Center,Syracuse,NY +195216,St Lawrence University,Canton,NY +442426,St Louis College of Health Careers-Fenton,Fenton,MO +179511,St Louis College of Health Careers-St Louis,Saint Louis,MO +179265,St Louis College of Pharmacy,Saint Louis,MO +154262,St Luke's College,Sioux City,IA +163912,St Mary's College of Maryland,St. Mary's City,MD +228149,St Mary's University,San Antonio,TX +174844,St Olaf College,Northfield,MN +189811,St Paul's School of Nursing-Queens,Rego Park,NY +195784,St Paul's School of Nursing-Staten Island,Staten Island,NY +137078,St Petersburg College,Clearwater,FL +227854,St Philip's College,San Antonio,TX +137476,St Thomas University,Miami Gardens,FL +130448,St Vincent's College,Bridgeport,CT +207689,St. Gregory's University,Shawnee,OK +245652,St. John's College,Santa Fe,NM +148593,St. John's College-Department of Nursing,Springfield,IL +195243,St. Thomas Aquinas College,Sparkill,NY +446561,Stanbridge College,Irvine,CA +483814,Standard Healthcare Services-College of Nursing,Falls Church,VA +243744,Stanford University,Stanford,CA +199740,Stanly Community College,Albemarle,NC +205841,Stark State College,North Canton,OH +123916,Starr King School for Ministry,Berkeley,CA +135391,State College of Florida-Manatee-Sarasota,Bradenton,FL +179539,State Fair Community College,Sedalia,MO +177977,State Technical College of Missouri,Linn,MO +196176,State University of New York at New Paltz,New Paltz,NY +448600,Stautzenberger College-Brecksville,Brecksville,OH +205887,Stautzenberger College-Maumee,Maumee,OH +228431,Stephen F Austin State University,Nacogdoches,TX +179548,Stephens College,Columbia,MO +231095,Sterling College-Craftsbury Common,Craftsbury Common,VT +155937,Sterling College-Sterling,Sterling,KS +137546,Stetson University,DeLand,FL +186867,Stevens Institute of Technology,Hoboken,NJ +460899,Stevens-Henager College-Boise,Boise,ID +474906,Stevens-Henager College-Idaho Falls,Idaho Falls,ID +446677,Stevens-Henager College-Logan,Logan,UT +438151,Stevens-Henager College-Murray,Murray,UT +230630,Stevens-Henager College-Orem,Orem,UT +477950,Stevens-Henager College-St. George,St. George,UT +230621,Stevens-Henager College-West Haven,West Haven,UT +164173,Stevenson University,Stevenson,MD +178767,Stevens-The Institute of Business & Arts,Saint Louis,MO +102270,Stillman College,Tuscaloosa,AL +186876,Stockton University,Galloway,NJ +366340,Stone Child College,Box Elder,MT +167996,Stonehill College,Easton,MA +196097,Stony Brook University,Stony Brook,NY +438498,Stratford University,Fairfax,VA +450377,Strayer University-Alabama,Birmingham,AL +458885,Strayer University-Arkansas,Little Rock,AR +450298,Strayer University-Delaware,Newark,DE +131803,Strayer University-District of Columbia,Washington,DC +449038,Strayer University-Florida,Tampa,FL +458919,Strayer University-Georgia,Atlanta,GA +459994,Strayer University-Global Region,Washington,DC +458937,Strayer University-Louisiana,Metairie,LA +430184,Strayer University-Maryland,Suitland,MD +458955,Strayer University-Mississippi,Jackson,MS +453215,Strayer University-New Jersey,Cherry Hill,NJ +453163,Strayer University-North Carolina,Morrisville,NC +443784,Strayer University-Pennsylvania,Trevose,PA +458964,Strayer University-South Carolina,Greenville,SC +443766,Strayer University-Tennessee,Memphis,TN +458973,Strayer University-Texas,Austin,TX +233684,Strayer University-Virginia,Arlington,VA +456621,Strayer University-West Virginia,Scott Depot,WV +366395,Suffolk County Community College,Selden,NY +168005,Suffolk University,Boston,MA +228501,Sul Ross State University,Alpine,TX +157270,Sullivan College of Technology and Design,Louisville,KY +195988,Sullivan County Community College,Loch Sheldrake,NY +157793,Sullivan University,Louisville,KY +447953,SUM Bible College and Theological Seminary,Oakland,CA +181543,Summit Christian College,Gering,NE +208512,Sumner College,Portland,OR +196060,SUNY at Albany,Albany,NY +196079,SUNY at Binghamton,Vestal,NY +196158,SUNY at Fredonia,Fredonia,NY +196219,SUNY at Purchase College,Purchase,NY +189547,SUNY Broome Community College,Binghamton,NY +196130,SUNY Buffalo State,Buffalo,NY +196121,SUNY College at Brockport,Brockport,NY +196149,SUNY College at Cortland,Cortland,NY +196167,SUNY College at Geneseo,Geneseo,NY +196237,SUNY College at Old Westbury,Old Westbury,NY +196194,SUNY College at Oswego,Oswego,NY +196246,SUNY College at Plattsburgh,Plattsburgh,NY +196200,SUNY College at Potsdam,Potsdam,NY +196033,SUNY College of Agriculture and Technology at Cobleskill,Cobleskill,NY +196103,SUNY College of Environmental Science and Forestry,Syracuse,NY +196228,SUNY College of Optometry,New York,NY +196006,SUNY College of Technology at Alfred,Alfred,NY +196015,SUNY College of Technology at Canton,Canton,NY +196024,SUNY College of Technology at Delhi,Delhi,NY +196255,SUNY Downstate Medical Center,Brooklyn,NY +196264,SUNY Empire State College,Saratoga Springs,NY +196291,SUNY Maritime College,Throggs Neck,NY +196185,SUNY Oneonta,Oneonta,NY +196112,SUNY Polytechnic Institute,Utica,NY +197294,SUNY Westchester Community College,Valhalla,NY +199768,Surry Community College,Dobson,NC +216278,Susquehanna University,Selinsgrove,PA +247603,Sussex County Community College,Newton,NJ +216287,Swarthmore College,Swarthmore,PA +196389,Swedish Institute a College of Health Sciences,New York,NY +233718,Sweet Briar College,Sweet Briar,VA +196413,Syracuse University,Syracuse,NY +155973,Tabor College,Hillsboro,KS +236753,Tacoma Community College,Tacoma,WA +124113,Taft College,Taft,CA +454689,Taft University System,Denver,CO +102298,Talladega College,Talladega,AL +137759,Tallahassee Community College,Tallahassee,FL +137777,Talmudic College of Florida,Miami Beach,FL +186900,Talmudical Academy-New Jersey,Adelphia,NJ +196440,Talmudical Institute of Upstate New York,Rochester,NY +451404,Talmudical Seminary of Bobov,Brooklyn,NY +196431,Talmudical Seminary Oholei Torah,Brooklyn,NY +216311,Talmudical Yeshiva of Philadelphia,Philadelphia,PA +228529,Tarleton State University,Stephenville,TX +228547,Tarrant County College District,Fort Worth,TX +149310,Taylor Business Institute,Chicago,IL +449524,Taylor College,Belleview,FL +152530,Taylor University,Upland,IN +196468,Teachers College at Columbia University,New York,NY +196477,Technical Career Institutes,New York,NY +217712,Technical College of the Lowcountry,Beaufort,SC +149329,Telshe Yeshiva-Chicago,Chicago,IL +228608,Temple College,Temple,TX +216339,Temple University,Philadelphia,PA +221838,Tennessee State University,Nashville,TN +221847,Tennessee Technological University,Cookeville,TN +221856,Tennessee Temple University,Chattanooga,TN +221731,Tennessee Wesleyan College,Athens,TN +206011,Terra State Community College,Fremont,OH +228699,Texarkana College,Texarkana,TX +226152,Texas A & M International University,Laredo,TX +483036,Texas A & M University-Central Texas,Killeen,TX +228723,Texas A & M University-College Station,College Station,TX +224554,Texas A & M University-Commerce,Commerce,TX +224147,Texas A & M University-Corpus Christi,Corpus Christi,TX +228705,Texas A & M University-Kingsville,Kingsville,TX +224545,Texas A & M University-Texarkana,Texarkana,TX +228866,Texas Chiropractic College Foundation Inc,Pasadena,TX +228875,Texas Christian University,Fort Worth,TX +228884,Texas College,Tyler,TX +441487,Texas County Technical College,Houston,MO +430704,Texas Health and Science University,Austin,TX +228981,Texas Lutheran University,Seguin,TX +229063,Texas Southern University,Houston,TX +229319,Texas State Technical College-Harlingen,Harlingen,TX +408394,Texas State Technical College-Marshall,Marshall,TX +228680,Texas State Technical College-Waco,Waco,TX +229328,Texas State Technical College-West Texas,Sweetwater,TX +228459,Texas State University,San Marcos,TX +229115,Texas Tech University,Lubbock,TX +229337,Texas Tech University Health Sciences Center,Lubbock,TX +229160,Texas Wesleyan University,Fort Worth,TX +229179,Texas Woman's University,Denton,TX +216296,Thaddeus Stevens College of Technology,Lancaster,PA +138813,The Art Institute of Atlanta,Atlanta,GA +451820,The Art Institute of Austin,Austin,TX +450085,The Art Institute of Charleston,Charleston,SC +197832,The Art Institute of Charlotte,Charlotte,NC +200624,The Art Institute of Cincinnati-AIC College of Design,Cincinnati,OH +126702,The Art Institute of Colorado,Denver,CO +132338,The Art Institute of Fort Lauderdale,Fort Lauderdale,FL +222938,The Art Institute of Houston,Houston,TX +448345,The Art Institute of Indianapolis,Indianapolis,IN +182111,The Art Institute of Las Vegas,Henderson,NV +451796,The Art Institute of Michigan,Novi,MI +365055,The Art Institute of New York City,New York,NY +446668,The Art Institute of Ohio-Cincinnati,Cincinnati,OH +210942,The Art Institute of Philadelphia,Philadelphia,PA +428444,The Art Institute of Phoenix,Phoenix,AZ +210960,The Art Institute of Pittsburgh,Pittsburgh,PA +451662,The Art Institute of Pittsburgh-Online Division,Pittsburgh,PA +208239,The Art Institute of Portland,Portland,OR +452027,The Art Institute of Raleigh-Durham,Durham,NC +450049,The Art Institute of Salt Lake City,Draper,UT +458982,The Art Institute of San Antonio,San Antonio,TX +234492,The Art Institute of Seattle,Seattle,WA +482398,The Art Institute of St Louis,St Charles,MO +449010,The Art Institute of Tennessee-Nashville,Nashville,TN +444927,The Art Institute of Tucson,Tucson,AZ +458496,The Art Institute of Virginia Beach,Virginia Beach,VA +440341,The Art Institute of Washington,Arlington,VA +456010,The Art Institute of Washington-Dulles,Sterling,VA +470092,The Art Institute of Wisconsin,Milwaukee,WI +452018,The Art Institutes International–Kansas City,Lenexa,KS +173887,The Art Institutes International-Minnesota,Minneapolis,MN +210906,The Art Institutes of York-PA,York,PA +132408,The Baptist College of Florida,Graceville,FL +164933,The Boston Conservatory,Boston,MA +111188,The California Maritime Academy,Vallejo,CA +143978,The Chicago School of Professional Psychology at Chicago,Chicago,IL +455433,The Chicago School of Professional Psychology at Irvine,Irvine,CA +455664,The Chicago School of Professional Psychology at Los Angeles,Los Angeles,CA +459745,The Chicago School of Professional Psychology at Washington DC,Washington,DC +455682,The Chicago School of Professional Psychology at Westwood,Los Angeles,CA +201821,The Christ College of Nursing and Health Sciences,Cincinnati,OH +437635,The College of Health Care Professions-Austin,Austin,TX +480824,The College of Health Care Professions-Dallas,Dallas,TX +480833,The College of Health Care Professions-Fort Worth,Fort Worth,TX +142294,The College of Idaho,Caldwell,ID +187134,The College of New Jersey,Ewing,NJ +193645,The College of New Rochelle,New Rochelle,NY +195234,The College of Saint Rose,Albany,NY +174899,The College of Saint Scholastica,Duluth,MN +197285,The College of Westchester,White Plains,NY +206589,The College of Wooster,Wooster,OH +456542,The Commonwealth Medical College,Scranton,PA +434672,The Community College of Baltimore County,Baltimore,MD +430485,The Creative Center,Omaha,NE +235167,The Evergreen State College,Olympia,WA +191320,The General Theological Seminary,New York,NY +148177,The Illinois Institute of Art-Chicago,Chicago,IL +428286,The Illinois Institute of Art-Schaumburg,Schaumburg,IL +146241,The John Marshall Law School,Chicago,IL +192110,The Juilliard School,New York,NY +454184,The King’s College,New York,NY +439701,The King's University,Southlake,TX +161208,The Landing School,Arundel,ME +213598,The Lincoln University,Lincoln University,PA +117751,The Master's College and Seminary,Santa Clarita,CA +119544,The National Hispanic University,San Jose,CA +167057,The New England Conservatory of Music,Boston,MA +167321,The New England Institute of Art,Brookline,MA +193654,The New School,New York,NY +215637,The Restaurant School at Walnut Hill College,Philadelphia,PA +448804,The Robert B Miller College,Battle Creek,MI +195128,The Sage Colleges,Troy,NY +475228,The Santa Barbara and Ventura Colleges of Law–Santa Barbara,Santa Barbara,CA +125037,The Santa Barbara and Ventura Colleges of Law-Ventura,Ventura,CA +441131,The Seattle School of Theology & Psychology,Seattle,WA +157748,The Southern Baptist Theological Seminary,Louisville,KY +100751,The University of Alabama,Tuscaloosa,AL +202763,The University of Findlay,Findlay,OH +180489,The University of Montana,Missoula,MT +180692,The University of Montana-Western,Dillon,MT +137847,The University of Tampa,Tampa,FL +221740,The University of Tennessee-Chattanooga,Chattanooga,TN +221759,The University of Tennessee-Knoxville,Knoxville,TN +221768,The University of Tennessee-Martin,Martin,TN +227368,The University of Texas - Rio Grande Valley,Edinburg,TX +228769,The University of Texas at Arlington,Arlington,TX +228778,The University of Texas at Austin,Austin,TX +228787,The University of Texas at Dallas,Richardson,TX +228796,The University of Texas at El Paso,El Paso,TX +229027,The University of Texas at San Antonio,San Antonio,TX +228802,The University of Texas at Tyler,Tyler,TX +229300,The University of Texas Health Science Center at Houston,Houston,TX +228644,The University of Texas Health Science Center at San Antonio,San Antonio,TX +416801,The University of Texas MD Anderson Cancer Center,Houston,TX +228653,The University of Texas Medical Branch,Galveston,TX +229018,The University of Texas of the Permian Basin,Odessa,TX +215105,The University of the Arts,Philadelphia,PA +233897,The University of Virginia's College at Wise,Wise,VA +138354,The University of West Florida,Pensacola,FL +126012,The Wright Institute,Berkeley,CA +216357,Thiel College,Greenville,PA +124292,Thomas Aquinas College,Santa Paula,CA +161563,Thomas College,Waterville,ME +187046,Thomas Edison State University,Trenton,NJ +126049,Thomas Jefferson School of Law,San Diego,CA +216366,Thomas Jefferson University,Philadelphia,PA +157809,Thomas More College,Crestview Hills,KY +183275,Thomas More College of Liberal Arts,Merrimack,NH +233754,Thomas Nelson Community College,Hampton,VA +141167,Thomas University,Thomasville,GA +129808,Three Rivers Community College-Norwich,Norwich,CT +179645,Three Rivers Community College-Poplar Bluff,Poplar Bluff,MO +103778,Thunderbird School of Global Management,Glendale,AZ +233772,Tidewater Community College,Norfolk,VA +206048,Tiffin University,Tiffin,OH +420723,Tillamook Bay Community College,Tillamook,OR +141185,Toccoa Falls College,Toccoa Falls,GA +442781,Tohono O'Odham Community College,Sells,AZ +196565,Tompkins Cortland Community College,Dryden,NY +196583,Torah Temimah Talmudical Seminary,Brooklyn,NY +176406,Tougaloo College,Tougaloo,MS +196592,Touro College,New York,NY +459736,Touro University California,Vallejo,CA +459824,Touro University Nevada,Henderson,NV +459727,Touro University Worldwide,Los Alamitos,CA +164076,Towson University,Towson,MD +157818,Transylvania University,Lexington,KY +210234,Treasure Valley Community College,Ontario,OR +221892,Trevecca Nazarene University,Nashville,TN +448859,Triangle Tech Inc-Bethlehem,Bethlehem,PA +216454,Triangle Tech Inc-Dubois,Falls Creek,PA +216427,Triangle Tech Inc-Erie,Erie,PA +216445,Triangle Tech Inc-Greensburg,Greensburg,PA +216436,Triangle Tech Inc-Pittsburgh,Pittsburgh,PA +443377,Triangle Tech Inc-Sunbury,Sunbury,PA +460747,Tribeca Flashpoint College,Chicago,IL +199795,Tri-County Community College,Murphy,NC +218885,Tri-County Technical College,Pendleton,SC +218894,Trident Technical College,Charleston,SC +450979,Trident University International,Cypress,CA +152567,Trine University,Angola,IN +414878,Trine University-Regional/Non-Traditional Campuses,Fort Wayne,IN +128258,Trinidad State Junior College,Trinidad,CO +137953,Trinity Baptist College,Jacksonville,FL +200484,Trinity Bible College,Ellendale,ND +149505,Trinity Christian College,Palos Heights,IL +130590,Trinity College,Hartford,CT +137962,Trinity College of Florida,Trinity,FL +146755,Trinity College of Nursing & Health Sciences,Rock Island,IL +216463,Trinity Episcopal School for Ministry,Ambridge,PA +135610,Trinity International University-Florida,Davie,FL +149514,Trinity International University-Illinois,Deerfield,IL +123448,Trinity Law School,Santa Ana,CA +235769,Trinity Lutheran College,Everett,WA +206215,Trinity Lutheran Seminary,Columbus,OH +229267,Trinity University,San Antonio,TX +225308,Trinity Valley Community College,Athens,TX +131876,Trinity Washington University,Washington,DC +206154,Tri-State Bible College,South Point,OH +130581,Tri-State College of Acupuncture,New York,NY +149532,Triton College,River Grove,IL +196653,Trocaire College,Buffalo,NY +102368,Troy University,Troy,AL +182500,Truckee Meadows Community College,Reno,NV +141237,Truett-McConnell College,Cleveland,GA +178615,Truman State University,Kirksville,MO +206224,Trumbull Business College,Warren,OH +168148,Tufts University,Medford,MA +160755,Tulane University of Louisiana,New Orleans,LA +207935,Tulsa Community College,Tulsa,OK +207962,Tulsa Welding School-Tulsa-Tulsa,Tulsa,OK +130606,Tunxis Community College,Farmington,CT +200527,Turtle Mountain Community College,Belcourt,ND +221953,Tusculum College,Greeneville,TN +102377,Tuskegee University,Tuskegee,AL +229355,Tyler Junior College,Tyler,TX +196699,Ulster County Community College,Stone Ridge,NY +441371,Ultimate Medical Academy-Clearwater,Clearwater,FL +450173,Ultimate Medical Academy-Tampa,Tampa,FL +481252,Ultrasound Medical Institute,Royal Palm Beach,FL +210270,Umpqua Community College,Roseburg,OR +246789,Unification Theological Seminary,Barrytown,NY +157863,Union College-Barbourville,Barbourville,KY +181738,Union College-Lincoln,Lincoln,NE +196866,Union College-Schenectady,Schenectady,NY +187198,Union County College,Cranford,NJ +446932,Union Graduate College,Schenectady,NY +206279,Union Institute & University,Cincinnati,OH +233842,Union Presbyterian Seminary,Richmond,VA +196884,Union Theological Seminary in the City of New York,New York,NY +221971,Union University,Jackson,TN +124681,United Education Institute-Huntington Park Campus,Huntington Park,CA +128328,United States Air Force Academy,USAFA,CO +130624,United States Coast Guard Academy,New London,CT +197027,United States Merchant Marine Academy,Kings Point,NY +197036,United States Military Academy,West Point,NY +164155,United States Naval Academy,Annapolis,MD +102395,United States Sports Academy,Daphne,AL +447050,United States University,Chula Vista,CA +197018,United Talmudical Seminary,Brooklyn,NY +206288,United Theological Seminary,Dayton,OH +175139,United Theological Seminary of the Twin Cities,New Brighton,MN +200554,United Tribes Technical College,Bismarck,ND +459204,Unitek College,Fremont,CA +161572,Unity College,Unity,ME +446598,Universal College of Healing Arts,Omaha,NE +106041,Universal Technical Institute of Arizona Inc,Avondale,AZ +376385,Universal Technology College of Puerto Rico,Aguadilla,PR +241191,Universidad Adventista de las Antillas,Mayaguez,PR +241225,Universidad Central de Bayamon,Bayamón,PR +243568,Universidad Central Del Caribe,Bayamon,PR +243346,Universidad Del Este,Carolina,PR +243443,Universidad del Sagrado Corazon,Santurce,PR +243601,Universidad Del Turabo,Gurabo,PR +475811,Universidad Internacional Iberoamericana,Arecibo,PR +241739,Universidad Metropolitana,Cupey,PR +441690,Universidad Pentecostal Mizpa,Rio Piedras,PR +243577,Universidad Politecnica de Puerto Rico,Hato Rey,PR +241614,Universidad Teologica del Caribe,Trujillo Alto,PR +196088,University at Buffalo,Buffalo,NY +363934,University of Advancing Technology,Tempe,AZ +200800,University of Akron Main Campus,Akron,OH +200846,University of Akron Wayne College,Orrville,OH +100663,University of Alabama at Birmingham,Birmingham,AL +100706,University of Alabama in Huntsville,Huntsville,AL +102553,University of Alaska Anchorage,Anchorage,AK +102614,University of Alaska Fairbanks,Fairbanks,AK +102632,University of Alaska Southeast,Juneau,AK +442930,University of Antelope Valley,Lancaster,CA +104179,University of Arizona,Tucson,AZ +106397,University of Arkansas,Fayetteville,AR +106245,University of Arkansas at Little Rock,Little Rock,AR +106485,University of Arkansas at Monticello,Monticello,AR +106412,University of Arkansas at Pine Bluff,Pine Bluff,AR +106999,University of Arkansas Community College-Batesville,Batesville,AR +107725,University of Arkansas Community College-Hope,Hope,AR +107585,University of Arkansas Community College-Morrilton,Morrilton,AR +106263,University of Arkansas for Medical Sciences,Little Rock,AR +108092,University of Arkansas-Fort Smith,Fort Smith,AR +161873,University of Baltimore,Baltimore,MD +128744,University of Bridgeport,Bridgeport,CT +110635,University of California-Berkeley,Berkeley,CA +110644,University of California-Davis,Davis,CA +110398,University of California-Hastings College of Law,San Francisco,CA +110653,University of California-Irvine,Irvine,CA +110662,University of California-Los Angeles,Los Angeles,CA +445188,University of California-Merced,Merced,CA +110671,University of California-Riverside,Riverside,CA +110680,University of California-San Diego,La Jolla,CA +110699,University of California-San Francisco,San Francisco,CA +110705,University of California-Santa Barbara,Santa Barbara,CA +110714,University of California-Santa Cruz,Santa Cruz,CA +106704,University of Central Arkansas,Conway,AR +132903,University of Central Florida,Orlando,FL +176965,University of Central Missouri,Warrensburg,MO +206941,University of Central Oklahoma,Edmond,OK +237312,University of Charleston,Charleston,WV +144050,University of Chicago,Chicago,IL +201955,University of Cincinnati-Blue Ash College,Blue Ash,OH +201946,University of Cincinnati-Clermont College,Batavia,OH +201885,University of Cincinnati-Main Campus,Cincinnati,OH +126614,University of Colorado Boulder,Boulder,CO +126580,University of Colorado Colorado Springs,Colorado Springs,CO +126562,University of Colorado Denver,Denver,CO +129020,University of Connecticut,Storrs,CT +224323,University of Dallas,Irving,TX +202480,University of Dayton,Dayton,OH +130943,University of Delaware,Newark,DE +127060,University of Denver,Denver,CO +169716,University of Detroit Mercy,Detroit,MI +153278,University of Dubuque,Dubuque,IA +447801,University of East-West Medicine,Sunnyvale,CA +150534,University of Evansville,Evansville,IN +134130,University of Florida,Gainesville,FL +457402,University of Fort Lauderdale,Lauderhill,FL +139959,University of Georgia,Athens,GA +180258,University of Great Falls,Great Falls,MT +240754,University of Guam,Mangilao,GU +129525,University of Hartford,West Hartford,CT +141565,University of Hawaii at Hilo,Hilo,HI +141574,University of Hawaii at Manoa,Honolulu,HI +141839,University of Hawaii Maui College,Kahului,HI +141981,University of Hawaii-West Oahu,Kapolei,HI +160065,University of Holy Cross,New Orleans,LA +225511,University of Houston,Houston,TX +225414,University of Houston-Clear Lake,Houston,TX +225432,University of Houston-Downtown,Houston,TX +225502,University of Houston-Victoria,Victoria,TX +142285,University of Idaho,Moscow,ID +145600,University of Illinois at Chicago,Chicago,IL +148654,University of Illinois at Springfield,Springfield,IL +145637,University of Illinois at Urbana-Champaign,Champaign,IL +151263,University of Indianapolis,Indianapolis,IN +153658,University of Iowa,Iowa City,IA +200156,University of Jamestown,Jamestown,ND +155317,University of Kansas,Lawrence,KS +157085,University of Kentucky,Lexington,KY +117140,University of La Verne,La Verne,CA +160658,University of Louisiana at Lafayette,Lafayette,LA +159993,University of Louisiana at Monroe,Monroe,LA +157289,University of Louisville,Louisville,KY +161253,University of Maine,Orono,ME +161217,University of Maine at Augusta,Augusta,ME +161226,University of Maine at Farmington,Farmington,ME +161235,University of Maine at Fort Kent,Fort Kent,ME +161244,University of Maine at Machias,Machias,ME +161341,University of Maine at Presque Isle,Presque Isle,ME +437097,University of Management and Technology,Arlington,VA +200217,University of Mary,Bismarck,ND +226471,University of Mary Hardin-Baylor,Belton,TX +232681,University of Mary Washington,Fredericksburg,VA +163338,University of Maryland Eastern Shore,Princess Anne,MD +163259,University of Maryland-Baltimore,Baltimore,MD +163268,University of Maryland-Baltimore County,Baltimore,MD +163286,University of Maryland-College Park,College Park,MD +163204,University of Maryland-University College,Adelphi,MD +166708,University of Massachusetts Medical School Worcester,Worcester,MA +166629,University of Massachusetts-Amherst,Amherst,MA +166638,University of Massachusetts-Boston,Boston,MA +167987,University of Massachusetts-Dartmouth,North Dartmouth,MA +166513,University of Massachusetts-Lowell,Lowell,MA +220862,University of Memphis,Memphis,TN +135726,University of Miami,Coral Gables,FL +170976,University of Michigan-Ann Arbor,Ann Arbor,MI +171137,University of Michigan-Dearborn,Dearborn,MI +171146,University of Michigan-Flint,Flint,MI +174075,University of Minnesota-Crookston,Crookston,MN +174233,University of Minnesota-Duluth,Duluth,MN +174251,University of Minnesota-Morris,Morris,MN +456959,University of Minnesota-Rochester,Rochester,MN +174066,University of Minnesota-Twin Cities,Minneapolis,MN +176017,University of Mississippi,University,MS +178396,University of Missouri-Columbia,Columbia,MO +178402,University of Missouri-Kansas City,Kansas City,MO +178420,University of Missouri-St Louis,Saint Louis,MO +101693,University of Mobile,Mobile,AL +101709,University of Montevallo,Montevallo,AL +199069,University of Mount Olive,Mount Olive,NC +204185,University of Mount Union,Alliance,OH +181215,University of Nebraska at Kearney,Kearney,NE +181394,University of Nebraska at Omaha,Omaha,NE +181428,University of Nebraska Medical Center,Omaha,NE +181464,University of Nebraska-Lincoln,Lincoln,NE +182281,University of Nevada-Las Vegas,Las Vegas,NV +182290,University of Nevada-Reno,Reno,NV +161457,University of New England,Biddeford,ME +183071,University of New Hampshire at Manchester,Manchester,NH +183044,University of New Hampshire-Main Campus,Durham,NH +182829,University of New Hampshire-School of Law,Concord,NH +129941,University of New Haven,West Haven,CT +187958,University of New Mexico-Gallup Campus,Gallup,NM +187976,University of New Mexico-Los Alamos Campus,Los Alamos,NM +187985,University of New Mexico-Main Campus,Albuquerque,NM +188225,University of New Mexico-Taos Campus,Ranchos de Taos,NM +188049,University of New Mexico-Valencia County Campus,Los Lunas,NM +159939,University of New Orleans,New Orleans,LA +101879,University of North Alabama,Florence,AL +199111,University of North Carolina at Asheville,Asheville,NC +199120,University of North Carolina at Chapel Hill,Chapel Hill,NC +199139,University of North Carolina at Charlotte,Charlotte,NC +199148,University of North Carolina at Greensboro,Greensboro,NC +199281,University of North Carolina at Pembroke,Pembroke,NC +199184,University of North Carolina School of the Arts,Winston-Salem,NC +199218,University of North Carolina Wilmington,Wilmington,NC +200280,University of North Dakota,Grand Forks,ND +136172,University of North Florida,Jacksonville,FL +482680,University of North Georgia,Dahlonega,GA +227216,University of North Texas,Denton,TX +484905,University of North Texas at Dallas,Dallas,TX +228909,University of North Texas Health Science Center,Fort Worth,TX +127741,University of Northern Colorado,Greeley,CO +154095,University of Northern Iowa,Cedar Falls,IA +204486,University of Northwestern Ohio,Lima,OH +174491,University of Northwestern-St Paul,Saint Paul,MN +152080,University of Notre Dame,Notre Dame,IN +207342,University of Oklahoma-Health Sciences Center,Oklahoma City,OK +207500,University of Oklahoma-Norman Campus,Norman,OK +209551,University of Oregon,Eugene,OR +215062,University of Pennsylvania,Philadelphia,PA +450456,University of Phoenix-Alabama,Birmingham,AL +484613,University of Phoenix-Arizona,Tempe,AZ +484622,University of Phoenix-Arkansas,Little Rock,AR +484631,University of Phoenix-California,Costa Mesa,CA +484640,University of Phoenix-Colorado,Lone Tree,CO +448822,University of Phoenix-Connecticut,Norwalk,CT +484668,University of Phoenix-Florida,Orlando,FL +484677,University of Phoenix-Georgia,Sandy Springs,GA +420042,University of Phoenix-Hawaii,Honolulu,HI +440466,University of Phoenix-Idaho,Meridian,ID +442161,University of Phoenix-Illinois,Schaumburg,IL +443544,University of Phoenix-Indiana,Indianapolis,IN +446729,University of Phoenix-Iowa,Des Moines,IA +445391,University of Phoenix-Kentucky,Louisville,KY +484686,University of Phoenix-Louisiana,Baton Rouge,LA +434973,University of Phoenix-Maryland,Columbia,MD +440420,University of Phoenix-Massachusetts,Braintree,MA +484695,University of Phoenix-Michigan,Southfield,MI +445319,University of Phoenix-Minnesota,Saint Louis Park,MN +462390,University of Phoenix-Mississippi,Flowood,MS +484701,University of Phoenix-Missouri,Saint Louis,MO +484710,University of Phoenix-Nevada,Las Vegas,NV +445300,University of Phoenix-New Jersey,Jersey City,NJ +405997,University of Phoenix-New Mexico,Albuquerque,NM +484729,University of Phoenix-North Carolina,Charlotte,NC +439297,University of Phoenix-Ohio,Beachwood,OH +484738,University of Phoenix-Oklahoma,Oklahoma City,OK +432241,University of Phoenix-Oregon,Tigard,OR +484783,University of Phoenix-Pennsylvania,Philadelphia,PA +382063,University of Phoenix-Puerto Rico,Guaynabo,PR +448567,University of Phoenix-South Carolina,Columbia,SC +484747,University of Phoenix-Tennessee,Nashville,TN +484756,University of Phoenix-Texas,Houston,TX +380465,University of Phoenix-Utah,Salt Lake City,UT +484765,University of Phoenix-Virginia,Glen Allen,VA +432223,University of Phoenix-Washington,Tukwila,WA +450483,University of Phoenix-Washington DC,Washington,DC +440457,University of Phoenix-Wisconsin,Milwaukee,WI +157535,University of Pikeville,Pikeville,KY +215266,University of Pittsburgh-Bradford,Bradford,PA +215275,University of Pittsburgh-Greensburg,Greensburg,PA +215284,University of Pittsburgh-Johnstown,Johnstown,PA +215293,University of Pittsburgh-Pittsburgh Campus,Pittsburgh,PA +215309,University of Pittsburgh-Titusville,Titusville,PA +209825,University of Portland,Portland,OR +243106,University of Puerto Rico-Aguadilla,Ramey,PR +243115,University of Puerto Rico-Arecibo,Arecibo,PR +243133,University of Puerto Rico-Bayamon,Bayamon,PR +243142,University of Puerto Rico-Carolina,Carolina,PR +243151,University of Puerto Rico-Cayey,Cayey,PR +243179,University of Puerto Rico-Humacao,Humacao,PR +243197,University of Puerto Rico-Mayaguez,Mayaguez,PR +243203,University of Puerto Rico-Medical Sciences,San Juan,PR +243212,University of Puerto Rico-Ponce,Ponce,PR +243221,University of Puerto Rico-Rio Piedras,San Juan,PR +243188,University of Puerto Rico-Utuado,Utuado,PR +236328,University of Puget Sound,Tacoma,WA +121691,University of Redlands,Redlands,CA +217484,University of Rhode Island,Kingston,RI +233374,University of Richmond,University of Richmond,VA +205203,University of Rio Grande,Rio Grande,OH +195030,University of Rochester,Rochester,NY +152336,University of Saint Francis-Fort Wayne,Fort Wayne,IN +130314,University of Saint Joseph,West Hartford,CT +155812,University of Saint Mary,Leavenworth,KS +148885,University of Saint Mary of the Lake,Mundelein,IL +122436,University of San Diego,San Diego,CA +122612,University of San Francisco,San Francisco,CA +207722,University of Science and Arts of Oklahoma,Chickasha,OK +215929,University of Scranton,Scranton,PA +219383,University of Sioux Falls,Sioux Falls,SD +102094,University of South Alabama,Mobile,AL +218645,University of South Carolina-Aiken,Aiken,SC +218654,University of South Carolina-Beaufort,Bluffton,SC +218663,University of South Carolina-Columbia,Columbia,SC +218672,University of South Carolina-Lancaster,Lancaster,SC +218681,University of South Carolina-Salkehatchie,Allendale,SC +218690,University of South Carolina-Sumter,Sumter,SC +218706,University of South Carolina-Union,Union,SC +218742,University of South Carolina-Upstate,Spartanburg,SC +219471,University of South Dakota,Vermillion,SD +137351,University of South Florida-Main Campus,Tampa,FL +451671,University of South Florida-Sarasota-Manatee,Sarasota,FL +448840,University of South Florida-St Petersburg,St. Petersburg,FL +123961,University of Southern California,Los Angeles,CA +151306,University of Southern Indiana,Evansville,IN +161554,University of Southern Maine,Portland,ME +176372,University of Southern Mississippi,Hattiesburg,MS +134121,University of Southernmost Florida,Jacksonville,FL +367954,University of St Augustine for Health Sciences,San Marcos,CA +148584,University of St Francis,Joliet,IL +227863,University of St Thomas-Houston,Houston,TX +174914,University of St Thomas-Saint Paul,Saint Paul,MN +228635,University of Texas Southwestern Medical Center,Dallas,TX +156541,University of the Cumberlands,Williamsburg,KY +131399,University of the District of Columbia,Washington,DC +363721,University of the District of Columbia-David A Clarke School of Law,Washington,DC +225627,University of the Incarnate Word,San Antonio,TX +107558,University of the Ozarks,Clarksville,AR +120883,University of the Pacific,Stockton,CA +442639,University of the Potomac-VA Campus,Vienna,VA +384412,University of the Potomac-Washington DC Campus,Washington,DC +441308,University of the Rockies,Colorado Springs,CO +215132,University of the Sciences,Philadelphia,PA +188182,University of the Southwest,Hobbs,NM +243665,University of the Virgin Islands,Charlotte Amalie,VI +449870,University of the West,Rosemead,CA +206084,University of Toledo,Toledo,OH +207971,University of Tulsa,Tulsa,OK +230764,University of Utah,Salt Lake City,UT +216542,University of Valley Forge,Phoenixville,PA +231174,University of Vermont,Burlington,VT +234076,University of Virginia-Main Campus,Charlottesville,VA +377555,University of Washington-Bothell Campus,Bothell,WA +236948,University of Washington-Seattle Campus,Seattle,WA +377564,University of Washington-Tacoma Campus,Tacoma,WA +101587,University of West Alabama,Livingston,AL +141334,University of West Georgia,Carrollton,GA +210438,University of Western States,Portland,OR +240055,University of Wisconsin Colleges,Madison,WI +240268,University of Wisconsin-Eau Claire,Eau Claire,WI +240277,University of Wisconsin-Green Bay,Green Bay,WI +240329,University of Wisconsin-La Crosse,La Crosse,WI +240444,University of Wisconsin-Madison,Madison,WI +240453,University of Wisconsin-Milwaukee,Milwaukee,WI +240365,University of Wisconsin-Oshkosh,Oshkosh,WI +240374,University of Wisconsin-Parkside,Kenosha,WI +240462,University of Wisconsin-Platteville,Platteville,WI +240471,University of Wisconsin-River Falls,River Falls,WI +240480,University of Wisconsin-Stevens Point,Stevens Point,WI +240417,University of Wisconsin-Stout,Menomonie,WI +240426,University of Wisconsin-Superior,Superior,WI +240189,University of Wisconsin-Whitewater,Whitewater,WI +240727,University of Wyoming,Laramie,WY +154493,Upper Iowa University,Fayette,IA +196307,Upstate Medical University,Syracuse,NY +429128,Urban College of Boston,Boston,MA +206330,Urbana University,Urbana,OH +455099,Urshan Graduate School of Theology,Florissant,MO +216524,Ursinus College,Collegeville,PA +206349,Ursuline College,Pepper Pike,OH +446604,Uta Mesivta of Kiryas Joel,Monroe,NY +230728,Utah State University,Logan,UT +230737,Utah Valley University,Orem,UT +197045,Utica College,Utica,NY +197081,Utica School of Commerce,Utica,NY +141264,Valdosta State University,Valdosta,GA +138187,Valencia College,Orlando,FL +200572,Valley City State University,Valley City,ND +377652,Valley College-Beckley,Beckley,WV +152600,Valparaiso University,Valparaiso,IN +199838,Vance-Granville Community College,Henderson,NC +221999,Vanderbilt University,Nashville,TN +149639,VanderCook College of Music,Chicago,IL +123651,Vanguard University of Southern California,Costa Mesa,CA +197133,Vassar College,Poughkeepsie,NY +455567,Vatterott College-Appling Farms,Memphis,TN +245342,Vatterott College-Berkeley,Berkeley,MO +442408,Vatterott College-Cleveland,Broadview Heights,OH +373058,Vatterott College-Des Moines,Des Moines,IA +440873,Vatterott College-Dividend,Memphis,TN +481988,Vatterott College-ex'treme Institute by Nelly-St Louis,St. Louis,MO +404374,Vatterott College-Joplin,Joplin,MO +404383,Vatterott College-Kansas City,Kansas City,MO +437060,Vatterott College-Oklahoma City,Warr Acres,OK +148140,Vatterott College-Quincy,Quincy,IL +181756,Vatterott College-Spring Valley,Omaha,NE +404365,Vatterott College-Springfield,Springfield,MO +445559,Vatterott College-St Charles,St Charles,MO +436182,Vatterott College-St Joseph,Saint Joseph,MO +436191,Vatterott College-Sunset Hills,Sunset Hills,MO +440882,Vatterott College-Tulsa,Tulsa,OK +440891,Vatterott College-Wichita,Wichita,KS +188340,Vaughn College of Aeronautics and Technology,Flushing,NY +125028,Ventura College,Ventura,CA +175157,Vermilion Community College,Ely,MN +455992,Vermont College of Fine Arts,Montpelier,VT +231147,Vermont Law School,South Royalton,VT +231165,Vermont Technical College,Randolph Center,VT +229504,Vernon College,Vernon,TX +213914,Vet Tech Institute,Pittsburgh,PA +223472,Vet Tech Institute of Houston,Houston,TX +125091,Victor Valley College,Victorville,CA +229540,Victoria College,Victoria,TX +197142,Villa Maria College,Buffalo,NY +216597,Villanova University,Villanova,PA +152637,Vincennes University,Vincennes,IN +482228,Virginia Baptist College,Fredericksburg,VA +458256,Virginia College-Augusta,Augusta,GA +441928,Virginia College-Austin,Austin,TX +460774,Virginia College-Baton Rouge,Baton Rouge,LA +450191,Virginia College-Biloxi,Biloxi,MS +420307,Virginia College-Birmingham,Birmingham,AL +456056,Virginia College-Charleston,North Charleston,SC +458593,Virginia College-Columbia,Columbia,SC +475370,Virginia College-Columbus,Columbus,GA +480107,Virginia College-Florence,Florence,SC +454625,Virginia College-Greenville,Greenville,SC +420316,Virginia College-Huntsville,Huntsville,AL +441919,Virginia College-Jackson,Jackson,MS +455716,Virginia College-Jacksonville,Jacksonville,FL +475617,Virginia College-Knoxville,Knoxville,TN +460844,Virginia College-Macon,Macon,GA +445090,Virginia College-Mobile,Mobile,AL +452115,Virginia College-Montgomery,Montgomery,AL +389727,Virginia College-Pensacola,Pensacola,FL +460923,Virginia College-Richmond,Richmond,VA +475352,Virginia College-Savannah,Savannah,GA +450289,Virginia College-School of Business and Health-Chattanooga,Chattanooga,TN +475866,Virginia College-Shreveport Bossier City,Bossier City,LA +460853,Virginia College-Spartanburg,Spartanburg,SC +475592,Virginia College-Tulsa,Tulsa,OK +234030,Virginia Commonwealth University,Richmond,VA +233903,Virginia Highlands Community College,Abingdon,VA +206394,Virginia Marti College of Art and Design,Lakewood,OH +234085,Virginia Military Institute,Lexington,VA +233921,Virginia Polytechnic Institute and State University,Blacksburg,VA +234155,Virginia State University,Petersburg,VA +459082,Virginia Tech Carilion School of Medicine,Roanoke,VA +234164,Virginia Union University,Richmond,VA +234137,Virginia University of Lynchburg,Lynchburg,VA +234173,Virginia Wesleyan College,Norfolk,VA +233949,Virginia Western Community College,Roanoke,VA +449764,Visible Music College,Memphis,TN +365204,Vista College,El Paso,TX +377342,Vista College-Online,Clearfield,UT +240107,Viterbo University,La Crosse,WI +222053,Volunteer State Community College,Gallatin,TN +218919,Voorhees College,Denmark,SC +152673,Wabash College,Crawfordsville,IN +403487,Wabash Valley College,Mount Carmel,IL +226879,Wade College,Dallas,TX +197197,Wagner College,Staten Island,NY +199847,Wake Forest University,Winston Salem,NC +199856,Wake Technical Community College,Raleigh,NC +125231,Walden University,Minneapolis,MN +154518,Waldorf College,Forest City,IA +236887,Walla Walla Community College,Walla Walla,WA +236896,Walla Walla University,College Place,WA +172608,Walsh College of Accountancy and Business Administration,Troy,MI +206437,Walsh University,North Canton,OH +222062,Walters State Community College,Morristown,TN +210304,Warner Pacific College,Portland,OR +480198,Warner Pacific College Adult Degree Program,Portland,OR +138275,Warner University,Lake Wales,FL +245625,Warren County Community College,Washington,NJ +199865,Warren Wilson College,Swannanoa,NC +154527,Wartburg College,Waverly,IA +154536,Wartburg Theological Seminary,Dubuque,IA +156082,Washburn University,Topeka,KS +216667,Washington & Jefferson College,Washington,PA +162210,Washington Adventist University,Takoma Park,MD +234207,Washington and Lee University,Lexington,VA +164216,Washington College,Chestertown,MD +161581,Washington County Community College,Calais,ME +206446,Washington State Community College,Marietta,OH +236939,Washington State University,Pullman,WA +179867,Washington University in St Louis,Saint Louis,MO +172617,Washtenaw Community College,Ann Arbor,MI +392840,Watkins College of Art Design & Film,Nashville,TN +149727,Waubonsee Community College,Sugar Grove,IL +240125,Waukesha County Technical College,Pewaukee,WI +229780,Wayland Baptist University,Plainview,TX +199892,Wayne Community College,Goldsboro,NC +172635,Wayne County Community College District,Detroit,MI +181783,Wayne State College,Wayne,NE +172644,Wayne State University,Detroit,MI +216694,Waynesburg University,Waynesburg,PA +229799,Weatherford College,Weatherford,TX +197221,Webb Institute,Glen Cove,NY +138293,Webber International University,Babson Park,FL +230782,Weber State University,Ogden,UT +179894,Webster University,Saint Louis,MO +190424,Weill Cornell Medicine,New York,NY +220206,Welch College,Nashville,TN +168218,Wellesley College,Wellesley,MA +197230,Wells College,Aurora,NY +447999,WellSpring School of Allied Health-Kansas City,Kansas City,MO +236975,Wenatchee Valley College,Wenatchee,WA +168227,Wentworth Institute of Technology,Boston,MA +179919,Wentworth Military Academy and College,Lexington,MO +176451,Wesley Biblical Seminary,Jackson,MS +131098,Wesley College,Dover,DE +131973,Wesley Theological Seminary,Washington,DC +141325,Wesleyan College,Macon,GA +130697,Wesleyan University,Middletown,CT +216764,West Chester University of Pennsylvania,West Chester,PA +441229,West Coast Ultrasound Institute,Beverly Hills,CA +477039,West Coast University-Dallas,Dallas,TX +443331,West Coast University-Los Angeles,North Hollywood,CA +458229,West Coast University-Ontario,Ontario,CA +458210,West Coast University-Orange County,Anaheim,CA +139278,West Georgia Technical College,Waco,GA +125462,West Hills College-Coalinga,Coalinga,CA +448594,West Hills College-Lemoore,Lemoore,CA +157483,West Kentucky Community and Technical College,Paducah,KY +237932,West Liberty University,West Liberty,WV +125471,West Los Angeles College,Culver City,CA +172671,West Shore Community College,Scottville,MI +222099,West Tennessee Business College,Jackson,TN +229814,West Texas A & M University,Canyon,TX +125499,West Valley College,Saratoga,CA +237978,West Virginia Business College-Wheeling,Wheeling,WV +442383,West Virginia Junior College-Bridgeport,Bridgeport,WV +237987,West Virginia Junior College-Charleston,Charleston,WV +237996,West Virginia Junior College-Morgantown,Morgantown,WV +238014,West Virginia Northern Community College,Wheeling,WV +237880,West Virginia School of Osteopathic Medicine,Lewisburg,WV +237899,West Virginia State University,Institute,WV +238032,West Virginia University,Morgantown,WV +237686,West Virginia University at Parkersburg,Parkersburg,WV +237950,West Virginia University Institute of Technology,Montgomery,WV +237969,West Virginia Wesleyan College,Buckhannon,WV +200004,Western Carolina University,Cullowhee,NC +130776,Western Connecticut State University,Danbury,CT +219480,Western Dakota Technical Institute,Rapid City,SD +433387,Western Governors University,Salt Lake City,UT +149772,Western Illinois University,Macomb,IL +106102,Western International University,Tempe,AZ +154572,Western Iowa Tech Community College,Sioux City,IA +157951,Western Kentucky University,Bowling Green,KY +172699,Western Michigan University,Kalamazoo,MI +172477,Western Michigan University-Thomas M. Cooley Law School,Lansing,MI +181817,Western Nebraska Community College,Scottsbluff,NE +182564,Western Nevada College,Carson City,NV +168254,Western New England University,Springfield,MA +188304,Western New Mexico University,Silver City,NM +208035,Western Oklahoma State College,Altus,OK +210429,Western Oregon University,Monmouth,OR +199908,Western Piedmont Community College,Morganton,NC +210368,Western Seminary,Portland,OR +126030,Western State College of Law at Argosy University,Fullerton,CA +128391,Western State Colorado University,Gunnison,CO +224660,Western Technical College-El Paso,El Paso,TX +224679,Western Technical College-El Paso,El Paso,TX +240170,Western Technical College-La Crosse,La Crosse,WI +229832,Western Texas College,Snyder,TX +172705,Western Theological Seminary,Holland,MI +112525,Western University of Health Sciences,Pomona,CA +237011,Western Washington University,Bellingham,WA +240693,Western Wyoming Community College,Rock Springs,WY +168263,Westfield State University,Westfield,MA +179946,Westminster College-Fulton,Fulton,MO +216807,Westminster College-New Wilmington,New Wilmington,PA +230807,Westminster College-Salt Lake City,Salt Lake City,UT +216816,Westminster Theological Seminary,Glenside,PA +125718,Westminster Theological Seminary in California,Escondido,CA +125727,Westmont College,Santa Barbara,CA +216825,Westmoreland County Community College,Youngwood,PA +437848,Westwood College-Anaheim,Anaheim,CA +448628,Westwood College-Annandale,Annandale,VA +447069,Westwood College-Arlington Ballston,Arlington,VA +445072,Westwood College-Atlanta Midtown,Atlanta,GA +443687,Westwood College-Chicago Loop,Chicago,IL +127024,Westwood College-Denver North,Denver,CO +381787,Westwood College-Denver South,Denver,CO +406194,Westwood College-Dupage,Woodridge,IL +440484,Westwood College-Inland Empire,Upland,CA +122843,Westwood College-Los Angeles,Los Angeles,CA +445276,Westwood College-Northlake,Atlanta,GA +178226,Westwood College-O'Hare Airport,Chicago,IL +440147,Westwood College-River Oaks,Calumet City,IL +121381,Westwood College-South Bay,Torrance,CA +229841,Wharton County Junior College,Wharton,TX +237039,Whatcom Community College,Bellingham,WA +168281,Wheaton College-Norton,Norton,MA +149781,Wheaton College-Wheaton,Wheaton,IL +238078,Wheeling Jesuit University,Wheeling,WV +168290,Wheelock College,Boston,MA +434751,White Earth Tribal and Community College,Mahnomen,MN +183105,White Mountains Community College,Berlin,NH +237057,Whitman College,Walla Walla,WA +125763,Whittier College,Whittier,CA +237066,Whitworth University,Spokane,WA +475200,Whitworth University-Adult Degree Programs,Spokane,WA +156107,Wichita Area Technical College,Wichita,KS +156125,Wichita State University,Wichita,KS +156134,Wichita Technical Institute,Wichita,KS +244190,Widener University-Delaware Campus,Wilmington,DE +402828,Widener University-Harrisburg Campus,Harrisburg,PA +216852,Widener University-Main Campus,Chester,PA +206491,Wilberforce University,Wilberforce,OH +229887,Wiley College,Marshall,TX +199926,Wilkes Community College,Wilkesboro,NC +216931,Wilkes University,Wilkes-Barre,PA +210401,Willamette University,Salem,OR +176479,William Carey University,Hattiesburg,MS +166717,William James College,Newton,MA +122728,William Jessup University,Rocklin,CA +179955,William Jewell College,Liberty,MO +175281,William Mitchell College of Law,Saint Paul,MN +222105,William Moore College of Technology,Memphis,TN +187444,William Paterson University of New Jersey,Wayne,NJ +199272,William Peace University,Raleigh,NC +154590,William Penn University,Oskaloosa,IA +149842,William Rainey Harper College,Palatine,IL +179964,William Woods University,Fulton,MO +107877,Williams Baptist College,Walnut Ridge,AR +168342,Williams College,Williamstown,MA +218955,Williamsburg Technical College,Kingstree,SC +443340,Williamson Christian College,Franklin,TN +200341,Williston State College,Williston,ND +206507,Wilmington College,Wilmington,OH +131113,Wilmington University,New Castle,DE +217013,Wilson College,Chambersburg,PA +199953,Wilson Community College,Wilson,NC +141990,Windward Community College,Kaneohe,HI +206516,Winebrenner Theological Seminary,Findlay,OH +199962,Wingate University,Wingate,NC +175272,Winona State University,Winona,MN +199999,Winston-Salem State University,Winston-Salem,NC +218964,Winthrop University,Rock Hill,SC +141255,Wiregrass Georgia Technical College,Valdosta,GA +240198,Wisconsin Indianhead Technical College,Shell Lake,WI +240338,Wisconsin Lutheran College,Milwaukee,WI +240213,Wisconsin School of Professional Psychology,Milwaukee,WI +206525,Wittenberg University,Springfield,OH +218973,Wofford College,Spartanburg,SC +451130,Wolford College,Naples,FL +442064,Won Institute of Graduate Studies,Glenside,PA +197522,Wood Tobe-Coburn School,New York,NY +125897,Woodbury University,Burbank,CA +455512,Woodland Community College,Woodland,CA +168421,Worcester Polytechnic Institute,Worcester,MA +168430,Worcester State University,Worcester,MA +141936,World Medicine Institute,Honolulu,HI +401223,World Mission University,Los Angeles,CA +369455,Worsham College of Mortuary Science,Wheeling,IL +164313,Wor-Wic Community College,Salisbury,MD +406200,Wright Career College,Overland Park,KS +206613,Wright State University-Lake Campus,Celina,OH +206604,Wright State University-Main Campus,Dayton,OH +441089,Wyo Tech-Blairsville,Blairsville,PA +132268,Wyotech-Daytona,Ormond Beach,FL +123208,Wyotech-Fremont,Fremont,CA +240718,Wyotech-Laramie,Laramie,WY +398574,Wyotech-Long Beach,Long Beach,CA +234377,Wytheville Community College,Wytheville,VA +206622,Xavier University,Cincinnati,OH +160904,Xavier University of Louisiana,New Orleans,LA +237109,Yakima Valley Community College,Yakima,WA +130794,Yale University,New Haven,CT +106148,Yavapai College,Prescott,AZ +245731,Yeshiva and Kollel Harbotzas Torah,Brooklyn,NY +434937,Yeshiva College of the Nations Capital,Silver Spring,MD +197647,Yeshiva Derech Chaim,Brooklyn,NY +420325,Yeshiva D'monsey Rabbinical College,Monsey,NY +375230,Yeshiva Gedolah Imrei Yosef D'spinka,Brooklyn,NY +481410,Yeshiva Gedolah Kesser Torah,Monsey,NY +247773,Yeshiva Gedolah of Greater Detroit,Oak Park,MI +476692,Yeshiva Gedolah Zichron Leyma,Linden,NJ +197601,Yeshiva Karlin Stolin,Brooklyn,NY +190752,Yeshiva of Far Rockaway Derech Ayson Rabbinical Seminary,Far Rockaway,NY +455257,Yeshiva of Machzikai Hadas,Brooklyn,NY +197674,Yeshiva of Nitra Rabbinical College,Mount Kisco,NY +431983,Yeshiva of the Telshe Alumni,Riverdale,NY +126076,Yeshiva Ohr Elchonon Chabad West Coast Talmudical Seminary,Los Angeles,CA +197692,Yeshiva Shaar Hatorah,Kew Gardens,NY +441609,Yeshiva Shaarei Torah of Rockland,Suffern,NY +451398,Yeshiva Toras Chaim,Lakewood,NJ +128425,Yeshiva Toras Chaim Talmudical Seminary,Denver,CO +197708,Yeshiva University,New York,NY +481438,Yeshiva Yesodei Hatorah,Lakewood,NJ +451370,Yeshivas Be'er Yitzchok,Elizabeth,NJ +405058,Yeshivas Novominsk,Brooklyn,NY +197610,Yeshivat Mikdash Melech,Brooklyn,NY +217040,Yeshivath Beth Moshe,Scranton,PA +197735,Yeshivath Viznitz,Monsey,NY +197744,Yeshivath Zichron Moshe,South Fallsburgh,NY +401250,Yo San University of Traditional Chinese Medicine,Los Angeles,CA +181853,York College,York,NE +217059,York College Pennsylvania,York,PA +420440,York County Community College,Wells,ME +218991,York Technical College,Rock Hill,SC +217086,Yorktowne Business Institute,York,PA +141361,Young Harris College,Young Harris,GA +206695,Youngstown State University,Youngstown,OH +375939,YTI Career Institute-Altoona,Altoona,PA +217077,YTI Career Institute-York,York,PA +126119,Yuba College,Marysville,CA +204255,Zane State College,Zanesville,OH \ No newline at end of file diff --git a/vite-app/src/apps/Auth2/resources/data/institutions.json b/vite-app/src/apps/Auth2/resources/data/institutions.json new file mode 100644 index 000000000..24ff890ff --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/institutions.json @@ -0,0 +1,5903 @@ +[ + { "value": "177834", "label": "A T Still University of Health Sciences" }, + { "value": "180203", "label": "Aaniiih Nakoda College" }, + { "value": "222178", "label": "Abilene Christian University" }, + { "value": "138558", "label": "Abraham Baldwin Agricultural College" }, + { "value": "172866", "label": "Academy College" }, + { "value": "451079", "label": "Academy for Five Element Acupuncture" }, + { "value": "457271", "label": "Academy for Jewish Religion-California" }, + { + "value": "412173", + "label": "Academy for Nursing and Health Occupations" + }, + { "value": "108232", "label": "Academy of Art University" }, + { + "value": "108269", + "label": "Academy of Chinese Culture and Health Sciences" + }, + { "value": "475635", "label": "Academy of Couture Art" }, + { "value": "449454", "label": "Academy of Natural Therapy Inc" }, + { + "value": "384306", + "label": "Acupuncture and Integrative Medicine College-Berkeley" + }, + { "value": "439969", "label": "Acupuncture and Massage College" }, + { "value": "126182", "label": "Adams State University" }, + { "value": "188429", "label": "Adelphi University" }, + { "value": "188438", "label": "Adirondack Community College" }, + { "value": "374024", "label": "Adler Graduate School" }, + { "value": "142832", "label": "Adler University" }, + { "value": "168528", "label": "Adrian College" }, + { "value": "444343", "label": "Advanced College" }, + { "value": "481234", "label": "Advanced Computing Institute" }, + { "value": "231411", "label": "Advanced Technology Institute" }, + { "value": "444361", "label": "Advanced Training Associates" }, + { "value": "133872", "label": "Adventist University of Health Sciences" }, + { + "value": "205391", + "label": "Advertising Art Educational Services DBA School of Advertising Art" + }, + { "value": "138600", "label": "Agnes Scott College" }, + { + "value": "134811", + "label": "AI Miami International University of Art and Design" + }, + { "value": "152822", "label": "AIB College of Business" }, + { "value": "217615", "label": "Aiken Technical College" }, + { "value": "126207", "label": "Aims Community College" }, + { + "value": "200697", + "label": "Air Force Institute of Technology-Graduate School of Engineering & Management" + }, + { "value": "200785", "label": "Akron Institute of Herzing University" }, + { "value": "100654", "label": "Alabama A & M University" }, + { "value": "101949", "label": "Alabama Southern Community College" }, + { "value": "100724", "label": "Alabama State University" }, + { "value": "199786", "label": "Alamance Community College" }, + { "value": "102580", "label": "Alaska Bible College" }, + { "value": "103501", "label": "Alaska Career College" }, + { "value": "442523", "label": "Alaska Christian College" }, + { "value": "102669", "label": "Alaska Pacific University" }, + { + "value": "188526", + "label": "Albany College of Pharmacy and Health Sciences" + }, + { "value": "188535", "label": "Albany Law School" }, + { "value": "188580", "label": "Albany Medical College" }, + { "value": "138716", "label": "Albany State University" }, + { "value": "138682", "label": "Albany Technical College" }, + { "value": "128498", "label": "Albertus Magnus College" }, + { "value": "168546", "label": "Albion College" }, + { "value": "210571", "label": "Albright College" }, + { "value": "175342", "label": "Alcorn State University" }, + { "value": "237118", "label": "Alderson Broaddus University" }, + { "value": "172918", "label": "Alexandria Technical & Community College" }, + { "value": "188641", "label": "Alfred University" }, + { "value": "156189", "label": "Alice Lloyd College" }, + { "value": "108807", "label": "Allan Hancock College" }, + { "value": "161688", "label": "Allegany College of Maryland" }, + { "value": "210669", "label": "Allegheny College" }, + { "value": "200873", "label": "Allegheny Wesleyan College" }, + { "value": "152798", "label": "Allen College" }, + { "value": "154642", "label": "Allen County Community College" }, + { "value": "217624", "label": "Allen University" }, + { + "value": "110468", + "label": "Alliant International University-San Diego" + }, + { "value": "460729", "label": "Allied American University" }, + { "value": "168591", "label": "Alma College" }, + { "value": "168607", "label": "Alpena Community College" }, + { "value": "210775", "label": "Alvernia University" }, + { "value": "238193", "label": "Alverno College" }, + { "value": "222567", "label": "Alvin Community College" }, + { "value": "222576", "label": "Amarillo College" }, + { "value": "222628", "label": "Amberton University" }, + { "value": "457527", "label": "Ambria College of Nursing" }, + { + "value": "188687", + "label": "American Academy McAllister Institute of Funeral Service" + }, + { + "value": "446002", + "label": "American Academy of Acupuncture and Oriental Medicine" + }, + { "value": "142887", "label": "American Academy of Art" }, + { + "value": "108852", + "label": "American Academy of Dramatic Arts-Los Angeles" + }, + { + "value": "188678", + "label": "American Academy of Dramatic Arts-New York" + }, + { "value": "219505", "label": "American Baptist College" }, + { "value": "108861", "label": "American Baptist Seminary of the West" }, + { + "value": "457688", + "label": "American Business and Technology University" + }, + { "value": "441052", "label": "American Career College-Anaheim" }, + { "value": "109040", "label": "American Career College-Los Angeles" }, + { "value": "447768", "label": "American Career College-Ontario" }, + { "value": "461005", "label": "American College for Medical Careers" }, + { + "value": "429085", + "label": "American College of Acupuncture and Oriental Med" + }, + { "value": "449889", "label": "American College of Education" }, + { "value": "210809", "label": "American College of Financial Services" }, + { "value": "443599", "label": "American College of Healthcare Sciences" }, + { + "value": "430591", + "label": "American College of Traditional Chinese Medicine" + }, + { "value": "109086", "label": "American Conservatory Theater" }, + { "value": "108870", "label": "American Film Institute Conservatory" }, + { "value": "103787", "label": "American Indian College Inc" }, + { + "value": "441636", + "label": "American Institute of Alternative Medicine" + }, + { + "value": "438586", + "label": "American InterContinental University-Atlanta" + }, + { + "value": "445133", + "label": "American InterContinental University-Houston" + }, + { + "value": "445027", + "label": "American InterContinental University-Online" + }, + { + "value": "438601", + "label": "American InterContinental University-South Florida" + }, + { "value": "164447", "label": "American International College" }, + { "value": "116846", "label": "American Jewish University" }, + { "value": "475714", "label": "American Medical Academy" }, + { "value": "188854", "label": "American Musical and Dramatic Academy" }, + { "value": "232797", "label": "American National University" }, + { "value": "449339", "label": "American Public University System" }, + { "value": "109208", "label": "American River College" }, + { "value": "240736", "label": "American Samoa Community College" }, + { "value": "460738", "label": "American Sentinel University" }, + { "value": "131159", "label": "American University" }, + { "value": "433004", "label": "American University of Health Sciences" }, + { + "value": "241100", + "label": "American University of Puerto Rico-Bayamon" + }, + { "value": "241128", "label": "American University of Puerto Rico-Manati" }, + { "value": "447263", "label": "AmeriTech College-Draper" }, + { "value": "164465", "label": "Amherst College" }, + { "value": "100690", "label": "Amridge University" }, + { "value": "151865", "label": "Anabaptist Mennonite Biblical Seminary" }, + { "value": "150048", "label": "Ancilla College" }, + { "value": "150066", "label": "Anderson University-Anderson" }, + { "value": "217633", "label": "Anderson University-Anderson" }, + { "value": "164474", "label": "Andover Newton Theological School" }, + { "value": "138761", "label": "Andrew College" }, + { "value": "168740", "label": "Andrews University" }, + { "value": "457299", "label": "Angeles College" }, + { "value": "222822", "label": "Angelina College" }, + { "value": "222831", "label": "Angelo State University" }, + { "value": "164492", "label": "Anna Maria College" }, + { "value": "161767", "label": "Anne Arundel Community College" }, + { "value": "172954", "label": "Anoka Technical College" }, + { "value": "172963", "label": "Anoka-Ramsey Community College" }, + { "value": "109350", "label": "Antelope Valley College" }, + { "value": "245838", "label": "Antioch University-Los Angeles" }, + { "value": "245892", "label": "Antioch University-Midwest" }, + { "value": "245865", "label": "Antioch University-New England" }, + { + "value": "442392", + "label": "Antioch University-PhD Program in Leadership and Change" + }, + { "value": "245847", "label": "Antioch University-Santa Barbara" }, + { "value": "245883", "label": "Antioch University-Seattle" }, + { "value": "201016", "label": "Antonelli College-Cincinnati" }, + { "value": "383950", "label": "Antonelli College-Hattiesburg" }, + { "value": "175528", "label": "Antonelli College-Jackson" }, + { "value": "210890", "label": "Antonelli Institute" }, + { + "value": "429094", + "label": "AOMA Graduate School of Integrative Medicine" + }, + { "value": "441511", "label": "Apex School of Theology" }, + { "value": "237136", "label": "Appalachian Bible College" }, + { "value": "449922", "label": "Appalachian College of Pharmacy" }, + { "value": "432348", "label": "Appalachian School of Law" }, + { "value": "197869", "label": "Appalachian State University" }, + { "value": "168786", "label": "Aquinas College-Grand Rapids" }, + { "value": "219578", "label": "Aquinas College-Nashville" }, + { "value": "176600", "label": "Aquinas Institute of Theology" }, + { "value": "126289", "label": "Arapahoe Community College" }, + { "value": "211088", "label": "Arcadia University" }, + { "value": "367936", "label": "Argosy University-Atlanta" }, + { "value": "145770", "label": "Argosy University-Chicago" }, + { "value": "442222", "label": "Argosy University-Dallas" }, + { "value": "448734", "label": "Argosy University-Denver" }, + { "value": "366748", "label": "Argosy University-Hawaii" }, + { "value": "450526", "label": "Argosy University-Inland Empire" }, + { "value": "447272", "label": "Argosy University-Los Angeles" }, + { "value": "450535", "label": "Argosy University-Nashville" }, + { "value": "436438", "label": "Argosy University-Orange County" }, + { "value": "436094", "label": "Argosy University-Phoenix" }, + { "value": "456348", "label": "Argosy University-Phoenix Online Division" }, + { "value": "452090", "label": "Argosy University-Salt Lake City" }, + { "value": "450544", "label": "Argosy University-San Diego" }, + { "value": "121983", "label": "Argosy University-San Francisco Bay Area" }, + { "value": "137148", "label": "Argosy University-Sarasota" }, + { "value": "420866", "label": "Argosy University-Schaumburg" }, + { "value": "439057", "label": "Argosy University-Seattle" }, + { "value": "428268", "label": "Argosy University-Tampa" }, + { + "value": "410502", + "label": "Argosy University-The Art Institute of California-Hollywood" + }, + { + "value": "448576", + "label": "Argosy University-The Art Institute of California-Inland Empire" + }, + { + "value": "432533", + "label": "Argosy University-The Art Institute of California-Los Angeles" + }, + { + "value": "441973", + "label": "Argosy University-The Art Institute of California-Orange County" + }, + { + "value": "450094", + "label": "Argosy University-The Art Institute of California-Sacramento" + }, + { + "value": "117113", + "label": "Argosy University-The Art Institute of California-San Diego" + }, + { + "value": "117928", + "label": "Argosy University-The Art Institute of California-San Francisco" + }, + { + "value": "451848", + "label": "Argosy University-The Art Institute of California-Silicon Valley" + }, + { "value": "173984", "label": "Argosy University-Twin Cities" }, + { "value": "419457", "label": "Argosy University-Washington DC" }, + { "value": "105899", "label": "Arizona Christian University" }, + { "value": "421708", "label": "Arizona College-Glendale" }, + { "value": "482990", "label": "Arizona College-Mesa" }, + { + "value": "446039", + "label": "Arizona School of Acupuncture and Oriental Medicine" + }, + { "value": "448886", "label": "Arizona State University-Downtown Phoenix" }, + { "value": "420574", "label": "Arizona State University-Polytechnic" }, + { "value": "483124", "label": "Arizona State University-Skysong" }, + { "value": "104151", "label": "Arizona State University-Tempe" }, + { "value": "407009", "label": "Arizona State University-West" }, + { "value": "450942", "label": "Arizona Summit Law School" }, + { "value": "104160", "label": "Arizona Western College" }, + { "value": "106306", "label": "Arkansas Baptist College" }, + { "value": "107327", "label": "Arkansas Northeastern College" }, + { "value": "106449", "label": "Arkansas State University-Beebe" }, + { "value": "106458", "label": "Arkansas State University-Main Campus" }, + { "value": "107318", "label": "Arkansas State University-Mid-South" }, + { "value": "420538", "label": "Arkansas State University-Mountain Home" }, + { "value": "440402", "label": "Arkansas State University-Newport" }, + { "value": "106467", "label": "Arkansas Tech University" }, + { "value": "222877", "label": "Arlington Baptist College" }, + { "value": "138789", "label": "Armstrong State University" }, + { "value": "201061", "label": "Art Academy of Cincinnati" }, + { "value": "109651", "label": "Art Center College of Design" }, + { "value": "404994", "label": "ASA College" }, + { "value": "156222", "label": "Asbury Theological Seminary" }, + { "value": "156213", "label": "Asbury University" }, + { "value": "461777", "label": "Ashdown College of Health Sciences" }, + { "value": "447777", "label": "Asher College" }, + { + "value": "197887", + "label": "Asheville-Buncombe Technical Community College" + }, + { "value": "154022", "label": "Ashford University" }, + { "value": "156231", "label": "Ashland Community and Technical College" }, + { "value": "201104", "label": "Ashland University" }, + { "value": "128577", "label": "Asnuntuck Community College" }, + { "value": "454829", "label": "Aspen University" }, + { "value": "176619", "label": "Assemblies of God Theological Seminary" }, + { "value": "164562", "label": "Assumption College" }, + { "value": "183600", "label": "Assumption College for Sisters" }, + { "value": "446127", "label": "ATA Career Education" }, + { "value": "447935", "label": "ATA College" }, + { "value": "440651", "label": "Atenas College" }, + { "value": "201140", "label": "Athenaeum of Ohio" }, + { "value": "100812", "label": "Athens State University" }, + { "value": "246813", "label": "Athens Technical College" }, + { "value": "138901", "label": "Atlanta Metropolitan State College" }, + { "value": "138840", "label": "Atlanta Technical College" }, + { "value": "138929", "label": "Atlanta's John Marshall Law School" }, + { "value": "183655", "label": "Atlantic Cape Community College" }, + { "value": "439446", "label": "Atlantic Institute of Oriental Medicine" }, + { "value": "241216", "label": "Atlantic University College" }, + { "value": "100858", "label": "Auburn University" }, + { "value": "100830", "label": "Auburn University at Montgomery" }, + { "value": "173045", "label": "Augsburg College" }, + { "value": "138956", "label": "Augusta Technical College" }, + { "value": "482149", "label": "Augusta University" }, + { "value": "143084", "label": "Augustana College-Rock Island" }, + { "value": "219000", "label": "Augustana University" }, + { + "value": "201177", + "label": "Aultman College of Nursing and Health Sciences" + }, + { "value": "143118", "label": "Aurora University" }, + { "value": "222983", "label": "Austin College" }, + { "value": "222992", "label": "Austin Community College District" }, + { "value": "247825", "label": "Austin Graduate School of Theology" }, + { "value": "219602", "label": "Austin Peay State University" }, + { "value": "223001", "label": "Austin Presbyterian Theological Seminary" }, + { "value": "442295", "label": "Ave Maria School of Law" }, + { "value": "446048", "label": "Ave Maria University" }, + { "value": "231420", "label": "Averett University" }, + { + "value": "449931", + "label": "Averett University-Non-Traditional Programs" + }, + { + "value": "447847", + "label": "Aviator College of Aeronautical Science and Technology" + }, + { "value": "176628", "label": "Avila University" }, + { "value": "102711", "label": "AVTEC-Alaska's Institute of Technology" }, + { "value": "483762", "label": "Azure College" }, + { "value": "109785", "label": "Azusa Pacific University" }, + { "value": "474863", "label": "Azusa Pacific University College" }, + { "value": "164580", "label": "Babson College" }, + { "value": "206817", "label": "Bacone College" }, + { "value": "139010", "label": "Bainbridge State College" }, + { "value": "476601", "label": "Bais HaMedrash and Mesivta of Baltimore" }, + { "value": "245777", "label": "Bais Medrash Elyon" }, + { "value": "449658", "label": "Bais Medrash Toras Chesed" }, + { "value": "168847", "label": "Baker College" }, + { "value": "414708", "label": "Baker College Center for Graduate Studies" }, + { "value": "444167", "label": "Baker College of Allen Park" }, + { "value": "404073", "label": "Baker College of Auburn Hills" }, + { "value": "404648", "label": "Baker College of Cadillac" }, + { "value": "404082", "label": "Baker College of Clinton Township" }, + { "value": "414160", "label": "Baker College of Jackson" }, + { "value": "171298", "label": "Baker College of Muskegon" }, + { "value": "168838", "label": "Baker College of Owosso" }, + { "value": "381617", "label": "Baker College of Port Huron" }, + { "value": "154688", "label": "Baker University" }, + { "value": "109819", "label": "Bakersfield College" }, + { "value": "420705", "label": "Bakke Graduate University" }, + { "value": "201195", "label": "Baldwin Wallace University" }, + { "value": "150136", "label": "Ball State University" }, + { "value": "161864", "label": "Baltimore City Community College" }, + { "value": "189015", "label": "Bank Street College of Education" }, + { "value": "176664", "label": "Baptist Bible College" }, + { "value": "211024", "label": "Clarks Summit University" }, + { + "value": "223083", + "label": "Baptist Health System School of Health Professions" + }, + { + "value": "219639", + "label": "Baptist Memorial College of Health Sciences" + }, + { + "value": "223117", + "label": "Baptist Missionary Association Theological Seminary" + }, + { "value": "366793", "label": "Baptist Theological Seminary at Richmond" }, + { "value": "444398", "label": "Baptist University of the Americas" }, + { "value": "155070", "label": "Barclay College" }, + { "value": "189088", "label": "Bard College" }, + { "value": "167792", "label": "Bard College at Simon's Rock" }, + { "value": "189097", "label": "Barnard College" }, + { + "value": "177719", + "label": "Barnes-Jewish College Goldfarb School of Nursing" + }, + { "value": "132471", "label": "Barry University" }, + { "value": "109907", "label": "Barstow Community College" }, + { "value": "197911", "label": "Barton College" }, + { "value": "154697", "label": "Barton County Community College" }, + { "value": "235547", "label": "Bastyr University" }, + { "value": "160977", "label": "Bates College" }, + { "value": "235671", "label": "Bates Technical College" }, + { "value": "437103", "label": "Baton Rouge Community College" }, + { "value": "158343", "label": "Baton Rouge School of Computers" }, + { "value": "139074", "label": "Bauder College" }, + { "value": "168883", "label": "Bay de Noc Community College" }, + { "value": "380359", "label": "Bay Mills Community College" }, + { "value": "164632", "label": "Bay Path University" }, + { "value": "164641", "label": "Bay State College" }, + { "value": "223223", "label": "Baylor College of Medicine" }, + { "value": "223232", "label": "Baylor University" }, + { "value": "384254", "label": "Beacon College" }, + { "value": "160995", "label": "Beal College" }, + { "value": "197966", "label": "Beaufort County Community College" }, + { "value": "164720", "label": "Becker College" }, + { "value": "247065", "label": "Beckfield College-Florence" }, + { "value": "452373", "label": "Beckfield College-Tri-County" }, + { "value": "476717", "label": "Be'er Yaakov Talmudic Seminary" }, + { "value": "444413", "label": "Beis Medrash Heichal Dovid" }, + { "value": "190956", "label": "Belanger School of Nursing" }, + { "value": "175421", "label": "Belhaven University" }, + { "value": "156286", "label": "Bellarmine University" }, + { "value": "234669", "label": "Bellevue College" }, + { "value": "180814", "label": "Bellevue University" }, + { "value": "238324", "label": "Bellin College" }, + { "value": "234696", "label": "Bellingham Technical College" }, + { "value": "197984", "label": "Belmont Abbey College" }, + { "value": "201283", "label": "Belmont College" }, + { "value": "219709", "label": "Belmont University" }, + { "value": "238333", "label": "Beloit College" }, + { "value": "126359", "label": "Bel-Rea Institute of Animal Technology" }, + { "value": "173124", "label": "Bemidji State University" }, + { "value": "217721", "label": "Benedict College" }, + { "value": "154712", "label": "Benedictine College" }, + { "value": "145619", "label": "Benedictine University" }, + { "value": "165884", "label": "Benjamin Franklin Institute of Technology" }, + { "value": "197993", "label": "Bennett College" }, + { "value": "230816", "label": "Bennington College" }, + { "value": "164739", "label": "Bentley University" }, + { "value": "156295", "label": "Berea College" }, + { "value": "183743", "label": "Bergen Community College" }, + { "value": "461643", "label": "Bergin University of Canine Studies" }, + { "value": "125170", "label": "Berkeley City College" }, + { "value": "189228", "label": "Berkeley College-New York" }, + { "value": "183789", "label": "Berkeley College-Woodland Park" }, + { "value": "164748", "label": "Berklee College of Music" }, + { "value": "213534", "label": "Berks Technical Institute" }, + { "value": "164775", "label": "Berkshire Community College" }, + { "value": "139144", "label": "Berry College" }, + { "value": "189273", "label": "Beth Hamedrash Shaarei Yosher Institute" }, + { "value": "189264", "label": "Beth Hatalmud Rabbinical College" }, + { "value": "183804", "label": "Beth Medrash Govoha" }, + { "value": "237181", "label": "Bethany College-Bethany" }, + { "value": "154721", "label": "Bethany College-Lindsborg" }, + { "value": "173142", "label": "Bethany Lutheran College" }, + { "value": "143233", "label": "Bethany Theological Seminary" }, + { "value": "458113", "label": "Bethel College" }, + { "value": "150145", "label": "Bethel College-Indiana" }, + { "value": "154749", "label": "Bethel College-North Newton" }, + { "value": "262022", "label": "Bethel Seminary-San Diego" }, + { "value": "173179", "label": "Bethel Seminary-St Paul" }, + { "value": "219718", "label": "Bethel University-McKenzie" }, + { "value": "173160", "label": "Bethel University-Saint Paul" }, + { "value": "110060", "label": "Bethesda University" }, + { "value": "132602", "label": "Bethune-Cookman University" }, + { "value": "139153", "label": "Beulah Heights University" }, + { "value": "102429", "label": "Bevill State Community College" }, + { + "value": "148724", + "label": "Bexley Hall Seabury Western Theological Seminary Federation" + }, + { + "value": "443702", + "label": "Bexley Hall Seabury Western Theological Seminary Federation " + }, + { "value": "211130", "label": "Biblical Theological Seminary" }, + { "value": "211149", "label": "Bidwell Training Center Inc" }, + { "value": "234711", "label": "Big Bend Community College" }, + { "value": "157553", "label": "Big Sandy Community and Technical College" }, + { "value": "110097", "label": "Biola University" }, + { "value": "100937", "label": "Birmingham Southern College" }, + { "value": "442949", "label": "Birthingway College of Midwifery" }, + { "value": "102030", "label": "Bishop State Community College" }, + { "value": "200022", "label": "Bismarck State College" }, + { "value": "143279", "label": "Black Hawk College" }, + { "value": "219046", "label": "Black Hills State University" }, + { "value": "106625", "label": "Black River Technical College" }, + { "value": "143288", "label": "Blackburn College" }, + { "value": "180054", "label": "Blackfeet Community College" }, + { "value": "238397", "label": "Blackhawk Technical College" }, + { "value": "198011", "label": "Bladen Community College" }, + { "value": "143297", "label": "Blessing Rieman College of Nursing" }, + { "value": "223427", "label": "Blinn College" }, + { "value": "183822", "label": "Bloomfield College" }, + { "value": "211158", "label": "Bloomsburg University of Pennsylvania" }, + { "value": "441502", "label": "Blue Cliff College-Gulfport" }, + { "value": "175430", "label": "Blue Mountain College" }, + { "value": "208275", "label": "Blue Mountain Community College" }, + { + "value": "446774", + "label": "Blue Ridge Community and Technical College" + }, + { "value": "198039", "label": "Blue Ridge Community College-Flat Rock" }, + { "value": "231536", "label": "Blue Ridge Community College-Weyers Cave" }, + { "value": "231554", "label": "Bluefield College" }, + { "value": "237215", "label": "Bluefield State College" }, + { "value": "156392", "label": "Bluegrass Community and Technical College" }, + { "value": "201371", "label": "Bluffton University" }, + { "value": "217749", "label": "Bob Jones University" }, + { "value": "142090", "label": "Boise Bible College" }, + { "value": "142115", "label": "Boise State University" }, + { "value": "233356", "label": "Bon Secours Memorial College of Nursing" }, + { "value": "189413", "label": "Boricua College" }, + { "value": "158431", "label": "Bossier Parish Community College" }, + { "value": "164872", "label": "Boston Architectural College" }, + { "value": "164614", "label": "Boston Baptist College" }, + { "value": "164924", "label": "Boston College" }, + { + "value": "164915", + "label": "Boston Graduate School of Psychoanalysis Inc" + }, + { "value": "164988", "label": "Boston University" }, + { "value": "161004", "label": "Bowdoin College" }, + { "value": "162007", "label": "Bowie State University" }, + { "value": "201432", "label": "Bowling Green State University-Firelands" }, + { + "value": "201441", + "label": "Bowling Green State University-Main Campus" + }, + { "value": "202161", "label": "Bradford School-Columbus" }, + { "value": "211200", "label": "Bradford School-Pittsburgh" }, + { "value": "143358", "label": "Bradley University" }, + { "value": "189422", "label": "Bramson ORT College" }, + { "value": "165015", "label": "Brandeis University" }, + { "value": "262086", "label": "Brandman University" }, + { "value": "223506", "label": "Brazosport College" }, + { "value": "139199", "label": "Brenau University" }, + { "value": "156356", "label": "Brescia University" }, + { "value": "198066", "label": "Brevard College" }, + { "value": "139205", "label": "Brewton-Parker College" }, + { "value": "152992", "label": "Briar Cliff University" }, + { "value": "189459", "label": "Briarcliffe College" }, + { "value": "231581", "label": "Bridgewater College" }, + { "value": "165024", "label": "Bridgewater State University" }, + { "value": "230047", "label": "Brigham Young University-Hawaii" }, + { "value": "142522", "label": "Brigham Young University-Idaho" }, + { "value": "230038", "label": "Brigham Young University-Provo" }, + { "value": "215646", "label": "Brightwood Career Institute-Broomall" }, + { "value": "251075", "label": "Brightwood Career Institute-Harrisburg" }, + { "value": "214254", "label": "Brightwood Career Institute-Philadelphia" }, + { + "value": "211617", + "label": "Brightwood Career Institute-Philadelphia Mills" + }, + { "value": "213002", "label": "Brightwood Career Institute-Pittsburgh" }, + { "value": "458690", "label": "Brightwood College-Arlington" }, + { "value": "447102", "label": "Brightwood College-Bakersfield" }, + { "value": "163736", "label": "Brightwood College-Baltimore" }, + { "value": "440323", "label": "Brightwood College-Beaumont" }, + { "value": "164058", "label": "Brightwood College-Beltsville" }, + { "value": "443827", "label": "Brightwood College-Brownsville" }, + { "value": "458706", "label": "Brightwood College-Charlotte" }, + { "value": "458186", "label": "Brightwood College-Chula Vista" }, + { "value": "443836", "label": "Brightwood College-Corpus Christi" }, + { "value": "382896", "label": "Brightwood College-Dallas" }, + { "value": "204626", "label": "Brightwood College-Dayton" }, + { "value": "246266", "label": "Brightwood College-El Paso" }, + { "value": "445328", "label": "Brightwood College-Fort Worth" }, + { "value": "447120", "label": "Brightwood College-Fresno" }, + { "value": "458283", "label": "Brightwood College-Indianapolis" }, + { "value": "440332", "label": "Brightwood College-Laredo" }, + { "value": "374875", "label": "Brightwood College-Las Vegas" }, + { "value": "227836", "label": "Brightwood College-McAllen" }, + { "value": "366960", "label": "Brightwood College-Modesto" }, + { "value": "246202", "label": "Brightwood College-Nashville" }, + { "value": "447634", "label": "Brightwood College-Palm Springs" }, + { "value": "432302", "label": "Brightwood College-Riverside" }, + { "value": "118259", "label": "Brightwood College-Sacramento" }, + { "value": "431886", "label": "Brightwood College-San Antonio-Ingram" }, + { "value": "364955", "label": "Brightwood College-San Antonio-San Pedro" }, + { "value": "118277", "label": "Brightwood College-San Diego" }, + { "value": "161776", "label": "Brightwood College-Towson" }, + { "value": "118286", "label": "Brightwood College-Vista" }, + { "value": "165033", "label": "Bristol Community College" }, + { "value": "397270", "label": "Bristol University" }, + { "value": "450304", "label": "Brite Divinity School" }, + { "value": "459091", "label": "Broadview Entertainment Arts University" }, + { "value": "467793", "label": "Broadview University-Boise" }, + { "value": "450429", "label": "Broadview University-Layton" }, + { "value": "454591", "label": "Broadview University-Orem" }, + { "value": "230056", "label": "Broadview University-West Jordan" }, + { "value": "183859", "label": "Brookdale Community College" }, + { "value": "223524", "label": "Brookhaven College" }, + { "value": "444088", "label": "Brookline College-Albuquerque" }, + { "value": "104090", "label": "Brookline College-Phoenix" }, + { "value": "404055", "label": "Brookline College-Tempe" }, + { "value": "438179", "label": "Brookline College-Tucson" }, + { "value": "189501", "label": "Brooklyn Law School" }, + { "value": "110185", "label": "Brooks Institute" }, + { "value": "132709", "label": "Broward College" }, + { "value": "205647", "label": "Brown Mackie College-Akron" }, + { "value": "460039", "label": "Brown Mackie College-Albuquerque" }, + { "value": "410283", "label": "Brown Mackie College-Atlanta" }, + { "value": "470162", "label": "Brown Mackie College-Birmingham" }, + { "value": "455600", "label": "Brown Mackie College-Boise" }, + { "value": "205610", "label": "Brown Mackie College-Cincinnati" }, + { "value": "482954", "label": "Brown Mackie College-Dallas" }, + { "value": "375489", "label": "Brown Mackie College-Findlay" }, + { "value": "408039", "label": "Brown Mackie College-Fort Wayne" }, + { "value": "456791", "label": "Brown Mackie College-Greenville" }, + { "value": "421513", "label": "Brown Mackie College-Hopkinsville" }, + { "value": "451699", "label": "Brown Mackie College-Indianapolis" }, + { "value": "154767", "label": "Brown Mackie College-Kansas City" }, + { "value": "157599", "label": "Brown Mackie College-Louisville" }, + { "value": "151616", "label": "Brown Mackie College-Merrillville" }, + { "value": "447290", "label": "Brown Mackie College-Miami" }, + { "value": "151625", "label": "Brown Mackie College-Michigan City" }, + { "value": "204316", "label": "Brown Mackie College-North Canton" }, + { "value": "157696", "label": "Brown Mackie College-Northern Kentucky" }, + { "value": "475042", "label": "Brown Mackie College-Oklahoma City" }, + { "value": "456612", "label": "Brown Mackie College-Phoenix" }, + { "value": "373085", "label": "Brown Mackie College-Quad Cities" }, + { "value": "154776", "label": "Brown Mackie College-Salina" }, + { "value": "460613", "label": "Brown Mackie College-San Antonio" }, + { "value": "151944", "label": "Brown Mackie College-South Bend" }, + { "value": "460048", "label": "Brown Mackie College-St Louis" }, + { "value": "104364", "label": "Brown Mackie College-Tucson" }, + { "value": "455619", "label": "Brown Mackie College-Tulsa" }, + { "value": "217156", "label": "Brown University" }, + { "value": "198084", "label": "Brunswick Community College" }, + { "value": "180878", "label": "Bryan College of Health Sciences" }, + { "value": "219790", "label": "Bryan College-Dayton" }, + { "value": "439826", "label": "Bryan College-Gold River" }, + { "value": "475583", "label": "Bryan University-Columbia" }, + { "value": "110219", "label": "Bryan University-Los Angeles" }, + { "value": "454458", "label": "Bryan University-Rogers" }, + { "value": "369516", "label": "Bryan University-Springfield" }, + { "value": "154794", "label": "Bryan University-Topeka" }, + { "value": "475699", "label": "Bryant & Stratton College-Akron" }, + { "value": "188517", "label": "Bryant & Stratton College-Albany" }, + { "value": "189556", "label": "Bryant & Stratton College-Amherst" }, + { "value": "458502", "label": "Bryant & Stratton College-Bayshore" }, + { "value": "189583", "label": "Bryant & Stratton College-Buffalo" }, + { "value": "202684", "label": "Bryant & Stratton College-Cleveland" }, + { "value": "369905", "label": "Bryant & Stratton College-Eastlake" }, + { "value": "189592", "label": "Bryant & Stratton College-Greece" }, + { "value": "459107", "label": "Bryant & Stratton College-Hampton" }, + { "value": "410496", "label": "Bryant & Stratton College-Henrietta" }, + { "value": "239929", "label": "Bryant & Stratton College-Milwaukee" }, + { "value": "480091", "label": "Bryant & Stratton College-Online" }, + { "value": "201469", "label": "Bryant & Stratton College-Parma" }, + { "value": "231828", "label": "Bryant & Stratton College-Richmond" }, + { "value": "374972", "label": "Bryant & Stratton College-Southtowns" }, + { "value": "189574", "label": "Bryant & Stratton College-Syracuse" }, + { "value": "189565", "label": "Bryant & Stratton College-Syracuse North" }, + { "value": "231785", "label": "Bryant & Stratton College-Virginia Beach" }, + { "value": "451750", "label": "Bryant & Stratton College-Wauwatosa" }, + { "value": "217165", "label": "Bryant University" }, + { "value": "210492", "label": "Bryn Athyn College of the New Church" }, + { "value": "211273", "label": "Bryn Mawr College" }, + { "value": "211291", "label": "Bucknell University" }, + { "value": "211307", "label": "Bucks County Community College" }, + { "value": "211316", "label": "Bucks County School of Beauty Culture Inc" }, + { "value": "153001", "label": "Buena Vista University" }, + { "value": "165112", "label": "Bunker Hill Community College" }, + { "value": "230825", "label": "Burlington College" }, + { "value": "484181", "label": "Burnett International College" }, + { "value": "189653", "label": "Business Informatics Center Inc" }, + { "value": "154800", "label": "Butler Community College" }, + { "value": "211343", "label": "Butler County Community College" }, + { "value": "150163", "label": "Butler University" }, + { "value": "110246", "label": "Butte College" }, + { + "value": "444103", + "label": "Byzantine Catholic Seminary of Saints Cyril and Methodius" + }, + { "value": "198109", "label": "Cabarrus College of Health Sciences" }, + { "value": "110334", "label": "Cabrillo College" }, + { "value": "211352", "label": "Cabrini University" }, + { "value": "215114", "label": "Cairn University-Langhorne" }, + { + "value": "198118", + "label": "Caldwell Community College and Technical Institute" + }, + { "value": "183910", "label": "Caldwell University" }, + { "value": "110361", "label": "California Baptist University" }, + { "value": "110918", "label": "California Christian College" }, + { "value": "110370", "label": "California College of the Arts" }, + { "value": "485263", "label": "California College San Diego-San Diego" }, + { "value": "478634", "label": "California College San Diego-San Marcos" }, + { "value": "110316", "label": "California Institute of Integral Studies" }, + { "value": "110404", "label": "California Institute of Technology" }, + { "value": "111081", "label": "California Institute of the Arts" }, + { "value": "110413", "label": "California Lutheran University" }, + { "value": "480781", "label": "California Miramar University" }, + { + "value": "110422", + "label": "California Polytechnic State University-San Luis Obispo" + }, + { + "value": "110529", + "label": "California State Polytechnic University-Pomona" + }, + { "value": "110486", "label": "California State University-Bakersfield" }, + { + "value": "441937", + "label": "California State University-Channel Islands" + }, + { "value": "110538", "label": "California State University-Chico" }, + { + "value": "110547", + "label": "California State University-Dominguez Hills" + }, + { "value": "110574", "label": "California State University-East Bay" }, + { "value": "110556", "label": "California State University-Fresno" }, + { "value": "110565", "label": "California State University-Fullerton" }, + { "value": "110583", "label": "California State University-Long Beach" }, + { "value": "110592", "label": "California State University-Los Angeles" }, + { "value": "409698", "label": "California State University-Monterey Bay" }, + { "value": "110608", "label": "California State University-Northridge" }, + { "value": "110617", "label": "California State University-Sacramento" }, + { + "value": "110510", + "label": "California State University-San Bernardino" + }, + { "value": "366711", "label": "California State University-San Marcos" }, + { "value": "110495", "label": "California State University-Stanislaus" }, + { + "value": "460075", + "label": "California University of Management and Sciences" + }, + { "value": "211361", "label": "California University of Pennsylvania" }, + { "value": "111391", "label": "California Western School of Law" }, + { "value": "150172", "label": "Calumet College of Saint Joseph" }, + { + "value": "176789", + "label": "Calvary Bible College and Theological Seminary" + }, + { "value": "169080", "label": "Calvin College" }, + { "value": "169099", "label": "Calvin Theological Seminary" }, + { "value": "428329", "label": "Cambria-Rowe Business College-Indiana" }, + { "value": "211398", "label": "Cambria-Rowe Business College-Johnstown" }, + { "value": "165167", "label": "Cambridge College" }, + { + "value": "454865", + "label": "Cambridge College of Healthcare & Technology" + }, + { "value": "446093", "label": "Cambridge Junior College-Yuba City" }, + { "value": "183938", "label": "Camden County College" }, + { "value": "158440", "label": "Cameron College" }, + { "value": "206914", "label": "Cameron University" }, + { "value": "198136", "label": "Campbell University" }, + { "value": "156365", "label": "Campbellsville University" }, + { "value": "111434", "label": "Canada College" }, + { "value": "189705", "label": "Canisius College" }, + { "value": "200208", "label": "Cankdeska Cikana Community College" }, + { "value": "165194", "label": "Cape Cod Community College" }, + { "value": "198154", "label": "Cape Fear Community College" }, + { "value": "413413", "label": "Capella University" }, + { "value": "158352", "label": "Capital Area Technical College" }, + { "value": "129367", "label": "Capital Community College" }, + { "value": "201548", "label": "Capital University" }, + { "value": "162061", "label": "Capitol Technology University" }, + { "value": "238430", "label": "Cardinal Stritch University" }, + { "value": "181941", "label": "Career College of Northern Nevada" }, + { "value": "224439", "label": "Career Point College-San Antonio" }, + { "value": "246008", "label": "Career Point College-Tulsa" }, + { "value": "454306", "label": "Career Quest Learning Centers-Jackson" }, + { "value": "446136", "label": "Career Quest Learning Centers-Lansing" }, + { "value": "367112", "label": "Career Technical College-Monroe" }, + { "value": "446880", "label": "Career Technical College-Shreveport" }, + { "value": "210951", "label": "Career Training Academy-Lower Burrell" }, + { "value": "408312", "label": "Career Training Academy-Monroeville" }, + { "value": "440174", "label": "Career Training Academy-Pittsburgh" }, + { "value": "448239", "label": "Careers Unlimited" }, + { "value": "241377", "label": "Caribbean University-Bayamon" }, + { "value": "241386", "label": "Caribbean University-Carolina" }, + { "value": "363907", "label": "Caribbean University-Ponce" }, + { "value": "363916", "label": "Caribbean University-Vega Baja" }, + { "value": "206923", "label": "Carl Albert State College" }, + { "value": "143613", "label": "Carl Sandburg College" }, + { "value": "173258", "label": "Carleton College" }, + { "value": "132842", "label": "Carlos Albizu University-Miami" }, + { "value": "241331", "label": "Carlos Albizu University-San Juan" }, + { "value": "211431", "label": "Carlow University" }, + { "value": "211440", "label": "Carnegie Mellon University" }, + { "value": "199971", "label": "Carolina Christian College" }, + { "value": "461032", "label": "Carolina College of Biblical Studies" }, + { "value": "433174", "label": "Carolinas College of Health Sciences" }, + { "value": "442602", "label": "Carrington College-Albuquerque" }, + { "value": "142054", "label": "Carrington College-Boise" }, + { "value": "450702", "label": "Carrington College-Citrus Heights" }, + { "value": "457101", "label": "Carrington College-Las Vegas" }, + { "value": "103909", "label": "Carrington College-Mesa" }, + { "value": "103893", "label": "Carrington College-Phoenix" }, + { "value": "438258", "label": "Carrington College-Pleasant Hill" }, + { "value": "467368", "label": "Carrington College-Pomona" }, + { "value": "246035", "label": "Carrington College-Portland" }, + { "value": "457110", "label": "Carrington College-Reno" }, + { "value": "125532", "label": "Carrington College-Sacramento" }, + { "value": "437936", "label": "Carrington College-San Jose" }, + { "value": "246974", "label": "Carrington College-San Leandro" }, + { "value": "439118", "label": "Carrington College-Spokane" }, + { "value": "450696", "label": "Carrington College-Stockton" }, + { "value": "103927", "label": "Carrington College-Tucson" }, + { "value": "250601", "label": "Carrington College-Westside" }, + { "value": "180106", "label": "Carroll College" }, + { "value": "405872", "label": "Carroll Community College" }, + { "value": "238458", "label": "Carroll University" }, + { "value": "219806", "label": "Carson-Newman University" }, + { "value": "198206", "label": "Carteret Community College" }, + { "value": "238476", "label": "Carthage College" }, + { "value": "139287", "label": "Carver Bible College" }, + { "value": "430795", "label": "Carver Career Center" }, + { "value": "111638", "label": "Casa Loma College-Van Nuys" }, + { "value": "439190", "label": "Cascadia College" }, + { "value": "201645", "label": "Case Western Reserve University" }, + { "value": "240505", "label": "Casper College" }, + { "value": "230834", "label": "Castleton State College" }, + { "value": "198215", "label": "Catawba College" }, + { "value": "198233", "label": "Catawba Valley Community College" }, + { "value": "475398", "label": "Catholic Distance University" }, + { "value": "143659", "label": "Catholic Theological Union at Chicago" }, + { "value": "131283", "label": "Catholic University of America" }, + { "value": "189839", "label": "Cayuga County Community College" }, + { "value": "189848", "label": "Cazenovia College" }, + { "value": "162104", "label": "Cecil College" }, + { "value": "211468", "label": "Cedar Crest College" }, + { "value": "223773", "label": "Cedar Valley College" }, + { "value": "201654", "label": "Cedarville University" }, + { "value": "183974", "label": "Centenary College" }, + { "value": "158477", "label": "Centenary College of Louisiana" }, + { "value": "379782", "label": "Center for Advanced Legal Studies" }, + { + "value": "241793", + "label": "Center for Advanced Studies On Puerto Rico and the Caribbean" + }, + { "value": "232618", "label": "Centra College of Nursing" }, + { "value": "100760", "label": "Central Alabama Community College" }, + { "value": "104346", "label": "Central Arizona College" }, + { "value": "106713", "label": "Central Baptist College" }, + { "value": "154837", "label": "Central Baptist Theological Seminary" }, + { "value": "198251", "label": "Central Carolina Community College" }, + { "value": "218858", "label": "Central Carolina Technical College" }, + { "value": "154855", "label": "Central Christian College of Kansas" }, + { "value": "176910", "label": "Central Christian College of the Bible" }, + { "value": "153108", "label": "Central College" }, + { "value": "180902", "label": "Central Community College" }, + { "value": "128771", "label": "Central Connecticut State University" }, + { "value": "439525", "label": "Central Florida Institute" }, + { "value": "483045", "label": "Central Georgia Technical College" }, + { "value": "173203", "label": "Central Lakes College-Brainerd" }, + { + "value": "158088", + "label": "Central Louisiana Technical Community College" + }, + { "value": "161077", "label": "Central Maine Community College" }, + { + "value": "445267", + "label": "Central Methodist University-College of Graduate and Extended Studies" + }, + { + "value": "176947", + "label": "Central Methodist University-College of Liberal Arts and Sciences" + }, + { "value": "169248", "label": "Central Michigan University" }, + { "value": "187532", "label": "Central New Mexico Community College" }, + { "value": "201672", "label": "Central Ohio Technical College" }, + { "value": "208318", "label": "Central Oregon Community College" }, + { "value": "211477", "label": "Central Penn College" }, + { "value": "198260", "label": "Central Piedmont Community College" }, + { "value": "201690", "label": "Central State University" }, + { "value": "223816", "label": "Central Texas College" }, + { "value": "231697", "label": "Central Virginia Community College" }, + { "value": "234827", "label": "Central Washington University" }, + { "value": "240514", "label": "Central Wyoming College" }, + { "value": "189857", "label": "Central Yeshiva Tomchei Tmimim Lubavitz" }, + { "value": "234845", "label": "Centralia College" }, + { "value": "156408", "label": "Centre College" }, + { + "value": "451741", + "label": "Centro de Estudios Multidisciplinarios-Bayamon" + }, + { + "value": "376224", + "label": "Centro de Estudios Multidisciplinarios-Humacao" + }, + { + "value": "241517", + "label": "Centro de Estudios Multidisciplinarios-San Juan" + }, + { "value": "420024", "label": "Centura College-Chesapeake" }, + { "value": "444972", "label": "Centura College-Columbia" }, + { "value": "377449", "label": "Centura College-Newport News" }, + { "value": "377458", "label": "Centura College-Norfolk" }, + { "value": "427982", "label": "Centura College-Richmond Main" }, + { "value": "232016", "label": "Centura College-Virginia Beach" }, + { "value": "175315", "label": "Century College-White Bear Lake" }, + { "value": "111887", "label": "Cerritos College" }, + { "value": "111896", "label": "Cerro Coso Community College" }, + { "value": "111920", "label": "Chabot College" }, + { "value": "180948", "label": "Chadron State College" }, + { "value": "111939", "label": "Chaffey College" }, + { "value": "454245", "label": "Chamberlain College of Nursing-Arizona" }, + { "value": "457129", "label": "Chamberlain College of Nursing-Florida" }, + { "value": "475732", "label": "Chamberlain College of Nursing-Georgia" }, + { "value": "454227", "label": "Chamberlain College of Nursing-Illinois" }, + { "value": "466921", "label": "Chamberlain College of Nursing-Missouri" }, + { "value": "454236", "label": "Chamberlain College of Nursing-Ohio" }, + { "value": "466930", "label": "Chamberlain College of Nursing-Texas" }, + { "value": "460871", "label": "Chamberlain College of Nursing-Virginia" }, + { "value": "141486", "label": "Chaminade University of Honolulu" }, + { "value": "230852", "label": "Champlain College" }, + { "value": "364025", "label": "Chandler-Gilbert Community College" }, + { "value": "111948", "label": "Chapman University" }, + { + "value": "111966", + "label": "Charles R Drew University of Medicine and Science" + }, + { "value": "451510", "label": "Charleston School of Law" }, + { "value": "217688", "label": "Charleston Southern University" }, + { + "value": "444778", + "label": "Charlotte Christian College and Theological Seminary" + }, + { "value": "455169", "label": "Charlotte School of Law" }, + { "value": "102845", "label": "Charter College-Anchorage" }, + { "value": "434317", "label": "Charter College-Canyon Country" }, + { "value": "128780", "label": "Charter Oak State College" }, + { "value": "201751", "label": "Chatfield College" }, + { "value": "211556", "label": "Chatham University" }, + { "value": "140331", "label": "Chattahoochee Technical College" }, + { "value": "101028", "label": "Chattahoochee Valley Community College" }, + { + "value": "220118", + "label": "Chattanooga College Medical Dental and Technical Careers" + }, + { "value": "219824", "label": "Chattanooga State Community College" }, + { "value": "208390", "label": "Chemeketa Community College" }, + { "value": "162168", "label": "Chesapeake College" }, + { "value": "437769", "label": "Chester Career College" }, + { "value": "211583", "label": "Chestnut Hill College" }, + { "value": "211608", "label": "Cheyney University of Pennsylvania" }, + { + "value": "181145", + "label": "CHI Health School of Radiologic Technology" + }, + { "value": "393180", "label": "Chicago ORT Technical Institute" }, + { "value": "144005", "label": "Chicago State University" }, + { "value": "144014", "label": "Chicago Theological Seminary" }, + { "value": "180160", "label": "Chief Dull Knife College" }, + { "value": "133021", "label": "Chipola College" }, + { "value": "240116", "label": "Chippewa Valley Technical College" }, + { "value": "198303", "label": "Chowan University" }, + { "value": "189981", "label": "Christ the King Seminary" }, + { "value": "219833", "label": "Christian Brothers University" }, + { "value": "260947", "label": "Christian Life College" }, + { "value": "150215", "label": "Christian Theological Seminary" }, + { "value": "475510", "label": "Christie's Education" }, + { "value": "231712", "label": "Christopher Newport University" }, + { "value": "112127", "label": "Church Divinity School of the Pacific" }, + { "value": "201858", "label": "Cincinnati Christian University" }, + { "value": "201867", "label": "Cincinnati College of Mortuary Science" }, + { + "value": "201928", + "label": "Cincinnati State Technical and Community College" + }, + { "value": "223898", "label": "Cisco College" }, + { + "value": "217864", + "label": "Citadel Military College of South Carolina" + }, + { "value": "112172", "label": "Citrus College" }, + { "value": "112190", "label": "City College of San Francisco" }, + { "value": "417327", "label": "City College-Altamonte Springs" }, + { "value": "244233", "label": "City College-Fort Lauderdale" }, + { "value": "406547", "label": "City College-Gainesville" }, + { "value": "475477", "label": "City College-Hollywood" }, + { "value": "434539", "label": "City College-Miami" }, + { + "value": "144209", + "label": "City Colleges of Chicago-Harold Washington College" + }, + { + "value": "144184", + "label": "City Colleges of Chicago-Harry S Truman College" + }, + { + "value": "144157", + "label": "City Colleges of Chicago-Kennedy-King College" + }, + { + "value": "144166", + "label": "City Colleges of Chicago-Malcolm X College" + }, + { + "value": "144175", + "label": "City Colleges of Chicago-Olive-Harvey College" + }, + { + "value": "144193", + "label": "City Colleges of Chicago-Richard J Daley College" + }, + { + "value": "144218", + "label": "City Colleges of Chicago-Wilbur Wright College" + }, + { "value": "234915", "label": "City University of Seattle" }, + { "value": "457697", "label": "City Vision University" }, + { "value": "208406", "label": "Clackamas Community College" }, + { "value": "217873", "label": "Claflin University" }, + { "value": "112251", "label": "Claremont Graduate University" }, + { "value": "112260", "label": "Claremont McKenna College" }, + { "value": "124283", "label": "Claremont School of Theology" }, + { "value": "223922", "label": "Clarendon College" }, + { "value": "211644", "label": "Clarion University of Pennsylvania" }, + { "value": "138947", "label": "Clark Atlanta University" }, + { "value": "234933", "label": "Clark College" }, + { "value": "201973", "label": "Clark State Community College" }, + { "value": "165334", "label": "Clark University" }, + { "value": "153126", "label": "Clarke University" }, + { "value": "180832", "label": "Clarkson College" }, + { "value": "190044", "label": "Clarkson University" }, + { "value": "450401", "label": "Clary Sage College" }, + { "value": "208415", "label": "Clatsop Community College" }, + { "value": "139311", "label": "Clayton State University" }, + { "value": "156417", "label": "Clear Creek Baptist Bible College" }, + { "value": "133085", "label": "Clearwater Christian College" }, + { "value": "169327", "label": "Cleary University" }, + { "value": "217882", "label": "Clemson University" }, + { "value": "198321", "label": "Cleveland Community College" }, + { "value": "202046", "label": "Cleveland Institute of Art" }, + { "value": "202073", "label": "Cleveland Institute of Music" }, + { "value": "219879", "label": "Cleveland State Community College" }, + { "value": "202134", "label": "Cleveland State University" }, + { "value": "177038", "label": "Cleveland University-Kansas City" }, + { "value": "217891", "label": "Clinton College" }, + { "value": "190053", "label": "Clinton Community College" }, + { "value": "154907", "label": "Cloud County Community College" }, + { "value": "234951", "label": "Clover Park Technical College" }, + { "value": "187639", "label": "Clovis Community College" }, + { "value": "175519", "label": "Coahoma Community College" }, + { "value": "223320", "label": "Coastal Bend College" }, + { "value": "198330", "label": "Coastal Carolina Community College" }, + { "value": "218724", "label": "Coastal Carolina University" }, + { "value": "485458", "label": "Coastal Pines Technical College-Waycross" }, + { "value": "112385", "label": "Coastline Community College" }, + { "value": "104425", "label": "Cochise County Community College District" }, + { "value": "190071", "label": "Cochran School of Nursing" }, + { "value": "404426", "label": "Coconino Community College" }, + { "value": "153144", "label": "Coe College" }, + { "value": "154925", "label": "Coffeyville Community College" }, + { "value": "112394", "label": "Cogswell College" }, + { "value": "217907", "label": "Coker College" }, + { "value": "161086", "label": "Colby College" }, + { "value": "154934", "label": "Colby Community College" }, + { "value": "182634", "label": "Colby-Sawyer College" }, + { + "value": "430935", + "label": "Colegio de Cinematografía Artes y Television" + }, + { "value": "241720", "label": "Colegio Universitario de San Juan" }, + { "value": "112446", "label": "Coleman University" }, + { "value": "190080", "label": "Colgate Rochester Crozer Divinity School" }, + { "value": "190099", "label": "Colgate University" }, + { "value": "169442", "label": "College for Creative Studies" }, + { "value": "108667", "label": "College of Alameda" }, + { "value": "388520", "label": "College of Biblical Studies-Houston" }, + { + "value": "456977", + "label": "College of Business and Technology-Cutler Bay" + }, + { + "value": "449083", + "label": "College of Business and Technology-Flagler" + }, + { + "value": "449092", + "label": "College of Business and Technology-Hialeah" + }, + { + "value": "417318", + "label": "College of Business and Technology-Kendall" + }, + { + "value": "482024", + "label": "College of Business and Technology-Miami Gardens" + }, + { "value": "132851", "label": "College of Central Florida" }, + { "value": "217819", "label": "College of Charleston" }, + { "value": "139250", "label": "College of Coastal Georgia" }, + { "value": "150251", "label": "College of Court Reporting Inc" }, + { "value": "144865", "label": "College of DuPage" }, + { + "value": "392257", + "label": "College of Health Care Professions-Northwest" + }, + { "value": "146472", "label": "College of Lake County" }, + { "value": "118347", "label": "College of Marin" }, + { "value": "413617", "label": "College of Menominee Nation" }, + { "value": "243638", "label": "College of Micronesia-FSM" }, + { "value": "193399", "label": "College of Mount Saint Vincent" }, + { "value": "167394", "label": "College of Our Lady of the Elms" }, + { "value": "174747", "label": "College of Saint Benedict" }, + { "value": "186618", "label": "College of Saint Elizabeth" }, + { "value": "181604", "label": "College of Saint Mary" }, + { "value": "122791", "label": "College of San Mateo" }, + { "value": "142559", "label": "College of Southern Idaho" }, + { "value": "162122", "label": "College of Southern Maryland" }, + { "value": "182005", "label": "College of Southern Nevada" }, + { "value": "231077", "label": "College of St Joseph" }, + { "value": "190558", "label": "College of Staten Island CUNY" }, + { "value": "197814", "label": "College of the Albemarle" }, + { "value": "160959", "label": "College of the Atlantic" }, + { "value": "111461", "label": "College of the Canyons" }, + { "value": "113573", "label": "College of the Desert" }, + { "value": "166124", "label": "College of the Holy Cross" }, + { "value": "226408", "label": "College of the Mainland" }, + { "value": "376695", "label": "College of the Marshall Islands" }, + { "value": "480967", "label": "College of the Muscogee Nation" }, + { "value": "107521", "label": "College of the Ouachitas" }, + { "value": "178697", "label": "College of the Ozarks" }, + { "value": "121707", "label": "College of the Redwoods" }, + { "value": "123217", "label": "College of the Sequoias" }, + { "value": "123484", "label": "College of the Siskiyous" }, + { "value": "455114", "label": "College of Western Idaho" }, + { "value": "231624", "label": "College of William and Mary" }, + { "value": "451705", "label": "CollegeAmerica-Cheyenne" }, + { "value": "448752", "label": "CollegeAmerica-Colorado Springs" }, + { "value": "126872", "label": "CollegeAmerica-Denver" }, + { "value": "103945", "label": "CollegeAmerica-Flagstaff" }, + { "value": "448761", "label": "CollegeAmerica-Fort Collins" }, + { "value": "474890", "label": "CollegeAmerica-Phoenix" }, + { "value": "247834", "label": "Collin County Community College District" }, + { "value": "103723", "label": "Collins College" }, + { "value": "461953", "label": "Colorado Academy of Veterinary Technology" }, + { "value": "126669", "label": "Colorado Christian University" }, + { "value": "126678", "label": "Colorado College" }, + { "value": "367839", "label": "Colorado Heights University" }, + { "value": "127556", "label": "Colorado Mesa University" }, + { "value": "126711", "label": "Colorado Mountain College" }, + { "value": "126748", "label": "Colorado Northwestern Community College" }, + { "value": "381732", "label": "Colorado School of Healing Arts" }, + { "value": "126775", "label": "Colorado School of Mines" }, + { "value": "126784", "label": "Colorado School of Trades" }, + { + "value": "381352", + "label": "Colorado School of Traditional Chinese Medicine" + }, + { "value": "126818", "label": "Colorado State University-Fort Collins" }, + { "value": "476975", "label": "Colorado State University-Global Campus" }, + { "value": "128106", "label": "Colorado State University-Pueblo" }, + { + "value": "126827", + "label": "Colorado Technical University-Colorado Springs" + }, + { + "value": "430087", + "label": "Colorado Technical University-Greenwood Village" + }, + { "value": "444158", "label": "Colorado Technical University-Online" }, + { "value": "402615", "label": "Colorado Technical University-Sioux Falls" }, + { "value": "234979", "label": "Columbia Basin College" }, + { "value": "241304", "label": "Columbia Central University-Caguas" }, + { "value": "404806", "label": "Columbia Central University-Yauco" }, + { "value": "238573", "label": "Columbia College of Nursing" }, + { "value": "144281", "label": "Columbia College-Chicago" }, + { "value": "177065", "label": "Columbia College-Columbia" }, + { "value": "217934", "label": "Columbia College-Columbia" }, + { "value": "455983", "label": "Columbia College-Fairfax" }, + { "value": "112570", "label": "Columbia College-Hollywood" }, + { "value": "112561", "label": "Columbia College-Sonora" }, + { "value": "420556", "label": "Columbia Gorge Community College" }, + { "value": "217925", "label": "Columbia International University" }, + { "value": "450933", "label": "Columbia Southern University" }, + { "value": "219888", "label": "Columbia State Community College" }, + { "value": "139348", "label": "Columbia Theological Seminary" }, + { + "value": "190150", + "label": "Columbia University in the City of New York" + }, + { "value": "190169", "label": "Columbia-Greene Community College" }, + { "value": "202170", "label": "Columbus College of Art and Design" }, + { "value": "202222", "label": "Columbus State Community College" }, + { "value": "139366", "label": "Columbus State University" }, + { "value": "139357", "label": "Columbus Technical College" }, + { "value": "483522", "label": "Comanche Nation College" }, + { "value": "366261", "label": "Commonwealth Institute of Funeral Service" }, + { "value": "212975", "label": "Commonwealth Technical Institute" }, + { "value": "439570", "label": "Community Care College" }, + { "value": "446163", "label": "Community Christian College" }, + { "value": "210605", "label": "Community College of Allegheny County" }, + { "value": "126863", "label": "Community College of Aurora" }, + { "value": "211079", "label": "Community College of Beaver County" }, + { "value": "126942", "label": "Community College of Denver" }, + { "value": "215239", "label": "Community College of Philadelphia" }, + { "value": "217475", "label": "Community College of Rhode Island" }, + { "value": "230861", "label": "Community College of Vermont" }, + { "value": "459417", "label": "Compass College of Cinematic Arts" }, + { "value": "177083", "label": "Conception Seminary College" }, + { "value": "237330", "label": "Concord University" }, + { "value": "126687", "label": "Concorde Career College-Aurora" }, + { "value": "460181", "label": "Concorde Career College-Dallas" }, + { "value": "123679", "label": "Concorde Career College-Garden Grove" }, + { "value": "441742", "label": "Concorde Career College-Grand Prairie" }, + { "value": "155283", "label": "Concorde Career College-Kansas City" }, + { "value": "219903", "label": "Concorde Career College-Memphis" }, + { "value": "124937", "label": "Concorde Career College-North Hollywood" }, + { "value": "208479", "label": "Concorde Career College-Portland" }, + { "value": "460206", "label": "Concorde Career College-San Antonio" }, + { "value": "124706", "label": "Concorde Career College-San Bernardino" }, + { "value": "120661", "label": "Concorde Career College-San Diego" }, + { "value": "133845", "label": "Concorde Career Institute-Jacksonville" }, + { "value": "133854", "label": "Concorde Career Institute-Miramar" }, + { "value": "460190", "label": "Concorde Career Institute-Orlando" }, + { "value": "133863", "label": "Concorde Career Institute-Tampa" }, + { "value": "101073", "label": "Concordia College Alabama" }, + { "value": "173300", "label": "Concordia College at Moorhead" }, + { "value": "190248", "label": "Concordia College-New York" }, + { "value": "177092", "label": "Concordia Seminary" }, + { "value": "150288", "label": "Concordia Theological Seminary" }, + { "value": "169363", "label": "Concordia University-Ann Arbor" }, + { "value": "144351", "label": "Concordia University-Chicago" }, + { "value": "112075", "label": "Concordia University-Irvine" }, + { "value": "180984", "label": "Concordia University-Nebraska" }, + { "value": "208488", "label": "Concordia University-Portland" }, + { "value": "173328", "label": "Concordia University-Saint Paul" }, + { "value": "224004", "label": "Concordia University-Texas" }, + { "value": "238616", "label": "Concordia University-Wisconsin" }, + { "value": "128902", "label": "Connecticut College" }, + { "value": "206996", "label": "Connors State College" }, + { "value": "260354", "label": "Consolidated School of Business-Lancaster" }, + { "value": "211820", "label": "Consolidated School of Business-York" }, + { "value": "112826", "label": "Contra Costa College" }, + { "value": "217961", "label": "Converse College" }, + { "value": "165495", "label": "Conway School of Landscape Design" }, + { + "value": "190372", + "label": "Cooper Union for the Advancement of Science and Art" + }, + { "value": "175573", "label": "Copiah-Lincoln Community College" }, + { "value": "395362", "label": "Copper Mountain Community College" }, + { "value": "162283", "label": "Coppin State University" }, + { "value": "210331", "label": "Corban University" }, + { "value": "153162", "label": "Cornell College" }, + { "value": "190415", "label": "Cornell University" }, + { "value": "170037", "label": "Cornerstone University" }, + { "value": "190442", "label": "Corning Community College" }, + { "value": "235024", "label": "Cornish College of the Arts" }, + { + "value": "106795", + "label": "Cossatot Community College of the University of Arkansas" + }, + { "value": "113096", "label": "Cosumnes River College" }, + { "value": "177117", "label": "Cottey College" }, + { "value": "184180", "label": "County College of Morris" }, + { "value": "224183", "label": "Court Reporting Institute of Dallas" }, + { "value": "139393", "label": "Covenant College" }, + { "value": "177126", "label": "Covenant Theological Seminary" }, + { "value": "154952", "label": "Cowley County Community College" }, + { "value": "176770", "label": "Cox College" }, + { "value": "144485", "label": "Coyne College" }, + { "value": "113111", "label": "Crafton Hills College" }, + { "value": "169424", "label": "Cranbrook Academy of Art" }, + { "value": "198367", "label": "Craven Community College" }, + { "value": "181002", "label": "Creighton University" }, + { "value": "475608", "label": "Criswell College" }, + { "value": "439613", "label": "Crossroads Bible College" }, + { "value": "174206", "label": "Crossroads College" }, + { "value": "177135", "label": "Crowder College" }, + { "value": "106810", "label": "Crowley's Ridge College" }, + { "value": "174862", "label": "Crown College" }, + { "value": "113193", "label": "Cuesta College" }, + { "value": "444565", "label": "Culinary Institute Inc" }, + { "value": "190503", "label": "Culinary Institute of America" }, + { "value": "177144", "label": "Culver-Stockton College" }, + { "value": "184205", "label": "Cumberland County College" }, + { "value": "219949", "label": "Cumberland University" }, + { "value": "190512", "label": "CUNY Bernard M Baruch College" }, + { + "value": "190521", + "label": "CUNY Borough of Manhattan Community College" + }, + { "value": "190530", "label": "CUNY Bronx Community College" }, + { "value": "190549", "label": "CUNY Brooklyn College" }, + { "value": "190567", "label": "CUNY City College" }, + { + "value": "190576", + "label": "CUNY Graduate School and University Center" + }, + { "value": "190585", "label": "CUNY Hostos Community College" }, + { "value": "190594", "label": "CUNY Hunter College" }, + { "value": "190600", "label": "CUNY John Jay College of Criminal Justice" }, + { "value": "190619", "label": "CUNY Kingsborough Community College" }, + { "value": "190628", "label": "CUNY LaGuardia Community College" }, + { "value": "190637", "label": "CUNY Lehman College" }, + { "value": "190646", "label": "CUNY Medgar Evers College" }, + { "value": "190655", "label": "CUNY New York City College of Technology" }, + { "value": "190664", "label": "CUNY Queens College" }, + { "value": "190673", "label": "CUNY Queensborough Community College" }, + { "value": "190682", "label": "CUNY School of Law" }, + { "value": "190691", "label": "CUNY York College" }, + { "value": "165529", "label": "Curry College" }, + { "value": "211893", "label": "Curtis Institute of Music" }, + { "value": "202356", "label": "Cuyahoga Community College District" }, + { "value": "113218", "label": "Cuyamaca College" }, + { "value": "113236", "label": "Cypress College" }, + { "value": "231873", "label": "Dabney S Lancaster Community College" }, + { "value": "458797", "label": "Dade Medical College-Hollywood" }, + { "value": "458247", "label": "Dade Medical College-Homestead" }, + { "value": "476391", "label": "Dade Medical College-Jacksonville" }, + { "value": "444574", "label": "Dade Medical College-Miami" }, + { "value": "454175", "label": "Dade Medical College-Miami Lakes" }, + { "value": "476382", "label": "Dade Medical College-West Palm Beach" }, + { "value": "190725", "label": "Daemen College" }, + { "value": "200314", "label": "Dakota College at Bottineau" }, + { "value": "173416", "label": "Dakota County Technical College" }, + { "value": "219082", "label": "Dakota State University" }, + { "value": "219091", "label": "Dakota Wesleyan University" }, + { "value": "224226", "label": "Dallas Baptist University" }, + { "value": "224244", "label": "Dallas Christian College" }, + { "value": "224271", "label": "Dallas Institute of Funeral Service" }, + { "value": "437732", "label": "Dallas Nursing Institute" }, + { "value": "224305", "label": "Dallas Theological Seminary" }, + { "value": "139463", "label": "Dalton State College" }, + { "value": "182661", "label": "Daniel Webster College" }, + { "value": "144564", "label": "Danville Area Community College" }, + { "value": "231882", "label": "Danville Community College" }, + { + "value": "455178", + "label": "Daoist Traditions College of Chinese Medical Arts" + }, + { "value": "182670", "label": "Dartmouth College" }, + { "value": "138691", "label": "Darton State College" }, + { "value": "169479", "label": "Davenport University" }, + { "value": "198385", "label": "Davidson College" }, + { "value": "198376", "label": "Davidson County Community College" }, + { "value": "237358", "label": "Davis & Elkins College" }, + { "value": "194569", "label": "Davis College-Johnson City" }, + { "value": "202435", "label": "Davis College-Toledo" }, + { "value": "180151", "label": "Dawson Community College" }, + { "value": "447476", "label": "Daymar College-Bellevue" }, + { "value": "363439", "label": "Daymar College-Bowling Green" }, + { "value": "205568", "label": "Daymar College-Chillicothe" }, + { "value": "205531", "label": "Daymar College-Jackson" }, + { "value": "205559", "label": "Daymar College-Lancaster" }, + { "value": "406219", "label": "Daymar College-Louisville-Louisville" }, + { "value": "449302", "label": "Daymar College-Madisonville" }, + { "value": "205522", "label": "Daymar College-New Boston" }, + { "value": "458557", "label": "Daymar College-Online" }, + { "value": "157465", "label": "Daymar College-Owensboro" }, + { "value": "156903", "label": "Daymar College-Paducah Main" }, + { "value": "368443", "label": "Daymar Institute-Clarksville" }, + { "value": "444255", "label": "Daymar Institute-Murfreesboro" }, + { "value": "220002", "label": "Daymar Institute-Nashville" }, + { "value": "447014", "label": "Daytona College" }, + { "value": "133386", "label": "Daytona State College" }, + { "value": "113333", "label": "De Anza College" }, + { "value": "165574", "label": "Dean College" }, + { "value": "211909", "label": "Dean Institute of Technology" }, + { "value": "202514", "label": "Defiance College" }, + { "value": "224350", "label": "Del Mar College" }, + { "value": "432524", "label": "Delaware College of Art and Design" }, + { "value": "211927", "label": "Delaware County Community College" }, + { "value": "130934", "label": "Delaware State University" }, + { + "value": "130891", + "label": "Delaware Technical Community College-Owens" + }, + { + "value": "130916", + "label": "Delaware Technical Community College-Stanton/Wilmington" + }, + { + "value": "130907", + "label": "Delaware Technical Community College-Terry" + }, + { "value": "211981", "label": "Delaware Valley University" }, + { "value": "158662", "label": "Delgado Community College" }, + { + "value": "113537", + "label": "Dell'Arte International School of Physical Theatre" + }, + { "value": "169521", "label": "Delta College" }, + { "value": "366270", "label": "Delta College of Arts & Technology" }, + { "value": "158723", "label": "Delta School of Business and Technology" }, + { "value": "175616", "label": "Delta State University" }, + { "value": "202523", "label": "Denison University" }, + { "value": "217989", "label": "Denmark Technical College" }, + { "value": "454856", "label": "Denver School of Nursing" }, + { "value": "126979", "label": "Denver Seminary" }, + { "value": "144740", "label": "DePaul University" }, + { "value": "150400", "label": "DePauw University" }, + { "value": "153214", "label": "Des Moines Area Community College" }, + { + "value": "154156", + "label": "Des Moines University-Osteopathic Medical Center" + }, + { "value": "210739", "label": "DeSales University" }, + { "value": "113582", "label": "Design Institute of San Diego" }, + { "value": "482413", "label": "DeVry College of New York" }, + { "value": "482422", "label": "DeVry University-Arizona" }, + { "value": "482431", "label": "DeVry University-California" }, + { "value": "482440", "label": "DeVry University-Colorado" }, + { "value": "482459", "label": "DeVry University-Florida" }, + { "value": "482468", "label": "DeVry University-Georgia" }, + { "value": "482477", "label": "DeVry University-Illinois" }, + { "value": "482486", "label": "DeVry University-Indiana" }, + { "value": "482501", "label": "DeVry University-Maryland" }, + { "value": "482510", "label": "DeVry University-Michigan" }, + { "value": "482529", "label": "DeVry University-Minnesota" }, + { "value": "482538", "label": "DeVry University-Missouri" }, + { "value": "482547", "label": "DeVry University-Nevada" }, + { "value": "482556", "label": "DeVry University-New Jersey" }, + { "value": "482565", "label": "DeVry University-North Carolina" }, + { "value": "482574", "label": "DeVry University-Ohio" }, + { "value": "482583", "label": "DeVry University-Oklahoma" }, + { "value": "482592", "label": "DeVry University-Oregon" }, + { "value": "482608", "label": "DeVry University-Pennsylvania" }, + { "value": "482617", "label": "DeVry University-Tennessee" }, + { "value": "482635", "label": "DeVry University-Texas" }, + { "value": "482644", "label": "DeVry University-Utah" }, + { "value": "482653", "label": "DeVry University-Virginia" }, + { "value": "482662", "label": "DeVry University-Washington" }, + { "value": "482671", "label": "DeVry University-Wisconsin" }, + { "value": "443562", "label": "Dewey University-Hato Rey-Hato Rey" }, + { "value": "113634", "label": "Diablo Valley College" }, + { "value": "212009", "label": "Dickinson College" }, + { "value": "200059", "label": "Dickinson State University" }, + { "value": "443410", "label": "DigiPen Institute of Technology" }, + { "value": "451060", "label": "Digital Media Arts College" }, + { "value": "158802", "label": "Dillard University" }, + { "value": "105297", "label": "Dine College" }, + { "value": "153241", "label": "Divine Word College" }, + { "value": "230171", "label": "Dixie State University" }, + { "value": "181020", "label": "Doane University-Arts & Sciences" }, + { + "value": "448284", + "label": "Doane University-Graduate and Professional Studies" + }, + { "value": "154998", "label": "Dodge City Community College" }, + { "value": "190761", "label": "Dominican College of Blauvelt" }, + { "value": "113704", "label": "Dominican School of Philosophy & Theology" }, + { "value": "148496", "label": "Dominican University" }, + { "value": "113698", "label": "Dominican University of California" }, + { "value": "122117", "label": "Dongguk University-Los Angeles" }, + { "value": "155007", "label": "Donnelly College" }, + { "value": "153250", "label": "Dordt College" }, + { "value": "212045", "label": "Douglas Education Center" }, + { "value": "190770", "label": "Dowling College" }, + { "value": "153269", "label": "Drake University" }, + { "value": "184348", "label": "Drew University" }, + { "value": "212054", "label": "Drexel University" }, + { "value": "177214", "label": "Drury University" }, + { "value": "212072", "label": "Du Bois Business College-Du Bois" }, + { "value": "439303", "label": "Du Bois Business College-Huntingdon" }, + { "value": "439312", "label": "Du Bois Business College-Oil City" }, + { "value": "198419", "label": "Duke University" }, + { "value": "173489", "label": "Duluth Business University" }, + { "value": "175227", "label": "Dunwoody College of Technology" }, + { "value": "212106", "label": "Duquesne University" }, + { "value": "198455", "label": "Durham Technical Community College" }, + { "value": "190840", "label": "Dutchess Community College" }, + { "value": "220057", "label": "Dyersburg State Community College" }, + { "value": "190716", "label": "D'Youville College" }, + { "value": "447421", "label": "Eagle Gate College-Layton" }, + { "value": "230366", "label": "Eagle Gate College-Murray" }, + { "value": "447625", "label": "Eagle Gate College-Salt Lake City" }, + { "value": "150455", "label": "Earlham College" }, + { "value": "106883", "label": "East Arkansas Community College" }, + { "value": "198464", "label": "East Carolina University" }, + { "value": "177250", "label": "East Central College" }, + { "value": "175643", "label": "East Central Community College" }, + { "value": "207041", "label": "East Central University" }, + { "value": "139621", "label": "East Georgia State College" }, + { "value": "113856", "label": "East Los Angeles College" }, + { "value": "175652", "label": "East Mississippi Community College" }, + { + "value": "413802", + "label": "East San Gabriel Valley Regional Occupational Program" + }, + { + "value": "212115", + "label": "East Stroudsburg University of Pennsylvania" + }, + { "value": "220075", "label": "East Tennessee State University" }, + { "value": "224527", "label": "East Texas Baptist University" }, + { "value": "439394", "label": "East West College of Natural Medicine" }, + { "value": "104577", "label": "Eastern Arizona College" }, + { "value": "129215", "label": "Eastern Connecticut State University" }, + { "value": "132693", "label": "Eastern Florida State College" }, + { "value": "203331", "label": "Eastern Gateway Community College" }, + { "value": "142179", "label": "Eastern Idaho Technical College" }, + { "value": "144892", "label": "Eastern Illinois University" }, + { "value": "448354", "label": "Eastern International College-Belleville" }, + { "value": "421878", "label": "Eastern International College-Jersey City" }, + { "value": "153311", "label": "Eastern Iowa Community College District" }, + { "value": "156620", "label": "Eastern Kentucky University" }, + { "value": "161138", "label": "Eastern Maine Community College" }, + { "value": "232043", "label": "Eastern Mennonite University" }, + { "value": "169798", "label": "Eastern Michigan University" }, + { "value": "165644", "label": "Eastern Nazarene College" }, + { "value": "187648", "label": "Eastern New Mexico University-Main Campus" }, + { + "value": "187666", + "label": "Eastern New Mexico University-Roswell Campus" + }, + { + "value": "383996", + "label": "Eastern New Mexico University-Ruidoso Campus" + }, + { "value": "207050", "label": "Eastern Oklahoma State College" }, + { "value": "208646", "label": "Eastern Oregon University" }, + { "value": "232052", "label": "Eastern Shore Community College" }, + { "value": "212133", "label": "Eastern University" }, + { "value": "441858", "label": "Eastern Virginia Career College" }, + { "value": "231970", "label": "Eastern Virginia Medical School" }, + { "value": "235097", "label": "Eastern Washington University" }, + { + "value": "438708", + "label": "Eastern West Virginia Community and Technical College" + }, + { "value": "240596", "label": "Eastern Wyoming College" }, + { "value": "224572", "label": "Eastfield College" }, + { "value": "144883", "label": "East-West University" }, + { "value": "183488", "label": "Eastwick College-Hackensack" }, + { "value": "184959", "label": "Eastwick College-Ramsey" }, + { "value": "446233", "label": "Ecclesia College" }, + { "value": "133492", "label": "Eckerd College" }, + { "value": "460215", "label": "Ecotech Institute" }, + { "value": "248934", "label": "ECPI University" }, + { "value": "247162", "label": "Ecumenical Theological Seminary" }, + { "value": "177278", "label": "Eden Theological Seminary" }, + { "value": "198491", "label": "Edgecombe Community College" }, + { "value": "238661", "label": "Edgewood College" }, + { "value": "376321", "label": "EDIC College" }, + { "value": "212160", "label": "Edinboro University of Pennsylvania" }, + { "value": "202648", "label": "Edison State Community College" }, + { "value": "235103", "label": "Edmonds Community College" }, + { + "value": "243832", + "label": "EDP Univeristy of Puerto Rico Inc-San Juan" + }, + { + "value": "241836", + "label": "EDP University of Puerto Rico Inc-San Sebastian" + }, + { + "value": "442806", + "label": "Edward Via College of Osteopathic Medicine" + }, + { "value": "133526", "label": "Edward Waters College" }, + { "value": "112686", "label": "El Camino College-Compton Center" }, + { "value": "113980", "label": "El Camino Community College District" }, + { "value": "224615", "label": "El Centro College" }, + { "value": "224642", "label": "El Paso Community College" }, + { "value": "144944", "label": "Elgin Community College" }, + { "value": "198507", "label": "Elizabeth City State University" }, + { "value": "212197", "label": "Elizabethtown College" }, + { + "value": "480134", + "label": "Elizabethtown College School of Continuing and Professional Studies" + }, + { + "value": "156648", + "label": "Elizabethtown Community and Technical College" + }, + { "value": "153296", "label": "Ellsworth Community College" }, + { "value": "144962", "label": "Elmhurst College" }, + { "value": "190974", "label": "Elmira Business Institute" }, + { "value": "190983", "label": "Elmira College" }, + { "value": "198516", "label": "Elon University" }, + { + "value": "133553", + "label": "Embry-Riddle Aeronautical University-Daytona Beach" + }, + { + "value": "104586", + "label": "Embry-Riddle Aeronautical University-Prescott" + }, + { + "value": "426314", + "label": "Embry-Riddle Aeronautical University-Worldwide" + }, + { "value": "165662", "label": "Emerson College" }, + { "value": "220136", "label": "Emmanuel Christian Seminary" }, + { "value": "165671", "label": "Emmanuel College-Boston" }, + { "value": "139630", "label": "Emmanuel College-Franklin Springs" }, + { "value": "153302", "label": "Emmaus Bible College" }, + { "value": "232025", "label": "Emory & Henry College" }, + { "value": "139658", "label": "Emory University" }, + { + "value": "114114", + "label": "Emperor's College of Traditional Oriental Medicine" + }, + { "value": "114123", "label": "Empire College" }, + { "value": "155025", "label": "Emporia State University" }, + { "value": "165699", "label": "Endicott College" }, + { "value": "101143", "label": "Enterprise State Community College" }, + { "value": "124487", "label": "Epic Bible College" }, + { "value": "165705", "label": "Episcopal Divinity School" }, + { + "value": "224712", + "label": "Episcopal Theological Seminary of the Southwest" + }, + { "value": "191083", "label": "Erie Community College" }, + { "value": "212434", "label": "Erie Institute of Technology Inc" }, + { "value": "409254", "label": "Erikson Institute" }, + { "value": "217998", "label": "Erskine College" }, + { "value": "241951", "label": "Escuela de Artes Plasticas de Puerto Rico" }, + { "value": "184481", "label": "Essex County College" }, + { "value": "384333", "label": "Estrella Mountain Community College" }, + { "value": "200590", "label": "ETI Technical College" }, + { "value": "144971", "label": "Eureka College" }, + { "value": "177339", "label": "Evangel University" }, + { "value": "212443", "label": "Evangelical Theological Seminary" }, + { "value": "371982", "label": "Everest College-Anaheim" }, + { "value": "443854", "label": "Everest College-Arlington" }, + { "value": "366544", "label": "Everest College-Aurora" }, + { "value": "234739", "label": "Everest College-Bremerton" }, + { "value": "438647", "label": "Everest College-Chesapeake" }, + { "value": "372037", "label": "Everest College-City of Industry" }, + { "value": "126401", "label": "Everest College-Colorado Springs" }, + { "value": "442790", "label": "Everest College-Dallas" }, + { "value": "363590", "label": "Everest College-Everett" }, + { "value": "445197", "label": "Everest College-Fort Worth" }, + { "value": "460358", "label": "Everest College-Fort Worth South" }, + { "value": "182148", "label": "Everest College-Henderson" }, + { "value": "445470", "label": "Everest College-McLean" }, + { "value": "447236", "label": "Everest College-Mesa" }, + { "value": "232502", "label": "Everest College-Newport News" }, + { "value": "440299", "label": "Everest College-Ontario Metro" }, + { "value": "103644", "label": "Everest College-Phoenix" }, + { "value": "210359", "label": "Everest College-Portland" }, + { "value": "119359", "label": "Everest College-Reseda" }, + { "value": "230472", "label": "Everest College-Salt Lake City" }, + { "value": "119508", "label": "Everest College-San Bernardino" }, + { "value": "179070", "label": "Everest College-Springfield" }, + { "value": "444024", "label": "Everest College-Tacoma" }, + { "value": "127787", "label": "Everest College-Thornton" }, + { "value": "236993", "label": "Everest College-Vancouver" }, + { "value": "368805", "label": "Everest College-West Los Angeles" }, + { "value": "237604", "label": "Everest Institute-Cross Lanes" }, + { "value": "409670", "label": "Everest Institute-Kendall" }, + { "value": "443748", "label": "Everest Institute-Norcross" }, + { "value": "135957", "label": "Everest Institute-North Miami" }, + { "value": "212090", "label": "Everest Institute-Pittsburgh" }, + { "value": "194967", "label": "Everest Institute-Rochester" }, + { "value": "260293", "label": "Everest University-Brandon" }, + { "value": "438902", "label": "Everest University-Jacksonville" }, + { "value": "367909", "label": "Everest University-Lakeland" }, + { "value": "137810", "label": "Everest University-Largo" }, + { "value": "420006", "label": "Everest University-Melbourne" }, + { "value": "136288", "label": "Everest University-North Orlando" }, + { "value": "445434", "label": "Everest University-Orange Park" }, + { "value": "134149", "label": "Everest University-Pompano Beach" }, + { "value": "390701", "label": "Everest University-South Orlando" }, + { "value": "137801", "label": "Everest University-Tampa" }, + { "value": "235149", "label": "Everett Community College" }, + { "value": "385619", "label": "Everglades University" }, + { "value": "114266", "label": "Evergreen Valley College" }, + { "value": "196680", "label": "Excelsior College" }, + { "value": "447458", "label": "Expression College for Digital Arts" }, + { "value": "129242", "label": "Fairfield University" }, + { + "value": "184694", + "label": "Fairleigh Dickinson University-College at Florham" + }, + { + "value": "184603", + "label": "Fairleigh Dickinson University-Metropolitan Campus" + }, + { "value": "237367", "label": "Fairmont State University" }, + { + "value": "153320", + "label": "Faith Baptist Bible College and Theological Seminary" + }, + { "value": "443049", "label": "Faith Evangelical College & Seminary" }, + { "value": "212452", "label": "Faith Theological Seminary" }, + { "value": "443058", "label": "Family of Faith College" }, + { "value": "196042", "label": "Farmingdale State College" }, + { + "value": "114354", + "label": "Fashion Institute of Design & Merchandising-Los Angeles" + }, + { + "value": "248846", + "label": "Fashion Institute of Design & Merchandising-San Diego" + }, + { + "value": "114390", + "label": "Fashion Institute of Design & Merchandising-San Francisco" + }, + { "value": "191126", "label": "Fashion Institute of Technology" }, + { "value": "101189", "label": "Faulkner University" }, + { "value": "198543", "label": "Fayetteville State University" }, + { "value": "198534", "label": "Fayetteville Technical Community College" }, + { "value": "114433", "label": "Feather River Community College District" }, + { "value": "184612", "label": "Felician University" }, + { "value": "169910", "label": "Ferris State University" }, + { "value": "232089", "label": "Ferrum College" }, + { "value": "114549", "label": "Fielding Graduate University" }, + { "value": "436599", "label": "FINE Mortuary College" }, + { "value": "191199", "label": "Finger Lakes Community College" }, + { "value": "475422", "label": "Finger Lakes Health College of Nursing" }, + { "value": "172440", "label": "Finlandia University" }, + { "value": "165802", "label": "Fisher College" }, + { "value": "220181", "label": "Fisk University" }, + { "value": "165820", "label": "Fitchburg State University" }, + { "value": "114585", "label": "Five Branches University" }, + { "value": "191205", "label": "Five Towns College" }, + { "value": "133711", "label": "Flagler College-St Augustine" }, + { "value": "444990", "label": "Flagler College-Tallahassee" }, + { "value": "180197", "label": "Flathead Valley Community College" }, + { "value": "160481", "label": "Fletcher Technical Community College" }, + { "value": "155052", "label": "Flint Hills Technical College" }, + { "value": "218025", "label": "Florence-Darlington Technical College" }, + { + "value": "133650", + "label": "Florida Agricultural and Mechanical University" + }, + { "value": "133669", "label": "Florida Atlantic University" }, + { "value": "133997", "label": "Florida Career College-Miami" }, + { "value": "434715", "label": "Florida Coastal School of Law" }, + { "value": "133809", "label": "Florida College" }, + { "value": "434441", "label": "Florida College of Integrative Medicine" }, + { + "value": "438294", + "label": "Florida College of Natural Health-Bradenton" + }, + { + "value": "438285", + "label": "Florida College of Natural Health-Maitland" + }, + { "value": "420103", "label": "Florida College of Natural Health-Miami" }, + { + "value": "387925", + "label": "Florida College of Natural Health-Pompano Beach" + }, + { "value": "135160", "label": "Florida Gateway College" }, + { "value": "433660", "label": "Florida Gulf Coast University" }, + { "value": "133881", "label": "Florida Institute of Technology" }, + { "value": "480569", "label": "Florida Institute of Technology-Online" }, + { "value": "133951", "label": "Florida International University" }, + { "value": "133960", "label": "Florida Keys Community College" }, + { "value": "133979", "label": "Florida Memorial University" }, + { "value": "408844", "label": "Florida National University-Main Campus" }, + { "value": "134079", "label": "Florida Southern College" }, + { "value": "133508", "label": "Florida SouthWestern State College" }, + { "value": "133702", "label": "Florida State College at Jacksonville" }, + { "value": "134097", "label": "Florida State University" }, + { "value": "134112", "label": "Florida Technical College" }, + { "value": "444219", "label": "Folsom Lake College" }, + { "value": "380368", "label": "Fond du Lac Tribal and Community College" }, + { "value": "177418", "label": "Fontbonne University" }, + { "value": "114716", "label": "Foothill College" }, + { "value": "191241", "label": "Fordham University" }, + { + "value": "177427", + "label": "Forest Institute of Professional Psychology" + }, + { "value": "218043", "label": "Forrest College" }, + { "value": "198552", "label": "Forsyth Technical Community College" }, + { "value": "155061", "label": "Fort Hays State University" }, + { "value": "127185", "label": "Fort Lewis College" }, + { "value": "180212", "label": "Fort Peck Community College" }, + { "value": "155098", "label": "Fort Scott Community College" }, + { "value": "139719", "label": "Fort Valley State University" }, + { "value": "439738", "label": "Fortis College-Baton Rouge" }, + { "value": "205179", "label": "Fortis College-Centerville" }, + { "value": "450067", "label": "Fortis College-Cincinnati" }, + { "value": "460020", "label": "Fortis College-Columbia" }, + { "value": "450058", "label": "Fortis College-Columbus" }, + { "value": "480143", "label": "Fortis College-Cutler Bay" }, + { "value": "204307", "label": "Fortis College-Cuyahoga Falls" }, + { "value": "458681", "label": "Fortis College-Indianapolis" }, + { "value": "451909", "label": "Fortis College-Landover" }, + { "value": "447360", "label": "Fortis College-Largo" }, + { "value": "371052", "label": "Fortis College-Mobile" }, + { "value": "455488", "label": "Fortis College-Montgomery-Montgomery" }, + { "value": "233329", "label": "Fortis College-Norfolk" }, + { "value": "439792", "label": "Fortis College-Orange Park" }, + { "value": "456180", "label": "Fortis College-Phoenix" }, + { "value": "201399", "label": "Fortis College-Ravenna" }, + { "value": "382957", "label": "Fortis College-Richmond" }, + { "value": "456454", "label": "Fortis College-Salt Lake City" }, + { "value": "372921", "label": "Fortis College-Smyrna" }, + { "value": "132806", "label": "Fortis College-Winter Park" }, + { "value": "442745", "label": "Fortis Institute" }, + { "value": "455628", "label": "Fortis Institute-Birmingham" }, + { "value": "418870", "label": "Fortis Institute-Cookeville" }, + { "value": "216418", "label": "Fortis Institute-Erie" }, + { "value": "443438", "label": "Fortis Institute-Fort Lauderdale" }, + { "value": "249609", "label": "Fortis Institute-Forty Fort" }, + { "value": "445753", "label": "Fortis Institute-Miami" }, + { "value": "452124", "label": "Fortis Institute-Nashville" }, + { "value": "455479", "label": "Fortis Institute-Pensacola" }, + { "value": "445744", "label": "Fortis Institute-Port Saint Lucie" }, + { "value": "385503", "label": "Fortis Institute-Scranton" }, + { "value": "221795", "label": "Fountainhead College of Technology" }, + { "value": "415774", "label": "Four-D College" }, + { "value": "145239", "label": "Fox College" }, + { "value": "238722", "label": "Fox Valley Technical College" }, + { "value": "165866", "label": "Framingham State University" }, + { "value": "218061", "label": "Francis Marion University" }, + { "value": "114734", "label": "Franciscan School of Theology" }, + { "value": "205957", "label": "Franciscan University of Steubenville" }, + { "value": "104665", "label": "Frank Lloyd Wright School of Architecture" }, + { "value": "224891", "label": "Frank Phillips College" }, + { "value": "212577", "label": "Franklin and Marshall College" }, + { "value": "150604", "label": "Franklin College" }, + { "value": "182795", "label": "Franklin Pierce University" }, + { "value": "202806", "label": "Franklin University" }, + { "value": "441982", "label": "Franklin W Olin College of Engineering" }, + { "value": "162557", "label": "Frederick Community College" }, + { "value": "220215", "label": "Freed-Hardeman University" }, + { "value": "372073", "label": "Fremont College" }, + { "value": "114789", "label": "Fresno City College" }, + { "value": "114813", "label": "Fresno Pacific University" }, + { "value": "155089", "label": "Friends University" }, + { "value": "127200", "label": "Front Range Community College" }, + { "value": "403469", "label": "Frontier Community College" }, + { "value": "156727", "label": "Frontier Nursing University" }, + { "value": "162584", "label": "Frostburg State University" }, + { "value": "134237", "label": "Full Sail University" }, + { "value": "114840", "label": "Fuller Theological Seminary in California" }, + { "value": "114859", "label": "Fullerton College" }, + { "value": "191302", "label": "Fulton-Montgomery Community College" }, + { "value": "218070", "label": "Furman University" }, + { "value": "481030", "label": "Future Generations Graduate School" }, + { "value": "101240", "label": "Gadsden State Community College" }, + { "value": "452948", "label": "Galen College of Nursing-Cincinnati" }, + { "value": "156471", "label": "Galen College of Nursing-Louisville" }, + { "value": "406033", "label": "Galen College of Nursing-San Antonio" }, + { "value": "406024", "label": "Galen College of Nursing-Tampa Bay" }, + { "value": "131450", "label": "Gallaudet University" }, + { "value": "205513", "label": "Gallipolis Career College" }, + { "value": "224961", "label": "Galveston College" }, + { "value": "212601", "label": "Gannon University" }, + { "value": "155104", "label": "Garden City Community College" }, + { "value": "198561", "label": "Gardner-Webb University" }, + { "value": "162609", "label": "Garrett College" }, + { "value": "145275", "label": "Garrett-Evangelical Theological Seminary" }, + { "value": "198570", "label": "Gaston College" }, + { "value": "157438", "label": "Gateway Community and Technical College" }, + { "value": "130396", "label": "Gateway Community College-New Haven" }, + { "value": "105145", "label": "GateWay Community College-Phoenix" }, + { "value": "238759", "label": "Gateway Technical College" }, + { "value": "114938", "label": "Gavilan College" }, + { "value": "191339", "label": "Genesee Community College" }, + { "value": "212656", "label": "Geneva College" }, + { + "value": "101286", + "label": "George C Wallace State Community College-Dothan" + }, + { + "value": "101295", + "label": "George C Wallace State Community College-Hanceville" + }, + { + "value": "101301", + "label": "George C Wallace State Community College-Selma" + }, + { "value": "208822", "label": "George Fox University" }, + { "value": "232186", "label": "George Mason University" }, + { "value": "131469", "label": "George Washington University" }, + { "value": "156745", "label": "Georgetown College" }, + { "value": "131496", "label": "Georgetown University" }, + { "value": "461236", "label": "Georgia Christian University" }, + { "value": "139861", "label": "Georgia College and State University" }, + { "value": "447689", "label": "Georgia Gwinnett College" }, + { "value": "139700", "label": "Georgia Highlands College" }, + { + "value": "139755", + "label": "Georgia Institute of Technology-Main Campus" + }, + { "value": "485111", "label": "Georgia Military College-Milledgeville" }, + { "value": "139384", "label": "Georgia Northwestern Technical College" }, + { "value": "244437", "label": "Georgia Perimeter College" }, + { "value": "244446", "label": "Georgia Piedmont Technical College" }, + { "value": "139931", "label": "Georgia Southern University" }, + { "value": "139764", "label": "Georgia Southwestern State University" }, + { "value": "139940", "label": "Georgia State University" }, + { "value": "184773", "label": "Georgian Court University" }, + { "value": "232195", "label": "Germanna Community College" }, + { "value": "212674", "label": "Gettysburg College" }, + { "value": "169974", "label": "Glen Oaks Community College" }, + { "value": "104708", "label": "Glendale Community College-Glendale" }, + { "value": "115001", "label": "Glendale Community College-Glendale" }, + { "value": "237385", "label": "Glenville State College" }, + { "value": "455390", "label": "Global Health College" }, + { "value": "188465", "label": "Globe Institute of Technology" }, + { "value": "466514", "label": "Globe University-Appleton" }, + { "value": "456816", "label": "Globe University-Eau Claire" }, + { "value": "458751", "label": "Globe University–Green Bay" }, + { "value": "458991", "label": "Globe University-La Crosse" }, + { "value": "458733", "label": "Globe University-Madison East" }, + { "value": "458760", "label": "Globe University–Madison West" }, + { "value": "456834", "label": "Globe University-Minneapolis" }, + { "value": "456807", "label": "Globe University-Sioux Falls" }, + { "value": "458779", "label": "Globe University–Wausau" }, + { "value": "173629", "label": "Globe University-Woodbury" }, + { "value": "230889", "label": "Goddard College" }, + { "value": "202903", "label": "Gods Bible School and College" }, + { "value": "169992", "label": "Gogebic Community College" }, + { "value": "115083", "label": "Golden Gate University-San Francisco" }, + { "value": "115126", "label": "Golden West College" }, + { "value": "130989", "label": "Goldey-Beacom College" }, + { "value": "430157", "label": "Golf Academy of America-Altamonte Springs" }, + { "value": "122366", "label": "Golf Academy of America-Carlsbad" }, + { "value": "476337", "label": "Golf Academy of America-Farmers Branch" }, + { "value": "434690", "label": "Golf Academy of America-Myrtle Beach" }, + { "value": "430166", "label": "Golf Academy of America-Phoenix" }, + { "value": "235316", "label": "Gonzaga University" }, + { + "value": "202912", + "label": "Good Samaritan College of Nursing and Health Science" + }, + { "value": "132523", "label": "Gooding Institute of Nurse Anesthesia" }, + { "value": "129154", "label": "Goodwin College" }, + { "value": "165936", "label": "Gordon College" }, + { "value": "139968", "label": "Gordon State College" }, + { "value": "165945", "label": "Gordon-Conwell Theological Seminary" }, + { "value": "150668", "label": "Goshen College" }, + { "value": "162654", "label": "Goucher College" }, + { "value": "145336", "label": "Governors State University" }, + { "value": "170000", "label": "Grace Bible College" }, + { "value": "150677", "label": "Grace College and Theological Seminary" }, + { "value": "461528", "label": "Grace College of Divinity" }, + { "value": "481058", "label": "Grace Mission University" }, + { "value": "481401", "label": "Grace School of Theology" }, + { "value": "181093", "label": "Grace University" }, + { "value": "153366", "label": "Graceland University-Lamoni" }, + { "value": "483285", "label": "Graduate School USA" }, + { "value": "115214", "label": "Graduate Theological Union" }, + { "value": "159009", "label": "Grambling State University" }, + { "value": "104717", "label": "Grand Canyon University" }, + { "value": "170055", "label": "Grand Rapids Community College" }, + { "value": "170082", "label": "Grand Valley State University" }, + { "value": "153375", "label": "Grand View University" }, + { "value": "183257", "label": "Granite State College" }, + { "value": "442569", "label": "Grantham University" }, + { "value": "212771", "label": "Gratz College" }, + { "value": "235334", "label": "Grays Harbor College" }, + { "value": "225070", "label": "Grayson College" }, + { "value": "182306", "label": "Great Basin College" }, + { "value": "183150", "label": "Great Bay Community College" }, + { + "value": "180249", + "label": "Great Falls College Montana State University" + }, + { "value": "170091", "label": "Great Lakes Christian College" }, + { "value": "213181", "label": "Great Lakes Institute of Technology" }, + { "value": "230898", "label": "Green Mountain College" }, + { "value": "235343", "label": "Green River College" }, + { "value": "165981", "label": "Greenfield Community College" }, + { "value": "198598", "label": "Greensboro College" }, + { "value": "145372", "label": "Greenville College" }, + { "value": "218113", "label": "Greenville Technical College" }, + { "value": "153384", "label": "Grinnell College" }, + { "value": "115296", "label": "Grossmont College" }, + { "value": "212805", "label": "Grove City College" }, + { "value": "240745", "label": "Guam Community College" }, + { "value": "198613", "label": "Guilford College" }, + { "value": "198622", "label": "Guilford Technical Community College" }, + { "value": "134343", "label": "Gulf Coast State College" }, + { "value": "139995", "label": "Gupton Jones College of Funeral Service" }, + { "value": "173647", "label": "Gustavus Adolphus College" }, + { "value": "140003", "label": "Gwinnett College-Lilburn" }, + { "value": "140012", "label": "Gwinnett Technical College" }, + { "value": "212832", "label": "Gwynedd Mercy University" }, + { + "value": "102313", + "label": "H Councill Trenholm State Community College" + }, + { "value": "162690", "label": "Hagerstown Community College" }, + { "value": "198640", "label": "Halifax Community College" }, + { "value": "225201", "label": "Hallmark University" }, + { "value": "191515", "label": "Hamilton College" }, + { "value": "153427", "label": "Hamilton Technical College" }, + { "value": "173665", "label": "Hamline University" }, + { "value": "232256", "label": "Hampden-Sydney College" }, + { "value": "166018", "label": "Hampshire College" }, + { "value": "232265", "label": "Hampton University" }, + { "value": "177542", "label": "Hannibal-LaGrange University" }, + { "value": "150756", "label": "Hanover College" }, + { "value": "212869", "label": "Harcum College" }, + { "value": "107044", "label": "Harding University" }, + { "value": "225247", "label": "Hardin-Simmons University" }, + { "value": "162706", "label": "Harford Community College" }, + { "value": "145460", "label": "Harrington College of Design" }, + { + "value": "212878", + "label": "Harrisburg Area Community College-Harrisburg" + }, + { + "value": "446640", + "label": "Harrisburg University of Science and Technology" + }, + { "value": "458432", "label": "Harrison College-Grove City" }, + { "value": "151166", "label": "Harrison College-Indianapolis" }, + { "value": "468398", "label": "Harrison College-Morrisville" }, + { "value": "177551", "label": "Harris-Stowe State University" }, + { "value": "129491", "label": "Hartford Seminary" }, + { "value": "115393", "label": "Hartnell College" }, + { "value": "191533", "label": "Hartwick College" }, + { "value": "166027", "label": "Harvard University" }, + { "value": "115409", "label": "Harvey Mudd College" }, + { "value": "155140", "label": "Haskell Indian Nations University" }, + { "value": "181127", "label": "Hastings College" }, + { "value": "212911", "label": "Haverford College" }, + { "value": "383190", "label": "Hawaii Community College" }, + { "value": "141644", "label": "Hawaii Pacific University" }, + { "value": "153445", "label": "Hawkeye Community College" }, + { "value": "198668", "label": "Haywood Community College" }, + { "value": "156790", "label": "Hazard Community and Technical College" }, + { + "value": "173683", + "label": "Hazelden Betty Ford Graduate School of Addiction Studies" + }, + { "value": "115533", "label": "Heald College-Concord" }, + { "value": "115472", "label": "Heald College-Fresno" }, + { "value": "371779", "label": "Heald College-Hayward" }, + { "value": "141468", "label": "Heald College-Honolulu" }, + { "value": "459930", "label": "Heald College-Modesto" }, + { "value": "430148", "label": "Heald College-Portland" }, + { "value": "115454", "label": "Heald College-Rancho Cordova" }, + { "value": "363387", "label": "Heald College-Roseville" }, + { "value": "409874", "label": "Heald College-Salinas" }, + { "value": "115515", "label": "Heald College-San Francisco" }, + { "value": "115490", "label": "Heald College-San Jose" }, + { "value": "371760", "label": "Heald College-Stockton" }, + { "value": "384342", "label": "Heartland Community College" }, + { "value": "166045", "label": "Hebrew College" }, + { "value": "145497", "label": "Hebrew Theological College" }, + { + "value": "203067", + "label": "Hebrew Union College-Jewish Institute of Religion" + }, + { "value": "203085", "label": "Heidelberg University" }, + { "value": "180276", "label": "Helena College University of Montana" }, + { "value": "191597", "label": "Helene Fuld College of Nursing" }, + { + "value": "166054", + "label": "Hellenic College-Holy Cross Greek Orthodox School of Theology" + }, + { "value": "156851", "label": "Henderson Community College" }, + { "value": "107071", "label": "Henderson State University" }, + { "value": "107080", "label": "Hendrix College" }, + { "value": "173708", "label": "Hennepin Technical College" }, + { "value": "170240", "label": "Henry Ford College" }, + { "value": "198677", "label": "Heritage Bible College" }, + { "value": "101453", "label": "Heritage Christian University" }, + { "value": "262509", "label": "Heritage College-Denver" }, + { "value": "445814", "label": "Heritage College-Kansas City" }, + { "value": "410070", "label": "Heritage College-Oklahoma City" }, + { "value": "456320", "label": "Heritage College-Wichita" }, + { "value": "135124", "label": "Heritage Institute-Ft Myers" }, + { "value": "372772", "label": "Heritage Institute-Jacksonville" }, + { "value": "235422", "label": "Heritage University" }, + { "value": "191612", "label": "Herkimer County Community College" }, + { "value": "140340", "label": "Herzing University-Atlanta" }, + { "value": "101365", "label": "Herzing University-Birmingham" }, + { "value": "459851", "label": "Herzing University-Brookfield" }, + { "value": "433536", "label": "Herzing University-Kenner" }, + { "value": "459842", "label": "Herzing University-Kenosha" }, + { "value": "240392", "label": "Herzing University-Madison" }, + { "value": "174154", "label": "Herzing University-Minneapolis" }, + { "value": "457022", "label": "Herzing University-Toledo" }, + { "value": "386472", "label": "Herzing University-Winter Park" }, + { "value": "155177", "label": "Hesston College" }, + { "value": "173735", "label": "Hibbing Community College" }, + { "value": "177579", "label": "Hickey College" }, + { "value": "198695", "label": "High Point University" }, + { "value": "145521", "label": "Highland Community College-Freeport" }, + { "value": "155186", "label": "Highland Community College-Highland" }, + { "value": "180081", "label": "Highlands College of Montana Tech" }, + { "value": "235431", "label": "Highline College" }, + { "value": "191621", "label": "Hilbert College" }, + { "value": "225371", "label": "Hill College" }, + { "value": "134495", "label": "Hillsborough Community College" }, + { "value": "170286", "label": "Hillsdale College" }, + { "value": "207157", "label": "Hillsdale Free Will Baptist College" }, + { "value": "175786", "label": "Hinds Community College" }, + { "value": "203128", "label": "Hiram College" }, + { "value": "220312", "label": "Hiwassee College" }, + { "value": "191630", "label": "Hobart William Smith Colleges" }, + { "value": "134510", "label": "Hobe Sound Bible College" }, + { "value": "203155", "label": "Hocking College" }, + { "value": "367884", "label": "Hodges University" }, + { "value": "191649", "label": "Hofstra University" }, + { "value": "232308", "label": "Hollins University" }, + { "value": "175810", "label": "Holmes Community College" }, + { "value": "129534", "label": "Holy Apostles College and Seminary" }, + { "value": "150774", "label": "Holy Cross College" }, + { "value": "212984", "label": "Holy Family University" }, + { "value": "115728", "label": "Holy Names University" }, + { "value": "166133", "label": "Holyoke Community College" }, + { "value": "203386", "label": "Hondros College" }, + { "value": "141680", "label": "Honolulu Community College" }, + { "value": "162760", "label": "Hood College" }, + { "value": "443076", "label": "Hood Theological Seminary" }, + { "value": "170301", "label": "Hope College" }, + { "value": "120537", "label": "Hope International University" }, + { "value": "156860", "label": "Hopkinsville Community College" }, + { "value": "457226", "label": "Horizon University" }, + { "value": "218140", "label": "Horry-Georgetown Technical College" }, + { "value": "191676", "label": "Houghton College" }, + { "value": "129543", "label": "Housatonic Community College" }, + { "value": "225399", "label": "Houston Baptist University" }, + { "value": "225423", "label": "Houston Community College" }, + { "value": "246345", "label": "Houston Graduate School of Theology" }, + { "value": "225520", "label": "Howard College" }, + { "value": "162779", "label": "Howard Community College" }, + { "value": "225548", "label": "Howard Payne University" }, + { "value": "131520", "label": "Howard University" }, + { "value": "184995", "label": "Hudson County Community College" }, + { "value": "191719", "label": "Hudson Valley Community College" }, + { "value": "242112", "label": "Huertas College" }, + { "value": "164368", "label": "Hult International Business School" }, + { "value": "242121", "label": "Humacao Community College" }, + { "value": "115755", "label": "Humboldt State University" }, + { + "value": "115773", + "label": "Humphreys College-Stockton and Modesto Campuses" + }, + { "value": "101435", "label": "Huntingdon College" }, + { "value": "237437", "label": "Huntington Junior College" }, + { "value": "150941", "label": "Huntington University" }, + { "value": "449348", "label": "Huntsville Bible College" }, + { "value": "212993", "label": "Hussian College School of Art" }, + { "value": "161165", "label": "Husson University" }, + { "value": "225575", "label": "Huston-Tillotson University" }, + { "value": "155195", "label": "Hutchinson Community College" }, + { "value": "127839", "label": "IBMC College" }, + { "value": "372329", "label": "IBMC College" }, + { "value": "193405", "label": "Icahn School of Medicine at Mount Sinai" }, + { "value": "437662", "label": "ICDC College" }, + { "value": "242130", "label": "ICPR Junior College-Arecibo" }, + { "value": "243841", "label": "ICPR Junior College-General Institutional" }, + { "value": "460677", "label": "ICPR Junior College-Manati" }, + { "value": "242149", "label": "ICPR Junior College-Mayaguez" }, + { "value": "142276", "label": "Idaho State University" }, + { "value": "483780", "label": "IGlobal University" }, + { "value": "127273", "label": "Iliff School of Theology" }, + { "value": "434584", "label": "Ilisagvik College" }, + { "value": "145682", "label": "Illinois Central College" }, + { "value": "145691", "label": "Illinois College" }, + { "value": "145628", "label": "Illinois College of Optometry" }, + { "value": "145725", "label": "Illinois Institute of Technology" }, + { "value": "145813", "label": "Illinois State University" }, + { "value": "145831", "label": "Illinois Valley Community College" }, + { "value": "145646", "label": "Illinois Wesleyan University" }, + { "value": "213011", "label": "Immaculata University" }, + { "value": "115861", "label": "Imperial Valley College" }, + { "value": "155201", "label": "Independence Community College" }, + { "value": "465812", "label": "Independence University" }, + { "value": "153472", "label": "Indian Hills Community College" }, + { "value": "134608", "label": "Indian River State College" }, + { "value": "151290", "label": "Indiana Institute of Technology" }, + { "value": "151324", "label": "Indiana State University" }, + { + "value": "213020", + "label": "Indiana University of Pennsylvania-Main Campus" + }, + { "value": "151351", "label": "Indiana University-Bloomington" }, + { "value": "151388", "label": "Indiana University-East" }, + { "value": "151333", "label": "Indiana University-Kokomo" }, + { "value": "151360", "label": "Indiana University-Northwest" }, + { + "value": "151102", + "label": "Indiana University-Purdue University-Fort Wayne" + }, + { + "value": "151111", + "label": "Indiana University-Purdue University-Indianapolis" + }, + { "value": "151342", "label": "Indiana University-South Bend" }, + { "value": "151379", "label": "Indiana University-Southeast" }, + { "value": "151801", "label": "Indiana Wesleyan University" }, + { "value": "145886", "label": "Institute for Clinical Social Work" }, + { + "value": "462044", + "label": "Institute for Doctoral Studies in the Visual Arts" + }, + { "value": "445869", "label": "Institute for the Psychological Sciences" }, + { + "value": "187745", + "label": "Institute of American Indian and Alaska Native Culture" + }, + { + "value": "444699", + "label": "Institute of Clinical Acupuncture & Oriental Med" + }, + { "value": "191764", "label": "Institute of Design and Construction" }, + { "value": "454616", "label": "Institute of Production and Recording" }, + { + "value": "454838", + "label": "Institute of Taoist Education and Acupuncture" + }, + { "value": "431141", "label": "Institute of Technology Inc-Clovis" }, + { "value": "455804", "label": "Institute of World Politics" }, + { "value": "242422", "label": "Instituto de Banca y Comercio Inc" }, + { + "value": "242556", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Guayama" + }, + { + "value": "242042", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Manati" + }, + { + "value": "242565", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Ponce" + }, + { + "value": "242583", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de San Juan" + }, + { "value": "128179", "label": "Intellitec College-Colorado Springs" }, + { "value": "128188", "label": "Intellitec College-Grand Junction" }, + { + "value": "242626", + "label": "Inter American University of Puerto Rico-Aguadilla" + }, + { + "value": "242635", + "label": "Inter American University of Puerto Rico-Arecibo" + }, + { + "value": "242644", + "label": "Inter American University of Puerto Rico-Barranquitas" + }, + { + "value": "242705", + "label": "Inter American University of Puerto Rico-Bayamon" + }, + { + "value": "242680", + "label": "Inter American University of Puerto Rico-Fajardo" + }, + { + "value": "242699", + "label": "Inter American University of Puerto Rico-Guayama" + }, + { + "value": "242653", + "label": "Inter American University of Puerto Rico-Metro" + }, + { + "value": "242662", + "label": "Inter American University of Puerto Rico-Ponce" + }, + { + "value": "242617", + "label": "Inter American University of Puerto Rico-San German" + }, + { + "value": "242723", + "label": "Inter American University of Puerto Rico-School of Law" + }, + { + "value": "404222", + "label": "Inter American University of Puerto Rico-School of Optometry" + }, + { + "value": "138655", + "label": "Interactive College of Technology-Chamblee" + }, + { + "value": "442435", + "label": "Interactive College of Technology-Gainesville" + }, + { "value": "367361", "label": "Interactive College of Technology-Houston" }, + { "value": "443696", "label": "Interactive College of Technology-Houston" }, + { "value": "138664", "label": "Interactive College of Technology-Morrow" }, + { "value": "367103", "label": "Interactive College of Technology-Newport" }, + { + "value": "440776", + "label": "Interactive College of Technology-Pasadena" + }, + { "value": "366289", "label": "InterCoast Colleges-Orange" }, + { "value": "140146", "label": "Interdenominational Theological Center" }, + { "value": "235495", "label": "Interface College-Spokane" }, + { "value": "116226", "label": "Interior Designers Institute" }, + { + "value": "446817", + "label": "International Academy of Design and Technology-Nashville" + }, + { + "value": "450447", + "label": "International Academy of Design and Technology-Sacramento" + }, + { + "value": "445124", + "label": "International Academy of Design and Technology-Troy" + }, + { + "value": "436614", + "label": "International Baptist College and Seminary" + }, + { + "value": "225779", + "label": "International Business College-El Paso-El Paso" + }, + { + "value": "225788", + "label": "International Business College-El Paso-El Paso" + }, + { "value": "151458", "label": "International Business College-Fort Wayne" }, + { + "value": "151467", + "label": "International Business College-Indianapolis" + }, + { "value": "203289", "label": "International College of Broadcasting" }, + { + "value": "448691", + "label": "International Institute for Restorative Practices" + }, + { + "value": "454740", + "label": "International Professional School of Bodywork" + }, + { "value": "443128", "label": "International Technological University" }, + { "value": "173799", "label": "Inver Hills Community College" }, + { "value": "191931", "label": "Iona College" }, + { "value": "153524", "label": "Iowa Central Community College" }, + { "value": "153533", "label": "Iowa Lakes Community College" }, + { "value": "153603", "label": "Iowa State University" }, + { "value": "153621", "label": "Iowa Wesleyan University" }, + { "value": "153630", "label": "Iowa Western Community College" }, + { + "value": "441238", + "label": "Irell & Manella Graduate School of Biological Sciences at City of Hope" + }, + { "value": "116439", "label": "Irvine Valley College" }, + { "value": "191959", "label": "Island Drafting and Technical Institute" }, + { "value": "198710", "label": "Isothermal Community College" }, + { "value": "173805", "label": "Itasca Community College" }, + { "value": "175829", "label": "Itawamba Community College" }, + { "value": "191968", "label": "Ithaca College" }, + { "value": "159197", "label": "ITI Technical College" }, + { "value": "459611", "label": "ITT Technical Institute-Akron" }, + { "value": "434566", "label": "ITT Technical Institute-Albany" }, + { "value": "369084", "label": "ITT Technical Institute-Albuquerque" }, + { "value": "225849", "label": "ITT Technical Institute-Arlington" }, + { "value": "260974", "label": "ITT Technical Institute-Arlington Heights" }, + { "value": "434548", "label": "ITT Technical Institute-Arnold" }, + { "value": "450243", "label": "ITT Technical Institute-Atlanta" }, + { "value": "459675", "label": "ITT Technical Institute-Aurora" }, + { "value": "366678", "label": "ITT Technical Institute-Austin" }, + { "value": "450216", "label": "ITT Technical Institute-Baton Rouge" }, + { "value": "414568", "label": "ITT Technical Institute-Bessemer" }, + { "value": "142337", "label": "ITT Technical Institute-Boise" }, + { "value": "470852", "label": "ITT Technical Institute-Bradenton" }, + { "value": "470870", "label": "ITT Technical Institute-Brooklyn Center" }, + { "value": "442338", "label": "ITT Technical Institute-Canton" }, + { "value": "451936", "label": "ITT Technical Institute-Cary" }, + { "value": "441964", "label": "ITT Technical Institute-Chantilly" }, + { "value": "456445", "label": "ITT Technical Institute-Charlotte North" }, + { "value": "448442", "label": "ITT Technical Institute-Charlotte South" }, + { "value": "450261", "label": "ITT Technical Institute-Chattanooga" }, + { "value": "451954", "label": "ITT Technical Institute-Clive" }, + { "value": "448451", "label": "ITT Technical Institute-Clovis" }, + { "value": "450225", "label": "ITT Technical Institute-Columbia" }, + { "value": "451963", "label": "ITT Technical Institute-Columbus" }, + { "value": "456427", "label": "ITT Technical Institute-Concord" }, + { "value": "413884", "label": "ITT Technical Institute-Cordova" }, + { "value": "459639", "label": "ITT Technical Institute-Corona" }, + { "value": "459693", "label": "ITT Technical Institute-Culver City" }, + { "value": "203313", "label": "ITT Technical Institute-Dayton" }, + { "value": "459709", "label": "ITT Technical Institute-Dearborn" }, + { "value": "479619", "label": "ITT Technical Institute-Deerfield Beach" }, + { "value": "459657", "label": "ITT Technical Institute-DeSoto" }, + { "value": "479637", "label": "ITT Technical Institute-Douglasville" }, + { "value": "443526", "label": "ITT Technical Institute-Duluth" }, + { "value": "448460", "label": "ITT Technical Institute-Dunmore" }, + { "value": "462363", "label": "ITT Technical Institute-Durham" }, + { "value": "176637", "label": "ITT Technical Institute-Earth City" }, + { "value": "445081", "label": "ITT Technical Institute-Eden Prairie" }, + { "value": "414531", "label": "ITT Technical Institute-Everett" }, + { "value": "409069", "label": "ITT Technical Institute-Fort Lauderdale" }, + { "value": "456436", "label": "ITT Technical Institute-Fort Myers" }, + { "value": "151500", "label": "ITT Technical Institute-Fort Wayne" }, + { "value": "479567", "label": "ITT Technical Institute-Germantown" }, + { "value": "420404", "label": "ITT Technical Institute-Getzville" }, + { "value": "440165", "label": "ITT Technical Institute-Green Bay" }, + { "value": "238892", "label": "ITT Technical Institute-Greenfield" }, + { "value": "413866", "label": "ITT Technical Institute-Greenville" }, + { "value": "462372", "label": "ITT Technical Institute-Hanover" }, + { "value": "430351", "label": "ITT Technical Institute-Harrisburg" }, + { "value": "429599", "label": "ITT Technical Institute-Henderson" }, + { "value": "430263", "label": "ITT Technical Institute-Hialeah" }, + { "value": "451990", "label": "ITT Technical Institute-High Point" }, + { "value": "443535", "label": "ITT Technical Institute-Hilliard" }, + { "value": "366696", "label": "ITT Technical Institute-Houston North" }, + { "value": "225858", "label": "ITT Technical Institute-Houston West" }, + { "value": "456418", "label": "ITT Technical Institute-Huntington" }, + { "value": "151519", "label": "ITT Technical Institute-Indianapolis" }, + { "value": "479628", "label": "ITT Technical Institute-Indianapolis East" }, + { "value": "407063", "label": "ITT Technical Institute-Jacksonville" }, + { "value": "459648", "label": "ITT Technical Institute-Johnson City" }, + { "value": "446899", "label": "ITT Technical Institute-Kansas City" }, + { "value": "446905", "label": "ITT Technical Institute-Kennesaw" }, + { "value": "366650", "label": "ITT Technical Institute-Knoxville" }, + { "value": "372578", "label": "ITT Technical Institute-Lake Mary" }, + { "value": "459718", "label": "ITT Technical Institute-Las Vegas" }, + { "value": "437219", "label": "ITT Technical Institute-Lathrop" }, + { "value": "440642", "label": "ITT Technical Institute-Levittown" }, + { "value": "448488", "label": "ITT Technical Institute-Lexington" }, + { "value": "413839", "label": "ITT Technical Institute-Little Rock" }, + { "value": "434575", "label": "ITT Technical Institute-Liverpool" }, + { "value": "413857", "label": "ITT Technical Institute-Louisville" }, + { "value": "451945", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "451981", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "456393", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "479558", "label": "ITT Technical Institute-Marlton" }, + { "value": "448497", "label": "ITT Technical Institute-Maumee" }, + { "value": "459587", "label": "ITT Technical Institute-Merrillville" }, + { "value": "450252", "label": "ITT Technical Institute-Mobile" }, + { "value": "230384", "label": "ITT Technical Institute-Murray" }, + { "value": "470904", "label": "ITT Technical Institute-Myrtle Beach" }, + { "value": "151494", "label": "ITT Technical Institute-Nashville" }, + { "value": "116466", "label": "ITT Technical Institute-National City" }, + { "value": "251251", "label": "ITT Technical Institute-Newburgh" }, + { "value": "368601", "label": "ITT Technical Institute-Norfolk" }, + { "value": "459666", "label": "ITT Technical Institute-North Charleston" }, + { "value": "366580", "label": "ITT Technical Institute-Norwood-Norwood" }, + { "value": "430379", "label": "ITT Technical Institute-Norwood-Norwood" }, + { "value": "434557", "label": "ITT Technical Institute-Oak Brook" }, + { "value": "467058", "label": "ITT Technical Institute-Oakland" }, + { "value": "448503", "label": "ITT Technical Institute-Oklahoma City" }, + { "value": "407319", "label": "ITT Technical Institute-Omaha" }, + { "value": "116484", "label": "ITT Technical Institute-Orange" }, + { "value": "414586", "label": "ITT Technical Institute-Orland Park" }, + { "value": "470889", "label": "ITT Technical Institute-Orlando" }, + { "value": "479646", "label": "ITT Technical Institute-Overland Park" }, + { "value": "446914", "label": "ITT Technical Institute-Owings Mills" }, + { "value": "413848", "label": "ITT Technical Institute-Oxnard" }, + { "value": "479549", "label": "ITT Technical Institute-Philadelphia" }, + { "value": "451972", "label": "ITT Technical Institute-Phoenix" }, + { "value": "470861", "label": "ITT Technical Institute-Phoenix West" }, + { "value": "414841", "label": "ITT Technical Institute-Pittsburgh" }, + { "value": "442347", "label": "ITT Technical Institute-Plymouth Meeting" }, + { "value": "208965", "label": "ITT Technical Institute-Portland" }, + { "value": "108250", "label": "ITT Technical Institute-Rancho Cordova" }, + { "value": "434052", "label": "ITT Technical Institute-Richardson" }, + { "value": "437051", "label": "ITT Technical Institute-Richmond" }, + { "value": "437042", "label": "ITT Technical Institute-Saint Rose" }, + { "value": "459602", "label": "ITT Technical Institute-Salem-Salem" }, + { "value": "479600", "label": "ITT Technical Institute-Salem-Salem" }, + { "value": "377069", "label": "ITT Technical Institute-San Antonio" }, + { "value": "481623", "label": "ITT Technical Institute-San Antonio East" }, + { "value": "381909", "label": "ITT Technical Institute-San Bernardino" }, + { "value": "116475", "label": "ITT Technical Institute-San Dimas" }, + { "value": "235510", "label": "ITT Technical Institute-Seattle" }, + { "value": "450270", "label": "ITT Technical Institute-South Bend" }, + { "value": "479585", "label": "ITT Technical Institute-Southfield" }, + { "value": "235529", "label": "ITT Technical Institute-Spokane Valley" }, + { + "value": "441955", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "value": "456409", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "value": "479655", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { "value": "450207", "label": "ITT Technical Institute-St Petersburg" }, + { "value": "430388", "label": "ITT Technical Institute-Strongsville" }, + { "value": "448479", "label": "ITT Technical Institute-Swartz Creek" }, + { "value": "244011", "label": "ITT Technical Institute-Sylmar" }, + { "value": "459596", "label": "ITT Technical Institute-Tallahassee" }, + { "value": "134909", "label": "ITT Technical Institute-Tampa" }, + { "value": "430360", "label": "ITT Technical Institute-Tarentum" }, + { "value": "105172", "label": "ITT Technical Institute-Tempe" }, + { "value": "378406", "label": "ITT Technical Institute-Torrance" }, + { "value": "261472", "label": "ITT Technical Institute-Troy" }, + { "value": "105163", "label": "ITT Technical Institute-Tucson" }, + { "value": "448512", "label": "ITT Technical Institute-Tulsa" }, + { "value": "470898", "label": "ITT Technical Institute-Waco" }, + { + "value": "446923", + "label": "ITT Technical Institute-Warrensville Heights" + }, + { "value": "427663", "label": "ITT Technical Institute-Webster" }, + { "value": "479664", "label": "ITT Technical Institute-West Chester" }, + { "value": "459684", "label": "ITT Technical Institute-West Covina" }, + { "value": "479594", "label": "ITT Technical Institute-West Palm Beach" }, + { "value": "244154", "label": "ITT Technical Institute-Westminster" }, + { "value": "450234", "label": "ITT Technical Institute-Wichita" }, + { "value": "439136", "label": "ITT Technical Institute-Wilmington" }, + { "value": "170417", "label": "ITT Technical Institute-Wyoming" }, + { "value": "206631", "label": "ITT Technical Institute-Youngstown" }, + { "value": "150987", "label": "Ivy Tech Community College" }, + { + "value": "101462", + "label": "J F Drake State Community and Technical College" + }, + { "value": "101471", "label": "J F Ingram State Technical College" }, + { "value": "232414", "label": "J Sargeant Reynolds Community College" }, + { "value": "170444", "label": "Jackson College" }, + { "value": "220400", "label": "Jackson State Community College" }, + { "value": "175856", "label": "Jackson State University" }, + { "value": "225876", "label": "Jacksonville College-Main Campus" }, + { "value": "101480", "label": "Jacksonville State University" }, + { "value": "134945", "label": "Jacksonville University" }, + { "value": "203678", "label": "James A Rhodes State College" }, + { "value": "101161", "label": "James H Faulkner State Community College" }, + { "value": "232423", "label": "James Madison University" }, + { "value": "198729", "label": "James Sprunt Community College" }, + { "value": "192004", "label": "Jamestown Business College" }, + { "value": "191986", "label": "Jamestown Community College" }, + { "value": "225885", "label": "Jarvis Christian College" }, + { "value": "177676", "label": "Jefferson College" }, + { "value": "231837", "label": "Jefferson College of Health Sciences" }, + { "value": "156921", "label": "Jefferson Community and Technical College" }, + { "value": "192022", "label": "Jefferson Community College" }, + { "value": "101499", "label": "Jefferson Davis Community College" }, + { "value": "101505", "label": "Jefferson State Community College" }, + { "value": "455196", "label": "Jersey College" }, + { "value": "192040", "label": "Jewish Theological Seminary of America" }, + { "value": "419341", "label": "Jna Institute of Culinary Arts" }, + { "value": "220464", "label": "John A Gupton College" }, + { "value": "146205", "label": "John A Logan College" }, + { "value": "107141", "label": "John Brown University" }, + { "value": "101514", "label": "John C Calhoun State Community College" }, + { "value": "203368", "label": "John Carroll University" }, + { "value": "116712", "label": "John F. Kennedy University" }, + { "value": "462354", "label": "John Paul the Great Catholic University" }, + { "value": "232450", "label": "John Tyler Community College" }, + { "value": "146278", "label": "John Wood Community College" }, + { "value": "162928", "label": "Johns Hopkins University" }, + { "value": "445708", "label": "Johnson & Wales University-Charlotte" }, + { "value": "439288", "label": "Johnson & Wales University-Denver" }, + { "value": "414823", "label": "Johnson & Wales University-North Miami" }, + { "value": "460349", "label": "Johnson & Wales University-Online" }, + { "value": "217235", "label": "Johnson & Wales University-Providence" }, + { "value": "198756", "label": "Johnson C Smith University" }, + { "value": "213233", "label": "Johnson College" }, + { "value": "155210", "label": "Johnson County Community College" }, + { "value": "230913", "label": "Johnson State College" }, + { "value": "220473", "label": "Johnson University" }, + { "value": "132879", "label": "Johnson University Florida" }, + { "value": "198774", "label": "Johnston Community College" }, + { "value": "146296", "label": "Joliet Junior College" }, + { "value": "135063", "label": "Jones College-Jacksonville" }, + { "value": "175883", "label": "Jones County Junior College" }, + { "value": "444723", "label": "Jones International University" }, + { "value": "461281", "label": "Jose Maria Vargas University" }, + { "value": "101541", "label": "Judson College" }, + { "value": "146339", "label": "Judson University" }, + { + "value": "461139", + "label": "Jung Tao School of Classical Chinese Medicine" + }, + { "value": "213251", "label": "Juniata College" }, + { "value": "170532", "label": "Kalamazoo College" }, + { "value": "170541", "label": "Kalamazoo Valley Community College" }, + { "value": "146348", "label": "Kankakee Community College" }, + { "value": "177746", "label": "Kansas City Art Institute" }, + { "value": "155308", "label": "Kansas City College & Bible School" }, + { "value": "155292", "label": "Kansas City Kansas Community College" }, + { + "value": "179812", + "label": "Kansas City University of Medicine and Biosciences" + }, + { "value": "155399", "label": "Kansas State University" }, + { "value": "155414", "label": "Kansas Wesleyan University" }, + { "value": "141796", "label": "Kapiolani Community College" }, + { "value": "458715", "label": "Kaplan College-Jacksonville" }, + { "value": "445346", "label": "Kaplan College-Lubbock" }, + { "value": "480064", "label": "Kaplan University-Augusta Campus" }, + { "value": "260910", "label": "Kaplan University-Cedar Falls Campus" }, + { "value": "153418", "label": "Kaplan University-Cedar Rapids Campus" }, + { "value": "260901", "label": "Kaplan University-Davenport Campus" }, + { "value": "367024", "label": "Kaplan University-Des Moines Campus" }, + { "value": "162681", "label": "Kaplan University-Hagerstown Campus" }, + { "value": "181242", "label": "Kaplan University-Lincoln Campus" }, + { "value": "160940", "label": "Kaplan University-Maine Campus" }, + { "value": "153409", "label": "Kaplan University-Mason City Campus" }, + { "value": "181400", "label": "Kaplan University-Omaha Campus" }, + { "value": "146366", "label": "Kaskaskia College" }, + { "value": "141802", "label": "Kauai Community College" }, + { + "value": "225991", + "label": "KD College Conservatory of Film and Dramatic Arts" + }, + { "value": "185262", "label": "Kean University" }, + { "value": "440031", "label": "Keck Graduate Institute" }, + { "value": "183062", "label": "Keene State College" }, + { "value": "192165", "label": "Kehilath Yakov Rabbinical Seminary" }, + { "value": "135081", "label": "Keiser University-Ft Lauderdale" }, + { "value": "170550", "label": "Kellogg Community College" }, + { "value": "146393", "label": "Kendall College" }, + { "value": "161192", "label": "Kennebec Valley Community College" }, + { "value": "140164", "label": "Kennesaw State University" }, + { "value": "177816", "label": "Kenrick Glennon Seminary" }, + { "value": "203447", "label": "Kent State University at Ashtabula" }, + { "value": "203456", "label": "Kent State University at East Liverpool" }, + { "value": "203526", "label": "Kent State University at Geauga" }, + { "value": "203517", "label": "Kent State University at Kent" }, + { "value": "203492", "label": "Kent State University at Salem" }, + { "value": "203465", "label": "Kent State University at Stark" }, + { "value": "203474", "label": "Kent State University at Trumbull" }, + { "value": "203483", "label": "Kent State University at Tuscarawas" }, + { "value": "157100", "label": "Kentucky Christian University" }, + { "value": "157030", "label": "Kentucky Mountain Bible College" }, + { "value": "157058", "label": "Kentucky State University" }, + { "value": "157076", "label": "Kentucky Wesleyan College" }, + { "value": "203535", "label": "Kenyon College" }, + { "value": "203544", "label": "Kettering College" }, + { "value": "169983", "label": "Kettering University" }, + { "value": "192192", "label": "Keuka College" }, + { "value": "461315", "label": "Keweenaw Bay Ojibwa Community College" }, + { "value": "134422", "label": "Key College" }, + { "value": "213303", "label": "Keystone College" }, + { "value": "210483", "label": "Keystone Technical Institute" }, + { "value": "226019", "label": "Kilgore College" }, + { "value": "219055", "label": "Kilian Community College" }, + { "value": "220516", "label": "King University" }, + { "value": "382504", "label": "King's College-Charlotte" }, + { "value": "213321", "label": "King's College-Wilkes-Barre" }, + { "value": "153737", "label": "Kirkwood Community College" }, + { "value": "170587", "label": "Kirtland Community College" }, + { "value": "146418", "label": "Kishwaukee College" }, + { "value": "428392", "label": "Klamath Community College" }, + { "value": "260956", "label": "Knowledge Systems Institute" }, + { "value": "146427", "label": "Knox College" }, + { "value": "484288", "label": "Knox Theological Seminary" }, + { "value": "213349", "label": "Kutztown University of Pennsylvania" }, + { "value": "171881", "label": "Kuyper College" }, + { "value": "213358", "label": "La Roche College" }, + { "value": "213367", "label": "La Salle University" }, + { "value": "117627", "label": "La Sierra University" }, + { "value": "155450", "label": "Labette Community College" }, + { "value": "165264", "label": "Laboure College" }, + { + "value": "260372", + "label": "Lac Courte Oreilles Ojibwa Community College" + }, + { "value": "213376", "label": "Lackawanna College" }, + { "value": "213385", "label": "Lafayette College" }, + { "value": "140234", "label": "LaGrange College" }, + { "value": "117168", "label": "Laguna College of Art and Design" }, + { "value": "219143", "label": "Lake Area Technical Institute" }, + { "value": "203580", "label": "Lake Erie College" }, + { "value": "407629", "label": "Lake Erie College of Osteopathic Medicine" }, + { "value": "146481", "label": "Lake Forest College" }, + { "value": "146490", "label": "Lake Forest Graduate School of Management" }, + { "value": "146506", "label": "Lake Land College" }, + { "value": "170620", "label": "Lake Michigan College" }, + { "value": "200192", "label": "Lake Region State College" }, + { "value": "173461", "label": "Lake Superior College" }, + { "value": "170639", "label": "Lake Superior State University" }, + { "value": "117195", "label": "Lake Tahoe Community College" }, + { "value": "235699", "label": "Lake Washington Institute of Technology" }, + { "value": "238980", "label": "Lakeland College" }, + { "value": "203599", "label": "Lakeland Community College" }, + { "value": "183123", "label": "Lakes Region Community College" }, + { "value": "239008", "label": "Lakeshore Technical College" }, + { "value": "135188", "label": "Lake-Sumter State College" }, + { "value": "146533", "label": "Lakeview College of Nursing" }, + { "value": "127389", "label": "Lamar Community College" }, + { "value": "441760", "label": "Lamar Institute of Technology" }, + { "value": "226107", "label": "Lamar State College-Orange" }, + { "value": "226116", "label": "Lamar State College-Port Arthur" }, + { "value": "226091", "label": "Lamar University" }, + { "value": "213400", "label": "Lancaster Bible College" }, + { + "value": "418533", + "label": "Lancaster County Career and Technology Center" + }, + { "value": "213446", "label": "Lancaster Theological Seminary" }, + { "value": "218229", "label": "Lander University" }, + { "value": "247649", "label": "Landmark College" }, + { "value": "220598", "label": "Lane College" }, + { "value": "209038", "label": "Lane Community College" }, + { "value": "117247", "label": "Laney College" }, + { "value": "207209", "label": "Langston University" }, + { "value": "140243", "label": "Lanier Technical College" }, + { "value": "213473", "label": "Lansdale School of Business" }, + { "value": "170657", "label": "Lansing Community College" }, + { "value": "240620", "label": "Laramie County Community College" }, + { "value": "226134", "label": "Laredo Community College" }, + { "value": "366401", "label": "Las Positas College" }, + { "value": "166391", "label": "Lasell College" }, + { "value": "117274", "label": "Lassen Community College" }, + { "value": "230418", "label": "Latter-day Saints Business College" }, + { "value": "250027", "label": "Laurel Business Institute" }, + { "value": "408729", "label": "Laurel Technical Institute-MEADVILLE" }, + { "value": "215992", "label": "Laurel Technical Institute-Sharon" }, + { "value": "198747", "label": "Laurel University" }, + { + "value": "166407", + "label": "Lawrence Memorial Hospital School of Nursing" + }, + { "value": "170675", "label": "Lawrence Technological University" }, + { "value": "239017", "label": "Lawrence University" }, + { + "value": "101569", + "label": "Lawson State Community College-Birmingham Campus" + }, + { + "value": "443623", + "label": "Le Cordon Bleu College of Culinary Arts-Atlanta" + }, + { + "value": "364973", + "label": "Le Cordon Bleu College of Culinary Arts-Austin" + }, + { + "value": "452054", + "label": "Le Cordon Bleu College of Culinary Arts-Cambridge" + }, + { + "value": "144467", + "label": "Le Cordon Bleu College of Culinary Arts-Chicago" + }, + { + "value": "452063", + "label": "Le Cordon Bleu College of Culinary Arts-Dallas" + }, + { + "value": "445115", + "label": "Le Cordon Bleu College of Culinary Arts-Las Vegas" + }, + { + "value": "446835", + "label": "Le Cordon Bleu College of Culinary Arts-Miami" + }, + { + "value": "446844", + "label": "Le Cordon Bleu College of Culinary Arts-Minneapolis" + }, + { + "value": "442231", + "label": "Le Cordon Bleu College of Culinary Arts-Orlando" + }, + { + "value": "423980", + "label": "Le Cordon Bleu College of Culinary Arts-Pasadena" + }, + { + "value": "375841", + "label": "Le Cordon Bleu College of Culinary Arts-Portland" + }, + { + "value": "111009", + "label": "Le Cordon Bleu College of Culinary Arts-San Francisco" + }, + { + "value": "262332", + "label": "Le Cordon Bleu College of Culinary Arts-Scottsdale" + }, + { "value": "192323", "label": "Le Moyne College" }, + { "value": "220604", "label": "Le Moyne-Owen College" }, + { "value": "213507", "label": "Lebanon Valley College" }, + { "value": "456940", "label": "L'Ecole Culinaire-Memphis" }, + { "value": "445726", "label": "L'Ecole Culinaire-St Louis" }, + { "value": "226204", "label": "Lee College" }, + { "value": "220613", "label": "Lee University" }, + { "value": "413626", "label": "Leech Lake Tribal College" }, + { "value": "198808", "label": "Lees-McRae College" }, + { "value": "141811", "label": "Leeward Community College" }, + { "value": "213525", "label": "Lehigh Carbon Community College" }, + { "value": "213543", "label": "Lehigh University" }, + { "value": "198817", "label": "Lenoir Community College" }, + { "value": "198835", "label": "Lenoir-Rhyne University" }, + { + "value": "218265", + "label": "Lenoir-Rhyne University-Lutheran Theological Southern Seminary" + }, + { "value": "166452", "label": "Lesley University" }, + { "value": "226231", "label": "LeTourneau University" }, + { "value": "209056", "label": "Lewis & Clark College" }, + { "value": "146603", "label": "Lewis and Clark Community College" }, + { "value": "146612", "label": "Lewis University" }, + { "value": "142328", "label": "Lewis-Clark State College" }, + { "value": "157207", "label": "Lexington Theological Seminary" }, + { "value": "232557", "label": "Liberty University" }, + { "value": "117520", "label": "Life Chiropractic College West" }, + { "value": "117104", "label": "Life Pacific College" }, + { "value": "140252", "label": "Life University" }, + { "value": "192271", "label": "LIM College" }, + { "value": "218238", "label": "Limestone College" }, + { "value": "146667", "label": "Lincoln Christian University" }, + { "value": "146676", "label": "Lincoln College" }, + { + "value": "128683", + "label": "Lincoln College of New England-Southington" + }, + { "value": "163028", "label": "Lincoln College of Technology-Columbia" }, + { "value": "126951", "label": "Lincoln College of Technology-Denver" }, + { + "value": "151661", + "label": "Lincoln College of Technology-Indianapolis" + }, + { "value": "434159", "label": "Lincoln College of Technology-Marietta" }, + { + "value": "146700", + "label": "Lincoln College of Technology-Melrose Park" + }, + { "value": "221148", "label": "Lincoln College of Technology-Nashville" }, + { + "value": "136066", + "label": "Lincoln College of Technology-West Palm Beach" + }, + { "value": "146685", "label": "Lincoln Land Community College" }, + { "value": "220631", "label": "Lincoln Memorial University" }, + { "value": "213570", "label": "Lincoln Technical Institute-Allentown" }, + { + "value": "442037", + "label": "Lincoln Technical Institute-Northeast Philadelphia" + }, + { "value": "213589", "label": "Lincoln Technical Institute-Philadelphia" }, + { "value": "403478", "label": "Lincoln Trail College" }, + { "value": "177940", "label": "Lincoln University-Jefferson City" }, + { "value": "117557", "label": "Lincoln University-Oakland" }, + { "value": "177968", "label": "Lindenwood University" }, + { "value": "157216", "label": "Lindsey Wilson College" }, + { "value": "437325", "label": "Linfield College-Adult Degree Program" }, + { "value": "209065", "label": "Linfield College-McMinnville Campus" }, + { "value": "437316", "label": "Linfield College-School of Nursing" }, + { "value": "209074", "label": "Linn-Benton Community College" }, + { "value": "219976", "label": "Lipscomb University" }, + { "value": "180328", "label": "Little Big Horn College" }, + { "value": "434016", "label": "Little Priest Tribal College" }, + { "value": "192563", "label": "LIU Brentwood" }, + { "value": "192439", "label": "LIU Brooklyn" }, + { "value": "192554", "label": "LIU Hudson at Rockland" }, + { "value": "432357", "label": "LIU Hudson at Westchester" }, + { "value": "192448", "label": "LIU Post" }, + { "value": "450766", "label": "LIU Riverhead" }, + { "value": "421832", "label": "Living Arts College" }, + { "value": "198862", "label": "Livingstone College" }, + { "value": "213613", "label": "Lock Haven University" }, + { "value": "177986", "label": "Logan University" }, + { "value": "117636", "label": "Loma Linda University" }, + { "value": "227182", "label": "Lone Star College System" }, + { "value": "117645", "label": "Long Beach City College" }, + { "value": "192509", "label": "Long Island Business Institute" }, + { "value": "232566", "label": "Longwood University" }, + { "value": "166489", "label": "Longy School of Music of Bard College" }, + { "value": "203748", "label": "Lorain County Community College" }, + { "value": "153825", "label": "Loras College" }, + { "value": "232575", "label": "Lord Fairfax Community College" }, + { "value": "117788", "label": "Los Angeles City College" }, + { "value": "446385", "label": "Los Angeles College of Music" }, + { + "value": "117803", + "label": "Los Angeles County College of Nursing and Allied Health" + }, + { "value": "436429", "label": "Los Angeles Film School" }, + { "value": "117690", "label": "Los Angeles Harbor College" }, + { "value": "117867", "label": "Los Angeles Mission College" }, + { + "value": "368780", + "label": "Los Angeles ORT College-Los Angeles Campus" + }, + { "value": "381945", "label": "Los Angeles ORT College-Van Nuys Campus" }, + { "value": "117706", "label": "Los Angeles Pierce College" }, + { "value": "117715", "label": "Los Angeles Southwest College" }, + { "value": "117724", "label": "Los Angeles Trade Technical College" }, + { "value": "117733", "label": "Los Angeles Valley College" }, + { "value": "117894", "label": "Los Medanos College" }, + { "value": "198871", "label": "Louisburg College" }, + { "value": "159568", "label": "Louisiana College" }, + { "value": "449612", "label": "Louisiana Culinary Institute" }, + { "value": "483212", "label": "Louisiana Delta Community College" }, + { + "value": "159391", + "label": "Louisiana State University and Agricultural & Mechanical College" + }, + { + "value": "159373", + "label": "Louisiana State University Health Sciences Center-New Orleans" + }, + { + "value": "435000", + "label": "Louisiana State University Health Sciences Center-Shreveport" + }, + { "value": "159382", "label": "Louisiana State University-Alexandria" }, + { "value": "159407", "label": "Louisiana State University-Eunice" }, + { "value": "159416", "label": "Louisiana State University-Shreveport" }, + { "value": "159647", "label": "Louisiana Tech University" }, + { + "value": "157298", + "label": "Louisville Presbyterian Theological Seminary" + }, + { "value": "203757", "label": "Lourdes University" }, + { "value": "235750", "label": "Lower Columbia College" }, + { "value": "117946", "label": "Loyola Marymount University" }, + { "value": "146719", "label": "Loyola University Chicago" }, + { "value": "163046", "label": "Loyola University Maryland" }, + { "value": "159656", "label": "Loyola University New Orleans" }, + { "value": "226383", "label": "Lubbock Christian University" }, + { "value": "363633", "label": "Luna Community College" }, + { "value": "101602", "label": "Lurleen B Wallace Community College" }, + { "value": "153834", "label": "Luther College" }, + { "value": "135364", "label": "Luther Rice University & Seminary" }, + { "value": "173896", "label": "Luther Seminary" }, + { "value": "146728", "label": "Lutheran School of Theology at Chicago" }, + { + "value": "213631", + "label": "Lutheran Theological Seminary at Gettysburg" + }, + { + "value": "213640", + "label": "Lutheran Theological Seminary at Philadelphia" + }, + { "value": "213659", "label": "Luzerne County Community College" }, + { "value": "213668", "label": "Lycoming College" }, + { "value": "232609", "label": "Lynchburg College" }, + { "value": "230931", "label": "Lyndon State College" }, + { "value": "132657", "label": "Lynn University" }, + { "value": "106342", "label": "Lyon College" }, + { "value": "173902", "label": "Macalester College" }, + { "value": "146816", "label": "MacCormac College" }, + { "value": "192624", "label": "Machzikei Hadath Rabbinical College" }, + { "value": "146825", "label": "MacMurray College" }, + { "value": "170790", "label": "Macomb Community College" }, + { "value": "238263", "label": "Madison Area Technical College" }, + { "value": "364168", "label": "Madison Media Institute" }, + { + "value": "148399", + "label": "Madison Media Institute-Rockford Career College" + }, + { "value": "157304", "label": "Madisonville Community College" }, + { "value": "170806", "label": "Madonna University" }, + { "value": "153861", "label": "Maharishi University of Management" }, + { "value": "161509", "label": "Maine College of Art" }, + { "value": "161022", "label": "Maine College of Health Professions" }, + { "value": "161299", "label": "Maine Maritime Academy" }, + { "value": "203775", "label": "Malone University" }, + { "value": "451103", "label": "Management Resources College" }, + { "value": "129695", "label": "Manchester Community College-Manchester" }, + { "value": "183132", "label": "Manchester Community College-Manchester" }, + { "value": "151777", "label": "Manchester University" }, + { "value": "192688", "label": "Mandl School-The College of Allied Health" }, + { "value": "155487", "label": "Manhattan Area Technical College" }, + { "value": "155496", "label": "Manhattan Christian College" }, + { "value": "192703", "label": "Manhattan College" }, + { "value": "192712", "label": "Manhattan School of Music" }, + { "value": "192749", "label": "Manhattanville College" }, + { "value": "213774", "label": "Manor College" }, + { "value": "213783", "label": "Mansfield University of Pennsylvania" }, + { + "value": "446394", + "label": "Maple Springs Baptist Bible College and Seminary" + }, + { "value": "239071", "label": "Maranatha Baptist University" }, + { "value": "192785", "label": "Maria College of Albany" }, + { "value": "166601", "label": "Marian Court College" }, + { "value": "239080", "label": "Marian University-Fond Du Lac" }, + { "value": "151786", "label": "Marian University-Indianapolis" }, + { "value": "203845", "label": "Marietta College" }, + { "value": "101648", "label": "Marion Military Institute" }, + { "value": "203881", "label": "Marion Technical College" }, + { "value": "192819", "label": "Marist College" }, + { "value": "230940", "label": "Marlboro College" }, + { + "value": "440411", + "label": "Marlboro College Graduate & Professional Studies" + }, + { "value": "239105", "label": "Marquette University" }, + { "value": "198899", "label": "Mars Hill University" }, + { "value": "123943", "label": "Marshall B Ketchum University" }, + { "value": "237525", "label": "Marshall University" }, + { "value": "153922", "label": "Marshalltown Community College" }, + { "value": "198905", "label": "Martin Community College" }, + { "value": "173452", "label": "Martin Luther College" }, + { "value": "220701", "label": "Martin Methodist College" }, + { "value": "151810", "label": "Martin University" }, + { "value": "232672", "label": "Mary Baldwin College" }, + { "value": "170842", "label": "Marygrove College" }, + { "value": "163295", "label": "Maryland Institute College of Art" }, + { "value": "164085", "label": "Maryland University of Integrative Health" }, + { "value": "209108", "label": "Marylhurst University" }, + { "value": "118541", "label": "Marymount California University" }, + { "value": "192864", "label": "Marymount Manhattan College" }, + { "value": "232706", "label": "Marymount University" }, + { "value": "220710", "label": "Maryville College" }, + { "value": "178059", "label": "Maryville University of Saint Louis" }, + { "value": "213826", "label": "Marywood University" }, + { "value": "166647", "label": "Massachusetts Bay Community College" }, + { "value": "166674", "label": "Massachusetts College of Art and Design" }, + { "value": "167288", "label": "Massachusetts College of Liberal Arts" }, + { "value": "166683", "label": "Massachusetts Institute of Technology" }, + { "value": "166692", "label": "Massachusetts Maritime Academy" }, + { "value": "369002", "label": "Massachusetts School of Law" }, + { "value": "166823", "label": "Massasoit Community College" }, + { "value": "436702", "label": "Mattia College" }, + { "value": "454698", "label": "Mayfield College" }, + { "value": "198914", "label": "Mayland Community College" }, + { "value": "365426", "label": "Mayo Graduate School" }, + { "value": "173957", "label": "Mayo Medical School" }, + { "value": "173966", "label": "Mayo School of Health Sciences" }, + { "value": "157331", "label": "Maysville Community and Technical College" }, + { "value": "200226", "label": "Mayville State University" }, + { "value": "438212", "label": "McCann School of Business & Technology" }, + { "value": "146977", "label": "McCormick Theological Seminary" }, + { "value": "164270", "label": "McDaniel College" }, + { "value": "198923", "label": "McDowell Technical Community College" }, + { "value": "147004", "label": "McHenry County College" }, + { "value": "147013", "label": "McKendree University" }, + { "value": "226578", "label": "McLennan Community College" }, + { "value": "226587", "label": "McMurry University" }, + { "value": "367194", "label": "McNally Smith College of Music" }, + { "value": "159717", "label": "McNeese State University" }, + { "value": "155511", "label": "McPherson College" }, + { "value": "166656", "label": "MCPHS University" }, + { "value": "147031", "label": "Meadville Lombard Theological School" }, + { "value": "414461", "label": "Mech-Tech College" }, + { "value": "192925", "label": "Medaille College" }, + { "value": "239169", "label": "Medical College of Wisconsin" }, + { "value": "218335", "label": "Medical University of South Carolina" }, + { "value": "448415", "label": "MedTech College" }, + { "value": "456366", "label": "MedTech College-Ft Wayne Campus" }, + { "value": "456357", "label": "MedTech College-Greenwood Campus" }, + { "value": "456375", "label": "MedTech College-Lexington Campus" }, + { "value": "131742", "label": "Medtech Institute" }, + { "value": "444714", "label": "MedTech Institute-Atlanta Campus" }, + { "value": "220792", "label": "Meharry Medical College" }, + { "value": "192961", "label": "Memorial School of Nursing" }, + { "value": "220808", "label": "Memphis College of Art" }, + { "value": "220871", "label": "Memphis Theological Seminary" }, + { "value": "118684", "label": "Mendocino College" }, + { "value": "118693", "label": "Menlo College" }, + { "value": "118718", "label": "Merced College" }, + { "value": "185509", "label": "Mercer County Community College" }, + { "value": "140447", "label": "Mercer University" }, + { "value": "193016", "label": "Mercy College" }, + { "value": "153977", "label": "Mercy College of Health Sciences" }, + { "value": "203960", "label": "Mercy College of Ohio" }, + { "value": "213987", "label": "Mercyhurst University" }, + { "value": "480189", "label": "Mercyhurst University-North East Campus" }, + { "value": "198950", "label": "Meredith College" }, + { "value": "244279", "label": "Meridian College" }, + { "value": "175935", "label": "Meridian Community College" }, + { "value": "166850", "label": "Merrimack College" }, + { "value": "118772", "label": "Merritt College" }, + { "value": "105154", "label": "Mesa Community College" }, + { "value": "173993", "label": "Mesabi Range College" }, + { "value": "188261", "label": "Mesalands Community College" }, + { "value": "461847", "label": "Mesivta Keser Torah" }, + { + "value": "193061", + "label": "Mesivta of Eastern Parkway-Yeshiva Zichron Meilech" + }, + { "value": "193052", "label": "Mesivta Torah Vodaath Rabbinical Seminary" }, + { "value": "193070", "label": "Mesivtha Tifereth Jerusalem of America" }, + { "value": "417752", "label": "Messenger College" }, + { "value": "213996", "label": "Messiah College" }, + { "value": "147129", "label": "Methodist College" }, + { "value": "203997", "label": "Methodist Theological School in Ohio" }, + { "value": "198969", "label": "Methodist University" }, + { "value": "455673", "label": "Metro Business College-Arnold" }, + { "value": "178110", "label": "Metro Business College-Cape Girardeau" }, + { "value": "245430", "label": "Metro Business College-Jefferson City" }, + { "value": "245421", "label": "Metro Business College-Rolla" }, + { + "value": "214023", + "label": "Metropolitan Career Center Computer Technology Institute" + }, + { "value": "190114", "label": "Metropolitan College of New York" }, + { "value": "181303", "label": "Metropolitan Community College Area" }, + { + "value": "177995", + "label": "Metropolitan Community College-Kansas City-Kansas City" + }, + { "value": "174020", "label": "Metropolitan State University" }, + { "value": "127565", "label": "Metropolitan State University of Denver" }, + { "value": "166869", "label": "MGH Institute of Health Professions" }, + { "value": "135717", "label": "Miami Dade College" }, + { "value": "204006", "label": "Miami University-Hamilton" }, + { "value": "204015", "label": "Miami University-Middletown" }, + { "value": "204024", "label": "Miami University-Oxford" }, + { "value": "369862", "label": "Miami-Jacobs Career College-Columbus" }, + { "value": "204060", "label": "Miami-Jacobs Career College-Dayton" }, + { "value": "200633", "label": "Miami-Jacobs Career College-Independence" }, + { "value": "441201", "label": "Miami-Jacobs Career College-Sharonville" }, + { "value": "449126", "label": "Miami-Jacobs Career College-Springboro" }, + { "value": "450003", "label": "Miami-Jacobs Career College-Troy" }, + { "value": "169655", "label": "MIAT College of Technology" }, + { "value": "434414", "label": "Michigan Jewish Institute" }, + { + "value": "169220", + "label": "Michigan School of Professional Psychology" + }, + { "value": "171100", "label": "Michigan State University" }, + { "value": "169628", "label": "Michigan State University-College of Law" }, + { "value": "171128", "label": "Michigan Technological University" }, + { "value": "171155", "label": "Mid Michigan Community College" }, + { "value": "245953", "label": "Mid-America Christian University" }, + { "value": "151962", "label": "Mid-America College of Funeral Service" }, + { "value": "155520", "label": "MidAmerica Nazarene University" }, + { "value": "199458", "label": "Mid-Atlantic Christian University" }, + { "value": "482158", "label": "Middle Georgia State College" }, + { "value": "220996", "label": "Middle Tennessee School of Anesthesia Inc" }, + { "value": "220978", "label": "Middle Tennessee State University" }, + { "value": "230959", "label": "Middlebury College" }, + { "value": "166887", "label": "Middlesex Community College-Bedford" }, + { "value": "129756", "label": "Middlesex Community College-Middletown" }, + { "value": "185536", "label": "Middlesex County College" }, + { "value": "226806", "label": "Midland College" }, + { "value": "181330", "label": "Midland University" }, + { "value": "218353", "label": "Midlands Technical College" }, + { "value": "181312", "label": "Mid-Plains Community College" }, + { "value": "481225", "label": "Mid-South Christian College" }, + { "value": "147165", "label": "Midstate College" }, + { "value": "239220", "label": "Mid-State Technical College" }, + { "value": "157377", "label": "Midway College" }, + { + "value": "439020", + "label": "Midwest College of Oriental Medicine-Chicago" + }, + { + "value": "383020", + "label": "Midwest College of Oriental Medicine-Racine" + }, + { "value": "178183", "label": "Midwest Institute" }, + { "value": "178208", "label": "Midwestern Baptist Theological Seminary" }, + { "value": "226833", "label": "Midwestern State University" }, + { "value": "143853", "label": "Midwestern University-Downers Grove" }, + { "value": "423643", "label": "Midwestern University-Glendale" }, + { "value": "480985", "label": "Midwives College of Utah" }, + { "value": "193201", "label": "Mildred Elley School-Albany Campus" }, + { "value": "461014", "label": "Mildred Elley-New York Campus" }, + { "value": "101675", "label": "Miles College" }, + { "value": "180373", "label": "Miles Community College" }, + { "value": "461883", "label": "Millennia Atlantic University" }, + { "value": "449117", "label": "Miller-Motte College-Cary" }, + { "value": "458405", "label": "Miller-Motte College-Fayetteville" }, + { "value": "455655", "label": "Miller-Motte College-Greenville" }, + { "value": "460817", "label": "Miller-Motte College-Jacksonville" }, + { "value": "456205", "label": "Miller-Motte College-Raleigh" }, + { "value": "198978", "label": "Miller-Motte College-Wilmington" }, + { "value": "460826", "label": "Miller-Motte Technical College-Augusta" }, + { "value": "441025", "label": "Miller-Motte Technical College-Charleston" }, + { + "value": "443650", + "label": "Miller-Motte Technical College-Chattanooga" + }, + { + "value": "382771", + "label": "Miller-Motte Technical College-Clarksville" + }, + { "value": "458441", "label": "Miller-Motte Technical College-Columbus" }, + { "value": "460835", "label": "Miller-Motte Technical College-Conway" }, + { "value": "475079", "label": "Miller-Motte Technical College-Gulfport" }, + { "value": "233091", "label": "Miller-Motte Technical College-Lynchburg" }, + { "value": "475060", "label": "Miller-Motte Technical College-Macon" }, + { "value": "448664", "label": "Miller-Motte Technical College-Madison" }, + { "value": "475194", "label": "Miller-Motte Technical College-Roanoke" }, + { "value": "214041", "label": "Millersville University of Pennsylvania" }, + { "value": "221014", "label": "Milligan College" }, + { "value": "147244", "label": "Millikin University" }, + { "value": "118888", "label": "Mills College" }, + { "value": "175980", "label": "Millsaps College" }, + { "value": "239248", "label": "Milwaukee Area Technical College" }, + { "value": "239309", "label": "Milwaukee Institute of Art & Design" }, + { "value": "239318", "label": "Milwaukee School of Engineering" }, + { "value": "178217", "label": "Mineral Area College" }, + { "value": "174118", "label": "Minneapolis Business College" }, + { "value": "174127", "label": "Minneapolis College of Art and Design" }, + { + "value": "174136", + "label": "Minneapolis Community and Technical College" + }, + { "value": "474881", "label": "Minneapolis Media Institute" }, + { "value": "451769", "label": "Minnesota School of Business-Blaine" }, + { + "value": "407285", + "label": "Minnesota School of Business-Brooklyn Center" + }, + { "value": "456782", "label": "Minnesota School of Business-Elk River" }, + { "value": "458742", "label": "Minnesota School of Business-Lakeville" }, + { "value": "455585", "label": "Minnesota School of Business-Moorhead" }, + { "value": "442578", "label": "Minnesota School of Business-Plymouth" }, + { "value": "174279", "label": "Minnesota School of Business-Richfield" }, + { "value": "447670", "label": "Minnesota School of Business-Rochester" }, + { "value": "445920", "label": "Minnesota School of Business-Waite Park" }, + { + "value": "175263", + "label": "Minnesota State College-Southeast Technical" + }, + { + "value": "173559", + "label": "Minnesota State Community and Technical College" + }, + { "value": "174358", "label": "Minnesota State University Moorhead" }, + { "value": "173920", "label": "Minnesota State University-Mankato" }, + { + "value": "173638", + "label": "Minnesota West Community and Technical College" + }, + { "value": "200253", "label": "Minot State University" }, + { "value": "118912", "label": "MiraCosta College" }, + { "value": "193247", "label": "Mirrer Yeshiva Cent Institute" }, + { "value": "214069", "label": "Misericordia University" }, + { "value": "118930", "label": "Mission College" }, + { "value": "176053", "label": "Mississippi College" }, + { "value": "176008", "label": "Mississippi Delta Community College" }, + { "value": "176071", "label": "Mississippi Gulf Coast Community College" }, + { "value": "176080", "label": "Mississippi State University" }, + { "value": "176035", "label": "Mississippi University for Women" }, + { "value": "176044", "label": "Mississippi Valley State University" }, + { "value": "178244", "label": "Missouri Baptist University" }, + { "value": "178305", "label": "Missouri College" }, + { "value": "178341", "label": "Missouri Southern State University" }, + { "value": "179566", "label": "Missouri State University-Springfield" }, + { "value": "179344", "label": "Missouri State University-West Plains" }, + { "value": "178350", "label": "Missouri Tech" }, + { + "value": "178411", + "label": "Missouri University of Science and Technology" + }, + { "value": "178369", "label": "Missouri Valley College" }, + { "value": "178387", "label": "Missouri Western State University" }, + { "value": "129774", "label": "Mitchell College" }, + { "value": "198987", "label": "Mitchell Community College" }, + { "value": "219189", "label": "Mitchell Technical Institute" }, + { "value": "178448", "label": "Moberly Area Community College" }, + { "value": "118976", "label": "Modesto Junior College" }, + { "value": "105206", "label": "Mohave Community College" }, + { "value": "193283", "label": "Mohawk Valley Community College" }, + { "value": "193292", "label": "Molloy College" }, + { "value": "147341", "label": "Monmouth College" }, + { "value": "185572", "label": "Monmouth University" }, + { "value": "193308", "label": "Monroe College" }, + { "value": "193326", "label": "Monroe Community College" }, + { "value": "171225", "label": "Monroe County Community College" }, + { "value": "262165", "label": "Montana Bible College" }, + { "value": "180461", "label": "Montana State University" }, + { "value": "180179", "label": "Montana State University-Billings" }, + { "value": "180522", "label": "Montana State University-Northern" }, + { "value": "180416", "label": "Montana Tech of the University of Montana" }, + { "value": "171234", "label": "Montcalm Community College" }, + { "value": "185590", "label": "Montclair State University" }, + { + "value": "119058", + "label": "Monterey Institute of International Studies" + }, + { "value": "119067", "label": "Monterey Peninsula College" }, + { "value": "163426", "label": "Montgomery College" }, + { "value": "199023", "label": "Montgomery Community College" }, + { "value": "214111", "label": "Montgomery County Community College" }, + { "value": "199032", "label": "Montreat College" }, + { "value": "166911", "label": "Montserrat College of Art" }, + { "value": "147369", "label": "Moody Bible Institute" }, + { "value": "214148", "label": "Moore College of Art and Design" }, + { "value": "119137", "label": "Moorpark College" }, + { "value": "239372", "label": "Moraine Park Technical College" }, + { "value": "147378", "label": "Moraine Valley Community College" }, + { "value": "214157", "label": "Moravian College" }, + { "value": "157386", "label": "Morehead State University" }, + { "value": "140553", "label": "Morehouse College" }, + { "value": "140562", "label": "Morehouse School of Medicine" }, + { "value": "460394", "label": "Moreno Valley College" }, + { "value": "127617", "label": "Morgan Community College" }, + { "value": "163453", "label": "Morgan State University" }, + { "value": "154004", "label": "Morningside College" }, + { "value": "218399", "label": "Morris College" }, + { "value": "147396", "label": "Morrison Institute of Technology" }, + { "value": "196051", "label": "Morrisville State College" }, + { "value": "147411", "label": "Morton College" }, + { "value": "221096", "label": "Motlow State Community College" }, + { "value": "169275", "label": "Mott Community College" }, + { "value": "140599", "label": "Moultrie Technical College" }, + { "value": "214166", "label": "Mount Aloysius College" }, + { "value": "209241", "label": "Mount Angel Seminary" }, + { "value": "204176", "label": "Mount Carmel College of Nursing" }, + { "value": "166939", "label": "Mount Holyoke College" }, + { "value": "166948", "label": "Mount Ida College" }, + { "value": "219198", "label": "Mount Marty College" }, + { "value": "239390", "label": "Mount Mary University" }, + { "value": "154013", "label": "Mount Mercy University" }, + { "value": "204200", "label": "Mount Saint Joseph University" }, + { "value": "193353", "label": "Mount Saint Mary College" }, + { "value": "119173", "label": "Mount Saint Mary's University" }, + { "value": "163462", "label": "Mount St Mary's University" }, + { "value": "204194", "label": "Mount Vernon Nazarene University" }, + { "value": "166957", "label": "Mount Wachusett Community College" }, + { "value": "182865", "label": "Mount Washington College" }, + { "value": "232788", "label": "Mountain Empire Community College" }, + { "value": "237598", "label": "Mountain State College" }, + { "value": "226930", "label": "Mountain View College" }, + { "value": "444954", "label": "Mountwest Community and Technical College" }, + { "value": "209250", "label": "Mt Hood Community College" }, + { "value": "119164", "label": "Mt San Antonio College" }, + { "value": "119216", "label": "Mt San Jacinto Community College District" }, + { "value": "398130", "label": "Mt Sierra College" }, + { "value": "118198", "label": "MTI College" }, + { "value": "214175", "label": "Muhlenberg College" }, + { "value": "209287", "label": "Multnomah University" }, + { "value": "207236", "label": "Murray State College" }, + { "value": "157401", "label": "Murray State University" }, + { "value": "119270", "label": "Musicians Institute" }, + { "value": "171304", "label": "Muskegon Community College" }, + { "value": "204264", "label": "Muskingum University" }, + { "value": "434432", "label": "Myotherapy Institute" }, + { "value": "119331", "label": "Napa Valley College" }, + { "value": "127653", "label": "Naropa University" }, + { "value": "199087", "label": "Nash Community College" }, + { "value": "239424", "label": "Nashotah House" }, + { "value": "183141", "label": "Nashua Community College" }, + { "value": "221184", "label": "Nashville State Community College" }, + { "value": "193478", "label": "Nassau Community College" }, + { "value": "248882", "label": "National American University-Albuquerque" }, + { + "value": "440758", + "label": "National American University-Albuquerque West" + }, + { "value": "451875", "label": "National American University-Austin" }, + { "value": "482307", "label": "National American University-Austin South" }, + { "value": "477996", "label": "National American University-Bellevue" }, + { "value": "436483", "label": "National American University-Bloomington" }, + { + "value": "440767", + "label": "National American University-Brooklyn Center" + }, + { "value": "478005", "label": "National American University-Burnsville" }, + { "value": "466161", "label": "National American University-Centennial" }, + { + "value": "127680", + "label": "National American University-Colorado Springs" + }, + { + "value": "466189", + "label": "National American University-Colorado Springs South" + }, + { "value": "127699", "label": "National American University-Denver" }, + { + "value": "440749", + "label": "National American University-Ellsworth AFB Extension" + }, + { "value": "482325", "label": "National American University-Georgetown" }, + { + "value": "485290", + "label": "National American University-Harold D. Buckingham Graduate School" + }, + { "value": "247700", "label": "National American University-Independence" }, + { "value": "482370", "label": "National American University-Indianapolis" }, + { "value": "466170", "label": "National American University-Lee's Summit" }, + { "value": "482316", "label": "National American University-Lewisville" }, + { + "value": "442718", + "label": "National American University-Overland Park" + }, + { "value": "219204", "label": "National American University-Rapid City" }, + { "value": "482343", "label": "National American University-Rochester" }, + { "value": "174385", "label": "National American University-Roseville" }, + { "value": "219213", "label": "National American University-Sioux Falls" }, + { "value": "466152", "label": "National American University-Tulsa" }, + { + "value": "482352", + "label": "National American University-Weldon Spring" + }, + { "value": "451884", "label": "National American University-Wichita" }, + { "value": "482361", "label": "National American University-Wichita West" }, + { "value": "448585", "label": "National American University-Zona Rosa" }, + { "value": "209296", "label": "National College of Natural Medicine" }, + { "value": "480480", "label": "National College-Canton" }, + { "value": "453473", "label": "National College-Cincinnati" }, + { "value": "457004", "label": "National College-Columbus" }, + { "value": "453455", "label": "National College-Dayton" }, + { "value": "157021", "label": "National College-Lexington" }, + { "value": "388043", "label": "National College-Nashville" }, + { "value": "453482", "label": "National College-Stow" }, + { "value": "459833", "label": "National College-Willoughby Hills" }, + { "value": "453464", "label": "National College-Youngstown" }, + { + "value": "441478", + "label": "National Graduate School of Quality Management" + }, + { "value": "412003", "label": "National Institute of Massotherapy" }, + { "value": "147536", "label": "National Louis University" }, + { "value": "448114", "label": "National Massage Therapy Institute" }, + { "value": "461023", "label": "National Paralegal College" }, + { "value": "106980", "label": "National Park Community College" }, + { "value": "119605", "label": "National University" }, + { "value": "242981", "label": "National University College-Arecibo" }, + { "value": "242972", "label": "National University College-Bayamon" }, + { "value": "468723", "label": "National University College-Caguas" }, + { "value": "458469", "label": "National University College-Ponce" }, + { "value": "444042", "label": "National University College-Rio Grande" }, + { "value": "147590", "label": "National University of Health Sciences" }, + { "value": "129729", "label": "Naugatuck Valley Community College" }, + { "value": "187596", "label": "Navajo Technical University" }, + { "value": "119678", "label": "Naval Postgraduate School" }, + { "value": "227146", "label": "Navarro College" }, + { "value": "127714", "label": "Nazarene Bible College" }, + { "value": "178518", "label": "Nazarene Theological Seminary" }, + { "value": "193584", "label": "Nazareth College" }, + { "value": "181376", "label": "Nebraska Christian College" }, + { "value": "181765", "label": "Nebraska College of Technical Agriculture" }, + { "value": "181419", "label": "Nebraska Indian Community College" }, + { + "value": "181297", + "label": "Nebraska Methodist College of Nursing & Allied Health" + }, + { "value": "181446", "label": "Nebraska Wesleyan University" }, + { "value": "155566", "label": "Neosho County Community College" }, + { "value": "163532", "label": "Ner Israel Rabbinical College" }, + { "value": "214272", "label": "Neumann University" }, + { "value": "445692", "label": "Neumont University" }, + { "value": "441900", "label": "Nevada State College" }, + { "value": "185758", "label": "New Brunswick Theological Seminary" }, + { "value": "214290", "label": "New Castle School of Trades" }, + { "value": "262129", "label": "New College of Florida" }, + { "value": "182980", "label": "New England College" }, + { + "value": "164438", + "label": "New England College of Business and Finance" + }, + { "value": "167093", "label": "New England College of Optometry" }, + { "value": "230977", "label": "New England Culinary Institute" }, + { "value": "217305", "label": "New England Institute of Technology" }, + { "value": "167215", "label": "New England Law-Boston" }, + { "value": "167181", "label": "New England School of Acupuncture" }, + { "value": "430810", "label": "New Hampshire Institute of Art" }, + { "value": "208725", "label": "New Hope Christian College-Eugene" }, + { "value": "185129", "label": "New Jersey City University" }, + { "value": "185828", "label": "New Jersey Institute of Technology" }, + { "value": "187897", "label": "New Mexico Highlands University" }, + { + "value": "187967", + "label": "New Mexico Institute of Mining and Technology" + }, + { "value": "187903", "label": "New Mexico Junior College" }, + { "value": "187912", "label": "New Mexico Military Institute" }, + { "value": "187994", "label": "New Mexico State University-Alamogordo" }, + { "value": "188003", "label": "New Mexico State University-Carlsbad" }, + { "value": "187620", "label": "New Mexico State University-Dona Ana" }, + { "value": "188021", "label": "New Mexico State University-Grants" }, + { "value": "188030", "label": "New Mexico State University-Main Campus" }, + { "value": "159948", "label": "New Orleans Baptist Theological Seminary" }, + { "value": "447582", "label": "New River Community and Technical College" }, + { "value": "232867", "label": "New River Community College" }, + { "value": "366368", "label": "New York Academy of Art" }, + { "value": "195845", "label": "New York Career Institute" }, + { "value": "193751", "label": "New York Chiropractic College" }, + { "value": "418126", "label": "New York College of Health Professions" }, + { "value": "194073", "label": "New York College of Podiatric Medicine" }, + { + "value": "439783", + "label": "New York College of Traditional Chinese Medicine" + }, + { "value": "421841", "label": "New York Conservatory for Dramatic Arts" }, + { "value": "461148", "label": "New York Film Academy" }, + { "value": "194091", "label": "New York Institute of Technology" }, + { "value": "193821", "label": "New York Law School" }, + { "value": "193830", "label": "New York Medical College" }, + { "value": "194116", "label": "New York School of Interior Design" }, + { "value": "193894", "label": "New York Theological Seminary" }, + { "value": "193900", "label": "New York University" }, + { "value": "218414", "label": "Newberry College" }, + { "value": "167251", "label": "Newbury College" }, + { "value": "155335", "label": "Newman University" }, + { "value": "119775", "label": "Newschool of Architecture and Design" }, + { "value": "183099", "label": "NHTI-Concord's Community College" }, + { "value": "193946", "label": "Niagara County Community College" }, + { "value": "193973", "label": "Niagara University" }, + { "value": "159966", "label": "Nicholls State University" }, + { "value": "167260", "label": "Nichols College" }, + { "value": "239442", "label": "Nicolet Area Technical College" }, + { "value": "444787", "label": "Nightingale College" }, + { "value": "460464", "label": "Norco College" }, + { "value": "232937", "label": "Norfolk State University" }, + { "value": "174428", "label": "Normandale Community College" }, + { "value": "461795", "label": "North American University" }, + { "value": "107460", "label": "North Arkansas College" }, + { "value": "199102", "label": "North Carolina A & T State University" }, + { "value": "199157", "label": "North Carolina Central University" }, + { + "value": "199193", + "label": "North Carolina State University at Raleigh" + }, + { "value": "199209", "label": "North Carolina Wesleyan College" }, + { "value": "147660", "label": "North Central College" }, + { "value": "418889", "label": "North Central Institute" }, + { "value": "155593", "label": "North Central Kansas Technical College" }, + { "value": "171395", "label": "North Central Michigan College" }, + { "value": "179715", "label": "North Central Missouri College" }, + { "value": "204422", "label": "North Central State College" }, + { "value": "224110", "label": "North Central Texas College" }, + { "value": "174437", "label": "North Central University" }, + { "value": "194028", "label": "North Country Community College" }, + { "value": "200305", "label": "North Dakota State College of Science" }, + { "value": "200332", "label": "North Dakota State University-Main Campus" }, + { "value": "136145", "label": "North Florida Community College" }, + { "value": "140678", "label": "North Georgia Technical College" }, + { "value": "218441", "label": "North Greenville University" }, + { "value": "174376", "label": "North Hennepin Community College" }, + { "value": "142443", "label": "North Idaho College" }, + { "value": "154059", "label": "North Iowa Area Community College" }, + { "value": "227191", "label": "North Lake College" }, + { "value": "147679", "label": "North Park University" }, + { "value": "236072", "label": "North Seattle College" }, + { "value": "167312", "label": "North Shore Community College" }, + { "value": "214379", "label": "Northampton County Area Community College" }, + { "value": "239460", "label": "Northcentral Technical College" }, + { "value": "444130", "label": "Northcentral University" }, + { "value": "101897", "label": "Northeast Alabama Community College" }, + { "value": "182917", "label": "Northeast Catholic College" }, + { "value": "181491", "label": "Northeast Community College" }, + { "value": "154110", "label": "Northeast Iowa Community College" }, + { "value": "176169", "label": "Northeast Mississippi Community College" }, + { "value": "204477", "label": "Northeast Ohio Medical University" }, + { "value": "221908", "label": "Northeast State Community College" }, + { "value": "227225", "label": "Northeast Texas Community College" }, + { "value": "239488", "label": "Northeast Wisconsin Technical College" }, + { "value": "147776", "label": "Northeastern Illinois University" }, + { "value": "127732", "label": "Northeastern Junior College" }, + { "value": "207290", "label": "Northeastern Oklahoma A&M College" }, + { "value": "439817", "label": "Northeastern Seminary" }, + { "value": "207263", "label": "Northeastern State University" }, + { "value": "217837", "label": "Northeastern Technical College" }, + { "value": "167358", "label": "Northeastern University" }, + { "value": "482705", "label": "Northeastern University Global Network" }, + { "value": "105330", "label": "Northern Arizona University" }, + { "value": "147697", "label": "Northern Baptist Theological Seminary" }, + { "value": "167376", "label": "Northern Essex Community College" }, + { "value": "147703", "label": "Northern Illinois University" }, + { "value": "157447", "label": "Northern Kentucky University" }, + { "value": "161484", "label": "Northern Maine Community College" }, + { "value": "240790", "label": "Northern Marianas College" }, + { "value": "171456", "label": "Northern Michigan University" }, + { "value": "188058", "label": "Northern New Mexico College" }, + { "value": "207281", "label": "Northern Oklahoma College" }, + { "value": "219259", "label": "Northern State University" }, + { "value": "232946", "label": "Northern Virginia Community College" }, + { "value": "239512", "label": "Northland College" }, + { "value": "174473", "label": "Northland Community and Technical College" }, + { "value": "239503", "label": "Northland International University" }, + { "value": "105349", "label": "Northland Pioneer College" }, + { "value": "217606", "label": "Northpoint Bible College" }, + { "value": "160667", "label": "Northshore Technical Community College" }, + { "value": "367459", "label": "NorthWest Arkansas Community College" }, + { "value": "445948", "label": "Northwest Career College" }, + { "value": "209409", "label": "Northwest Christian University" }, + { "value": "240657", "label": "Northwest College" }, + { "value": "377546", "label": "Northwest College of Art & Design" }, + { "value": "136233", "label": "Northwest Florida State College" }, + { "value": "380377", "label": "Northwest Indian College" }, + { "value": "460941", "label": "Northwest Institute of Literary Arts" }, + { "value": "154129", "label": "Northwest Iowa Community College" }, + { "value": "155618", "label": "Northwest Kansas Technical College" }, + { "value": "160010", "label": "Northwest Louisiana Technical College" }, + { "value": "176178", "label": "Northwest Mississippi Community College" }, + { "value": "178624", "label": "Northwest Missouri State University" }, + { "value": "142461", "label": "Northwest Nazarene University" }, + { "value": "458140", "label": "Northwest School of Wooden Boat Building" }, + { "value": "204440", "label": "Northwest State Community College" }, + { "value": "173115", "label": "Northwest Technical College" }, + { "value": "236133", "label": "Northwest University" }, + { "value": "420398", "label": "Northwest Vista College" }, + { "value": "154101", "label": "Northwestern College" }, + { "value": "147749", "label": "Northwestern College-Chicago Campus" }, + { "value": "260992", "label": "Northwestern College-Southwestern Campus" }, + { + "value": "130040", + "label": "Northwestern Connecticut Community College" + }, + { "value": "174507", "label": "Northwestern Health Sciences University" }, + { "value": "171483", "label": "Northwestern Michigan College" }, + { "value": "207306", "label": "Northwestern Oklahoma State University" }, + { + "value": "160038", + "label": "Northwestern State University of Louisiana" + }, + { "value": "147767", "label": "Northwestern University" }, + { "value": "101736", "label": "Northwest-Shoals Community College" }, + { "value": "136206", "label": "Northwood University-Florida" }, + { "value": "171492", "label": "Northwood University-Michigan" }, + { "value": "227243", "label": "Northwood University-Texas" }, + { "value": "130004", "label": "Norwalk Community College" }, + { "value": "230995", "label": "Norwich University" }, + { "value": "368452", "label": "Nossi College of Art" }, + { "value": "204468", "label": "Notre Dame College" }, + { "value": "120184", "label": "Notre Dame de Namur University" }, + { "value": "163578", "label": "Notre Dame of Maryland University" }, + { + "value": "160029", + "label": "Notre Dame Seminary Graduate School of Theology" + }, + { "value": "136215", "label": "Nova Southeastern University" }, + { "value": "200086", "label": "Nueta Hidatsa Sahnish College" }, + { "value": "158884", "label": "Nunez Community College" }, + { "value": "194161", "label": "Nyack College" }, + { "value": "174525", "label": "Oak Hills Christian College" }, + { "value": "152099", "label": "Oakland City University" }, + { "value": "171535", "label": "Oakland Community College" }, + { "value": "171571", "label": "Oakland University" }, + { "value": "147800", "label": "Oakton Community College" }, + { "value": "101912", "label": "Oakwood University" }, + { "value": "204501", "label": "Oberlin College" }, + { "value": "227289", "label": "Oblate School of Theology" }, + { "value": "120254", "label": "Occidental College" }, + { "value": "185873", "label": "Ocean County College" }, + { "value": "420431", "label": "Oconee Fall Line Technical College" }, + { "value": "227304", "label": "Odessa College" }, + { "value": "366465", "label": "Ogeechee Technical College" }, + { "value": "219277", "label": "Oglala Lakota College" }, + { "value": "140696", "label": "Oglethorpe University" }, + { "value": "453747", "label": "Ohio Business College-Hilliard" }, + { "value": "203739", "label": "Ohio Business College-Sandusky" }, + { "value": "203720", "label": "Ohio Business College-Sheffield" }, + { "value": "201964", "label": "Ohio Christian University" }, + { "value": "204592", "label": "Ohio College of Massotherapy Inc" }, + { "value": "204617", "label": "Ohio Dominican University" }, + { "value": "206002", "label": "Ohio Mid-Western College" }, + { "value": "204635", "label": "Ohio Northern University" }, + { + "value": "204662", + "label": "Ohio State University Agricultural Technical Institute" + }, + { "value": "204671", "label": "Ohio State University-Lima Campus" }, + { "value": "204796", "label": "Ohio State University-Main Campus" }, + { "value": "204680", "label": "Ohio State University-Mansfield Campus" }, + { "value": "204699", "label": "Ohio State University-Marion Campus" }, + { "value": "204705", "label": "Ohio State University-Newark Campus" }, + { "value": "204608", "label": "Ohio Technical College" }, + { + "value": "453817", + "label": "Ohio Technical College-PowerSport Institute" + }, + { "value": "204820", "label": "Ohio University-Chillicothe Campus" }, + { "value": "204802", "label": "Ohio University-Eastern Campus" }, + { "value": "204848", "label": "Ohio University-Lancaster Campus" }, + { "value": "204857", "label": "Ohio University-Main Campus" }, + { "value": "204839", "label": "Ohio University-Southern Campus" }, + { "value": "204866", "label": "Ohio University-Zanesville Campus" }, + { "value": "204884", "label": "Ohio Valley College of Technology" }, + { "value": "237640", "label": "Ohio Valley University" }, + { "value": "204909", "label": "Ohio Wesleyan University" }, + { "value": "120290", "label": "Ohlone College" }, + { "value": "194189", "label": "Ohr Hameir Theological Seminary" }, + { "value": "207403", "label": "Oklahoma Baptist University" }, + { "value": "207324", "label": "Oklahoma Christian University" }, + { "value": "207449", "label": "Oklahoma City Community College" }, + { "value": "207458", "label": "Oklahoma City University" }, + { "value": "207351", "label": "Oklahoma Panhandle State University" }, + { + "value": "207315", + "label": "Oklahoma State University Center for Health Sciences" + }, + { + "value": "207564", + "label": "Oklahoma State University Institute of Technology" + }, + { "value": "207388", "label": "Oklahoma State University-Main Campus" }, + { "value": "207397", "label": "Oklahoma State University-Oklahoma City" }, + { "value": "469629", "label": "Oklahoma Technical College" }, + { "value": "206835", "label": "Oklahoma Wesleyan University" }, + { "value": "232982", "label": "Old Dominion University" }, + { "value": "171599", "label": "Olivet College" }, + { "value": "147828", "label": "Olivet Nazarene University" }, + { "value": "145707", "label": "Olney Central College" }, + { "value": "236188", "label": "Olympic College" }, + { + "value": "407328", + "label": "Omaha School of Massage and Healthcare of Herzing University" + }, + { "value": "221254", "label": "O'More College of Design" }, + { "value": "194222", "label": "Onondaga Community College" }, + { "value": "207582", "label": "Oral Roberts University" }, + { "value": "120342", "label": "Orange Coast College" }, + { "value": "194240", "label": "Orange County Community College" }, + { "value": "218487", "label": "Orangeburg Calhoun Technical College" }, + { "value": "423652", "label": "Oregon Coast Community College" }, + { "value": "209533", "label": "Oregon College of Art and Craft" }, + { "value": "369659", "label": "Oregon College of Oriental Medicine" }, + { "value": "209490", "label": "Oregon Health & Science University" }, + { "value": "209506", "label": "Oregon Institute of Technology" }, + { "value": "209542", "label": "Oregon State University" }, + { "value": "454883", "label": "Orion College" }, + { "value": "214528", "label": "Orleans Technical Institute" }, + { "value": "127778", "label": "Otero Junior College" }, + { "value": "120403", "label": "Otis College of Art and Design" }, + { "value": "442897", "label": "Ottawa University-Jeffersonville" }, + { "value": "155636", "label": "Ottawa University-Kansas City" }, + { "value": "428259", "label": "Ottawa University-Milwaukee" }, + { "value": "454582", "label": "Ottawa University-Online" }, + { "value": "155627", "label": "Ottawa University-Ottawa" }, + { "value": "105367", "label": "Ottawa University-Phoenix" }, + { "value": "204936", "label": "Otterbein University" }, + { "value": "107512", "label": "Ouachita Baptist University" }, + { "value": "160074", "label": "Our Lady of the Lake College" }, + { "value": "227331", "label": "Our Lady of the Lake University" }, + { "value": "204945", "label": "Owens Community College" }, + { "value": "247940", "label": "Owensboro Community and Technical College" }, + { "value": "461120", "label": "Oxford Graduate School" }, + { "value": "120421", "label": "Oxnard College" }, + { "value": "178679", "label": "Ozark Christian College" }, + { "value": "107549", "label": "Ozarka College" }, + { "value": "177472", "label": "Ozarks Technical Community College" }, + { "value": "214838", "label": "Pace Institute" }, + { "value": "194310", "label": "Pace University-New York" }, + { "value": "422695", "label": "Pacific College" }, + { + "value": "442842", + "label": "Pacific College of Oriental Medicine-Chicago" + }, + { + "value": "414595", + "label": "Pacific College of Oriental Medicine-New York" + }, + { + "value": "378576", + "label": "Pacific College of Oriental Medicine-San Diego" + }, + { "value": "439862", "label": "Pacific Islands University" }, + { "value": "120740", "label": "Pacific Lutheran Theological Seminary" }, + { "value": "236230", "label": "Pacific Lutheran University" }, + { "value": "209603", "label": "Pacific Northwest College of Art" }, + { + "value": "455406", + "label": "Pacific Northwest University of Health Sciences" + }, + { "value": "120768", "label": "Pacific Oaks College" }, + { "value": "457484", "label": "Pacific Rim Christian University" }, + { "value": "120795", "label": "Pacific School of Religion" }, + { "value": "120838", "label": "Pacific States University" }, + { "value": "120865", "label": "Pacific Union College" }, + { "value": "209612", "label": "Pacific University" }, + { "value": "115746", "label": "Pacifica Graduate Institute" }, + { "value": "130110", "label": "Paier College of Art Inc" }, + { "value": "140720", "label": "Paine College" }, + { "value": "243647", "label": "Palau Community College" }, + { "value": "136330", "label": "Palm Beach Atlantic University" }, + { "value": "136358", "label": "Palm Beach State College" }, + { "value": "154174", "label": "Palmer College of Chiropractic" }, + { "value": "246354", "label": "Palo Alto College" }, + { "value": "120698", "label": "Palo Alto University" }, + { "value": "120953", "label": "Palo Verde College" }, + { "value": "120971", "label": "Palomar College" }, + { "value": "199263", "label": "Pamlico Community College" }, + { "value": "227386", "label": "Panola College" }, + { "value": "364016", "label": "Paradise Valley Community College" }, + { "value": "121628", "label": "Pardee RAND Graduate School" }, + { "value": "227401", "label": "Paris Junior College" }, + { "value": "178721", "label": "Park University" }, + { "value": "243823", "label": "Parker University" }, + { "value": "147916", "label": "Parkland College" }, + { "value": "121044", "label": "Pasadena City College" }, + { "value": "136400", "label": "Pasco-Hernando State College" }, + { "value": "186034", "label": "Passaic County Community College" }, + { "value": "666666", "label": "Patrick Henry College" }, + { "value": "233019", "label": "Patrick Henry Community College" }, + { "value": "233037", "label": "Paul D Camp Community College" }, + { "value": "227429", "label": "Paul Quinn College" }, + { "value": "194392", "label": "Paul Smiths College of Arts and Science" }, + { "value": "204990", "label": "Payne Theological Seminary" }, + { "value": "176239", "label": "Pearl River Community College" }, + { "value": "214883", "label": "Peirce College" }, + { "value": "221643", "label": "Pellissippi State Community College" }, + { "value": "236258", "label": "Peninsula College" }, + { "value": "214892", "label": "Penn Commercial Business/Technical School" }, + { "value": "214944", "label": "Pennco Tech-Bristol" }, + { "value": "214971", "label": "Pennsylvania Academy of the Fine Arts" }, + { "value": "215053", "label": "Pennsylvania College of Art and Design" }, + { "value": "442356", "label": "Pennsylvania College of Health Sciences" }, + { "value": "366252", "label": "Pennsylvania College of Technology" }, + { "value": "414911", "label": "Pennsylvania Highlands Community College" }, + { + "value": "261861", + "label": "Pennsylvania Institute of Health and Technology" + }, + { "value": "214582", "label": "Pennsylvania Institute of Technology" }, + { + "value": "214616", + "label": "Pennsylvania State University-College of Medicine" + }, + { + "value": "212018", + "label": "Pennsylvania State University-Dickinson Law" + }, + { "value": "214777", "label": "Pennsylvania State University-Main Campus" }, + { + "value": "214801", + "label": "Pennsylvania State University-Penn State Abington" + }, + { + "value": "214689", + "label": "Pennsylvania State University-Penn State Altoona" + }, + { + "value": "214698", + "label": "Pennsylvania State University-Penn State Beaver" + }, + { + "value": "214704", + "label": "Pennsylvania State University-Penn State Berks" + }, + { + "value": "214731", + "label": "Pennsylvania State University-Penn State Brandywine" + }, + { + "value": "214740", + "label": "Pennsylvania State University-Penn State DuBois" + }, + { + "value": "214591", + "label": "Pennsylvania State University-Penn State Erie-Behrend College" + }, + { + "value": "214759", + "label": "Pennsylvania State University-Penn State Fayette- Eberly" + }, + { + "value": "214607", + "label": "Pennsylvania State University-Penn State Great Valley" + }, + { + "value": "214786", + "label": "Pennsylvania State University-Penn State Greater Allegheny" + }, + { + "value": "214713", + "label": "Pennsylvania State University-Penn State Harrisburg" + }, + { + "value": "214768", + "label": "Pennsylvania State University-Penn State Hazleton" + }, + { + "value": "214670", + "label": "Pennsylvania State University-Penn State Lehigh Valley" + }, + { + "value": "214795", + "label": "Pennsylvania State University-Penn State Mont Alto" + }, + { + "value": "214625", + "label": "Pennsylvania State University-Penn State New Kensington" + }, + { + "value": "214810", + "label": "Pennsylvania State University-Penn State Schuylkill" + }, + { + "value": "214634", + "label": "Pennsylvania State University-Penn State Shenango" + }, + { + "value": "214643", + "label": "Pennsylvania State University-Penn State Wilkes-Barre" + }, + { + "value": "214652", + "label": "Pennsylvania State University-Penn State Worthington Scranton" + }, + { + "value": "214829", + "label": "Pennsylvania State University-Penn State York" + }, + { + "value": "479956", + "label": "Pennsylvania State University-World Campus" + }, + { "value": "136473", "label": "Pensacola State College" }, + { "value": "219842", "label": "Pentecostal Theological Seminary" }, + { "value": "121150", "label": "Pepperdine University" }, + { "value": "181534", "label": "Peru State College" }, + { "value": "199306", "label": "Pfeiffer University" }, + { + "value": "215123", + "label": "Philadelphia College of Osteopathic Medicine" + }, + { "value": "215099", "label": "Philadelphia University" }, + { "value": "107600", "label": "Philander Smith College" }, + { "value": "189282", "label": "Phillips Beth Israel School of Nursing" }, + { + "value": "107619", + "label": "Phillips Community College of the University of Arkansas" + }, + { "value": "110307", "label": "Phillips Graduate Institute" }, + { "value": "414966", "label": "Phillips Theological Seminary" }, + { "value": "105428", "label": "Phoenix College" }, + { + "value": "447698", + "label": "Phoenix Institute of Herbal Medicine & Acupuncture" + }, + { "value": "381459", "label": "Phoenix Seminary" }, + { "value": "140818", "label": "Piedmont College" }, + { "value": "199324", "label": "Piedmont Community College" }, + { "value": "199315", "label": "Piedmont International University" }, + { "value": "218520", "label": "Piedmont Technical College" }, + { "value": "233116", "label": "Piedmont Virginia Community College" }, + { "value": "235237", "label": "Pierce College-Fort Steilacoom" }, + { "value": "439145", "label": "Pierce College-Puyallup" }, + { "value": "443492", "label": "Pierpont Community and Technical College" }, + { "value": "127820", "label": "Pikes Peak Community College" }, + { "value": "440794", "label": "Pillar College" }, + { "value": "105525", "label": "Pima Community College" }, + { "value": "105543", "label": "Pima Medical Institute-Albuquerque" }, + { "value": "461689", "label": "Pima Medical Institute-Aurora" }, + { "value": "434140", "label": "Pima Medical Institute-Chula Vista" }, + { "value": "442134", "label": "Pima Medical Institute-Colorado Springs" }, + { "value": "404912", "label": "Pima Medical Institute-Denver" }, + { "value": "456038", "label": "Pima Medical Institute-East Valley" }, + { "value": "460136", "label": "Pima Medical Institute-Houston" }, + { "value": "445230", "label": "Pima Medical Institute-Las Vegas" }, + { "value": "260691", "label": "Pima Medical Institute-Mesa" }, + { "value": "449074", "label": "Pima Medical Institute-Renton" }, + { "value": "368629", "label": "Pima Medical Institute-Seattle" }, + { "value": "105534", "label": "Pima Medical Institute-Tucson" }, + { "value": "458159", "label": "Pinchot University" }, + { "value": "167455", "label": "Pine Manor College" }, + { "value": "174570", "label": "Pine Technical & Community College" }, + { "value": "367097", "label": "Pinnacle Career Institute-Lawrence" }, + { + "value": "453109", + "label": "Pinnacle Career Institute-North Kansas City" + }, + { + "value": "177302", + "label": "Pinnacle Career Institute-South Kansas City" + }, + { "value": "210076", "label": "Pioneer Pacific College" }, + { "value": "199333", "label": "Pitt Community College" }, + { "value": "155681", "label": "Pittsburg State University" }, + { "value": "216782", "label": "Pittsburgh Career Institute" }, + { "value": "215381", "label": "Pittsburgh Institute of Aeronautics" }, + { + "value": "215390", + "label": "Pittsburgh Institute of Mortuary Science Inc" + }, + { "value": "215415", "label": "Pittsburgh Technical Institute" }, + { "value": "215424", "label": "Pittsburgh Theological Seminary" }, + { "value": "121257", "label": "Pitzer College" }, + { "value": "260813", "label": "Platt College-Aurora" }, + { "value": "207625", "label": "Platt College-Central OKC" }, + { "value": "260789", "label": "Platt College-Los Angeles" }, + { "value": "447379", "label": "Platt College-Moore" }, + { "value": "445258", "label": "Platt College-North OKC" }, + { "value": "432384", "label": "Platt College-Ontario" }, + { "value": "480204", "label": "Platt College-Riverside" }, + { "value": "121275", "label": "Platt College-San Diego" }, + { "value": "245962", "label": "Platt College-Tulsa" }, + { "value": "194499", "label": "Plaza College" }, + { "value": "183080", "label": "Plymouth State University" }, + { "value": "121309", "label": "Point Loma Nazarene University" }, + { "value": "215442", "label": "Point Park University" }, + { "value": "138868", "label": "Point University" }, + { "value": "136516", "label": "Polk State College" }, + { + "value": "456481", + "label": "Polytechnic University of Puerto Rico-Miami" + }, + { + "value": "456490", + "label": "Polytechnic University of Puerto Rico-Orlando" + }, + { + "value": "190451", + "label": "Pomeroy College of Nursing at Crouse Hospital" + }, + { "value": "121345", "label": "Pomona College" }, + { "value": "243081", "label": "Ponce Health Sciences University" }, + { "value": "243072", "label": "Ponce Paramedical College Inc" }, + { + "value": "241395", + "label": "Pontifical Catholic University of Puerto Rico-Arecibo" + }, + { + "value": "243586", + "label": "Pontifical Catholic University of Puerto Rico-Mayaguez" + }, + { + "value": "241410", + "label": "Pontifical Catholic University of Puerto Rico-Ponce" + }, + { "value": "205027", "label": "Pontifical College Josephinum" }, + { + "value": "131405", + "label": "Pontifical Faculty of the Immaculate Conception at the Dominican House of Studies" + }, + { + "value": "455813", + "label": "Pontifical John Paul II Institute for Studies on Marriage and Family" + }, + { "value": "167464", "label": "Pope St John XXIII National Seminary" }, + { "value": "121363", "label": "Porterville College" }, + { "value": "209746", "label": "Portland Community College" }, + { "value": "209807", "label": "Portland State University" }, + { "value": "130183", "label": "Post University" }, + { + "value": "237701", + "label": "Potomac State College of West Virginia University" + }, + { "value": "148007", "label": "Prairie State College" }, + { "value": "227526", "label": "Prairie View A & M University" }, + { "value": "155715", "label": "Pratt Community College" }, + { "value": "194578", "label": "Pratt Institute-Main" }, + { "value": "218539", "label": "Presbyterian College" }, + { "value": "105589", "label": "Prescott College" }, + { "value": "219295", "label": "Presentation College" }, + { "value": "163657", "label": "Prince George's Community College" }, + { "value": "101958", "label": "Prince Institute-Southeast" }, + { "value": "186122", "label": "Princeton Theological Seminary" }, + { "value": "186131", "label": "Princeton University" }, + { "value": "148016", "label": "Principia College" }, + { "value": "215433", "label": "Prism Career Institute-Upper Darby" }, + { "value": "437750", "label": "Professional Golfers Career College" }, + { "value": "205054", "label": "Professional Skills Institute" }, + { "value": "455770", "label": "Providence Christian College" }, + { "value": "217402", "label": "Providence College" }, + { "value": "380438", "label": "Provo College" }, + { "value": "127884", "label": "Pueblo Community College" }, + { "value": "241766", "label": "Puerto Rico Conservatory of Music" }, + { "value": "107664", "label": "Pulaski Technical College" }, + { "value": "152248", "label": "Purdue University-Calumet Campus" }, + { "value": "243780", "label": "Purdue University-Main Campus" }, + { "value": "152266", "label": "Purdue University-North Central Campus" }, + { "value": "199412", "label": "Queens University of Charlotte" }, + { "value": "167525", "label": "Quincy College" }, + { "value": "148131", "label": "Quincy University" }, + { "value": "130217", "label": "Quinebaug Valley Community College" }, + { "value": "130226", "label": "Quinnipiac University" }, + { "value": "167534", "label": "Quinsigamond Community College" }, + { "value": "384421", "label": "Rabbi Jacob Joseph School" }, + { + "value": "194657", + "label": "Rabbinical Academy Mesivta Rabbi Chaim Berlin" + }, + { "value": "194693", "label": "Rabbinical College Beth Shraga" }, + { + "value": "194666", + "label": "Rabbinical College Bobover Yeshiva Bnei Zion" + }, + { "value": "186186", "label": "Rabbinical College of America" }, + { + "value": "194675", + "label": "Rabbinical College of Ch'san Sofer New York" + }, + { "value": "194736", "label": "Rabbinical College of Long Island" }, + { "value": "405854", "label": "Rabbinical College of Ohr Shimon Yisroel" }, + { "value": "484871", "label": "Rabbinical College Ohr Yisroel" }, + { "value": "205124", "label": "Rabbinical College Telshe" }, + { "value": "194763", "label": "Rabbinical Seminary of America" }, + { "value": "233277", "label": "Radford University" }, + { "value": "481119", "label": "Radians College" }, + { "value": "174604", "label": "Rainy River Community College" }, + { "value": "186201", "label": "Ramapo College of New Jersey" }, + { "value": "233301", "label": "Randolph College" }, + { "value": "199421", "label": "Randolph Community College" }, + { "value": "233295", "label": "Randolph-Macon College" }, + { "value": "227687", "label": "Ranger College" }, + { "value": "178891", "label": "Ranken Technical College" }, + { "value": "233310", "label": "Rappahannock Community College" }, + { "value": "186645", "label": "Raritan Valley Community College" }, + { "value": "138309", "label": "Rasmussen College-Florida" }, + { "value": "448673", "label": "Rasmussen College-Illinois" }, + { "value": "175014", "label": "Rasmussen College-Minnesota" }, + { "value": "200013", "label": "Rasmussen College-North Dakota" }, + { "value": "450571", "label": "Rasmussen College-Wisconsin" }, + { "value": "215585", "label": "Reading Area Community College" }, + { "value": "215619", "label": "Reconstructionist Rabbinical College" }, + { "value": "127909", "label": "Red Rocks Community College" }, + { "value": "207069", "label": "Redlands Community College" }, + { "value": "126605", "label": "Redstone College" }, + { "value": "209922", "label": "Reed College" }, + { "value": "117052", "label": "Reedley College" }, + { + "value": "215628", + "label": "Reformed Presbyterian Theological Seminary" + }, + { "value": "105659", "label": "Refrigeration School Inc" }, + { "value": "231651", "label": "Regent University" }, + { "value": "167598", "label": "Regis College" }, + { "value": "127918", "label": "Regis University" }, + { "value": "101994", "label": "Reid State Technical College" }, + { "value": "140872", "label": "Reinhardt University" }, + { "value": "475033", "label": "Relay Graduate School of Education" }, + { "value": "457183", "label": "Remington College of Nursing Orlando" }, + { "value": "440271", "label": "Remington College-Baton Rouge Campus" }, + { "value": "375416", "label": "Remington College-Cleveland Campus" }, + { "value": "223463", "label": "Remington College-Dallas Campus" }, + { "value": "377111", "label": "Remington College-Fort Worth Campus" }, + { "value": "460783", "label": "Remington College-Heathrow Campus" }, + { "value": "372958", "label": "Remington College-Honolulu Campus" }, + { "value": "380094", "label": "Remington College-Houston Campus" }, + { "value": "160524", "label": "Remington College-Lafayette Campus" }, + { "value": "438869", "label": "Remington College-Little Rock Campus" }, + { "value": "412599", "label": "Remington College-Memphis Campus" }, + { "value": "366535", "label": "Remington College-Mobile Campus" }, + { "value": "445249", "label": "Remington College-Nashville Campus" }, + { "value": "445203", "label": "Remington College-North Houston Campus" }, + { "value": "451866", "label": "Remington College-Shreveport Campus" }, + { "value": "135939", "label": "Remington College-Tampa Campus" }, + { "value": "148256", "label": "Rend Lake College" }, + { "value": "129428", "label": "Rensselaer Hartford Graduate Center Inc" }, + { "value": "194824", "label": "Rensselaer Polytechnic Institute" }, + { "value": "236382", "label": "Renton Technical College" }, + { "value": "178989", "label": "Research College of Nursing" }, + { "value": "149763", "label": "Resurrection University" }, + { "value": "217420", "label": "Rhode Island College" }, + { "value": "217493", "label": "Rhode Island School of Design" }, + { "value": "221351", "label": "Rhodes College" }, + { "value": "227757", "label": "Rice University" }, + { "value": "107743", "label": "Rich Mountain Community College" }, + { + "value": "233338", + "label": "Richard Bland College of the College of William and Mary" + }, + { "value": "227766", "label": "Richland College" }, + { "value": "148292", "label": "Richland Community College" }, + { "value": "199449", "label": "Richmond Community College" }, + { "value": "441104", "label": "Richmont Graduate University" }, + { "value": "186283", "label": "Rider University" }, + { "value": "175236", "label": "Ridgewater College" }, + { "value": "136774", "label": "Ringling College of Art and Design" }, + { "value": "475185", "label": "Rio Grande Bible Institute" }, + { "value": "121886", "label": "Rio Hondo College" }, + { "value": "105668", "label": "Rio Salado College" }, + { "value": "239628", "label": "Ripon College" }, + { "value": "436304", "label": "River Parishes Community College" }, + { "value": "183114", "label": "River Valley Community College" }, + { "value": "173063", "label": "Riverland Community College" }, + { "value": "121901", "label": "Riverside City College" }, + { "value": "233408", "label": "Riverside College of Health Careers" }, + { "value": "183211", "label": "Rivier University" }, + { "value": "221397", "label": "Roane State Community College" }, + { "value": "233426", "label": "Roanoke College" }, + { "value": "199467", "label": "Roanoke-Chowan Community College" }, + { "value": "215655", "label": "Robert Morris University" }, + { "value": "148335", "label": "Robert Morris University Illinois" }, + { "value": "194958", "label": "Roberts Wesleyan College" }, + { "value": "199476", "label": "Robeson Community College" }, + { "value": "170967", "label": "Rochester College" }, + { "value": "174738", "label": "Rochester Community and Technical College" }, + { "value": "195003", "label": "Rochester Institute of Technology" }, + { "value": "148380", "label": "Rock Valley College" }, + { "value": "195049", "label": "Rockefeller University" }, + { "value": "148405", "label": "Rockford University" }, + { "value": "179043", "label": "Rockhurst University" }, + { "value": "199485", "label": "Rockingham Community College" }, + { "value": "195058", "label": "Rockland Community College" }, + { "value": "180595", "label": "Rocky Mountain College" }, + { "value": "127945", "label": "Rocky Mountain College of Art and Design" }, + { + "value": "475495", + "label": "Rocky Mountain University of Health Professions" + }, + { "value": "480790", "label": "Rocky Vista University" }, + { "value": "217518", "label": "Roger Williams University" }, + { "value": "409616", "label": "Roger Williams University School of Law" }, + { "value": "207661", "label": "Rogers State University" }, + { "value": "209940", "label": "Rogue Community College" }, + { "value": "136950", "label": "Rollins College" }, + { "value": "148487", "label": "Roosevelt University" }, + { + "value": "145558", + "label": "Rosalind Franklin University of Medicine and Science" + }, + { "value": "207670", "label": "Rose State College" }, + { "value": "439899", "label": "Rosedale Bible College" }, + { "value": "215682", "label": "Rosedale Technical Institute" }, + { "value": "152318", "label": "Rose-Hulman Institute of Technology" }, + { "value": "445735", "label": "Roseman University of Health Sciences" }, + { "value": "215691", "label": "Rosemont College" }, + { "value": "452081", "label": "Ross College-Sylvania" }, + { "value": "183877", "label": "Rowan College at Burlington County" }, + { "value": "184791", "label": "Rowan College at Gloucester County" }, + { "value": "184782", "label": "Rowan University" }, + { "value": "199494", "label": "Rowan-Cabarrus Community College" }, + { "value": "167631", "label": "Roxbury Community College" }, + { "value": "148511", "label": "Rush University" }, + { "value": "176318", "label": "Rust College" }, + { "value": "186371", "label": "Rutgers University-Camden" }, + { "value": "186380", "label": "Rutgers University-New Brunswick" }, + { "value": "186399", "label": "Rutgers University-Newark" }, + { "value": "449506", "label": "SABER College" }, + { "value": "122180", "label": "Sacramento City College" }, + { "value": "172033", "label": "Sacred Heart Major Seminary" }, + { "value": "239637", "label": "Sacred Heart School of Theology" }, + { "value": "130253", "label": "Sacred Heart University" }, + { "value": "122205", "label": "Saddleback College" }, + { "value": "476948", "label": "SAE Institute of Technology-Atlanta" }, + { "value": "446525", "label": "SAE Institute of Technology-Nashville" }, + { "value": "410520", "label": "Sage College" }, + { "value": "441070", "label": "Saginaw Chippewa Tribal College" }, + { "value": "172051", "label": "Saginaw Valley State University" }, + { "value": "154235", "label": "Saint Ambrose University" }, + { "value": "183239", "label": "Saint Anselm College" }, + { "value": "149028", "label": "Saint Anthony College of Nursing" }, + { "value": "148876", "label": "Saint Augustine College" }, + { "value": "199582", "label": "Saint Augustine's University" }, + { "value": "157632", "label": "Saint Catharine College" }, + { "value": "216047", "label": "Saint Charles Borromeo Seminary-Overbrook" }, + { "value": "174783", "label": "Saint Cloud State University" }, + { "value": "227845", "label": "Saint Edward's University" }, + { "value": "195702", "label": "Saint Elizabeth College of Nursing-Utica" }, + { + "value": "148575", + "label": "Saint Francis Medical Center College of Nursing" + }, + { "value": "215743", "label": "Saint Francis University" }, + { "value": "195720", "label": "Saint John Fisher College" }, + { "value": "137272", "label": "Saint John Vianney College Seminary" }, + { "value": "137281", "label": "Saint Johns River State College" }, + { "value": "167677", "label": "Saint John's Seminary" }, + { "value": "174792", "label": "Saint Johns University" }, + { "value": "160409", "label": "Saint Joseph Seminary College" }, + { "value": "152363", "label": "Saint Josephs College" }, + { "value": "161518", "label": "Saint Joseph's College of Maine" }, + { "value": "195544", "label": "Saint Joseph's College-New York" }, + { "value": "215770", "label": "Saint Joseph's University" }, + { "value": "137032", "label": "Saint Leo University" }, + { "value": "179256", "label": "Saint Louis Christian College" }, + { "value": "179308", "label": "Saint Louis Community College" }, + { "value": "179159", "label": "Saint Louis University" }, + { "value": "179450", "label": "Saint Luke's College of Health Sciences" }, + { "value": "236452", "label": "Saint Martin's University" }, + { "value": "152381", "label": "Saint Mary-of-the-Woods College" }, + { "value": "152390", "label": "Saint Mary's College" }, + { "value": "123554", "label": "Saint Mary's College of California" }, + { "value": "174817", "label": "Saint Mary's University of Minnesota" }, + { "value": "152451", "label": "Saint Meinrad School of Theology" }, + { "value": "231059", "label": "Saint Michael's College" }, + { "value": "239716", "label": "Saint Norbert College" }, + { "value": "175041", "label": "Saint Paul College" }, + { "value": "179317", "label": "Saint Paul School of Theology" }, + { "value": "186432", "label": "Saint Peter's University" }, + { "value": "215798", "label": "Saint Vincent College" }, + { "value": "136701", "label": "Saint Vincent de Paul Regional Seminary" }, + { "value": "215813", "label": "Saint Vincent Seminary" }, + { + "value": "195580", + "label": "Saint Vladimirs Orthodox Theological Seminary" + }, + { "value": "148627", "label": "Saint Xavier University" }, + { "value": "199607", "label": "Salem College" }, + { "value": "186469", "label": "Salem Community College" }, + { "value": "237783", "label": "Salem International University" }, + { "value": "167729", "label": "Salem State University" }, + { "value": "155830", "label": "Salina Area Technical College" }, + { "value": "163851", "label": "Salisbury University" }, + { "value": "180647", "label": "Salish Kootenai College" }, + { "value": "230746", "label": "Salt Lake Community College" }, + { "value": "466523", "label": "Salter College-Chicopee" }, + { "value": "167738", "label": "Salter College-West Boylston" }, + { "value": "214564", "label": "Salus University" }, + { "value": "217536", "label": "Salve Regina University" }, + { "value": "227881", "label": "Sam Houston State University" }, + { "value": "195289", "label": "Samaritan Hospital School of Nursing" }, + { "value": "102049", "label": "Samford University" }, + { "value": "199625", "label": "Sampson Community College" }, + { "value": "122296", "label": "Samuel Merritt University" }, + { "value": "227924", "label": "San Antonio College" }, + { "value": "123527", "label": "San Bernardino Valley College" }, + { "value": "112084", "label": "San Diego Christian College" }, + { "value": "122339", "label": "San Diego City College" }, + { "value": "122375", "label": "San Diego Mesa College" }, + { "value": "122384", "label": "San Diego Miramar College" }, + { "value": "122409", "label": "San Diego State University" }, + { "value": "122454", "label": "San Francisco Art Institute" }, + { "value": "122506", "label": "San Francisco Conservatory of Music" }, + { "value": "122597", "label": "San Francisco State University" }, + { "value": "122603", "label": "San Francisco Theological Seminary" }, + { "value": "227979", "label": "San Jacinto Community College" }, + { "value": "122649", "label": "San Joaquin College of Law" }, + { "value": "122658", "label": "San Joaquin Delta College" }, + { "value": "122685", "label": "San Joaquin Valley College-Visalia" }, + { "value": "122746", "label": "San Jose City College" }, + { "value": "122755", "label": "San Jose State University" }, + { "value": "430670", "label": "San Juan Bautista School of Medicine" }, + { "value": "188100", "label": "San Juan College" }, + { "value": "199634", "label": "Sandhills Community College" }, + { + "value": "481535", + "label": "Sanford Burnham Prybis Medical Discovery Institute" + }, + { "value": "420495", "label": "Sanford-Brown College-Atlanta" }, + { "value": "475291", "label": "Sanford-Brown College-Brooklyn Center" }, + { "value": "146010", "label": "Sanford-Brown College-Chicago" }, + { "value": "404514", "label": "Sanford-Brown College-Dallas" }, + { "value": "179201", "label": "Sanford-Brown College-Fenton" }, + { "value": "404499", "label": "Sanford-Brown College-Houston" }, + { "value": "446792", "label": "Sanford-Brown College-Las Vegas" }, + { "value": "174394", "label": "Sanford-Brown College-Mendota Heights" }, + { "value": "420501", "label": "Sanford-Brown College-Middleburg Heights" }, + { "value": "456296", "label": "Sanford-Brown College-Online" }, + { "value": "440925", "label": "Sanford-Brown College-Orlando" }, + { + "value": "450465", + "label": "Sanford-Brown College-San Antonio-San Antonio" + }, + { "value": "446808", "label": "Sanford-Brown College-Seattle" }, + { "value": "134680", "label": "Sanford-Brown College-Tampa" }, + { "value": "234216", "label": "Sanford-Brown College-Tysons Corner" }, + { "value": "385008", "label": "Sanford-Brown Institute-Ft Lauderdale" }, + { "value": "404505", "label": "Sanford-Brown Institute-Jacksonville" }, + { "value": "121619", "label": "Santa Ana College" }, + { + "value": "122834", + "label": "Santa Barbara Business College-Bakersfield" + }, + { + "value": "122852", + "label": "Santa Barbara Business College-Santa Maria" + }, + { "value": "433420", "label": "Santa Barbara Business College-Ventura" }, + { "value": "122889", "label": "Santa Barbara City College" }, + { "value": "122931", "label": "Santa Clara University" }, + { "value": "137096", "label": "Santa Fe College" }, + { "value": "188137", "label": "Santa Fe Community College" }, + { "value": "188146", "label": "Santa Fe University of Art and Design" }, + { "value": "122977", "label": "Santa Monica College" }, + { "value": "123013", "label": "Santa Rosa Junior College" }, + { "value": "399212", "label": "Santiago Canyon College" }, + { "value": "195304", "label": "Sarah Lawrence College" }, + { "value": "148672", "label": "Sauk Valley Community College" }, + { "value": "140951", "label": "Savannah College of Art and Design" }, + { "value": "140960", "label": "Savannah State University" }, + { "value": "140942", "label": "Savannah Technical College" }, + { "value": "123095", "label": "Saybrook University" }, + { "value": "192156", "label": "SBI Campus-An Affiliate of Sanford-Brown" }, + { "value": "195322", "label": "Schenectady County Community College" }, + { "value": "404338", "label": "Schiller International University" }, + { "value": "143048", "label": "School of the Art Institute of Chicago" }, + { "value": "166984", "label": "School of the Museum of Fine Arts-Boston" }, + { "value": "197151", "label": "School of Visual Arts" }, + { "value": "172200", "label": "Schoolcraft College" }, + { "value": "228042", "label": "Schreiner University" }, + { "value": "105747", "label": "Scottsdale Community College" }, + { "value": "123165", "label": "Scripps College" }, + { "value": "236513", "label": "Seattle Central College" }, + { "value": "439914", "label": "Seattle Institute of Oriental Medicine" }, + { "value": "236577", "label": "Seattle Pacific University" }, + { "value": "236595", "label": "Seattle University" }, + { "value": "102058", "label": "Selma University" }, + { "value": "243498", "label": "Seminario Evangelico de Puerto Rico" }, + { "value": "207740", "label": "Seminole State College" }, + { "value": "137209", "label": "Seminole State College of Florida" }, + { "value": "232885", "label": "Sentara College of Health Sciences" }, + { "value": "475839", "label": "Sessions College for Professional Design" }, + { "value": "186584", "label": "Seton Hall University" }, + { "value": "215947", "label": "Seton Hill University" }, + { "value": "221519", "label": "Sewanee-The University of the South" }, + { + "value": "155858", + "label": "Seward County Community College and Area Technical School" + }, + { "value": "123280", "label": "Shasta Bible College and Graduate School" }, + { "value": "123299", "label": "Shasta College" }, + { "value": "199643", "label": "Shaw University" }, + { "value": "148821", "label": "Shawnee Community College" }, + { "value": "205443", "label": "Shawnee State University" }, + { "value": "102067", "label": "Shelton State Community College" }, + { "value": "233541", "label": "Shenandoah University" }, + { "value": "237792", "label": "Shepherd University" }, + { "value": "461485", "label": "Shepherds Theological Seminary" }, + { "value": "240666", "label": "Sheridan College" }, + { "value": "218751", "label": "Sherman College of Straight Chiropractic" }, + { "value": "480499", "label": "Shiloh University" }, + { "value": "148849", "label": "Shimer College" }, + { "value": "216010", "label": "Shippensburg University of Pennsylvania" }, + { "value": "195438", "label": "Sh'or Yoshuv Rabbinical College" }, + { "value": "236610", "label": "Shoreline Community College" }, + { "value": "107840", "label": "Shorter College" }, + { "value": "140988", "label": "Shorter University" }, + { + "value": "448309", + "label": "Shorter University-College of Adult & Professional Programs" + }, + { "value": "195474", "label": "Siena College" }, + { "value": "172264", "label": "Siena Heights University" }, + { "value": "123341", "label": "Sierra College" }, + { "value": "182458", "label": "Sierra Nevada College" }, + { "value": "239743", "label": "Silver Lake College of the Holy Family" }, + { "value": "167783", "label": "Simmons College" }, + { "value": "461759", "label": "Simmons College of Kentucky" }, + { "value": "154350", "label": "Simpson College" }, + { "value": "123457", "label": "Simpson University" }, + { "value": "205470", "label": "Sinclair Community College" }, + { "value": "219374", "label": "Sinte Gleska University" }, + { "value": "219240", "label": "Sioux Falls Seminary" }, + { "value": "219408", "label": "Sisseton Wahpeton College" }, + { "value": "231068", "label": "SIT Graduate Institute" }, + { "value": "200466", "label": "Sitting Bull College" }, + { "value": "236638", "label": "Skagit Valley College" }, + { "value": "195526", "label": "Skidmore College" }, + { "value": "123509", "label": "Skyline College" }, + { "value": "261931", "label": "Skyline College-Roanoke" }, + { "value": "216038", "label": "Slippery Rock University of Pennsylvania" }, + { "value": "167835", "label": "Smith College" }, + { "value": "102076", "label": "Snead State Community College" }, + { "value": "230597", "label": "Snow College" }, + { "value": "110778", "label": "Sofia University" }, + { "value": "163921", "label": "Sojourner-Douglass College" }, + { "value": "399911", "label": "Soka University of America" }, + { "value": "123563", "label": "Solano Community College" }, + { "value": "459356", "label": "SOLEX College" }, + { "value": "157711", "label": "Somerset Community College" }, + { "value": "123572", "label": "Sonoma State University" }, + { "value": "481094", "label": "Sotheby's Institute of Art-NY" }, + { "value": "107974", "label": "South Arkansas Community College" }, + { "value": "123633", "label": "South Baylo University" }, + { "value": "218733", "label": "South Carolina State University" }, + { "value": "173911", "label": "South Central College" }, + { + "value": "160913", + "label": "South Central Louisiana Technical College-Young Memorial Campus" + }, + { "value": "123642", "label": "South Coast College" }, + { "value": "220552", "label": "South College" }, + { "value": "198242", "label": "South College-Asheville" }, + { + "value": "219347", + "label": "South Dakota School of Mines and Technology" + }, + { "value": "219356", "label": "South Dakota State University" }, + { + "value": "366003", + "label": "South Florida Bible College and Theological Seminary" + }, + { "value": "137315", "label": "South Florida State College" }, + { "value": "482699", "label": "South Georgia State College" }, + { "value": "141006", "label": "South Georgia Technical College" }, + { + "value": "216083", + "label": "South Hills School of Business & Technology" + }, + { "value": "434061", "label": "South Louisiana Community College" }, + { "value": "105792", "label": "South Mountain Community College" }, + { "value": "197850", "label": "South Piedmont Community College" }, + { "value": "228158", "label": "South Plains College" }, + { "value": "236656", "label": "South Puget Sound Community College" }, + { "value": "236504", "label": "South Seattle College" }, + { "value": "149365", "label": "South Suburban College" }, + { "value": "409315", "label": "South Texas College" }, + { "value": "228194", "label": "South Texas College of Law" }, + { + "value": "468006", + "label": "South University-Accelerated Graduate Programs" + }, + { "value": "480073", "label": "South University-Austin" }, + { "value": "480082", "label": "South University-Cleveland" }, + { "value": "251312", "label": "South University-Columbia" }, + { "value": "481720", "label": "South University-High Point" }, + { "value": "101116", "label": "South University-Montgomery" }, + { "value": "468024", "label": "South University-Novi" }, + { "value": "459259", "label": "South University–Richmond" }, + { "value": "139579", "label": "South University-Savannah" }, + { "value": "475121", "label": "South University–Savannah Online" }, + { "value": "449898", "label": "South University-Tampa" }, + { + "value": "224776", + "label": "South University-The Art Institute of Dallas" + }, + { + "value": "468015", + "label": "South University-The Art Institute of Fort Worth" + }, + { "value": "459268", "label": "South University–Virginia Beach" }, + { "value": "133465", "label": "South University-West Palm Beach" }, + { + "value": "156338", + "label": "Southcentral Kentucky Community and Technical College" + }, + { "value": "107637", "label": "Southeast Arkansas College" }, + { "value": "181640", "label": "Southeast Community College Area" }, + { + "value": "157739", + "label": "Southeast Kentucky Community and Technical College" + }, + { + "value": "417734", + "label": "Southeast Missouri Hospital College of Nursing and Health Sciences" + }, + { "value": "179557", "label": "Southeast Missouri State University" }, + { "value": "219426", "label": "Southeast Technical Institute" }, + { "value": "176336", "label": "Southeastern Baptist College" }, + { "value": "199759", "label": "Southeastern Baptist Theological Seminary" }, + { "value": "102261", "label": "Southeastern Bible College" }, + { "value": "443270", "label": "Southeastern College-Jacksonville" }, + { "value": "428170", "label": "Southeastern College-West Palm Beach" }, + { + "value": "154378", + "label": "Southeastern Community College-West Burlington" + }, + { "value": "199722", "label": "Southeastern Community College-Whiteville" }, + { "value": "148937", "label": "Southeastern Illinois College" }, + { "value": "160612", "label": "Southeastern Louisiana University" }, + { "value": "207847", "label": "Southeastern Oklahoma State University" }, + { "value": "368911", "label": "Southeastern Technical College" }, + { "value": "137564", "label": "Southeastern University" }, + { "value": "221661", "label": "Southern Adventist University" }, + { "value": "107983", "label": "Southern Arkansas University Main Campus" }, + { "value": "107992", "label": "Southern Arkansas University Tech" }, + { + "value": "123952", + "label": "Southern California Institute of Architecture" + }, + { + "value": "399869", + "label": "Southern California Institute of Technology" + }, + { "value": "117575", "label": "Southern California Seminary" }, + { + "value": "117672", + "label": "Southern California University of Health Sciences" + }, + { "value": "459222", "label": "Southern California University SOMA" }, + { "value": "221670", "label": "Southern College of Optometry" }, + { "value": "130493", "label": "Southern Connecticut State University" }, + { "value": "139986", "label": "Southern Crescent Technical College" }, + { "value": "149222", "label": "Southern Illinois University-Carbondale" }, + { "value": "149231", "label": "Southern Illinois University-Edwardsville" }, + { "value": "161545", "label": "Southern Maine Community College" }, + { "value": "228246", "label": "Southern Methodist University" }, + { "value": "206862", "label": "Southern Nazarene University" }, + { "value": "183026", "label": "Southern New Hampshire University" }, + { "value": "210146", "label": "Southern Oregon University" }, + { "value": "141097", "label": "Southern Polytechnic State University" }, + { "value": "205966", "label": "Southern State Community College" }, + { "value": "366553", "label": "Southern Technical College-Fort Myers" }, + { "value": "446552", "label": "Southern Technical College-Orlando" }, + { "value": "251260", "label": "Southern Union State Community College" }, + { "value": "160621", "label": "Southern University and A & M College" }, + { "value": "160630", "label": "Southern University at New Orleans" }, + { "value": "160649", "label": "Southern University at Shreveport" }, + { "value": "440916", "label": "Southern University Law Center" }, + { "value": "230603", "label": "Southern Utah University" }, + { "value": "231086", "label": "Southern Vermont College" }, + { "value": "233611", "label": "Southern Virginia University" }, + { "value": "217776", "label": "Southern Wesleyan University" }, + { + "value": "237817", + "label": "Southern West Virginia Community and Technical College" + }, + { + "value": "233082", + "label": "Southside Regional Medical Center Professional Schools" + }, + { "value": "233639", "label": "Southside Virginia Community College" }, + { "value": "413644", "label": "Southwest Acupuncture College-Albuquerque" }, + { "value": "436261", "label": "Southwest Acupuncture College-Boulder" }, + { "value": "366605", "label": "Southwest Acupuncture College-Santa Fe" }, + { "value": "179326", "label": "Southwest Baptist University" }, + { + "value": "420246", + "label": "Southwest College of Naturopathic Medicine & Health Sciences" + }, + { + "value": "382911", + "label": "Southwest Collegiate Institute for the Deaf" + }, + { "value": "141158", "label": "Southwest Georgia Technical College" }, + { "value": "442879", "label": "Southwest Institute of Healing Arts" }, + { "value": "175078", "label": "Southwest Minnesota State University" }, + { "value": "176354", "label": "Southwest Mississippi Community College" }, + { "value": "221485", "label": "Southwest Tennessee Community College" }, + { "value": "228316", "label": "Southwest Texas Junior College" }, + { "value": "451556", "label": "Southwest University at El Paso" }, + { + "value": "402776", + "label": "Southwest University of Visual Arts-Albuquerque" + }, + { + "value": "104188", + "label": "Southwest University of Visual Arts-Tucson" + }, + { "value": "233648", "label": "Southwest Virginia Community College" }, + { "value": "239910", "label": "Southwest Wisconsin Technical College" }, + { "value": "228468", "label": "Southwestern Adventist University" }, + { "value": "228325", "label": "Southwestern Assemblies of God University" }, + { "value": "228486", "label": "Southwestern Christian College" }, + { "value": "207856", "label": "Southwestern Christian University" }, + { "value": "123800", "label": "Southwestern College-Chula Vista" }, + { "value": "188207", "label": "Southwestern College-Santa Fe" }, + { "value": "155900", "label": "Southwestern College-Winfield" }, + { "value": "154396", "label": "Southwestern Community College-Creston" }, + { "value": "199731", "label": "Southwestern Community College-Sylva" }, + { "value": "143215", "label": "Southwestern Illinois College" }, + { "value": "188216", "label": "Southwestern Indian Polytechnic Institute" }, + { "value": "123970", "label": "Southwestern Law School" }, + { "value": "172307", "label": "Southwestern Michigan College" }, + { "value": "207865", "label": "Southwestern Oklahoma State University" }, + { "value": "210155", "label": "Southwestern Oregon Community College" }, + { "value": "228343", "label": "Southwestern University" }, + { "value": "160579", "label": "SOWELA Technical Community College" }, + { "value": "157757", "label": "Spalding University" }, + { + "value": "207254", + "label": "Spartan College of Aeronautics and Technology" + }, + { "value": "218830", "label": "Spartanburg Community College" }, + { "value": "218821", "label": "Spartanburg Methodist College" }, + { "value": "141060", "label": "Spelman College" }, + { "value": "433563", "label": "Spencerian College-Lexington" }, + { "value": "157766", "label": "Spencerian College-Louisville" }, + { "value": "148982", "label": "Spertus College" }, + { "value": "236692", "label": "Spokane Community College" }, + { "value": "236708", "label": "Spokane Falls Community College" }, + { "value": "148991", "label": "Spoon River College" }, + { "value": "172334", "label": "Spring Arbor University" }, + { "value": "102234", "label": "Spring Hill College" }, + { "value": "167899", "label": "Springfield College" }, + { + "value": "475273", + "label": "Springfield College-School of Professional and Continuing Studies" + }, + { "value": "167905", "label": "Springfield Technical Community College" }, + { "value": "199698", "label": "St Andrews University" }, + { + "value": "195155", + "label": "St Bernard's School of Theology and Ministry" + }, + { "value": "195164", "label": "St Bonaventure University" }, + { "value": "175005", "label": "St Catherine University" }, + { "value": "262031", "label": "St Charles Community College" }, + { "value": "172291", "label": "St Clair County Community College" }, + { "value": "174756", "label": "St Cloud Technical and Community College" }, + { "value": "195173", "label": "St Francis College" }, + { "value": "163976", "label": "St John's College" }, + { "value": "123855", "label": "St John's Seminary" }, + { "value": "195809", "label": "St John's University-New York" }, + { "value": "183248", "label": "St Joseph School of Nursing-Nashua" }, + { + "value": "195191", + "label": "St Joseph's College of Nursing at St Joseph's Hospital Health Center" + }, + { "value": "195216", "label": "St Lawrence University" }, + { "value": "442426", "label": "St Louis College of Health Careers-Fenton" }, + { + "value": "179511", + "label": "St Louis College of Health Careers-St Louis" + }, + { "value": "179265", "label": "St Louis College of Pharmacy" }, + { "value": "154262", "label": "St Luke's College" }, + { "value": "163912", "label": "St Mary's College of Maryland" }, + { "value": "228149", "label": "St Mary's University" }, + { "value": "174844", "label": "St Olaf College" }, + { "value": "189811", "label": "St Paul's School of Nursing-Queens" }, + { "value": "195784", "label": "St Paul's School of Nursing-Staten Island" }, + { "value": "137078", "label": "St Petersburg College" }, + { "value": "227854", "label": "St Philip's College" }, + { "value": "137476", "label": "St Thomas University" }, + { "value": "130448", "label": "St Vincent's College" }, + { "value": "207689", "label": "St. Gregory's University" }, + { "value": "245652", "label": "St. John's College" }, + { "value": "148593", "label": "St. John's College-Department of Nursing" }, + { "value": "195243", "label": "St. Thomas Aquinas College" }, + { "value": "446561", "label": "Stanbridge College" }, + { + "value": "483814", + "label": "Standard Healthcare Services-College of Nursing" + }, + { "value": "243744", "label": "Stanford University" }, + { "value": "199740", "label": "Stanly Community College" }, + { "value": "205841", "label": "Stark State College" }, + { "value": "123916", "label": "Starr King School for Ministry" }, + { "value": "135391", "label": "State College of Florida-Manatee-Sarasota" }, + { "value": "179539", "label": "State Fair Community College" }, + { "value": "177977", "label": "State Technical College of Missouri" }, + { "value": "196176", "label": "State University of New York at New Paltz" }, + { "value": "448600", "label": "Stautzenberger College-Brecksville" }, + { "value": "205887", "label": "Stautzenberger College-Maumee" }, + { "value": "228431", "label": "Stephen F Austin State University" }, + { "value": "179548", "label": "Stephens College" }, + { "value": "231095", "label": "Sterling College-Craftsbury Common" }, + { "value": "155937", "label": "Sterling College-Sterling" }, + { "value": "137546", "label": "Stetson University" }, + { "value": "186867", "label": "Stevens Institute of Technology" }, + { "value": "460899", "label": "Stevens-Henager College-Boise" }, + { "value": "474906", "label": "Stevens-Henager College-Idaho Falls" }, + { "value": "446677", "label": "Stevens-Henager College-Logan" }, + { "value": "438151", "label": "Stevens-Henager College-Murray" }, + { "value": "230630", "label": "Stevens-Henager College-Orem" }, + { "value": "477950", "label": "Stevens-Henager College-St. George" }, + { "value": "230621", "label": "Stevens-Henager College-West Haven" }, + { "value": "164173", "label": "Stevenson University" }, + { "value": "178767", "label": "Stevens-The Institute of Business & Arts" }, + { "value": "102270", "label": "Stillman College" }, + { "value": "186876", "label": "Stockton University" }, + { "value": "366340", "label": "Stone Child College" }, + { "value": "167996", "label": "Stonehill College" }, + { "value": "196097", "label": "Stony Brook University" }, + { "value": "438498", "label": "Stratford University" }, + { "value": "450377", "label": "Strayer University-Alabama" }, + { "value": "458885", "label": "Strayer University-Arkansas" }, + { "value": "450298", "label": "Strayer University-Delaware" }, + { "value": "131803", "label": "Strayer University-District of Columbia" }, + { "value": "449038", "label": "Strayer University-Florida" }, + { "value": "458919", "label": "Strayer University-Georgia" }, + { "value": "459994", "label": "Strayer University-Global Region" }, + { "value": "458937", "label": "Strayer University-Louisiana" }, + { "value": "430184", "label": "Strayer University-Maryland" }, + { "value": "458955", "label": "Strayer University-Mississippi" }, + { "value": "453215", "label": "Strayer University-New Jersey" }, + { "value": "453163", "label": "Strayer University-North Carolina" }, + { "value": "443784", "label": "Strayer University-Pennsylvania" }, + { "value": "458964", "label": "Strayer University-South Carolina" }, + { "value": "443766", "label": "Strayer University-Tennessee" }, + { "value": "458973", "label": "Strayer University-Texas" }, + { "value": "233684", "label": "Strayer University-Virginia" }, + { "value": "456621", "label": "Strayer University-West Virginia" }, + { "value": "366395", "label": "Suffolk County Community College" }, + { "value": "168005", "label": "Suffolk University" }, + { "value": "228501", "label": "Sul Ross State University" }, + { "value": "157270", "label": "Sullivan College of Technology and Design" }, + { "value": "195988", "label": "Sullivan County Community College" }, + { "value": "157793", "label": "Sullivan University" }, + { + "value": "447953", + "label": "SUM Bible College and Theological Seminary" + }, + { "value": "181543", "label": "Summit Christian College" }, + { "value": "208512", "label": "Sumner College" }, + { "value": "196060", "label": "SUNY at Albany" }, + { "value": "196079", "label": "SUNY at Binghamton" }, + { "value": "196158", "label": "SUNY at Fredonia" }, + { "value": "196219", "label": "SUNY at Purchase College" }, + { "value": "189547", "label": "SUNY Broome Community College" }, + { "value": "196130", "label": "SUNY Buffalo State" }, + { "value": "196121", "label": "SUNY College at Brockport" }, + { "value": "196149", "label": "SUNY College at Cortland" }, + { "value": "196167", "label": "SUNY College at Geneseo" }, + { "value": "196237", "label": "SUNY College at Old Westbury" }, + { "value": "196194", "label": "SUNY College at Oswego" }, + { "value": "196246", "label": "SUNY College at Plattsburgh" }, + { "value": "196200", "label": "SUNY College at Potsdam" }, + { + "value": "196033", + "label": "SUNY College of Agriculture and Technology at Cobleskill" + }, + { + "value": "196103", + "label": "SUNY College of Environmental Science and Forestry" + }, + { "value": "196228", "label": "SUNY College of Optometry" }, + { "value": "196006", "label": "SUNY College of Technology at Alfred" }, + { "value": "196015", "label": "SUNY College of Technology at Canton" }, + { "value": "196024", "label": "SUNY College of Technology at Delhi" }, + { "value": "196255", "label": "SUNY Downstate Medical Center" }, + { "value": "196264", "label": "SUNY Empire State College" }, + { "value": "196291", "label": "SUNY Maritime College" }, + { "value": "196185", "label": "SUNY Oneonta" }, + { "value": "196112", "label": "SUNY Polytechnic Institute" }, + { "value": "197294", "label": "SUNY Westchester Community College" }, + { "value": "199768", "label": "Surry Community College" }, + { "value": "216278", "label": "Susquehanna University" }, + { "value": "247603", "label": "Sussex County Community College" }, + { "value": "216287", "label": "Swarthmore College" }, + { + "value": "196389", + "label": "Swedish Institute a College of Health Sciences" + }, + { "value": "233718", "label": "Sweet Briar College" }, + { "value": "196413", "label": "Syracuse University" }, + { "value": "155973", "label": "Tabor College" }, + { "value": "236753", "label": "Tacoma Community College" }, + { "value": "124113", "label": "Taft College" }, + { "value": "454689", "label": "Taft University System" }, + { "value": "102298", "label": "Talladega College" }, + { "value": "137759", "label": "Tallahassee Community College" }, + { "value": "137777", "label": "Talmudic College of Florida" }, + { "value": "186900", "label": "Talmudical Academy-New Jersey" }, + { "value": "196440", "label": "Talmudical Institute of Upstate New York" }, + { "value": "451404", "label": "Talmudical Seminary of Bobov" }, + { "value": "196431", "label": "Talmudical Seminary Oholei Torah" }, + { "value": "216311", "label": "Talmudical Yeshiva of Philadelphia" }, + { "value": "228529", "label": "Tarleton State University" }, + { "value": "228547", "label": "Tarrant County College District" }, + { "value": "149310", "label": "Taylor Business Institute" }, + { "value": "449524", "label": "Taylor College" }, + { "value": "152530", "label": "Taylor University" }, + { "value": "196468", "label": "Teachers College at Columbia University" }, + { "value": "196477", "label": "Technical Career Institutes" }, + { "value": "217712", "label": "Technical College of the Lowcountry" }, + { "value": "149329", "label": "Telshe Yeshiva-Chicago" }, + { "value": "228608", "label": "Temple College" }, + { "value": "216339", "label": "Temple University" }, + { "value": "221838", "label": "Tennessee State University" }, + { "value": "221847", "label": "Tennessee Technological University" }, + { "value": "221856", "label": "Tennessee Temple University" }, + { "value": "221731", "label": "Tennessee Wesleyan College" }, + { "value": "206011", "label": "Terra State Community College" }, + { "value": "228699", "label": "Texarkana College" }, + { "value": "226152", "label": "Texas A & M International University" }, + { "value": "483036", "label": "Texas A & M University-Central Texas" }, + { "value": "228723", "label": "Texas A & M University-College Station" }, + { "value": "224554", "label": "Texas A & M University-Commerce" }, + { "value": "224147", "label": "Texas A & M University-Corpus Christi" }, + { "value": "228705", "label": "Texas A & M University-Kingsville" }, + { "value": "224545", "label": "Texas A & M University-Texarkana" }, + { "value": "228866", "label": "Texas Chiropractic College Foundation Inc" }, + { "value": "228875", "label": "Texas Christian University" }, + { "value": "228884", "label": "Texas College" }, + { "value": "441487", "label": "Texas County Technical College" }, + { "value": "430704", "label": "Texas Health and Science University" }, + { "value": "228981", "label": "Texas Lutheran University" }, + { "value": "229063", "label": "Texas Southern University" }, + { "value": "229319", "label": "Texas State Technical College-Harlingen" }, + { "value": "408394", "label": "Texas State Technical College-Marshall" }, + { "value": "228680", "label": "Texas State Technical College-Waco" }, + { "value": "229328", "label": "Texas State Technical College-West Texas" }, + { "value": "228459", "label": "Texas State University" }, + { "value": "229115", "label": "Texas Tech University" }, + { + "value": "229337", + "label": "Texas Tech University Health Sciences Center" + }, + { "value": "229160", "label": "Texas Wesleyan University" }, + { "value": "229179", "label": "Texas Woman's University" }, + { "value": "216296", "label": "Thaddeus Stevens College of Technology" }, + { "value": "138813", "label": "The Art Institute of Atlanta" }, + { "value": "451820", "label": "The Art Institute of Austin" }, + { "value": "450085", "label": "The Art Institute of Charleston" }, + { "value": "197832", "label": "The Art Institute of Charlotte" }, + { + "value": "200624", + "label": "The Art Institute of Cincinnati-AIC College of Design" + }, + { "value": "126702", "label": "The Art Institute of Colorado" }, + { "value": "132338", "label": "The Art Institute of Fort Lauderdale" }, + { "value": "222938", "label": "The Art Institute of Houston" }, + { "value": "448345", "label": "The Art Institute of Indianapolis" }, + { "value": "182111", "label": "The Art Institute of Las Vegas" }, + { "value": "451796", "label": "The Art Institute of Michigan" }, + { "value": "365055", "label": "The Art Institute of New York City" }, + { "value": "446668", "label": "The Art Institute of Ohio-Cincinnati" }, + { "value": "210942", "label": "The Art Institute of Philadelphia" }, + { "value": "428444", "label": "The Art Institute of Phoenix" }, + { "value": "210960", "label": "The Art Institute of Pittsburgh" }, + { + "value": "451662", + "label": "The Art Institute of Pittsburgh-Online Division" + }, + { "value": "208239", "label": "The Art Institute of Portland" }, + { "value": "452027", "label": "The Art Institute of Raleigh-Durham" }, + { "value": "450049", "label": "The Art Institute of Salt Lake City" }, + { "value": "458982", "label": "The Art Institute of San Antonio" }, + { "value": "234492", "label": "The Art Institute of Seattle" }, + { "value": "482398", "label": "The Art Institute of St Louis" }, + { "value": "449010", "label": "The Art Institute of Tennessee-Nashville" }, + { "value": "444927", "label": "The Art Institute of Tucson" }, + { "value": "458496", "label": "The Art Institute of Virginia Beach" }, + { "value": "440341", "label": "The Art Institute of Washington" }, + { "value": "456010", "label": "The Art Institute of Washington-Dulles" }, + { "value": "470092", "label": "The Art Institute of Wisconsin" }, + { + "value": "452018", + "label": "The Art Institutes International–Kansas City" + }, + { + "value": "173887", + "label": "The Art Institutes International-Minnesota" + }, + { "value": "210906", "label": "The Art Institutes of York-PA" }, + { "value": "132408", "label": "The Baptist College of Florida" }, + { "value": "164933", "label": "The Boston Conservatory" }, + { "value": "111188", "label": "The California Maritime Academy" }, + { + "value": "143978", + "label": "The Chicago School of Professional Psychology at Chicago" + }, + { + "value": "455433", + "label": "The Chicago School of Professional Psychology at Irvine" + }, + { + "value": "455664", + "label": "The Chicago School of Professional Psychology at Los Angeles" + }, + { + "value": "459745", + "label": "The Chicago School of Professional Psychology at Washington DC" + }, + { + "value": "455682", + "label": "The Chicago School of Professional Psychology at Westwood" + }, + { + "value": "201821", + "label": "The Christ College of Nursing and Health Sciences" + }, + { + "value": "437635", + "label": "The College of Health Care Professions-Austin" + }, + { + "value": "480824", + "label": "The College of Health Care Professions-Dallas" + }, + { + "value": "480833", + "label": "The College of Health Care Professions-Fort Worth" + }, + { "value": "142294", "label": "The College of Idaho" }, + { "value": "187134", "label": "The College of New Jersey" }, + { "value": "193645", "label": "The College of New Rochelle" }, + { "value": "195234", "label": "The College of Saint Rose" }, + { "value": "174899", "label": "The College of Saint Scholastica" }, + { "value": "197285", "label": "The College of Westchester" }, + { "value": "206589", "label": "The College of Wooster" }, + { "value": "456542", "label": "The Commonwealth Medical College" }, + { "value": "434672", "label": "The Community College of Baltimore County" }, + { "value": "430485", "label": "The Creative Center" }, + { "value": "235167", "label": "The Evergreen State College" }, + { "value": "191320", "label": "The General Theological Seminary" }, + { "value": "148177", "label": "The Illinois Institute of Art-Chicago" }, + { "value": "428286", "label": "The Illinois Institute of Art-Schaumburg" }, + { "value": "146241", "label": "The John Marshall Law School" }, + { "value": "192110", "label": "The Juilliard School" }, + { "value": "454184", "label": "The King’s College" }, + { "value": "439701", "label": "The King's University" }, + { "value": "161208", "label": "The Landing School" }, + { "value": "213598", "label": "The Lincoln University" }, + { "value": "117751", "label": "The Master's College and Seminary" }, + { "value": "119544", "label": "The National Hispanic University" }, + { "value": "167057", "label": "The New England Conservatory of Music" }, + { "value": "167321", "label": "The New England Institute of Art" }, + { "value": "193654", "label": "The New School" }, + { + "value": "215637", + "label": "The Restaurant School at Walnut Hill College" + }, + { "value": "448804", "label": "The Robert B Miller College" }, + { "value": "195128", "label": "The Sage Colleges" }, + { + "value": "475228", + "label": "The Santa Barbara and Ventura Colleges of Law–Santa Barbara" + }, + { + "value": "125037", + "label": "The Santa Barbara and Ventura Colleges of Law-Ventura" + }, + { + "value": "441131", + "label": "The Seattle School of Theology & Psychology" + }, + { "value": "157748", "label": "The Southern Baptist Theological Seminary" }, + { "value": "100751", "label": "The University of Alabama" }, + { "value": "202763", "label": "The University of Findlay" }, + { "value": "180489", "label": "The University of Montana" }, + { "value": "180692", "label": "The University of Montana-Western" }, + { "value": "137847", "label": "The University of Tampa" }, + { "value": "221740", "label": "The University of Tennessee-Chattanooga" }, + { "value": "221759", "label": "The University of Tennessee-Knoxville" }, + { "value": "221768", "label": "The University of Tennessee-Martin" }, + { + "value": "227368", + "label": "The University of Texas - Rio Grande Valley" + }, + { "value": "228769", "label": "The University of Texas at Arlington" }, + { "value": "228778", "label": "The University of Texas at Austin" }, + { "value": "228787", "label": "The University of Texas at Dallas" }, + { "value": "228796", "label": "The University of Texas at El Paso" }, + { "value": "229027", "label": "The University of Texas at San Antonio" }, + { "value": "228802", "label": "The University of Texas at Tyler" }, + { + "value": "229300", + "label": "The University of Texas Health Science Center at Houston" + }, + { + "value": "228644", + "label": "The University of Texas Health Science Center at San Antonio" + }, + { + "value": "416801", + "label": "The University of Texas MD Anderson Cancer Center" + }, + { "value": "228653", "label": "The University of Texas Medical Branch" }, + { + "value": "229018", + "label": "The University of Texas of the Permian Basin" + }, + { "value": "215105", "label": "The University of the Arts" }, + { + "value": "233897", + "label": "The University of Virginia's College at Wise" + }, + { "value": "138354", "label": "The University of West Florida" }, + { "value": "126012", "label": "The Wright Institute" }, + { "value": "216357", "label": "Thiel College" }, + { "value": "124292", "label": "Thomas Aquinas College" }, + { "value": "161563", "label": "Thomas College" }, + { "value": "187046", "label": "Thomas Edison State University" }, + { "value": "126049", "label": "Thomas Jefferson School of Law" }, + { "value": "216366", "label": "Thomas Jefferson University" }, + { "value": "157809", "label": "Thomas More College" }, + { "value": "183275", "label": "Thomas More College of Liberal Arts" }, + { "value": "233754", "label": "Thomas Nelson Community College" }, + { "value": "141167", "label": "Thomas University" }, + { "value": "129808", "label": "Three Rivers Community College-Norwich" }, + { + "value": "179645", + "label": "Three Rivers Community College-Poplar Bluff" + }, + { "value": "103778", "label": "Thunderbird School of Global Management" }, + { "value": "233772", "label": "Tidewater Community College" }, + { "value": "206048", "label": "Tiffin University" }, + { "value": "420723", "label": "Tillamook Bay Community College" }, + { "value": "141185", "label": "Toccoa Falls College" }, + { "value": "442781", "label": "Tohono O'Odham Community College" }, + { "value": "196565", "label": "Tompkins Cortland Community College" }, + { "value": "196583", "label": "Torah Temimah Talmudical Seminary" }, + { "value": "176406", "label": "Tougaloo College" }, + { "value": "196592", "label": "Touro College" }, + { "value": "459736", "label": "Touro University California" }, + { "value": "459824", "label": "Touro University Nevada" }, + { "value": "459727", "label": "Touro University Worldwide" }, + { "value": "164076", "label": "Towson University" }, + { "value": "157818", "label": "Transylvania University" }, + { "value": "210234", "label": "Treasure Valley Community College" }, + { "value": "221892", "label": "Trevecca Nazarene University" }, + { "value": "448859", "label": "Triangle Tech Inc-Bethlehem" }, + { "value": "216454", "label": "Triangle Tech Inc-Dubois" }, + { "value": "216427", "label": "Triangle Tech Inc-Erie" }, + { "value": "216445", "label": "Triangle Tech Inc-Greensburg" }, + { "value": "216436", "label": "Triangle Tech Inc-Pittsburgh" }, + { "value": "443377", "label": "Triangle Tech Inc-Sunbury" }, + { "value": "460747", "label": "Tribeca Flashpoint College" }, + { "value": "199795", "label": "Tri-County Community College" }, + { "value": "218885", "label": "Tri-County Technical College" }, + { "value": "218894", "label": "Trident Technical College" }, + { "value": "450979", "label": "Trident University International" }, + { "value": "152567", "label": "Trine University" }, + { + "value": "414878", + "label": "Trine University-Regional/Non-Traditional Campuses" + }, + { "value": "128258", "label": "Trinidad State Junior College" }, + { "value": "137953", "label": "Trinity Baptist College" }, + { "value": "200484", "label": "Trinity Bible College" }, + { "value": "149505", "label": "Trinity Christian College" }, + { "value": "130590", "label": "Trinity College" }, + { "value": "137962", "label": "Trinity College of Florida" }, + { + "value": "146755", + "label": "Trinity College of Nursing & Health Sciences" + }, + { "value": "216463", "label": "Trinity Episcopal School for Ministry" }, + { "value": "135610", "label": "Trinity International University-Florida" }, + { "value": "149514", "label": "Trinity International University-Illinois" }, + { "value": "123448", "label": "Trinity Law School" }, + { "value": "235769", "label": "Trinity Lutheran College" }, + { "value": "206215", "label": "Trinity Lutheran Seminary" }, + { "value": "229267", "label": "Trinity University" }, + { "value": "225308", "label": "Trinity Valley Community College" }, + { "value": "131876", "label": "Trinity Washington University" }, + { "value": "206154", "label": "Tri-State Bible College" }, + { "value": "130581", "label": "Tri-State College of Acupuncture" }, + { "value": "149532", "label": "Triton College" }, + { "value": "196653", "label": "Trocaire College" }, + { "value": "102368", "label": "Troy University" }, + { "value": "182500", "label": "Truckee Meadows Community College" }, + { "value": "141237", "label": "Truett-McConnell College" }, + { "value": "178615", "label": "Truman State University" }, + { "value": "206224", "label": "Trumbull Business College" }, + { "value": "168148", "label": "Tufts University" }, + { "value": "160755", "label": "Tulane University of Louisiana" }, + { "value": "207935", "label": "Tulsa Community College" }, + { "value": "207962", "label": "Tulsa Welding School-Tulsa-Tulsa" }, + { "value": "130606", "label": "Tunxis Community College" }, + { "value": "200527", "label": "Turtle Mountain Community College" }, + { "value": "221953", "label": "Tusculum College" }, + { "value": "102377", "label": "Tuskegee University" }, + { "value": "229355", "label": "Tyler Junior College" }, + { "value": "196699", "label": "Ulster County Community College" }, + { "value": "441371", "label": "Ultimate Medical Academy-Clearwater" }, + { "value": "450173", "label": "Ultimate Medical Academy-Tampa" }, + { "value": "481252", "label": "Ultrasound Medical Institute" }, + { "value": "210270", "label": "Umpqua Community College" }, + { "value": "246789", "label": "Unification Theological Seminary" }, + { "value": "157863", "label": "Union College-Barbourville" }, + { "value": "181738", "label": "Union College-Lincoln" }, + { "value": "196866", "label": "Union College-Schenectady" }, + { "value": "187198", "label": "Union County College" }, + { "value": "446932", "label": "Union Graduate College" }, + { "value": "206279", "label": "Union Institute & University" }, + { "value": "233842", "label": "Union Presbyterian Seminary" }, + { + "value": "196884", + "label": "Union Theological Seminary in the City of New York" + }, + { "value": "221971", "label": "Union University" }, + { + "value": "124681", + "label": "United Education Institute-Huntington Park Campus" + }, + { "value": "128328", "label": "United States Air Force Academy" }, + { "value": "130624", "label": "United States Coast Guard Academy" }, + { "value": "197027", "label": "United States Merchant Marine Academy" }, + { "value": "197036", "label": "United States Military Academy" }, + { "value": "164155", "label": "United States Naval Academy" }, + { "value": "102395", "label": "United States Sports Academy" }, + { "value": "447050", "label": "United States University" }, + { "value": "197018", "label": "United Talmudical Seminary" }, + { "value": "206288", "label": "United Theological Seminary" }, + { + "value": "175139", + "label": "United Theological Seminary of the Twin Cities" + }, + { "value": "200554", "label": "United Tribes Technical College" }, + { "value": "459204", "label": "Unitek College" }, + { "value": "161572", "label": "Unity College" }, + { "value": "446598", "label": "Universal College of Healing Arts" }, + { + "value": "106041", + "label": "Universal Technical Institute of Arizona Inc" + }, + { + "value": "376385", + "label": "Universal Technology College of Puerto Rico" + }, + { "value": "241191", "label": "Universidad Adventista de las Antillas" }, + { "value": "241225", "label": "Universidad Central de Bayamon" }, + { "value": "243568", "label": "Universidad Central Del Caribe" }, + { "value": "243346", "label": "Universidad Del Este" }, + { "value": "243443", "label": "Universidad del Sagrado Corazon" }, + { "value": "243601", "label": "Universidad Del Turabo" }, + { "value": "475811", "label": "Universidad Internacional Iberoamericana" }, + { "value": "241739", "label": "Universidad Metropolitana" }, + { "value": "441690", "label": "Universidad Pentecostal Mizpa" }, + { "value": "243577", "label": "Universidad Politecnica de Puerto Rico" }, + { "value": "241614", "label": "Universidad Teologica del Caribe" }, + { "value": "196088", "label": "University at Buffalo" }, + { "value": "363934", "label": "University of Advancing Technology" }, + { "value": "200800", "label": "University of Akron Main Campus" }, + { "value": "200846", "label": "University of Akron Wayne College" }, + { "value": "100663", "label": "University of Alabama at Birmingham" }, + { "value": "100706", "label": "University of Alabama in Huntsville" }, + { "value": "102553", "label": "University of Alaska Anchorage" }, + { "value": "102614", "label": "University of Alaska Fairbanks" }, + { "value": "102632", "label": "University of Alaska Southeast" }, + { "value": "442930", "label": "University of Antelope Valley" }, + { "value": "104179", "label": "University of Arizona" }, + { "value": "106397", "label": "University of Arkansas" }, + { "value": "106245", "label": "University of Arkansas at Little Rock" }, + { "value": "106485", "label": "University of Arkansas at Monticello" }, + { "value": "106412", "label": "University of Arkansas at Pine Bluff" }, + { + "value": "106999", + "label": "University of Arkansas Community College-Batesville" + }, + { + "value": "107725", + "label": "University of Arkansas Community College-Hope" + }, + { + "value": "107585", + "label": "University of Arkansas Community College-Morrilton" + }, + { + "value": "106263", + "label": "University of Arkansas for Medical Sciences" + }, + { "value": "108092", "label": "University of Arkansas-Fort Smith" }, + { "value": "161873", "label": "University of Baltimore" }, + { "value": "128744", "label": "University of Bridgeport" }, + { "value": "110635", "label": "University of California-Berkeley" }, + { "value": "110644", "label": "University of California-Davis" }, + { + "value": "110398", + "label": "University of California-Hastings College of Law" + }, + { "value": "110653", "label": "University of California-Irvine" }, + { "value": "110662", "label": "University of California-Los Angeles" }, + { "value": "445188", "label": "University of California-Merced" }, + { "value": "110671", "label": "University of California-Riverside" }, + { "value": "110680", "label": "University of California-San Diego" }, + { "value": "110699", "label": "University of California-San Francisco" }, + { "value": "110705", "label": "University of California-Santa Barbara" }, + { "value": "110714", "label": "University of California-Santa Cruz" }, + { "value": "106704", "label": "University of Central Arkansas" }, + { "value": "132903", "label": "University of Central Florida" }, + { "value": "176965", "label": "University of Central Missouri" }, + { "value": "206941", "label": "University of Central Oklahoma" }, + { "value": "237312", "label": "University of Charleston" }, + { "value": "144050", "label": "University of Chicago" }, + { "value": "201955", "label": "University of Cincinnati-Blue Ash College" }, + { "value": "201946", "label": "University of Cincinnati-Clermont College" }, + { "value": "201885", "label": "University of Cincinnati-Main Campus" }, + { "value": "126614", "label": "University of Colorado Boulder" }, + { "value": "126580", "label": "University of Colorado Colorado Springs" }, + { "value": "126562", "label": "University of Colorado Denver" }, + { "value": "129020", "label": "University of Connecticut" }, + { "value": "224323", "label": "University of Dallas" }, + { "value": "202480", "label": "University of Dayton" }, + { "value": "130943", "label": "University of Delaware" }, + { "value": "127060", "label": "University of Denver" }, + { "value": "169716", "label": "University of Detroit Mercy" }, + { "value": "153278", "label": "University of Dubuque" }, + { "value": "447801", "label": "University of East-West Medicine" }, + { "value": "150534", "label": "University of Evansville" }, + { "value": "134130", "label": "University of Florida" }, + { "value": "457402", "label": "University of Fort Lauderdale" }, + { "value": "139959", "label": "University of Georgia" }, + { "value": "180258", "label": "University of Great Falls" }, + { "value": "240754", "label": "University of Guam" }, + { "value": "129525", "label": "University of Hartford" }, + { "value": "141565", "label": "University of Hawaii at Hilo" }, + { "value": "141574", "label": "University of Hawaii at Manoa" }, + { "value": "141839", "label": "University of Hawaii Maui College" }, + { "value": "141981", "label": "University of Hawaii-West Oahu" }, + { "value": "160065", "label": "University of Holy Cross" }, + { "value": "225511", "label": "University of Houston" }, + { "value": "225414", "label": "University of Houston-Clear Lake" }, + { "value": "225432", "label": "University of Houston-Downtown" }, + { "value": "225502", "label": "University of Houston-Victoria" }, + { "value": "142285", "label": "University of Idaho" }, + { "value": "145600", "label": "University of Illinois at Chicago" }, + { "value": "148654", "label": "University of Illinois at Springfield" }, + { + "value": "145637", + "label": "University of Illinois at Urbana-Champaign" + }, + { "value": "151263", "label": "University of Indianapolis" }, + { "value": "153658", "label": "University of Iowa" }, + { "value": "200156", "label": "University of Jamestown" }, + { "value": "155317", "label": "University of Kansas" }, + { "value": "157085", "label": "University of Kentucky" }, + { "value": "117140", "label": "University of La Verne" }, + { "value": "160658", "label": "University of Louisiana at Lafayette" }, + { "value": "159993", "label": "University of Louisiana at Monroe" }, + { "value": "157289", "label": "University of Louisville" }, + { "value": "161253", "label": "University of Maine" }, + { "value": "161217", "label": "University of Maine at Augusta" }, + { "value": "161226", "label": "University of Maine at Farmington" }, + { "value": "161235", "label": "University of Maine at Fort Kent" }, + { "value": "161244", "label": "University of Maine at Machias" }, + { "value": "161341", "label": "University of Maine at Presque Isle" }, + { "value": "437097", "label": "University of Management and Technology" }, + { "value": "200217", "label": "University of Mary" }, + { "value": "226471", "label": "University of Mary Hardin-Baylor" }, + { "value": "232681", "label": "University of Mary Washington" }, + { "value": "163338", "label": "University of Maryland Eastern Shore" }, + { "value": "163259", "label": "University of Maryland-Baltimore" }, + { "value": "163268", "label": "University of Maryland-Baltimore County" }, + { "value": "163286", "label": "University of Maryland-College Park" }, + { "value": "163204", "label": "University of Maryland-University College" }, + { + "value": "166708", + "label": "University of Massachusetts Medical School Worcester" + }, + { "value": "166629", "label": "University of Massachusetts-Amherst" }, + { "value": "166638", "label": "University of Massachusetts-Boston" }, + { "value": "167987", "label": "University of Massachusetts-Dartmouth" }, + { "value": "166513", "label": "University of Massachusetts-Lowell" }, + { "value": "220862", "label": "University of Memphis" }, + { "value": "135726", "label": "University of Miami" }, + { "value": "170976", "label": "University of Michigan-Ann Arbor" }, + { "value": "171137", "label": "University of Michigan-Dearborn" }, + { "value": "171146", "label": "University of Michigan-Flint" }, + { "value": "174075", "label": "University of Minnesota-Crookston" }, + { "value": "174233", "label": "University of Minnesota-Duluth" }, + { "value": "174251", "label": "University of Minnesota-Morris" }, + { "value": "456959", "label": "University of Minnesota-Rochester" }, + { "value": "174066", "label": "University of Minnesota-Twin Cities" }, + { "value": "176017", "label": "University of Mississippi" }, + { "value": "178396", "label": "University of Missouri-Columbia" }, + { "value": "178402", "label": "University of Missouri-Kansas City" }, + { "value": "178420", "label": "University of Missouri-St Louis" }, + { "value": "101693", "label": "University of Mobile" }, + { "value": "101709", "label": "University of Montevallo" }, + { "value": "199069", "label": "University of Mount Olive" }, + { "value": "204185", "label": "University of Mount Union" }, + { "value": "181215", "label": "University of Nebraska at Kearney" }, + { "value": "181394", "label": "University of Nebraska at Omaha" }, + { "value": "181428", "label": "University of Nebraska Medical Center" }, + { "value": "181464", "label": "University of Nebraska-Lincoln" }, + { "value": "182281", "label": "University of Nevada-Las Vegas" }, + { "value": "182290", "label": "University of Nevada-Reno" }, + { "value": "161457", "label": "University of New England" }, + { "value": "183071", "label": "University of New Hampshire at Manchester" }, + { "value": "183044", "label": "University of New Hampshire-Main Campus" }, + { "value": "182829", "label": "University of New Hampshire-School of Law" }, + { "value": "129941", "label": "University of New Haven" }, + { "value": "187958", "label": "University of New Mexico-Gallup Campus" }, + { + "value": "187976", + "label": "University of New Mexico-Los Alamos Campus" + }, + { "value": "187985", "label": "University of New Mexico-Main Campus" }, + { "value": "188225", "label": "University of New Mexico-Taos Campus" }, + { + "value": "188049", + "label": "University of New Mexico-Valencia County Campus" + }, + { "value": "159939", "label": "University of New Orleans" }, + { "value": "101879", "label": "University of North Alabama" }, + { "value": "199111", "label": "University of North Carolina at Asheville" }, + { + "value": "199120", + "label": "University of North Carolina at Chapel Hill" + }, + { "value": "199139", "label": "University of North Carolina at Charlotte" }, + { + "value": "199148", + "label": "University of North Carolina at Greensboro" + }, + { "value": "199281", "label": "University of North Carolina at Pembroke" }, + { + "value": "199184", + "label": "University of North Carolina School of the Arts" + }, + { "value": "199218", "label": "University of North Carolina Wilmington" }, + { "value": "200280", "label": "University of North Dakota" }, + { "value": "136172", "label": "University of North Florida" }, + { "value": "482680", "label": "University of North Georgia" }, + { "value": "227216", "label": "University of North Texas" }, + { "value": "484905", "label": "University of North Texas at Dallas" }, + { + "value": "228909", + "label": "University of North Texas Health Science Center" + }, + { "value": "127741", "label": "University of Northern Colorado" }, + { "value": "154095", "label": "University of Northern Iowa" }, + { "value": "204486", "label": "University of Northwestern Ohio" }, + { "value": "174491", "label": "University of Northwestern-St Paul" }, + { "value": "152080", "label": "University of Notre Dame" }, + { + "value": "207342", + "label": "University of Oklahoma-Health Sciences Center" + }, + { "value": "207500", "label": "University of Oklahoma-Norman Campus" }, + { "value": "209551", "label": "University of Oregon" }, + { "value": "215062", "label": "University of Pennsylvania" }, + { "value": "450456", "label": "University of Phoenix-Alabama" }, + { "value": "484613", "label": "University of Phoenix-Arizona" }, + { "value": "484622", "label": "University of Phoenix-Arkansas" }, + { "value": "484631", "label": "University of Phoenix-California" }, + { "value": "484640", "label": "University of Phoenix-Colorado" }, + { "value": "448822", "label": "University of Phoenix-Connecticut" }, + { "value": "484668", "label": "University of Phoenix-Florida" }, + { "value": "484677", "label": "University of Phoenix-Georgia" }, + { "value": "420042", "label": "University of Phoenix-Hawaii" }, + { "value": "440466", "label": "University of Phoenix-Idaho" }, + { "value": "442161", "label": "University of Phoenix-Illinois" }, + { "value": "443544", "label": "University of Phoenix-Indiana" }, + { "value": "446729", "label": "University of Phoenix-Iowa" }, + { "value": "445391", "label": "University of Phoenix-Kentucky" }, + { "value": "484686", "label": "University of Phoenix-Louisiana" }, + { "value": "434973", "label": "University of Phoenix-Maryland" }, + { "value": "440420", "label": "University of Phoenix-Massachusetts" }, + { "value": "484695", "label": "University of Phoenix-Michigan" }, + { "value": "445319", "label": "University of Phoenix-Minnesota" }, + { "value": "462390", "label": "University of Phoenix-Mississippi" }, + { "value": "484701", "label": "University of Phoenix-Missouri" }, + { "value": "484710", "label": "University of Phoenix-Nevada" }, + { "value": "445300", "label": "University of Phoenix-New Jersey" }, + { "value": "405997", "label": "University of Phoenix-New Mexico" }, + { "value": "484729", "label": "University of Phoenix-North Carolina" }, + { "value": "439297", "label": "University of Phoenix-Ohio" }, + { "value": "484738", "label": "University of Phoenix-Oklahoma" }, + { "value": "432241", "label": "University of Phoenix-Oregon" }, + { "value": "484783", "label": "University of Phoenix-Pennsylvania" }, + { "value": "382063", "label": "University of Phoenix-Puerto Rico" }, + { "value": "448567", "label": "University of Phoenix-South Carolina" }, + { "value": "484747", "label": "University of Phoenix-Tennessee" }, + { "value": "484756", "label": "University of Phoenix-Texas" }, + { "value": "380465", "label": "University of Phoenix-Utah" }, + { "value": "484765", "label": "University of Phoenix-Virginia" }, + { "value": "432223", "label": "University of Phoenix-Washington" }, + { "value": "450483", "label": "University of Phoenix-Washington DC" }, + { "value": "440457", "label": "University of Phoenix-Wisconsin" }, + { "value": "157535", "label": "University of Pikeville" }, + { "value": "215266", "label": "University of Pittsburgh-Bradford" }, + { "value": "215275", "label": "University of Pittsburgh-Greensburg" }, + { "value": "215284", "label": "University of Pittsburgh-Johnstown" }, + { + "value": "215293", + "label": "University of Pittsburgh-Pittsburgh Campus" + }, + { "value": "215309", "label": "University of Pittsburgh-Titusville" }, + { "value": "209825", "label": "University of Portland" }, + { "value": "243106", "label": "University of Puerto Rico-Aguadilla" }, + { "value": "243115", "label": "University of Puerto Rico-Arecibo" }, + { "value": "243133", "label": "University of Puerto Rico-Bayamon" }, + { "value": "243142", "label": "University of Puerto Rico-Carolina" }, + { "value": "243151", "label": "University of Puerto Rico-Cayey" }, + { "value": "243179", "label": "University of Puerto Rico-Humacao" }, + { "value": "243197", "label": "University of Puerto Rico-Mayaguez" }, + { + "value": "243203", + "label": "University of Puerto Rico-Medical Sciences" + }, + { "value": "243212", "label": "University of Puerto Rico-Ponce" }, + { "value": "243221", "label": "University of Puerto Rico-Rio Piedras" }, + { "value": "243188", "label": "University of Puerto Rico-Utuado" }, + { "value": "236328", "label": "University of Puget Sound" }, + { "value": "121691", "label": "University of Redlands" }, + { "value": "217484", "label": "University of Rhode Island" }, + { "value": "233374", "label": "University of Richmond" }, + { "value": "205203", "label": "University of Rio Grande" }, + { "value": "195030", "label": "University of Rochester" }, + { "value": "152336", "label": "University of Saint Francis-Fort Wayne" }, + { "value": "130314", "label": "University of Saint Joseph" }, + { "value": "155812", "label": "University of Saint Mary" }, + { "value": "148885", "label": "University of Saint Mary of the Lake" }, + { "value": "122436", "label": "University of San Diego" }, + { "value": "122612", "label": "University of San Francisco" }, + { + "value": "207722", + "label": "University of Science and Arts of Oklahoma" + }, + { "value": "215929", "label": "University of Scranton" }, + { "value": "219383", "label": "University of Sioux Falls" }, + { "value": "102094", "label": "University of South Alabama" }, + { "value": "218645", "label": "University of South Carolina-Aiken" }, + { "value": "218654", "label": "University of South Carolina-Beaufort" }, + { "value": "218663", "label": "University of South Carolina-Columbia" }, + { "value": "218672", "label": "University of South Carolina-Lancaster" }, + { "value": "218681", "label": "University of South Carolina-Salkehatchie" }, + { "value": "218690", "label": "University of South Carolina-Sumter" }, + { "value": "218706", "label": "University of South Carolina-Union" }, + { "value": "218742", "label": "University of South Carolina-Upstate" }, + { "value": "219471", "label": "University of South Dakota" }, + { "value": "137351", "label": "University of South Florida-Main Campus" }, + { + "value": "451671", + "label": "University of South Florida-Sarasota-Manatee" + }, + { "value": "448840", "label": "University of South Florida-St Petersburg" }, + { "value": "123961", "label": "University of Southern California" }, + { "value": "151306", "label": "University of Southern Indiana" }, + { "value": "161554", "label": "University of Southern Maine" }, + { "value": "176372", "label": "University of Southern Mississippi" }, + { "value": "134121", "label": "University of Southernmost Florida" }, + { + "value": "367954", + "label": "University of St Augustine for Health Sciences" + }, + { "value": "148584", "label": "University of St Francis" }, + { "value": "227863", "label": "University of St Thomas-Houston" }, + { "value": "174914", "label": "University of St Thomas-Saint Paul" }, + { + "value": "228635", + "label": "University of Texas Southwestern Medical Center" + }, + { "value": "156541", "label": "University of the Cumberlands" }, + { "value": "131399", "label": "University of the District of Columbia" }, + { + "value": "363721", + "label": "University of the District of Columbia-David A Clarke School of Law" + }, + { "value": "225627", "label": "University of the Incarnate Word" }, + { "value": "107558", "label": "University of the Ozarks" }, + { "value": "120883", "label": "University of the Pacific" }, + { "value": "442639", "label": "University of the Potomac-VA Campus" }, + { + "value": "384412", + "label": "University of the Potomac-Washington DC Campus" + }, + { "value": "441308", "label": "University of the Rockies" }, + { "value": "215132", "label": "University of the Sciences" }, + { "value": "188182", "label": "University of the Southwest" }, + { "value": "243665", "label": "University of the Virgin Islands" }, + { "value": "449870", "label": "University of the West" }, + { "value": "206084", "label": "University of Toledo" }, + { "value": "207971", "label": "University of Tulsa" }, + { "value": "230764", "label": "University of Utah" }, + { "value": "216542", "label": "University of Valley Forge" }, + { "value": "231174", "label": "University of Vermont" }, + { "value": "234076", "label": "University of Virginia-Main Campus" }, + { "value": "377555", "label": "University of Washington-Bothell Campus" }, + { "value": "236948", "label": "University of Washington-Seattle Campus" }, + { "value": "377564", "label": "University of Washington-Tacoma Campus" }, + { "value": "101587", "label": "University of West Alabama" }, + { "value": "141334", "label": "University of West Georgia" }, + { "value": "210438", "label": "University of Western States" }, + { "value": "240055", "label": "University of Wisconsin Colleges" }, + { "value": "240268", "label": "University of Wisconsin-Eau Claire" }, + { "value": "240277", "label": "University of Wisconsin-Green Bay" }, + { "value": "240329", "label": "University of Wisconsin-La Crosse" }, + { "value": "240444", "label": "University of Wisconsin-Madison" }, + { "value": "240453", "label": "University of Wisconsin-Milwaukee" }, + { "value": "240365", "label": "University of Wisconsin-Oshkosh" }, + { "value": "240374", "label": "University of Wisconsin-Parkside" }, + { "value": "240462", "label": "University of Wisconsin-Platteville" }, + { "value": "240471", "label": "University of Wisconsin-River Falls" }, + { "value": "240480", "label": "University of Wisconsin-Stevens Point" }, + { "value": "240417", "label": "University of Wisconsin-Stout" }, + { "value": "240426", "label": "University of Wisconsin-Superior" }, + { "value": "240189", "label": "University of Wisconsin-Whitewater" }, + { "value": "240727", "label": "University of Wyoming" }, + { "value": "154493", "label": "Upper Iowa University" }, + { "value": "196307", "label": "Upstate Medical University" }, + { "value": "429128", "label": "Urban College of Boston" }, + { "value": "206330", "label": "Urbana University" }, + { "value": "455099", "label": "Urshan Graduate School of Theology" }, + { "value": "216524", "label": "Ursinus College" }, + { "value": "206349", "label": "Ursuline College" }, + { "value": "446604", "label": "Uta Mesivta of Kiryas Joel" }, + { "value": "230728", "label": "Utah State University" }, + { "value": "230737", "label": "Utah Valley University" }, + { "value": "197045", "label": "Utica College" }, + { "value": "197081", "label": "Utica School of Commerce" }, + { "value": "141264", "label": "Valdosta State University" }, + { "value": "138187", "label": "Valencia College" }, + { "value": "200572", "label": "Valley City State University" }, + { "value": "377652", "label": "Valley College-Beckley" }, + { "value": "152600", "label": "Valparaiso University" }, + { "value": "199838", "label": "Vance-Granville Community College" }, + { "value": "221999", "label": "Vanderbilt University" }, + { "value": "149639", "label": "VanderCook College of Music" }, + { + "value": "123651", + "label": "Vanguard University of Southern California" + }, + { "value": "197133", "label": "Vassar College" }, + { "value": "455567", "label": "Vatterott College-Appling Farms" }, + { "value": "245342", "label": "Vatterott College-Berkeley" }, + { "value": "442408", "label": "Vatterott College-Cleveland" }, + { "value": "373058", "label": "Vatterott College-Des Moines" }, + { "value": "440873", "label": "Vatterott College-Dividend" }, + { + "value": "481988", + "label": "Vatterott College-ex'treme Institute by Nelly-St Louis" + }, + { "value": "404374", "label": "Vatterott College-Joplin" }, + { "value": "404383", "label": "Vatterott College-Kansas City" }, + { "value": "437060", "label": "Vatterott College-Oklahoma City" }, + { "value": "148140", "label": "Vatterott College-Quincy" }, + { "value": "181756", "label": "Vatterott College-Spring Valley" }, + { "value": "404365", "label": "Vatterott College-Springfield" }, + { "value": "445559", "label": "Vatterott College-St Charles" }, + { "value": "436182", "label": "Vatterott College-St Joseph" }, + { "value": "436191", "label": "Vatterott College-Sunset Hills" }, + { "value": "440882", "label": "Vatterott College-Tulsa" }, + { "value": "440891", "label": "Vatterott College-Wichita" }, + { + "value": "188340", + "label": "Vaughn College of Aeronautics and Technology" + }, + { "value": "125028", "label": "Ventura College" }, + { "value": "175157", "label": "Vermilion Community College" }, + { "value": "455992", "label": "Vermont College of Fine Arts" }, + { "value": "231147", "label": "Vermont Law School" }, + { "value": "231165", "label": "Vermont Technical College" }, + { "value": "229504", "label": "Vernon College" }, + { "value": "213914", "label": "Vet Tech Institute" }, + { "value": "223472", "label": "Vet Tech Institute of Houston" }, + { "value": "125091", "label": "Victor Valley College" }, + { "value": "229540", "label": "Victoria College" }, + { "value": "197142", "label": "Villa Maria College" }, + { "value": "216597", "label": "Villanova University" }, + { "value": "152637", "label": "Vincennes University" }, + { "value": "482228", "label": "Virginia Baptist College" }, + { "value": "458256", "label": "Virginia College-Augusta" }, + { "value": "441928", "label": "Virginia College-Austin" }, + { "value": "460774", "label": "Virginia College-Baton Rouge" }, + { "value": "450191", "label": "Virginia College-Biloxi" }, + { "value": "420307", "label": "Virginia College-Birmingham" }, + { "value": "456056", "label": "Virginia College-Charleston" }, + { "value": "458593", "label": "Virginia College-Columbia" }, + { "value": "475370", "label": "Virginia College-Columbus" }, + { "value": "480107", "label": "Virginia College-Florence" }, + { "value": "454625", "label": "Virginia College-Greenville" }, + { "value": "420316", "label": "Virginia College-Huntsville" }, + { "value": "441919", "label": "Virginia College-Jackson" }, + { "value": "455716", "label": "Virginia College-Jacksonville" }, + { "value": "475617", "label": "Virginia College-Knoxville" }, + { "value": "460844", "label": "Virginia College-Macon" }, + { "value": "445090", "label": "Virginia College-Mobile" }, + { "value": "452115", "label": "Virginia College-Montgomery" }, + { "value": "389727", "label": "Virginia College-Pensacola" }, + { "value": "460923", "label": "Virginia College-Richmond" }, + { "value": "475352", "label": "Virginia College-Savannah" }, + { + "value": "450289", + "label": "Virginia College-School of Business and Health-Chattanooga" + }, + { "value": "475866", "label": "Virginia College-Shreveport Bossier City" }, + { "value": "460853", "label": "Virginia College-Spartanburg" }, + { "value": "475592", "label": "Virginia College-Tulsa" }, + { "value": "234030", "label": "Virginia Commonwealth University" }, + { "value": "233903", "label": "Virginia Highlands Community College" }, + { "value": "206394", "label": "Virginia Marti College of Art and Design" }, + { "value": "234085", "label": "Virginia Military Institute" }, + { + "value": "233921", + "label": "Virginia Polytechnic Institute and State University" + }, + { "value": "234155", "label": "Virginia State University" }, + { "value": "459082", "label": "Virginia Tech Carilion School of Medicine" }, + { "value": "234164", "label": "Virginia Union University" }, + { "value": "234137", "label": "Virginia University of Lynchburg" }, + { "value": "234173", "label": "Virginia Wesleyan College" }, + { "value": "233949", "label": "Virginia Western Community College" }, + { "value": "449764", "label": "Visible Music College" }, + { "value": "365204", "label": "Vista College" }, + { "value": "377342", "label": "Vista College-Online" }, + { "value": "240107", "label": "Viterbo University" }, + { "value": "222053", "label": "Volunteer State Community College" }, + { "value": "218919", "label": "Voorhees College" }, + { "value": "152673", "label": "Wabash College" }, + { "value": "403487", "label": "Wabash Valley College" }, + { "value": "226879", "label": "Wade College" }, + { "value": "197197", "label": "Wagner College" }, + { "value": "199847", "label": "Wake Forest University" }, + { "value": "199856", "label": "Wake Technical Community College" }, + { "value": "125231", "label": "Walden University" }, + { "value": "154518", "label": "Waldorf College" }, + { "value": "236887", "label": "Walla Walla Community College" }, + { "value": "236896", "label": "Walla Walla University" }, + { + "value": "172608", + "label": "Walsh College of Accountancy and Business Administration" + }, + { "value": "206437", "label": "Walsh University" }, + { "value": "222062", "label": "Walters State Community College" }, + { "value": "210304", "label": "Warner Pacific College" }, + { + "value": "480198", + "label": "Warner Pacific College Adult Degree Program" + }, + { "value": "138275", "label": "Warner University" }, + { "value": "245625", "label": "Warren County Community College" }, + { "value": "199865", "label": "Warren Wilson College" }, + { "value": "154527", "label": "Wartburg College" }, + { "value": "154536", "label": "Wartburg Theological Seminary" }, + { "value": "156082", "label": "Washburn University" }, + { "value": "216667", "label": "Washington & Jefferson College" }, + { "value": "162210", "label": "Washington Adventist University" }, + { "value": "234207", "label": "Washington and Lee University" }, + { "value": "164216", "label": "Washington College" }, + { "value": "161581", "label": "Washington County Community College" }, + { "value": "206446", "label": "Washington State Community College" }, + { "value": "236939", "label": "Washington State University" }, + { "value": "179867", "label": "Washington University in St Louis" }, + { "value": "172617", "label": "Washtenaw Community College" }, + { "value": "392840", "label": "Watkins College of Art Design & Film" }, + { "value": "149727", "label": "Waubonsee Community College" }, + { "value": "240125", "label": "Waukesha County Technical College" }, + { "value": "229780", "label": "Wayland Baptist University" }, + { "value": "199892", "label": "Wayne Community College" }, + { "value": "172635", "label": "Wayne County Community College District" }, + { "value": "181783", "label": "Wayne State College" }, + { "value": "172644", "label": "Wayne State University" }, + { "value": "216694", "label": "Waynesburg University" }, + { "value": "229799", "label": "Weatherford College" }, + { "value": "197221", "label": "Webb Institute" }, + { "value": "138293", "label": "Webber International University" }, + { "value": "230782", "label": "Weber State University" }, + { "value": "179894", "label": "Webster University" }, + { "value": "190424", "label": "Weill Cornell Medicine" }, + { "value": "220206", "label": "Welch College" }, + { "value": "168218", "label": "Wellesley College" }, + { "value": "197230", "label": "Wells College" }, + { + "value": "447999", + "label": "WellSpring School of Allied Health-Kansas City" + }, + { "value": "236975", "label": "Wenatchee Valley College" }, + { "value": "168227", "label": "Wentworth Institute of Technology" }, + { "value": "179919", "label": "Wentworth Military Academy and College" }, + { "value": "176451", "label": "Wesley Biblical Seminary" }, + { "value": "131098", "label": "Wesley College" }, + { "value": "131973", "label": "Wesley Theological Seminary" }, + { "value": "141325", "label": "Wesleyan College" }, + { "value": "130697", "label": "Wesleyan University" }, + { "value": "216764", "label": "West Chester University of Pennsylvania" }, + { "value": "441229", "label": "West Coast Ultrasound Institute" }, + { "value": "477039", "label": "West Coast University-Dallas" }, + { "value": "443331", "label": "West Coast University-Los Angeles" }, + { "value": "458229", "label": "West Coast University-Ontario" }, + { "value": "458210", "label": "West Coast University-Orange County" }, + { "value": "139278", "label": "West Georgia Technical College" }, + { "value": "125462", "label": "West Hills College-Coalinga" }, + { "value": "448594", "label": "West Hills College-Lemoore" }, + { + "value": "157483", + "label": "West Kentucky Community and Technical College" + }, + { "value": "237932", "label": "West Liberty University" }, + { "value": "125471", "label": "West Los Angeles College" }, + { "value": "172671", "label": "West Shore Community College" }, + { "value": "222099", "label": "West Tennessee Business College" }, + { "value": "229814", "label": "West Texas A & M University" }, + { "value": "125499", "label": "West Valley College" }, + { "value": "237978", "label": "West Virginia Business College-Wheeling" }, + { "value": "442383", "label": "West Virginia Junior College-Bridgeport" }, + { "value": "237987", "label": "West Virginia Junior College-Charleston" }, + { "value": "237996", "label": "West Virginia Junior College-Morgantown" }, + { "value": "238014", "label": "West Virginia Northern Community College" }, + { + "value": "237880", + "label": "West Virginia School of Osteopathic Medicine" + }, + { "value": "237899", "label": "West Virginia State University" }, + { "value": "238032", "label": "West Virginia University" }, + { "value": "237686", "label": "West Virginia University at Parkersburg" }, + { + "value": "237950", + "label": "West Virginia University Institute of Technology" + }, + { "value": "237969", "label": "West Virginia Wesleyan College" }, + { "value": "200004", "label": "Western Carolina University" }, + { "value": "130776", "label": "Western Connecticut State University" }, + { "value": "219480", "label": "Western Dakota Technical Institute" }, + { "value": "433387", "label": "Western Governors University" }, + { "value": "149772", "label": "Western Illinois University" }, + { "value": "106102", "label": "Western International University" }, + { "value": "154572", "label": "Western Iowa Tech Community College" }, + { "value": "157951", "label": "Western Kentucky University" }, + { "value": "172699", "label": "Western Michigan University" }, + { + "value": "172477", + "label": "Western Michigan University-Thomas M. Cooley Law School" + }, + { "value": "181817", "label": "Western Nebraska Community College" }, + { "value": "182564", "label": "Western Nevada College" }, + { "value": "168254", "label": "Western New England University" }, + { "value": "188304", "label": "Western New Mexico University" }, + { "value": "208035", "label": "Western Oklahoma State College" }, + { "value": "210429", "label": "Western Oregon University" }, + { "value": "199908", "label": "Western Piedmont Community College" }, + { "value": "210368", "label": "Western Seminary" }, + { + "value": "126030", + "label": "Western State College of Law at Argosy University" + }, + { "value": "128391", "label": "Western State Colorado University" }, + { "value": "224660", "label": "Western Technical College-El Paso" }, + { "value": "224679", "label": "Western Technical College-El Paso" }, + { "value": "240170", "label": "Western Technical College-La Crosse" }, + { "value": "229832", "label": "Western Texas College" }, + { "value": "172705", "label": "Western Theological Seminary" }, + { "value": "112525", "label": "Western University of Health Sciences" }, + { "value": "237011", "label": "Western Washington University" }, + { "value": "240693", "label": "Western Wyoming Community College" }, + { "value": "168263", "label": "Westfield State University" }, + { "value": "179946", "label": "Westminster College-Fulton" }, + { "value": "216807", "label": "Westminster College-New Wilmington" }, + { "value": "230807", "label": "Westminster College-Salt Lake City" }, + { "value": "216816", "label": "Westminster Theological Seminary" }, + { + "value": "125718", + "label": "Westminster Theological Seminary in California" + }, + { "value": "125727", "label": "Westmont College" }, + { "value": "216825", "label": "Westmoreland County Community College" }, + { "value": "437848", "label": "Westwood College-Anaheim" }, + { "value": "448628", "label": "Westwood College-Annandale" }, + { "value": "447069", "label": "Westwood College-Arlington Ballston" }, + { "value": "445072", "label": "Westwood College-Atlanta Midtown" }, + { "value": "443687", "label": "Westwood College-Chicago Loop" }, + { "value": "127024", "label": "Westwood College-Denver North" }, + { "value": "381787", "label": "Westwood College-Denver South" }, + { "value": "406194", "label": "Westwood College-Dupage" }, + { "value": "440484", "label": "Westwood College-Inland Empire" }, + { "value": "122843", "label": "Westwood College-Los Angeles" }, + { "value": "445276", "label": "Westwood College-Northlake" }, + { "value": "178226", "label": "Westwood College-O'Hare Airport" }, + { "value": "440147", "label": "Westwood College-River Oaks" }, + { "value": "121381", "label": "Westwood College-South Bay" }, + { "value": "229841", "label": "Wharton County Junior College" }, + { "value": "237039", "label": "Whatcom Community College" }, + { "value": "168281", "label": "Wheaton College-Norton" }, + { "value": "149781", "label": "Wheaton College-Wheaton" }, + { "value": "238078", "label": "Wheeling Jesuit University" }, + { "value": "168290", "label": "Wheelock College" }, + { "value": "434751", "label": "White Earth Tribal and Community College" }, + { "value": "183105", "label": "White Mountains Community College" }, + { "value": "237057", "label": "Whitman College" }, + { "value": "125763", "label": "Whittier College" }, + { "value": "237066", "label": "Whitworth University" }, + { + "value": "475200", + "label": "Whitworth University-Adult Degree Programs" + }, + { "value": "156107", "label": "Wichita Area Technical College" }, + { "value": "156125", "label": "Wichita State University" }, + { "value": "156134", "label": "Wichita Technical Institute" }, + { "value": "244190", "label": "Widener University-Delaware Campus" }, + { "value": "402828", "label": "Widener University-Harrisburg Campus" }, + { "value": "216852", "label": "Widener University-Main Campus" }, + { "value": "206491", "label": "Wilberforce University" }, + { "value": "229887", "label": "Wiley College" }, + { "value": "199926", "label": "Wilkes Community College" }, + { "value": "216931", "label": "Wilkes University" }, + { "value": "210401", "label": "Willamette University" }, + { "value": "176479", "label": "William Carey University" }, + { "value": "166717", "label": "William James College" }, + { "value": "122728", "label": "William Jessup University" }, + { "value": "179955", "label": "William Jewell College" }, + { "value": "175281", "label": "William Mitchell College of Law" }, + { "value": "222105", "label": "William Moore College of Technology" }, + { "value": "187444", "label": "William Paterson University of New Jersey" }, + { "value": "199272", "label": "William Peace University" }, + { "value": "154590", "label": "William Penn University" }, + { "value": "149842", "label": "William Rainey Harper College" }, + { "value": "179964", "label": "William Woods University" }, + { "value": "107877", "label": "Williams Baptist College" }, + { "value": "168342", "label": "Williams College" }, + { "value": "218955", "label": "Williamsburg Technical College" }, + { "value": "443340", "label": "Williamson Christian College" }, + { "value": "200341", "label": "Williston State College" }, + { "value": "206507", "label": "Wilmington College" }, + { "value": "131113", "label": "Wilmington University" }, + { "value": "217013", "label": "Wilson College" }, + { "value": "199953", "label": "Wilson Community College" }, + { "value": "141990", "label": "Windward Community College" }, + { "value": "206516", "label": "Winebrenner Theological Seminary" }, + { "value": "199962", "label": "Wingate University" }, + { "value": "175272", "label": "Winona State University" }, + { "value": "199999", "label": "Winston-Salem State University" }, + { "value": "218964", "label": "Winthrop University" }, + { "value": "141255", "label": "Wiregrass Georgia Technical College" }, + { "value": "240198", "label": "Wisconsin Indianhead Technical College" }, + { "value": "240338", "label": "Wisconsin Lutheran College" }, + { + "value": "240213", + "label": "Wisconsin School of Professional Psychology" + }, + { "value": "206525", "label": "Wittenberg University" }, + { "value": "218973", "label": "Wofford College" }, + { "value": "451130", "label": "Wolford College" }, + { "value": "442064", "label": "Won Institute of Graduate Studies" }, + { "value": "197522", "label": "Wood Tobe-Coburn School" }, + { "value": "125897", "label": "Woodbury University" }, + { "value": "455512", "label": "Woodland Community College" }, + { "value": "168421", "label": "Worcester Polytechnic Institute" }, + { "value": "168430", "label": "Worcester State University" }, + { "value": "141936", "label": "World Medicine Institute" }, + { "value": "401223", "label": "World Mission University" }, + { "value": "369455", "label": "Worsham College of Mortuary Science" }, + { "value": "164313", "label": "Wor-Wic Community College" }, + { "value": "406200", "label": "Wright Career College" }, + { "value": "206613", "label": "Wright State University-Lake Campus" }, + { "value": "206604", "label": "Wright State University-Main Campus" }, + { "value": "441089", "label": "Wyo Tech-Blairsville" }, + { "value": "132268", "label": "Wyotech-Daytona" }, + { "value": "123208", "label": "Wyotech-Fremont" }, + { "value": "240718", "label": "Wyotech-Laramie" }, + { "value": "398574", "label": "Wyotech-Long Beach" }, + { "value": "234377", "label": "Wytheville Community College" }, + { "value": "206622", "label": "Xavier University" }, + { "value": "160904", "label": "Xavier University of Louisiana" }, + { "value": "237109", "label": "Yakima Valley Community College" }, + { "value": "130794", "label": "Yale University" }, + { "value": "106148", "label": "Yavapai College" }, + { "value": "245731", "label": "Yeshiva and Kollel Harbotzas Torah" }, + { "value": "434937", "label": "Yeshiva College of the Nations Capital" }, + { "value": "197647", "label": "Yeshiva Derech Chaim" }, + { "value": "420325", "label": "Yeshiva D'monsey Rabbinical College" }, + { "value": "375230", "label": "Yeshiva Gedolah Imrei Yosef D'spinka" }, + { "value": "481410", "label": "Yeshiva Gedolah Kesser Torah" }, + { "value": "247773", "label": "Yeshiva Gedolah of Greater Detroit" }, + { "value": "476692", "label": "Yeshiva Gedolah Zichron Leyma" }, + { "value": "197601", "label": "Yeshiva Karlin Stolin" }, + { + "value": "190752", + "label": "Yeshiva of Far Rockaway Derech Ayson Rabbinical Seminary" + }, + { "value": "455257", "label": "Yeshiva of Machzikai Hadas" }, + { "value": "197674", "label": "Yeshiva of Nitra Rabbinical College" }, + { "value": "431983", "label": "Yeshiva of the Telshe Alumni" }, + { + "value": "126076", + "label": "Yeshiva Ohr Elchonon Chabad West Coast Talmudical Seminary" + }, + { "value": "197692", "label": "Yeshiva Shaar Hatorah" }, + { "value": "441609", "label": "Yeshiva Shaarei Torah of Rockland" }, + { "value": "451398", "label": "Yeshiva Toras Chaim" }, + { "value": "128425", "label": "Yeshiva Toras Chaim Talmudical Seminary" }, + { "value": "197708", "label": "Yeshiva University" }, + { "value": "481438", "label": "Yeshiva Yesodei Hatorah" }, + { "value": "451370", "label": "Yeshivas Be'er Yitzchok" }, + { "value": "405058", "label": "Yeshivas Novominsk" }, + { "value": "197610", "label": "Yeshivat Mikdash Melech" }, + { "value": "217040", "label": "Yeshivath Beth Moshe" }, + { "value": "197735", "label": "Yeshivath Viznitz" }, + { "value": "197744", "label": "Yeshivath Zichron Moshe" }, + { + "value": "401250", + "label": "Yo San University of Traditional Chinese Medicine" + }, + { "value": "181853", "label": "York College" }, + { "value": "217059", "label": "York College Pennsylvania" }, + { "value": "420440", "label": "York County Community College" }, + { "value": "218991", "label": "York Technical College" }, + { "value": "217086", "label": "Yorktowne Business Institute" }, + { "value": "141361", "label": "Young Harris College" }, + { "value": "206695", "label": "Youngstown State University" }, + { "value": "375939", "label": "YTI Career Institute-Altoona" }, + { "value": "217077", "label": "YTI Career Institute-York" }, + { "value": "126119", "label": "Yuba College" }, + { "value": "204255", "label": "Zane State College" } +] diff --git a/vite-app/src/apps/Auth2/resources/data/nationalLabs.yaml b/vite-app/src/apps/Auth2/resources/data/nationalLabs.yaml new file mode 100644 index 000000000..e92cda420 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/nationalLabs.yaml @@ -0,0 +1,91 @@ +# National Labs +--- +- name: Ames Laboratory + city: Ames + state: Iowa + initials: Ames + type: OSL +- name: Argonne National Laboratory + city: Argonne + state: Illinois + initials: ANL + type: OSL +- name: Brookhaven National Laboratory + city: Upton + state: New York + initials: BNL + type: OSL +- name: Fermi National Accelerator Laboratory + city: Berkeley + state: California + initials: FERMILAB + type: OSL +- name: Oak Ridge National Laboratory + city: Oak Ridge + state: Tennessee + initials: ORNL + type: OSL +- name: Lawrence Berkeley National Laboratory + city: Berkeley + state: California + initials: LBNL + type: OSL +- name: Pacific Northwest National Laboratory + city: Richland + state: Washington + initials: PNNL + type: OSL +- name: Princeton Plasma Physics Laboratory + city: Princeton + state: New Jersey + initials: PPPL + type: OSL +- name: SLAC National Accelerator Laboratory + city: Newport News + state: Virginia + initials: SLAC + type: OSL +- name: Idaho National Laboratory + city: Idaho Falls + state: Idaho + initials: INL + type: OTHER +- name: National Energy Technology Laboratory + locations: + - city: Morgantown + state: West Virginia + - city: Pittsburgh + state: Pennsylvania + - city: Albany + state: Orgegon + initials: NETL + type: OTHER +- name: National Renewabl Energy Laboratory + city: Golden + state: Colorado + initials: NREL + type: OTHER +- name: Savannah River National Laboratory + city: Aiken + state: South Carolina + initials: SRNL + type: OTHER + +- name: Lawrence Livermore National Laboratory + city: Livermore + state: California + initials: LLNL + type: NNSA +- name: Los Alamos National Laboratory + city: Los Alamos + state: New Mexico + initials: LANL + type: NNSA +- name: Sandia National Laboratory + locations: + - city: Albequerque + state: New Mexico + - city: Livermore + state: California + initials: SNL + type: NNSA diff --git a/vite-app/src/apps/Auth2/resources/data/organizations.json b/vite-app/src/apps/Auth2/resources/data/organizations.json new file mode 100644 index 000000000..643d78e9f --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/organizations.json @@ -0,0 +1,14068 @@ +[ + { + "label": "A T Still University of Health Sciences" + }, + { + "label": "Aaniiih Nakoda College" + }, + { + "label": "Abilene Christian University" + }, + { + "label": "Abraham Baldwin Agricultural College" + }, + { + "label": "Academy College" + }, + { + "label": "Academy for Five Element Acupuncture" + }, + { + "label": "Academy for Jewish Religion-California" + }, + { + "label": "Academy for Nursing and Health Occupations" + }, + { + "label": "Academy of Art University" + }, + { + "label": "Academy of Chinese Culture and Health Sciences" + }, + { + "label": "Academy of Couture Art" + }, + { + "label": "Academy of Natural Therapy Inc" + }, + { + "label": "Acupuncture and Integrative Medicine College-Berkeley" + }, + { + "label": "Acupuncture and Massage College" + }, + { + "label": "Adams State University" + }, + { + "label": "Adelphi University" + }, + { + "label": "Adirondack Community College" + }, + { + "label": "Adler Graduate School" + }, + { + "label": "Adler University" + }, + { + "label": "Adrian College" + }, + { + "label": "Advanced College" + }, + { + "label": "Advanced Computing Institute" + }, + { + "label": "Advanced Technology Institute" + }, + { + "label": "Advanced Training Associates" + }, + { + "label": "Adventist University of Health Sciences" + }, + { + "label": "Advertising Art Educational Services DBA School of Advertising Art" + }, + { + "label": "Agnes Scott College" + }, + { + "label": "AI Miami International University of Art and Design" + }, + { + "label": "AIB College of Business" + }, + { + "label": "Aiken Technical College" + }, + { + "label": "Aims Community College" + }, + { + "label": "Air Force Institute of Technology-Graduate School of Engineering & Management" + }, + { + "label": "Akron Institute of Herzing University" + }, + { + "label": "Alabama A & M University" + }, + { + "label": "Alabama Southern Community College" + }, + { + "label": "Alabama State University" + }, + { + "label": "Alamance Community College" + }, + { + "label": "Alaska Bible College" + }, + { + "label": "Alaska Career College" + }, + { + "label": "Alaska Christian College" + }, + { + "label": "Alaska Pacific University" + }, + { + "label": "Albany College of Pharmacy and Health Sciences" + }, + { + "label": "Albany Law School" + }, + { + "label": "Albany Medical College" + }, + { + "label": "Albany State University" + }, + { + "label": "Albany Technical College" + }, + { + "label": "Albertus Magnus College" + }, + { + "label": "Albion College" + }, + { + "label": "Albright College" + }, + { + "label": "Alcorn State University" + }, + { + "label": "Alderson Broaddus University" + }, + { + "label": "Alexandria Technical & Community College" + }, + { + "label": "Alfred University" + }, + { + "label": "Alice Lloyd College" + }, + { + "label": "Allan Hancock College" + }, + { + "label": "Allegany College of Maryland" + }, + { + "label": "Allegheny College" + }, + { + "label": "Allegheny Wesleyan College" + }, + { + "label": "Allen College" + }, + { + "label": "Allen County Community College" + }, + { + "label": "Allen University" + }, + { + "label": "Alliant International University-San Diego" + }, + { + "label": "Allied American University" + }, + { + "label": "Alma College" + }, + { + "label": "Alpena Community College" + }, + { + "label": "Alvernia University" + }, + { + "label": "Alverno College" + }, + { + "label": "Alvin Community College" + }, + { + "label": "Amarillo College" + }, + { + "label": "Amberton University" + }, + { + "label": "Ambria College of Nursing" + }, + { + "label": "American Academy McAllister Institute of Funeral Service" + }, + { + "label": "American Academy of Acupuncture and Oriental Medicine" + }, + { + "label": "American Academy of Art" + }, + { + "label": "American Academy of Dramatic Arts-Los Angeles" + }, + { + "label": "American Academy of Dramatic Arts-New York" + }, + { + "label": "American Baptist College" + }, + { + "label": "American Baptist Seminary of the West" + }, + { + "label": "American Business and Technology University" + }, + { + "label": "American Career College-Anaheim" + }, + { + "label": "American Career College-Los Angeles" + }, + { + "label": "American Career College-Ontario" + }, + { + "label": "American College for Medical Careers" + }, + { + "label": "American College of Acupuncture and Oriental Med" + }, + { + "label": "American College of Education" + }, + { + "label": "American College of Financial Services" + }, + { + "label": "American College of Healthcare Sciences" + }, + { + "label": "American College of Traditional Chinese Medicine" + }, + { + "label": "American Conservatory Theater" + }, + { + "label": "American Film Institute Conservatory" + }, + { + "label": "American Indian College Inc" + }, + { + "label": "American Institute of Alternative Medicine" + }, + { + "label": "American InterContinental University-Atlanta" + }, + { + "label": "American InterContinental University-Houston" + }, + { + "label": "American InterContinental University-Online" + }, + { + "label": "American InterContinental University-South Florida" + }, + { + "label": "American International College" + }, + { + "label": "American Jewish University" + }, + { + "label": "American Medical Academy" + }, + { + "label": "American Musical and Dramatic Academy" + }, + { + "label": "American National University" + }, + { + "label": "American Public University System" + }, + { + "label": "American River College" + }, + { + "label": "American Samoa Community College" + }, + { + "label": "American Sentinel University" + }, + { + "label": "American University" + }, + { + "label": "American University of Health Sciences" + }, + { + "label": "American University of Puerto Rico-Bayamon" + }, + { + "label": "American University of Puerto Rico-Manati" + }, + { + "label": "AmeriTech College-Draper" + }, + { + "label": "Amherst College" + }, + { + "label": "Amridge University" + }, + { + "label": "Anabaptist Mennonite Biblical Seminary" + }, + { + "label": "Ancilla College" + }, + { + "label": "Anderson University-Anderson" + }, + { + "label": "Anderson University-Anderson" + }, + { + "label": "Andover Newton Theological School" + }, + { + "label": "Andrew College" + }, + { + "label": "Andrews University" + }, + { + "label": "Angeles College" + }, + { + "label": "Angelina College" + }, + { + "label": "Angelo State University" + }, + { + "label": "Anna Maria College" + }, + { + "label": "Anne Arundel Community College" + }, + { + "label": "Anoka Technical College" + }, + { + "label": "Anoka-Ramsey Community College" + }, + { + "label": "Antelope Valley College" + }, + { + "label": "Antioch University-Los Angeles" + }, + { + "label": "Antioch University-Midwest" + }, + { + "label": "Antioch University-New England" + }, + { + "label": "Antioch University-PhD Program in Leadership and Change" + }, + { + "label": "Antioch University-Santa Barbara" + }, + { + "label": "Antioch University-Seattle" + }, + { + "label": "Antonelli College-Cincinnati" + }, + { + "label": "Antonelli College-Hattiesburg" + }, + { + "label": "Antonelli College-Jackson" + }, + { + "label": "Antonelli Institute" + }, + { + "label": "AOMA Graduate School of Integrative Medicine" + }, + { + "label": "Apex School of Theology" + }, + { + "label": "Appalachian Bible College" + }, + { + "label": "Appalachian College of Pharmacy" + }, + { + "label": "Appalachian School of Law" + }, + { + "label": "Appalachian State University" + }, + { + "label": "Aquinas College-Grand Rapids" + }, + { + "label": "Aquinas College-Nashville" + }, + { + "label": "Aquinas Institute of Theology" + }, + { + "label": "Arapahoe Community College" + }, + { + "label": "Arcadia University" + }, + { + "label": "Argosy University-Atlanta" + }, + { + "label": "Argosy University-Chicago" + }, + { + "label": "Argosy University-Dallas" + }, + { + "label": "Argosy University-Denver" + }, + { + "label": "Argosy University-Hawaii" + }, + { + "label": "Argosy University-Inland Empire" + }, + { + "label": "Argosy University-Los Angeles" + }, + { + "label": "Argosy University-Nashville" + }, + { + "label": "Argosy University-Orange County" + }, + { + "label": "Argosy University-Phoenix" + }, + { + "label": "Argosy University-Phoenix Online Division" + }, + { + "label": "Argosy University-Salt Lake City" + }, + { + "label": "Argosy University-San Diego" + }, + { + "label": "Argosy University-San Francisco Bay Area" + }, + { + "label": "Argosy University-Sarasota" + }, + { + "label": "Argosy University-Schaumburg" + }, + { + "label": "Argosy University-Seattle" + }, + { + "label": "Argosy University-Tampa" + }, + { + "label": "Argosy University-The Art Institute of California-Hollywood" + }, + { + "label": "Argosy University-The Art Institute of California-Inland Empire" + }, + { + "label": "Argosy University-The Art Institute of California-Los Angeles" + }, + { + "label": "Argosy University-The Art Institute of California-Orange County" + }, + { + "label": "Argosy University-The Art Institute of California-Sacramento" + }, + { + "label": "Argosy University-The Art Institute of California-San Diego" + }, + { + "label": "Argosy University-The Art Institute of California-San Francisco" + }, + { + "label": "Argosy University-The Art Institute of California-Silicon Valley" + }, + { + "label": "Argosy University-Twin Cities" + }, + { + "label": "Argosy University-Washington DC" + }, + { + "label": "Arizona Christian University" + }, + { + "label": "Arizona College-Glendale" + }, + { + "label": "Arizona College-Mesa" + }, + { + "label": "Arizona School of Acupuncture and Oriental Medicine" + }, + { + "label": "Arizona State University-Downtown Phoenix" + }, + { + "label": "Arizona State University-Polytechnic" + }, + { + "label": "Arizona State University-Skysong" + }, + { + "label": "Arizona State University-Tempe" + }, + { + "label": "Arizona State University-West" + }, + { + "label": "Arizona Summit Law School" + }, + { + "label": "Arizona Western College" + }, + { + "label": "Arkansas Baptist College" + }, + { + "label": "Arkansas Northeastern College" + }, + { + "label": "Arkansas State University-Beebe" + }, + { + "label": "Arkansas State University-Main Campus" + }, + { + "label": "Arkansas State University-Mid-South" + }, + { + "label": "Arkansas State University-Mountain Home" + }, + { + "label": "Arkansas State University-Newport" + }, + { + "label": "Arkansas Tech University" + }, + { + "label": "Arlington Baptist College" + }, + { + "label": "Armstrong State University" + }, + { + "label": "Art Academy of Cincinnati" + }, + { + "label": "Art Center College of Design" + }, + { + "label": "ASA College" + }, + { + "label": "Asbury Theological Seminary" + }, + { + "label": "Asbury University" + }, + { + "label": "Ashdown College of Health Sciences" + }, + { + "label": "Asher College" + }, + { + "label": "Asheville-Buncombe Technical Community College" + }, + { + "label": "Ashford University" + }, + { + "label": "Ashland Community and Technical College" + }, + { + "label": "Ashland University" + }, + { + "label": "Asnuntuck Community College" + }, + { + "label": "Aspen University" + }, + { + "label": "Assemblies of God Theological Seminary" + }, + { + "label": "Assumption College" + }, + { + "label": "Assumption College for Sisters" + }, + { + "label": "ATA Career Education" + }, + { + "label": "ATA College" + }, + { + "label": "Atenas College" + }, + { + "label": "Athenaeum of Ohio" + }, + { + "label": "Athens State University" + }, + { + "label": "Athens Technical College" + }, + { + "label": "Atlanta Metropolitan State College" + }, + { + "label": "Atlanta Technical College" + }, + { + "label": "Atlanta's John Marshall Law School" + }, + { + "label": "Atlantic Cape Community College" + }, + { + "label": "Atlantic Institute of Oriental Medicine" + }, + { + "label": "Atlantic University College" + }, + { + "label": "Auburn University" + }, + { + "label": "Auburn University at Montgomery" + }, + { + "label": "Augsburg College" + }, + { + "label": "Augusta Technical College" + }, + { + "label": "Augusta University" + }, + { + "label": "Augustana College-Rock Island" + }, + { + "label": "Augustana University" + }, + { + "label": "Aultman College of Nursing and Health Sciences" + }, + { + "label": "Aurora University" + }, + { + "label": "Austin College" + }, + { + "label": "Austin Community College District" + }, + { + "label": "Austin Graduate School of Theology" + }, + { + "label": "Austin Peay State University" + }, + { + "label": "Austin Presbyterian Theological Seminary" + }, + { + "label": "Ave Maria School of Law" + }, + { + "label": "Ave Maria University" + }, + { + "label": "Averett University" + }, + { + "label": "Averett University-Non-Traditional Programs" + }, + { + "label": "Aviator College of Aeronautical Science and Technology" + }, + { + "label": "Avila University" + }, + { + "label": "AVTEC-Alaska's Institute of Technology" + }, + { + "label": "Azure College" + }, + { + "label": "Azusa Pacific University" + }, + { + "label": "Azusa Pacific University College" + }, + { + "label": "Babson College" + }, + { + "label": "Bacone College" + }, + { + "label": "Bainbridge State College" + }, + { + "label": "Bais HaMedrash and Mesivta of Baltimore" + }, + { + "label": "Bais Medrash Elyon" + }, + { + "label": "Bais Medrash Toras Chesed" + }, + { + "label": "Baker College" + }, + { + "label": "Baker College Center for Graduate Studies" + }, + { + "label": "Baker College of Allen Park" + }, + { + "label": "Baker College of Auburn Hills" + }, + { + "label": "Baker College of Cadillac" + }, + { + "label": "Baker College of Clinton Township" + }, + { + "label": "Baker College of Jackson" + }, + { + "label": "Baker College of Muskegon" + }, + { + "label": "Baker College of Owosso" + }, + { + "label": "Baker College of Port Huron" + }, + { + "label": "Baker University" + }, + { + "label": "Bakersfield College" + }, + { + "label": "Bakke Graduate University" + }, + { + "label": "Baldwin Wallace University" + }, + { + "label": "Ball State University" + }, + { + "label": "Baltimore City Community College" + }, + { + "label": "Bank Street College of Education" + }, + { + "label": "Baptist Bible College" + }, + { + "label": "Clarks Summit University" + }, + { + "label": "Baptist Health System School of Health Professions" + }, + { + "label": "Baptist Memorial College of Health Sciences" + }, + { + "label": "Baptist Missionary Association Theological Seminary" + }, + { + "label": "Baptist Theological Seminary at Richmond" + }, + { + "label": "Baptist University of the Americas" + }, + { + "label": "Barclay College" + }, + { + "label": "Bard College" + }, + { + "label": "Bard College at Simon's Rock" + }, + { + "label": "Barnard College" + }, + { + "label": "Barnes-Jewish College Goldfarb School of Nursing" + }, + { + "label": "Barry University" + }, + { + "label": "Barstow Community College" + }, + { + "label": "Barton College" + }, + { + "label": "Barton County Community College" + }, + { + "label": "Bastyr University" + }, + { + "label": "Bates College" + }, + { + "label": "Bates Technical College" + }, + { + "label": "Baton Rouge Community College" + }, + { + "label": "Baton Rouge School of Computers" + }, + { + "label": "Bauder College" + }, + { + "label": "Bay de Noc Community College" + }, + { + "label": "Bay Mills Community College" + }, + { + "label": "Bay Path University" + }, + { + "label": "Bay State College" + }, + { + "label": "Baylor College of Medicine" + }, + { + "label": "Baylor University" + }, + { + "label": "Beacon College" + }, + { + "label": "Beal College" + }, + { + "label": "Beaufort County Community College" + }, + { + "label": "Becker College" + }, + { + "label": "Beckfield College-Florence" + }, + { + "label": "Beckfield College-Tri-County" + }, + { + "label": "Be'er Yaakov Talmudic Seminary" + }, + { + "label": "Beis Medrash Heichal Dovid" + }, + { + "label": "Belanger School of Nursing" + }, + { + "label": "Belhaven University" + }, + { + "label": "Bellarmine University" + }, + { + "label": "Bellevue College" + }, + { + "label": "Bellevue University" + }, + { + "label": "Bellin College" + }, + { + "label": "Bellingham Technical College" + }, + { + "label": "Belmont Abbey College" + }, + { + "label": "Belmont College" + }, + { + "label": "Belmont University" + }, + { + "label": "Beloit College" + }, + { + "label": "Bel-Rea Institute of Animal Technology" + }, + { + "label": "Bemidji State University" + }, + { + "label": "Benedict College" + }, + { + "label": "Benedictine College" + }, + { + "label": "Benedictine University" + }, + { + "label": "Benjamin Franklin Institute of Technology" + }, + { + "label": "Bennett College" + }, + { + "label": "Bennington College" + }, + { + "label": "Bentley University" + }, + { + "label": "Berea College" + }, + { + "label": "Bergen Community College" + }, + { + "label": "Bergin University of Canine Studies" + }, + { + "label": "Berkeley City College" + }, + { + "label": "Berkeley College-New York" + }, + { + "label": "Berkeley College-Woodland Park" + }, + { + "label": "Berklee College of Music" + }, + { + "label": "Berks Technical Institute" + }, + { + "label": "Berkshire Community College" + }, + { + "label": "Berry College" + }, + { + "label": "Beth Hamedrash Shaarei Yosher Institute" + }, + { + "label": "Beth Hatalmud Rabbinical College" + }, + { + "label": "Beth Medrash Govoha" + }, + { + "label": "Bethany College-Bethany" + }, + { + "label": "Bethany College-Lindsborg" + }, + { + "label": "Bethany Lutheran College" + }, + { + "label": "Bethany Theological Seminary" + }, + { + "label": "Bethel College" + }, + { + "label": "Bethel College-Indiana" + }, + { + "label": "Bethel College-North Newton" + }, + { + "label": "Bethel Seminary-San Diego" + }, + { + "label": "Bethel Seminary-St Paul" + }, + { + "label": "Bethel University-McKenzie" + }, + { + "label": "Bethel University-Saint Paul" + }, + { + "label": "Bethesda University" + }, + { + "label": "Bethune-Cookman University" + }, + { + "label": "Beulah Heights University" + }, + { + "label": "Bevill State Community College" + }, + { + "label": "Bexley Hall Seabury Western Theological Seminary Federation" + }, + { + "label": "Bexley Hall Seabury Western Theological Seminary Federation " + }, + { + "label": "Biblical Theological Seminary" + }, + { + "label": "Bidwell Training Center Inc" + }, + { + "label": "Big Bend Community College" + }, + { + "label": "Big Sandy Community and Technical College" + }, + { + "label": "Biola University" + }, + { + "label": "Birmingham Southern College" + }, + { + "label": "Birthingway College of Midwifery" + }, + { + "label": "Bishop State Community College" + }, + { + "label": "Bismarck State College" + }, + { + "label": "Black Hawk College" + }, + { + "label": "Black Hills State University" + }, + { + "label": "Black River Technical College" + }, + { + "label": "Blackburn College" + }, + { + "label": "Blackfeet Community College" + }, + { + "label": "Blackhawk Technical College" + }, + { + "label": "Bladen Community College" + }, + { + "label": "Blessing Rieman College of Nursing" + }, + { + "label": "Blinn College" + }, + { + "label": "Bloomfield College" + }, + { + "label": "Bloomsburg University of Pennsylvania" + }, + { + "label": "Blue Cliff College-Gulfport" + }, + { + "label": "Blue Mountain College" + }, + { + "label": "Blue Mountain Community College" + }, + { + "label": "Blue Ridge Community and Technical College" + }, + { + "label": "Blue Ridge Community College-Flat Rock" + }, + { + "label": "Blue Ridge Community College-Weyers Cave" + }, + { + "label": "Bluefield College" + }, + { + "label": "Bluefield State College" + }, + { + "label": "Bluegrass Community and Technical College" + }, + { + "label": "Bluffton University" + }, + { + "label": "Bob Jones University" + }, + { + "label": "Boise Bible College" + }, + { + "label": "Boise State University" + }, + { + "label": "Bon Secours Memorial College of Nursing" + }, + { + "label": "Boricua College" + }, + { + "label": "Bossier Parish Community College" + }, + { + "label": "Boston Architectural College" + }, + { + "label": "Boston Baptist College" + }, + { + "label": "Boston College" + }, + { + "label": "Boston Graduate School of Psychoanalysis Inc" + }, + { + "label": "Boston University" + }, + { + "label": "Bowdoin College" + }, + { + "label": "Bowie State University" + }, + { + "label": "Bowling Green State University-Firelands" + }, + { + "label": "Bowling Green State University-Main Campus" + }, + { + "label": "Bradford School-Columbus" + }, + { + "label": "Bradford School-Pittsburgh" + }, + { + "label": "Bradley University" + }, + { + "label": "Bramson ORT College" + }, + { + "label": "Brandeis University" + }, + { + "label": "Brandman University" + }, + { + "label": "Brazosport College" + }, + { + "label": "Brenau University" + }, + { + "label": "Brescia University" + }, + { + "label": "Brevard College" + }, + { + "label": "Brewton-Parker College" + }, + { + "label": "Briar Cliff University" + }, + { + "label": "Briarcliffe College" + }, + { + "label": "Bridgewater College" + }, + { + "label": "Bridgewater State University" + }, + { + "label": "Brigham Young University-Hawaii" + }, + { + "label": "Brigham Young University-Idaho" + }, + { + "label": "Brigham Young University-Provo" + }, + { + "label": "Brightwood Career Institute-Broomall" + }, + { + "label": "Brightwood Career Institute-Harrisburg" + }, + { + "label": "Brightwood Career Institute-Philadelphia" + }, + { + "label": "Brightwood Career Institute-Philadelphia Mills" + }, + { + "label": "Brightwood Career Institute-Pittsburgh" + }, + { + "label": "Brightwood College-Arlington" + }, + { + "label": "Brightwood College-Bakersfield" + }, + { + "label": "Brightwood College-Baltimore" + }, + { + "label": "Brightwood College-Beaumont" + }, + { + "label": "Brightwood College-Beltsville" + }, + { + "label": "Brightwood College-Brownsville" + }, + { + "label": "Brightwood College-Charlotte" + }, + { + "label": "Brightwood College-Chula Vista" + }, + { + "label": "Brightwood College-Corpus Christi" + }, + { + "label": "Brightwood College-Dallas" + }, + { + "label": "Brightwood College-Dayton" + }, + { + "label": "Brightwood College-El Paso" + }, + { + "label": "Brightwood College-Fort Worth" + }, + { + "label": "Brightwood College-Fresno" + }, + { + "label": "Brightwood College-Indianapolis" + }, + { + "label": "Brightwood College-Laredo" + }, + { + "label": "Brightwood College-Las Vegas" + }, + { + "label": "Brightwood College-McAllen" + }, + { + "label": "Brightwood College-Modesto" + }, + { + "label": "Brightwood College-Nashville" + }, + { + "label": "Brightwood College-Palm Springs" + }, + { + "label": "Brightwood College-Riverside" + }, + { + "label": "Brightwood College-Sacramento" + }, + { + "label": "Brightwood College-San Antonio-Ingram" + }, + { + "label": "Brightwood College-San Antonio-San Pedro" + }, + { + "label": "Brightwood College-San Diego" + }, + { + "label": "Brightwood College-Towson" + }, + { + "label": "Brightwood College-Vista" + }, + { + "label": "Bristol Community College" + }, + { + "label": "Bristol University" + }, + { + "label": "Brite Divinity School" + }, + { + "label": "Broadview Entertainment Arts University" + }, + { + "label": "Broadview University-Boise" + }, + { + "label": "Broadview University-Layton" + }, + { + "label": "Broadview University-Orem" + }, + { + "label": "Broadview University-West Jordan" + }, + { + "label": "Brookdale Community College" + }, + { + "label": "Brookhaven College" + }, + { + "label": "Brookline College-Albuquerque" + }, + { + "label": "Brookline College-Phoenix" + }, + { + "label": "Brookline College-Tempe" + }, + { + "label": "Brookline College-Tucson" + }, + { + "label": "Brooklyn Law School" + }, + { + "label": "Brooks Institute" + }, + { + "label": "Broward College" + }, + { + "label": "Brown Mackie College-Akron" + }, + { + "label": "Brown Mackie College-Albuquerque" + }, + { + "label": "Brown Mackie College-Atlanta" + }, + { + "label": "Brown Mackie College-Birmingham" + }, + { + "label": "Brown Mackie College-Boise" + }, + { + "label": "Brown Mackie College-Cincinnati" + }, + { + "label": "Brown Mackie College-Dallas" + }, + { + "label": "Brown Mackie College-Findlay" + }, + { + "label": "Brown Mackie College-Fort Wayne" + }, + { + "label": "Brown Mackie College-Greenville" + }, + { + "label": "Brown Mackie College-Hopkinsville" + }, + { + "label": "Brown Mackie College-Indianapolis" + }, + { + "label": "Brown Mackie College-Kansas City" + }, + { + "label": "Brown Mackie College-Louisville" + }, + { + "label": "Brown Mackie College-Merrillville" + }, + { + "label": "Brown Mackie College-Miami" + }, + { + "label": "Brown Mackie College-Michigan City" + }, + { + "label": "Brown Mackie College-North Canton" + }, + { + "label": "Brown Mackie College-Northern Kentucky" + }, + { + "label": "Brown Mackie College-Oklahoma City" + }, + { + "label": "Brown Mackie College-Phoenix" + }, + { + "label": "Brown Mackie College-Quad Cities" + }, + { + "label": "Brown Mackie College-Salina" + }, + { + "label": "Brown Mackie College-San Antonio" + }, + { + "label": "Brown Mackie College-South Bend" + }, + { + "label": "Brown Mackie College-St Louis" + }, + { + "label": "Brown Mackie College-Tucson" + }, + { + "label": "Brown Mackie College-Tulsa" + }, + { + "label": "Brown University" + }, + { + "label": "Brunswick Community College" + }, + { + "label": "Bryan College of Health Sciences" + }, + { + "label": "Bryan College-Dayton" + }, + { + "label": "Bryan College-Gold River" + }, + { + "label": "Bryan University-Columbia" + }, + { + "label": "Bryan University-Los Angeles" + }, + { + "label": "Bryan University-Rogers" + }, + { + "label": "Bryan University-Springfield" + }, + { + "label": "Bryan University-Topeka" + }, + { + "label": "Bryant & Stratton College-Akron" + }, + { + "label": "Bryant & Stratton College-Albany" + }, + { + "label": "Bryant & Stratton College-Amherst" + }, + { + "label": "Bryant & Stratton College-Bayshore" + }, + { + "label": "Bryant & Stratton College-Buffalo" + }, + { + "label": "Bryant & Stratton College-Cleveland" + }, + { + "label": "Bryant & Stratton College-Eastlake" + }, + { + "label": "Bryant & Stratton College-Greece" + }, + { + "label": "Bryant & Stratton College-Hampton" + }, + { + "label": "Bryant & Stratton College-Henrietta" + }, + { + "label": "Bryant & Stratton College-Milwaukee" + }, + { + "label": "Bryant & Stratton College-Online" + }, + { + "label": "Bryant & Stratton College-Parma" + }, + { + "label": "Bryant & Stratton College-Richmond" + }, + { + "label": "Bryant & Stratton College-Southtowns" + }, + { + "label": "Bryant & Stratton College-Syracuse" + }, + { + "label": "Bryant & Stratton College-Syracuse North" + }, + { + "label": "Bryant & Stratton College-Virginia Beach" + }, + { + "label": "Bryant & Stratton College-Wauwatosa" + }, + { + "label": "Bryant University" + }, + { + "label": "Bryn Athyn College of the New Church" + }, + { + "label": "Bryn Mawr College" + }, + { + "label": "Bucknell University" + }, + { + "label": "Bucks County Community College" + }, + { + "label": "Bucks County School of Beauty Culture Inc" + }, + { + "label": "Buena Vista University" + }, + { + "label": "Bunker Hill Community College" + }, + { + "label": "Burlington College" + }, + { + "label": "Burnett International College" + }, + { + "label": "Business Informatics Center Inc" + }, + { + "label": "Butler Community College" + }, + { + "label": "Butler County Community College" + }, + { + "label": "Butler University" + }, + { + "label": "Butte College" + }, + { + "label": "Byzantine Catholic Seminary of Saints Cyril and Methodius" + }, + { + "label": "Cabarrus College of Health Sciences" + }, + { + "label": "Cabrillo College" + }, + { + "label": "Cabrini University" + }, + { + "label": "Cairn University-Langhorne" + }, + { + "label": "Caldwell Community College and Technical Institute" + }, + { + "label": "Caldwell University" + }, + { + "label": "California Baptist University" + }, + { + "label": "California Christian College" + }, + { + "label": "California College of the Arts" + }, + { + "label": "California College San Diego-San Diego" + }, + { + "label": "California College San Diego-San Marcos" + }, + { + "label": "California Institute of Integral Studies" + }, + { + "label": "California Institute of Technology" + }, + { + "label": "California Institute of the Arts" + }, + { + "label": "California Lutheran University" + }, + { + "label": "California Miramar University" + }, + { + "label": "California Polytechnic State University-San Luis Obispo" + }, + { + "label": "California State Polytechnic University-Pomona" + }, + { + "label": "California State University-Bakersfield" + }, + { + "label": "California State University-Channel Islands" + }, + { + "label": "California State University-Chico" + }, + { + "label": "California State University-Dominguez Hills" + }, + { + "label": "California State University-East Bay" + }, + { + "label": "California State University-Fresno" + }, + { + "label": "California State University-Fullerton" + }, + { + "label": "California State University-Long Beach" + }, + { + "label": "California State University-Los Angeles" + }, + { + "label": "California State University-Monterey Bay" + }, + { + "label": "California State University-Northridge" + }, + { + "label": "California State University-Sacramento" + }, + { + "label": "California State University-San Bernardino" + }, + { + "label": "California State University-San Marcos" + }, + { + "label": "California State University-Stanislaus" + }, + { + "label": "California University of Management and Sciences" + }, + { + "label": "California University of Pennsylvania" + }, + { + "label": "California Western School of Law" + }, + { + "label": "Calumet College of Saint Joseph" + }, + { + "label": "Calvary Bible College and Theological Seminary" + }, + { + "label": "Calvin College" + }, + { + "label": "Calvin Theological Seminary" + }, + { + "label": "Cambria-Rowe Business College-Indiana" + }, + { + "label": "Cambria-Rowe Business College-Johnstown" + }, + { + "label": "Cambridge College" + }, + { + "label": "Cambridge College of Healthcare & Technology" + }, + { + "label": "Cambridge Junior College-Yuba City" + }, + { + "label": "Camden County College" + }, + { + "label": "Cameron College" + }, + { + "label": "Cameron University" + }, + { + "label": "Campbell University" + }, + { + "label": "Campbellsville University" + }, + { + "label": "Canada College" + }, + { + "label": "Canisius College" + }, + { + "label": "Cankdeska Cikana Community College" + }, + { + "label": "Cape Cod Community College" + }, + { + "label": "Cape Fear Community College" + }, + { + "label": "Capella University" + }, + { + "label": "Capital Area Technical College" + }, + { + "label": "Capital Community College" + }, + { + "label": "Capital University" + }, + { + "label": "Capitol Technology University" + }, + { + "label": "Cardinal Stritch University" + }, + { + "label": "Career College of Northern Nevada" + }, + { + "label": "Career Point College-San Antonio" + }, + { + "label": "Career Point College-Tulsa" + }, + { + "label": "Career Quest Learning Centers-Jackson" + }, + { + "label": "Career Quest Learning Centers-Lansing" + }, + { + "label": "Career Technical College-Monroe" + }, + { + "label": "Career Technical College-Shreveport" + }, + { + "label": "Career Training Academy-Lower Burrell" + }, + { + "label": "Career Training Academy-Monroeville" + }, + { + "label": "Career Training Academy-Pittsburgh" + }, + { + "label": "Careers Unlimited" + }, + { + "label": "Caribbean University-Bayamon" + }, + { + "label": "Caribbean University-Carolina" + }, + { + "label": "Caribbean University-Ponce" + }, + { + "label": "Caribbean University-Vega Baja" + }, + { + "label": "Carl Albert State College" + }, + { + "label": "Carl Sandburg College" + }, + { + "label": "Carleton College" + }, + { + "label": "Carlos Albizu University-Miami" + }, + { + "label": "Carlos Albizu University-San Juan" + }, + { + "label": "Carlow University" + }, + { + "label": "Carnegie Mellon University" + }, + { + "label": "Carolina Christian College" + }, + { + "label": "Carolina College of Biblical Studies" + }, + { + "label": "Carolinas College of Health Sciences" + }, + { + "label": "Carrington College-Albuquerque" + }, + { + "label": "Carrington College-Boise" + }, + { + "label": "Carrington College-Citrus Heights" + }, + { + "label": "Carrington College-Las Vegas" + }, + { + "label": "Carrington College-Mesa" + }, + { + "label": "Carrington College-Phoenix" + }, + { + "label": "Carrington College-Pleasant Hill" + }, + { + "label": "Carrington College-Pomona" + }, + { + "label": "Carrington College-Portland" + }, + { + "label": "Carrington College-Reno" + }, + { + "label": "Carrington College-Sacramento" + }, + { + "label": "Carrington College-San Jose" + }, + { + "label": "Carrington College-San Leandro" + }, + { + "label": "Carrington College-Spokane" + }, + { + "label": "Carrington College-Stockton" + }, + { + "label": "Carrington College-Tucson" + }, + { + "label": "Carrington College-Westside" + }, + { + "label": "Carroll College" + }, + { + "label": "Carroll Community College" + }, + { + "label": "Carroll University" + }, + { + "label": "Carson-Newman University" + }, + { + "label": "Carteret Community College" + }, + { + "label": "Carthage College" + }, + { + "label": "Carver Bible College" + }, + { + "label": "Carver Career Center" + }, + { + "label": "Casa Loma College-Van Nuys" + }, + { + "label": "Cascadia College" + }, + { + "label": "Case Western Reserve University" + }, + { + "label": "Casper College" + }, + { + "label": "Castleton State College" + }, + { + "label": "Catawba College" + }, + { + "label": "Catawba Valley Community College" + }, + { + "label": "Catholic Distance University" + }, + { + "label": "Catholic Theological Union at Chicago" + }, + { + "label": "Catholic University of America" + }, + { + "label": "Cayuga County Community College" + }, + { + "label": "Cazenovia College" + }, + { + "label": "Cecil College" + }, + { + "label": "Cedar Crest College" + }, + { + "label": "Cedar Valley College" + }, + { + "label": "Cedarville University" + }, + { + "label": "Centenary College" + }, + { + "label": "Centenary College of Louisiana" + }, + { + "label": "Center for Advanced Legal Studies" + }, + { + "label": "Center for Advanced Studies On Puerto Rico and the Caribbean" + }, + { + "label": "Centra College of Nursing" + }, + { + "label": "Central Alabama Community College" + }, + { + "label": "Central Arizona College" + }, + { + "label": "Central Baptist College" + }, + { + "label": "Central Baptist Theological Seminary" + }, + { + "label": "Central Carolina Community College" + }, + { + "label": "Central Carolina Technical College" + }, + { + "label": "Central Christian College of Kansas" + }, + { + "label": "Central Christian College of the Bible" + }, + { + "label": "Central College" + }, + { + "label": "Central Community College" + }, + { + "label": "Central Connecticut State University" + }, + { + "label": "Central Florida Institute" + }, + { + "label": "Central Georgia Technical College" + }, + { + "label": "Central Lakes College-Brainerd" + }, + { + "label": "Central Louisiana Technical Community College" + }, + { + "label": "Central Maine Community College" + }, + { + "label": "Central Methodist University-College of Graduate and Extended Studies" + }, + { + "label": "Central Methodist University-College of Liberal Arts and Sciences" + }, + { + "label": "Central Michigan University" + }, + { + "label": "Central New Mexico Community College" + }, + { + "label": "Central Ohio Technical College" + }, + { + "label": "Central Oregon Community College" + }, + { + "label": "Central Penn College" + }, + { + "label": "Central Piedmont Community College" + }, + { + "label": "Central State University" + }, + { + "label": "Central Texas College" + }, + { + "label": "Central Virginia Community College" + }, + { + "label": "Central Washington University" + }, + { + "label": "Central Wyoming College" + }, + { + "label": "Central Yeshiva Tomchei Tmimim Lubavitz" + }, + { + "label": "Centralia College" + }, + { + "label": "Centre College" + }, + { + "label": "Centro de Estudios Multidisciplinarios-Bayamon" + }, + { + "label": "Centro de Estudios Multidisciplinarios-Humacao" + }, + { + "label": "Centro de Estudios Multidisciplinarios-San Juan" + }, + { + "label": "Centura College-Chesapeake" + }, + { + "label": "Centura College-Columbia" + }, + { + "label": "Centura College-Newport News" + }, + { + "label": "Centura College-Norfolk" + }, + { + "label": "Centura College-Richmond Main" + }, + { + "label": "Centura College-Virginia Beach" + }, + { + "label": "Century College-White Bear Lake" + }, + { + "label": "Cerritos College" + }, + { + "label": "Cerro Coso Community College" + }, + { + "label": "Chabot College" + }, + { + "label": "Chadron State College" + }, + { + "label": "Chaffey College" + }, + { + "label": "Chamberlain College of Nursing-Arizona" + }, + { + "label": "Chamberlain College of Nursing-Florida" + }, + { + "label": "Chamberlain College of Nursing-Georgia" + }, + { + "label": "Chamberlain College of Nursing-Illinois" + }, + { + "label": "Chamberlain College of Nursing-Missouri" + }, + { + "label": "Chamberlain College of Nursing-Ohio" + }, + { + "label": "Chamberlain College of Nursing-Texas" + }, + { + "label": "Chamberlain College of Nursing-Virginia" + }, + { + "label": "Chaminade University of Honolulu" + }, + { + "label": "Champlain College" + }, + { + "label": "Chandler-Gilbert Community College" + }, + { + "label": "Chapman University" + }, + { + "label": "Charles R Drew University of Medicine and Science" + }, + { + "label": "Charleston School of Law" + }, + { + "label": "Charleston Southern University" + }, + { + "label": "Charlotte Christian College and Theological Seminary" + }, + { + "label": "Charlotte School of Law" + }, + { + "label": "Charter College-Anchorage" + }, + { + "label": "Charter College-Canyon Country" + }, + { + "label": "Charter Oak State College" + }, + { + "label": "Chatfield College" + }, + { + "label": "Chatham University" + }, + { + "label": "Chattahoochee Technical College" + }, + { + "label": "Chattahoochee Valley Community College" + }, + { + "label": "Chattanooga College Medical Dental and Technical Careers" + }, + { + "label": "Chattanooga State Community College" + }, + { + "label": "Chemeketa Community College" + }, + { + "label": "Chesapeake College" + }, + { + "label": "Chester Career College" + }, + { + "label": "Chestnut Hill College" + }, + { + "label": "Cheyney University of Pennsylvania" + }, + { + "label": "CHI Health School of Radiologic Technology" + }, + { + "label": "Chicago ORT Technical Institute" + }, + { + "label": "Chicago State University" + }, + { + "label": "Chicago Theological Seminary" + }, + { + "label": "Chief Dull Knife College" + }, + { + "label": "Chipola College" + }, + { + "label": "Chippewa Valley Technical College" + }, + { + "label": "Chowan University" + }, + { + "label": "Christ the King Seminary" + }, + { + "label": "Christian Brothers University" + }, + { + "label": "Christian Life College" + }, + { + "label": "Christian Theological Seminary" + }, + { + "label": "Christie's Education" + }, + { + "label": "Christopher Newport University" + }, + { + "label": "Church Divinity School of the Pacific" + }, + { + "label": "Cincinnati Christian University" + }, + { + "label": "Cincinnati College of Mortuary Science" + }, + { + "label": "Cincinnati State Technical and Community College" + }, + { + "label": "Cisco College" + }, + { + "label": "Citadel Military College of South Carolina" + }, + { + "label": "Citrus College" + }, + { + "label": "City College of San Francisco" + }, + { + "label": "City College-Altamonte Springs" + }, + { + "label": "City College-Fort Lauderdale" + }, + { + "label": "City College-Gainesville" + }, + { + "label": "City College-Hollywood" + }, + { + "label": "City College-Miami" + }, + { + "label": "City Colleges of Chicago-Harold Washington College" + }, + { + "label": "City Colleges of Chicago-Harry S Truman College" + }, + { + "label": "City Colleges of Chicago-Kennedy-King College" + }, + { + "label": "City Colleges of Chicago-Malcolm X College" + }, + { + "label": "City Colleges of Chicago-Olive-Harvey College" + }, + { + "label": "City Colleges of Chicago-Richard J Daley College" + }, + { + "label": "City Colleges of Chicago-Wilbur Wright College" + }, + { + "label": "City University of Seattle" + }, + { + "label": "City Vision University" + }, + { + "label": "Clackamas Community College" + }, + { + "label": "Claflin University" + }, + { + "label": "Claremont Graduate University" + }, + { + "label": "Claremont McKenna College" + }, + { + "label": "Claremont School of Theology" + }, + { + "label": "Clarendon College" + }, + { + "label": "Clarion University of Pennsylvania" + }, + { + "label": "Clark Atlanta University" + }, + { + "label": "Clark College" + }, + { + "label": "Clark State Community College" + }, + { + "label": "Clark University" + }, + { + "label": "Clarke University" + }, + { + "label": "Clarkson College" + }, + { + "label": "Clarkson University" + }, + { + "label": "Clary Sage College" + }, + { + "label": "Clatsop Community College" + }, + { + "label": "Clayton State University" + }, + { + "label": "Clear Creek Baptist Bible College" + }, + { + "label": "Clearwater Christian College" + }, + { + "label": "Cleary University" + }, + { + "label": "Clemson University" + }, + { + "label": "Cleveland Community College" + }, + { + "label": "Cleveland Institute of Art" + }, + { + "label": "Cleveland Institute of Music" + }, + { + "label": "Cleveland State Community College" + }, + { + "label": "Cleveland State University" + }, + { + "label": "Cleveland University-Kansas City" + }, + { + "label": "Clinton College" + }, + { + "label": "Clinton Community College" + }, + { + "label": "Cloud County Community College" + }, + { + "label": "Clover Park Technical College" + }, + { + "label": "Clovis Community College" + }, + { + "label": "Coahoma Community College" + }, + { + "label": "Coastal Bend College" + }, + { + "label": "Coastal Carolina Community College" + }, + { + "label": "Coastal Carolina University" + }, + { + "label": "Coastal Pines Technical College-Waycross" + }, + { + "label": "Coastline Community College" + }, + { + "label": "Cochise County Community College District" + }, + { + "label": "Cochran School of Nursing" + }, + { + "label": "Coconino Community College" + }, + { + "label": "Coe College" + }, + { + "label": "Coffeyville Community College" + }, + { + "label": "Cogswell College" + }, + { + "label": "Coker College" + }, + { + "label": "Colby College" + }, + { + "label": "Colby Community College" + }, + { + "label": "Colby-Sawyer College" + }, + { + "label": "Colegio de Cinematografía Artes y Television" + }, + { + "label": "Colegio Universitario de San Juan" + }, + { + "label": "Coleman University" + }, + { + "label": "Colgate Rochester Crozer Divinity School" + }, + { + "label": "Colgate University" + }, + { + "label": "College for Creative Studies" + }, + { + "label": "College of Alameda" + }, + { + "label": "College of Biblical Studies-Houston" + }, + { + "label": "College of Business and Technology-Cutler Bay" + }, + { + "label": "College of Business and Technology-Flagler" + }, + { + "label": "College of Business and Technology-Hialeah" + }, + { + "label": "College of Business and Technology-Kendall" + }, + { + "label": "College of Business and Technology-Miami Gardens" + }, + { + "label": "College of Central Florida" + }, + { + "label": "College of Charleston" + }, + { + "label": "College of Coastal Georgia" + }, + { + "label": "College of Court Reporting Inc" + }, + { + "label": "College of DuPage" + }, + { + "label": "College of Health Care Professions-Northwest" + }, + { + "label": "College of Lake County" + }, + { + "label": "College of Marin" + }, + { + "label": "College of Menominee Nation" + }, + { + "label": "College of Micronesia-FSM" + }, + { + "label": "College of Mount Saint Vincent" + }, + { + "label": "College of Our Lady of the Elms" + }, + { + "label": "College of Saint Benedict" + }, + { + "label": "College of Saint Elizabeth" + }, + { + "label": "College of Saint Mary" + }, + { + "label": "College of San Mateo" + }, + { + "label": "College of Southern Idaho" + }, + { + "label": "College of Southern Maryland" + }, + { + "label": "College of Southern Nevada" + }, + { + "label": "College of St Joseph" + }, + { + "label": "College of Staten Island CUNY" + }, + { + "label": "College of the Albemarle" + }, + { + "label": "College of the Atlantic" + }, + { + "label": "College of the Canyons" + }, + { + "label": "College of the Desert" + }, + { + "label": "College of the Holy Cross" + }, + { + "label": "College of the Mainland" + }, + { + "label": "College of the Marshall Islands" + }, + { + "label": "College of the Muscogee Nation" + }, + { + "label": "College of the Ouachitas" + }, + { + "label": "College of the Ozarks" + }, + { + "label": "College of the Redwoods" + }, + { + "label": "College of the Sequoias" + }, + { + "label": "College of the Siskiyous" + }, + { + "label": "College of Western Idaho" + }, + { + "label": "College of William and Mary" + }, + { + "label": "CollegeAmerica-Cheyenne" + }, + { + "label": "CollegeAmerica-Colorado Springs" + }, + { + "label": "CollegeAmerica-Denver" + }, + { + "label": "CollegeAmerica-Flagstaff" + }, + { + "label": "CollegeAmerica-Fort Collins" + }, + { + "label": "CollegeAmerica-Phoenix" + }, + { + "label": "Collin County Community College District" + }, + { + "label": "Collins College" + }, + { + "label": "Colorado Academy of Veterinary Technology" + }, + { + "label": "Colorado Christian University" + }, + { + "label": "Colorado College" + }, + { + "label": "Colorado Heights University" + }, + { + "label": "Colorado Mesa University" + }, + { + "label": "Colorado Mountain College" + }, + { + "label": "Colorado Northwestern Community College" + }, + { + "label": "Colorado School of Healing Arts" + }, + { + "label": "Colorado School of Mines" + }, + { + "label": "Colorado School of Trades" + }, + { + "label": "Colorado School of Traditional Chinese Medicine" + }, + { + "label": "Colorado State University-Fort Collins" + }, + { + "label": "Colorado State University-Global Campus" + }, + { + "label": "Colorado State University-Pueblo" + }, + { + "label": "Colorado Technical University-Colorado Springs" + }, + { + "label": "Colorado Technical University-Greenwood Village" + }, + { + "label": "Colorado Technical University-Online" + }, + { + "label": "Colorado Technical University-Sioux Falls" + }, + { + "label": "Columbia Basin College" + }, + { + "label": "Columbia Central University-Caguas" + }, + { + "label": "Columbia Central University-Yauco" + }, + { + "label": "Columbia College of Nursing" + }, + { + "label": "Columbia College-Chicago" + }, + { + "label": "Columbia College-Columbia" + }, + { + "label": "Columbia College-Columbia" + }, + { + "label": "Columbia College-Fairfax" + }, + { + "label": "Columbia College-Hollywood" + }, + { + "label": "Columbia College-Sonora" + }, + { + "label": "Columbia Gorge Community College" + }, + { + "label": "Columbia International University" + }, + { + "label": "Columbia Southern University" + }, + { + "label": "Columbia State Community College" + }, + { + "label": "Columbia Theological Seminary" + }, + { + "label": "Columbia University in the City of New York" + }, + { + "label": "Columbia-Greene Community College" + }, + { + "label": "Columbus College of Art and Design" + }, + { + "label": "Columbus State Community College" + }, + { + "label": "Columbus State University" + }, + { + "label": "Columbus Technical College" + }, + { + "label": "Comanche Nation College" + }, + { + "label": "Commonwealth Institute of Funeral Service" + }, + { + "label": "Commonwealth Technical Institute" + }, + { + "label": "Community Care College" + }, + { + "label": "Community Christian College" + }, + { + "label": "Community College of Allegheny County" + }, + { + "label": "Community College of Aurora" + }, + { + "label": "Community College of Beaver County" + }, + { + "label": "Community College of Denver" + }, + { + "label": "Community College of Philadelphia" + }, + { + "label": "Community College of Rhode Island" + }, + { + "label": "Community College of Vermont" + }, + { + "label": "Compass College of Cinematic Arts" + }, + { + "label": "Conception Seminary College" + }, + { + "label": "Concord University" + }, + { + "label": "Concorde Career College-Aurora" + }, + { + "label": "Concorde Career College-Dallas" + }, + { + "label": "Concorde Career College-Garden Grove" + }, + { + "label": "Concorde Career College-Grand Prairie" + }, + { + "label": "Concorde Career College-Kansas City" + }, + { + "label": "Concorde Career College-Memphis" + }, + { + "label": "Concorde Career College-North Hollywood" + }, + { + "label": "Concorde Career College-Portland" + }, + { + "label": "Concorde Career College-San Antonio" + }, + { + "label": "Concorde Career College-San Bernardino" + }, + { + "label": "Concorde Career College-San Diego" + }, + { + "label": "Concorde Career Institute-Jacksonville" + }, + { + "label": "Concorde Career Institute-Miramar" + }, + { + "label": "Concorde Career Institute-Orlando" + }, + { + "label": "Concorde Career Institute-Tampa" + }, + { + "label": "Concordia College Alabama" + }, + { + "label": "Concordia College at Moorhead" + }, + { + "label": "Concordia College-New York" + }, + { + "label": "Concordia Seminary" + }, + { + "label": "Concordia Theological Seminary" + }, + { + "label": "Concordia University-Ann Arbor" + }, + { + "label": "Concordia University-Chicago" + }, + { + "label": "Concordia University-Irvine" + }, + { + "label": "Concordia University-Nebraska" + }, + { + "label": "Concordia University-Portland" + }, + { + "label": "Concordia University-Saint Paul" + }, + { + "label": "Concordia University-Texas" + }, + { + "label": "Concordia University-Wisconsin" + }, + { + "label": "Connecticut College" + }, + { + "label": "Connors State College" + }, + { + "label": "Consolidated School of Business-Lancaster" + }, + { + "label": "Consolidated School of Business-York" + }, + { + "label": "Contra Costa College" + }, + { + "label": "Converse College" + }, + { + "label": "Conway School of Landscape Design" + }, + { + "label": "Cooper Union for the Advancement of Science and Art" + }, + { + "label": "Copiah-Lincoln Community College" + }, + { + "label": "Copper Mountain Community College" + }, + { + "label": "Coppin State University" + }, + { + "label": "Corban University" + }, + { + "label": "Cornell College" + }, + { + "label": "Cornell University" + }, + { + "label": "Cornerstone University" + }, + { + "label": "Corning Community College" + }, + { + "label": "Cornish College of the Arts" + }, + { + "label": "Cossatot Community College of the University of Arkansas" + }, + { + "label": "Cosumnes River College" + }, + { + "label": "Cottey College" + }, + { + "label": "County College of Morris" + }, + { + "label": "Court Reporting Institute of Dallas" + }, + { + "label": "Covenant College" + }, + { + "label": "Covenant Theological Seminary" + }, + { + "label": "Cowley County Community College" + }, + { + "label": "Cox College" + }, + { + "label": "Coyne College" + }, + { + "label": "Crafton Hills College" + }, + { + "label": "Cranbrook Academy of Art" + }, + { + "label": "Craven Community College" + }, + { + "label": "Creighton University" + }, + { + "label": "Criswell College" + }, + { + "label": "Crossroads Bible College" + }, + { + "label": "Crossroads College" + }, + { + "label": "Crowder College" + }, + { + "label": "Crowley's Ridge College" + }, + { + "label": "Crown College" + }, + { + "label": "Cuesta College" + }, + { + "label": "Culinary Institute Inc" + }, + { + "label": "Culinary Institute of America" + }, + { + "label": "Culver-Stockton College" + }, + { + "label": "Cumberland County College" + }, + { + "label": "Cumberland University" + }, + { + "label": "CUNY Bernard M Baruch College" + }, + { + "label": "CUNY Borough of Manhattan Community College" + }, + { + "label": "CUNY Bronx Community College" + }, + { + "label": "CUNY Brooklyn College" + }, + { + "label": "CUNY City College" + }, + { + "label": "CUNY Graduate School and University Center" + }, + { + "label": "CUNY Hostos Community College" + }, + { + "label": "CUNY Hunter College" + }, + { + "label": "CUNY John Jay College of Criminal Justice" + }, + { + "label": "CUNY Kingsborough Community College" + }, + { + "label": "CUNY LaGuardia Community College" + }, + { + "label": "CUNY Lehman College" + }, + { + "label": "CUNY Medgar Evers College" + }, + { + "label": "CUNY New York City College of Technology" + }, + { + "label": "CUNY Queens College" + }, + { + "label": "CUNY Queensborough Community College" + }, + { + "label": "CUNY School of Law" + }, + { + "label": "CUNY York College" + }, + { + "label": "Curry College" + }, + { + "label": "Curtis Institute of Music" + }, + { + "label": "Cuyahoga Community College District" + }, + { + "label": "Cuyamaca College" + }, + { + "label": "Cypress College" + }, + { + "label": "Dabney S Lancaster Community College" + }, + { + "label": "Dade Medical College-Hollywood" + }, + { + "label": "Dade Medical College-Homestead" + }, + { + "label": "Dade Medical College-Jacksonville" + }, + { + "label": "Dade Medical College-Miami" + }, + { + "label": "Dade Medical College-Miami Lakes" + }, + { + "label": "Dade Medical College-West Palm Beach" + }, + { + "label": "Daemen College" + }, + { + "label": "Dakota College at Bottineau" + }, + { + "label": "Dakota County Technical College" + }, + { + "label": "Dakota State University" + }, + { + "label": "Dakota Wesleyan University" + }, + { + "label": "Dallas Baptist University" + }, + { + "label": "Dallas Christian College" + }, + { + "label": "Dallas Institute of Funeral Service" + }, + { + "label": "Dallas Nursing Institute" + }, + { + "label": "Dallas Theological Seminary" + }, + { + "label": "Dalton State College" + }, + { + "label": "Daniel Webster College" + }, + { + "label": "Danville Area Community College" + }, + { + "label": "Danville Community College" + }, + { + "label": "Daoist Traditions College of Chinese Medical Arts" + }, + { + "label": "Dartmouth College" + }, + { + "label": "Darton State College" + }, + { + "label": "Davenport University" + }, + { + "label": "Davidson College" + }, + { + "label": "Davidson County Community College" + }, + { + "label": "Davis & Elkins College" + }, + { + "label": "Davis College-Johnson City" + }, + { + "label": "Davis College-Toledo" + }, + { + "label": "Dawson Community College" + }, + { + "label": "Daymar College-Bellevue" + }, + { + "label": "Daymar College-Bowling Green" + }, + { + "label": "Daymar College-Chillicothe" + }, + { + "label": "Daymar College-Jackson" + }, + { + "label": "Daymar College-Lancaster" + }, + { + "label": "Daymar College-Louisville-Louisville" + }, + { + "label": "Daymar College-Madisonville" + }, + { + "label": "Daymar College-New Boston" + }, + { + "label": "Daymar College-Online" + }, + { + "label": "Daymar College-Owensboro" + }, + { + "label": "Daymar College-Paducah Main" + }, + { + "label": "Daymar Institute-Clarksville" + }, + { + "label": "Daymar Institute-Murfreesboro" + }, + { + "label": "Daymar Institute-Nashville" + }, + { + "label": "Daytona College" + }, + { + "label": "Daytona State College" + }, + { + "label": "De Anza College" + }, + { + "label": "Dean College" + }, + { + "label": "Dean Institute of Technology" + }, + { + "label": "Defiance College" + }, + { + "label": "Del Mar College" + }, + { + "label": "Delaware College of Art and Design" + }, + { + "label": "Delaware County Community College" + }, + { + "label": "Delaware State University" + }, + { + "label": "Delaware Technical Community College-Owens" + }, + { + "label": "Delaware Technical Community College-Stanton/Wilmington" + }, + { + "label": "Delaware Technical Community College-Terry" + }, + { + "label": "Delaware Valley University" + }, + { + "label": "Delgado Community College" + }, + { + "label": "Dell'Arte International School of Physical Theatre" + }, + { + "label": "Delta College" + }, + { + "label": "Delta College of Arts & Technology" + }, + { + "label": "Delta School of Business and Technology" + }, + { + "label": "Delta State University" + }, + { + "label": "Denison University" + }, + { + "label": "Denmark Technical College" + }, + { + "label": "Denver School of Nursing" + }, + { + "label": "Denver Seminary" + }, + { + "label": "DePaul University" + }, + { + "label": "DePauw University" + }, + { + "label": "Des Moines Area Community College" + }, + { + "label": "Des Moines University-Osteopathic Medical Center" + }, + { + "label": "DeSales University" + }, + { + "label": "Design Institute of San Diego" + }, + { + "label": "DeVry College of New York" + }, + { + "label": "DeVry University-Arizona" + }, + { + "label": "DeVry University-California" + }, + { + "label": "DeVry University-Colorado" + }, + { + "label": "DeVry University-Florida" + }, + { + "label": "DeVry University-Georgia" + }, + { + "label": "DeVry University-Illinois" + }, + { + "label": "DeVry University-Indiana" + }, + { + "label": "DeVry University-Maryland" + }, + { + "label": "DeVry University-Michigan" + }, + { + "label": "DeVry University-Minnesota" + }, + { + "label": "DeVry University-Missouri" + }, + { + "label": "DeVry University-Nevada" + }, + { + "label": "DeVry University-New Jersey" + }, + { + "label": "DeVry University-North Carolina" + }, + { + "label": "DeVry University-Ohio" + }, + { + "label": "DeVry University-Oklahoma" + }, + { + "label": "DeVry University-Oregon" + }, + { + "label": "DeVry University-Pennsylvania" + }, + { + "label": "DeVry University-Tennessee" + }, + { + "label": "DeVry University-Texas" + }, + { + "label": "DeVry University-Utah" + }, + { + "label": "DeVry University-Virginia" + }, + { + "label": "DeVry University-Washington" + }, + { + "label": "DeVry University-Wisconsin" + }, + { + "label": "Dewey University-Hato Rey-Hato Rey" + }, + { + "label": "Diablo Valley College" + }, + { + "label": "Dickinson College" + }, + { + "label": "Dickinson State University" + }, + { + "label": "DigiPen Institute of Technology" + }, + { + "label": "Digital Media Arts College" + }, + { + "label": "Dillard University" + }, + { + "label": "Dine College" + }, + { + "label": "Divine Word College" + }, + { + "label": "Dixie State University" + }, + { + "label": "Doane University-Arts & Sciences" + }, + { + "label": "Doane University-Graduate and Professional Studies" + }, + { + "label": "Dodge City Community College" + }, + { + "label": "Dominican College of Blauvelt" + }, + { + "label": "Dominican School of Philosophy & Theology" + }, + { + "label": "Dominican University" + }, + { + "label": "Dominican University of California" + }, + { + "label": "Dongguk University-Los Angeles" + }, + { + "label": "Donnelly College" + }, + { + "label": "Dordt College" + }, + { + "label": "Douglas Education Center" + }, + { + "label": "Dowling College" + }, + { + "label": "Drake University" + }, + { + "label": "Drew University" + }, + { + "label": "Drexel University" + }, + { + "label": "Drury University" + }, + { + "label": "Du Bois Business College-Du Bois" + }, + { + "label": "Du Bois Business College-Huntingdon" + }, + { + "label": "Du Bois Business College-Oil City" + }, + { + "label": "Duke University" + }, + { + "label": "Duluth Business University" + }, + { + "label": "Dunwoody College of Technology" + }, + { + "label": "Duquesne University" + }, + { + "label": "Durham Technical Community College" + }, + { + "label": "Dutchess Community College" + }, + { + "label": "Dyersburg State Community College" + }, + { + "label": "D'Youville College" + }, + { + "label": "Eagle Gate College-Layton" + }, + { + "label": "Eagle Gate College-Murray" + }, + { + "label": "Eagle Gate College-Salt Lake City" + }, + { + "label": "Earlham College" + }, + { + "label": "East Arkansas Community College" + }, + { + "label": "East Carolina University" + }, + { + "label": "East Central College" + }, + { + "label": "East Central Community College" + }, + { + "label": "East Central University" + }, + { + "label": "East Georgia State College" + }, + { + "label": "East Los Angeles College" + }, + { + "label": "East Mississippi Community College" + }, + { + "label": "East San Gabriel Valley Regional Occupational Program" + }, + { + "label": "East Stroudsburg University of Pennsylvania" + }, + { + "label": "East Tennessee State University" + }, + { + "label": "East Texas Baptist University" + }, + { + "label": "East West College of Natural Medicine" + }, + { + "label": "Eastern Arizona College" + }, + { + "label": "Eastern Connecticut State University" + }, + { + "label": "Eastern Florida State College" + }, + { + "label": "Eastern Gateway Community College" + }, + { + "label": "Eastern Idaho Technical College" + }, + { + "label": "Eastern Illinois University" + }, + { + "label": "Eastern International College-Belleville" + }, + { + "label": "Eastern International College-Jersey City" + }, + { + "label": "Eastern Iowa Community College District" + }, + { + "label": "Eastern Kentucky University" + }, + { + "label": "Eastern Maine Community College" + }, + { + "label": "Eastern Mennonite University" + }, + { + "label": "Eastern Michigan University" + }, + { + "label": "Eastern Nazarene College" + }, + { + "label": "Eastern New Mexico University-Main Campus" + }, + { + "label": "Eastern New Mexico University-Roswell Campus" + }, + { + "label": "Eastern New Mexico University-Ruidoso Campus" + }, + { + "label": "Eastern Oklahoma State College" + }, + { + "label": "Eastern Oregon University" + }, + { + "label": "Eastern Shore Community College" + }, + { + "label": "Eastern University" + }, + { + "label": "Eastern Virginia Career College" + }, + { + "label": "Eastern Virginia Medical School" + }, + { + "label": "Eastern Washington University" + }, + { + "label": "Eastern West Virginia Community and Technical College" + }, + { + "label": "Eastern Wyoming College" + }, + { + "label": "Eastfield College" + }, + { + "label": "East-West University" + }, + { + "label": "Eastwick College-Hackensack" + }, + { + "label": "Eastwick College-Ramsey" + }, + { + "label": "Ecclesia College" + }, + { + "label": "Eckerd College" + }, + { + "label": "Ecotech Institute" + }, + { + "label": "ECPI University" + }, + { + "label": "Ecumenical Theological Seminary" + }, + { + "label": "Eden Theological Seminary" + }, + { + "label": "Edgecombe Community College" + }, + { + "label": "Edgewood College" + }, + { + "label": "EDIC College" + }, + { + "label": "Edinboro University of Pennsylvania" + }, + { + "label": "Edison State Community College" + }, + { + "label": "Edmonds Community College" + }, + { + "label": "EDP Univeristy of Puerto Rico Inc-San Juan" + }, + { + "label": "EDP University of Puerto Rico Inc-San Sebastian" + }, + { + "label": "Edward Via College of Osteopathic Medicine" + }, + { + "label": "Edward Waters College" + }, + { + "label": "El Camino College-Compton Center" + }, + { + "label": "El Camino Community College District" + }, + { + "label": "El Centro College" + }, + { + "label": "El Paso Community College" + }, + { + "label": "Elgin Community College" + }, + { + "label": "Elizabeth City State University" + }, + { + "label": "Elizabethtown College" + }, + { + "label": "Elizabethtown College School of Continuing and Professional Studies" + }, + { + "label": "Elizabethtown Community and Technical College" + }, + { + "label": "Ellsworth Community College" + }, + { + "label": "Elmhurst College" + }, + { + "label": "Elmira Business Institute" + }, + { + "label": "Elmira College" + }, + { + "label": "Elon University" + }, + { + "label": "Embry-Riddle Aeronautical University-Daytona Beach" + }, + { + "label": "Embry-Riddle Aeronautical University-Prescott" + }, + { + "label": "Embry-Riddle Aeronautical University-Worldwide" + }, + { + "label": "Emerson College" + }, + { + "label": "Emmanuel Christian Seminary" + }, + { + "label": "Emmanuel College-Boston" + }, + { + "label": "Emmanuel College-Franklin Springs" + }, + { + "label": "Emmaus Bible College" + }, + { + "label": "Emory & Henry College" + }, + { + "label": "Emory University" + }, + { + "label": "Emperor's College of Traditional Oriental Medicine" + }, + { + "label": "Empire College" + }, + { + "label": "Emporia State University" + }, + { + "label": "Endicott College" + }, + { + "label": "Enterprise State Community College" + }, + { + "label": "Epic Bible College" + }, + { + "label": "Episcopal Divinity School" + }, + { + "label": "Episcopal Theological Seminary of the Southwest" + }, + { + "label": "Erie Community College" + }, + { + "label": "Erie Institute of Technology Inc" + }, + { + "label": "Erikson Institute" + }, + { + "label": "Erskine College" + }, + { + "label": "Escuela de Artes Plasticas de Puerto Rico" + }, + { + "label": "Essex County College" + }, + { + "label": "Estrella Mountain Community College" + }, + { + "label": "ETI Technical College" + }, + { + "label": "Eureka College" + }, + { + "label": "Evangel University" + }, + { + "label": "Evangelical Theological Seminary" + }, + { + "label": "Everest College-Anaheim" + }, + { + "label": "Everest College-Arlington" + }, + { + "label": "Everest College-Aurora" + }, + { + "label": "Everest College-Bremerton" + }, + { + "label": "Everest College-Chesapeake" + }, + { + "label": "Everest College-City of Industry" + }, + { + "label": "Everest College-Colorado Springs" + }, + { + "label": "Everest College-Dallas" + }, + { + "label": "Everest College-Everett" + }, + { + "label": "Everest College-Fort Worth" + }, + { + "label": "Everest College-Fort Worth South" + }, + { + "label": "Everest College-Henderson" + }, + { + "label": "Everest College-McLean" + }, + { + "label": "Everest College-Mesa" + }, + { + "label": "Everest College-Newport News" + }, + { + "label": "Everest College-Ontario Metro" + }, + { + "label": "Everest College-Phoenix" + }, + { + "label": "Everest College-Portland" + }, + { + "label": "Everest College-Reseda" + }, + { + "label": "Everest College-Salt Lake City" + }, + { + "label": "Everest College-San Bernardino" + }, + { + "label": "Everest College-Springfield" + }, + { + "label": "Everest College-Tacoma" + }, + { + "label": "Everest College-Thornton" + }, + { + "label": "Everest College-Vancouver" + }, + { + "label": "Everest College-West Los Angeles" + }, + { + "label": "Everest Institute-Cross Lanes" + }, + { + "label": "Everest Institute-Kendall" + }, + { + "label": "Everest Institute-Norcross" + }, + { + "label": "Everest Institute-North Miami" + }, + { + "label": "Everest Institute-Pittsburgh" + }, + { + "label": "Everest Institute-Rochester" + }, + { + "label": "Everest University-Brandon" + }, + { + "label": "Everest University-Jacksonville" + }, + { + "label": "Everest University-Lakeland" + }, + { + "label": "Everest University-Largo" + }, + { + "label": "Everest University-Melbourne" + }, + { + "label": "Everest University-North Orlando" + }, + { + "label": "Everest University-Orange Park" + }, + { + "label": "Everest University-Pompano Beach" + }, + { + "label": "Everest University-South Orlando" + }, + { + "label": "Everest University-Tampa" + }, + { + "label": "Everett Community College" + }, + { + "label": "Everglades University" + }, + { + "label": "Evergreen Valley College" + }, + { + "label": "Excelsior College" + }, + { + "label": "Expression College for Digital Arts" + }, + { + "label": "Fairfield University" + }, + { + "label": "Fairleigh Dickinson University-College at Florham" + }, + { + "label": "Fairleigh Dickinson University-Metropolitan Campus" + }, + { + "label": "Fairmont State University" + }, + { + "label": "Faith Baptist Bible College and Theological Seminary" + }, + { + "label": "Faith Evangelical College & Seminary" + }, + { + "label": "Faith Theological Seminary" + }, + { + "label": "Family of Faith College" + }, + { + "label": "Farmingdale State College" + }, + { + "label": "Fashion Institute of Design & Merchandising-Los Angeles" + }, + { + "label": "Fashion Institute of Design & Merchandising-San Diego" + }, + { + "label": "Fashion Institute of Design & Merchandising-San Francisco" + }, + { + "label": "Fashion Institute of Technology" + }, + { + "label": "Faulkner University" + }, + { + "label": "Fayetteville State University" + }, + { + "label": "Fayetteville Technical Community College" + }, + { + "label": "Feather River Community College District" + }, + { + "label": "Felician University" + }, + { + "label": "Ferris State University" + }, + { + "label": "Ferrum College" + }, + { + "label": "Fielding Graduate University" + }, + { + "label": "FINE Mortuary College" + }, + { + "label": "Finger Lakes Community College" + }, + { + "label": "Finger Lakes Health College of Nursing" + }, + { + "label": "Finlandia University" + }, + { + "label": "Fisher College" + }, + { + "label": "Fisk University" + }, + { + "label": "Fitchburg State University" + }, + { + "label": "Five Branches University" + }, + { + "label": "Five Towns College" + }, + { + "label": "Flagler College-St Augustine" + }, + { + "label": "Flagler College-Tallahassee" + }, + { + "label": "Flathead Valley Community College" + }, + { + "label": "Fletcher Technical Community College" + }, + { + "label": "Flint Hills Technical College" + }, + { + "label": "Florence-Darlington Technical College" + }, + { + "label": "Florida Agricultural and Mechanical University" + }, + { + "label": "Florida Atlantic University" + }, + { + "label": "Florida Career College-Miami" + }, + { + "label": "Florida Coastal School of Law" + }, + { + "label": "Florida College" + }, + { + "label": "Florida College of Integrative Medicine" + }, + { + "label": "Florida College of Natural Health-Bradenton" + }, + { + "label": "Florida College of Natural Health-Maitland" + }, + { + "label": "Florida College of Natural Health-Miami" + }, + { + "label": "Florida College of Natural Health-Pompano Beach" + }, + { + "label": "Florida Gateway College" + }, + { + "label": "Florida Gulf Coast University" + }, + { + "label": "Florida Institute of Technology" + }, + { + "label": "Florida Institute of Technology-Online" + }, + { + "label": "Florida International University" + }, + { + "label": "Florida Keys Community College" + }, + { + "label": "Florida Memorial University" + }, + { + "label": "Florida National University-Main Campus" + }, + { + "label": "Florida Southern College" + }, + { + "label": "Florida SouthWestern State College" + }, + { + "label": "Florida State College at Jacksonville" + }, + { + "label": "Florida State University" + }, + { + "label": "Florida Technical College" + }, + { + "label": "Folsom Lake College" + }, + { + "label": "Fond du Lac Tribal and Community College" + }, + { + "label": "Fontbonne University" + }, + { + "label": "Foothill College" + }, + { + "label": "Fordham University" + }, + { + "label": "Forest Institute of Professional Psychology" + }, + { + "label": "Forrest College" + }, + { + "label": "Forsyth Technical Community College" + }, + { + "label": "Fort Hays State University" + }, + { + "label": "Fort Lewis College" + }, + { + "label": "Fort Peck Community College" + }, + { + "label": "Fort Scott Community College" + }, + { + "label": "Fort Valley State University" + }, + { + "label": "Fortis College-Baton Rouge" + }, + { + "label": "Fortis College-Centerville" + }, + { + "label": "Fortis College-Cincinnati" + }, + { + "label": "Fortis College-Columbia" + }, + { + "label": "Fortis College-Columbus" + }, + { + "label": "Fortis College-Cutler Bay" + }, + { + "label": "Fortis College-Cuyahoga Falls" + }, + { + "label": "Fortis College-Indianapolis" + }, + { + "label": "Fortis College-Landover" + }, + { + "label": "Fortis College-Largo" + }, + { + "label": "Fortis College-Mobile" + }, + { + "label": "Fortis College-Montgomery-Montgomery" + }, + { + "label": "Fortis College-Norfolk" + }, + { + "label": "Fortis College-Orange Park" + }, + { + "label": "Fortis College-Phoenix" + }, + { + "label": "Fortis College-Ravenna" + }, + { + "label": "Fortis College-Richmond" + }, + { + "label": "Fortis College-Salt Lake City" + }, + { + "label": "Fortis College-Smyrna" + }, + { + "label": "Fortis College-Winter Park" + }, + { + "label": "Fortis Institute" + }, + { + "label": "Fortis Institute-Birmingham" + }, + { + "label": "Fortis Institute-Cookeville" + }, + { + "label": "Fortis Institute-Erie" + }, + { + "label": "Fortis Institute-Fort Lauderdale" + }, + { + "label": "Fortis Institute-Forty Fort" + }, + { + "label": "Fortis Institute-Miami" + }, + { + "label": "Fortis Institute-Nashville" + }, + { + "label": "Fortis Institute-Pensacola" + }, + { + "label": "Fortis Institute-Port Saint Lucie" + }, + { + "label": "Fortis Institute-Scranton" + }, + { + "label": "Fountainhead College of Technology" + }, + { + "label": "Four-D College" + }, + { + "label": "Fox College" + }, + { + "label": "Fox Valley Technical College" + }, + { + "label": "Framingham State University" + }, + { + "label": "Francis Marion University" + }, + { + "label": "Franciscan School of Theology" + }, + { + "label": "Franciscan University of Steubenville" + }, + { + "label": "Frank Lloyd Wright School of Architecture" + }, + { + "label": "Frank Phillips College" + }, + { + "label": "Franklin and Marshall College" + }, + { + "label": "Franklin College" + }, + { + "label": "Franklin Pierce University" + }, + { + "label": "Franklin University" + }, + { + "label": "Franklin W Olin College of Engineering" + }, + { + "label": "Frederick Community College" + }, + { + "label": "Freed-Hardeman University" + }, + { + "label": "Fremont College" + }, + { + "label": "Fresno City College" + }, + { + "label": "Fresno Pacific University" + }, + { + "label": "Friends University" + }, + { + "label": "Front Range Community College" + }, + { + "label": "Frontier Community College" + }, + { + "label": "Frontier Nursing University" + }, + { + "label": "Frostburg State University" + }, + { + "label": "Full Sail University" + }, + { + "label": "Fuller Theological Seminary in California" + }, + { + "label": "Fullerton College" + }, + { + "label": "Fulton-Montgomery Community College" + }, + { + "label": "Furman University" + }, + { + "label": "Future Generations Graduate School" + }, + { + "label": "Gadsden State Community College" + }, + { + "label": "Galen College of Nursing-Cincinnati" + }, + { + "label": "Galen College of Nursing-Louisville" + }, + { + "label": "Galen College of Nursing-San Antonio" + }, + { + "label": "Galen College of Nursing-Tampa Bay" + }, + { + "label": "Gallaudet University" + }, + { + "label": "Gallipolis Career College" + }, + { + "label": "Galveston College" + }, + { + "label": "Gannon University" + }, + { + "label": "Garden City Community College" + }, + { + "label": "Gardner-Webb University" + }, + { + "label": "Garrett College" + }, + { + "label": "Garrett-Evangelical Theological Seminary" + }, + { + "label": "Gaston College" + }, + { + "label": "Gateway Community and Technical College" + }, + { + "label": "Gateway Community College-New Haven" + }, + { + "label": "GateWay Community College-Phoenix" + }, + { + "label": "Gateway Technical College" + }, + { + "label": "Gavilan College" + }, + { + "label": "Genesee Community College" + }, + { + "label": "Geneva College" + }, + { + "label": "George C Wallace State Community College-Dothan" + }, + { + "label": "George C Wallace State Community College-Hanceville" + }, + { + "label": "George C Wallace State Community College-Selma" + }, + { + "label": "George Fox University" + }, + { + "label": "George Mason University" + }, + { + "label": "George Washington University" + }, + { + "label": "Georgetown College" + }, + { + "label": "Georgetown University" + }, + { + "label": "Georgia Christian University" + }, + { + "label": "Georgia College and State University" + }, + { + "label": "Georgia Gwinnett College" + }, + { + "label": "Georgia Highlands College" + }, + { + "label": "Georgia Institute of Technology-Main Campus" + }, + { + "label": "Georgia Military College-Milledgeville" + }, + { + "label": "Georgia Northwestern Technical College" + }, + { + "label": "Georgia Perimeter College" + }, + { + "label": "Georgia Piedmont Technical College" + }, + { + "label": "Georgia Southern University" + }, + { + "label": "Georgia Southwestern State University" + }, + { + "label": "Georgia State University" + }, + { + "label": "Georgian Court University" + }, + { + "label": "Germanna Community College" + }, + { + "label": "Gettysburg College" + }, + { + "label": "Glen Oaks Community College" + }, + { + "label": "Glendale Community College-Glendale" + }, + { + "label": "Glendale Community College-Glendale" + }, + { + "label": "Glenville State College" + }, + { + "label": "Global Health College" + }, + { + "label": "Globe Institute of Technology" + }, + { + "label": "Globe University-Appleton" + }, + { + "label": "Globe University-Eau Claire" + }, + { + "label": "Globe University–Green Bay" + }, + { + "label": "Globe University-La Crosse" + }, + { + "label": "Globe University-Madison East" + }, + { + "label": "Globe University–Madison West" + }, + { + "label": "Globe University-Minneapolis" + }, + { + "label": "Globe University-Sioux Falls" + }, + { + "label": "Globe University–Wausau" + }, + { + "label": "Globe University-Woodbury" + }, + { + "label": "Goddard College" + }, + { + "label": "Gods Bible School and College" + }, + { + "label": "Gogebic Community College" + }, + { + "label": "Golden Gate University-San Francisco" + }, + { + "label": "Golden West College" + }, + { + "label": "Goldey-Beacom College" + }, + { + "label": "Golf Academy of America-Altamonte Springs" + }, + { + "label": "Golf Academy of America-Carlsbad" + }, + { + "label": "Golf Academy of America-Farmers Branch" + }, + { + "label": "Golf Academy of America-Myrtle Beach" + }, + { + "label": "Golf Academy of America-Phoenix" + }, + { + "label": "Gonzaga University" + }, + { + "label": "Good Samaritan College of Nursing and Health Science" + }, + { + "label": "Gooding Institute of Nurse Anesthesia" + }, + { + "label": "Goodwin College" + }, + { + "label": "Gordon College" + }, + { + "label": "Gordon State College" + }, + { + "label": "Gordon-Conwell Theological Seminary" + }, + { + "label": "Goshen College" + }, + { + "label": "Goucher College" + }, + { + "label": "Governors State University" + }, + { + "label": "Grace Bible College" + }, + { + "label": "Grace College and Theological Seminary" + }, + { + "label": "Grace College of Divinity" + }, + { + "label": "Grace Mission University" + }, + { + "label": "Grace School of Theology" + }, + { + "label": "Grace University" + }, + { + "label": "Graceland University-Lamoni" + }, + { + "label": "Graduate School USA" + }, + { + "label": "Graduate Theological Union" + }, + { + "label": "Grambling State University" + }, + { + "label": "Grand Canyon University" + }, + { + "label": "Grand Rapids Community College" + }, + { + "label": "Grand Valley State University" + }, + { + "label": "Grand View University" + }, + { + "label": "Granite State College" + }, + { + "label": "Grantham University" + }, + { + "label": "Gratz College" + }, + { + "label": "Grays Harbor College" + }, + { + "label": "Grayson College" + }, + { + "label": "Great Basin College" + }, + { + "label": "Great Bay Community College" + }, + { + "label": "Great Falls College Montana State University" + }, + { + "label": "Great Lakes Christian College" + }, + { + "label": "Great Lakes Institute of Technology" + }, + { + "label": "Green Mountain College" + }, + { + "label": "Green River College" + }, + { + "label": "Greenfield Community College" + }, + { + "label": "Greensboro College" + }, + { + "label": "Greenville College" + }, + { + "label": "Greenville Technical College" + }, + { + "label": "Grinnell College" + }, + { + "label": "Grossmont College" + }, + { + "label": "Grove City College" + }, + { + "label": "Guam Community College" + }, + { + "label": "Guilford College" + }, + { + "label": "Guilford Technical Community College" + }, + { + "label": "Gulf Coast State College" + }, + { + "label": "Gupton Jones College of Funeral Service" + }, + { + "label": "Gustavus Adolphus College" + }, + { + "label": "Gwinnett College-Lilburn" + }, + { + "label": "Gwinnett Technical College" + }, + { + "label": "Gwynedd Mercy University" + }, + { + "label": "H Councill Trenholm State Community College" + }, + { + "label": "Hagerstown Community College" + }, + { + "label": "Halifax Community College" + }, + { + "label": "Hallmark University" + }, + { + "label": "Hamilton College" + }, + { + "label": "Hamilton Technical College" + }, + { + "label": "Hamline University" + }, + { + "label": "Hampden-Sydney College" + }, + { + "label": "Hampshire College" + }, + { + "label": "Hampton University" + }, + { + "label": "Hannibal-LaGrange University" + }, + { + "label": "Hanover College" + }, + { + "label": "Harcum College" + }, + { + "label": "Harding University" + }, + { + "label": "Hardin-Simmons University" + }, + { + "label": "Harford Community College" + }, + { + "label": "Harrington College of Design" + }, + { + "label": "Harrisburg Area Community College-Harrisburg" + }, + { + "label": "Harrisburg University of Science and Technology" + }, + { + "label": "Harrison College-Grove City" + }, + { + "label": "Harrison College-Indianapolis" + }, + { + "label": "Harrison College-Morrisville" + }, + { + "label": "Harris-Stowe State University" + }, + { + "label": "Hartford Seminary" + }, + { + "label": "Hartnell College" + }, + { + "label": "Hartwick College" + }, + { + "label": "Harvard University" + }, + { + "label": "Harvey Mudd College" + }, + { + "label": "Haskell Indian Nations University" + }, + { + "label": "Hastings College" + }, + { + "label": "Haverford College" + }, + { + "label": "Hawaii Community College" + }, + { + "label": "Hawaii Pacific University" + }, + { + "label": "Hawkeye Community College" + }, + { + "label": "Haywood Community College" + }, + { + "label": "Hazard Community and Technical College" + }, + { + "label": "Hazelden Betty Ford Graduate School of Addiction Studies" + }, + { + "label": "Heald College-Concord" + }, + { + "label": "Heald College-Fresno" + }, + { + "label": "Heald College-Hayward" + }, + { + "label": "Heald College-Honolulu" + }, + { + "label": "Heald College-Modesto" + }, + { + "label": "Heald College-Portland" + }, + { + "label": "Heald College-Rancho Cordova" + }, + { + "label": "Heald College-Roseville" + }, + { + "label": "Heald College-Salinas" + }, + { + "label": "Heald College-San Francisco" + }, + { + "label": "Heald College-San Jose" + }, + { + "label": "Heald College-Stockton" + }, + { + "label": "Heartland Community College" + }, + { + "label": "Hebrew College" + }, + { + "label": "Hebrew Theological College" + }, + { + "label": "Hebrew Union College-Jewish Institute of Religion" + }, + { + "label": "Heidelberg University" + }, + { + "label": "Helena College University of Montana" + }, + { + "label": "Helene Fuld College of Nursing" + }, + { + "label": "Hellenic College-Holy Cross Greek Orthodox School of Theology" + }, + { + "label": "Henderson Community College" + }, + { + "label": "Henderson State University" + }, + { + "label": "Hendrix College" + }, + { + "label": "Hennepin Technical College" + }, + { + "label": "Henry Ford College" + }, + { + "label": "Heritage Bible College" + }, + { + "label": "Heritage Christian University" + }, + { + "label": "Heritage College-Denver" + }, + { + "label": "Heritage College-Kansas City" + }, + { + "label": "Heritage College-Oklahoma City" + }, + { + "label": "Heritage College-Wichita" + }, + { + "label": "Heritage Institute-Ft Myers" + }, + { + "label": "Heritage Institute-Jacksonville" + }, + { + "label": "Heritage University" + }, + { + "label": "Herkimer County Community College" + }, + { + "label": "Herzing University-Atlanta" + }, + { + "label": "Herzing University-Birmingham" + }, + { + "label": "Herzing University-Brookfield" + }, + { + "label": "Herzing University-Kenner" + }, + { + "label": "Herzing University-Kenosha" + }, + { + "label": "Herzing University-Madison" + }, + { + "label": "Herzing University-Minneapolis" + }, + { + "label": "Herzing University-Toledo" + }, + { + "label": "Herzing University-Winter Park" + }, + { + "label": "Hesston College" + }, + { + "label": "Hibbing Community College" + }, + { + "label": "Hickey College" + }, + { + "label": "High Point University" + }, + { + "label": "Highland Community College-Freeport" + }, + { + "label": "Highland Community College-Highland" + }, + { + "label": "Highlands College of Montana Tech" + }, + { + "label": "Highline College" + }, + { + "label": "Hilbert College" + }, + { + "label": "Hill College" + }, + { + "label": "Hillsborough Community College" + }, + { + "label": "Hillsdale College" + }, + { + "label": "Hillsdale Free Will Baptist College" + }, + { + "label": "Hinds Community College" + }, + { + "label": "Hiram College" + }, + { + "label": "Hiwassee College" + }, + { + "label": "Hobart William Smith Colleges" + }, + { + "label": "Hobe Sound Bible College" + }, + { + "label": "Hocking College" + }, + { + "label": "Hodges University" + }, + { + "label": "Hofstra University" + }, + { + "label": "Hollins University" + }, + { + "label": "Holmes Community College" + }, + { + "label": "Holy Apostles College and Seminary" + }, + { + "label": "Holy Cross College" + }, + { + "label": "Holy Family University" + }, + { + "label": "Holy Names University" + }, + { + "label": "Holyoke Community College" + }, + { + "label": "Hondros College" + }, + { + "label": "Honolulu Community College" + }, + { + "label": "Hood College" + }, + { + "label": "Hood Theological Seminary" + }, + { + "label": "Hope College" + }, + { + "label": "Hope International University" + }, + { + "label": "Hopkinsville Community College" + }, + { + "label": "Horizon University" + }, + { + "label": "Horry-Georgetown Technical College" + }, + { + "label": "Houghton College" + }, + { + "label": "Housatonic Community College" + }, + { + "label": "Houston Baptist University" + }, + { + "label": "Houston Community College" + }, + { + "label": "Houston Graduate School of Theology" + }, + { + "label": "Howard College" + }, + { + "label": "Howard Community College" + }, + { + "label": "Howard Payne University" + }, + { + "label": "Howard University" + }, + { + "label": "Hudson County Community College" + }, + { + "label": "Hudson Valley Community College" + }, + { + "label": "Huertas College" + }, + { + "label": "Hult International Business School" + }, + { + "label": "Humacao Community College" + }, + { + "label": "Humboldt State University" + }, + { + "label": "Humphreys College-Stockton and Modesto Campuses" + }, + { + "label": "Huntingdon College" + }, + { + "label": "Huntington Junior College" + }, + { + "label": "Huntington University" + }, + { + "label": "Huntsville Bible College" + }, + { + "label": "Hussian College School of Art" + }, + { + "label": "Husson University" + }, + { + "label": "Huston-Tillotson University" + }, + { + "label": "Hutchinson Community College" + }, + { + "label": "IBMC College" + }, + { + "label": "IBMC College" + }, + { + "label": "Icahn School of Medicine at Mount Sinai" + }, + { + "label": "ICDC College" + }, + { + "label": "ICPR Junior College-Arecibo" + }, + { + "label": "ICPR Junior College-General Institutional" + }, + { + "label": "ICPR Junior College-Manati" + }, + { + "label": "ICPR Junior College-Mayaguez" + }, + { + "label": "Idaho State University" + }, + { + "label": "IGlobal University" + }, + { + "label": "Iliff School of Theology" + }, + { + "label": "Ilisagvik College" + }, + { + "label": "Illinois Central College" + }, + { + "label": "Illinois College" + }, + { + "label": "Illinois College of Optometry" + }, + { + "label": "Illinois Institute of Technology" + }, + { + "label": "Illinois State University" + }, + { + "label": "Illinois Valley Community College" + }, + { + "label": "Illinois Wesleyan University" + }, + { + "label": "Immaculata University" + }, + { + "label": "Imperial Valley College" + }, + { + "label": "Independence Community College" + }, + { + "label": "Independence University" + }, + { + "label": "Indian Hills Community College" + }, + { + "label": "Indian River State College" + }, + { + "label": "Indiana Institute of Technology" + }, + { + "label": "Indiana State University" + }, + { + "label": "Indiana University of Pennsylvania-Main Campus" + }, + { + "label": "Indiana University-Bloomington" + }, + { + "label": "Indiana University-East" + }, + { + "label": "Indiana University-Kokomo" + }, + { + "label": "Indiana University-Northwest" + }, + { + "label": "Indiana University-Purdue University-Fort Wayne" + }, + { + "label": "Indiana University-Purdue University-Indianapolis" + }, + { + "label": "Indiana University-South Bend" + }, + { + "label": "Indiana University-Southeast" + }, + { + "label": "Indiana Wesleyan University" + }, + { + "label": "Institute for Clinical Social Work" + }, + { + "label": "Institute for Doctoral Studies in the Visual Arts" + }, + { + "label": "Institute for the Psychological Sciences" + }, + { + "label": "Institute of American Indian and Alaska Native Culture" + }, + { + "label": "Institute of Clinical Acupuncture & Oriental Med" + }, + { + "label": "Institute of Design and Construction" + }, + { + "label": "Institute of Production and Recording" + }, + { + "label": "Institute of Taoist Education and Acupuncture" + }, + { + "label": "Institute of Technology Inc-Clovis" + }, + { + "label": "Institute of World Politics" + }, + { + "label": "Instituto de Banca y Comercio Inc" + }, + { + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Guayama" + }, + { + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Manati" + }, + { + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Ponce" + }, + { + "label": "Instituto Tecnologico de Puerto Rico-Recinto de San Juan" + }, + { + "label": "Intellitec College-Colorado Springs" + }, + { + "label": "Intellitec College-Grand Junction" + }, + { + "label": "Inter American University of Puerto Rico-Aguadilla" + }, + { + "label": "Inter American University of Puerto Rico-Arecibo" + }, + { + "label": "Inter American University of Puerto Rico-Barranquitas" + }, + { + "label": "Inter American University of Puerto Rico-Bayamon" + }, + { + "label": "Inter American University of Puerto Rico-Fajardo" + }, + { + "label": "Inter American University of Puerto Rico-Guayama" + }, + { + "label": "Inter American University of Puerto Rico-Metro" + }, + { + "label": "Inter American University of Puerto Rico-Ponce" + }, + { + "label": "Inter American University of Puerto Rico-San German" + }, + { + "label": "Inter American University of Puerto Rico-School of Law" + }, + { + "label": "Inter American University of Puerto Rico-School of Optometry" + }, + { + "label": "Interactive College of Technology-Chamblee" + }, + { + "label": "Interactive College of Technology-Gainesville" + }, + { + "label": "Interactive College of Technology-Houston" + }, + { + "label": "Interactive College of Technology-Houston" + }, + { + "label": "Interactive College of Technology-Morrow" + }, + { + "label": "Interactive College of Technology-Newport" + }, + { + "label": "Interactive College of Technology-Pasadena" + }, + { + "label": "InterCoast Colleges-Orange" + }, + { + "label": "Interdenominational Theological Center" + }, + { + "label": "Interface College-Spokane" + }, + { + "label": "Interior Designers Institute" + }, + { + "label": "International Academy of Design and Technology-Nashville" + }, + { + "label": "International Academy of Design and Technology-Sacramento" + }, + { + "label": "International Academy of Design and Technology-Troy" + }, + { + "label": "International Baptist College and Seminary" + }, + { + "label": "International Business College-El Paso-El Paso" + }, + { + "label": "International Business College-El Paso-El Paso" + }, + { + "label": "International Business College-Fort Wayne" + }, + { + "label": "International Business College-Indianapolis" + }, + { + "label": "International College of Broadcasting" + }, + { + "label": "International Institute for Restorative Practices" + }, + { + "label": "International Professional School of Bodywork" + }, + { + "label": "International Technological University" + }, + { + "label": "Inver Hills Community College" + }, + { + "label": "Iona College" + }, + { + "label": "Iowa Central Community College" + }, + { + "label": "Iowa Lakes Community College" + }, + { + "label": "Iowa State University" + }, + { + "label": "Iowa Wesleyan University" + }, + { + "label": "Iowa Western Community College" + }, + { + "label": "Irell & Manella Graduate School of Biological Sciences at City of Hope" + }, + { + "label": "Irvine Valley College" + }, + { + "label": "Island Drafting and Technical Institute" + }, + { + "label": "Isothermal Community College" + }, + { + "label": "Itasca Community College" + }, + { + "label": "Itawamba Community College" + }, + { + "label": "Ithaca College" + }, + { + "label": "ITI Technical College" + }, + { + "label": "ITT Technical Institute-Akron" + }, + { + "label": "ITT Technical Institute-Albany" + }, + { + "label": "ITT Technical Institute-Albuquerque" + }, + { + "label": "ITT Technical Institute-Arlington" + }, + { + "label": "ITT Technical Institute-Arlington Heights" + }, + { + "label": "ITT Technical Institute-Arnold" + }, + { + "label": "ITT Technical Institute-Atlanta" + }, + { + "label": "ITT Technical Institute-Aurora" + }, + { + "label": "ITT Technical Institute-Austin" + }, + { + "label": "ITT Technical Institute-Baton Rouge" + }, + { + "label": "ITT Technical Institute-Bessemer" + }, + { + "label": "ITT Technical Institute-Boise" + }, + { + "label": "ITT Technical Institute-Bradenton" + }, + { + "label": "ITT Technical Institute-Brooklyn Center" + }, + { + "label": "ITT Technical Institute-Canton" + }, + { + "label": "ITT Technical Institute-Cary" + }, + { + "label": "ITT Technical Institute-Chantilly" + }, + { + "label": "ITT Technical Institute-Charlotte North" + }, + { + "label": "ITT Technical Institute-Charlotte South" + }, + { + "label": "ITT Technical Institute-Chattanooga" + }, + { + "label": "ITT Technical Institute-Clive" + }, + { + "label": "ITT Technical Institute-Clovis" + }, + { + "label": "ITT Technical Institute-Columbia" + }, + { + "label": "ITT Technical Institute-Columbus" + }, + { + "label": "ITT Technical Institute-Concord" + }, + { + "label": "ITT Technical Institute-Cordova" + }, + { + "label": "ITT Technical Institute-Corona" + }, + { + "label": "ITT Technical Institute-Culver City" + }, + { + "label": "ITT Technical Institute-Dayton" + }, + { + "label": "ITT Technical Institute-Dearborn" + }, + { + "label": "ITT Technical Institute-Deerfield Beach" + }, + { + "label": "ITT Technical Institute-DeSoto" + }, + { + "label": "ITT Technical Institute-Douglasville" + }, + { + "label": "ITT Technical Institute-Duluth" + }, + { + "label": "ITT Technical Institute-Dunmore" + }, + { + "label": "ITT Technical Institute-Durham" + }, + { + "label": "ITT Technical Institute-Earth City" + }, + { + "label": "ITT Technical Institute-Eden Prairie" + }, + { + "label": "ITT Technical Institute-Everett" + }, + { + "label": "ITT Technical Institute-Fort Lauderdale" + }, + { + "label": "ITT Technical Institute-Fort Myers" + }, + { + "label": "ITT Technical Institute-Fort Wayne" + }, + { + "label": "ITT Technical Institute-Germantown" + }, + { + "label": "ITT Technical Institute-Getzville" + }, + { + "label": "ITT Technical Institute-Green Bay" + }, + { + "label": "ITT Technical Institute-Greenfield" + }, + { + "label": "ITT Technical Institute-Greenville" + }, + { + "label": "ITT Technical Institute-Hanover" + }, + { + "label": "ITT Technical Institute-Harrisburg" + }, + { + "label": "ITT Technical Institute-Henderson" + }, + { + "label": "ITT Technical Institute-Hialeah" + }, + { + "label": "ITT Technical Institute-High Point" + }, + { + "label": "ITT Technical Institute-Hilliard" + }, + { + "label": "ITT Technical Institute-Houston North" + }, + { + "label": "ITT Technical Institute-Houston West" + }, + { + "label": "ITT Technical Institute-Huntington" + }, + { + "label": "ITT Technical Institute-Indianapolis" + }, + { + "label": "ITT Technical Institute-Indianapolis East" + }, + { + "label": "ITT Technical Institute-Jacksonville" + }, + { + "label": "ITT Technical Institute-Johnson City" + }, + { + "label": "ITT Technical Institute-Kansas City" + }, + { + "label": "ITT Technical Institute-Kennesaw" + }, + { + "label": "ITT Technical Institute-Knoxville" + }, + { + "label": "ITT Technical Institute-Lake Mary" + }, + { + "label": "ITT Technical Institute-Las Vegas" + }, + { + "label": "ITT Technical Institute-Lathrop" + }, + { + "label": "ITT Technical Institute-Levittown" + }, + { + "label": "ITT Technical Institute-Lexington" + }, + { + "label": "ITT Technical Institute-Little Rock" + }, + { + "label": "ITT Technical Institute-Liverpool" + }, + { + "label": "ITT Technical Institute-Louisville" + }, + { + "label": "ITT Technical Institute-Madison-Madison" + }, + { + "label": "ITT Technical Institute-Madison-Madison" + }, + { + "label": "ITT Technical Institute-Madison-Madison" + }, + { + "label": "ITT Technical Institute-Marlton" + }, + { + "label": "ITT Technical Institute-Maumee" + }, + { + "label": "ITT Technical Institute-Merrillville" + }, + { + "label": "ITT Technical Institute-Mobile" + }, + { + "label": "ITT Technical Institute-Murray" + }, + { + "label": "ITT Technical Institute-Myrtle Beach" + }, + { + "label": "ITT Technical Institute-Nashville" + }, + { + "label": "ITT Technical Institute-National City" + }, + { + "label": "ITT Technical Institute-Newburgh" + }, + { + "label": "ITT Technical Institute-Norfolk" + }, + { + "label": "ITT Technical Institute-North Charleston" + }, + { + "label": "ITT Technical Institute-Norwood-Norwood" + }, + { + "label": "ITT Technical Institute-Norwood-Norwood" + }, + { + "label": "ITT Technical Institute-Oak Brook" + }, + { + "label": "ITT Technical Institute-Oakland" + }, + { + "label": "ITT Technical Institute-Oklahoma City" + }, + { + "label": "ITT Technical Institute-Omaha" + }, + { + "label": "ITT Technical Institute-Orange" + }, + { + "label": "ITT Technical Institute-Orland Park" + }, + { + "label": "ITT Technical Institute-Orlando" + }, + { + "label": "ITT Technical Institute-Overland Park" + }, + { + "label": "ITT Technical Institute-Owings Mills" + }, + { + "label": "ITT Technical Institute-Oxnard" + }, + { + "label": "ITT Technical Institute-Philadelphia" + }, + { + "label": "ITT Technical Institute-Phoenix" + }, + { + "label": "ITT Technical Institute-Phoenix West" + }, + { + "label": "ITT Technical Institute-Pittsburgh" + }, + { + "label": "ITT Technical Institute-Plymouth Meeting" + }, + { + "label": "ITT Technical Institute-Portland" + }, + { + "label": "ITT Technical Institute-Rancho Cordova" + }, + { + "label": "ITT Technical Institute-Richardson" + }, + { + "label": "ITT Technical Institute-Richmond" + }, + { + "label": "ITT Technical Institute-Saint Rose" + }, + { + "label": "ITT Technical Institute-Salem-Salem" + }, + { + "label": "ITT Technical Institute-Salem-Salem" + }, + { + "label": "ITT Technical Institute-San Antonio" + }, + { + "label": "ITT Technical Institute-San Antonio East" + }, + { + "label": "ITT Technical Institute-San Bernardino" + }, + { + "label": "ITT Technical Institute-San Dimas" + }, + { + "label": "ITT Technical Institute-Seattle" + }, + { + "label": "ITT Technical Institute-South Bend" + }, + { + "label": "ITT Technical Institute-Southfield" + }, + { + "label": "ITT Technical Institute-Spokane Valley" + }, + { + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "label": "ITT Technical Institute-St Petersburg" + }, + { + "label": "ITT Technical Institute-Strongsville" + }, + { + "label": "ITT Technical Institute-Swartz Creek" + }, + { + "label": "ITT Technical Institute-Sylmar" + }, + { + "label": "ITT Technical Institute-Tallahassee" + }, + { + "label": "ITT Technical Institute-Tampa" + }, + { + "label": "ITT Technical Institute-Tarentum" + }, + { + "label": "ITT Technical Institute-Tempe" + }, + { + "label": "ITT Technical Institute-Torrance" + }, + { + "label": "ITT Technical Institute-Troy" + }, + { + "label": "ITT Technical Institute-Tucson" + }, + { + "label": "ITT Technical Institute-Tulsa" + }, + { + "label": "ITT Technical Institute-Waco" + }, + { + "label": "ITT Technical Institute-Warrensville Heights" + }, + { + "label": "ITT Technical Institute-Webster" + }, + { + "label": "ITT Technical Institute-West Chester" + }, + { + "label": "ITT Technical Institute-West Covina" + }, + { + "label": "ITT Technical Institute-West Palm Beach" + }, + { + "label": "ITT Technical Institute-Westminster" + }, + { + "label": "ITT Technical Institute-Wichita" + }, + { + "label": "ITT Technical Institute-Wilmington" + }, + { + "label": "ITT Technical Institute-Wyoming" + }, + { + "label": "ITT Technical Institute-Youngstown" + }, + { + "label": "Ivy Tech Community College" + }, + { + "label": "J F Drake State Community and Technical College" + }, + { + "label": "J F Ingram State Technical College" + }, + { + "label": "J Sargeant Reynolds Community College" + }, + { + "label": "Jackson College" + }, + { + "label": "Jackson State Community College" + }, + { + "label": "Jackson State University" + }, + { + "label": "Jacksonville College-Main Campus" + }, + { + "label": "Jacksonville State University" + }, + { + "label": "Jacksonville University" + }, + { + "label": "James A Rhodes State College" + }, + { + "label": "James H Faulkner State Community College" + }, + { + "label": "James Madison University" + }, + { + "label": "James Sprunt Community College" + }, + { + "label": "Jamestown Business College" + }, + { + "label": "Jamestown Community College" + }, + { + "label": "Jarvis Christian College" + }, + { + "label": "Jefferson College" + }, + { + "label": "Jefferson College of Health Sciences" + }, + { + "label": "Jefferson Community and Technical College" + }, + { + "label": "Jefferson Community College" + }, + { + "label": "Jefferson Davis Community College" + }, + { + "label": "Jefferson State Community College" + }, + { + "label": "Jersey College" + }, + { + "label": "Jewish Theological Seminary of America" + }, + { + "label": "Jna Institute of Culinary Arts" + }, + { + "label": "John A Gupton College" + }, + { + "label": "John A Logan College" + }, + { + "label": "John Brown University" + }, + { + "label": "John C Calhoun State Community College" + }, + { + "label": "John Carroll University" + }, + { + "label": "John F. Kennedy University" + }, + { + "label": "John Paul the Great Catholic University" + }, + { + "label": "John Tyler Community College" + }, + { + "label": "John Wood Community College" + }, + { + "label": "Johns Hopkins University" + }, + { + "label": "Johnson & Wales University-Charlotte" + }, + { + "label": "Johnson & Wales University-Denver" + }, + { + "label": "Johnson & Wales University-North Miami" + }, + { + "label": "Johnson & Wales University-Online" + }, + { + "label": "Johnson & Wales University-Providence" + }, + { + "label": "Johnson C Smith University" + }, + { + "label": "Johnson College" + }, + { + "label": "Johnson County Community College" + }, + { + "label": "Johnson State College" + }, + { + "label": "Johnson University" + }, + { + "label": "Johnson University Florida" + }, + { + "label": "Johnston Community College" + }, + { + "label": "Joliet Junior College" + }, + { + "label": "Jones College-Jacksonville" + }, + { + "label": "Jones County Junior College" + }, + { + "label": "Jones International University" + }, + { + "label": "Jose Maria Vargas University" + }, + { + "label": "Judson College" + }, + { + "label": "Judson University" + }, + { + "label": "Jung Tao School of Classical Chinese Medicine" + }, + { + "label": "Juniata College" + }, + { + "label": "Kalamazoo College" + }, + { + "label": "Kalamazoo Valley Community College" + }, + { + "label": "Kankakee Community College" + }, + { + "label": "Kansas City Art Institute" + }, + { + "label": "Kansas City College & Bible School" + }, + { + "label": "Kansas City Kansas Community College" + }, + { + "label": "Kansas City University of Medicine and Biosciences" + }, + { + "label": "Kansas State University" + }, + { + "label": "Kansas Wesleyan University" + }, + { + "label": "Kapiolani Community College" + }, + { + "label": "Kaplan College-Jacksonville" + }, + { + "label": "Kaplan College-Lubbock" + }, + { + "label": "Kaplan University-Augusta Campus" + }, + { + "label": "Kaplan University-Cedar Falls Campus" + }, + { + "label": "Kaplan University-Cedar Rapids Campus" + }, + { + "label": "Kaplan University-Davenport Campus" + }, + { + "label": "Kaplan University-Des Moines Campus" + }, + { + "label": "Kaplan University-Hagerstown Campus" + }, + { + "label": "Kaplan University-Lincoln Campus" + }, + { + "label": "Kaplan University-Maine Campus" + }, + { + "label": "Kaplan University-Mason City Campus" + }, + { + "label": "Kaplan University-Omaha Campus" + }, + { + "label": "Kaskaskia College" + }, + { + "label": "Kauai Community College" + }, + { + "label": "KD College Conservatory of Film and Dramatic Arts" + }, + { + "label": "Kean University" + }, + { + "label": "Keck Graduate Institute" + }, + { + "label": "Keene State College" + }, + { + "label": "Kehilath Yakov Rabbinical Seminary" + }, + { + "label": "Keiser University-Ft Lauderdale" + }, + { + "label": "Kellogg Community College" + }, + { + "label": "Kendall College" + }, + { + "label": "Kennebec Valley Community College" + }, + { + "label": "Kennesaw State University" + }, + { + "label": "Kenrick Glennon Seminary" + }, + { + "label": "Kent State University at Ashtabula" + }, + { + "label": "Kent State University at East Liverpool" + }, + { + "label": "Kent State University at Geauga" + }, + { + "label": "Kent State University at Kent" + }, + { + "label": "Kent State University at Salem" + }, + { + "label": "Kent State University at Stark" + }, + { + "label": "Kent State University at Trumbull" + }, + { + "label": "Kent State University at Tuscarawas" + }, + { + "label": "Kentucky Christian University" + }, + { + "label": "Kentucky Mountain Bible College" + }, + { + "label": "Kentucky State University" + }, + { + "label": "Kentucky Wesleyan College" + }, + { + "label": "Kenyon College" + }, + { + "label": "Kettering College" + }, + { + "label": "Kettering University" + }, + { + "label": "Keuka College" + }, + { + "label": "Keweenaw Bay Ojibwa Community College" + }, + { + "label": "Key College" + }, + { + "label": "Keystone College" + }, + { + "label": "Keystone Technical Institute" + }, + { + "label": "Kilgore College" + }, + { + "label": "Kilian Community College" + }, + { + "label": "King University" + }, + { + "label": "King's College-Charlotte" + }, + { + "label": "King's College-Wilkes-Barre" + }, + { + "label": "Kirkwood Community College" + }, + { + "label": "Kirtland Community College" + }, + { + "label": "Kishwaukee College" + }, + { + "label": "Klamath Community College" + }, + { + "label": "Knowledge Systems Institute" + }, + { + "label": "Knox College" + }, + { + "label": "Knox Theological Seminary" + }, + { + "label": "Kutztown University of Pennsylvania" + }, + { + "label": "Kuyper College" + }, + { + "label": "La Roche College" + }, + { + "label": "La Salle University" + }, + { + "label": "La Sierra University" + }, + { + "label": "Labette Community College" + }, + { + "label": "Laboure College" + }, + { + "label": "Lac Courte Oreilles Ojibwa Community College" + }, + { + "label": "Lackawanna College" + }, + { + "label": "Lafayette College" + }, + { + "label": "LaGrange College" + }, + { + "label": "Laguna College of Art and Design" + }, + { + "label": "Lake Area Technical Institute" + }, + { + "label": "Lake Erie College" + }, + { + "label": "Lake Erie College of Osteopathic Medicine" + }, + { + "label": "Lake Forest College" + }, + { + "label": "Lake Forest Graduate School of Management" + }, + { + "label": "Lake Land College" + }, + { + "label": "Lake Michigan College" + }, + { + "label": "Lake Region State College" + }, + { + "label": "Lake Superior College" + }, + { + "label": "Lake Superior State University" + }, + { + "label": "Lake Tahoe Community College" + }, + { + "label": "Lake Washington Institute of Technology" + }, + { + "label": "Lakeland College" + }, + { + "label": "Lakeland Community College" + }, + { + "label": "Lakes Region Community College" + }, + { + "label": "Lakeshore Technical College" + }, + { + "label": "Lake-Sumter State College" + }, + { + "label": "Lakeview College of Nursing" + }, + { + "label": "Lamar Community College" + }, + { + "label": "Lamar Institute of Technology" + }, + { + "label": "Lamar State College-Orange" + }, + { + "label": "Lamar State College-Port Arthur" + }, + { + "label": "Lamar University" + }, + { + "label": "Lancaster Bible College" + }, + { + "label": "Lancaster County Career and Technology Center" + }, + { + "label": "Lancaster Theological Seminary" + }, + { + "label": "Lander University" + }, + { + "label": "Landmark College" + }, + { + "label": "Lane College" + }, + { + "label": "Lane Community College" + }, + { + "label": "Laney College" + }, + { + "label": "Langston University" + }, + { + "label": "Lanier Technical College" + }, + { + "label": "Lansdale School of Business" + }, + { + "label": "Lansing Community College" + }, + { + "label": "Laramie County Community College" + }, + { + "label": "Laredo Community College" + }, + { + "label": "Las Positas College" + }, + { + "label": "Lasell College" + }, + { + "label": "Lassen Community College" + }, + { + "label": "Latter-day Saints Business College" + }, + { + "label": "Laurel Business Institute" + }, + { + "label": "Laurel Technical Institute-MEADVILLE" + }, + { + "label": "Laurel Technical Institute-Sharon" + }, + { + "label": "Laurel University" + }, + { + "label": "Lawrence Memorial Hospital School of Nursing" + }, + { + "label": "Lawrence Technological University" + }, + { + "label": "Lawrence University" + }, + { + "label": "Lawson State Community College-Birmingham Campus" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Atlanta" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Austin" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Cambridge" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Chicago" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Dallas" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Las Vegas" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Miami" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Minneapolis" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Orlando" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Pasadena" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Portland" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-San Francisco" + }, + { + "label": "Le Cordon Bleu College of Culinary Arts-Scottsdale" + }, + { + "label": "Le Moyne College" + }, + { + "label": "Le Moyne-Owen College" + }, + { + "label": "Lebanon Valley College" + }, + { + "label": "L'Ecole Culinaire-Memphis" + }, + { + "label": "L'Ecole Culinaire-St Louis" + }, + { + "label": "Lee College" + }, + { + "label": "Lee University" + }, + { + "label": "Leech Lake Tribal College" + }, + { + "label": "Lees-McRae College" + }, + { + "label": "Leeward Community College" + }, + { + "label": "Lehigh Carbon Community College" + }, + { + "label": "Lehigh University" + }, + { + "label": "Lenoir Community College" + }, + { + "label": "Lenoir-Rhyne University" + }, + { + "label": "Lenoir-Rhyne University-Lutheran Theological Southern Seminary" + }, + { + "label": "Lesley University" + }, + { + "label": "LeTourneau University" + }, + { + "label": "Lewis & Clark College" + }, + { + "label": "Lewis and Clark Community College" + }, + { + "label": "Lewis University" + }, + { + "label": "Lewis-Clark State College" + }, + { + "label": "Lexington Theological Seminary" + }, + { + "label": "Liberty University" + }, + { + "label": "Life Chiropractic College West" + }, + { + "label": "Life Pacific College" + }, + { + "label": "Life University" + }, + { + "label": "LIM College" + }, + { + "label": "Limestone College" + }, + { + "label": "Lincoln Christian University" + }, + { + "label": "Lincoln College" + }, + { + "label": "Lincoln College of New England-Southington" + }, + { + "label": "Lincoln College of Technology-Columbia" + }, + { + "label": "Lincoln College of Technology-Denver" + }, + { + "label": "Lincoln College of Technology-Indianapolis" + }, + { + "label": "Lincoln College of Technology-Marietta" + }, + { + "label": "Lincoln College of Technology-Melrose Park" + }, + { + "label": "Lincoln College of Technology-Nashville" + }, + { + "label": "Lincoln College of Technology-West Palm Beach" + }, + { + "label": "Lincoln Land Community College" + }, + { + "label": "Lincoln Memorial University" + }, + { + "label": "Lincoln Technical Institute-Allentown" + }, + { + "label": "Lincoln Technical Institute-Northeast Philadelphia" + }, + { + "label": "Lincoln Technical Institute-Philadelphia" + }, + { + "label": "Lincoln Trail College" + }, + { + "label": "Lincoln University-Jefferson City" + }, + { + "label": "Lincoln University-Oakland" + }, + { + "label": "Lindenwood University" + }, + { + "label": "Lindsey Wilson College" + }, + { + "label": "Linfield College-Adult Degree Program" + }, + { + "label": "Linfield College-McMinnville Campus" + }, + { + "label": "Linfield College-School of Nursing" + }, + { + "label": "Linn-Benton Community College" + }, + { + "label": "Lipscomb University" + }, + { + "label": "Little Big Horn College" + }, + { + "label": "Little Priest Tribal College" + }, + { + "label": "LIU Brentwood" + }, + { + "label": "LIU Brooklyn" + }, + { + "label": "LIU Hudson at Rockland" + }, + { + "label": "LIU Hudson at Westchester" + }, + { + "label": "LIU Post" + }, + { + "label": "LIU Riverhead" + }, + { + "label": "Living Arts College" + }, + { + "label": "Livingstone College" + }, + { + "label": "Lock Haven University" + }, + { + "label": "Logan University" + }, + { + "label": "Loma Linda University" + }, + { + "label": "Lone Star College System" + }, + { + "label": "Long Beach City College" + }, + { + "label": "Long Island Business Institute" + }, + { + "label": "Longwood University" + }, + { + "label": "Longy School of Music of Bard College" + }, + { + "label": "Lorain County Community College" + }, + { + "label": "Loras College" + }, + { + "label": "Lord Fairfax Community College" + }, + { + "label": "Los Angeles City College" + }, + { + "label": "Los Angeles College of Music" + }, + { + "label": "Los Angeles County College of Nursing and Allied Health" + }, + { + "label": "Los Angeles Film School" + }, + { + "label": "Los Angeles Harbor College" + }, + { + "label": "Los Angeles Mission College" + }, + { + "label": "Los Angeles ORT College-Los Angeles Campus" + }, + { + "label": "Los Angeles ORT College-Van Nuys Campus" + }, + { + "label": "Los Angeles Pierce College" + }, + { + "label": "Los Angeles Southwest College" + }, + { + "label": "Los Angeles Trade Technical College" + }, + { + "label": "Los Angeles Valley College" + }, + { + "label": "Los Medanos College" + }, + { + "label": "Louisburg College" + }, + { + "label": "Louisiana College" + }, + { + "label": "Louisiana Culinary Institute" + }, + { + "label": "Louisiana Delta Community College" + }, + { + "label": "Louisiana State University and Agricultural & Mechanical College" + }, + { + "label": "Louisiana State University Health Sciences Center-New Orleans" + }, + { + "label": "Louisiana State University Health Sciences Center-Shreveport" + }, + { + "label": "Louisiana State University-Alexandria" + }, + { + "label": "Louisiana State University-Eunice" + }, + { + "label": "Louisiana State University-Shreveport" + }, + { + "label": "Louisiana Tech University" + }, + { + "label": "Louisville Presbyterian Theological Seminary" + }, + { + "label": "Lourdes University" + }, + { + "label": "Lower Columbia College" + }, + { + "label": "Loyola Marymount University" + }, + { + "label": "Loyola University Chicago" + }, + { + "label": "Loyola University Maryland" + }, + { + "label": "Loyola University New Orleans" + }, + { + "label": "Lubbock Christian University" + }, + { + "label": "Luna Community College" + }, + { + "label": "Lurleen B Wallace Community College" + }, + { + "label": "Luther College" + }, + { + "label": "Luther Rice University & Seminary" + }, + { + "label": "Luther Seminary" + }, + { + "label": "Lutheran School of Theology at Chicago" + }, + { + "label": "Lutheran Theological Seminary at Gettysburg" + }, + { + "label": "Lutheran Theological Seminary at Philadelphia" + }, + { + "label": "Luzerne County Community College" + }, + { + "label": "Lycoming College" + }, + { + "label": "Lynchburg College" + }, + { + "label": "Lyndon State College" + }, + { + "label": "Lynn University" + }, + { + "label": "Lyon College" + }, + { + "label": "Macalester College" + }, + { + "label": "MacCormac College" + }, + { + "label": "Machzikei Hadath Rabbinical College" + }, + { + "label": "MacMurray College" + }, + { + "label": "Macomb Community College" + }, + { + "label": "Madison Area Technical College" + }, + { + "label": "Madison Media Institute" + }, + { + "label": "Madison Media Institute-Rockford Career College" + }, + { + "label": "Madisonville Community College" + }, + { + "label": "Madonna University" + }, + { + "label": "Maharishi University of Management" + }, + { + "label": "Maine College of Art" + }, + { + "label": "Maine College of Health Professions" + }, + { + "label": "Maine Maritime Academy" + }, + { + "label": "Malone University" + }, + { + "label": "Management Resources College" + }, + { + "label": "Manchester Community College-Manchester" + }, + { + "label": "Manchester Community College-Manchester" + }, + { + "label": "Manchester University" + }, + { + "label": "Mandl School-The College of Allied Health" + }, + { + "label": "Manhattan Area Technical College" + }, + { + "label": "Manhattan Christian College" + }, + { + "label": "Manhattan College" + }, + { + "label": "Manhattan School of Music" + }, + { + "label": "Manhattanville College" + }, + { + "label": "Manor College" + }, + { + "label": "Mansfield University of Pennsylvania" + }, + { + "label": "Maple Springs Baptist Bible College and Seminary" + }, + { + "label": "Maranatha Baptist University" + }, + { + "label": "Maria College of Albany" + }, + { + "label": "Marian Court College" + }, + { + "label": "Marian University-Fond Du Lac" + }, + { + "label": "Marian University-Indianapolis" + }, + { + "label": "Marietta College" + }, + { + "label": "Marion Military Institute" + }, + { + "label": "Marion Technical College" + }, + { + "label": "Marist College" + }, + { + "label": "Marlboro College" + }, + { + "label": "Marlboro College Graduate & Professional Studies" + }, + { + "label": "Marquette University" + }, + { + "label": "Mars Hill University" + }, + { + "label": "Marshall B Ketchum University" + }, + { + "label": "Marshall University" + }, + { + "label": "Marshalltown Community College" + }, + { + "label": "Martin Community College" + }, + { + "label": "Martin Luther College" + }, + { + "label": "Martin Methodist College" + }, + { + "label": "Martin University" + }, + { + "label": "Mary Baldwin College" + }, + { + "label": "Marygrove College" + }, + { + "label": "Maryland Institute College of Art" + }, + { + "label": "Maryland University of Integrative Health" + }, + { + "label": "Marylhurst University" + }, + { + "label": "Marymount California University" + }, + { + "label": "Marymount Manhattan College" + }, + { + "label": "Marymount University" + }, + { + "label": "Maryville College" + }, + { + "label": "Maryville University of Saint Louis" + }, + { + "label": "Marywood University" + }, + { + "label": "Massachusetts Bay Community College" + }, + { + "label": "Massachusetts College of Art and Design" + }, + { + "label": "Massachusetts College of Liberal Arts" + }, + { + "label": "Massachusetts Institute of Technology" + }, + { + "label": "Massachusetts Maritime Academy" + }, + { + "label": "Massachusetts School of Law" + }, + { + "label": "Massasoit Community College" + }, + { + "label": "Mattia College" + }, + { + "label": "Mayfield College" + }, + { + "label": "Mayland Community College" + }, + { + "label": "Mayo Graduate School" + }, + { + "label": "Mayo Medical School" + }, + { + "label": "Mayo School of Health Sciences" + }, + { + "label": "Maysville Community and Technical College" + }, + { + "label": "Mayville State University" + }, + { + "label": "McCann School of Business & Technology" + }, + { + "label": "McCormick Theological Seminary" + }, + { + "label": "McDaniel College" + }, + { + "label": "McDowell Technical Community College" + }, + { + "label": "McHenry County College" + }, + { + "label": "McKendree University" + }, + { + "label": "McLennan Community College" + }, + { + "label": "McMurry University" + }, + { + "label": "McNally Smith College of Music" + }, + { + "label": "McNeese State University" + }, + { + "label": "McPherson College" + }, + { + "label": "MCPHS University" + }, + { + "label": "Meadville Lombard Theological School" + }, + { + "label": "Mech-Tech College" + }, + { + "label": "Medaille College" + }, + { + "label": "Medical College of Wisconsin" + }, + { + "label": "Medical University of South Carolina" + }, + { + "label": "MedTech College" + }, + { + "label": "MedTech College-Ft Wayne Campus" + }, + { + "label": "MedTech College-Greenwood Campus" + }, + { + "label": "MedTech College-Lexington Campus" + }, + { + "label": "Medtech Institute" + }, + { + "label": "MedTech Institute-Atlanta Campus" + }, + { + "label": "Meharry Medical College" + }, + { + "label": "Memorial School of Nursing" + }, + { + "label": "Memphis College of Art" + }, + { + "label": "Memphis Theological Seminary" + }, + { + "label": "Mendocino College" + }, + { + "label": "Menlo College" + }, + { + "label": "Merced College" + }, + { + "label": "Mercer County Community College" + }, + { + "label": "Mercer University" + }, + { + "label": "Mercy College" + }, + { + "label": "Mercy College of Health Sciences" + }, + { + "label": "Mercy College of Ohio" + }, + { + "label": "Mercyhurst University" + }, + { + "label": "Mercyhurst University-North East Campus" + }, + { + "label": "Meredith College" + }, + { + "label": "Meridian College" + }, + { + "label": "Meridian Community College" + }, + { + "label": "Merrimack College" + }, + { + "label": "Merritt College" + }, + { + "label": "Mesa Community College" + }, + { + "label": "Mesabi Range College" + }, + { + "label": "Mesalands Community College" + }, + { + "label": "Mesivta Keser Torah" + }, + { + "label": "Mesivta of Eastern Parkway-Yeshiva Zichron Meilech" + }, + { + "label": "Mesivta Torah Vodaath Rabbinical Seminary" + }, + { + "label": "Mesivtha Tifereth Jerusalem of America" + }, + { + "label": "Messenger College" + }, + { + "label": "Messiah College" + }, + { + "label": "Methodist College" + }, + { + "label": "Methodist Theological School in Ohio" + }, + { + "label": "Methodist University" + }, + { + "label": "Metro Business College-Arnold" + }, + { + "label": "Metro Business College-Cape Girardeau" + }, + { + "label": "Metro Business College-Jefferson City" + }, + { + "label": "Metro Business College-Rolla" + }, + { + "label": "Metropolitan Career Center Computer Technology Institute" + }, + { + "label": "Metropolitan College of New York" + }, + { + "label": "Metropolitan Community College Area" + }, + { + "label": "Metropolitan Community College-Kansas City-Kansas City" + }, + { + "label": "Metropolitan State University" + }, + { + "label": "Metropolitan State University of Denver" + }, + { + "label": "MGH Institute of Health Professions" + }, + { + "label": "Miami Dade College" + }, + { + "label": "Miami University-Hamilton" + }, + { + "label": "Miami University-Middletown" + }, + { + "label": "Miami University-Oxford" + }, + { + "label": "Miami-Jacobs Career College-Columbus" + }, + { + "label": "Miami-Jacobs Career College-Dayton" + }, + { + "label": "Miami-Jacobs Career College-Independence" + }, + { + "label": "Miami-Jacobs Career College-Sharonville" + }, + { + "label": "Miami-Jacobs Career College-Springboro" + }, + { + "label": "Miami-Jacobs Career College-Troy" + }, + { + "label": "MIAT College of Technology" + }, + { + "label": "Michigan Jewish Institute" + }, + { + "label": "Michigan School of Professional Psychology" + }, + { + "label": "Michigan State University" + }, + { + "label": "Michigan State University-College of Law" + }, + { + "label": "Michigan Technological University" + }, + { + "label": "Mid Michigan Community College" + }, + { + "label": "Mid-America Christian University" + }, + { + "label": "Mid-America College of Funeral Service" + }, + { + "label": "MidAmerica Nazarene University" + }, + { + "label": "Mid-Atlantic Christian University" + }, + { + "label": "Middle Georgia State College" + }, + { + "label": "Middle Tennessee School of Anesthesia Inc" + }, + { + "label": "Middle Tennessee State University" + }, + { + "label": "Middlebury College" + }, + { + "label": "Middlesex Community College-Bedford" + }, + { + "label": "Middlesex Community College-Middletown" + }, + { + "label": "Middlesex County College" + }, + { + "label": "Midland College" + }, + { + "label": "Midland University" + }, + { + "label": "Midlands Technical College" + }, + { + "label": "Mid-Plains Community College" + }, + { + "label": "Mid-South Christian College" + }, + { + "label": "Midstate College" + }, + { + "label": "Mid-State Technical College" + }, + { + "label": "Midway College" + }, + { + "label": "Midwest College of Oriental Medicine-Chicago" + }, + { + "label": "Midwest College of Oriental Medicine-Racine" + }, + { + "label": "Midwest Institute" + }, + { + "label": "Midwestern Baptist Theological Seminary" + }, + { + "label": "Midwestern State University" + }, + { + "label": "Midwestern University-Downers Grove" + }, + { + "label": "Midwestern University-Glendale" + }, + { + "label": "Midwives College of Utah" + }, + { + "label": "Mildred Elley School-Albany Campus" + }, + { + "label": "Mildred Elley-New York Campus" + }, + { + "label": "Miles College" + }, + { + "label": "Miles Community College" + }, + { + "label": "Millennia Atlantic University" + }, + { + "label": "Miller-Motte College-Cary" + }, + { + "label": "Miller-Motte College-Fayetteville" + }, + { + "label": "Miller-Motte College-Greenville" + }, + { + "label": "Miller-Motte College-Jacksonville" + }, + { + "label": "Miller-Motte College-Raleigh" + }, + { + "label": "Miller-Motte College-Wilmington" + }, + { + "label": "Miller-Motte Technical College-Augusta" + }, + { + "label": "Miller-Motte Technical College-Charleston" + }, + { + "label": "Miller-Motte Technical College-Chattanooga" + }, + { + "label": "Miller-Motte Technical College-Clarksville" + }, + { + "label": "Miller-Motte Technical College-Columbus" + }, + { + "label": "Miller-Motte Technical College-Conway" + }, + { + "label": "Miller-Motte Technical College-Gulfport" + }, + { + "label": "Miller-Motte Technical College-Lynchburg" + }, + { + "label": "Miller-Motte Technical College-Macon" + }, + { + "label": "Miller-Motte Technical College-Madison" + }, + { + "label": "Miller-Motte Technical College-Roanoke" + }, + { + "label": "Millersville University of Pennsylvania" + }, + { + "label": "Milligan College" + }, + { + "label": "Millikin University" + }, + { + "label": "Mills College" + }, + { + "label": "Millsaps College" + }, + { + "label": "Milwaukee Area Technical College" + }, + { + "label": "Milwaukee Institute of Art & Design" + }, + { + "label": "Milwaukee School of Engineering" + }, + { + "label": "Mineral Area College" + }, + { + "label": "Minneapolis Business College" + }, + { + "label": "Minneapolis College of Art and Design" + }, + { + "label": "Minneapolis Community and Technical College" + }, + { + "label": "Minneapolis Media Institute" + }, + { + "label": "Minnesota School of Business-Blaine" + }, + { + "label": "Minnesota School of Business-Brooklyn Center" + }, + { + "label": "Minnesota School of Business-Elk River" + }, + { + "label": "Minnesota School of Business-Lakeville" + }, + { + "label": "Minnesota School of Business-Moorhead" + }, + { + "label": "Minnesota School of Business-Plymouth" + }, + { + "label": "Minnesota School of Business-Richfield" + }, + { + "label": "Minnesota School of Business-Rochester" + }, + { + "label": "Minnesota School of Business-Waite Park" + }, + { + "label": "Minnesota State College-Southeast Technical" + }, + { + "label": "Minnesota State Community and Technical College" + }, + { + "label": "Minnesota State University Moorhead" + }, + { + "label": "Minnesota State University-Mankato" + }, + { + "label": "Minnesota West Community and Technical College" + }, + { + "label": "Minot State University" + }, + { + "label": "MiraCosta College" + }, + { + "label": "Mirrer Yeshiva Cent Institute" + }, + { + "label": "Misericordia University" + }, + { + "label": "Mission College" + }, + { + "label": "Mississippi College" + }, + { + "label": "Mississippi Delta Community College" + }, + { + "label": "Mississippi Gulf Coast Community College" + }, + { + "label": "Mississippi State University" + }, + { + "label": "Mississippi University for Women" + }, + { + "label": "Mississippi Valley State University" + }, + { + "label": "Missouri Baptist University" + }, + { + "label": "Missouri College" + }, + { + "label": "Missouri Southern State University" + }, + { + "label": "Missouri State University-Springfield" + }, + { + "label": "Missouri State University-West Plains" + }, + { + "label": "Missouri Tech" + }, + { + "label": "Missouri University of Science and Technology" + }, + { + "label": "Missouri Valley College" + }, + { + "label": "Missouri Western State University" + }, + { + "label": "Mitchell College" + }, + { + "label": "Mitchell Community College" + }, + { + "label": "Mitchell Technical Institute" + }, + { + "label": "Moberly Area Community College" + }, + { + "label": "Modesto Junior College" + }, + { + "label": "Mohave Community College" + }, + { + "label": "Mohawk Valley Community College" + }, + { + "label": "Molloy College" + }, + { + "label": "Monmouth College" + }, + { + "label": "Monmouth University" + }, + { + "label": "Monroe College" + }, + { + "label": "Monroe Community College" + }, + { + "label": "Monroe County Community College" + }, + { + "label": "Montana Bible College" + }, + { + "label": "Montana State University" + }, + { + "label": "Montana State University-Billings" + }, + { + "label": "Montana State University-Northern" + }, + { + "label": "Montana Tech of the University of Montana" + }, + { + "label": "Montcalm Community College" + }, + { + "label": "Montclair State University" + }, + { + "label": "Monterey Institute of International Studies" + }, + { + "label": "Monterey Peninsula College" + }, + { + "label": "Montgomery College" + }, + { + "label": "Montgomery Community College" + }, + { + "label": "Montgomery County Community College" + }, + { + "label": "Montreat College" + }, + { + "label": "Montserrat College of Art" + }, + { + "label": "Moody Bible Institute" + }, + { + "label": "Moore College of Art and Design" + }, + { + "label": "Moorpark College" + }, + { + "label": "Moraine Park Technical College" + }, + { + "label": "Moraine Valley Community College" + }, + { + "label": "Moravian College" + }, + { + "label": "Morehead State University" + }, + { + "label": "Morehouse College" + }, + { + "label": "Morehouse School of Medicine" + }, + { + "label": "Moreno Valley College" + }, + { + "label": "Morgan Community College" + }, + { + "label": "Morgan State University" + }, + { + "label": "Morningside College" + }, + { + "label": "Morris College" + }, + { + "label": "Morrison Institute of Technology" + }, + { + "label": "Morrisville State College" + }, + { + "label": "Morton College" + }, + { + "label": "Motlow State Community College" + }, + { + "label": "Mott Community College" + }, + { + "label": "Moultrie Technical College" + }, + { + "label": "Mount Aloysius College" + }, + { + "label": "Mount Angel Seminary" + }, + { + "label": "Mount Carmel College of Nursing" + }, + { + "label": "Mount Holyoke College" + }, + { + "label": "Mount Ida College" + }, + { + "label": "Mount Marty College" + }, + { + "label": "Mount Mary University" + }, + { + "label": "Mount Mercy University" + }, + { + "label": "Mount Saint Joseph University" + }, + { + "label": "Mount Saint Mary College" + }, + { + "label": "Mount Saint Mary's University" + }, + { + "label": "Mount St Mary's University" + }, + { + "label": "Mount Vernon Nazarene University" + }, + { + "label": "Mount Wachusett Community College" + }, + { + "label": "Mount Washington College" + }, + { + "label": "Mountain Empire Community College" + }, + { + "label": "Mountain State College" + }, + { + "label": "Mountain View College" + }, + { + "label": "Mountwest Community and Technical College" + }, + { + "label": "Mt Hood Community College" + }, + { + "label": "Mt San Antonio College" + }, + { + "label": "Mt San Jacinto Community College District" + }, + { + "label": "Mt Sierra College" + }, + { + "label": "MTI College" + }, + { + "label": "Muhlenberg College" + }, + { + "label": "Multnomah University" + }, + { + "label": "Murray State College" + }, + { + "label": "Murray State University" + }, + { + "label": "Musicians Institute" + }, + { + "label": "Muskegon Community College" + }, + { + "label": "Muskingum University" + }, + { + "label": "Myotherapy Institute" + }, + { + "label": "Napa Valley College" + }, + { + "label": "Naropa University" + }, + { + "label": "Nash Community College" + }, + { + "label": "Nashotah House" + }, + { + "label": "Nashua Community College" + }, + { + "label": "Nashville State Community College" + }, + { + "label": "Nassau Community College" + }, + { + "label": "National American University-Albuquerque" + }, + { + "label": "National American University-Albuquerque West" + }, + { + "label": "National American University-Austin" + }, + { + "label": "National American University-Austin South" + }, + { + "label": "National American University-Bellevue" + }, + { + "label": "National American University-Bloomington" + }, + { + "label": "National American University-Brooklyn Center" + }, + { + "label": "National American University-Burnsville" + }, + { + "label": "National American University-Centennial" + }, + { + "label": "National American University-Colorado Springs" + }, + { + "label": "National American University-Colorado Springs South" + }, + { + "label": "National American University-Denver" + }, + { + "label": "National American University-Ellsworth AFB Extension" + }, + { + "label": "National American University-Georgetown" + }, + { + "label": "National American University-Harold D. Buckingham Graduate School" + }, + { + "label": "National American University-Independence" + }, + { + "label": "National American University-Indianapolis" + }, + { + "label": "National American University-Lee's Summit" + }, + { + "label": "National American University-Lewisville" + }, + { + "label": "National American University-Overland Park" + }, + { + "label": "National American University-Rapid City" + }, + { + "label": "National American University-Rochester" + }, + { + "label": "National American University-Roseville" + }, + { + "label": "National American University-Sioux Falls" + }, + { + "label": "National American University-Tulsa" + }, + { + "label": "National American University-Weldon Spring" + }, + { + "label": "National American University-Wichita" + }, + { + "label": "National American University-Wichita West" + }, + { + "label": "National American University-Zona Rosa" + }, + { + "label": "National College of Natural Medicine" + }, + { + "label": "National College-Canton" + }, + { + "label": "National College-Cincinnati" + }, + { + "label": "National College-Columbus" + }, + { + "label": "National College-Dayton" + }, + { + "label": "National College-Lexington" + }, + { + "label": "National College-Nashville" + }, + { + "label": "National College-Stow" + }, + { + "label": "National College-Willoughby Hills" + }, + { + "label": "National College-Youngstown" + }, + { + "label": "National Graduate School of Quality Management" + }, + { + "label": "National Institute of Massotherapy" + }, + { + "label": "National Louis University" + }, + { + "label": "National Massage Therapy Institute" + }, + { + "label": "National Paralegal College" + }, + { + "label": "National Park Community College" + }, + { + "label": "National University" + }, + { + "label": "National University College-Arecibo" + }, + { + "label": "National University College-Bayamon" + }, + { + "label": "National University College-Caguas" + }, + { + "label": "National University College-Ponce" + }, + { + "label": "National University College-Rio Grande" + }, + { + "label": "National University of Health Sciences" + }, + { + "label": "Naugatuck Valley Community College" + }, + { + "label": "Navajo Technical University" + }, + { + "label": "Naval Postgraduate School" + }, + { + "label": "Navarro College" + }, + { + "label": "Nazarene Bible College" + }, + { + "label": "Nazarene Theological Seminary" + }, + { + "label": "Nazareth College" + }, + { + "label": "Nebraska Christian College" + }, + { + "label": "Nebraska College of Technical Agriculture" + }, + { + "label": "Nebraska Indian Community College" + }, + { + "label": "Nebraska Methodist College of Nursing & Allied Health" + }, + { + "label": "Nebraska Wesleyan University" + }, + { + "label": "Neosho County Community College" + }, + { + "label": "Ner Israel Rabbinical College" + }, + { + "label": "Neumann University" + }, + { + "label": "Neumont University" + }, + { + "label": "Nevada State College" + }, + { + "label": "New Brunswick Theological Seminary" + }, + { + "label": "New Castle School of Trades" + }, + { + "label": "New College of Florida" + }, + { + "label": "New England College" + }, + { + "label": "New England College of Business and Finance" + }, + { + "label": "New England College of Optometry" + }, + { + "label": "New England Culinary Institute" + }, + { + "label": "New England Institute of Technology" + }, + { + "label": "New England Law-Boston" + }, + { + "label": "New England School of Acupuncture" + }, + { + "label": "New Hampshire Institute of Art" + }, + { + "label": "New Hope Christian College-Eugene" + }, + { + "label": "New Jersey City University" + }, + { + "label": "New Jersey Institute of Technology" + }, + { + "label": "New Mexico Highlands University" + }, + { + "label": "New Mexico Institute of Mining and Technology" + }, + { + "label": "New Mexico Junior College" + }, + { + "label": "New Mexico Military Institute" + }, + { + "label": "New Mexico State University-Alamogordo" + }, + { + "label": "New Mexico State University-Carlsbad" + }, + { + "label": "New Mexico State University-Dona Ana" + }, + { + "label": "New Mexico State University-Grants" + }, + { + "label": "New Mexico State University-Main Campus" + }, + { + "label": "New Orleans Baptist Theological Seminary" + }, + { + "label": "New River Community and Technical College" + }, + { + "label": "New River Community College" + }, + { + "label": "New York Academy of Art" + }, + { + "label": "New York Career Institute" + }, + { + "label": "New York Chiropractic College" + }, + { + "label": "New York College of Health Professions" + }, + { + "label": "New York College of Podiatric Medicine" + }, + { + "label": "New York College of Traditional Chinese Medicine" + }, + { + "label": "New York Conservatory for Dramatic Arts" + }, + { + "label": "New York Film Academy" + }, + { + "label": "New York Institute of Technology" + }, + { + "label": "New York Law School" + }, + { + "label": "New York Medical College" + }, + { + "label": "New York School of Interior Design" + }, + { + "label": "New York Theological Seminary" + }, + { + "label": "New York University" + }, + { + "label": "Newberry College" + }, + { + "label": "Newbury College" + }, + { + "label": "Newman University" + }, + { + "label": "Newschool of Architecture and Design" + }, + { + "label": "NHTI-Concord's Community College" + }, + { + "label": "Niagara County Community College" + }, + { + "label": "Niagara University" + }, + { + "label": "Nicholls State University" + }, + { + "label": "Nichols College" + }, + { + "label": "Nicolet Area Technical College" + }, + { + "label": "Nightingale College" + }, + { + "label": "Norco College" + }, + { + "label": "Norfolk State University" + }, + { + "label": "Normandale Community College" + }, + { + "label": "North American University" + }, + { + "label": "North Arkansas College" + }, + { + "label": "North Carolina A & T State University" + }, + { + "label": "North Carolina Central University" + }, + { + "label": "North Carolina State University at Raleigh" + }, + { + "label": "North Carolina Wesleyan College" + }, + { + "label": "North Central College" + }, + { + "label": "North Central Institute" + }, + { + "label": "North Central Kansas Technical College" + }, + { + "label": "North Central Michigan College" + }, + { + "label": "North Central Missouri College" + }, + { + "label": "North Central State College" + }, + { + "label": "North Central Texas College" + }, + { + "label": "North Central University" + }, + { + "label": "North Country Community College" + }, + { + "label": "North Dakota State College of Science" + }, + { + "label": "North Dakota State University-Main Campus" + }, + { + "label": "North Florida Community College" + }, + { + "label": "North Georgia Technical College" + }, + { + "label": "North Greenville University" + }, + { + "label": "North Hennepin Community College" + }, + { + "label": "North Idaho College" + }, + { + "label": "North Iowa Area Community College" + }, + { + "label": "North Lake College" + }, + { + "label": "North Park University" + }, + { + "label": "North Seattle College" + }, + { + "label": "North Shore Community College" + }, + { + "label": "Northampton County Area Community College" + }, + { + "label": "Northcentral Technical College" + }, + { + "label": "Northcentral University" + }, + { + "label": "Northeast Alabama Community College" + }, + { + "label": "Northeast Catholic College" + }, + { + "label": "Northeast Community College" + }, + { + "label": "Northeast Iowa Community College" + }, + { + "label": "Northeast Mississippi Community College" + }, + { + "label": "Northeast Ohio Medical University" + }, + { + "label": "Northeast State Community College" + }, + { + "label": "Northeast Texas Community College" + }, + { + "label": "Northeast Wisconsin Technical College" + }, + { + "label": "Northeastern Illinois University" + }, + { + "label": "Northeastern Junior College" + }, + { + "label": "Northeastern Oklahoma A&M College" + }, + { + "label": "Northeastern Seminary" + }, + { + "label": "Northeastern State University" + }, + { + "label": "Northeastern Technical College" + }, + { + "label": "Northeastern University" + }, + { + "label": "Northeastern University Global Network" + }, + { + "label": "Northern Arizona University" + }, + { + "label": "Northern Baptist Theological Seminary" + }, + { + "label": "Northern Essex Community College" + }, + { + "label": "Northern Illinois University" + }, + { + "label": "Northern Kentucky University" + }, + { + "label": "Northern Maine Community College" + }, + { + "label": "Northern Marianas College" + }, + { + "label": "Northern Michigan University" + }, + { + "label": "Northern New Mexico College" + }, + { + "label": "Northern Oklahoma College" + }, + { + "label": "Northern State University" + }, + { + "label": "Northern Virginia Community College" + }, + { + "label": "Northland College" + }, + { + "label": "Northland Community and Technical College" + }, + { + "label": "Northland International University" + }, + { + "label": "Northland Pioneer College" + }, + { + "label": "Northpoint Bible College" + }, + { + "label": "Northshore Technical Community College" + }, + { + "label": "NorthWest Arkansas Community College" + }, + { + "label": "Northwest Career College" + }, + { + "label": "Northwest Christian University" + }, + { + "label": "Northwest College" + }, + { + "label": "Northwest College of Art & Design" + }, + { + "label": "Northwest Florida State College" + }, + { + "label": "Northwest Indian College" + }, + { + "label": "Northwest Institute of Literary Arts" + }, + { + "label": "Northwest Iowa Community College" + }, + { + "label": "Northwest Kansas Technical College" + }, + { + "label": "Northwest Louisiana Technical College" + }, + { + "label": "Northwest Mississippi Community College" + }, + { + "label": "Northwest Missouri State University" + }, + { + "label": "Northwest Nazarene University" + }, + { + "label": "Northwest School of Wooden Boat Building" + }, + { + "label": "Northwest State Community College" + }, + { + "label": "Northwest Technical College" + }, + { + "label": "Northwest University" + }, + { + "label": "Northwest Vista College" + }, + { + "label": "Northwestern College" + }, + { + "label": "Northwestern College-Chicago Campus" + }, + { + "label": "Northwestern College-Southwestern Campus" + }, + { + "label": "Northwestern Connecticut Community College" + }, + { + "label": "Northwestern Health Sciences University" + }, + { + "label": "Northwestern Michigan College" + }, + { + "label": "Northwestern Oklahoma State University" + }, + { + "label": "Northwestern State University of Louisiana" + }, + { + "label": "Northwestern University" + }, + { + "label": "Northwest-Shoals Community College" + }, + { + "label": "Northwood University-Florida" + }, + { + "label": "Northwood University-Michigan" + }, + { + "label": "Northwood University-Texas" + }, + { + "label": "Norwalk Community College" + }, + { + "label": "Norwich University" + }, + { + "label": "Nossi College of Art" + }, + { + "label": "Notre Dame College" + }, + { + "label": "Notre Dame de Namur University" + }, + { + "label": "Notre Dame of Maryland University" + }, + { + "label": "Notre Dame Seminary Graduate School of Theology" + }, + { + "label": "Nova Southeastern University" + }, + { + "label": "Nueta Hidatsa Sahnish College" + }, + { + "label": "Nunez Community College" + }, + { + "label": "Nyack College" + }, + { + "label": "Oak Hills Christian College" + }, + { + "label": "Oakland City University" + }, + { + "label": "Oakland Community College" + }, + { + "label": "Oakland University" + }, + { + "label": "Oakton Community College" + }, + { + "label": "Oakwood University" + }, + { + "label": "Oberlin College" + }, + { + "label": "Oblate School of Theology" + }, + { + "label": "Occidental College" + }, + { + "label": "Ocean County College" + }, + { + "label": "Oconee Fall Line Technical College" + }, + { + "label": "Odessa College" + }, + { + "label": "Ogeechee Technical College" + }, + { + "label": "Oglala Lakota College" + }, + { + "label": "Oglethorpe University" + }, + { + "label": "Ohio Business College-Hilliard" + }, + { + "label": "Ohio Business College-Sandusky" + }, + { + "label": "Ohio Business College-Sheffield" + }, + { + "label": "Ohio Christian University" + }, + { + "label": "Ohio College of Massotherapy Inc" + }, + { + "label": "Ohio Dominican University" + }, + { + "label": "Ohio Mid-Western College" + }, + { + "label": "Ohio Northern University" + }, + { + "label": "Ohio State University Agricultural Technical Institute" + }, + { + "label": "Ohio State University-Lima Campus" + }, + { + "label": "Ohio State University-Main Campus" + }, + { + "label": "Ohio State University-Mansfield Campus" + }, + { + "label": "Ohio State University-Marion Campus" + }, + { + "label": "Ohio State University-Newark Campus" + }, + { + "label": "Ohio Technical College" + }, + { + "label": "Ohio Technical College-PowerSport Institute" + }, + { + "label": "Ohio University-Chillicothe Campus" + }, + { + "label": "Ohio University-Eastern Campus" + }, + { + "label": "Ohio University-Lancaster Campus" + }, + { + "label": "Ohio University-Main Campus" + }, + { + "label": "Ohio University-Southern Campus" + }, + { + "label": "Ohio University-Zanesville Campus" + }, + { + "label": "Ohio Valley College of Technology" + }, + { + "label": "Ohio Valley University" + }, + { + "label": "Ohio Wesleyan University" + }, + { + "label": "Ohlone College" + }, + { + "label": "Ohr Hameir Theological Seminary" + }, + { + "label": "Oklahoma Baptist University" + }, + { + "label": "Oklahoma Christian University" + }, + { + "label": "Oklahoma City Community College" + }, + { + "label": "Oklahoma City University" + }, + { + "label": "Oklahoma Panhandle State University" + }, + { + "label": "Oklahoma State University Center for Health Sciences" + }, + { + "label": "Oklahoma State University Institute of Technology" + }, + { + "label": "Oklahoma State University-Main Campus" + }, + { + "label": "Oklahoma State University-Oklahoma City" + }, + { + "label": "Oklahoma Technical College" + }, + { + "label": "Oklahoma Wesleyan University" + }, + { + "label": "Old Dominion University" + }, + { + "label": "Olivet College" + }, + { + "label": "Olivet Nazarene University" + }, + { + "label": "Olney Central College" + }, + { + "label": "Olympic College" + }, + { + "label": "Omaha School of Massage and Healthcare of Herzing University" + }, + { + "label": "O'More College of Design" + }, + { + "label": "Onondaga Community College" + }, + { + "label": "Oral Roberts University" + }, + { + "label": "Orange Coast College" + }, + { + "label": "Orange County Community College" + }, + { + "label": "Orangeburg Calhoun Technical College" + }, + { + "label": "Oregon Coast Community College" + }, + { + "label": "Oregon College of Art and Craft" + }, + { + "label": "Oregon College of Oriental Medicine" + }, + { + "label": "Oregon Health & Science University" + }, + { + "label": "Oregon Institute of Technology" + }, + { + "label": "Oregon State University" + }, + { + "label": "Orion College" + }, + { + "label": "Orleans Technical Institute" + }, + { + "label": "Otero Junior College" + }, + { + "label": "Otis College of Art and Design" + }, + { + "label": "Ottawa University-Jeffersonville" + }, + { + "label": "Ottawa University-Kansas City" + }, + { + "label": "Ottawa University-Milwaukee" + }, + { + "label": "Ottawa University-Online" + }, + { + "label": "Ottawa University-Ottawa" + }, + { + "label": "Ottawa University-Phoenix" + }, + { + "label": "Otterbein University" + }, + { + "label": "Ouachita Baptist University" + }, + { + "label": "Our Lady of the Lake College" + }, + { + "label": "Our Lady of the Lake University" + }, + { + "label": "Owens Community College" + }, + { + "label": "Owensboro Community and Technical College" + }, + { + "label": "Oxford Graduate School" + }, + { + "label": "Oxnard College" + }, + { + "label": "Ozark Christian College" + }, + { + "label": "Ozarka College" + }, + { + "label": "Ozarks Technical Community College" + }, + { + "label": "Pace Institute" + }, + { + "label": "Pace University-New York" + }, + { + "label": "Pacific College" + }, + { + "label": "Pacific College of Oriental Medicine-Chicago" + }, + { + "label": "Pacific College of Oriental Medicine-New York" + }, + { + "label": "Pacific College of Oriental Medicine-San Diego" + }, + { + "label": "Pacific Islands University" + }, + { + "label": "Pacific Lutheran Theological Seminary" + }, + { + "label": "Pacific Lutheran University" + }, + { + "label": "Pacific Northwest College of Art" + }, + { + "label": "Pacific Northwest University of Health Sciences" + }, + { + "label": "Pacific Oaks College" + }, + { + "label": "Pacific Rim Christian University" + }, + { + "label": "Pacific School of Religion" + }, + { + "label": "Pacific States University" + }, + { + "label": "Pacific Union College" + }, + { + "label": "Pacific University" + }, + { + "label": "Pacifica Graduate Institute" + }, + { + "label": "Paier College of Art Inc" + }, + { + "label": "Paine College" + }, + { + "label": "Palau Community College" + }, + { + "label": "Palm Beach Atlantic University" + }, + { + "label": "Palm Beach State College" + }, + { + "label": "Palmer College of Chiropractic" + }, + { + "label": "Palo Alto College" + }, + { + "label": "Palo Alto University" + }, + { + "label": "Palo Verde College" + }, + { + "label": "Palomar College" + }, + { + "label": "Pamlico Community College" + }, + { + "label": "Panola College" + }, + { + "label": "Paradise Valley Community College" + }, + { + "label": "Pardee RAND Graduate School" + }, + { + "label": "Paris Junior College" + }, + { + "label": "Park University" + }, + { + "label": "Parker University" + }, + { + "label": "Parkland College" + }, + { + "label": "Pasadena City College" + }, + { + "label": "Pasco-Hernando State College" + }, + { + "label": "Passaic County Community College" + }, + { + "label": "Patrick Henry College" + }, + { + "label": "Patrick Henry Community College" + }, + { + "label": "Paul D Camp Community College" + }, + { + "label": "Paul Quinn College" + }, + { + "label": "Paul Smiths College of Arts and Science" + }, + { + "label": "Payne Theological Seminary" + }, + { + "label": "Pearl River Community College" + }, + { + "label": "Peirce College" + }, + { + "label": "Pellissippi State Community College" + }, + { + "label": "Peninsula College" + }, + { + "label": "Penn Commercial Business/Technical School" + }, + { + "label": "Pennco Tech-Bristol" + }, + { + "label": "Pennsylvania Academy of the Fine Arts" + }, + { + "label": "Pennsylvania College of Art and Design" + }, + { + "label": "Pennsylvania College of Health Sciences" + }, + { + "label": "Pennsylvania College of Technology" + }, + { + "label": "Pennsylvania Highlands Community College" + }, + { + "label": "Pennsylvania Institute of Health and Technology" + }, + { + "label": "Pennsylvania Institute of Technology" + }, + { + "label": "Pennsylvania State University-College of Medicine" + }, + { + "label": "Pennsylvania State University-Dickinson Law" + }, + { + "label": "Pennsylvania State University-Main Campus" + }, + { + "label": "Pennsylvania State University-Penn State Abington" + }, + { + "label": "Pennsylvania State University-Penn State Altoona" + }, + { + "label": "Pennsylvania State University-Penn State Beaver" + }, + { + "label": "Pennsylvania State University-Penn State Berks" + }, + { + "label": "Pennsylvania State University-Penn State Brandywine" + }, + { + "label": "Pennsylvania State University-Penn State DuBois" + }, + { + "label": "Pennsylvania State University-Penn State Erie-Behrend College" + }, + { + "label": "Pennsylvania State University-Penn State Fayette- Eberly" + }, + { + "label": "Pennsylvania State University-Penn State Great Valley" + }, + { + "label": "Pennsylvania State University-Penn State Greater Allegheny" + }, + { + "label": "Pennsylvania State University-Penn State Harrisburg" + }, + { + "label": "Pennsylvania State University-Penn State Hazleton" + }, + { + "label": "Pennsylvania State University-Penn State Lehigh Valley" + }, + { + "label": "Pennsylvania State University-Penn State Mont Alto" + }, + { + "label": "Pennsylvania State University-Penn State New Kensington" + }, + { + "label": "Pennsylvania State University-Penn State Schuylkill" + }, + { + "label": "Pennsylvania State University-Penn State Shenango" + }, + { + "label": "Pennsylvania State University-Penn State Wilkes-Barre" + }, + { + "label": "Pennsylvania State University-Penn State Worthington Scranton" + }, + { + "label": "Pennsylvania State University-Penn State York" + }, + { + "label": "Pennsylvania State University-World Campus" + }, + { + "label": "Pensacola State College" + }, + { + "label": "Pentecostal Theological Seminary" + }, + { + "label": "Pepperdine University" + }, + { + "label": "Peru State College" + }, + { + "label": "Pfeiffer University" + }, + { + "label": "Philadelphia College of Osteopathic Medicine" + }, + { + "label": "Philadelphia University" + }, + { + "label": "Philander Smith College" + }, + { + "label": "Phillips Beth Israel School of Nursing" + }, + { + "label": "Phillips Community College of the University of Arkansas" + }, + { + "label": "Phillips Graduate Institute" + }, + { + "label": "Phillips Theological Seminary" + }, + { + "label": "Phoenix College" + }, + { + "label": "Phoenix Institute of Herbal Medicine & Acupuncture" + }, + { + "label": "Phoenix Seminary" + }, + { + "label": "Piedmont College" + }, + { + "label": "Piedmont Community College" + }, + { + "label": "Piedmont International University" + }, + { + "label": "Piedmont Technical College" + }, + { + "label": "Piedmont Virginia Community College" + }, + { + "label": "Pierce College-Fort Steilacoom" + }, + { + "label": "Pierce College-Puyallup" + }, + { + "label": "Pierpont Community and Technical College" + }, + { + "label": "Pikes Peak Community College" + }, + { + "label": "Pillar College" + }, + { + "label": "Pima Community College" + }, + { + "label": "Pima Medical Institute-Albuquerque" + }, + { + "label": "Pima Medical Institute-Aurora" + }, + { + "label": "Pima Medical Institute-Chula Vista" + }, + { + "label": "Pima Medical Institute-Colorado Springs" + }, + { + "label": "Pima Medical Institute-Denver" + }, + { + "label": "Pima Medical Institute-East Valley" + }, + { + "label": "Pima Medical Institute-Houston" + }, + { + "label": "Pima Medical Institute-Las Vegas" + }, + { + "label": "Pima Medical Institute-Mesa" + }, + { + "label": "Pima Medical Institute-Renton" + }, + { + "label": "Pima Medical Institute-Seattle" + }, + { + "label": "Pima Medical Institute-Tucson" + }, + { + "label": "Pinchot University" + }, + { + "label": "Pine Manor College" + }, + { + "label": "Pine Technical & Community College" + }, + { + "label": "Pinnacle Career Institute-Lawrence" + }, + { + "label": "Pinnacle Career Institute-North Kansas City" + }, + { + "label": "Pinnacle Career Institute-South Kansas City" + }, + { + "label": "Pioneer Pacific College" + }, + { + "label": "Pitt Community College" + }, + { + "label": "Pittsburg State University" + }, + { + "label": "Pittsburgh Career Institute" + }, + { + "label": "Pittsburgh Institute of Aeronautics" + }, + { + "label": "Pittsburgh Institute of Mortuary Science Inc" + }, + { + "label": "Pittsburgh Technical Institute" + }, + { + "label": "Pittsburgh Theological Seminary" + }, + { + "label": "Pitzer College" + }, + { + "label": "Platt College-Aurora" + }, + { + "label": "Platt College-Central OKC" + }, + { + "label": "Platt College-Los Angeles" + }, + { + "label": "Platt College-Moore" + }, + { + "label": "Platt College-North OKC" + }, + { + "label": "Platt College-Ontario" + }, + { + "label": "Platt College-Riverside" + }, + { + "label": "Platt College-San Diego" + }, + { + "label": "Platt College-Tulsa" + }, + { + "label": "Plaza College" + }, + { + "label": "Plymouth State University" + }, + { + "label": "Point Loma Nazarene University" + }, + { + "label": "Point Park University" + }, + { + "label": "Point University" + }, + { + "label": "Polk State College" + }, + { + "label": "Polytechnic University of Puerto Rico-Miami" + }, + { + "label": "Polytechnic University of Puerto Rico-Orlando" + }, + { + "label": "Pomeroy College of Nursing at Crouse Hospital" + }, + { + "label": "Pomona College" + }, + { + "label": "Ponce Health Sciences University" + }, + { + "label": "Ponce Paramedical College Inc" + }, + { + "label": "Pontifical Catholic University of Puerto Rico-Arecibo" + }, + { + "label": "Pontifical Catholic University of Puerto Rico-Mayaguez" + }, + { + "label": "Pontifical Catholic University of Puerto Rico-Ponce" + }, + { + "label": "Pontifical College Josephinum" + }, + { + "label": "Pontifical Faculty of the Immaculate Conception at the Dominican House of Studies" + }, + { + "label": "Pontifical John Paul II Institute for Studies on Marriage and Family" + }, + { + "label": "Pope St John XXIII National Seminary" + }, + { + "label": "Porterville College" + }, + { + "label": "Portland Community College" + }, + { + "label": "Portland State University" + }, + { + "label": "Post University" + }, + { + "label": "Potomac State College of West Virginia University" + }, + { + "label": "Prairie State College" + }, + { + "label": "Prairie View A & M University" + }, + { + "label": "Pratt Community College" + }, + { + "label": "Pratt Institute-Main" + }, + { + "label": "Presbyterian College" + }, + { + "label": "Prescott College" + }, + { + "label": "Presentation College" + }, + { + "label": "Prince George's Community College" + }, + { + "label": "Prince Institute-Southeast" + }, + { + "label": "Princeton Theological Seminary" + }, + { + "label": "Princeton University" + }, + { + "label": "Principia College" + }, + { + "label": "Prism Career Institute-Upper Darby" + }, + { + "label": "Professional Golfers Career College" + }, + { + "label": "Professional Skills Institute" + }, + { + "label": "Providence Christian College" + }, + { + "label": "Providence College" + }, + { + "label": "Provo College" + }, + { + "label": "Pueblo Community College" + }, + { + "label": "Puerto Rico Conservatory of Music" + }, + { + "label": "Pulaski Technical College" + }, + { + "label": "Purdue University-Calumet Campus" + }, + { + "label": "Purdue University-Main Campus" + }, + { + "label": "Purdue University-North Central Campus" + }, + { + "label": "Queens University of Charlotte" + }, + { + "label": "Quincy College" + }, + { + "label": "Quincy University" + }, + { + "label": "Quinebaug Valley Community College" + }, + { + "label": "Quinnipiac University" + }, + { + "label": "Quinsigamond Community College" + }, + { + "label": "Rabbi Jacob Joseph School" + }, + { + "label": "Rabbinical Academy Mesivta Rabbi Chaim Berlin" + }, + { + "label": "Rabbinical College Beth Shraga" + }, + { + "label": "Rabbinical College Bobover Yeshiva Bnei Zion" + }, + { + "label": "Rabbinical College of America" + }, + { + "label": "Rabbinical College of Ch'san Sofer New York" + }, + { + "label": "Rabbinical College of Long Island" + }, + { + "label": "Rabbinical College of Ohr Shimon Yisroel" + }, + { + "label": "Rabbinical College Ohr Yisroel" + }, + { + "label": "Rabbinical College Telshe" + }, + { + "label": "Rabbinical Seminary of America" + }, + { + "label": "Radford University" + }, + { + "label": "Radians College" + }, + { + "label": "Rainy River Community College" + }, + { + "label": "Ramapo College of New Jersey" + }, + { + "label": "Randolph College" + }, + { + "label": "Randolph Community College" + }, + { + "label": "Randolph-Macon College" + }, + { + "label": "Ranger College" + }, + { + "label": "Ranken Technical College" + }, + { + "label": "Rappahannock Community College" + }, + { + "label": "Raritan Valley Community College" + }, + { + "label": "Rasmussen College-Florida" + }, + { + "label": "Rasmussen College-Illinois" + }, + { + "label": "Rasmussen College-Minnesota" + }, + { + "label": "Rasmussen College-North Dakota" + }, + { + "label": "Rasmussen College-Wisconsin" + }, + { + "label": "Reading Area Community College" + }, + { + "label": "Reconstructionist Rabbinical College" + }, + { + "label": "Red Rocks Community College" + }, + { + "label": "Redlands Community College" + }, + { + "label": "Redstone College" + }, + { + "label": "Reed College" + }, + { + "label": "Reedley College" + }, + { + "label": "Reformed Presbyterian Theological Seminary" + }, + { + "label": "Refrigeration School Inc" + }, + { + "label": "Regent University" + }, + { + "label": "Regis College" + }, + { + "label": "Regis University" + }, + { + "label": "Reid State Technical College" + }, + { + "label": "Reinhardt University" + }, + { + "label": "Relay Graduate School of Education" + }, + { + "label": "Remington College of Nursing Orlando" + }, + { + "label": "Remington College-Baton Rouge Campus" + }, + { + "label": "Remington College-Cleveland Campus" + }, + { + "label": "Remington College-Dallas Campus" + }, + { + "label": "Remington College-Fort Worth Campus" + }, + { + "label": "Remington College-Heathrow Campus" + }, + { + "label": "Remington College-Honolulu Campus" + }, + { + "label": "Remington College-Houston Campus" + }, + { + "label": "Remington College-Lafayette Campus" + }, + { + "label": "Remington College-Little Rock Campus" + }, + { + "label": "Remington College-Memphis Campus" + }, + { + "label": "Remington College-Mobile Campus" + }, + { + "label": "Remington College-Nashville Campus" + }, + { + "label": "Remington College-North Houston Campus" + }, + { + "label": "Remington College-Shreveport Campus" + }, + { + "label": "Remington College-Tampa Campus" + }, + { + "label": "Rend Lake College" + }, + { + "label": "Rensselaer Hartford Graduate Center Inc" + }, + { + "label": "Rensselaer Polytechnic Institute" + }, + { + "label": "Renton Technical College" + }, + { + "label": "Research College of Nursing" + }, + { + "label": "Resurrection University" + }, + { + "label": "Rhode Island College" + }, + { + "label": "Rhode Island School of Design" + }, + { + "label": "Rhodes College" + }, + { + "label": "Rice University" + }, + { + "label": "Rich Mountain Community College" + }, + { + "label": "Richard Bland College of the College of William and Mary" + }, + { + "label": "Richland College" + }, + { + "label": "Richland Community College" + }, + { + "label": "Richmond Community College" + }, + { + "label": "Richmont Graduate University" + }, + { + "label": "Rider University" + }, + { + "label": "Ridgewater College" + }, + { + "label": "Ringling College of Art and Design" + }, + { + "label": "Rio Grande Bible Institute" + }, + { + "label": "Rio Hondo College" + }, + { + "label": "Rio Salado College" + }, + { + "label": "Ripon College" + }, + { + "label": "River Parishes Community College" + }, + { + "label": "River Valley Community College" + }, + { + "label": "Riverland Community College" + }, + { + "label": "Riverside City College" + }, + { + "label": "Riverside College of Health Careers" + }, + { + "label": "Rivier University" + }, + { + "label": "Roane State Community College" + }, + { + "label": "Roanoke College" + }, + { + "label": "Roanoke-Chowan Community College" + }, + { + "label": "Robert Morris University" + }, + { + "label": "Robert Morris University Illinois" + }, + { + "label": "Roberts Wesleyan College" + }, + { + "label": "Robeson Community College" + }, + { + "label": "Rochester College" + }, + { + "label": "Rochester Community and Technical College" + }, + { + "label": "Rochester Institute of Technology" + }, + { + "label": "Rock Valley College" + }, + { + "label": "Rockefeller University" + }, + { + "label": "Rockford University" + }, + { + "label": "Rockhurst University" + }, + { + "label": "Rockingham Community College" + }, + { + "label": "Rockland Community College" + }, + { + "label": "Rocky Mountain College" + }, + { + "label": "Rocky Mountain College of Art and Design" + }, + { + "label": "Rocky Mountain University of Health Professions" + }, + { + "label": "Rocky Vista University" + }, + { + "label": "Roger Williams University" + }, + { + "label": "Roger Williams University School of Law" + }, + { + "label": "Rogers State University" + }, + { + "label": "Rogue Community College" + }, + { + "label": "Rollins College" + }, + { + "label": "Roosevelt University" + }, + { + "label": "Rosalind Franklin University of Medicine and Science" + }, + { + "label": "Rose State College" + }, + { + "label": "Rosedale Bible College" + }, + { + "label": "Rosedale Technical Institute" + }, + { + "label": "Rose-Hulman Institute of Technology" + }, + { + "label": "Roseman University of Health Sciences" + }, + { + "label": "Rosemont College" + }, + { + "label": "Ross College-Sylvania" + }, + { + "label": "Rowan College at Burlington County" + }, + { + "label": "Rowan College at Gloucester County" + }, + { + "label": "Rowan University" + }, + { + "label": "Rowan-Cabarrus Community College" + }, + { + "label": "Roxbury Community College" + }, + { + "label": "Rush University" + }, + { + "label": "Rust College" + }, + { + "label": "Rutgers University-Camden" + }, + { + "label": "Rutgers University-New Brunswick" + }, + { + "label": "Rutgers University-Newark" + }, + { + "label": "SABER College" + }, + { + "label": "Sacramento City College" + }, + { + "label": "Sacred Heart Major Seminary" + }, + { + "label": "Sacred Heart School of Theology" + }, + { + "label": "Sacred Heart University" + }, + { + "label": "Saddleback College" + }, + { + "label": "SAE Institute of Technology-Atlanta" + }, + { + "label": "SAE Institute of Technology-Nashville" + }, + { + "label": "Sage College" + }, + { + "label": "Saginaw Chippewa Tribal College" + }, + { + "label": "Saginaw Valley State University" + }, + { + "label": "Saint Ambrose University" + }, + { + "label": "Saint Anselm College" + }, + { + "label": "Saint Anthony College of Nursing" + }, + { + "label": "Saint Augustine College" + }, + { + "label": "Saint Augustine's University" + }, + { + "label": "Saint Catharine College" + }, + { + "label": "Saint Charles Borromeo Seminary-Overbrook" + }, + { + "label": "Saint Cloud State University" + }, + { + "label": "Saint Edward's University" + }, + { + "label": "Saint Elizabeth College of Nursing-Utica" + }, + { + "label": "Saint Francis Medical Center College of Nursing" + }, + { + "label": "Saint Francis University" + }, + { + "label": "Saint John Fisher College" + }, + { + "label": "Saint John Vianney College Seminary" + }, + { + "label": "Saint Johns River State College" + }, + { + "label": "Saint John's Seminary" + }, + { + "label": "Saint Johns University" + }, + { + "label": "Saint Joseph Seminary College" + }, + { + "label": "Saint Josephs College" + }, + { + "label": "Saint Joseph's College of Maine" + }, + { + "label": "Saint Joseph's College-New York" + }, + { + "label": "Saint Joseph's University" + }, + { + "label": "Saint Leo University" + }, + { + "label": "Saint Louis Christian College" + }, + { + "label": "Saint Louis Community College" + }, + { + "label": "Saint Louis University" + }, + { + "label": "Saint Luke's College of Health Sciences" + }, + { + "label": "Saint Martin's University" + }, + { + "label": "Saint Mary-of-the-Woods College" + }, + { + "label": "Saint Mary's College" + }, + { + "label": "Saint Mary's College of California" + }, + { + "label": "Saint Mary's University of Minnesota" + }, + { + "label": "Saint Meinrad School of Theology" + }, + { + "label": "Saint Michael's College" + }, + { + "label": "Saint Norbert College" + }, + { + "label": "Saint Paul College" + }, + { + "label": "Saint Paul School of Theology" + }, + { + "label": "Saint Peter's University" + }, + { + "label": "Saint Vincent College" + }, + { + "label": "Saint Vincent de Paul Regional Seminary" + }, + { + "label": "Saint Vincent Seminary" + }, + { + "label": "Saint Vladimirs Orthodox Theological Seminary" + }, + { + "label": "Saint Xavier University" + }, + { + "label": "Salem College" + }, + { + "label": "Salem Community College" + }, + { + "label": "Salem International University" + }, + { + "label": "Salem State University" + }, + { + "label": "Salina Area Technical College" + }, + { + "label": "Salisbury University" + }, + { + "label": "Salish Kootenai College" + }, + { + "label": "Salt Lake Community College" + }, + { + "label": "Salter College-Chicopee" + }, + { + "label": "Salter College-West Boylston" + }, + { + "label": "Salus University" + }, + { + "label": "Salve Regina University" + }, + { + "label": "Sam Houston State University" + }, + { + "label": "Samaritan Hospital School of Nursing" + }, + { + "label": "Samford University" + }, + { + "label": "Sampson Community College" + }, + { + "label": "Samuel Merritt University" + }, + { + "label": "San Antonio College" + }, + { + "label": "San Bernardino Valley College" + }, + { + "label": "San Diego Christian College" + }, + { + "label": "San Diego City College" + }, + { + "label": "San Diego Mesa College" + }, + { + "label": "San Diego Miramar College" + }, + { + "label": "San Diego State University" + }, + { + "label": "San Francisco Art Institute" + }, + { + "label": "San Francisco Conservatory of Music" + }, + { + "label": "San Francisco State University" + }, + { + "label": "San Francisco Theological Seminary" + }, + { + "label": "San Jacinto Community College" + }, + { + "label": "San Joaquin College of Law" + }, + { + "label": "San Joaquin Delta College" + }, + { + "label": "San Joaquin Valley College-Visalia" + }, + { + "label": "San Jose City College" + }, + { + "label": "San Jose State University" + }, + { + "label": "San Juan Bautista School of Medicine" + }, + { + "label": "San Juan College" + }, + { + "label": "Sandhills Community College" + }, + { + "label": "Sanford Burnham Prybis Medical Discovery Institute" + }, + { + "label": "Sanford-Brown College-Atlanta" + }, + { + "label": "Sanford-Brown College-Brooklyn Center" + }, + { + "label": "Sanford-Brown College-Chicago" + }, + { + "label": "Sanford-Brown College-Dallas" + }, + { + "label": "Sanford-Brown College-Fenton" + }, + { + "label": "Sanford-Brown College-Houston" + }, + { + "label": "Sanford-Brown College-Las Vegas" + }, + { + "label": "Sanford-Brown College-Mendota Heights" + }, + { + "label": "Sanford-Brown College-Middleburg Heights" + }, + { + "label": "Sanford-Brown College-Online" + }, + { + "label": "Sanford-Brown College-Orlando" + }, + { + "label": "Sanford-Brown College-San Antonio-San Antonio" + }, + { + "label": "Sanford-Brown College-Seattle" + }, + { + "label": "Sanford-Brown College-Tampa" + }, + { + "label": "Sanford-Brown College-Tysons Corner" + }, + { + "label": "Sanford-Brown Institute-Ft Lauderdale" + }, + { + "label": "Sanford-Brown Institute-Jacksonville" + }, + { + "label": "Santa Ana College" + }, + { + "label": "Santa Barbara Business College-Bakersfield" + }, + { + "label": "Santa Barbara Business College-Santa Maria" + }, + { + "label": "Santa Barbara Business College-Ventura" + }, + { + "label": "Santa Barbara City College" + }, + { + "label": "Santa Clara University" + }, + { + "label": "Santa Fe College" + }, + { + "label": "Santa Fe Community College" + }, + { + "label": "Santa Fe University of Art and Design" + }, + { + "label": "Santa Monica College" + }, + { + "label": "Santa Rosa Junior College" + }, + { + "label": "Santiago Canyon College" + }, + { + "label": "Sarah Lawrence College" + }, + { + "label": "Sauk Valley Community College" + }, + { + "label": "Savannah College of Art and Design" + }, + { + "label": "Savannah State University" + }, + { + "label": "Savannah Technical College" + }, + { + "label": "Saybrook University" + }, + { + "label": "SBI Campus-An Affiliate of Sanford-Brown" + }, + { + "label": "Schenectady County Community College" + }, + { + "label": "Schiller International University" + }, + { + "label": "School of the Art Institute of Chicago" + }, + { + "label": "School of the Museum of Fine Arts-Boston" + }, + { + "label": "School of Visual Arts" + }, + { + "label": "Schoolcraft College" + }, + { + "label": "Schreiner University" + }, + { + "label": "Scottsdale Community College" + }, + { + "label": "Scripps College" + }, + { + "label": "Seattle Central College" + }, + { + "label": "Seattle Institute of Oriental Medicine" + }, + { + "label": "Seattle Pacific University" + }, + { + "label": "Seattle University" + }, + { + "label": "Selma University" + }, + { + "label": "Seminario Evangelico de Puerto Rico" + }, + { + "label": "Seminole State College" + }, + { + "label": "Seminole State College of Florida" + }, + { + "label": "Sentara College of Health Sciences" + }, + { + "label": "Sessions College for Professional Design" + }, + { + "label": "Seton Hall University" + }, + { + "label": "Seton Hill University" + }, + { + "label": "Sewanee-The University of the South" + }, + { + "label": "Seward County Community College and Area Technical School" + }, + { + "label": "Shasta Bible College and Graduate School" + }, + { + "label": "Shasta College" + }, + { + "label": "Shaw University" + }, + { + "label": "Shawnee Community College" + }, + { + "label": "Shawnee State University" + }, + { + "label": "Shelton State Community College" + }, + { + "label": "Shenandoah University" + }, + { + "label": "Shepherd University" + }, + { + "label": "Shepherds Theological Seminary" + }, + { + "label": "Sheridan College" + }, + { + "label": "Sherman College of Straight Chiropractic" + }, + { + "label": "Shiloh University" + }, + { + "label": "Shimer College" + }, + { + "label": "Shippensburg University of Pennsylvania" + }, + { + "label": "Sh'or Yoshuv Rabbinical College" + }, + { + "label": "Shoreline Community College" + }, + { + "label": "Shorter College" + }, + { + "label": "Shorter University" + }, + { + "label": "Shorter University-College of Adult & Professional Programs" + }, + { + "label": "Siena College" + }, + { + "label": "Siena Heights University" + }, + { + "label": "Sierra College" + }, + { + "label": "Sierra Nevada College" + }, + { + "label": "Silver Lake College of the Holy Family" + }, + { + "label": "Simmons College" + }, + { + "label": "Simmons College of Kentucky" + }, + { + "label": "Simpson College" + }, + { + "label": "Simpson University" + }, + { + "label": "Sinclair Community College" + }, + { + "label": "Sinte Gleska University" + }, + { + "label": "Sioux Falls Seminary" + }, + { + "label": "Sisseton Wahpeton College" + }, + { + "label": "SIT Graduate Institute" + }, + { + "label": "Sitting Bull College" + }, + { + "label": "Skagit Valley College" + }, + { + "label": "Skidmore College" + }, + { + "label": "Skyline College" + }, + { + "label": "Skyline College-Roanoke" + }, + { + "label": "Slippery Rock University of Pennsylvania" + }, + { + "label": "Smith College" + }, + { + "label": "Snead State Community College" + }, + { + "label": "Snow College" + }, + { + "label": "Sofia University" + }, + { + "label": "Sojourner-Douglass College" + }, + { + "label": "Soka University of America" + }, + { + "label": "Solano Community College" + }, + { + "label": "SOLEX College" + }, + { + "label": "Somerset Community College" + }, + { + "label": "Sonoma State University" + }, + { + "label": "Sotheby's Institute of Art-NY" + }, + { + "label": "South Arkansas Community College" + }, + { + "label": "South Baylo University" + }, + { + "label": "South Carolina State University" + }, + { + "label": "South Central College" + }, + { + "label": "South Central Louisiana Technical College-Young Memorial Campus" + }, + { + "label": "South Coast College" + }, + { + "label": "South College" + }, + { + "label": "South College-Asheville" + }, + { + "label": "South Dakota School of Mines and Technology" + }, + { + "label": "South Dakota State University" + }, + { + "label": "South Florida Bible College and Theological Seminary" + }, + { + "label": "South Florida State College" + }, + { + "label": "South Georgia State College" + }, + { + "label": "South Georgia Technical College" + }, + { + "label": "South Hills School of Business & Technology" + }, + { + "label": "South Louisiana Community College" + }, + { + "label": "South Mountain Community College" + }, + { + "label": "South Piedmont Community College" + }, + { + "label": "South Plains College" + }, + { + "label": "South Puget Sound Community College" + }, + { + "label": "South Seattle College" + }, + { + "label": "South Suburban College" + }, + { + "label": "South Texas College" + }, + { + "label": "South Texas College of Law" + }, + { + "label": "South University-Accelerated Graduate Programs" + }, + { + "label": "South University-Austin" + }, + { + "label": "South University-Cleveland" + }, + { + "label": "South University-Columbia" + }, + { + "label": "South University-High Point" + }, + { + "label": "South University-Montgomery" + }, + { + "label": "South University-Novi" + }, + { + "label": "South University–Richmond" + }, + { + "label": "South University-Savannah" + }, + { + "label": "South University–Savannah Online" + }, + { + "label": "South University-Tampa" + }, + { + "label": "South University-The Art Institute of Dallas" + }, + { + "label": "South University-The Art Institute of Fort Worth" + }, + { + "label": "South University–Virginia Beach" + }, + { + "label": "South University-West Palm Beach" + }, + { + "label": "Southcentral Kentucky Community and Technical College" + }, + { + "label": "Southeast Arkansas College" + }, + { + "label": "Southeast Community College Area" + }, + { + "label": "Southeast Kentucky Community and Technical College" + }, + { + "label": "Southeast Missouri Hospital College of Nursing and Health Sciences" + }, + { + "label": "Southeast Missouri State University" + }, + { + "label": "Southeast Technical Institute" + }, + { + "label": "Southeastern Baptist College" + }, + { + "label": "Southeastern Baptist Theological Seminary" + }, + { + "label": "Southeastern Bible College" + }, + { + "label": "Southeastern College-Jacksonville" + }, + { + "label": "Southeastern College-West Palm Beach" + }, + { + "label": "Southeastern Community College-West Burlington" + }, + { + "label": "Southeastern Community College-Whiteville" + }, + { + "label": "Southeastern Illinois College" + }, + { + "label": "Southeastern Louisiana University" + }, + { + "label": "Southeastern Oklahoma State University" + }, + { + "label": "Southeastern Technical College" + }, + { + "label": "Southeastern University" + }, + { + "label": "Southern Adventist University" + }, + { + "label": "Southern Arkansas University Main Campus" + }, + { + "label": "Southern Arkansas University Tech" + }, + { + "label": "Southern California Institute of Architecture" + }, + { + "label": "Southern California Institute of Technology" + }, + { + "label": "Southern California Seminary" + }, + { + "label": "Southern California University of Health Sciences" + }, + { + "label": "Southern California University SOMA" + }, + { + "label": "Southern College of Optometry" + }, + { + "label": "Southern Connecticut State University" + }, + { + "label": "Southern Crescent Technical College" + }, + { + "label": "Southern Illinois University-Carbondale" + }, + { + "label": "Southern Illinois University-Edwardsville" + }, + { + "label": "Southern Maine Community College" + }, + { + "label": "Southern Methodist University" + }, + { + "label": "Southern Nazarene University" + }, + { + "label": "Southern New Hampshire University" + }, + { + "label": "Southern Oregon University" + }, + { + "label": "Southern Polytechnic State University" + }, + { + "label": "Southern State Community College" + }, + { + "label": "Southern Technical College-Fort Myers" + }, + { + "label": "Southern Technical College-Orlando" + }, + { + "label": "Southern Union State Community College" + }, + { + "label": "Southern University and A & M College" + }, + { + "label": "Southern University at New Orleans" + }, + { + "label": "Southern University at Shreveport" + }, + { + "label": "Southern University Law Center" + }, + { + "label": "Southern Utah University" + }, + { + "label": "Southern Vermont College" + }, + { + "label": "Southern Virginia University" + }, + { + "label": "Southern Wesleyan University" + }, + { + "label": "Southern West Virginia Community and Technical College" + }, + { + "label": "Southside Regional Medical Center Professional Schools" + }, + { + "label": "Southside Virginia Community College" + }, + { + "label": "Southwest Acupuncture College-Albuquerque" + }, + { + "label": "Southwest Acupuncture College-Boulder" + }, + { + "label": "Southwest Acupuncture College-Santa Fe" + }, + { + "label": "Southwest Baptist University" + }, + { + "label": "Southwest College of Naturopathic Medicine & Health Sciences" + }, + { + "label": "Southwest Collegiate Institute for the Deaf" + }, + { + "label": "Southwest Georgia Technical College" + }, + { + "label": "Southwest Institute of Healing Arts" + }, + { + "label": "Southwest Minnesota State University" + }, + { + "label": "Southwest Mississippi Community College" + }, + { + "label": "Southwest Tennessee Community College" + }, + { + "label": "Southwest Texas Junior College" + }, + { + "label": "Southwest University at El Paso" + }, + { + "label": "Southwest University of Visual Arts-Albuquerque" + }, + { + "label": "Southwest University of Visual Arts-Tucson" + }, + { + "label": "Southwest Virginia Community College" + }, + { + "label": "Southwest Wisconsin Technical College" + }, + { + "label": "Southwestern Adventist University" + }, + { + "label": "Southwestern Assemblies of God University" + }, + { + "label": "Southwestern Christian College" + }, + { + "label": "Southwestern Christian University" + }, + { + "label": "Southwestern College-Chula Vista" + }, + { + "label": "Southwestern College-Santa Fe" + }, + { + "label": "Southwestern College-Winfield" + }, + { + "label": "Southwestern Community College-Creston" + }, + { + "label": "Southwestern Community College-Sylva" + }, + { + "label": "Southwestern Illinois College" + }, + { + "label": "Southwestern Indian Polytechnic Institute" + }, + { + "label": "Southwestern Law School" + }, + { + "label": "Southwestern Michigan College" + }, + { + "label": "Southwestern Oklahoma State University" + }, + { + "label": "Southwestern Oregon Community College" + }, + { + "label": "Southwestern University" + }, + { + "label": "SOWELA Technical Community College" + }, + { + "label": "Spalding University" + }, + { + "label": "Spartan College of Aeronautics and Technology" + }, + { + "label": "Spartanburg Community College" + }, + { + "label": "Spartanburg Methodist College" + }, + { + "label": "Spelman College" + }, + { + "label": "Spencerian College-Lexington" + }, + { + "label": "Spencerian College-Louisville" + }, + { + "label": "Spertus College" + }, + { + "label": "Spokane Community College" + }, + { + "label": "Spokane Falls Community College" + }, + { + "label": "Spoon River College" + }, + { + "label": "Spring Arbor University" + }, + { + "label": "Spring Hill College" + }, + { + "label": "Springfield College" + }, + { + "label": "Springfield College-School of Professional and Continuing Studies" + }, + { + "label": "Springfield Technical Community College" + }, + { + "label": "St Andrews University" + }, + { + "label": "St Bernard's School of Theology and Ministry" + }, + { + "label": "St Bonaventure University" + }, + { + "label": "St Catherine University" + }, + { + "label": "St Charles Community College" + }, + { + "label": "St Clair County Community College" + }, + { + "label": "St Cloud Technical and Community College" + }, + { + "label": "St Francis College" + }, + { + "label": "St John's College" + }, + { + "label": "St John's Seminary" + }, + { + "label": "St John's University-New York" + }, + { + "label": "St Joseph School of Nursing-Nashua" + }, + { + "label": "St Joseph's College of Nursing at St Joseph's Hospital Health Center" + }, + { + "label": "St Lawrence University" + }, + { + "label": "St Louis College of Health Careers-Fenton" + }, + { + "label": "St Louis College of Health Careers-St Louis" + }, + { + "label": "St Louis College of Pharmacy" + }, + { + "label": "St Luke's College" + }, + { + "label": "St Mary's College of Maryland" + }, + { + "label": "St Mary's University" + }, + { + "label": "St Olaf College" + }, + { + "label": "St Paul's School of Nursing-Queens" + }, + { + "label": "St Paul's School of Nursing-Staten Island" + }, + { + "label": "St Petersburg College" + }, + { + "label": "St Philip's College" + }, + { + "label": "St Thomas University" + }, + { + "label": "St Vincent's College" + }, + { + "label": "St. Gregory's University" + }, + { + "label": "St. John's College" + }, + { + "label": "St. John's College-Department of Nursing" + }, + { + "label": "St. Thomas Aquinas College" + }, + { + "label": "Stanbridge College" + }, + { + "label": "Standard Healthcare Services-College of Nursing" + }, + { + "label": "Stanford University" + }, + { + "label": "Stanly Community College" + }, + { + "label": "Stark State College" + }, + { + "label": "Starr King School for Ministry" + }, + { + "label": "State College of Florida-Manatee-Sarasota" + }, + { + "label": "State Fair Community College" + }, + { + "label": "State Technical College of Missouri" + }, + { + "label": "State University of New York at New Paltz" + }, + { + "label": "Stautzenberger College-Brecksville" + }, + { + "label": "Stautzenberger College-Maumee" + }, + { + "label": "Stephen F Austin State University" + }, + { + "label": "Stephens College" + }, + { + "label": "Sterling College-Craftsbury Common" + }, + { + "label": "Sterling College-Sterling" + }, + { + "label": "Stetson University" + }, + { + "label": "Stevens Institute of Technology" + }, + { + "label": "Stevens-Henager College-Boise" + }, + { + "label": "Stevens-Henager College-Idaho Falls" + }, + { + "label": "Stevens-Henager College-Logan" + }, + { + "label": "Stevens-Henager College-Murray" + }, + { + "label": "Stevens-Henager College-Orem" + }, + { + "label": "Stevens-Henager College-St. George" + }, + { + "label": "Stevens-Henager College-West Haven" + }, + { + "label": "Stevenson University" + }, + { + "label": "Stevens-The Institute of Business & Arts" + }, + { + "label": "Stillman College" + }, + { + "label": "Stockton University" + }, + { + "label": "Stone Child College" + }, + { + "label": "Stonehill College" + }, + { + "label": "Stony Brook University" + }, + { + "label": "Stratford University" + }, + { + "label": "Strayer University-Alabama" + }, + { + "label": "Strayer University-Arkansas" + }, + { + "label": "Strayer University-Delaware" + }, + { + "label": "Strayer University-District of Columbia" + }, + { + "label": "Strayer University-Florida" + }, + { + "label": "Strayer University-Georgia" + }, + { + "label": "Strayer University-Global Region" + }, + { + "label": "Strayer University-Louisiana" + }, + { + "label": "Strayer University-Maryland" + }, + { + "label": "Strayer University-Mississippi" + }, + { + "label": "Strayer University-New Jersey" + }, + { + "label": "Strayer University-North Carolina" + }, + { + "label": "Strayer University-Pennsylvania" + }, + { + "label": "Strayer University-South Carolina" + }, + { + "label": "Strayer University-Tennessee" + }, + { + "label": "Strayer University-Texas" + }, + { + "label": "Strayer University-Virginia" + }, + { + "label": "Strayer University-West Virginia" + }, + { + "label": "Suffolk County Community College" + }, + { + "label": "Suffolk University" + }, + { + "label": "Sul Ross State University" + }, + { + "label": "Sullivan College of Technology and Design" + }, + { + "label": "Sullivan County Community College" + }, + { + "label": "Sullivan University" + }, + { + "label": "SUM Bible College and Theological Seminary" + }, + { + "label": "Summit Christian College" + }, + { + "label": "Sumner College" + }, + { + "label": "SUNY at Albany" + }, + { + "label": "SUNY at Binghamton" + }, + { + "label": "SUNY at Fredonia" + }, + { + "label": "SUNY at Purchase College" + }, + { + "label": "SUNY Broome Community College" + }, + { + "label": "SUNY Buffalo State" + }, + { + "label": "SUNY College at Brockport" + }, + { + "label": "SUNY College at Cortland" + }, + { + "label": "SUNY College at Geneseo" + }, + { + "label": "SUNY College at Old Westbury" + }, + { + "label": "SUNY College at Oswego" + }, + { + "label": "SUNY College at Plattsburgh" + }, + { + "label": "SUNY College at Potsdam" + }, + { + "label": "SUNY College of Agriculture and Technology at Cobleskill" + }, + { + "label": "SUNY College of Environmental Science and Forestry" + }, + { + "label": "SUNY College of Optometry" + }, + { + "label": "SUNY College of Technology at Alfred" + }, + { + "label": "SUNY College of Technology at Canton" + }, + { + "label": "SUNY College of Technology at Delhi" + }, + { + "label": "SUNY Downstate Medical Center" + }, + { + "label": "SUNY Empire State College" + }, + { + "label": "SUNY Maritime College" + }, + { + "label": "SUNY Oneonta" + }, + { + "label": "SUNY Polytechnic Institute" + }, + { + "label": "SUNY Westchester Community College" + }, + { + "label": "Surry Community College" + }, + { + "label": "Susquehanna University" + }, + { + "label": "Sussex County Community College" + }, + { + "label": "Swarthmore College" + }, + { + "label": "Swedish Institute a College of Health Sciences" + }, + { + "label": "Sweet Briar College" + }, + { + "label": "Syracuse University" + }, + { + "label": "Tabor College" + }, + { + "label": "Tacoma Community College" + }, + { + "label": "Taft College" + }, + { + "label": "Taft University System" + }, + { + "label": "Talladega College" + }, + { + "label": "Tallahassee Community College" + }, + { + "label": "Talmudic College of Florida" + }, + { + "label": "Talmudical Academy-New Jersey" + }, + { + "label": "Talmudical Institute of Upstate New York" + }, + { + "label": "Talmudical Seminary of Bobov" + }, + { + "label": "Talmudical Seminary Oholei Torah" + }, + { + "label": "Talmudical Yeshiva of Philadelphia" + }, + { + "label": "Tarleton State University" + }, + { + "label": "Tarrant County College District" + }, + { + "label": "Taylor Business Institute" + }, + { + "label": "Taylor College" + }, + { + "label": "Taylor University" + }, + { + "label": "Teachers College at Columbia University" + }, + { + "label": "Technical Career Institutes" + }, + { + "label": "Technical College of the Lowcountry" + }, + { + "label": "Telshe Yeshiva-Chicago" + }, + { + "label": "Temple College" + }, + { + "label": "Temple University" + }, + { + "label": "Tennessee State University" + }, + { + "label": "Tennessee Technological University" + }, + { + "label": "Tennessee Temple University" + }, + { + "label": "Tennessee Wesleyan College" + }, + { + "label": "Terra State Community College" + }, + { + "label": "Texarkana College" + }, + { + "label": "Texas A & M International University" + }, + { + "label": "Texas A & M University-Central Texas" + }, + { + "label": "Texas A & M University-College Station" + }, + { + "label": "Texas A & M University-Commerce" + }, + { + "label": "Texas A & M University-Corpus Christi" + }, + { + "label": "Texas A & M University-Kingsville" + }, + { + "label": "Texas A & M University-Texarkana" + }, + { + "label": "Texas Chiropractic College Foundation Inc" + }, + { + "label": "Texas Christian University" + }, + { + "label": "Texas College" + }, + { + "label": "Texas County Technical College" + }, + { + "label": "Texas Health and Science University" + }, + { + "label": "Texas Lutheran University" + }, + { + "label": "Texas Southern University" + }, + { + "label": "Texas State Technical College-Harlingen" + }, + { + "label": "Texas State Technical College-Marshall" + }, + { + "label": "Texas State Technical College-Waco" + }, + { + "label": "Texas State Technical College-West Texas" + }, + { + "label": "Texas State University" + }, + { + "label": "Texas Tech University" + }, + { + "label": "Texas Tech University Health Sciences Center" + }, + { + "label": "Texas Wesleyan University" + }, + { + "label": "Texas Woman's University" + }, + { + "label": "Thaddeus Stevens College of Technology" + }, + { + "label": "The Art Institute of Atlanta" + }, + { + "label": "The Art Institute of Austin" + }, + { + "label": "The Art Institute of Charleston" + }, + { + "label": "The Art Institute of Charlotte" + }, + { + "label": "The Art Institute of Cincinnati-AIC College of Design" + }, + { + "label": "The Art Institute of Colorado" + }, + { + "label": "The Art Institute of Fort Lauderdale" + }, + { + "label": "The Art Institute of Houston" + }, + { + "label": "The Art Institute of Indianapolis" + }, + { + "label": "The Art Institute of Las Vegas" + }, + { + "label": "The Art Institute of Michigan" + }, + { + "label": "The Art Institute of New York City" + }, + { + "label": "The Art Institute of Ohio-Cincinnati" + }, + { + "label": "The Art Institute of Philadelphia" + }, + { + "label": "The Art Institute of Phoenix" + }, + { + "label": "The Art Institute of Pittsburgh" + }, + { + "label": "The Art Institute of Pittsburgh-Online Division" + }, + { + "label": "The Art Institute of Portland" + }, + { + "label": "The Art Institute of Raleigh-Durham" + }, + { + "label": "The Art Institute of Salt Lake City" + }, + { + "label": "The Art Institute of San Antonio" + }, + { + "label": "The Art Institute of Seattle" + }, + { + "label": "The Art Institute of St Louis" + }, + { + "label": "The Art Institute of Tennessee-Nashville" + }, + { + "label": "The Art Institute of Tucson" + }, + { + "label": "The Art Institute of Virginia Beach" + }, + { + "label": "The Art Institute of Washington" + }, + { + "label": "The Art Institute of Washington-Dulles" + }, + { + "label": "The Art Institute of Wisconsin" + }, + { + "label": "The Art Institutes International–Kansas City" + }, + { + "label": "The Art Institutes International-Minnesota" + }, + { + "label": "The Art Institutes of York-PA" + }, + { + "label": "The Baptist College of Florida" + }, + { + "label": "The Boston Conservatory" + }, + { + "label": "The California Maritime Academy" + }, + { + "label": "The Chicago School of Professional Psychology at Chicago" + }, + { + "label": "The Chicago School of Professional Psychology at Irvine" + }, + { + "label": "The Chicago School of Professional Psychology at Los Angeles" + }, + { + "label": "The Chicago School of Professional Psychology at Washington DC" + }, + { + "label": "The Chicago School of Professional Psychology at Westwood" + }, + { + "label": "The Christ College of Nursing and Health Sciences" + }, + { + "label": "The College of Health Care Professions-Austin" + }, + { + "label": "The College of Health Care Professions-Dallas" + }, + { + "label": "The College of Health Care Professions-Fort Worth" + }, + { + "label": "The College of Idaho" + }, + { + "label": "The College of New Jersey" + }, + { + "label": "The College of New Rochelle" + }, + { + "label": "The College of Saint Rose" + }, + { + "label": "The College of Saint Scholastica" + }, + { + "label": "The College of Westchester" + }, + { + "label": "The College of Wooster" + }, + { + "label": "The Commonwealth Medical College" + }, + { + "label": "The Community College of Baltimore County" + }, + { + "label": "The Creative Center" + }, + { + "label": "The Evergreen State College" + }, + { + "label": "The General Theological Seminary" + }, + { + "label": "The Illinois Institute of Art-Chicago" + }, + { + "label": "The Illinois Institute of Art-Schaumburg" + }, + { + "label": "The John Marshall Law School" + }, + { + "label": "The Juilliard School" + }, + { + "label": "The King’s College" + }, + { + "label": "The King's University" + }, + { + "label": "The Landing School" + }, + { + "label": "The Lincoln University" + }, + { + "label": "The Master's College and Seminary" + }, + { + "label": "The National Hispanic University" + }, + { + "label": "The New England Conservatory of Music" + }, + { + "label": "The New England Institute of Art" + }, + { + "label": "The New School" + }, + { + "label": "The Restaurant School at Walnut Hill College" + }, + { + "label": "The Robert B Miller College" + }, + { + "label": "The Sage Colleges" + }, + { + "label": "The Santa Barbara and Ventura Colleges of Law–Santa Barbara" + }, + { + "label": "The Santa Barbara and Ventura Colleges of Law-Ventura" + }, + { + "label": "The Seattle School of Theology & Psychology" + }, + { + "label": "The Southern Baptist Theological Seminary" + }, + { + "label": "The University of Alabama" + }, + { + "label": "The University of Findlay" + }, + { + "label": "The University of Montana" + }, + { + "label": "The University of Montana-Western" + }, + { + "label": "The University of Tampa" + }, + { + "label": "The University of Tennessee-Chattanooga" + }, + { + "label": "The University of Tennessee-Knoxville" + }, + { + "label": "The University of Tennessee-Martin" + }, + { + "label": "The University of Texas - Rio Grande Valley" + }, + { + "label": "The University of Texas at Arlington" + }, + { + "label": "The University of Texas at Austin" + }, + { + "label": "The University of Texas at Dallas" + }, + { + "label": "The University of Texas at El Paso" + }, + { + "label": "The University of Texas at San Antonio" + }, + { + "label": "The University of Texas at Tyler" + }, + { + "label": "The University of Texas Health Science Center at Houston" + }, + { + "label": "The University of Texas Health Science Center at San Antonio" + }, + { + "label": "The University of Texas MD Anderson Cancer Center" + }, + { + "label": "The University of Texas Medical Branch" + }, + { + "label": "The University of Texas of the Permian Basin" + }, + { + "label": "The University of the Arts" + }, + { + "label": "The University of Virginia's College at Wise" + }, + { + "label": "The University of West Florida" + }, + { + "label": "The Wright Institute" + }, + { + "label": "Thiel College" + }, + { + "label": "Thomas Aquinas College" + }, + { + "label": "Thomas College" + }, + { + "label": "Thomas Edison State University" + }, + { + "label": "Thomas Jefferson School of Law" + }, + { + "label": "Thomas Jefferson University" + }, + { + "label": "Thomas More College" + }, + { + "label": "Thomas More College of Liberal Arts" + }, + { + "label": "Thomas Nelson Community College" + }, + { + "label": "Thomas University" + }, + { + "label": "Three Rivers Community College-Norwich" + }, + { + "label": "Three Rivers Community College-Poplar Bluff" + }, + { + "label": "Thunderbird School of Global Management" + }, + { + "label": "Tidewater Community College" + }, + { + "label": "Tiffin University" + }, + { + "label": "Tillamook Bay Community College" + }, + { + "label": "Toccoa Falls College" + }, + { + "label": "Tohono O'Odham Community College" + }, + { + "label": "Tompkins Cortland Community College" + }, + { + "label": "Torah Temimah Talmudical Seminary" + }, + { + "label": "Tougaloo College" + }, + { + "label": "Touro College" + }, + { + "label": "Touro University California" + }, + { + "label": "Touro University Nevada" + }, + { + "label": "Touro University Worldwide" + }, + { + "label": "Towson University" + }, + { + "label": "Transylvania University" + }, + { + "label": "Treasure Valley Community College" + }, + { + "label": "Trevecca Nazarene University" + }, + { + "label": "Triangle Tech Inc-Bethlehem" + }, + { + "label": "Triangle Tech Inc-Dubois" + }, + { + "label": "Triangle Tech Inc-Erie" + }, + { + "label": "Triangle Tech Inc-Greensburg" + }, + { + "label": "Triangle Tech Inc-Pittsburgh" + }, + { + "label": "Triangle Tech Inc-Sunbury" + }, + { + "label": "Tribeca Flashpoint College" + }, + { + "label": "Tri-County Community College" + }, + { + "label": "Tri-County Technical College" + }, + { + "label": "Trident Technical College" + }, + { + "label": "Trident University International" + }, + { + "label": "Trine University" + }, + { + "label": "Trine University-Regional/Non-Traditional Campuses" + }, + { + "label": "Trinidad State Junior College" + }, + { + "label": "Trinity Baptist College" + }, + { + "label": "Trinity Bible College" + }, + { + "label": "Trinity Christian College" + }, + { + "label": "Trinity College" + }, + { + "label": "Trinity College of Florida" + }, + { + "label": "Trinity College of Nursing & Health Sciences" + }, + { + "label": "Trinity Episcopal School for Ministry" + }, + { + "label": "Trinity International University-Florida" + }, + { + "label": "Trinity International University-Illinois" + }, + { + "label": "Trinity Law School" + }, + { + "label": "Trinity Lutheran College" + }, + { + "label": "Trinity Lutheran Seminary" + }, + { + "label": "Trinity University" + }, + { + "label": "Trinity Valley Community College" + }, + { + "label": "Trinity Washington University" + }, + { + "label": "Tri-State Bible College" + }, + { + "label": "Tri-State College of Acupuncture" + }, + { + "label": "Triton College" + }, + { + "label": "Trocaire College" + }, + { + "label": "Troy University" + }, + { + "label": "Truckee Meadows Community College" + }, + { + "label": "Truett-McConnell College" + }, + { + "label": "Truman State University" + }, + { + "label": "Trumbull Business College" + }, + { + "label": "Tufts University" + }, + { + "label": "Tulane University of Louisiana" + }, + { + "label": "Tulsa Community College" + }, + { + "label": "Tulsa Welding School-Tulsa-Tulsa" + }, + { + "label": "Tunxis Community College" + }, + { + "label": "Turtle Mountain Community College" + }, + { + "label": "Tusculum College" + }, + { + "label": "Tuskegee University" + }, + { + "label": "Tyler Junior College" + }, + { + "label": "Ulster County Community College" + }, + { + "label": "Ultimate Medical Academy-Clearwater" + }, + { + "label": "Ultimate Medical Academy-Tampa" + }, + { + "label": "Ultrasound Medical Institute" + }, + { + "label": "Umpqua Community College" + }, + { + "label": "Unification Theological Seminary" + }, + { + "label": "Union College-Barbourville" + }, + { + "label": "Union College-Lincoln" + }, + { + "label": "Union College-Schenectady" + }, + { + "label": "Union County College" + }, + { + "label": "Union Graduate College" + }, + { + "label": "Union Institute & University" + }, + { + "label": "Union Presbyterian Seminary" + }, + { + "label": "Union Theological Seminary in the City of New York" + }, + { + "label": "Union University" + }, + { + "label": "United Education Institute-Huntington Park Campus" + }, + { + "label": "United States Air Force Academy" + }, + { + "label": "United States Coast Guard Academy" + }, + { + "label": "United States Merchant Marine Academy" + }, + { + "label": "United States Military Academy" + }, + { + "label": "United States Naval Academy" + }, + { + "label": "United States Sports Academy" + }, + { + "label": "United States University" + }, + { + "label": "United Talmudical Seminary" + }, + { + "label": "United Theological Seminary" + }, + { + "label": "United Theological Seminary of the Twin Cities" + }, + { + "label": "United Tribes Technical College" + }, + { + "label": "Unitek College" + }, + { + "label": "Unity College" + }, + { + "label": "Universal College of Healing Arts" + }, + { + "label": "Universal Technical Institute of Arizona Inc" + }, + { + "label": "Universal Technology College of Puerto Rico" + }, + { + "label": "Universidad Adventista de las Antillas" + }, + { + "label": "Universidad Central de Bayamon" + }, + { + "label": "Universidad Central Del Caribe" + }, + { + "label": "Universidad Del Este" + }, + { + "label": "Universidad del Sagrado Corazon" + }, + { + "label": "Universidad Del Turabo" + }, + { + "label": "Universidad Internacional Iberoamericana" + }, + { + "label": "Universidad Metropolitana" + }, + { + "label": "Universidad Pentecostal Mizpa" + }, + { + "label": "Universidad Politecnica de Puerto Rico" + }, + { + "label": "Universidad Teologica del Caribe" + }, + { + "label": "University at Buffalo" + }, + { + "label": "University of Advancing Technology" + }, + { + "label": "University of Akron Main Campus" + }, + { + "label": "University of Akron Wayne College" + }, + { + "label": "University of Alabama at Birmingham" + }, + { + "label": "University of Alabama in Huntsville" + }, + { + "label": "University of Alaska Anchorage" + }, + { + "label": "University of Alaska Fairbanks" + }, + { + "label": "University of Alaska Southeast" + }, + { + "label": "University of Antelope Valley" + }, + { + "label": "University of Arizona" + }, + { + "label": "University of Arkansas" + }, + { + "label": "University of Arkansas at Little Rock" + }, + { + "label": "University of Arkansas at Monticello" + }, + { + "label": "University of Arkansas at Pine Bluff" + }, + { + "label": "University of Arkansas Community College-Batesville" + }, + { + "label": "University of Arkansas Community College-Hope" + }, + { + "label": "University of Arkansas Community College-Morrilton" + }, + { + "label": "University of Arkansas for Medical Sciences" + }, + { + "label": "University of Arkansas-Fort Smith" + }, + { + "label": "University of Baltimore" + }, + { + "label": "University of Bridgeport" + }, + { + "label": "University of California-Berkeley" + }, + { + "label": "University of California-Davis" + }, + { + "label": "University of California-Hastings College of Law" + }, + { + "label": "University of California-Irvine" + }, + { + "label": "University of California-Los Angeles" + }, + { + "label": "University of California-Merced" + }, + { + "label": "University of California-Riverside" + }, + { + "label": "University of California-San Diego" + }, + { + "label": "University of California-San Francisco" + }, + { + "label": "University of California-Santa Barbara" + }, + { + "label": "University of California-Santa Cruz" + }, + { + "label": "University of Central Arkansas" + }, + { + "label": "University of Central Florida" + }, + { + "label": "University of Central Missouri" + }, + { + "label": "University of Central Oklahoma" + }, + { + "label": "University of Charleston" + }, + { + "label": "University of Chicago" + }, + { + "label": "University of Cincinnati-Blue Ash College" + }, + { + "label": "University of Cincinnati-Clermont College" + }, + { + "label": "University of Cincinnati-Main Campus" + }, + { + "label": "University of Colorado Boulder" + }, + { + "label": "University of Colorado Colorado Springs" + }, + { + "label": "University of Colorado Denver" + }, + { + "label": "University of Connecticut" + }, + { + "label": "University of Dallas" + }, + { + "label": "University of Dayton" + }, + { + "label": "University of Delaware" + }, + { + "label": "University of Denver" + }, + { + "label": "University of Detroit Mercy" + }, + { + "label": "University of Dubuque" + }, + { + "label": "University of East-West Medicine" + }, + { + "label": "University of Evansville" + }, + { + "label": "University of Florida" + }, + { + "label": "University of Fort Lauderdale" + }, + { + "label": "University of Georgia" + }, + { + "label": "University of Great Falls" + }, + { + "label": "University of Guam" + }, + { + "label": "University of Hartford" + }, + { + "label": "University of Hawaii at Hilo" + }, + { + "label": "University of Hawaii at Manoa" + }, + { + "label": "University of Hawaii Maui College" + }, + { + "label": "University of Hawaii-West Oahu" + }, + { + "label": "University of Holy Cross" + }, + { + "label": "University of Houston" + }, + { + "label": "University of Houston-Clear Lake" + }, + { + "label": "University of Houston-Downtown" + }, + { + "label": "University of Houston-Victoria" + }, + { + "label": "University of Idaho" + }, + { + "label": "University of Illinois at Chicago" + }, + { + "label": "University of Illinois at Springfield" + }, + { + "label": "University of Illinois at Urbana-Champaign" + }, + { + "label": "University of Indianapolis" + }, + { + "label": "University of Iowa" + }, + { + "label": "University of Jamestown" + }, + { + "label": "University of Kansas" + }, + { + "label": "University of Kentucky" + }, + { + "label": "University of La Verne" + }, + { + "label": "University of Louisiana at Lafayette" + }, + { + "label": "University of Louisiana at Monroe" + }, + { + "label": "University of Louisville" + }, + { + "label": "University of Maine" + }, + { + "label": "University of Maine at Augusta" + }, + { + "label": "University of Maine at Farmington" + }, + { + "label": "University of Maine at Fort Kent" + }, + { + "label": "University of Maine at Machias" + }, + { + "label": "University of Maine at Presque Isle" + }, + { + "label": "University of Management and Technology" + }, + { + "label": "University of Mary" + }, + { + "label": "University of Mary Hardin-Baylor" + }, + { + "label": "University of Mary Washington" + }, + { + "label": "University of Maryland Eastern Shore" + }, + { + "label": "University of Maryland-Baltimore" + }, + { + "label": "University of Maryland-Baltimore County" + }, + { + "label": "University of Maryland-College Park" + }, + { + "label": "University of Maryland-University College" + }, + { + "label": "University of Massachusetts Medical School Worcester" + }, + { + "label": "University of Massachusetts-Amherst" + }, + { + "label": "University of Massachusetts-Boston" + }, + { + "label": "University of Massachusetts-Dartmouth" + }, + { + "label": "University of Massachusetts-Lowell" + }, + { + "label": "University of Memphis" + }, + { + "label": "University of Miami" + }, + { + "label": "University of Michigan-Ann Arbor" + }, + { + "label": "University of Michigan-Dearborn" + }, + { + "label": "University of Michigan-Flint" + }, + { + "label": "University of Minnesota-Crookston" + }, + { + "label": "University of Minnesota-Duluth" + }, + { + "label": "University of Minnesota-Morris" + }, + { + "label": "University of Minnesota-Rochester" + }, + { + "label": "University of Minnesota-Twin Cities" + }, + { + "label": "University of Mississippi" + }, + { + "label": "University of Missouri-Columbia" + }, + { + "label": "University of Missouri-Kansas City" + }, + { + "label": "University of Missouri-St Louis" + }, + { + "label": "University of Mobile" + }, + { + "label": "University of Montevallo" + }, + { + "label": "University of Mount Olive" + }, + { + "label": "University of Mount Union" + }, + { + "label": "University of Nebraska at Kearney" + }, + { + "label": "University of Nebraska at Omaha" + }, + { + "label": "University of Nebraska Medical Center" + }, + { + "label": "University of Nebraska-Lincoln" + }, + { + "label": "University of Nevada-Las Vegas" + }, + { + "label": "University of Nevada-Reno" + }, + { + "label": "University of New England" + }, + { + "label": "University of New Hampshire at Manchester" + }, + { + "label": "University of New Hampshire-Main Campus" + }, + { + "label": "University of New Hampshire-School of Law" + }, + { + "label": "University of New Haven" + }, + { + "label": "University of New Mexico-Gallup Campus" + }, + { + "label": "University of New Mexico-Los Alamos Campus" + }, + { + "label": "University of New Mexico-Main Campus" + }, + { + "label": "University of New Mexico-Taos Campus" + }, + { + "label": "University of New Mexico-Valencia County Campus" + }, + { + "label": "University of New Orleans" + }, + { + "label": "University of North Alabama" + }, + { + "label": "University of North Carolina at Asheville" + }, + { + "label": "University of North Carolina at Chapel Hill" + }, + { + "label": "University of North Carolina at Charlotte" + }, + { + "label": "University of North Carolina at Greensboro" + }, + { + "label": "University of North Carolina at Pembroke" + }, + { + "label": "University of North Carolina School of the Arts" + }, + { + "label": "University of North Carolina Wilmington" + }, + { + "label": "University of North Dakota" + }, + { + "label": "University of North Florida" + }, + { + "label": "University of North Georgia" + }, + { + "label": "University of North Texas" + }, + { + "label": "University of North Texas at Dallas" + }, + { + "label": "University of North Texas Health Science Center" + }, + { + "label": "University of Northern Colorado" + }, + { + "label": "University of Northern Iowa" + }, + { + "label": "University of Northwestern Ohio" + }, + { + "label": "University of Northwestern-St Paul" + }, + { + "label": "University of Notre Dame" + }, + { + "label": "University of Oklahoma-Health Sciences Center" + }, + { + "label": "University of Oklahoma-Norman Campus" + }, + { + "label": "University of Oregon" + }, + { + "label": "University of Pennsylvania" + }, + { + "label": "University of Phoenix-Alabama" + }, + { + "label": "University of Phoenix-Arizona" + }, + { + "label": "University of Phoenix-Arkansas" + }, + { + "label": "University of Phoenix-California" + }, + { + "label": "University of Phoenix-Colorado" + }, + { + "label": "University of Phoenix-Connecticut" + }, + { + "label": "University of Phoenix-Florida" + }, + { + "label": "University of Phoenix-Georgia" + }, + { + "label": "University of Phoenix-Hawaii" + }, + { + "label": "University of Phoenix-Idaho" + }, + { + "label": "University of Phoenix-Illinois" + }, + { + "label": "University of Phoenix-Indiana" + }, + { + "label": "University of Phoenix-Iowa" + }, + { + "label": "University of Phoenix-Kentucky" + }, + { + "label": "University of Phoenix-Louisiana" + }, + { + "label": "University of Phoenix-Maryland" + }, + { + "label": "University of Phoenix-Massachusetts" + }, + { + "label": "University of Phoenix-Michigan" + }, + { + "label": "University of Phoenix-Minnesota" + }, + { + "label": "University of Phoenix-Mississippi" + }, + { + "label": "University of Phoenix-Missouri" + }, + { + "label": "University of Phoenix-Nevada" + }, + { + "label": "University of Phoenix-New Jersey" + }, + { + "label": "University of Phoenix-New Mexico" + }, + { + "label": "University of Phoenix-North Carolina" + }, + { + "label": "University of Phoenix-Ohio" + }, + { + "label": "University of Phoenix-Oklahoma" + }, + { + "label": "University of Phoenix-Oregon" + }, + { + "label": "University of Phoenix-Pennsylvania" + }, + { + "label": "University of Phoenix-Puerto Rico" + }, + { + "label": "University of Phoenix-South Carolina" + }, + { + "label": "University of Phoenix-Tennessee" + }, + { + "label": "University of Phoenix-Texas" + }, + { + "label": "University of Phoenix-Utah" + }, + { + "label": "University of Phoenix-Virginia" + }, + { + "label": "University of Phoenix-Washington" + }, + { + "label": "University of Phoenix-Washington DC" + }, + { + "label": "University of Phoenix-Wisconsin" + }, + { + "label": "University of Pikeville" + }, + { + "label": "University of Pittsburgh-Bradford" + }, + { + "label": "University of Pittsburgh-Greensburg" + }, + { + "label": "University of Pittsburgh-Johnstown" + }, + { + "label": "University of Pittsburgh-Pittsburgh Campus" + }, + { + "label": "University of Pittsburgh-Titusville" + }, + { + "label": "University of Portland" + }, + { + "label": "University of Puerto Rico-Aguadilla" + }, + { + "label": "University of Puerto Rico-Arecibo" + }, + { + "label": "University of Puerto Rico-Bayamon" + }, + { + "label": "University of Puerto Rico-Carolina" + }, + { + "label": "University of Puerto Rico-Cayey" + }, + { + "label": "University of Puerto Rico-Humacao" + }, + { + "label": "University of Puerto Rico-Mayaguez" + }, + { + "label": "University of Puerto Rico-Medical Sciences" + }, + { + "label": "University of Puerto Rico-Ponce" + }, + { + "label": "University of Puerto Rico-Rio Piedras" + }, + { + "label": "University of Puerto Rico-Utuado" + }, + { + "label": "University of Puget Sound" + }, + { + "label": "University of Redlands" + }, + { + "label": "University of Rhode Island" + }, + { + "label": "University of Richmond" + }, + { + "label": "University of Rio Grande" + }, + { + "label": "University of Rochester" + }, + { + "label": "University of Saint Francis-Fort Wayne" + }, + { + "label": "University of Saint Joseph" + }, + { + "label": "University of Saint Mary" + }, + { + "label": "University of Saint Mary of the Lake" + }, + { + "label": "University of San Diego" + }, + { + "label": "University of San Francisco" + }, + { + "label": "University of Science and Arts of Oklahoma" + }, + { + "label": "University of Scranton" + }, + { + "label": "University of Sioux Falls" + }, + { + "label": "University of South Alabama" + }, + { + "label": "University of South Carolina-Aiken" + }, + { + "label": "University of South Carolina-Beaufort" + }, + { + "label": "University of South Carolina-Columbia" + }, + { + "label": "University of South Carolina-Lancaster" + }, + { + "label": "University of South Carolina-Salkehatchie" + }, + { + "label": "University of South Carolina-Sumter" + }, + { + "label": "University of South Carolina-Union" + }, + { + "label": "University of South Carolina-Upstate" + }, + { + "label": "University of South Dakota" + }, + { + "label": "University of South Florida-Main Campus" + }, + { + "label": "University of South Florida-Sarasota-Manatee" + }, + { + "label": "University of South Florida-St Petersburg" + }, + { + "label": "University of Southern California" + }, + { + "label": "University of Southern Indiana" + }, + { + "label": "University of Southern Maine" + }, + { + "label": "University of Southern Mississippi" + }, + { + "label": "University of Southernmost Florida" + }, + { + "label": "University of St Augustine for Health Sciences" + }, + { + "label": "University of St Francis" + }, + { + "label": "University of St Thomas-Houston" + }, + { + "label": "University of St Thomas-Saint Paul" + }, + { + "label": "University of Texas Southwestern Medical Center" + }, + { + "label": "University of the Cumberlands" + }, + { + "label": "University of the District of Columbia" + }, + { + "label": "University of the District of Columbia-David A Clarke School of Law" + }, + { + "label": "University of the Incarnate Word" + }, + { + "label": "University of the Ozarks" + }, + { + "label": "University of the Pacific" + }, + { + "label": "University of the Potomac-VA Campus" + }, + { + "label": "University of the Potomac-Washington DC Campus" + }, + { + "label": "University of the Rockies" + }, + { + "label": "University of the Sciences" + }, + { + "label": "University of the Southwest" + }, + { + "label": "University of the Virgin Islands" + }, + { + "label": "University of the West" + }, + { + "label": "University of Toledo" + }, + { + "label": "University of Tulsa" + }, + { + "label": "University of Utah" + }, + { + "label": "University of Valley Forge" + }, + { + "label": "University of Vermont" + }, + { + "label": "University of Virginia-Main Campus" + }, + { + "label": "University of Washington-Bothell Campus" + }, + { + "label": "University of Washington-Seattle Campus" + }, + { + "label": "University of Washington-Tacoma Campus" + }, + { + "label": "University of West Alabama" + }, + { + "label": "University of West Georgia" + }, + { + "label": "University of Western States" + }, + { + "label": "University of Wisconsin Colleges" + }, + { + "label": "University of Wisconsin-Eau Claire" + }, + { + "label": "University of Wisconsin-Green Bay" + }, + { + "label": "University of Wisconsin-La Crosse" + }, + { + "label": "University of Wisconsin-Madison" + }, + { + "label": "University of Wisconsin-Milwaukee" + }, + { + "label": "University of Wisconsin-Oshkosh" + }, + { + "label": "University of Wisconsin-Parkside" + }, + { + "label": "University of Wisconsin-Platteville" + }, + { + "label": "University of Wisconsin-River Falls" + }, + { + "label": "University of Wisconsin-Stevens Point" + }, + { + "label": "University of Wisconsin-Stout" + }, + { + "label": "University of Wisconsin-Superior" + }, + { + "label": "University of Wisconsin-Whitewater" + }, + { + "label": "University of Wyoming" + }, + { + "label": "Upper Iowa University" + }, + { + "label": "Upstate Medical University" + }, + { + "label": "Urban College of Boston" + }, + { + "label": "Urbana University" + }, + { + "label": "Urshan Graduate School of Theology" + }, + { + "label": "Ursinus College" + }, + { + "label": "Ursuline College" + }, + { + "label": "Uta Mesivta of Kiryas Joel" + }, + { + "label": "Utah State University" + }, + { + "label": "Utah Valley University" + }, + { + "label": "Utica College" + }, + { + "label": "Utica School of Commerce" + }, + { + "label": "Valdosta State University" + }, + { + "label": "Valencia College" + }, + { + "label": "Valley City State University" + }, + { + "label": "Valley College-Beckley" + }, + { + "label": "Valparaiso University" + }, + { + "label": "Vance-Granville Community College" + }, + { + "label": "Vanderbilt University" + }, + { + "label": "VanderCook College of Music" + }, + { + "label": "Vanguard University of Southern California" + }, + { + "label": "Vassar College" + }, + { + "label": "Vatterott College-Appling Farms" + }, + { + "label": "Vatterott College-Berkeley" + }, + { + "label": "Vatterott College-Cleveland" + }, + { + "label": "Vatterott College-Des Moines" + }, + { + "label": "Vatterott College-Dividend" + }, + { + "label": "Vatterott College-ex'treme Institute by Nelly-St Louis" + }, + { + "label": "Vatterott College-Joplin" + }, + { + "label": "Vatterott College-Kansas City" + }, + { + "label": "Vatterott College-Oklahoma City" + }, + { + "label": "Vatterott College-Quincy" + }, + { + "label": "Vatterott College-Spring Valley" + }, + { + "label": "Vatterott College-Springfield" + }, + { + "label": "Vatterott College-St Charles" + }, + { + "label": "Vatterott College-St Joseph" + }, + { + "label": "Vatterott College-Sunset Hills" + }, + { + "label": "Vatterott College-Tulsa" + }, + { + "label": "Vatterott College-Wichita" + }, + { + "label": "Vaughn College of Aeronautics and Technology" + }, + { + "label": "Ventura College" + }, + { + "label": "Vermilion Community College" + }, + { + "label": "Vermont College of Fine Arts" + }, + { + "label": "Vermont Law School" + }, + { + "label": "Vermont Technical College" + }, + { + "label": "Vernon College" + }, + { + "label": "Vet Tech Institute" + }, + { + "label": "Vet Tech Institute of Houston" + }, + { + "label": "Victor Valley College" + }, + { + "label": "Victoria College" + }, + { + "label": "Villa Maria College" + }, + { + "label": "Villanova University" + }, + { + "label": "Vincennes University" + }, + { + "label": "Virginia Baptist College" + }, + { + "label": "Virginia College-Augusta" + }, + { + "label": "Virginia College-Austin" + }, + { + "label": "Virginia College-Baton Rouge" + }, + { + "label": "Virginia College-Biloxi" + }, + { + "label": "Virginia College-Birmingham" + }, + { + "label": "Virginia College-Charleston" + }, + { + "label": "Virginia College-Columbia" + }, + { + "label": "Virginia College-Columbus" + }, + { + "label": "Virginia College-Florence" + }, + { + "label": "Virginia College-Greenville" + }, + { + "label": "Virginia College-Huntsville" + }, + { + "label": "Virginia College-Jackson" + }, + { + "label": "Virginia College-Jacksonville" + }, + { + "label": "Virginia College-Knoxville" + }, + { + "label": "Virginia College-Macon" + }, + { + "label": "Virginia College-Mobile" + }, + { + "label": "Virginia College-Montgomery" + }, + { + "label": "Virginia College-Pensacola" + }, + { + "label": "Virginia College-Richmond" + }, + { + "label": "Virginia College-Savannah" + }, + { + "label": "Virginia College-School of Business and Health-Chattanooga" + }, + { + "label": "Virginia College-Shreveport Bossier City" + }, + { + "label": "Virginia College-Spartanburg" + }, + { + "label": "Virginia College-Tulsa" + }, + { + "label": "Virginia Commonwealth University" + }, + { + "label": "Virginia Highlands Community College" + }, + { + "label": "Virginia Marti College of Art and Design" + }, + { + "label": "Virginia Military Institute" + }, + { + "label": "Virginia Polytechnic Institute and State University" + }, + { + "label": "Virginia State University" + }, + { + "label": "Virginia Tech Carilion School of Medicine" + }, + { + "label": "Virginia Union University" + }, + { + "label": "Virginia University of Lynchburg" + }, + { + "label": "Virginia Wesleyan College" + }, + { + "label": "Virginia Western Community College" + }, + { + "label": "Visible Music College" + }, + { + "label": "Vista College" + }, + { + "label": "Vista College-Online" + }, + { + "label": "Viterbo University" + }, + { + "label": "Volunteer State Community College" + }, + { + "label": "Voorhees College" + }, + { + "label": "Wabash College" + }, + { + "label": "Wabash Valley College" + }, + { + "label": "Wade College" + }, + { + "label": "Wagner College" + }, + { + "label": "Wake Forest University" + }, + { + "label": "Wake Technical Community College" + }, + { + "label": "Walden University" + }, + { + "label": "Waldorf College" + }, + { + "label": "Walla Walla Community College" + }, + { + "label": "Walla Walla University" + }, + { + "label": "Walsh College of Accountancy and Business Administration" + }, + { + "label": "Walsh University" + }, + { + "label": "Walters State Community College" + }, + { + "label": "Warner Pacific College" + }, + { + "label": "Warner Pacific College Adult Degree Program" + }, + { + "label": "Warner University" + }, + { + "label": "Warren County Community College" + }, + { + "label": "Warren Wilson College" + }, + { + "label": "Wartburg College" + }, + { + "label": "Wartburg Theological Seminary" + }, + { + "label": "Washburn University" + }, + { + "label": "Washington & Jefferson College" + }, + { + "label": "Washington Adventist University" + }, + { + "label": "Washington and Lee University" + }, + { + "label": "Washington College" + }, + { + "label": "Washington County Community College" + }, + { + "label": "Washington State Community College" + }, + { + "label": "Washington State University" + }, + { + "label": "Washington University in St Louis" + }, + { + "label": "Washtenaw Community College" + }, + { + "label": "Watkins College of Art Design & Film" + }, + { + "label": "Waubonsee Community College" + }, + { + "label": "Waukesha County Technical College" + }, + { + "label": "Wayland Baptist University" + }, + { + "label": "Wayne Community College" + }, + { + "label": "Wayne County Community College District" + }, + { + "label": "Wayne State College" + }, + { + "label": "Wayne State University" + }, + { + "label": "Waynesburg University" + }, + { + "label": "Weatherford College" + }, + { + "label": "Webb Institute" + }, + { + "label": "Webber International University" + }, + { + "label": "Weber State University" + }, + { + "label": "Webster University" + }, + { + "label": "Weill Cornell Medicine" + }, + { + "label": "Welch College" + }, + { + "label": "Wellesley College" + }, + { + "label": "Wells College" + }, + { + "label": "WellSpring School of Allied Health-Kansas City" + }, + { + "label": "Wenatchee Valley College" + }, + { + "label": "Wentworth Institute of Technology" + }, + { + "label": "Wentworth Military Academy and College" + }, + { + "label": "Wesley Biblical Seminary" + }, + { + "label": "Wesley College" + }, + { + "label": "Wesley Theological Seminary" + }, + { + "label": "Wesleyan College" + }, + { + "label": "Wesleyan University" + }, + { + "label": "West Chester University of Pennsylvania" + }, + { + "label": "West Coast Ultrasound Institute" + }, + { + "label": "West Coast University-Dallas" + }, + { + "label": "West Coast University-Los Angeles" + }, + { + "label": "West Coast University-Ontario" + }, + { + "label": "West Coast University-Orange County" + }, + { + "label": "West Georgia Technical College" + }, + { + "label": "West Hills College-Coalinga" + }, + { + "label": "West Hills College-Lemoore" + }, + { + "label": "West Kentucky Community and Technical College" + }, + { + "label": "West Liberty University" + }, + { + "label": "West Los Angeles College" + }, + { + "label": "West Shore Community College" + }, + { + "label": "West Tennessee Business College" + }, + { + "label": "West Texas A & M University" + }, + { + "label": "West Valley College" + }, + { + "label": "West Virginia Business College-Wheeling" + }, + { + "label": "West Virginia Junior College-Bridgeport" + }, + { + "label": "West Virginia Junior College-Charleston" + }, + { + "label": "West Virginia Junior College-Morgantown" + }, + { + "label": "West Virginia Northern Community College" + }, + { + "label": "West Virginia School of Osteopathic Medicine" + }, + { + "label": "West Virginia State University" + }, + { + "label": "West Virginia University" + }, + { + "label": "West Virginia University at Parkersburg" + }, + { + "label": "West Virginia University Institute of Technology" + }, + { + "label": "West Virginia Wesleyan College" + }, + { + "label": "Western Carolina University" + }, + { + "label": "Western Connecticut State University" + }, + { + "label": "Western Dakota Technical Institute" + }, + { + "label": "Western Governors University" + }, + { + "label": "Western Illinois University" + }, + { + "label": "Western International University" + }, + { + "label": "Western Iowa Tech Community College" + }, + { + "label": "Western Kentucky University" + }, + { + "label": "Western Michigan University" + }, + { + "label": "Western Michigan University-Thomas M. Cooley Law School" + }, + { + "label": "Western Nebraska Community College" + }, + { + "label": "Western Nevada College" + }, + { + "label": "Western New England University" + }, + { + "label": "Western New Mexico University" + }, + { + "label": "Western Oklahoma State College" + }, + { + "label": "Western Oregon University" + }, + { + "label": "Western Piedmont Community College" + }, + { + "label": "Western Seminary" + }, + { + "label": "Western State College of Law at Argosy University" + }, + { + "label": "Western State Colorado University" + }, + { + "label": "Western Technical College-El Paso" + }, + { + "label": "Western Technical College-El Paso" + }, + { + "label": "Western Technical College-La Crosse" + }, + { + "label": "Western Texas College" + }, + { + "label": "Western Theological Seminary" + }, + { + "label": "Western University of Health Sciences" + }, + { + "label": "Western Washington University" + }, + { + "label": "Western Wyoming Community College" + }, + { + "label": "Westfield State University" + }, + { + "label": "Westminster College-Fulton" + }, + { + "label": "Westminster College-New Wilmington" + }, + { + "label": "Westminster College-Salt Lake City" + }, + { + "label": "Westminster Theological Seminary" + }, + { + "label": "Westminster Theological Seminary in California" + }, + { + "label": "Westmont College" + }, + { + "label": "Westmoreland County Community College" + }, + { + "label": "Westwood College-Anaheim" + }, + { + "label": "Westwood College-Annandale" + }, + { + "label": "Westwood College-Arlington Ballston" + }, + { + "label": "Westwood College-Atlanta Midtown" + }, + { + "label": "Westwood College-Chicago Loop" + }, + { + "label": "Westwood College-Denver North" + }, + { + "label": "Westwood College-Denver South" + }, + { + "label": "Westwood College-Dupage" + }, + { + "label": "Westwood College-Inland Empire" + }, + { + "label": "Westwood College-Los Angeles" + }, + { + "label": "Westwood College-Northlake" + }, + { + "label": "Westwood College-O'Hare Airport" + }, + { + "label": "Westwood College-River Oaks" + }, + { + "label": "Westwood College-South Bay" + }, + { + "label": "Wharton County Junior College" + }, + { + "label": "Whatcom Community College" + }, + { + "label": "Wheaton College-Norton" + }, + { + "label": "Wheaton College-Wheaton" + }, + { + "label": "Wheeling Jesuit University" + }, + { + "label": "Wheelock College" + }, + { + "label": "White Earth Tribal and Community College" + }, + { + "label": "White Mountains Community College" + }, + { + "label": "Whitman College" + }, + { + "label": "Whittier College" + }, + { + "label": "Whitworth University" + }, + { + "label": "Whitworth University-Adult Degree Programs" + }, + { + "label": "Wichita Area Technical College" + }, + { + "label": "Wichita State University" + }, + { + "label": "Wichita Technical Institute" + }, + { + "label": "Widener University-Delaware Campus" + }, + { + "label": "Widener University-Harrisburg Campus" + }, + { + "label": "Widener University-Main Campus" + }, + { + "label": "Wilberforce University" + }, + { + "label": "Wiley College" + }, + { + "label": "Wilkes Community College" + }, + { + "label": "Wilkes University" + }, + { + "label": "Willamette University" + }, + { + "label": "William Carey University" + }, + { + "label": "William James College" + }, + { + "label": "William Jessup University" + }, + { + "label": "William Jewell College" + }, + { + "label": "William Mitchell College of Law" + }, + { + "label": "William Moore College of Technology" + }, + { + "label": "William Paterson University of New Jersey" + }, + { + "label": "William Peace University" + }, + { + "label": "William Penn University" + }, + { + "label": "William Rainey Harper College" + }, + { + "label": "William Woods University" + }, + { + "label": "Williams Baptist College" + }, + { + "label": "Williams College" + }, + { + "label": "Williamsburg Technical College" + }, + { + "label": "Williamson Christian College" + }, + { + "label": "Williston State College" + }, + { + "label": "Wilmington College" + }, + { + "label": "Wilmington University" + }, + { + "label": "Wilson College" + }, + { + "label": "Wilson Community College" + }, + { + "label": "Windward Community College" + }, + { + "label": "Winebrenner Theological Seminary" + }, + { + "label": "Wingate University" + }, + { + "label": "Winona State University" + }, + { + "label": "Winston-Salem State University" + }, + { + "label": "Winthrop University" + }, + { + "label": "Wiregrass Georgia Technical College" + }, + { + "label": "Wisconsin Indianhead Technical College" + }, + { + "label": "Wisconsin Lutheran College" + }, + { + "label": "Wisconsin School of Professional Psychology" + }, + { + "label": "Wittenberg University" + }, + { + "label": "Wofford College" + }, + { + "label": "Wolford College" + }, + { + "label": "Won Institute of Graduate Studies" + }, + { + "label": "Wood Tobe-Coburn School" + }, + { + "label": "Woodbury University" + }, + { + "label": "Woodland Community College" + }, + { + "label": "Worcester Polytechnic Institute" + }, + { + "label": "Worcester State University" + }, + { + "label": "World Medicine Institute" + }, + { + "label": "World Mission University" + }, + { + "label": "Worsham College of Mortuary Science" + }, + { + "label": "Wor-Wic Community College" + }, + { + "label": "Wright Career College" + }, + { + "label": "Wright State University-Lake Campus" + }, + { + "label": "Wright State University-Main Campus" + }, + { + "label": "Wyo Tech-Blairsville" + }, + { + "label": "Wyotech-Daytona" + }, + { + "label": "Wyotech-Fremont" + }, + { + "label": "Wyotech-Laramie" + }, + { + "label": "Wyotech-Long Beach" + }, + { + "label": "Wytheville Community College" + }, + { + "label": "Xavier University" + }, + { + "label": "Xavier University of Louisiana" + }, + { + "label": "Yakima Valley Community College" + }, + { + "label": "Yale University" + }, + { + "label": "Yavapai College" + }, + { + "label": "Yeshiva and Kollel Harbotzas Torah" + }, + { + "label": "Yeshiva College of the Nations Capital" + }, + { + "label": "Yeshiva Derech Chaim" + }, + { + "label": "Yeshiva D'monsey Rabbinical College" + }, + { + "label": "Yeshiva Gedolah Imrei Yosef D'spinka" + }, + { + "label": "Yeshiva Gedolah Kesser Torah" + }, + { + "label": "Yeshiva Gedolah of Greater Detroit" + }, + { + "label": "Yeshiva Gedolah Zichron Leyma" + }, + { + "label": "Yeshiva Karlin Stolin" + }, + { + "label": "Yeshiva of Far Rockaway Derech Ayson Rabbinical Seminary" + }, + { + "label": "Yeshiva of Machzikai Hadas" + }, + { + "label": "Yeshiva of Nitra Rabbinical College" + }, + { + "label": "Yeshiva of the Telshe Alumni" + }, + { + "label": "Yeshiva Ohr Elchonon Chabad West Coast Talmudical Seminary" + }, + { + "label": "Yeshiva Shaar Hatorah" + }, + { + "label": "Yeshiva Shaarei Torah of Rockland" + }, + { + "label": "Yeshiva Toras Chaim" + }, + { + "label": "Yeshiva Toras Chaim Talmudical Seminary" + }, + { + "label": "Yeshiva University" + }, + { + "label": "Yeshiva Yesodei Hatorah" + }, + { + "label": "Yeshivas Be'er Yitzchok" + }, + { + "label": "Yeshivas Novominsk" + }, + { + "label": "Yeshivat Mikdash Melech" + }, + { + "label": "Yeshivath Beth Moshe" + }, + { + "label": "Yeshivath Viznitz" + }, + { + "label": "Yeshivath Zichron Moshe" + }, + { + "label": "Yo San University of Traditional Chinese Medicine" + }, + { + "label": "York College" + }, + { + "label": "York College Pennsylvania" + }, + { + "label": "York County Community College" + }, + { + "label": "York Technical College" + }, + { + "label": "Yorktowne Business Institute" + }, + { + "label": "Young Harris College" + }, + { + "label": "Youngstown State University" + }, + { + "label": "YTI Career Institute-Altoona" + }, + { + "label": "YTI Career Institute-York" + }, + { + "label": "Yuba College" + }, + { + "label": "Zane State College" + }, + { + "label": "Ames Laboratory" + }, + { + "label": "Argonne National Laboratory", + "abbreviation": "ANL" + }, + { + "label": "Brookhaven National Laboratory", + "abbreviation": "BNL" + }, + { + "label": "Fermi National Accelerator Laboratory", + "abbreviation": "FERMILAB" + }, + { + "label": "Oak Ridge National Laboratory", + "abbreviation": "ORNL" + }, + { + "label": "Lawrence Berkeley National Laboratory", + "abbreviation": "LBNL" + }, + { + "label": "Pacific Northwest National Laboratory", + "abbreviation": "PNNL" + }, + { + "label": "Princeton Plasma Physics Laboratory", + "abbreviation": "PPPL" + }, + { + "label": "SLAC National Accelerator Laboratory", + "abbreviation": "SLAC" + }, + { + "label": "Idaho National Laboratory", + "abbreviation": "INL" + }, + { + "label": "National Energy Technology Laboratory", + "abbreviation": "NETL" + }, + { + "label": "National Renewable Energy Laboratory", + "abbreviation": "NREL" + }, + { + "label": "Savannah River National Laboratory", + "abbreviation": "SRNL" + }, + { + "label": "Lawrence Livermore National Laboratory", + "abbreviation": "LLNL" + }, + { + "label": "Los Alamos National Laboratory", + "abbreviation": "LANL" + }, + { + "label": "Sandia National Laboratory", + "abbreviation": "SNL" + }, + { + "label": "Cold Spring Harbor Laboratory", + "abbreviation": "CSHL" + }, + { + "label": "Joint Genome Institute", + "abbreviation": "JGI" + } +] diff --git a/vite-app/src/apps/Auth2/resources/data/providers.json b/vite-app/src/apps/Auth2/resources/data/providers.json new file mode 100644 index 000000000..6db6261c1 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/providers.json @@ -0,0 +1,26 @@ +[ + { + "id": "Google", + "label": "Google", + "logoutUrl": "https://accounts.google.com/Logout", + "priority": 1, + "confirmSignin": false, + "description": "Any Google account may be used to access KBase.\n" + }, + { + "id": "OrcID", + "label": "ORCID", + "logoutUrl": "https://www.orcid.org/signout", + "priority": 1, + "confirmSignin": true, + "description": "Use your ORCiD account to access KBase.\n" + }, + { + "id": "Globus", + "label": "Globus", + "logoutUrl": "https://app.globus.org/logout", + "priority": 2, + "confirmSignin": true, + "description": "Use your Globus ID to access KBase.\n" + } +] diff --git a/vite-app/src/apps/Auth2/resources/data/providers.yaml b/vite-app/src/apps/Auth2/resources/data/providers.yaml new file mode 100644 index 000000000..4ffeed270 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/providers.yaml @@ -0,0 +1,23 @@ +# Auth Providers +--- +- id: Google + label: Google + logoutUrl: https://accounts.google.com/Logout + priority: 1 + confirmSignin: false + description: > + Any Google account may be used to access KBase. +- id: OrcID + label: ORCID + logoutUrl: https://www.orcid.org/signout + priority: 1 + confirmSignin: true + description: > + Use your ORCiD account to access KBase. +- id: Globus + label: Globus + logoutUrl: https://app.globus.org/logout + priority: 2 + confirmSignin: true + description: | + Use your Globus ID to access KBase. diff --git a/vite-app/src/apps/Auth2/resources/data/referralSources.json b/vite-app/src/apps/Auth2/resources/data/referralSources.json new file mode 100644 index 000000000..94c2a7863 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/data/referralSources.json @@ -0,0 +1,47 @@ +[ + { + "label": "Journal Publication", + "value": "journal-publication" + }, + { + "label": "Conference Presentation", + "value": "conference-presentation" + }, + { + "label": "Workshop/Webinar", + "value": "workshop-webinar" + }, + { + "label": "Colleague", + "value": "colleague" + }, + { + "label": "Course/Instructor", + "value": "course" + }, + { + "label": "Newsletter/Email", + "value": "newsletter-email" + }, + { + "label": "YouTube", + "value": "youtube" + }, + { + "label": "Twitter (X)", + "value": "twitter" + }, + { + "label": "Search Engine", + "value": "search-engine" + }, + { + "label": "Online Advertisement", + "value": "online-ad" + }, + { + "label": "Other...", + "value": "other", + "customText": true + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/avatarOptions.json b/vite-app/src/apps/Auth2/resources/dataSources/avatarOptions.json new file mode 100644 index 000000000..11ef5d179 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/avatarOptions.json @@ -0,0 +1,10 @@ +[ + { + "value": "gravatar", + "label": "Gravatar - Use your Gravatar image otherwise random generator selected below" + }, + { + "value": "silhouette", + "label": "silhouette - simple, anonymous, featureless, silhouette" + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/countries.json b/vite-app/src/apps/Auth2/resources/dataSources/countries.json new file mode 100644 index 000000000..83ebe7b5e --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/countries.json @@ -0,0 +1,308 @@ +[ + { "value": "United States", "label": "United States" }, + { "value": "Afghanistan", "label": "Afghanistan" }, + { "value": "Aland Islands", "label": "Aland Islands" }, + { "value": "Albania", "label": "Albania" }, + { "value": "Algeria", "label": "Algeria" }, + { "value": "American Samoa", "label": "American Samoa" }, + { "value": "Andorra", "label": "Andorra" }, + { "value": "Angola", "label": "Angola" }, + { "value": "Anguilla", "label": "Anguilla" }, + { "value": "Antarctica", "label": "Antarctica" }, + { "value": "Antigua And Barbuda", "label": "Antigua And Barbuda" }, + { "value": "Argentina", "label": "Argentina" }, + { "value": "Armenia", "label": "Armenia" }, + { "value": "Aruba", "label": "Aruba" }, + { "value": "Australia", "label": "Australia" }, + { "value": "Austria", "label": "Austria" }, + { "value": "Azerbaijan", "label": "Azerbaijan" }, + { "value": "Bahamas", "label": "Bahamas" }, + { "value": "Bahrain", "label": "Bahrain" }, + { "value": "Bangladesh", "label": "Bangladesh" }, + { "value": "Barbados", "label": "Barbados" }, + { "value": "Belarus", "label": "Belarus" }, + { "value": "Belgium", "label": "Belgium" }, + { "value": "Belize", "label": "Belize" }, + { "value": "Benin", "label": "Benin" }, + { "value": "Bermuda", "label": "Bermuda" }, + { "value": "Bhutan", "label": "Bhutan" }, + { "value": "Bolivia", "label": "Bolivia" }, + { "value": "Bosnia and Herzegovina", "label": "Bosnia and Herzegovina" }, + { "value": "Botswana", "label": "Botswana" }, + { "value": "Bouvet Island", "label": "Bouvet Island" }, + { "value": "Brazil", "label": "Brazil" }, + { + "value": "British Indian Ocean Territory", + "label": "British Indian Ocean Territory" + }, + { "value": "Brunei Darussalam", "label": "Brunei Darussalam" }, + { "value": "Bulgaria", "label": "Bulgaria" }, + { "value": "Burkina Faso", "label": "Burkina Faso" }, + { "value": "Burundi", "label": "Burundi" }, + { "value": "Cambodia", "label": "Cambodia" }, + { "value": "Cameroon", "label": "Cameroon" }, + { "value": "Canada", "label": "Canada" }, + { "value": "Cape Verde", "label": "Cape Verde" }, + { "value": "Cayman Islands", "label": "Cayman Islands" }, + { + "value": "Central African Republic", + "label": "Central African Republic" + }, + { "value": "Chad", "label": "Chad" }, + { "value": "Chile", "label": "Chile" }, + { "value": "China", "label": "China" }, + { "value": "Christmas Island", "label": "Christmas Island" }, + { "value": "Cocos (Keeling) Islands", "label": "Cocos (Keeling) Islands" }, + { "value": "Colombia", "label": "Colombia" }, + { "value": "Comoros", "label": "Comoros" }, + { "value": "Congo", "label": "Congo" }, + { + "value": "Congo, the Democratic Republic of the", + "label": "Congo, the Democratic Republic of the" + }, + { "value": "Cook Islands", "label": "Cook Islands" }, + { "value": "Costa Rica", "label": "Costa Rica" }, + { "value": "Cote d'Ivoire", "label": "Cote d'Ivoire" }, + { "value": "Croatia", "label": "Croatia" }, + { "value": "Cuba", "label": "Cuba" }, + { "value": "Curacao", "label": "Curacao" }, + { "value": "Cyprus", "label": "Cyprus" }, + { "value": "Czech Republic", "label": "Czech Republic" }, + { "value": "Denmark", "label": "Denmark" }, + { "value": "Djibouti", "label": "Djibouti" }, + { "value": "Dominica", "label": "Dominica" }, + { "value": "Dominican Republic", "label": "Dominican Republic" }, + { "value": "Ecuador", "label": "Ecuador" }, + { "value": "Egypt", "label": "Egypt" }, + { "value": "El Salvador", "label": "El Salvador" }, + { "value": "Equatorial Guinea", "label": "Equatorial Guinea" }, + { "value": "Eritrea", "label": "Eritrea" }, + { "value": "Estonia", "label": "Estonia" }, + { "value": "Ethiopia", "label": "Ethiopia" }, + { + "value": "Falkland Islands (Malvinas)", + "label": "Falkland Islands (Malvinas)" + }, + { "value": "Faroe Islands", "label": "Faroe Islands" }, + { "value": "Fiji", "label": "Fiji" }, + { "value": "Finland", "label": "Finland" }, + { "value": "France", "label": "France" }, + { "value": "French Guiana", "label": "French Guiana" }, + { "value": "French Polynesia", "label": "French Polynesia" }, + { + "value": "French Southern Territories", + "label": "French Southern Territories" + }, + { "value": "Gabon", "label": "Gabon" }, + { "value": "Gambia", "label": "Gambia" }, + { "value": "Georgia", "label": "Georgia" }, + { "value": "Germany", "label": "Germany" }, + { "value": "Ghana", "label": "Ghana" }, + { "value": "Gibraltar", "label": "Gibraltar" }, + { "value": "Greece", "label": "Greece" }, + { "value": "Greenland", "label": "Greenland" }, + { "value": "Grenada", "label": "Grenada" }, + { "value": "Guadeloupe", "label": "Guadeloupe" }, + { "value": "Guam", "label": "Guam" }, + { "value": "Guatemala", "label": "Guatemala" }, + { "value": "Guernsey", "label": "Guernsey" }, + { "value": "Guinea", "label": "Guinea" }, + { "value": "Guinea-Bissau", "label": "Guinea-Bissau" }, + { "value": "Guyana", "label": "Guyana" }, + { "value": "Haiti", "label": "Haiti" }, + { + "value": "Heard and McDonald Islands", + "label": "Heard and McDonald Islands" + }, + { + "value": "Holy See (Vatican City State)", + "label": "Holy See (Vatican City State)" + }, + { "value": "Honduras", "label": "Honduras" }, + { "value": "Hong Kong", "label": "Hong Kong" }, + { "value": "Hungary", "label": "Hungary" }, + { "value": "Iceland", "label": "Iceland" }, + { "value": "India", "label": "India" }, + { "value": "Indonesia", "label": "Indonesia" }, + { + "value": "Iran, Islamic Republic of", + "label": "Iran, Islamic Republic of" + }, + { "value": "Iraq", "label": "Iraq" }, + { "value": "Ireland", "label": "Ireland" }, + { "value": "Isle of Man", "label": "Isle of Man" }, + { "value": "Israel", "label": "Israel" }, + { "value": "Italy", "label": "Italy" }, + { "value": "Jamaica", "label": "Jamaica" }, + { "value": "Japan", "label": "Japan" }, + { "value": "Jersey", "label": "Jersey" }, + { "value": "Jordan", "label": "Jordan" }, + { "value": "Kazakhstan", "label": "Kazakhstan" }, + { "value": "Kenya", "label": "Kenya" }, + { "value": "Kiribati", "label": "Kiribati" }, + { + "value": "Korea, Democratic People's Republic of", + "label": "Korea, Democratic People's Republic of" + }, + { "value": "Korea, Republic of", "label": "Korea, Republic of" }, + { "value": "Kuwait", "label": "Kuwait" }, + { "value": "Kyrgyzstan", "label": "Kyrgyzstan" }, + { + "value": "Lao People's Democratic Republic", + "label": "Lao People's Democratic Republic" + }, + { "value": "Latvia", "label": "Latvia" }, + { "value": "Lebanon", "label": "Lebanon" }, + { "value": "Lesotho", "label": "Lesotho" }, + { "value": "Liberia", "label": "Liberia" }, + { "value": "Libyan Arab Jamahiriya", "label": "Libyan Arab Jamahiriya" }, + { "value": "Liechtenstein", "label": "Liechtenstein" }, + { "value": "Lithuania", "label": "Lithuania" }, + { "value": "Luxembourg", "label": "Luxembourg" }, + { "value": "Macao", "label": "Macao" }, + { + "value": "Macedonia, The Former Yugoslav Republic Of", + "label": "Macedonia, The Former Yugoslav Republic Of" + }, + { "value": "Madagascar", "label": "Madagascar" }, + { "value": "Malawi", "label": "Malawi" }, + { "value": "Malaysia", "label": "Malaysia" }, + { "value": "Maldives", "label": "Maldives" }, + { "value": "Mali", "label": "Mali" }, + { "value": "Malta", "label": "Malta" }, + { "value": "Marshall Islands", "label": "Marshall Islands" }, + { "value": "Martinique", "label": "Martinique" }, + { "value": "Mauritania", "label": "Mauritania" }, + { "value": "Mauritius", "label": "Mauritius" }, + { "value": "Mayotte", "label": "Mayotte" }, + { "value": "Mexico", "label": "Mexico" }, + { + "value": "Micronesia, Federated States of", + "label": "Micronesia, Federated States of" + }, + { "value": "Moldova, Republic of", "label": "Moldova, Republic of" }, + { "value": "Monaco", "label": "Monaco" }, + { "value": "Mongolia", "label": "Mongolia" }, + { "value": "Montenegro", "label": "Montenegro" }, + { "value": "Montserrat", "label": "Montserrat" }, + { "value": "Morocco", "label": "Morocco" }, + { "value": "Mozambique", "label": "Mozambique" }, + { "value": "Myanmar", "label": "Myanmar" }, + { "value": "Namibia", "label": "Namibia" }, + { "value": "Nauru", "label": "Nauru" }, + { "value": "Nepal", "label": "Nepal" }, + { "value": "Netherlands", "label": "Netherlands" }, + { "value": "New Caledonia", "label": "New Caledonia" }, + { "value": "New Zealand", "label": "New Zealand" }, + { "value": "Nicaragua", "label": "Nicaragua" }, + { "value": "Niger", "label": "Niger" }, + { "value": "Nigeria", "label": "Nigeria" }, + { "value": "Niue", "label": "Niue" }, + { "value": "Norfolk Island", "label": "Norfolk Island" }, + { + "value": "Northern Mariana Islands", + "label": "Northern Mariana Islands" + }, + { "value": "Norway", "label": "Norway" }, + { "value": "Oman", "label": "Oman" }, + { "value": "Pakistan", "label": "Pakistan" }, + { "value": "Palau", "label": "Palau" }, + { + "value": "Palestinian Territory, Occupied", + "label": "Palestinian Territory, Occupied" + }, + { "value": "Panama", "label": "Panama" }, + { "value": "Papua New Guinea", "label": "Papua New Guinea" }, + { "value": "Paraguay", "label": "Paraguay" }, + { "value": "Peru", "label": "Peru" }, + { "value": "Philippines", "label": "Philippines" }, + { "value": "Pitcairn", "label": "Pitcairn" }, + { "value": "Poland", "label": "Poland" }, + { "value": "Portugal", "label": "Portugal" }, + { "value": "Puerto Rico", "label": "Puerto Rico" }, + { "value": "Qatar", "label": "Qatar" }, + { "value": "Reunion", "label": "Reunion" }, + { "value": "Romania", "label": "Romania" }, + { "value": "Russian Federation", "label": "Russian Federation" }, + { "value": "Rwanda", "label": "Rwanda" }, + { "value": "Saint Barthelemy", "label": "Saint Barthelemy" }, + { "value": "Saint Helena", "label": "Saint Helena" }, + { "value": "Saint Kitts and Nevis", "label": "Saint Kitts and Nevis" }, + { "value": "Saint Lucia", "label": "Saint Lucia" }, + { + "value": "Saint Pierre and Miquelon", + "label": "Saint Pierre and Miquelon" + }, + { + "value": "Saint Vincent and the Grenadines", + "label": "Saint Vincent and the Grenadines" + }, + { "value": "Samoa", "label": "Samoa" }, + { "value": "San Marino", "label": "San Marino" }, + { "value": "Sao Tome and Principe", "label": "Sao Tome and Principe" }, + { "value": "Saudi Arabia", "label": "Saudi Arabia" }, + { "value": "Senegal", "label": "Senegal" }, + { "value": "Serbia", "label": "Serbia" }, + { "value": "Seychelles", "label": "Seychelles" }, + { "value": "Sierra Leone", "label": "Sierra Leone" }, + { "value": "Singapore", "label": "Singapore" }, + { "value": "Sint Maarten", "label": "Sint Maarten" }, + { "value": "Slovakia", "label": "Slovakia" }, + { "value": "Slovenia", "label": "Slovenia" }, + { "value": "Solomon Islands", "label": "Solomon Islands" }, + { "value": "Somalia", "label": "Somalia" }, + { "value": "South Africa", "label": "South Africa" }, + { + "value": "South Georgia and the South Sandwich Islands", + "label": "South Georgia and the South Sandwich Islands" + }, + { "value": "Spain", "label": "Spain" }, + { "value": "Sri Lanka", "label": "Sri Lanka" }, + { "value": "Sudan", "label": "Sudan" }, + { "value": "Suriname", "label": "Suriname" }, + { "value": "Svalbard and Jan Mayen", "label": "Svalbard and Jan Mayen" }, + { "value": "Swaziland", "label": "Swaziland" }, + { "value": "Sweden", "label": "Sweden" }, + { "value": "Switzerland", "label": "Switzerland" }, + { "value": "Syrian Arab Republic", "label": "Syrian Arab Republic" }, + { "value": "Taiwan", "label": "Taiwan" }, + { "value": "Tajikistan", "label": "Tajikistan" }, + { + "value": "Tanzania, United Republic of", + "label": "Tanzania, United Republic of" + }, + { "value": "Thailand", "label": "Thailand" }, + { "value": "Timor-Leste", "label": "Timor-Leste" }, + { "value": "Togo", "label": "Togo" }, + { "value": "Tokelau", "label": "Tokelau" }, + { "value": "Tonga", "label": "Tonga" }, + { "value": "Trinidad and Tobago", "label": "Trinidad and Tobago" }, + { "value": "Tunisia", "label": "Tunisia" }, + { "value": "Turkey", "label": "Turkey" }, + { "value": "Turkmenistan", "label": "Turkmenistan" }, + { + "value": "Turks and Caicos Islands", + "label": "Turks and Caicos Islands" + }, + { "value": "Tuvalu", "label": "Tuvalu" }, + { "value": "Uganda", "label": "Uganda" }, + { "value": "Ukraine", "label": "Ukraine" }, + { "value": "United Arab Emirates", "label": "United Arab Emirates" }, + { "value": "United Kingdom", "label": "United Kingdom" }, + { + "value": "United States Minor Outlying Islands", + "label": "United States Minor Outlying Islands" + }, + { "value": "Uruguay", "label": "Uruguay" }, + { "value": "Uzbekistan", "label": "Uzbekistan" }, + { "value": "Vanuatu", "label": "Vanuatu" }, + { "value": "Venezuela", "label": "Venezuela" }, + { "value": "Viet Nam", "label": "Viet Nam" }, + { "value": "Virgin Islands, British", "label": "Virgin Islands, British" }, + { "value": "Virgin Islands, U.S.", "label": "Virgin Islands, U.S." }, + { "value": "Wallis and Futuna", "label": "Wallis and Futuna" }, + { "value": "Western Sahara", "label": "Western Sahara" }, + { "value": "Yemen", "label": "Yemen" }, + { "value": "Zambia", "label": "Zambia" }, + { "value": "Zimbabwe", "label": "Zimbabwe" } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/fundingSources.json b/vite-app/src/apps/Auth2/resources/dataSources/fundingSources.json new file mode 100644 index 000000000..ebc9c5009 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/fundingSources.json @@ -0,0 +1,151 @@ +[ + { + "value": "DOE Office of Energy Efficiency and Renewable Energy (EERE)", + "label": "DOE Office of Energy Efficiency and Renewable Energy (EERE)" + }, + { + "value": "DOE Office of Environmental Management (EM)", + "label": "DOE Office of Environmental Management (EM)" + }, + { + "value": "DOE Office of Fossil Energy (FE)", + "label": "DOE Office of Fossil Energy (FE)" + }, + { + "value": "DOE Office Nuclear Energy (NE)", + "label": "DOE Office Nuclear Energy (NE)" + }, + { + "value": "DOE National Nuclear Security Administration (NNSA)", + "label": "DOE National Nuclear Security Administration (NNSA)" + }, + { + "value": "DOE Small Business Innovation Research/Small Business Technology Transfer (SBIR/STTR)", + "label": "DOE Small Business Innovation Research/Small Business Technology Transfer (SBIR/STTR)" + }, + { + "value": "DOE Office of Science Advenced Scientific Computing Research (ASCR)", + "label": "DOE Office of Science Advenced Scientific Computing Research (ASCR)" + }, + { + "value": "DOE Office of Science Basic Energy Sciences (BES)", + "label": "DOE Office of Science Basic Energy Sciences (BES)" + }, + { + "value": "DOE Office of Science BES Energy Frontier Science Center (EFRC)", + "label": "DOE Office of Science BES Energy Frontier Science Center (EFRC)" + }, + { + "value": "DOE Office of Science Biological and Environmental Research (BER)", + "label": "DOE Office of Science Biological and Environmental Research (BER)" + }, + { + "value": "DOE Office of Science Fusion Energy Sciences (FES)", + "label": "DOE Office of Science Fusion Energy Sciences (FES)" + }, + { + "value": "DOE Office of Science High Energy Physics (HEP)", + "label": "DOE Office of Science High Energy Physics (HEP)" + }, + { + "value": "DOE Office of Science Nuclear Physics (NP)", + "label": "DOE Office of Science Nuclear Physics (NP)" + }, + { + "value": "DOE Office of Science Workforce Development for Teachers and Students (WDTS)", + "label": "DOE Office of Science Workforce Development for Teachers and Students (WDTS)" + }, + { + "value": "DOE Laboratory Directed Research and Development (LDRD)", + "label": "DOE Laboratory Directed Research and Development (LDRD)" + }, + { + "value": "USDA - Agricultural Research Service (ARS)", + "label": "USDA - Agricultural Research Service (ARS)" + }, + { + "value": "USDA - Forest Service (FS)", + "label": "USDA - Forest Service (FS)" + }, + { + "value": "DOC - National Institute of Standards and Technology (NIST)", + "label": "DOC - National Institute of Standards and Technology (NIST)" + }, + { + "value": "DOC - National Oceanic and Atmospheric Administration (NOAA)", + "label": "DOC - National Oceanic and Atmospheric Administration (NOAA)" + }, + { + "value": "DOD - Defense Advanced Research Projects Agency (DARPA)", + "label": "DOD - Defense Advanced Research Projects Agency (DARPA)" + }, + { + "value": "U.S. Department of Education (DOEd)", + "label": "U.S. Department of Education (DOEd)" + }, + { + "value": "U.S. Department of Health and Human Services (HHS) - Other (excl. NCI and NIH)", + "label": "U.S. Department of Health and Human Services (HHS) - Other (excl. NCI and NIH)" + }, + { + "value": "HHS - Centers for Disease Control (CDC)", + "label": "HHS - Centers for Disease Control (CDC)" + }, + { + "value": "HHS - National Institutes of Health (NIH)", + "label": "HHS - National Institutes of Health (NIH)" + }, + { + "value": "HHS - NIH - National Cancer Institute (NCI)", + "label": "HHS - NIH - National Cancer Institute (NCI)" + }, + { + "value": "HHS - U.S. United States Food and Drug Administration (FDA)", + "label": "HHS - U.S. United States Food and Drug Administration (FDA)" + }, + { + "value": "U.S. Department of Homeland Security (DHS)", + "label": "U.S. Department of Homeland Security (DHS)" + }, + { + "value": "DOI - U.S. Geological Survey (USGS)", + "label": "DOI - U.S. Geological Survey (USGS)" + }, + { + "value": "DOI - U.S. Fish and Wildlife Service (FWS)", + "label": "DOI - U.S. Fish and Wildlife Service (FWS)" + }, + { + "value": "U.S. Department of Transportation (DOT)", + "label": "U.S. Department of Transportation (DOT)" + }, + { + "value": "Environmental Protection Agency (EPA)", + "label": "Environmental Protection Agency (EPA)" + }, + { + "value": "National Aeronautics and Space Administration (NASA)", + "label": "National Aeronautics and Space Administration (NASA)" + }, + { + "value": "National Science Foundation (NSF)", + "label": "National Science Foundation (NSF)" + }, + { + "value": "Nuclear Regulatory Commission (NRC)", + "label": "Nuclear Regulatory Commission (NRC)" + }, + { + "value": "Small Business Administration (SBA)", + "label": "Small Business Administration (SBA)" + }, + { + "value": "U.S. Other Federal Agency", + "label": "U.S. Other Federal Agency" + }, + { + "value": "Federally Funded Research and Development Center (FFRDC) - (Specify)", + "label": "Federally Funded Research and Development Center (FFRDC) - (Specify)" + }, + { "value": "other", "label": "Other" } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/gravatarDefaults.json b/vite-app/src/apps/Auth2/resources/dataSources/gravatarDefaults.json new file mode 100644 index 000000000..581fee25a --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/gravatarDefaults.json @@ -0,0 +1,22 @@ +[ + { + "value": "mm", + "label": "Mystery Man - simple, cartoon-style silhouetted outline" + }, + { + "value": "identicon", + "label": "Identicon - a geometric pattern based on an email hash" + }, + { + "value": "monsterid", + "label": "MonsterID - generated \"monster\" with different colors, faces, etc" + }, + { + "value": "wavatar", + "label": "Wavatar - generated faces with differing features and backgrounds" + }, + { + "value": "retro", + "label": "Retro - 8-bit arcade-style pixelated faces" + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/institutions.json b/vite-app/src/apps/Auth2/resources/dataSources/institutions.json new file mode 100644 index 000000000..24ff890ff --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/institutions.json @@ -0,0 +1,5903 @@ +[ + { "value": "177834", "label": "A T Still University of Health Sciences" }, + { "value": "180203", "label": "Aaniiih Nakoda College" }, + { "value": "222178", "label": "Abilene Christian University" }, + { "value": "138558", "label": "Abraham Baldwin Agricultural College" }, + { "value": "172866", "label": "Academy College" }, + { "value": "451079", "label": "Academy for Five Element Acupuncture" }, + { "value": "457271", "label": "Academy for Jewish Religion-California" }, + { + "value": "412173", + "label": "Academy for Nursing and Health Occupations" + }, + { "value": "108232", "label": "Academy of Art University" }, + { + "value": "108269", + "label": "Academy of Chinese Culture and Health Sciences" + }, + { "value": "475635", "label": "Academy of Couture Art" }, + { "value": "449454", "label": "Academy of Natural Therapy Inc" }, + { + "value": "384306", + "label": "Acupuncture and Integrative Medicine College-Berkeley" + }, + { "value": "439969", "label": "Acupuncture and Massage College" }, + { "value": "126182", "label": "Adams State University" }, + { "value": "188429", "label": "Adelphi University" }, + { "value": "188438", "label": "Adirondack Community College" }, + { "value": "374024", "label": "Adler Graduate School" }, + { "value": "142832", "label": "Adler University" }, + { "value": "168528", "label": "Adrian College" }, + { "value": "444343", "label": "Advanced College" }, + { "value": "481234", "label": "Advanced Computing Institute" }, + { "value": "231411", "label": "Advanced Technology Institute" }, + { "value": "444361", "label": "Advanced Training Associates" }, + { "value": "133872", "label": "Adventist University of Health Sciences" }, + { + "value": "205391", + "label": "Advertising Art Educational Services DBA School of Advertising Art" + }, + { "value": "138600", "label": "Agnes Scott College" }, + { + "value": "134811", + "label": "AI Miami International University of Art and Design" + }, + { "value": "152822", "label": "AIB College of Business" }, + { "value": "217615", "label": "Aiken Technical College" }, + { "value": "126207", "label": "Aims Community College" }, + { + "value": "200697", + "label": "Air Force Institute of Technology-Graduate School of Engineering & Management" + }, + { "value": "200785", "label": "Akron Institute of Herzing University" }, + { "value": "100654", "label": "Alabama A & M University" }, + { "value": "101949", "label": "Alabama Southern Community College" }, + { "value": "100724", "label": "Alabama State University" }, + { "value": "199786", "label": "Alamance Community College" }, + { "value": "102580", "label": "Alaska Bible College" }, + { "value": "103501", "label": "Alaska Career College" }, + { "value": "442523", "label": "Alaska Christian College" }, + { "value": "102669", "label": "Alaska Pacific University" }, + { + "value": "188526", + "label": "Albany College of Pharmacy and Health Sciences" + }, + { "value": "188535", "label": "Albany Law School" }, + { "value": "188580", "label": "Albany Medical College" }, + { "value": "138716", "label": "Albany State University" }, + { "value": "138682", "label": "Albany Technical College" }, + { "value": "128498", "label": "Albertus Magnus College" }, + { "value": "168546", "label": "Albion College" }, + { "value": "210571", "label": "Albright College" }, + { "value": "175342", "label": "Alcorn State University" }, + { "value": "237118", "label": "Alderson Broaddus University" }, + { "value": "172918", "label": "Alexandria Technical & Community College" }, + { "value": "188641", "label": "Alfred University" }, + { "value": "156189", "label": "Alice Lloyd College" }, + { "value": "108807", "label": "Allan Hancock College" }, + { "value": "161688", "label": "Allegany College of Maryland" }, + { "value": "210669", "label": "Allegheny College" }, + { "value": "200873", "label": "Allegheny Wesleyan College" }, + { "value": "152798", "label": "Allen College" }, + { "value": "154642", "label": "Allen County Community College" }, + { "value": "217624", "label": "Allen University" }, + { + "value": "110468", + "label": "Alliant International University-San Diego" + }, + { "value": "460729", "label": "Allied American University" }, + { "value": "168591", "label": "Alma College" }, + { "value": "168607", "label": "Alpena Community College" }, + { "value": "210775", "label": "Alvernia University" }, + { "value": "238193", "label": "Alverno College" }, + { "value": "222567", "label": "Alvin Community College" }, + { "value": "222576", "label": "Amarillo College" }, + { "value": "222628", "label": "Amberton University" }, + { "value": "457527", "label": "Ambria College of Nursing" }, + { + "value": "188687", + "label": "American Academy McAllister Institute of Funeral Service" + }, + { + "value": "446002", + "label": "American Academy of Acupuncture and Oriental Medicine" + }, + { "value": "142887", "label": "American Academy of Art" }, + { + "value": "108852", + "label": "American Academy of Dramatic Arts-Los Angeles" + }, + { + "value": "188678", + "label": "American Academy of Dramatic Arts-New York" + }, + { "value": "219505", "label": "American Baptist College" }, + { "value": "108861", "label": "American Baptist Seminary of the West" }, + { + "value": "457688", + "label": "American Business and Technology University" + }, + { "value": "441052", "label": "American Career College-Anaheim" }, + { "value": "109040", "label": "American Career College-Los Angeles" }, + { "value": "447768", "label": "American Career College-Ontario" }, + { "value": "461005", "label": "American College for Medical Careers" }, + { + "value": "429085", + "label": "American College of Acupuncture and Oriental Med" + }, + { "value": "449889", "label": "American College of Education" }, + { "value": "210809", "label": "American College of Financial Services" }, + { "value": "443599", "label": "American College of Healthcare Sciences" }, + { + "value": "430591", + "label": "American College of Traditional Chinese Medicine" + }, + { "value": "109086", "label": "American Conservatory Theater" }, + { "value": "108870", "label": "American Film Institute Conservatory" }, + { "value": "103787", "label": "American Indian College Inc" }, + { + "value": "441636", + "label": "American Institute of Alternative Medicine" + }, + { + "value": "438586", + "label": "American InterContinental University-Atlanta" + }, + { + "value": "445133", + "label": "American InterContinental University-Houston" + }, + { + "value": "445027", + "label": "American InterContinental University-Online" + }, + { + "value": "438601", + "label": "American InterContinental University-South Florida" + }, + { "value": "164447", "label": "American International College" }, + { "value": "116846", "label": "American Jewish University" }, + { "value": "475714", "label": "American Medical Academy" }, + { "value": "188854", "label": "American Musical and Dramatic Academy" }, + { "value": "232797", "label": "American National University" }, + { "value": "449339", "label": "American Public University System" }, + { "value": "109208", "label": "American River College" }, + { "value": "240736", "label": "American Samoa Community College" }, + { "value": "460738", "label": "American Sentinel University" }, + { "value": "131159", "label": "American University" }, + { "value": "433004", "label": "American University of Health Sciences" }, + { + "value": "241100", + "label": "American University of Puerto Rico-Bayamon" + }, + { "value": "241128", "label": "American University of Puerto Rico-Manati" }, + { "value": "447263", "label": "AmeriTech College-Draper" }, + { "value": "164465", "label": "Amherst College" }, + { "value": "100690", "label": "Amridge University" }, + { "value": "151865", "label": "Anabaptist Mennonite Biblical Seminary" }, + { "value": "150048", "label": "Ancilla College" }, + { "value": "150066", "label": "Anderson University-Anderson" }, + { "value": "217633", "label": "Anderson University-Anderson" }, + { "value": "164474", "label": "Andover Newton Theological School" }, + { "value": "138761", "label": "Andrew College" }, + { "value": "168740", "label": "Andrews University" }, + { "value": "457299", "label": "Angeles College" }, + { "value": "222822", "label": "Angelina College" }, + { "value": "222831", "label": "Angelo State University" }, + { "value": "164492", "label": "Anna Maria College" }, + { "value": "161767", "label": "Anne Arundel Community College" }, + { "value": "172954", "label": "Anoka Technical College" }, + { "value": "172963", "label": "Anoka-Ramsey Community College" }, + { "value": "109350", "label": "Antelope Valley College" }, + { "value": "245838", "label": "Antioch University-Los Angeles" }, + { "value": "245892", "label": "Antioch University-Midwest" }, + { "value": "245865", "label": "Antioch University-New England" }, + { + "value": "442392", + "label": "Antioch University-PhD Program in Leadership and Change" + }, + { "value": "245847", "label": "Antioch University-Santa Barbara" }, + { "value": "245883", "label": "Antioch University-Seattle" }, + { "value": "201016", "label": "Antonelli College-Cincinnati" }, + { "value": "383950", "label": "Antonelli College-Hattiesburg" }, + { "value": "175528", "label": "Antonelli College-Jackson" }, + { "value": "210890", "label": "Antonelli Institute" }, + { + "value": "429094", + "label": "AOMA Graduate School of Integrative Medicine" + }, + { "value": "441511", "label": "Apex School of Theology" }, + { "value": "237136", "label": "Appalachian Bible College" }, + { "value": "449922", "label": "Appalachian College of Pharmacy" }, + { "value": "432348", "label": "Appalachian School of Law" }, + { "value": "197869", "label": "Appalachian State University" }, + { "value": "168786", "label": "Aquinas College-Grand Rapids" }, + { "value": "219578", "label": "Aquinas College-Nashville" }, + { "value": "176600", "label": "Aquinas Institute of Theology" }, + { "value": "126289", "label": "Arapahoe Community College" }, + { "value": "211088", "label": "Arcadia University" }, + { "value": "367936", "label": "Argosy University-Atlanta" }, + { "value": "145770", "label": "Argosy University-Chicago" }, + { "value": "442222", "label": "Argosy University-Dallas" }, + { "value": "448734", "label": "Argosy University-Denver" }, + { "value": "366748", "label": "Argosy University-Hawaii" }, + { "value": "450526", "label": "Argosy University-Inland Empire" }, + { "value": "447272", "label": "Argosy University-Los Angeles" }, + { "value": "450535", "label": "Argosy University-Nashville" }, + { "value": "436438", "label": "Argosy University-Orange County" }, + { "value": "436094", "label": "Argosy University-Phoenix" }, + { "value": "456348", "label": "Argosy University-Phoenix Online Division" }, + { "value": "452090", "label": "Argosy University-Salt Lake City" }, + { "value": "450544", "label": "Argosy University-San Diego" }, + { "value": "121983", "label": "Argosy University-San Francisco Bay Area" }, + { "value": "137148", "label": "Argosy University-Sarasota" }, + { "value": "420866", "label": "Argosy University-Schaumburg" }, + { "value": "439057", "label": "Argosy University-Seattle" }, + { "value": "428268", "label": "Argosy University-Tampa" }, + { + "value": "410502", + "label": "Argosy University-The Art Institute of California-Hollywood" + }, + { + "value": "448576", + "label": "Argosy University-The Art Institute of California-Inland Empire" + }, + { + "value": "432533", + "label": "Argosy University-The Art Institute of California-Los Angeles" + }, + { + "value": "441973", + "label": "Argosy University-The Art Institute of California-Orange County" + }, + { + "value": "450094", + "label": "Argosy University-The Art Institute of California-Sacramento" + }, + { + "value": "117113", + "label": "Argosy University-The Art Institute of California-San Diego" + }, + { + "value": "117928", + "label": "Argosy University-The Art Institute of California-San Francisco" + }, + { + "value": "451848", + "label": "Argosy University-The Art Institute of California-Silicon Valley" + }, + { "value": "173984", "label": "Argosy University-Twin Cities" }, + { "value": "419457", "label": "Argosy University-Washington DC" }, + { "value": "105899", "label": "Arizona Christian University" }, + { "value": "421708", "label": "Arizona College-Glendale" }, + { "value": "482990", "label": "Arizona College-Mesa" }, + { + "value": "446039", + "label": "Arizona School of Acupuncture and Oriental Medicine" + }, + { "value": "448886", "label": "Arizona State University-Downtown Phoenix" }, + { "value": "420574", "label": "Arizona State University-Polytechnic" }, + { "value": "483124", "label": "Arizona State University-Skysong" }, + { "value": "104151", "label": "Arizona State University-Tempe" }, + { "value": "407009", "label": "Arizona State University-West" }, + { "value": "450942", "label": "Arizona Summit Law School" }, + { "value": "104160", "label": "Arizona Western College" }, + { "value": "106306", "label": "Arkansas Baptist College" }, + { "value": "107327", "label": "Arkansas Northeastern College" }, + { "value": "106449", "label": "Arkansas State University-Beebe" }, + { "value": "106458", "label": "Arkansas State University-Main Campus" }, + { "value": "107318", "label": "Arkansas State University-Mid-South" }, + { "value": "420538", "label": "Arkansas State University-Mountain Home" }, + { "value": "440402", "label": "Arkansas State University-Newport" }, + { "value": "106467", "label": "Arkansas Tech University" }, + { "value": "222877", "label": "Arlington Baptist College" }, + { "value": "138789", "label": "Armstrong State University" }, + { "value": "201061", "label": "Art Academy of Cincinnati" }, + { "value": "109651", "label": "Art Center College of Design" }, + { "value": "404994", "label": "ASA College" }, + { "value": "156222", "label": "Asbury Theological Seminary" }, + { "value": "156213", "label": "Asbury University" }, + { "value": "461777", "label": "Ashdown College of Health Sciences" }, + { "value": "447777", "label": "Asher College" }, + { + "value": "197887", + "label": "Asheville-Buncombe Technical Community College" + }, + { "value": "154022", "label": "Ashford University" }, + { "value": "156231", "label": "Ashland Community and Technical College" }, + { "value": "201104", "label": "Ashland University" }, + { "value": "128577", "label": "Asnuntuck Community College" }, + { "value": "454829", "label": "Aspen University" }, + { "value": "176619", "label": "Assemblies of God Theological Seminary" }, + { "value": "164562", "label": "Assumption College" }, + { "value": "183600", "label": "Assumption College for Sisters" }, + { "value": "446127", "label": "ATA Career Education" }, + { "value": "447935", "label": "ATA College" }, + { "value": "440651", "label": "Atenas College" }, + { "value": "201140", "label": "Athenaeum of Ohio" }, + { "value": "100812", "label": "Athens State University" }, + { "value": "246813", "label": "Athens Technical College" }, + { "value": "138901", "label": "Atlanta Metropolitan State College" }, + { "value": "138840", "label": "Atlanta Technical College" }, + { "value": "138929", "label": "Atlanta's John Marshall Law School" }, + { "value": "183655", "label": "Atlantic Cape Community College" }, + { "value": "439446", "label": "Atlantic Institute of Oriental Medicine" }, + { "value": "241216", "label": "Atlantic University College" }, + { "value": "100858", "label": "Auburn University" }, + { "value": "100830", "label": "Auburn University at Montgomery" }, + { "value": "173045", "label": "Augsburg College" }, + { "value": "138956", "label": "Augusta Technical College" }, + { "value": "482149", "label": "Augusta University" }, + { "value": "143084", "label": "Augustana College-Rock Island" }, + { "value": "219000", "label": "Augustana University" }, + { + "value": "201177", + "label": "Aultman College of Nursing and Health Sciences" + }, + { "value": "143118", "label": "Aurora University" }, + { "value": "222983", "label": "Austin College" }, + { "value": "222992", "label": "Austin Community College District" }, + { "value": "247825", "label": "Austin Graduate School of Theology" }, + { "value": "219602", "label": "Austin Peay State University" }, + { "value": "223001", "label": "Austin Presbyterian Theological Seminary" }, + { "value": "442295", "label": "Ave Maria School of Law" }, + { "value": "446048", "label": "Ave Maria University" }, + { "value": "231420", "label": "Averett University" }, + { + "value": "449931", + "label": "Averett University-Non-Traditional Programs" + }, + { + "value": "447847", + "label": "Aviator College of Aeronautical Science and Technology" + }, + { "value": "176628", "label": "Avila University" }, + { "value": "102711", "label": "AVTEC-Alaska's Institute of Technology" }, + { "value": "483762", "label": "Azure College" }, + { "value": "109785", "label": "Azusa Pacific University" }, + { "value": "474863", "label": "Azusa Pacific University College" }, + { "value": "164580", "label": "Babson College" }, + { "value": "206817", "label": "Bacone College" }, + { "value": "139010", "label": "Bainbridge State College" }, + { "value": "476601", "label": "Bais HaMedrash and Mesivta of Baltimore" }, + { "value": "245777", "label": "Bais Medrash Elyon" }, + { "value": "449658", "label": "Bais Medrash Toras Chesed" }, + { "value": "168847", "label": "Baker College" }, + { "value": "414708", "label": "Baker College Center for Graduate Studies" }, + { "value": "444167", "label": "Baker College of Allen Park" }, + { "value": "404073", "label": "Baker College of Auburn Hills" }, + { "value": "404648", "label": "Baker College of Cadillac" }, + { "value": "404082", "label": "Baker College of Clinton Township" }, + { "value": "414160", "label": "Baker College of Jackson" }, + { "value": "171298", "label": "Baker College of Muskegon" }, + { "value": "168838", "label": "Baker College of Owosso" }, + { "value": "381617", "label": "Baker College of Port Huron" }, + { "value": "154688", "label": "Baker University" }, + { "value": "109819", "label": "Bakersfield College" }, + { "value": "420705", "label": "Bakke Graduate University" }, + { "value": "201195", "label": "Baldwin Wallace University" }, + { "value": "150136", "label": "Ball State University" }, + { "value": "161864", "label": "Baltimore City Community College" }, + { "value": "189015", "label": "Bank Street College of Education" }, + { "value": "176664", "label": "Baptist Bible College" }, + { "value": "211024", "label": "Clarks Summit University" }, + { + "value": "223083", + "label": "Baptist Health System School of Health Professions" + }, + { + "value": "219639", + "label": "Baptist Memorial College of Health Sciences" + }, + { + "value": "223117", + "label": "Baptist Missionary Association Theological Seminary" + }, + { "value": "366793", "label": "Baptist Theological Seminary at Richmond" }, + { "value": "444398", "label": "Baptist University of the Americas" }, + { "value": "155070", "label": "Barclay College" }, + { "value": "189088", "label": "Bard College" }, + { "value": "167792", "label": "Bard College at Simon's Rock" }, + { "value": "189097", "label": "Barnard College" }, + { + "value": "177719", + "label": "Barnes-Jewish College Goldfarb School of Nursing" + }, + { "value": "132471", "label": "Barry University" }, + { "value": "109907", "label": "Barstow Community College" }, + { "value": "197911", "label": "Barton College" }, + { "value": "154697", "label": "Barton County Community College" }, + { "value": "235547", "label": "Bastyr University" }, + { "value": "160977", "label": "Bates College" }, + { "value": "235671", "label": "Bates Technical College" }, + { "value": "437103", "label": "Baton Rouge Community College" }, + { "value": "158343", "label": "Baton Rouge School of Computers" }, + { "value": "139074", "label": "Bauder College" }, + { "value": "168883", "label": "Bay de Noc Community College" }, + { "value": "380359", "label": "Bay Mills Community College" }, + { "value": "164632", "label": "Bay Path University" }, + { "value": "164641", "label": "Bay State College" }, + { "value": "223223", "label": "Baylor College of Medicine" }, + { "value": "223232", "label": "Baylor University" }, + { "value": "384254", "label": "Beacon College" }, + { "value": "160995", "label": "Beal College" }, + { "value": "197966", "label": "Beaufort County Community College" }, + { "value": "164720", "label": "Becker College" }, + { "value": "247065", "label": "Beckfield College-Florence" }, + { "value": "452373", "label": "Beckfield College-Tri-County" }, + { "value": "476717", "label": "Be'er Yaakov Talmudic Seminary" }, + { "value": "444413", "label": "Beis Medrash Heichal Dovid" }, + { "value": "190956", "label": "Belanger School of Nursing" }, + { "value": "175421", "label": "Belhaven University" }, + { "value": "156286", "label": "Bellarmine University" }, + { "value": "234669", "label": "Bellevue College" }, + { "value": "180814", "label": "Bellevue University" }, + { "value": "238324", "label": "Bellin College" }, + { "value": "234696", "label": "Bellingham Technical College" }, + { "value": "197984", "label": "Belmont Abbey College" }, + { "value": "201283", "label": "Belmont College" }, + { "value": "219709", "label": "Belmont University" }, + { "value": "238333", "label": "Beloit College" }, + { "value": "126359", "label": "Bel-Rea Institute of Animal Technology" }, + { "value": "173124", "label": "Bemidji State University" }, + { "value": "217721", "label": "Benedict College" }, + { "value": "154712", "label": "Benedictine College" }, + { "value": "145619", "label": "Benedictine University" }, + { "value": "165884", "label": "Benjamin Franklin Institute of Technology" }, + { "value": "197993", "label": "Bennett College" }, + { "value": "230816", "label": "Bennington College" }, + { "value": "164739", "label": "Bentley University" }, + { "value": "156295", "label": "Berea College" }, + { "value": "183743", "label": "Bergen Community College" }, + { "value": "461643", "label": "Bergin University of Canine Studies" }, + { "value": "125170", "label": "Berkeley City College" }, + { "value": "189228", "label": "Berkeley College-New York" }, + { "value": "183789", "label": "Berkeley College-Woodland Park" }, + { "value": "164748", "label": "Berklee College of Music" }, + { "value": "213534", "label": "Berks Technical Institute" }, + { "value": "164775", "label": "Berkshire Community College" }, + { "value": "139144", "label": "Berry College" }, + { "value": "189273", "label": "Beth Hamedrash Shaarei Yosher Institute" }, + { "value": "189264", "label": "Beth Hatalmud Rabbinical College" }, + { "value": "183804", "label": "Beth Medrash Govoha" }, + { "value": "237181", "label": "Bethany College-Bethany" }, + { "value": "154721", "label": "Bethany College-Lindsborg" }, + { "value": "173142", "label": "Bethany Lutheran College" }, + { "value": "143233", "label": "Bethany Theological Seminary" }, + { "value": "458113", "label": "Bethel College" }, + { "value": "150145", "label": "Bethel College-Indiana" }, + { "value": "154749", "label": "Bethel College-North Newton" }, + { "value": "262022", "label": "Bethel Seminary-San Diego" }, + { "value": "173179", "label": "Bethel Seminary-St Paul" }, + { "value": "219718", "label": "Bethel University-McKenzie" }, + { "value": "173160", "label": "Bethel University-Saint Paul" }, + { "value": "110060", "label": "Bethesda University" }, + { "value": "132602", "label": "Bethune-Cookman University" }, + { "value": "139153", "label": "Beulah Heights University" }, + { "value": "102429", "label": "Bevill State Community College" }, + { + "value": "148724", + "label": "Bexley Hall Seabury Western Theological Seminary Federation" + }, + { + "value": "443702", + "label": "Bexley Hall Seabury Western Theological Seminary Federation " + }, + { "value": "211130", "label": "Biblical Theological Seminary" }, + { "value": "211149", "label": "Bidwell Training Center Inc" }, + { "value": "234711", "label": "Big Bend Community College" }, + { "value": "157553", "label": "Big Sandy Community and Technical College" }, + { "value": "110097", "label": "Biola University" }, + { "value": "100937", "label": "Birmingham Southern College" }, + { "value": "442949", "label": "Birthingway College of Midwifery" }, + { "value": "102030", "label": "Bishop State Community College" }, + { "value": "200022", "label": "Bismarck State College" }, + { "value": "143279", "label": "Black Hawk College" }, + { "value": "219046", "label": "Black Hills State University" }, + { "value": "106625", "label": "Black River Technical College" }, + { "value": "143288", "label": "Blackburn College" }, + { "value": "180054", "label": "Blackfeet Community College" }, + { "value": "238397", "label": "Blackhawk Technical College" }, + { "value": "198011", "label": "Bladen Community College" }, + { "value": "143297", "label": "Blessing Rieman College of Nursing" }, + { "value": "223427", "label": "Blinn College" }, + { "value": "183822", "label": "Bloomfield College" }, + { "value": "211158", "label": "Bloomsburg University of Pennsylvania" }, + { "value": "441502", "label": "Blue Cliff College-Gulfport" }, + { "value": "175430", "label": "Blue Mountain College" }, + { "value": "208275", "label": "Blue Mountain Community College" }, + { + "value": "446774", + "label": "Blue Ridge Community and Technical College" + }, + { "value": "198039", "label": "Blue Ridge Community College-Flat Rock" }, + { "value": "231536", "label": "Blue Ridge Community College-Weyers Cave" }, + { "value": "231554", "label": "Bluefield College" }, + { "value": "237215", "label": "Bluefield State College" }, + { "value": "156392", "label": "Bluegrass Community and Technical College" }, + { "value": "201371", "label": "Bluffton University" }, + { "value": "217749", "label": "Bob Jones University" }, + { "value": "142090", "label": "Boise Bible College" }, + { "value": "142115", "label": "Boise State University" }, + { "value": "233356", "label": "Bon Secours Memorial College of Nursing" }, + { "value": "189413", "label": "Boricua College" }, + { "value": "158431", "label": "Bossier Parish Community College" }, + { "value": "164872", "label": "Boston Architectural College" }, + { "value": "164614", "label": "Boston Baptist College" }, + { "value": "164924", "label": "Boston College" }, + { + "value": "164915", + "label": "Boston Graduate School of Psychoanalysis Inc" + }, + { "value": "164988", "label": "Boston University" }, + { "value": "161004", "label": "Bowdoin College" }, + { "value": "162007", "label": "Bowie State University" }, + { "value": "201432", "label": "Bowling Green State University-Firelands" }, + { + "value": "201441", + "label": "Bowling Green State University-Main Campus" + }, + { "value": "202161", "label": "Bradford School-Columbus" }, + { "value": "211200", "label": "Bradford School-Pittsburgh" }, + { "value": "143358", "label": "Bradley University" }, + { "value": "189422", "label": "Bramson ORT College" }, + { "value": "165015", "label": "Brandeis University" }, + { "value": "262086", "label": "Brandman University" }, + { "value": "223506", "label": "Brazosport College" }, + { "value": "139199", "label": "Brenau University" }, + { "value": "156356", "label": "Brescia University" }, + { "value": "198066", "label": "Brevard College" }, + { "value": "139205", "label": "Brewton-Parker College" }, + { "value": "152992", "label": "Briar Cliff University" }, + { "value": "189459", "label": "Briarcliffe College" }, + { "value": "231581", "label": "Bridgewater College" }, + { "value": "165024", "label": "Bridgewater State University" }, + { "value": "230047", "label": "Brigham Young University-Hawaii" }, + { "value": "142522", "label": "Brigham Young University-Idaho" }, + { "value": "230038", "label": "Brigham Young University-Provo" }, + { "value": "215646", "label": "Brightwood Career Institute-Broomall" }, + { "value": "251075", "label": "Brightwood Career Institute-Harrisburg" }, + { "value": "214254", "label": "Brightwood Career Institute-Philadelphia" }, + { + "value": "211617", + "label": "Brightwood Career Institute-Philadelphia Mills" + }, + { "value": "213002", "label": "Brightwood Career Institute-Pittsburgh" }, + { "value": "458690", "label": "Brightwood College-Arlington" }, + { "value": "447102", "label": "Brightwood College-Bakersfield" }, + { "value": "163736", "label": "Brightwood College-Baltimore" }, + { "value": "440323", "label": "Brightwood College-Beaumont" }, + { "value": "164058", "label": "Brightwood College-Beltsville" }, + { "value": "443827", "label": "Brightwood College-Brownsville" }, + { "value": "458706", "label": "Brightwood College-Charlotte" }, + { "value": "458186", "label": "Brightwood College-Chula Vista" }, + { "value": "443836", "label": "Brightwood College-Corpus Christi" }, + { "value": "382896", "label": "Brightwood College-Dallas" }, + { "value": "204626", "label": "Brightwood College-Dayton" }, + { "value": "246266", "label": "Brightwood College-El Paso" }, + { "value": "445328", "label": "Brightwood College-Fort Worth" }, + { "value": "447120", "label": "Brightwood College-Fresno" }, + { "value": "458283", "label": "Brightwood College-Indianapolis" }, + { "value": "440332", "label": "Brightwood College-Laredo" }, + { "value": "374875", "label": "Brightwood College-Las Vegas" }, + { "value": "227836", "label": "Brightwood College-McAllen" }, + { "value": "366960", "label": "Brightwood College-Modesto" }, + { "value": "246202", "label": "Brightwood College-Nashville" }, + { "value": "447634", "label": "Brightwood College-Palm Springs" }, + { "value": "432302", "label": "Brightwood College-Riverside" }, + { "value": "118259", "label": "Brightwood College-Sacramento" }, + { "value": "431886", "label": "Brightwood College-San Antonio-Ingram" }, + { "value": "364955", "label": "Brightwood College-San Antonio-San Pedro" }, + { "value": "118277", "label": "Brightwood College-San Diego" }, + { "value": "161776", "label": "Brightwood College-Towson" }, + { "value": "118286", "label": "Brightwood College-Vista" }, + { "value": "165033", "label": "Bristol Community College" }, + { "value": "397270", "label": "Bristol University" }, + { "value": "450304", "label": "Brite Divinity School" }, + { "value": "459091", "label": "Broadview Entertainment Arts University" }, + { "value": "467793", "label": "Broadview University-Boise" }, + { "value": "450429", "label": "Broadview University-Layton" }, + { "value": "454591", "label": "Broadview University-Orem" }, + { "value": "230056", "label": "Broadview University-West Jordan" }, + { "value": "183859", "label": "Brookdale Community College" }, + { "value": "223524", "label": "Brookhaven College" }, + { "value": "444088", "label": "Brookline College-Albuquerque" }, + { "value": "104090", "label": "Brookline College-Phoenix" }, + { "value": "404055", "label": "Brookline College-Tempe" }, + { "value": "438179", "label": "Brookline College-Tucson" }, + { "value": "189501", "label": "Brooklyn Law School" }, + { "value": "110185", "label": "Brooks Institute" }, + { "value": "132709", "label": "Broward College" }, + { "value": "205647", "label": "Brown Mackie College-Akron" }, + { "value": "460039", "label": "Brown Mackie College-Albuquerque" }, + { "value": "410283", "label": "Brown Mackie College-Atlanta" }, + { "value": "470162", "label": "Brown Mackie College-Birmingham" }, + { "value": "455600", "label": "Brown Mackie College-Boise" }, + { "value": "205610", "label": "Brown Mackie College-Cincinnati" }, + { "value": "482954", "label": "Brown Mackie College-Dallas" }, + { "value": "375489", "label": "Brown Mackie College-Findlay" }, + { "value": "408039", "label": "Brown Mackie College-Fort Wayne" }, + { "value": "456791", "label": "Brown Mackie College-Greenville" }, + { "value": "421513", "label": "Brown Mackie College-Hopkinsville" }, + { "value": "451699", "label": "Brown Mackie College-Indianapolis" }, + { "value": "154767", "label": "Brown Mackie College-Kansas City" }, + { "value": "157599", "label": "Brown Mackie College-Louisville" }, + { "value": "151616", "label": "Brown Mackie College-Merrillville" }, + { "value": "447290", "label": "Brown Mackie College-Miami" }, + { "value": "151625", "label": "Brown Mackie College-Michigan City" }, + { "value": "204316", "label": "Brown Mackie College-North Canton" }, + { "value": "157696", "label": "Brown Mackie College-Northern Kentucky" }, + { "value": "475042", "label": "Brown Mackie College-Oklahoma City" }, + { "value": "456612", "label": "Brown Mackie College-Phoenix" }, + { "value": "373085", "label": "Brown Mackie College-Quad Cities" }, + { "value": "154776", "label": "Brown Mackie College-Salina" }, + { "value": "460613", "label": "Brown Mackie College-San Antonio" }, + { "value": "151944", "label": "Brown Mackie College-South Bend" }, + { "value": "460048", "label": "Brown Mackie College-St Louis" }, + { "value": "104364", "label": "Brown Mackie College-Tucson" }, + { "value": "455619", "label": "Brown Mackie College-Tulsa" }, + { "value": "217156", "label": "Brown University" }, + { "value": "198084", "label": "Brunswick Community College" }, + { "value": "180878", "label": "Bryan College of Health Sciences" }, + { "value": "219790", "label": "Bryan College-Dayton" }, + { "value": "439826", "label": "Bryan College-Gold River" }, + { "value": "475583", "label": "Bryan University-Columbia" }, + { "value": "110219", "label": "Bryan University-Los Angeles" }, + { "value": "454458", "label": "Bryan University-Rogers" }, + { "value": "369516", "label": "Bryan University-Springfield" }, + { "value": "154794", "label": "Bryan University-Topeka" }, + { "value": "475699", "label": "Bryant & Stratton College-Akron" }, + { "value": "188517", "label": "Bryant & Stratton College-Albany" }, + { "value": "189556", "label": "Bryant & Stratton College-Amherst" }, + { "value": "458502", "label": "Bryant & Stratton College-Bayshore" }, + { "value": "189583", "label": "Bryant & Stratton College-Buffalo" }, + { "value": "202684", "label": "Bryant & Stratton College-Cleveland" }, + { "value": "369905", "label": "Bryant & Stratton College-Eastlake" }, + { "value": "189592", "label": "Bryant & Stratton College-Greece" }, + { "value": "459107", "label": "Bryant & Stratton College-Hampton" }, + { "value": "410496", "label": "Bryant & Stratton College-Henrietta" }, + { "value": "239929", "label": "Bryant & Stratton College-Milwaukee" }, + { "value": "480091", "label": "Bryant & Stratton College-Online" }, + { "value": "201469", "label": "Bryant & Stratton College-Parma" }, + { "value": "231828", "label": "Bryant & Stratton College-Richmond" }, + { "value": "374972", "label": "Bryant & Stratton College-Southtowns" }, + { "value": "189574", "label": "Bryant & Stratton College-Syracuse" }, + { "value": "189565", "label": "Bryant & Stratton College-Syracuse North" }, + { "value": "231785", "label": "Bryant & Stratton College-Virginia Beach" }, + { "value": "451750", "label": "Bryant & Stratton College-Wauwatosa" }, + { "value": "217165", "label": "Bryant University" }, + { "value": "210492", "label": "Bryn Athyn College of the New Church" }, + { "value": "211273", "label": "Bryn Mawr College" }, + { "value": "211291", "label": "Bucknell University" }, + { "value": "211307", "label": "Bucks County Community College" }, + { "value": "211316", "label": "Bucks County School of Beauty Culture Inc" }, + { "value": "153001", "label": "Buena Vista University" }, + { "value": "165112", "label": "Bunker Hill Community College" }, + { "value": "230825", "label": "Burlington College" }, + { "value": "484181", "label": "Burnett International College" }, + { "value": "189653", "label": "Business Informatics Center Inc" }, + { "value": "154800", "label": "Butler Community College" }, + { "value": "211343", "label": "Butler County Community College" }, + { "value": "150163", "label": "Butler University" }, + { "value": "110246", "label": "Butte College" }, + { + "value": "444103", + "label": "Byzantine Catholic Seminary of Saints Cyril and Methodius" + }, + { "value": "198109", "label": "Cabarrus College of Health Sciences" }, + { "value": "110334", "label": "Cabrillo College" }, + { "value": "211352", "label": "Cabrini University" }, + { "value": "215114", "label": "Cairn University-Langhorne" }, + { + "value": "198118", + "label": "Caldwell Community College and Technical Institute" + }, + { "value": "183910", "label": "Caldwell University" }, + { "value": "110361", "label": "California Baptist University" }, + { "value": "110918", "label": "California Christian College" }, + { "value": "110370", "label": "California College of the Arts" }, + { "value": "485263", "label": "California College San Diego-San Diego" }, + { "value": "478634", "label": "California College San Diego-San Marcos" }, + { "value": "110316", "label": "California Institute of Integral Studies" }, + { "value": "110404", "label": "California Institute of Technology" }, + { "value": "111081", "label": "California Institute of the Arts" }, + { "value": "110413", "label": "California Lutheran University" }, + { "value": "480781", "label": "California Miramar University" }, + { + "value": "110422", + "label": "California Polytechnic State University-San Luis Obispo" + }, + { + "value": "110529", + "label": "California State Polytechnic University-Pomona" + }, + { "value": "110486", "label": "California State University-Bakersfield" }, + { + "value": "441937", + "label": "California State University-Channel Islands" + }, + { "value": "110538", "label": "California State University-Chico" }, + { + "value": "110547", + "label": "California State University-Dominguez Hills" + }, + { "value": "110574", "label": "California State University-East Bay" }, + { "value": "110556", "label": "California State University-Fresno" }, + { "value": "110565", "label": "California State University-Fullerton" }, + { "value": "110583", "label": "California State University-Long Beach" }, + { "value": "110592", "label": "California State University-Los Angeles" }, + { "value": "409698", "label": "California State University-Monterey Bay" }, + { "value": "110608", "label": "California State University-Northridge" }, + { "value": "110617", "label": "California State University-Sacramento" }, + { + "value": "110510", + "label": "California State University-San Bernardino" + }, + { "value": "366711", "label": "California State University-San Marcos" }, + { "value": "110495", "label": "California State University-Stanislaus" }, + { + "value": "460075", + "label": "California University of Management and Sciences" + }, + { "value": "211361", "label": "California University of Pennsylvania" }, + { "value": "111391", "label": "California Western School of Law" }, + { "value": "150172", "label": "Calumet College of Saint Joseph" }, + { + "value": "176789", + "label": "Calvary Bible College and Theological Seminary" + }, + { "value": "169080", "label": "Calvin College" }, + { "value": "169099", "label": "Calvin Theological Seminary" }, + { "value": "428329", "label": "Cambria-Rowe Business College-Indiana" }, + { "value": "211398", "label": "Cambria-Rowe Business College-Johnstown" }, + { "value": "165167", "label": "Cambridge College" }, + { + "value": "454865", + "label": "Cambridge College of Healthcare & Technology" + }, + { "value": "446093", "label": "Cambridge Junior College-Yuba City" }, + { "value": "183938", "label": "Camden County College" }, + { "value": "158440", "label": "Cameron College" }, + { "value": "206914", "label": "Cameron University" }, + { "value": "198136", "label": "Campbell University" }, + { "value": "156365", "label": "Campbellsville University" }, + { "value": "111434", "label": "Canada College" }, + { "value": "189705", "label": "Canisius College" }, + { "value": "200208", "label": "Cankdeska Cikana Community College" }, + { "value": "165194", "label": "Cape Cod Community College" }, + { "value": "198154", "label": "Cape Fear Community College" }, + { "value": "413413", "label": "Capella University" }, + { "value": "158352", "label": "Capital Area Technical College" }, + { "value": "129367", "label": "Capital Community College" }, + { "value": "201548", "label": "Capital University" }, + { "value": "162061", "label": "Capitol Technology University" }, + { "value": "238430", "label": "Cardinal Stritch University" }, + { "value": "181941", "label": "Career College of Northern Nevada" }, + { "value": "224439", "label": "Career Point College-San Antonio" }, + { "value": "246008", "label": "Career Point College-Tulsa" }, + { "value": "454306", "label": "Career Quest Learning Centers-Jackson" }, + { "value": "446136", "label": "Career Quest Learning Centers-Lansing" }, + { "value": "367112", "label": "Career Technical College-Monroe" }, + { "value": "446880", "label": "Career Technical College-Shreveport" }, + { "value": "210951", "label": "Career Training Academy-Lower Burrell" }, + { "value": "408312", "label": "Career Training Academy-Monroeville" }, + { "value": "440174", "label": "Career Training Academy-Pittsburgh" }, + { "value": "448239", "label": "Careers Unlimited" }, + { "value": "241377", "label": "Caribbean University-Bayamon" }, + { "value": "241386", "label": "Caribbean University-Carolina" }, + { "value": "363907", "label": "Caribbean University-Ponce" }, + { "value": "363916", "label": "Caribbean University-Vega Baja" }, + { "value": "206923", "label": "Carl Albert State College" }, + { "value": "143613", "label": "Carl Sandburg College" }, + { "value": "173258", "label": "Carleton College" }, + { "value": "132842", "label": "Carlos Albizu University-Miami" }, + { "value": "241331", "label": "Carlos Albizu University-San Juan" }, + { "value": "211431", "label": "Carlow University" }, + { "value": "211440", "label": "Carnegie Mellon University" }, + { "value": "199971", "label": "Carolina Christian College" }, + { "value": "461032", "label": "Carolina College of Biblical Studies" }, + { "value": "433174", "label": "Carolinas College of Health Sciences" }, + { "value": "442602", "label": "Carrington College-Albuquerque" }, + { "value": "142054", "label": "Carrington College-Boise" }, + { "value": "450702", "label": "Carrington College-Citrus Heights" }, + { "value": "457101", "label": "Carrington College-Las Vegas" }, + { "value": "103909", "label": "Carrington College-Mesa" }, + { "value": "103893", "label": "Carrington College-Phoenix" }, + { "value": "438258", "label": "Carrington College-Pleasant Hill" }, + { "value": "467368", "label": "Carrington College-Pomona" }, + { "value": "246035", "label": "Carrington College-Portland" }, + { "value": "457110", "label": "Carrington College-Reno" }, + { "value": "125532", "label": "Carrington College-Sacramento" }, + { "value": "437936", "label": "Carrington College-San Jose" }, + { "value": "246974", "label": "Carrington College-San Leandro" }, + { "value": "439118", "label": "Carrington College-Spokane" }, + { "value": "450696", "label": "Carrington College-Stockton" }, + { "value": "103927", "label": "Carrington College-Tucson" }, + { "value": "250601", "label": "Carrington College-Westside" }, + { "value": "180106", "label": "Carroll College" }, + { "value": "405872", "label": "Carroll Community College" }, + { "value": "238458", "label": "Carroll University" }, + { "value": "219806", "label": "Carson-Newman University" }, + { "value": "198206", "label": "Carteret Community College" }, + { "value": "238476", "label": "Carthage College" }, + { "value": "139287", "label": "Carver Bible College" }, + { "value": "430795", "label": "Carver Career Center" }, + { "value": "111638", "label": "Casa Loma College-Van Nuys" }, + { "value": "439190", "label": "Cascadia College" }, + { "value": "201645", "label": "Case Western Reserve University" }, + { "value": "240505", "label": "Casper College" }, + { "value": "230834", "label": "Castleton State College" }, + { "value": "198215", "label": "Catawba College" }, + { "value": "198233", "label": "Catawba Valley Community College" }, + { "value": "475398", "label": "Catholic Distance University" }, + { "value": "143659", "label": "Catholic Theological Union at Chicago" }, + { "value": "131283", "label": "Catholic University of America" }, + { "value": "189839", "label": "Cayuga County Community College" }, + { "value": "189848", "label": "Cazenovia College" }, + { "value": "162104", "label": "Cecil College" }, + { "value": "211468", "label": "Cedar Crest College" }, + { "value": "223773", "label": "Cedar Valley College" }, + { "value": "201654", "label": "Cedarville University" }, + { "value": "183974", "label": "Centenary College" }, + { "value": "158477", "label": "Centenary College of Louisiana" }, + { "value": "379782", "label": "Center for Advanced Legal Studies" }, + { + "value": "241793", + "label": "Center for Advanced Studies On Puerto Rico and the Caribbean" + }, + { "value": "232618", "label": "Centra College of Nursing" }, + { "value": "100760", "label": "Central Alabama Community College" }, + { "value": "104346", "label": "Central Arizona College" }, + { "value": "106713", "label": "Central Baptist College" }, + { "value": "154837", "label": "Central Baptist Theological Seminary" }, + { "value": "198251", "label": "Central Carolina Community College" }, + { "value": "218858", "label": "Central Carolina Technical College" }, + { "value": "154855", "label": "Central Christian College of Kansas" }, + { "value": "176910", "label": "Central Christian College of the Bible" }, + { "value": "153108", "label": "Central College" }, + { "value": "180902", "label": "Central Community College" }, + { "value": "128771", "label": "Central Connecticut State University" }, + { "value": "439525", "label": "Central Florida Institute" }, + { "value": "483045", "label": "Central Georgia Technical College" }, + { "value": "173203", "label": "Central Lakes College-Brainerd" }, + { + "value": "158088", + "label": "Central Louisiana Technical Community College" + }, + { "value": "161077", "label": "Central Maine Community College" }, + { + "value": "445267", + "label": "Central Methodist University-College of Graduate and Extended Studies" + }, + { + "value": "176947", + "label": "Central Methodist University-College of Liberal Arts and Sciences" + }, + { "value": "169248", "label": "Central Michigan University" }, + { "value": "187532", "label": "Central New Mexico Community College" }, + { "value": "201672", "label": "Central Ohio Technical College" }, + { "value": "208318", "label": "Central Oregon Community College" }, + { "value": "211477", "label": "Central Penn College" }, + { "value": "198260", "label": "Central Piedmont Community College" }, + { "value": "201690", "label": "Central State University" }, + { "value": "223816", "label": "Central Texas College" }, + { "value": "231697", "label": "Central Virginia Community College" }, + { "value": "234827", "label": "Central Washington University" }, + { "value": "240514", "label": "Central Wyoming College" }, + { "value": "189857", "label": "Central Yeshiva Tomchei Tmimim Lubavitz" }, + { "value": "234845", "label": "Centralia College" }, + { "value": "156408", "label": "Centre College" }, + { + "value": "451741", + "label": "Centro de Estudios Multidisciplinarios-Bayamon" + }, + { + "value": "376224", + "label": "Centro de Estudios Multidisciplinarios-Humacao" + }, + { + "value": "241517", + "label": "Centro de Estudios Multidisciplinarios-San Juan" + }, + { "value": "420024", "label": "Centura College-Chesapeake" }, + { "value": "444972", "label": "Centura College-Columbia" }, + { "value": "377449", "label": "Centura College-Newport News" }, + { "value": "377458", "label": "Centura College-Norfolk" }, + { "value": "427982", "label": "Centura College-Richmond Main" }, + { "value": "232016", "label": "Centura College-Virginia Beach" }, + { "value": "175315", "label": "Century College-White Bear Lake" }, + { "value": "111887", "label": "Cerritos College" }, + { "value": "111896", "label": "Cerro Coso Community College" }, + { "value": "111920", "label": "Chabot College" }, + { "value": "180948", "label": "Chadron State College" }, + { "value": "111939", "label": "Chaffey College" }, + { "value": "454245", "label": "Chamberlain College of Nursing-Arizona" }, + { "value": "457129", "label": "Chamberlain College of Nursing-Florida" }, + { "value": "475732", "label": "Chamberlain College of Nursing-Georgia" }, + { "value": "454227", "label": "Chamberlain College of Nursing-Illinois" }, + { "value": "466921", "label": "Chamberlain College of Nursing-Missouri" }, + { "value": "454236", "label": "Chamberlain College of Nursing-Ohio" }, + { "value": "466930", "label": "Chamberlain College of Nursing-Texas" }, + { "value": "460871", "label": "Chamberlain College of Nursing-Virginia" }, + { "value": "141486", "label": "Chaminade University of Honolulu" }, + { "value": "230852", "label": "Champlain College" }, + { "value": "364025", "label": "Chandler-Gilbert Community College" }, + { "value": "111948", "label": "Chapman University" }, + { + "value": "111966", + "label": "Charles R Drew University of Medicine and Science" + }, + { "value": "451510", "label": "Charleston School of Law" }, + { "value": "217688", "label": "Charleston Southern University" }, + { + "value": "444778", + "label": "Charlotte Christian College and Theological Seminary" + }, + { "value": "455169", "label": "Charlotte School of Law" }, + { "value": "102845", "label": "Charter College-Anchorage" }, + { "value": "434317", "label": "Charter College-Canyon Country" }, + { "value": "128780", "label": "Charter Oak State College" }, + { "value": "201751", "label": "Chatfield College" }, + { "value": "211556", "label": "Chatham University" }, + { "value": "140331", "label": "Chattahoochee Technical College" }, + { "value": "101028", "label": "Chattahoochee Valley Community College" }, + { + "value": "220118", + "label": "Chattanooga College Medical Dental and Technical Careers" + }, + { "value": "219824", "label": "Chattanooga State Community College" }, + { "value": "208390", "label": "Chemeketa Community College" }, + { "value": "162168", "label": "Chesapeake College" }, + { "value": "437769", "label": "Chester Career College" }, + { "value": "211583", "label": "Chestnut Hill College" }, + { "value": "211608", "label": "Cheyney University of Pennsylvania" }, + { + "value": "181145", + "label": "CHI Health School of Radiologic Technology" + }, + { "value": "393180", "label": "Chicago ORT Technical Institute" }, + { "value": "144005", "label": "Chicago State University" }, + { "value": "144014", "label": "Chicago Theological Seminary" }, + { "value": "180160", "label": "Chief Dull Knife College" }, + { "value": "133021", "label": "Chipola College" }, + { "value": "240116", "label": "Chippewa Valley Technical College" }, + { "value": "198303", "label": "Chowan University" }, + { "value": "189981", "label": "Christ the King Seminary" }, + { "value": "219833", "label": "Christian Brothers University" }, + { "value": "260947", "label": "Christian Life College" }, + { "value": "150215", "label": "Christian Theological Seminary" }, + { "value": "475510", "label": "Christie's Education" }, + { "value": "231712", "label": "Christopher Newport University" }, + { "value": "112127", "label": "Church Divinity School of the Pacific" }, + { "value": "201858", "label": "Cincinnati Christian University" }, + { "value": "201867", "label": "Cincinnati College of Mortuary Science" }, + { + "value": "201928", + "label": "Cincinnati State Technical and Community College" + }, + { "value": "223898", "label": "Cisco College" }, + { + "value": "217864", + "label": "Citadel Military College of South Carolina" + }, + { "value": "112172", "label": "Citrus College" }, + { "value": "112190", "label": "City College of San Francisco" }, + { "value": "417327", "label": "City College-Altamonte Springs" }, + { "value": "244233", "label": "City College-Fort Lauderdale" }, + { "value": "406547", "label": "City College-Gainesville" }, + { "value": "475477", "label": "City College-Hollywood" }, + { "value": "434539", "label": "City College-Miami" }, + { + "value": "144209", + "label": "City Colleges of Chicago-Harold Washington College" + }, + { + "value": "144184", + "label": "City Colleges of Chicago-Harry S Truman College" + }, + { + "value": "144157", + "label": "City Colleges of Chicago-Kennedy-King College" + }, + { + "value": "144166", + "label": "City Colleges of Chicago-Malcolm X College" + }, + { + "value": "144175", + "label": "City Colleges of Chicago-Olive-Harvey College" + }, + { + "value": "144193", + "label": "City Colleges of Chicago-Richard J Daley College" + }, + { + "value": "144218", + "label": "City Colleges of Chicago-Wilbur Wright College" + }, + { "value": "234915", "label": "City University of Seattle" }, + { "value": "457697", "label": "City Vision University" }, + { "value": "208406", "label": "Clackamas Community College" }, + { "value": "217873", "label": "Claflin University" }, + { "value": "112251", "label": "Claremont Graduate University" }, + { "value": "112260", "label": "Claremont McKenna College" }, + { "value": "124283", "label": "Claremont School of Theology" }, + { "value": "223922", "label": "Clarendon College" }, + { "value": "211644", "label": "Clarion University of Pennsylvania" }, + { "value": "138947", "label": "Clark Atlanta University" }, + { "value": "234933", "label": "Clark College" }, + { "value": "201973", "label": "Clark State Community College" }, + { "value": "165334", "label": "Clark University" }, + { "value": "153126", "label": "Clarke University" }, + { "value": "180832", "label": "Clarkson College" }, + { "value": "190044", "label": "Clarkson University" }, + { "value": "450401", "label": "Clary Sage College" }, + { "value": "208415", "label": "Clatsop Community College" }, + { "value": "139311", "label": "Clayton State University" }, + { "value": "156417", "label": "Clear Creek Baptist Bible College" }, + { "value": "133085", "label": "Clearwater Christian College" }, + { "value": "169327", "label": "Cleary University" }, + { "value": "217882", "label": "Clemson University" }, + { "value": "198321", "label": "Cleveland Community College" }, + { "value": "202046", "label": "Cleveland Institute of Art" }, + { "value": "202073", "label": "Cleveland Institute of Music" }, + { "value": "219879", "label": "Cleveland State Community College" }, + { "value": "202134", "label": "Cleveland State University" }, + { "value": "177038", "label": "Cleveland University-Kansas City" }, + { "value": "217891", "label": "Clinton College" }, + { "value": "190053", "label": "Clinton Community College" }, + { "value": "154907", "label": "Cloud County Community College" }, + { "value": "234951", "label": "Clover Park Technical College" }, + { "value": "187639", "label": "Clovis Community College" }, + { "value": "175519", "label": "Coahoma Community College" }, + { "value": "223320", "label": "Coastal Bend College" }, + { "value": "198330", "label": "Coastal Carolina Community College" }, + { "value": "218724", "label": "Coastal Carolina University" }, + { "value": "485458", "label": "Coastal Pines Technical College-Waycross" }, + { "value": "112385", "label": "Coastline Community College" }, + { "value": "104425", "label": "Cochise County Community College District" }, + { "value": "190071", "label": "Cochran School of Nursing" }, + { "value": "404426", "label": "Coconino Community College" }, + { "value": "153144", "label": "Coe College" }, + { "value": "154925", "label": "Coffeyville Community College" }, + { "value": "112394", "label": "Cogswell College" }, + { "value": "217907", "label": "Coker College" }, + { "value": "161086", "label": "Colby College" }, + { "value": "154934", "label": "Colby Community College" }, + { "value": "182634", "label": "Colby-Sawyer College" }, + { + "value": "430935", + "label": "Colegio de Cinematografía Artes y Television" + }, + { "value": "241720", "label": "Colegio Universitario de San Juan" }, + { "value": "112446", "label": "Coleman University" }, + { "value": "190080", "label": "Colgate Rochester Crozer Divinity School" }, + { "value": "190099", "label": "Colgate University" }, + { "value": "169442", "label": "College for Creative Studies" }, + { "value": "108667", "label": "College of Alameda" }, + { "value": "388520", "label": "College of Biblical Studies-Houston" }, + { + "value": "456977", + "label": "College of Business and Technology-Cutler Bay" + }, + { + "value": "449083", + "label": "College of Business and Technology-Flagler" + }, + { + "value": "449092", + "label": "College of Business and Technology-Hialeah" + }, + { + "value": "417318", + "label": "College of Business and Technology-Kendall" + }, + { + "value": "482024", + "label": "College of Business and Technology-Miami Gardens" + }, + { "value": "132851", "label": "College of Central Florida" }, + { "value": "217819", "label": "College of Charleston" }, + { "value": "139250", "label": "College of Coastal Georgia" }, + { "value": "150251", "label": "College of Court Reporting Inc" }, + { "value": "144865", "label": "College of DuPage" }, + { + "value": "392257", + "label": "College of Health Care Professions-Northwest" + }, + { "value": "146472", "label": "College of Lake County" }, + { "value": "118347", "label": "College of Marin" }, + { "value": "413617", "label": "College of Menominee Nation" }, + { "value": "243638", "label": "College of Micronesia-FSM" }, + { "value": "193399", "label": "College of Mount Saint Vincent" }, + { "value": "167394", "label": "College of Our Lady of the Elms" }, + { "value": "174747", "label": "College of Saint Benedict" }, + { "value": "186618", "label": "College of Saint Elizabeth" }, + { "value": "181604", "label": "College of Saint Mary" }, + { "value": "122791", "label": "College of San Mateo" }, + { "value": "142559", "label": "College of Southern Idaho" }, + { "value": "162122", "label": "College of Southern Maryland" }, + { "value": "182005", "label": "College of Southern Nevada" }, + { "value": "231077", "label": "College of St Joseph" }, + { "value": "190558", "label": "College of Staten Island CUNY" }, + { "value": "197814", "label": "College of the Albemarle" }, + { "value": "160959", "label": "College of the Atlantic" }, + { "value": "111461", "label": "College of the Canyons" }, + { "value": "113573", "label": "College of the Desert" }, + { "value": "166124", "label": "College of the Holy Cross" }, + { "value": "226408", "label": "College of the Mainland" }, + { "value": "376695", "label": "College of the Marshall Islands" }, + { "value": "480967", "label": "College of the Muscogee Nation" }, + { "value": "107521", "label": "College of the Ouachitas" }, + { "value": "178697", "label": "College of the Ozarks" }, + { "value": "121707", "label": "College of the Redwoods" }, + { "value": "123217", "label": "College of the Sequoias" }, + { "value": "123484", "label": "College of the Siskiyous" }, + { "value": "455114", "label": "College of Western Idaho" }, + { "value": "231624", "label": "College of William and Mary" }, + { "value": "451705", "label": "CollegeAmerica-Cheyenne" }, + { "value": "448752", "label": "CollegeAmerica-Colorado Springs" }, + { "value": "126872", "label": "CollegeAmerica-Denver" }, + { "value": "103945", "label": "CollegeAmerica-Flagstaff" }, + { "value": "448761", "label": "CollegeAmerica-Fort Collins" }, + { "value": "474890", "label": "CollegeAmerica-Phoenix" }, + { "value": "247834", "label": "Collin County Community College District" }, + { "value": "103723", "label": "Collins College" }, + { "value": "461953", "label": "Colorado Academy of Veterinary Technology" }, + { "value": "126669", "label": "Colorado Christian University" }, + { "value": "126678", "label": "Colorado College" }, + { "value": "367839", "label": "Colorado Heights University" }, + { "value": "127556", "label": "Colorado Mesa University" }, + { "value": "126711", "label": "Colorado Mountain College" }, + { "value": "126748", "label": "Colorado Northwestern Community College" }, + { "value": "381732", "label": "Colorado School of Healing Arts" }, + { "value": "126775", "label": "Colorado School of Mines" }, + { "value": "126784", "label": "Colorado School of Trades" }, + { + "value": "381352", + "label": "Colorado School of Traditional Chinese Medicine" + }, + { "value": "126818", "label": "Colorado State University-Fort Collins" }, + { "value": "476975", "label": "Colorado State University-Global Campus" }, + { "value": "128106", "label": "Colorado State University-Pueblo" }, + { + "value": "126827", + "label": "Colorado Technical University-Colorado Springs" + }, + { + "value": "430087", + "label": "Colorado Technical University-Greenwood Village" + }, + { "value": "444158", "label": "Colorado Technical University-Online" }, + { "value": "402615", "label": "Colorado Technical University-Sioux Falls" }, + { "value": "234979", "label": "Columbia Basin College" }, + { "value": "241304", "label": "Columbia Central University-Caguas" }, + { "value": "404806", "label": "Columbia Central University-Yauco" }, + { "value": "238573", "label": "Columbia College of Nursing" }, + { "value": "144281", "label": "Columbia College-Chicago" }, + { "value": "177065", "label": "Columbia College-Columbia" }, + { "value": "217934", "label": "Columbia College-Columbia" }, + { "value": "455983", "label": "Columbia College-Fairfax" }, + { "value": "112570", "label": "Columbia College-Hollywood" }, + { "value": "112561", "label": "Columbia College-Sonora" }, + { "value": "420556", "label": "Columbia Gorge Community College" }, + { "value": "217925", "label": "Columbia International University" }, + { "value": "450933", "label": "Columbia Southern University" }, + { "value": "219888", "label": "Columbia State Community College" }, + { "value": "139348", "label": "Columbia Theological Seminary" }, + { + "value": "190150", + "label": "Columbia University in the City of New York" + }, + { "value": "190169", "label": "Columbia-Greene Community College" }, + { "value": "202170", "label": "Columbus College of Art and Design" }, + { "value": "202222", "label": "Columbus State Community College" }, + { "value": "139366", "label": "Columbus State University" }, + { "value": "139357", "label": "Columbus Technical College" }, + { "value": "483522", "label": "Comanche Nation College" }, + { "value": "366261", "label": "Commonwealth Institute of Funeral Service" }, + { "value": "212975", "label": "Commonwealth Technical Institute" }, + { "value": "439570", "label": "Community Care College" }, + { "value": "446163", "label": "Community Christian College" }, + { "value": "210605", "label": "Community College of Allegheny County" }, + { "value": "126863", "label": "Community College of Aurora" }, + { "value": "211079", "label": "Community College of Beaver County" }, + { "value": "126942", "label": "Community College of Denver" }, + { "value": "215239", "label": "Community College of Philadelphia" }, + { "value": "217475", "label": "Community College of Rhode Island" }, + { "value": "230861", "label": "Community College of Vermont" }, + { "value": "459417", "label": "Compass College of Cinematic Arts" }, + { "value": "177083", "label": "Conception Seminary College" }, + { "value": "237330", "label": "Concord University" }, + { "value": "126687", "label": "Concorde Career College-Aurora" }, + { "value": "460181", "label": "Concorde Career College-Dallas" }, + { "value": "123679", "label": "Concorde Career College-Garden Grove" }, + { "value": "441742", "label": "Concorde Career College-Grand Prairie" }, + { "value": "155283", "label": "Concorde Career College-Kansas City" }, + { "value": "219903", "label": "Concorde Career College-Memphis" }, + { "value": "124937", "label": "Concorde Career College-North Hollywood" }, + { "value": "208479", "label": "Concorde Career College-Portland" }, + { "value": "460206", "label": "Concorde Career College-San Antonio" }, + { "value": "124706", "label": "Concorde Career College-San Bernardino" }, + { "value": "120661", "label": "Concorde Career College-San Diego" }, + { "value": "133845", "label": "Concorde Career Institute-Jacksonville" }, + { "value": "133854", "label": "Concorde Career Institute-Miramar" }, + { "value": "460190", "label": "Concorde Career Institute-Orlando" }, + { "value": "133863", "label": "Concorde Career Institute-Tampa" }, + { "value": "101073", "label": "Concordia College Alabama" }, + { "value": "173300", "label": "Concordia College at Moorhead" }, + { "value": "190248", "label": "Concordia College-New York" }, + { "value": "177092", "label": "Concordia Seminary" }, + { "value": "150288", "label": "Concordia Theological Seminary" }, + { "value": "169363", "label": "Concordia University-Ann Arbor" }, + { "value": "144351", "label": "Concordia University-Chicago" }, + { "value": "112075", "label": "Concordia University-Irvine" }, + { "value": "180984", "label": "Concordia University-Nebraska" }, + { "value": "208488", "label": "Concordia University-Portland" }, + { "value": "173328", "label": "Concordia University-Saint Paul" }, + { "value": "224004", "label": "Concordia University-Texas" }, + { "value": "238616", "label": "Concordia University-Wisconsin" }, + { "value": "128902", "label": "Connecticut College" }, + { "value": "206996", "label": "Connors State College" }, + { "value": "260354", "label": "Consolidated School of Business-Lancaster" }, + { "value": "211820", "label": "Consolidated School of Business-York" }, + { "value": "112826", "label": "Contra Costa College" }, + { "value": "217961", "label": "Converse College" }, + { "value": "165495", "label": "Conway School of Landscape Design" }, + { + "value": "190372", + "label": "Cooper Union for the Advancement of Science and Art" + }, + { "value": "175573", "label": "Copiah-Lincoln Community College" }, + { "value": "395362", "label": "Copper Mountain Community College" }, + { "value": "162283", "label": "Coppin State University" }, + { "value": "210331", "label": "Corban University" }, + { "value": "153162", "label": "Cornell College" }, + { "value": "190415", "label": "Cornell University" }, + { "value": "170037", "label": "Cornerstone University" }, + { "value": "190442", "label": "Corning Community College" }, + { "value": "235024", "label": "Cornish College of the Arts" }, + { + "value": "106795", + "label": "Cossatot Community College of the University of Arkansas" + }, + { "value": "113096", "label": "Cosumnes River College" }, + { "value": "177117", "label": "Cottey College" }, + { "value": "184180", "label": "County College of Morris" }, + { "value": "224183", "label": "Court Reporting Institute of Dallas" }, + { "value": "139393", "label": "Covenant College" }, + { "value": "177126", "label": "Covenant Theological Seminary" }, + { "value": "154952", "label": "Cowley County Community College" }, + { "value": "176770", "label": "Cox College" }, + { "value": "144485", "label": "Coyne College" }, + { "value": "113111", "label": "Crafton Hills College" }, + { "value": "169424", "label": "Cranbrook Academy of Art" }, + { "value": "198367", "label": "Craven Community College" }, + { "value": "181002", "label": "Creighton University" }, + { "value": "475608", "label": "Criswell College" }, + { "value": "439613", "label": "Crossroads Bible College" }, + { "value": "174206", "label": "Crossroads College" }, + { "value": "177135", "label": "Crowder College" }, + { "value": "106810", "label": "Crowley's Ridge College" }, + { "value": "174862", "label": "Crown College" }, + { "value": "113193", "label": "Cuesta College" }, + { "value": "444565", "label": "Culinary Institute Inc" }, + { "value": "190503", "label": "Culinary Institute of America" }, + { "value": "177144", "label": "Culver-Stockton College" }, + { "value": "184205", "label": "Cumberland County College" }, + { "value": "219949", "label": "Cumberland University" }, + { "value": "190512", "label": "CUNY Bernard M Baruch College" }, + { + "value": "190521", + "label": "CUNY Borough of Manhattan Community College" + }, + { "value": "190530", "label": "CUNY Bronx Community College" }, + { "value": "190549", "label": "CUNY Brooklyn College" }, + { "value": "190567", "label": "CUNY City College" }, + { + "value": "190576", + "label": "CUNY Graduate School and University Center" + }, + { "value": "190585", "label": "CUNY Hostos Community College" }, + { "value": "190594", "label": "CUNY Hunter College" }, + { "value": "190600", "label": "CUNY John Jay College of Criminal Justice" }, + { "value": "190619", "label": "CUNY Kingsborough Community College" }, + { "value": "190628", "label": "CUNY LaGuardia Community College" }, + { "value": "190637", "label": "CUNY Lehman College" }, + { "value": "190646", "label": "CUNY Medgar Evers College" }, + { "value": "190655", "label": "CUNY New York City College of Technology" }, + { "value": "190664", "label": "CUNY Queens College" }, + { "value": "190673", "label": "CUNY Queensborough Community College" }, + { "value": "190682", "label": "CUNY School of Law" }, + { "value": "190691", "label": "CUNY York College" }, + { "value": "165529", "label": "Curry College" }, + { "value": "211893", "label": "Curtis Institute of Music" }, + { "value": "202356", "label": "Cuyahoga Community College District" }, + { "value": "113218", "label": "Cuyamaca College" }, + { "value": "113236", "label": "Cypress College" }, + { "value": "231873", "label": "Dabney S Lancaster Community College" }, + { "value": "458797", "label": "Dade Medical College-Hollywood" }, + { "value": "458247", "label": "Dade Medical College-Homestead" }, + { "value": "476391", "label": "Dade Medical College-Jacksonville" }, + { "value": "444574", "label": "Dade Medical College-Miami" }, + { "value": "454175", "label": "Dade Medical College-Miami Lakes" }, + { "value": "476382", "label": "Dade Medical College-West Palm Beach" }, + { "value": "190725", "label": "Daemen College" }, + { "value": "200314", "label": "Dakota College at Bottineau" }, + { "value": "173416", "label": "Dakota County Technical College" }, + { "value": "219082", "label": "Dakota State University" }, + { "value": "219091", "label": "Dakota Wesleyan University" }, + { "value": "224226", "label": "Dallas Baptist University" }, + { "value": "224244", "label": "Dallas Christian College" }, + { "value": "224271", "label": "Dallas Institute of Funeral Service" }, + { "value": "437732", "label": "Dallas Nursing Institute" }, + { "value": "224305", "label": "Dallas Theological Seminary" }, + { "value": "139463", "label": "Dalton State College" }, + { "value": "182661", "label": "Daniel Webster College" }, + { "value": "144564", "label": "Danville Area Community College" }, + { "value": "231882", "label": "Danville Community College" }, + { + "value": "455178", + "label": "Daoist Traditions College of Chinese Medical Arts" + }, + { "value": "182670", "label": "Dartmouth College" }, + { "value": "138691", "label": "Darton State College" }, + { "value": "169479", "label": "Davenport University" }, + { "value": "198385", "label": "Davidson College" }, + { "value": "198376", "label": "Davidson County Community College" }, + { "value": "237358", "label": "Davis & Elkins College" }, + { "value": "194569", "label": "Davis College-Johnson City" }, + { "value": "202435", "label": "Davis College-Toledo" }, + { "value": "180151", "label": "Dawson Community College" }, + { "value": "447476", "label": "Daymar College-Bellevue" }, + { "value": "363439", "label": "Daymar College-Bowling Green" }, + { "value": "205568", "label": "Daymar College-Chillicothe" }, + { "value": "205531", "label": "Daymar College-Jackson" }, + { "value": "205559", "label": "Daymar College-Lancaster" }, + { "value": "406219", "label": "Daymar College-Louisville-Louisville" }, + { "value": "449302", "label": "Daymar College-Madisonville" }, + { "value": "205522", "label": "Daymar College-New Boston" }, + { "value": "458557", "label": "Daymar College-Online" }, + { "value": "157465", "label": "Daymar College-Owensboro" }, + { "value": "156903", "label": "Daymar College-Paducah Main" }, + { "value": "368443", "label": "Daymar Institute-Clarksville" }, + { "value": "444255", "label": "Daymar Institute-Murfreesboro" }, + { "value": "220002", "label": "Daymar Institute-Nashville" }, + { "value": "447014", "label": "Daytona College" }, + { "value": "133386", "label": "Daytona State College" }, + { "value": "113333", "label": "De Anza College" }, + { "value": "165574", "label": "Dean College" }, + { "value": "211909", "label": "Dean Institute of Technology" }, + { "value": "202514", "label": "Defiance College" }, + { "value": "224350", "label": "Del Mar College" }, + { "value": "432524", "label": "Delaware College of Art and Design" }, + { "value": "211927", "label": "Delaware County Community College" }, + { "value": "130934", "label": "Delaware State University" }, + { + "value": "130891", + "label": "Delaware Technical Community College-Owens" + }, + { + "value": "130916", + "label": "Delaware Technical Community College-Stanton/Wilmington" + }, + { + "value": "130907", + "label": "Delaware Technical Community College-Terry" + }, + { "value": "211981", "label": "Delaware Valley University" }, + { "value": "158662", "label": "Delgado Community College" }, + { + "value": "113537", + "label": "Dell'Arte International School of Physical Theatre" + }, + { "value": "169521", "label": "Delta College" }, + { "value": "366270", "label": "Delta College of Arts & Technology" }, + { "value": "158723", "label": "Delta School of Business and Technology" }, + { "value": "175616", "label": "Delta State University" }, + { "value": "202523", "label": "Denison University" }, + { "value": "217989", "label": "Denmark Technical College" }, + { "value": "454856", "label": "Denver School of Nursing" }, + { "value": "126979", "label": "Denver Seminary" }, + { "value": "144740", "label": "DePaul University" }, + { "value": "150400", "label": "DePauw University" }, + { "value": "153214", "label": "Des Moines Area Community College" }, + { + "value": "154156", + "label": "Des Moines University-Osteopathic Medical Center" + }, + { "value": "210739", "label": "DeSales University" }, + { "value": "113582", "label": "Design Institute of San Diego" }, + { "value": "482413", "label": "DeVry College of New York" }, + { "value": "482422", "label": "DeVry University-Arizona" }, + { "value": "482431", "label": "DeVry University-California" }, + { "value": "482440", "label": "DeVry University-Colorado" }, + { "value": "482459", "label": "DeVry University-Florida" }, + { "value": "482468", "label": "DeVry University-Georgia" }, + { "value": "482477", "label": "DeVry University-Illinois" }, + { "value": "482486", "label": "DeVry University-Indiana" }, + { "value": "482501", "label": "DeVry University-Maryland" }, + { "value": "482510", "label": "DeVry University-Michigan" }, + { "value": "482529", "label": "DeVry University-Minnesota" }, + { "value": "482538", "label": "DeVry University-Missouri" }, + { "value": "482547", "label": "DeVry University-Nevada" }, + { "value": "482556", "label": "DeVry University-New Jersey" }, + { "value": "482565", "label": "DeVry University-North Carolina" }, + { "value": "482574", "label": "DeVry University-Ohio" }, + { "value": "482583", "label": "DeVry University-Oklahoma" }, + { "value": "482592", "label": "DeVry University-Oregon" }, + { "value": "482608", "label": "DeVry University-Pennsylvania" }, + { "value": "482617", "label": "DeVry University-Tennessee" }, + { "value": "482635", "label": "DeVry University-Texas" }, + { "value": "482644", "label": "DeVry University-Utah" }, + { "value": "482653", "label": "DeVry University-Virginia" }, + { "value": "482662", "label": "DeVry University-Washington" }, + { "value": "482671", "label": "DeVry University-Wisconsin" }, + { "value": "443562", "label": "Dewey University-Hato Rey-Hato Rey" }, + { "value": "113634", "label": "Diablo Valley College" }, + { "value": "212009", "label": "Dickinson College" }, + { "value": "200059", "label": "Dickinson State University" }, + { "value": "443410", "label": "DigiPen Institute of Technology" }, + { "value": "451060", "label": "Digital Media Arts College" }, + { "value": "158802", "label": "Dillard University" }, + { "value": "105297", "label": "Dine College" }, + { "value": "153241", "label": "Divine Word College" }, + { "value": "230171", "label": "Dixie State University" }, + { "value": "181020", "label": "Doane University-Arts & Sciences" }, + { + "value": "448284", + "label": "Doane University-Graduate and Professional Studies" + }, + { "value": "154998", "label": "Dodge City Community College" }, + { "value": "190761", "label": "Dominican College of Blauvelt" }, + { "value": "113704", "label": "Dominican School of Philosophy & Theology" }, + { "value": "148496", "label": "Dominican University" }, + { "value": "113698", "label": "Dominican University of California" }, + { "value": "122117", "label": "Dongguk University-Los Angeles" }, + { "value": "155007", "label": "Donnelly College" }, + { "value": "153250", "label": "Dordt College" }, + { "value": "212045", "label": "Douglas Education Center" }, + { "value": "190770", "label": "Dowling College" }, + { "value": "153269", "label": "Drake University" }, + { "value": "184348", "label": "Drew University" }, + { "value": "212054", "label": "Drexel University" }, + { "value": "177214", "label": "Drury University" }, + { "value": "212072", "label": "Du Bois Business College-Du Bois" }, + { "value": "439303", "label": "Du Bois Business College-Huntingdon" }, + { "value": "439312", "label": "Du Bois Business College-Oil City" }, + { "value": "198419", "label": "Duke University" }, + { "value": "173489", "label": "Duluth Business University" }, + { "value": "175227", "label": "Dunwoody College of Technology" }, + { "value": "212106", "label": "Duquesne University" }, + { "value": "198455", "label": "Durham Technical Community College" }, + { "value": "190840", "label": "Dutchess Community College" }, + { "value": "220057", "label": "Dyersburg State Community College" }, + { "value": "190716", "label": "D'Youville College" }, + { "value": "447421", "label": "Eagle Gate College-Layton" }, + { "value": "230366", "label": "Eagle Gate College-Murray" }, + { "value": "447625", "label": "Eagle Gate College-Salt Lake City" }, + { "value": "150455", "label": "Earlham College" }, + { "value": "106883", "label": "East Arkansas Community College" }, + { "value": "198464", "label": "East Carolina University" }, + { "value": "177250", "label": "East Central College" }, + { "value": "175643", "label": "East Central Community College" }, + { "value": "207041", "label": "East Central University" }, + { "value": "139621", "label": "East Georgia State College" }, + { "value": "113856", "label": "East Los Angeles College" }, + { "value": "175652", "label": "East Mississippi Community College" }, + { + "value": "413802", + "label": "East San Gabriel Valley Regional Occupational Program" + }, + { + "value": "212115", + "label": "East Stroudsburg University of Pennsylvania" + }, + { "value": "220075", "label": "East Tennessee State University" }, + { "value": "224527", "label": "East Texas Baptist University" }, + { "value": "439394", "label": "East West College of Natural Medicine" }, + { "value": "104577", "label": "Eastern Arizona College" }, + { "value": "129215", "label": "Eastern Connecticut State University" }, + { "value": "132693", "label": "Eastern Florida State College" }, + { "value": "203331", "label": "Eastern Gateway Community College" }, + { "value": "142179", "label": "Eastern Idaho Technical College" }, + { "value": "144892", "label": "Eastern Illinois University" }, + { "value": "448354", "label": "Eastern International College-Belleville" }, + { "value": "421878", "label": "Eastern International College-Jersey City" }, + { "value": "153311", "label": "Eastern Iowa Community College District" }, + { "value": "156620", "label": "Eastern Kentucky University" }, + { "value": "161138", "label": "Eastern Maine Community College" }, + { "value": "232043", "label": "Eastern Mennonite University" }, + { "value": "169798", "label": "Eastern Michigan University" }, + { "value": "165644", "label": "Eastern Nazarene College" }, + { "value": "187648", "label": "Eastern New Mexico University-Main Campus" }, + { + "value": "187666", + "label": "Eastern New Mexico University-Roswell Campus" + }, + { + "value": "383996", + "label": "Eastern New Mexico University-Ruidoso Campus" + }, + { "value": "207050", "label": "Eastern Oklahoma State College" }, + { "value": "208646", "label": "Eastern Oregon University" }, + { "value": "232052", "label": "Eastern Shore Community College" }, + { "value": "212133", "label": "Eastern University" }, + { "value": "441858", "label": "Eastern Virginia Career College" }, + { "value": "231970", "label": "Eastern Virginia Medical School" }, + { "value": "235097", "label": "Eastern Washington University" }, + { + "value": "438708", + "label": "Eastern West Virginia Community and Technical College" + }, + { "value": "240596", "label": "Eastern Wyoming College" }, + { "value": "224572", "label": "Eastfield College" }, + { "value": "144883", "label": "East-West University" }, + { "value": "183488", "label": "Eastwick College-Hackensack" }, + { "value": "184959", "label": "Eastwick College-Ramsey" }, + { "value": "446233", "label": "Ecclesia College" }, + { "value": "133492", "label": "Eckerd College" }, + { "value": "460215", "label": "Ecotech Institute" }, + { "value": "248934", "label": "ECPI University" }, + { "value": "247162", "label": "Ecumenical Theological Seminary" }, + { "value": "177278", "label": "Eden Theological Seminary" }, + { "value": "198491", "label": "Edgecombe Community College" }, + { "value": "238661", "label": "Edgewood College" }, + { "value": "376321", "label": "EDIC College" }, + { "value": "212160", "label": "Edinboro University of Pennsylvania" }, + { "value": "202648", "label": "Edison State Community College" }, + { "value": "235103", "label": "Edmonds Community College" }, + { + "value": "243832", + "label": "EDP Univeristy of Puerto Rico Inc-San Juan" + }, + { + "value": "241836", + "label": "EDP University of Puerto Rico Inc-San Sebastian" + }, + { + "value": "442806", + "label": "Edward Via College of Osteopathic Medicine" + }, + { "value": "133526", "label": "Edward Waters College" }, + { "value": "112686", "label": "El Camino College-Compton Center" }, + { "value": "113980", "label": "El Camino Community College District" }, + { "value": "224615", "label": "El Centro College" }, + { "value": "224642", "label": "El Paso Community College" }, + { "value": "144944", "label": "Elgin Community College" }, + { "value": "198507", "label": "Elizabeth City State University" }, + { "value": "212197", "label": "Elizabethtown College" }, + { + "value": "480134", + "label": "Elizabethtown College School of Continuing and Professional Studies" + }, + { + "value": "156648", + "label": "Elizabethtown Community and Technical College" + }, + { "value": "153296", "label": "Ellsworth Community College" }, + { "value": "144962", "label": "Elmhurst College" }, + { "value": "190974", "label": "Elmira Business Institute" }, + { "value": "190983", "label": "Elmira College" }, + { "value": "198516", "label": "Elon University" }, + { + "value": "133553", + "label": "Embry-Riddle Aeronautical University-Daytona Beach" + }, + { + "value": "104586", + "label": "Embry-Riddle Aeronautical University-Prescott" + }, + { + "value": "426314", + "label": "Embry-Riddle Aeronautical University-Worldwide" + }, + { "value": "165662", "label": "Emerson College" }, + { "value": "220136", "label": "Emmanuel Christian Seminary" }, + { "value": "165671", "label": "Emmanuel College-Boston" }, + { "value": "139630", "label": "Emmanuel College-Franklin Springs" }, + { "value": "153302", "label": "Emmaus Bible College" }, + { "value": "232025", "label": "Emory & Henry College" }, + { "value": "139658", "label": "Emory University" }, + { + "value": "114114", + "label": "Emperor's College of Traditional Oriental Medicine" + }, + { "value": "114123", "label": "Empire College" }, + { "value": "155025", "label": "Emporia State University" }, + { "value": "165699", "label": "Endicott College" }, + { "value": "101143", "label": "Enterprise State Community College" }, + { "value": "124487", "label": "Epic Bible College" }, + { "value": "165705", "label": "Episcopal Divinity School" }, + { + "value": "224712", + "label": "Episcopal Theological Seminary of the Southwest" + }, + { "value": "191083", "label": "Erie Community College" }, + { "value": "212434", "label": "Erie Institute of Technology Inc" }, + { "value": "409254", "label": "Erikson Institute" }, + { "value": "217998", "label": "Erskine College" }, + { "value": "241951", "label": "Escuela de Artes Plasticas de Puerto Rico" }, + { "value": "184481", "label": "Essex County College" }, + { "value": "384333", "label": "Estrella Mountain Community College" }, + { "value": "200590", "label": "ETI Technical College" }, + { "value": "144971", "label": "Eureka College" }, + { "value": "177339", "label": "Evangel University" }, + { "value": "212443", "label": "Evangelical Theological Seminary" }, + { "value": "371982", "label": "Everest College-Anaheim" }, + { "value": "443854", "label": "Everest College-Arlington" }, + { "value": "366544", "label": "Everest College-Aurora" }, + { "value": "234739", "label": "Everest College-Bremerton" }, + { "value": "438647", "label": "Everest College-Chesapeake" }, + { "value": "372037", "label": "Everest College-City of Industry" }, + { "value": "126401", "label": "Everest College-Colorado Springs" }, + { "value": "442790", "label": "Everest College-Dallas" }, + { "value": "363590", "label": "Everest College-Everett" }, + { "value": "445197", "label": "Everest College-Fort Worth" }, + { "value": "460358", "label": "Everest College-Fort Worth South" }, + { "value": "182148", "label": "Everest College-Henderson" }, + { "value": "445470", "label": "Everest College-McLean" }, + { "value": "447236", "label": "Everest College-Mesa" }, + { "value": "232502", "label": "Everest College-Newport News" }, + { "value": "440299", "label": "Everest College-Ontario Metro" }, + { "value": "103644", "label": "Everest College-Phoenix" }, + { "value": "210359", "label": "Everest College-Portland" }, + { "value": "119359", "label": "Everest College-Reseda" }, + { "value": "230472", "label": "Everest College-Salt Lake City" }, + { "value": "119508", "label": "Everest College-San Bernardino" }, + { "value": "179070", "label": "Everest College-Springfield" }, + { "value": "444024", "label": "Everest College-Tacoma" }, + { "value": "127787", "label": "Everest College-Thornton" }, + { "value": "236993", "label": "Everest College-Vancouver" }, + { "value": "368805", "label": "Everest College-West Los Angeles" }, + { "value": "237604", "label": "Everest Institute-Cross Lanes" }, + { "value": "409670", "label": "Everest Institute-Kendall" }, + { "value": "443748", "label": "Everest Institute-Norcross" }, + { "value": "135957", "label": "Everest Institute-North Miami" }, + { "value": "212090", "label": "Everest Institute-Pittsburgh" }, + { "value": "194967", "label": "Everest Institute-Rochester" }, + { "value": "260293", "label": "Everest University-Brandon" }, + { "value": "438902", "label": "Everest University-Jacksonville" }, + { "value": "367909", "label": "Everest University-Lakeland" }, + { "value": "137810", "label": "Everest University-Largo" }, + { "value": "420006", "label": "Everest University-Melbourne" }, + { "value": "136288", "label": "Everest University-North Orlando" }, + { "value": "445434", "label": "Everest University-Orange Park" }, + { "value": "134149", "label": "Everest University-Pompano Beach" }, + { "value": "390701", "label": "Everest University-South Orlando" }, + { "value": "137801", "label": "Everest University-Tampa" }, + { "value": "235149", "label": "Everett Community College" }, + { "value": "385619", "label": "Everglades University" }, + { "value": "114266", "label": "Evergreen Valley College" }, + { "value": "196680", "label": "Excelsior College" }, + { "value": "447458", "label": "Expression College for Digital Arts" }, + { "value": "129242", "label": "Fairfield University" }, + { + "value": "184694", + "label": "Fairleigh Dickinson University-College at Florham" + }, + { + "value": "184603", + "label": "Fairleigh Dickinson University-Metropolitan Campus" + }, + { "value": "237367", "label": "Fairmont State University" }, + { + "value": "153320", + "label": "Faith Baptist Bible College and Theological Seminary" + }, + { "value": "443049", "label": "Faith Evangelical College & Seminary" }, + { "value": "212452", "label": "Faith Theological Seminary" }, + { "value": "443058", "label": "Family of Faith College" }, + { "value": "196042", "label": "Farmingdale State College" }, + { + "value": "114354", + "label": "Fashion Institute of Design & Merchandising-Los Angeles" + }, + { + "value": "248846", + "label": "Fashion Institute of Design & Merchandising-San Diego" + }, + { + "value": "114390", + "label": "Fashion Institute of Design & Merchandising-San Francisco" + }, + { "value": "191126", "label": "Fashion Institute of Technology" }, + { "value": "101189", "label": "Faulkner University" }, + { "value": "198543", "label": "Fayetteville State University" }, + { "value": "198534", "label": "Fayetteville Technical Community College" }, + { "value": "114433", "label": "Feather River Community College District" }, + { "value": "184612", "label": "Felician University" }, + { "value": "169910", "label": "Ferris State University" }, + { "value": "232089", "label": "Ferrum College" }, + { "value": "114549", "label": "Fielding Graduate University" }, + { "value": "436599", "label": "FINE Mortuary College" }, + { "value": "191199", "label": "Finger Lakes Community College" }, + { "value": "475422", "label": "Finger Lakes Health College of Nursing" }, + { "value": "172440", "label": "Finlandia University" }, + { "value": "165802", "label": "Fisher College" }, + { "value": "220181", "label": "Fisk University" }, + { "value": "165820", "label": "Fitchburg State University" }, + { "value": "114585", "label": "Five Branches University" }, + { "value": "191205", "label": "Five Towns College" }, + { "value": "133711", "label": "Flagler College-St Augustine" }, + { "value": "444990", "label": "Flagler College-Tallahassee" }, + { "value": "180197", "label": "Flathead Valley Community College" }, + { "value": "160481", "label": "Fletcher Technical Community College" }, + { "value": "155052", "label": "Flint Hills Technical College" }, + { "value": "218025", "label": "Florence-Darlington Technical College" }, + { + "value": "133650", + "label": "Florida Agricultural and Mechanical University" + }, + { "value": "133669", "label": "Florida Atlantic University" }, + { "value": "133997", "label": "Florida Career College-Miami" }, + { "value": "434715", "label": "Florida Coastal School of Law" }, + { "value": "133809", "label": "Florida College" }, + { "value": "434441", "label": "Florida College of Integrative Medicine" }, + { + "value": "438294", + "label": "Florida College of Natural Health-Bradenton" + }, + { + "value": "438285", + "label": "Florida College of Natural Health-Maitland" + }, + { "value": "420103", "label": "Florida College of Natural Health-Miami" }, + { + "value": "387925", + "label": "Florida College of Natural Health-Pompano Beach" + }, + { "value": "135160", "label": "Florida Gateway College" }, + { "value": "433660", "label": "Florida Gulf Coast University" }, + { "value": "133881", "label": "Florida Institute of Technology" }, + { "value": "480569", "label": "Florida Institute of Technology-Online" }, + { "value": "133951", "label": "Florida International University" }, + { "value": "133960", "label": "Florida Keys Community College" }, + { "value": "133979", "label": "Florida Memorial University" }, + { "value": "408844", "label": "Florida National University-Main Campus" }, + { "value": "134079", "label": "Florida Southern College" }, + { "value": "133508", "label": "Florida SouthWestern State College" }, + { "value": "133702", "label": "Florida State College at Jacksonville" }, + { "value": "134097", "label": "Florida State University" }, + { "value": "134112", "label": "Florida Technical College" }, + { "value": "444219", "label": "Folsom Lake College" }, + { "value": "380368", "label": "Fond du Lac Tribal and Community College" }, + { "value": "177418", "label": "Fontbonne University" }, + { "value": "114716", "label": "Foothill College" }, + { "value": "191241", "label": "Fordham University" }, + { + "value": "177427", + "label": "Forest Institute of Professional Psychology" + }, + { "value": "218043", "label": "Forrest College" }, + { "value": "198552", "label": "Forsyth Technical Community College" }, + { "value": "155061", "label": "Fort Hays State University" }, + { "value": "127185", "label": "Fort Lewis College" }, + { "value": "180212", "label": "Fort Peck Community College" }, + { "value": "155098", "label": "Fort Scott Community College" }, + { "value": "139719", "label": "Fort Valley State University" }, + { "value": "439738", "label": "Fortis College-Baton Rouge" }, + { "value": "205179", "label": "Fortis College-Centerville" }, + { "value": "450067", "label": "Fortis College-Cincinnati" }, + { "value": "460020", "label": "Fortis College-Columbia" }, + { "value": "450058", "label": "Fortis College-Columbus" }, + { "value": "480143", "label": "Fortis College-Cutler Bay" }, + { "value": "204307", "label": "Fortis College-Cuyahoga Falls" }, + { "value": "458681", "label": "Fortis College-Indianapolis" }, + { "value": "451909", "label": "Fortis College-Landover" }, + { "value": "447360", "label": "Fortis College-Largo" }, + { "value": "371052", "label": "Fortis College-Mobile" }, + { "value": "455488", "label": "Fortis College-Montgomery-Montgomery" }, + { "value": "233329", "label": "Fortis College-Norfolk" }, + { "value": "439792", "label": "Fortis College-Orange Park" }, + { "value": "456180", "label": "Fortis College-Phoenix" }, + { "value": "201399", "label": "Fortis College-Ravenna" }, + { "value": "382957", "label": "Fortis College-Richmond" }, + { "value": "456454", "label": "Fortis College-Salt Lake City" }, + { "value": "372921", "label": "Fortis College-Smyrna" }, + { "value": "132806", "label": "Fortis College-Winter Park" }, + { "value": "442745", "label": "Fortis Institute" }, + { "value": "455628", "label": "Fortis Institute-Birmingham" }, + { "value": "418870", "label": "Fortis Institute-Cookeville" }, + { "value": "216418", "label": "Fortis Institute-Erie" }, + { "value": "443438", "label": "Fortis Institute-Fort Lauderdale" }, + { "value": "249609", "label": "Fortis Institute-Forty Fort" }, + { "value": "445753", "label": "Fortis Institute-Miami" }, + { "value": "452124", "label": "Fortis Institute-Nashville" }, + { "value": "455479", "label": "Fortis Institute-Pensacola" }, + { "value": "445744", "label": "Fortis Institute-Port Saint Lucie" }, + { "value": "385503", "label": "Fortis Institute-Scranton" }, + { "value": "221795", "label": "Fountainhead College of Technology" }, + { "value": "415774", "label": "Four-D College" }, + { "value": "145239", "label": "Fox College" }, + { "value": "238722", "label": "Fox Valley Technical College" }, + { "value": "165866", "label": "Framingham State University" }, + { "value": "218061", "label": "Francis Marion University" }, + { "value": "114734", "label": "Franciscan School of Theology" }, + { "value": "205957", "label": "Franciscan University of Steubenville" }, + { "value": "104665", "label": "Frank Lloyd Wright School of Architecture" }, + { "value": "224891", "label": "Frank Phillips College" }, + { "value": "212577", "label": "Franklin and Marshall College" }, + { "value": "150604", "label": "Franklin College" }, + { "value": "182795", "label": "Franklin Pierce University" }, + { "value": "202806", "label": "Franklin University" }, + { "value": "441982", "label": "Franklin W Olin College of Engineering" }, + { "value": "162557", "label": "Frederick Community College" }, + { "value": "220215", "label": "Freed-Hardeman University" }, + { "value": "372073", "label": "Fremont College" }, + { "value": "114789", "label": "Fresno City College" }, + { "value": "114813", "label": "Fresno Pacific University" }, + { "value": "155089", "label": "Friends University" }, + { "value": "127200", "label": "Front Range Community College" }, + { "value": "403469", "label": "Frontier Community College" }, + { "value": "156727", "label": "Frontier Nursing University" }, + { "value": "162584", "label": "Frostburg State University" }, + { "value": "134237", "label": "Full Sail University" }, + { "value": "114840", "label": "Fuller Theological Seminary in California" }, + { "value": "114859", "label": "Fullerton College" }, + { "value": "191302", "label": "Fulton-Montgomery Community College" }, + { "value": "218070", "label": "Furman University" }, + { "value": "481030", "label": "Future Generations Graduate School" }, + { "value": "101240", "label": "Gadsden State Community College" }, + { "value": "452948", "label": "Galen College of Nursing-Cincinnati" }, + { "value": "156471", "label": "Galen College of Nursing-Louisville" }, + { "value": "406033", "label": "Galen College of Nursing-San Antonio" }, + { "value": "406024", "label": "Galen College of Nursing-Tampa Bay" }, + { "value": "131450", "label": "Gallaudet University" }, + { "value": "205513", "label": "Gallipolis Career College" }, + { "value": "224961", "label": "Galveston College" }, + { "value": "212601", "label": "Gannon University" }, + { "value": "155104", "label": "Garden City Community College" }, + { "value": "198561", "label": "Gardner-Webb University" }, + { "value": "162609", "label": "Garrett College" }, + { "value": "145275", "label": "Garrett-Evangelical Theological Seminary" }, + { "value": "198570", "label": "Gaston College" }, + { "value": "157438", "label": "Gateway Community and Technical College" }, + { "value": "130396", "label": "Gateway Community College-New Haven" }, + { "value": "105145", "label": "GateWay Community College-Phoenix" }, + { "value": "238759", "label": "Gateway Technical College" }, + { "value": "114938", "label": "Gavilan College" }, + { "value": "191339", "label": "Genesee Community College" }, + { "value": "212656", "label": "Geneva College" }, + { + "value": "101286", + "label": "George C Wallace State Community College-Dothan" + }, + { + "value": "101295", + "label": "George C Wallace State Community College-Hanceville" + }, + { + "value": "101301", + "label": "George C Wallace State Community College-Selma" + }, + { "value": "208822", "label": "George Fox University" }, + { "value": "232186", "label": "George Mason University" }, + { "value": "131469", "label": "George Washington University" }, + { "value": "156745", "label": "Georgetown College" }, + { "value": "131496", "label": "Georgetown University" }, + { "value": "461236", "label": "Georgia Christian University" }, + { "value": "139861", "label": "Georgia College and State University" }, + { "value": "447689", "label": "Georgia Gwinnett College" }, + { "value": "139700", "label": "Georgia Highlands College" }, + { + "value": "139755", + "label": "Georgia Institute of Technology-Main Campus" + }, + { "value": "485111", "label": "Georgia Military College-Milledgeville" }, + { "value": "139384", "label": "Georgia Northwestern Technical College" }, + { "value": "244437", "label": "Georgia Perimeter College" }, + { "value": "244446", "label": "Georgia Piedmont Technical College" }, + { "value": "139931", "label": "Georgia Southern University" }, + { "value": "139764", "label": "Georgia Southwestern State University" }, + { "value": "139940", "label": "Georgia State University" }, + { "value": "184773", "label": "Georgian Court University" }, + { "value": "232195", "label": "Germanna Community College" }, + { "value": "212674", "label": "Gettysburg College" }, + { "value": "169974", "label": "Glen Oaks Community College" }, + { "value": "104708", "label": "Glendale Community College-Glendale" }, + { "value": "115001", "label": "Glendale Community College-Glendale" }, + { "value": "237385", "label": "Glenville State College" }, + { "value": "455390", "label": "Global Health College" }, + { "value": "188465", "label": "Globe Institute of Technology" }, + { "value": "466514", "label": "Globe University-Appleton" }, + { "value": "456816", "label": "Globe University-Eau Claire" }, + { "value": "458751", "label": "Globe University–Green Bay" }, + { "value": "458991", "label": "Globe University-La Crosse" }, + { "value": "458733", "label": "Globe University-Madison East" }, + { "value": "458760", "label": "Globe University–Madison West" }, + { "value": "456834", "label": "Globe University-Minneapolis" }, + { "value": "456807", "label": "Globe University-Sioux Falls" }, + { "value": "458779", "label": "Globe University–Wausau" }, + { "value": "173629", "label": "Globe University-Woodbury" }, + { "value": "230889", "label": "Goddard College" }, + { "value": "202903", "label": "Gods Bible School and College" }, + { "value": "169992", "label": "Gogebic Community College" }, + { "value": "115083", "label": "Golden Gate University-San Francisco" }, + { "value": "115126", "label": "Golden West College" }, + { "value": "130989", "label": "Goldey-Beacom College" }, + { "value": "430157", "label": "Golf Academy of America-Altamonte Springs" }, + { "value": "122366", "label": "Golf Academy of America-Carlsbad" }, + { "value": "476337", "label": "Golf Academy of America-Farmers Branch" }, + { "value": "434690", "label": "Golf Academy of America-Myrtle Beach" }, + { "value": "430166", "label": "Golf Academy of America-Phoenix" }, + { "value": "235316", "label": "Gonzaga University" }, + { + "value": "202912", + "label": "Good Samaritan College of Nursing and Health Science" + }, + { "value": "132523", "label": "Gooding Institute of Nurse Anesthesia" }, + { "value": "129154", "label": "Goodwin College" }, + { "value": "165936", "label": "Gordon College" }, + { "value": "139968", "label": "Gordon State College" }, + { "value": "165945", "label": "Gordon-Conwell Theological Seminary" }, + { "value": "150668", "label": "Goshen College" }, + { "value": "162654", "label": "Goucher College" }, + { "value": "145336", "label": "Governors State University" }, + { "value": "170000", "label": "Grace Bible College" }, + { "value": "150677", "label": "Grace College and Theological Seminary" }, + { "value": "461528", "label": "Grace College of Divinity" }, + { "value": "481058", "label": "Grace Mission University" }, + { "value": "481401", "label": "Grace School of Theology" }, + { "value": "181093", "label": "Grace University" }, + { "value": "153366", "label": "Graceland University-Lamoni" }, + { "value": "483285", "label": "Graduate School USA" }, + { "value": "115214", "label": "Graduate Theological Union" }, + { "value": "159009", "label": "Grambling State University" }, + { "value": "104717", "label": "Grand Canyon University" }, + { "value": "170055", "label": "Grand Rapids Community College" }, + { "value": "170082", "label": "Grand Valley State University" }, + { "value": "153375", "label": "Grand View University" }, + { "value": "183257", "label": "Granite State College" }, + { "value": "442569", "label": "Grantham University" }, + { "value": "212771", "label": "Gratz College" }, + { "value": "235334", "label": "Grays Harbor College" }, + { "value": "225070", "label": "Grayson College" }, + { "value": "182306", "label": "Great Basin College" }, + { "value": "183150", "label": "Great Bay Community College" }, + { + "value": "180249", + "label": "Great Falls College Montana State University" + }, + { "value": "170091", "label": "Great Lakes Christian College" }, + { "value": "213181", "label": "Great Lakes Institute of Technology" }, + { "value": "230898", "label": "Green Mountain College" }, + { "value": "235343", "label": "Green River College" }, + { "value": "165981", "label": "Greenfield Community College" }, + { "value": "198598", "label": "Greensboro College" }, + { "value": "145372", "label": "Greenville College" }, + { "value": "218113", "label": "Greenville Technical College" }, + { "value": "153384", "label": "Grinnell College" }, + { "value": "115296", "label": "Grossmont College" }, + { "value": "212805", "label": "Grove City College" }, + { "value": "240745", "label": "Guam Community College" }, + { "value": "198613", "label": "Guilford College" }, + { "value": "198622", "label": "Guilford Technical Community College" }, + { "value": "134343", "label": "Gulf Coast State College" }, + { "value": "139995", "label": "Gupton Jones College of Funeral Service" }, + { "value": "173647", "label": "Gustavus Adolphus College" }, + { "value": "140003", "label": "Gwinnett College-Lilburn" }, + { "value": "140012", "label": "Gwinnett Technical College" }, + { "value": "212832", "label": "Gwynedd Mercy University" }, + { + "value": "102313", + "label": "H Councill Trenholm State Community College" + }, + { "value": "162690", "label": "Hagerstown Community College" }, + { "value": "198640", "label": "Halifax Community College" }, + { "value": "225201", "label": "Hallmark University" }, + { "value": "191515", "label": "Hamilton College" }, + { "value": "153427", "label": "Hamilton Technical College" }, + { "value": "173665", "label": "Hamline University" }, + { "value": "232256", "label": "Hampden-Sydney College" }, + { "value": "166018", "label": "Hampshire College" }, + { "value": "232265", "label": "Hampton University" }, + { "value": "177542", "label": "Hannibal-LaGrange University" }, + { "value": "150756", "label": "Hanover College" }, + { "value": "212869", "label": "Harcum College" }, + { "value": "107044", "label": "Harding University" }, + { "value": "225247", "label": "Hardin-Simmons University" }, + { "value": "162706", "label": "Harford Community College" }, + { "value": "145460", "label": "Harrington College of Design" }, + { + "value": "212878", + "label": "Harrisburg Area Community College-Harrisburg" + }, + { + "value": "446640", + "label": "Harrisburg University of Science and Technology" + }, + { "value": "458432", "label": "Harrison College-Grove City" }, + { "value": "151166", "label": "Harrison College-Indianapolis" }, + { "value": "468398", "label": "Harrison College-Morrisville" }, + { "value": "177551", "label": "Harris-Stowe State University" }, + { "value": "129491", "label": "Hartford Seminary" }, + { "value": "115393", "label": "Hartnell College" }, + { "value": "191533", "label": "Hartwick College" }, + { "value": "166027", "label": "Harvard University" }, + { "value": "115409", "label": "Harvey Mudd College" }, + { "value": "155140", "label": "Haskell Indian Nations University" }, + { "value": "181127", "label": "Hastings College" }, + { "value": "212911", "label": "Haverford College" }, + { "value": "383190", "label": "Hawaii Community College" }, + { "value": "141644", "label": "Hawaii Pacific University" }, + { "value": "153445", "label": "Hawkeye Community College" }, + { "value": "198668", "label": "Haywood Community College" }, + { "value": "156790", "label": "Hazard Community and Technical College" }, + { + "value": "173683", + "label": "Hazelden Betty Ford Graduate School of Addiction Studies" + }, + { "value": "115533", "label": "Heald College-Concord" }, + { "value": "115472", "label": "Heald College-Fresno" }, + { "value": "371779", "label": "Heald College-Hayward" }, + { "value": "141468", "label": "Heald College-Honolulu" }, + { "value": "459930", "label": "Heald College-Modesto" }, + { "value": "430148", "label": "Heald College-Portland" }, + { "value": "115454", "label": "Heald College-Rancho Cordova" }, + { "value": "363387", "label": "Heald College-Roseville" }, + { "value": "409874", "label": "Heald College-Salinas" }, + { "value": "115515", "label": "Heald College-San Francisco" }, + { "value": "115490", "label": "Heald College-San Jose" }, + { "value": "371760", "label": "Heald College-Stockton" }, + { "value": "384342", "label": "Heartland Community College" }, + { "value": "166045", "label": "Hebrew College" }, + { "value": "145497", "label": "Hebrew Theological College" }, + { + "value": "203067", + "label": "Hebrew Union College-Jewish Institute of Religion" + }, + { "value": "203085", "label": "Heidelberg University" }, + { "value": "180276", "label": "Helena College University of Montana" }, + { "value": "191597", "label": "Helene Fuld College of Nursing" }, + { + "value": "166054", + "label": "Hellenic College-Holy Cross Greek Orthodox School of Theology" + }, + { "value": "156851", "label": "Henderson Community College" }, + { "value": "107071", "label": "Henderson State University" }, + { "value": "107080", "label": "Hendrix College" }, + { "value": "173708", "label": "Hennepin Technical College" }, + { "value": "170240", "label": "Henry Ford College" }, + { "value": "198677", "label": "Heritage Bible College" }, + { "value": "101453", "label": "Heritage Christian University" }, + { "value": "262509", "label": "Heritage College-Denver" }, + { "value": "445814", "label": "Heritage College-Kansas City" }, + { "value": "410070", "label": "Heritage College-Oklahoma City" }, + { "value": "456320", "label": "Heritage College-Wichita" }, + { "value": "135124", "label": "Heritage Institute-Ft Myers" }, + { "value": "372772", "label": "Heritage Institute-Jacksonville" }, + { "value": "235422", "label": "Heritage University" }, + { "value": "191612", "label": "Herkimer County Community College" }, + { "value": "140340", "label": "Herzing University-Atlanta" }, + { "value": "101365", "label": "Herzing University-Birmingham" }, + { "value": "459851", "label": "Herzing University-Brookfield" }, + { "value": "433536", "label": "Herzing University-Kenner" }, + { "value": "459842", "label": "Herzing University-Kenosha" }, + { "value": "240392", "label": "Herzing University-Madison" }, + { "value": "174154", "label": "Herzing University-Minneapolis" }, + { "value": "457022", "label": "Herzing University-Toledo" }, + { "value": "386472", "label": "Herzing University-Winter Park" }, + { "value": "155177", "label": "Hesston College" }, + { "value": "173735", "label": "Hibbing Community College" }, + { "value": "177579", "label": "Hickey College" }, + { "value": "198695", "label": "High Point University" }, + { "value": "145521", "label": "Highland Community College-Freeport" }, + { "value": "155186", "label": "Highland Community College-Highland" }, + { "value": "180081", "label": "Highlands College of Montana Tech" }, + { "value": "235431", "label": "Highline College" }, + { "value": "191621", "label": "Hilbert College" }, + { "value": "225371", "label": "Hill College" }, + { "value": "134495", "label": "Hillsborough Community College" }, + { "value": "170286", "label": "Hillsdale College" }, + { "value": "207157", "label": "Hillsdale Free Will Baptist College" }, + { "value": "175786", "label": "Hinds Community College" }, + { "value": "203128", "label": "Hiram College" }, + { "value": "220312", "label": "Hiwassee College" }, + { "value": "191630", "label": "Hobart William Smith Colleges" }, + { "value": "134510", "label": "Hobe Sound Bible College" }, + { "value": "203155", "label": "Hocking College" }, + { "value": "367884", "label": "Hodges University" }, + { "value": "191649", "label": "Hofstra University" }, + { "value": "232308", "label": "Hollins University" }, + { "value": "175810", "label": "Holmes Community College" }, + { "value": "129534", "label": "Holy Apostles College and Seminary" }, + { "value": "150774", "label": "Holy Cross College" }, + { "value": "212984", "label": "Holy Family University" }, + { "value": "115728", "label": "Holy Names University" }, + { "value": "166133", "label": "Holyoke Community College" }, + { "value": "203386", "label": "Hondros College" }, + { "value": "141680", "label": "Honolulu Community College" }, + { "value": "162760", "label": "Hood College" }, + { "value": "443076", "label": "Hood Theological Seminary" }, + { "value": "170301", "label": "Hope College" }, + { "value": "120537", "label": "Hope International University" }, + { "value": "156860", "label": "Hopkinsville Community College" }, + { "value": "457226", "label": "Horizon University" }, + { "value": "218140", "label": "Horry-Georgetown Technical College" }, + { "value": "191676", "label": "Houghton College" }, + { "value": "129543", "label": "Housatonic Community College" }, + { "value": "225399", "label": "Houston Baptist University" }, + { "value": "225423", "label": "Houston Community College" }, + { "value": "246345", "label": "Houston Graduate School of Theology" }, + { "value": "225520", "label": "Howard College" }, + { "value": "162779", "label": "Howard Community College" }, + { "value": "225548", "label": "Howard Payne University" }, + { "value": "131520", "label": "Howard University" }, + { "value": "184995", "label": "Hudson County Community College" }, + { "value": "191719", "label": "Hudson Valley Community College" }, + { "value": "242112", "label": "Huertas College" }, + { "value": "164368", "label": "Hult International Business School" }, + { "value": "242121", "label": "Humacao Community College" }, + { "value": "115755", "label": "Humboldt State University" }, + { + "value": "115773", + "label": "Humphreys College-Stockton and Modesto Campuses" + }, + { "value": "101435", "label": "Huntingdon College" }, + { "value": "237437", "label": "Huntington Junior College" }, + { "value": "150941", "label": "Huntington University" }, + { "value": "449348", "label": "Huntsville Bible College" }, + { "value": "212993", "label": "Hussian College School of Art" }, + { "value": "161165", "label": "Husson University" }, + { "value": "225575", "label": "Huston-Tillotson University" }, + { "value": "155195", "label": "Hutchinson Community College" }, + { "value": "127839", "label": "IBMC College" }, + { "value": "372329", "label": "IBMC College" }, + { "value": "193405", "label": "Icahn School of Medicine at Mount Sinai" }, + { "value": "437662", "label": "ICDC College" }, + { "value": "242130", "label": "ICPR Junior College-Arecibo" }, + { "value": "243841", "label": "ICPR Junior College-General Institutional" }, + { "value": "460677", "label": "ICPR Junior College-Manati" }, + { "value": "242149", "label": "ICPR Junior College-Mayaguez" }, + { "value": "142276", "label": "Idaho State University" }, + { "value": "483780", "label": "IGlobal University" }, + { "value": "127273", "label": "Iliff School of Theology" }, + { "value": "434584", "label": "Ilisagvik College" }, + { "value": "145682", "label": "Illinois Central College" }, + { "value": "145691", "label": "Illinois College" }, + { "value": "145628", "label": "Illinois College of Optometry" }, + { "value": "145725", "label": "Illinois Institute of Technology" }, + { "value": "145813", "label": "Illinois State University" }, + { "value": "145831", "label": "Illinois Valley Community College" }, + { "value": "145646", "label": "Illinois Wesleyan University" }, + { "value": "213011", "label": "Immaculata University" }, + { "value": "115861", "label": "Imperial Valley College" }, + { "value": "155201", "label": "Independence Community College" }, + { "value": "465812", "label": "Independence University" }, + { "value": "153472", "label": "Indian Hills Community College" }, + { "value": "134608", "label": "Indian River State College" }, + { "value": "151290", "label": "Indiana Institute of Technology" }, + { "value": "151324", "label": "Indiana State University" }, + { + "value": "213020", + "label": "Indiana University of Pennsylvania-Main Campus" + }, + { "value": "151351", "label": "Indiana University-Bloomington" }, + { "value": "151388", "label": "Indiana University-East" }, + { "value": "151333", "label": "Indiana University-Kokomo" }, + { "value": "151360", "label": "Indiana University-Northwest" }, + { + "value": "151102", + "label": "Indiana University-Purdue University-Fort Wayne" + }, + { + "value": "151111", + "label": "Indiana University-Purdue University-Indianapolis" + }, + { "value": "151342", "label": "Indiana University-South Bend" }, + { "value": "151379", "label": "Indiana University-Southeast" }, + { "value": "151801", "label": "Indiana Wesleyan University" }, + { "value": "145886", "label": "Institute for Clinical Social Work" }, + { + "value": "462044", + "label": "Institute for Doctoral Studies in the Visual Arts" + }, + { "value": "445869", "label": "Institute for the Psychological Sciences" }, + { + "value": "187745", + "label": "Institute of American Indian and Alaska Native Culture" + }, + { + "value": "444699", + "label": "Institute of Clinical Acupuncture & Oriental Med" + }, + { "value": "191764", "label": "Institute of Design and Construction" }, + { "value": "454616", "label": "Institute of Production and Recording" }, + { + "value": "454838", + "label": "Institute of Taoist Education and Acupuncture" + }, + { "value": "431141", "label": "Institute of Technology Inc-Clovis" }, + { "value": "455804", "label": "Institute of World Politics" }, + { "value": "242422", "label": "Instituto de Banca y Comercio Inc" }, + { + "value": "242556", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Guayama" + }, + { + "value": "242042", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Manati" + }, + { + "value": "242565", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de Ponce" + }, + { + "value": "242583", + "label": "Instituto Tecnologico de Puerto Rico-Recinto de San Juan" + }, + { "value": "128179", "label": "Intellitec College-Colorado Springs" }, + { "value": "128188", "label": "Intellitec College-Grand Junction" }, + { + "value": "242626", + "label": "Inter American University of Puerto Rico-Aguadilla" + }, + { + "value": "242635", + "label": "Inter American University of Puerto Rico-Arecibo" + }, + { + "value": "242644", + "label": "Inter American University of Puerto Rico-Barranquitas" + }, + { + "value": "242705", + "label": "Inter American University of Puerto Rico-Bayamon" + }, + { + "value": "242680", + "label": "Inter American University of Puerto Rico-Fajardo" + }, + { + "value": "242699", + "label": "Inter American University of Puerto Rico-Guayama" + }, + { + "value": "242653", + "label": "Inter American University of Puerto Rico-Metro" + }, + { + "value": "242662", + "label": "Inter American University of Puerto Rico-Ponce" + }, + { + "value": "242617", + "label": "Inter American University of Puerto Rico-San German" + }, + { + "value": "242723", + "label": "Inter American University of Puerto Rico-School of Law" + }, + { + "value": "404222", + "label": "Inter American University of Puerto Rico-School of Optometry" + }, + { + "value": "138655", + "label": "Interactive College of Technology-Chamblee" + }, + { + "value": "442435", + "label": "Interactive College of Technology-Gainesville" + }, + { "value": "367361", "label": "Interactive College of Technology-Houston" }, + { "value": "443696", "label": "Interactive College of Technology-Houston" }, + { "value": "138664", "label": "Interactive College of Technology-Morrow" }, + { "value": "367103", "label": "Interactive College of Technology-Newport" }, + { + "value": "440776", + "label": "Interactive College of Technology-Pasadena" + }, + { "value": "366289", "label": "InterCoast Colleges-Orange" }, + { "value": "140146", "label": "Interdenominational Theological Center" }, + { "value": "235495", "label": "Interface College-Spokane" }, + { "value": "116226", "label": "Interior Designers Institute" }, + { + "value": "446817", + "label": "International Academy of Design and Technology-Nashville" + }, + { + "value": "450447", + "label": "International Academy of Design and Technology-Sacramento" + }, + { + "value": "445124", + "label": "International Academy of Design and Technology-Troy" + }, + { + "value": "436614", + "label": "International Baptist College and Seminary" + }, + { + "value": "225779", + "label": "International Business College-El Paso-El Paso" + }, + { + "value": "225788", + "label": "International Business College-El Paso-El Paso" + }, + { "value": "151458", "label": "International Business College-Fort Wayne" }, + { + "value": "151467", + "label": "International Business College-Indianapolis" + }, + { "value": "203289", "label": "International College of Broadcasting" }, + { + "value": "448691", + "label": "International Institute for Restorative Practices" + }, + { + "value": "454740", + "label": "International Professional School of Bodywork" + }, + { "value": "443128", "label": "International Technological University" }, + { "value": "173799", "label": "Inver Hills Community College" }, + { "value": "191931", "label": "Iona College" }, + { "value": "153524", "label": "Iowa Central Community College" }, + { "value": "153533", "label": "Iowa Lakes Community College" }, + { "value": "153603", "label": "Iowa State University" }, + { "value": "153621", "label": "Iowa Wesleyan University" }, + { "value": "153630", "label": "Iowa Western Community College" }, + { + "value": "441238", + "label": "Irell & Manella Graduate School of Biological Sciences at City of Hope" + }, + { "value": "116439", "label": "Irvine Valley College" }, + { "value": "191959", "label": "Island Drafting and Technical Institute" }, + { "value": "198710", "label": "Isothermal Community College" }, + { "value": "173805", "label": "Itasca Community College" }, + { "value": "175829", "label": "Itawamba Community College" }, + { "value": "191968", "label": "Ithaca College" }, + { "value": "159197", "label": "ITI Technical College" }, + { "value": "459611", "label": "ITT Technical Institute-Akron" }, + { "value": "434566", "label": "ITT Technical Institute-Albany" }, + { "value": "369084", "label": "ITT Technical Institute-Albuquerque" }, + { "value": "225849", "label": "ITT Technical Institute-Arlington" }, + { "value": "260974", "label": "ITT Technical Institute-Arlington Heights" }, + { "value": "434548", "label": "ITT Technical Institute-Arnold" }, + { "value": "450243", "label": "ITT Technical Institute-Atlanta" }, + { "value": "459675", "label": "ITT Technical Institute-Aurora" }, + { "value": "366678", "label": "ITT Technical Institute-Austin" }, + { "value": "450216", "label": "ITT Technical Institute-Baton Rouge" }, + { "value": "414568", "label": "ITT Technical Institute-Bessemer" }, + { "value": "142337", "label": "ITT Technical Institute-Boise" }, + { "value": "470852", "label": "ITT Technical Institute-Bradenton" }, + { "value": "470870", "label": "ITT Technical Institute-Brooklyn Center" }, + { "value": "442338", "label": "ITT Technical Institute-Canton" }, + { "value": "451936", "label": "ITT Technical Institute-Cary" }, + { "value": "441964", "label": "ITT Technical Institute-Chantilly" }, + { "value": "456445", "label": "ITT Technical Institute-Charlotte North" }, + { "value": "448442", "label": "ITT Technical Institute-Charlotte South" }, + { "value": "450261", "label": "ITT Technical Institute-Chattanooga" }, + { "value": "451954", "label": "ITT Technical Institute-Clive" }, + { "value": "448451", "label": "ITT Technical Institute-Clovis" }, + { "value": "450225", "label": "ITT Technical Institute-Columbia" }, + { "value": "451963", "label": "ITT Technical Institute-Columbus" }, + { "value": "456427", "label": "ITT Technical Institute-Concord" }, + { "value": "413884", "label": "ITT Technical Institute-Cordova" }, + { "value": "459639", "label": "ITT Technical Institute-Corona" }, + { "value": "459693", "label": "ITT Technical Institute-Culver City" }, + { "value": "203313", "label": "ITT Technical Institute-Dayton" }, + { "value": "459709", "label": "ITT Technical Institute-Dearborn" }, + { "value": "479619", "label": "ITT Technical Institute-Deerfield Beach" }, + { "value": "459657", "label": "ITT Technical Institute-DeSoto" }, + { "value": "479637", "label": "ITT Technical Institute-Douglasville" }, + { "value": "443526", "label": "ITT Technical Institute-Duluth" }, + { "value": "448460", "label": "ITT Technical Institute-Dunmore" }, + { "value": "462363", "label": "ITT Technical Institute-Durham" }, + { "value": "176637", "label": "ITT Technical Institute-Earth City" }, + { "value": "445081", "label": "ITT Technical Institute-Eden Prairie" }, + { "value": "414531", "label": "ITT Technical Institute-Everett" }, + { "value": "409069", "label": "ITT Technical Institute-Fort Lauderdale" }, + { "value": "456436", "label": "ITT Technical Institute-Fort Myers" }, + { "value": "151500", "label": "ITT Technical Institute-Fort Wayne" }, + { "value": "479567", "label": "ITT Technical Institute-Germantown" }, + { "value": "420404", "label": "ITT Technical Institute-Getzville" }, + { "value": "440165", "label": "ITT Technical Institute-Green Bay" }, + { "value": "238892", "label": "ITT Technical Institute-Greenfield" }, + { "value": "413866", "label": "ITT Technical Institute-Greenville" }, + { "value": "462372", "label": "ITT Technical Institute-Hanover" }, + { "value": "430351", "label": "ITT Technical Institute-Harrisburg" }, + { "value": "429599", "label": "ITT Technical Institute-Henderson" }, + { "value": "430263", "label": "ITT Technical Institute-Hialeah" }, + { "value": "451990", "label": "ITT Technical Institute-High Point" }, + { "value": "443535", "label": "ITT Technical Institute-Hilliard" }, + { "value": "366696", "label": "ITT Technical Institute-Houston North" }, + { "value": "225858", "label": "ITT Technical Institute-Houston West" }, + { "value": "456418", "label": "ITT Technical Institute-Huntington" }, + { "value": "151519", "label": "ITT Technical Institute-Indianapolis" }, + { "value": "479628", "label": "ITT Technical Institute-Indianapolis East" }, + { "value": "407063", "label": "ITT Technical Institute-Jacksonville" }, + { "value": "459648", "label": "ITT Technical Institute-Johnson City" }, + { "value": "446899", "label": "ITT Technical Institute-Kansas City" }, + { "value": "446905", "label": "ITT Technical Institute-Kennesaw" }, + { "value": "366650", "label": "ITT Technical Institute-Knoxville" }, + { "value": "372578", "label": "ITT Technical Institute-Lake Mary" }, + { "value": "459718", "label": "ITT Technical Institute-Las Vegas" }, + { "value": "437219", "label": "ITT Technical Institute-Lathrop" }, + { "value": "440642", "label": "ITT Technical Institute-Levittown" }, + { "value": "448488", "label": "ITT Technical Institute-Lexington" }, + { "value": "413839", "label": "ITT Technical Institute-Little Rock" }, + { "value": "434575", "label": "ITT Technical Institute-Liverpool" }, + { "value": "413857", "label": "ITT Technical Institute-Louisville" }, + { "value": "451945", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "451981", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "456393", "label": "ITT Technical Institute-Madison-Madison" }, + { "value": "479558", "label": "ITT Technical Institute-Marlton" }, + { "value": "448497", "label": "ITT Technical Institute-Maumee" }, + { "value": "459587", "label": "ITT Technical Institute-Merrillville" }, + { "value": "450252", "label": "ITT Technical Institute-Mobile" }, + { "value": "230384", "label": "ITT Technical Institute-Murray" }, + { "value": "470904", "label": "ITT Technical Institute-Myrtle Beach" }, + { "value": "151494", "label": "ITT Technical Institute-Nashville" }, + { "value": "116466", "label": "ITT Technical Institute-National City" }, + { "value": "251251", "label": "ITT Technical Institute-Newburgh" }, + { "value": "368601", "label": "ITT Technical Institute-Norfolk" }, + { "value": "459666", "label": "ITT Technical Institute-North Charleston" }, + { "value": "366580", "label": "ITT Technical Institute-Norwood-Norwood" }, + { "value": "430379", "label": "ITT Technical Institute-Norwood-Norwood" }, + { "value": "434557", "label": "ITT Technical Institute-Oak Brook" }, + { "value": "467058", "label": "ITT Technical Institute-Oakland" }, + { "value": "448503", "label": "ITT Technical Institute-Oklahoma City" }, + { "value": "407319", "label": "ITT Technical Institute-Omaha" }, + { "value": "116484", "label": "ITT Technical Institute-Orange" }, + { "value": "414586", "label": "ITT Technical Institute-Orland Park" }, + { "value": "470889", "label": "ITT Technical Institute-Orlando" }, + { "value": "479646", "label": "ITT Technical Institute-Overland Park" }, + { "value": "446914", "label": "ITT Technical Institute-Owings Mills" }, + { "value": "413848", "label": "ITT Technical Institute-Oxnard" }, + { "value": "479549", "label": "ITT Technical Institute-Philadelphia" }, + { "value": "451972", "label": "ITT Technical Institute-Phoenix" }, + { "value": "470861", "label": "ITT Technical Institute-Phoenix West" }, + { "value": "414841", "label": "ITT Technical Institute-Pittsburgh" }, + { "value": "442347", "label": "ITT Technical Institute-Plymouth Meeting" }, + { "value": "208965", "label": "ITT Technical Institute-Portland" }, + { "value": "108250", "label": "ITT Technical Institute-Rancho Cordova" }, + { "value": "434052", "label": "ITT Technical Institute-Richardson" }, + { "value": "437051", "label": "ITT Technical Institute-Richmond" }, + { "value": "437042", "label": "ITT Technical Institute-Saint Rose" }, + { "value": "459602", "label": "ITT Technical Institute-Salem-Salem" }, + { "value": "479600", "label": "ITT Technical Institute-Salem-Salem" }, + { "value": "377069", "label": "ITT Technical Institute-San Antonio" }, + { "value": "481623", "label": "ITT Technical Institute-San Antonio East" }, + { "value": "381909", "label": "ITT Technical Institute-San Bernardino" }, + { "value": "116475", "label": "ITT Technical Institute-San Dimas" }, + { "value": "235510", "label": "ITT Technical Institute-Seattle" }, + { "value": "450270", "label": "ITT Technical Institute-South Bend" }, + { "value": "479585", "label": "ITT Technical Institute-Southfield" }, + { "value": "235529", "label": "ITT Technical Institute-Spokane Valley" }, + { + "value": "441955", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "value": "456409", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { + "value": "479655", + "label": "ITT Technical Institute-Springfield-Springfield" + }, + { "value": "450207", "label": "ITT Technical Institute-St Petersburg" }, + { "value": "430388", "label": "ITT Technical Institute-Strongsville" }, + { "value": "448479", "label": "ITT Technical Institute-Swartz Creek" }, + { "value": "244011", "label": "ITT Technical Institute-Sylmar" }, + { "value": "459596", "label": "ITT Technical Institute-Tallahassee" }, + { "value": "134909", "label": "ITT Technical Institute-Tampa" }, + { "value": "430360", "label": "ITT Technical Institute-Tarentum" }, + { "value": "105172", "label": "ITT Technical Institute-Tempe" }, + { "value": "378406", "label": "ITT Technical Institute-Torrance" }, + { "value": "261472", "label": "ITT Technical Institute-Troy" }, + { "value": "105163", "label": "ITT Technical Institute-Tucson" }, + { "value": "448512", "label": "ITT Technical Institute-Tulsa" }, + { "value": "470898", "label": "ITT Technical Institute-Waco" }, + { + "value": "446923", + "label": "ITT Technical Institute-Warrensville Heights" + }, + { "value": "427663", "label": "ITT Technical Institute-Webster" }, + { "value": "479664", "label": "ITT Technical Institute-West Chester" }, + { "value": "459684", "label": "ITT Technical Institute-West Covina" }, + { "value": "479594", "label": "ITT Technical Institute-West Palm Beach" }, + { "value": "244154", "label": "ITT Technical Institute-Westminster" }, + { "value": "450234", "label": "ITT Technical Institute-Wichita" }, + { "value": "439136", "label": "ITT Technical Institute-Wilmington" }, + { "value": "170417", "label": "ITT Technical Institute-Wyoming" }, + { "value": "206631", "label": "ITT Technical Institute-Youngstown" }, + { "value": "150987", "label": "Ivy Tech Community College" }, + { + "value": "101462", + "label": "J F Drake State Community and Technical College" + }, + { "value": "101471", "label": "J F Ingram State Technical College" }, + { "value": "232414", "label": "J Sargeant Reynolds Community College" }, + { "value": "170444", "label": "Jackson College" }, + { "value": "220400", "label": "Jackson State Community College" }, + { "value": "175856", "label": "Jackson State University" }, + { "value": "225876", "label": "Jacksonville College-Main Campus" }, + { "value": "101480", "label": "Jacksonville State University" }, + { "value": "134945", "label": "Jacksonville University" }, + { "value": "203678", "label": "James A Rhodes State College" }, + { "value": "101161", "label": "James H Faulkner State Community College" }, + { "value": "232423", "label": "James Madison University" }, + { "value": "198729", "label": "James Sprunt Community College" }, + { "value": "192004", "label": "Jamestown Business College" }, + { "value": "191986", "label": "Jamestown Community College" }, + { "value": "225885", "label": "Jarvis Christian College" }, + { "value": "177676", "label": "Jefferson College" }, + { "value": "231837", "label": "Jefferson College of Health Sciences" }, + { "value": "156921", "label": "Jefferson Community and Technical College" }, + { "value": "192022", "label": "Jefferson Community College" }, + { "value": "101499", "label": "Jefferson Davis Community College" }, + { "value": "101505", "label": "Jefferson State Community College" }, + { "value": "455196", "label": "Jersey College" }, + { "value": "192040", "label": "Jewish Theological Seminary of America" }, + { "value": "419341", "label": "Jna Institute of Culinary Arts" }, + { "value": "220464", "label": "John A Gupton College" }, + { "value": "146205", "label": "John A Logan College" }, + { "value": "107141", "label": "John Brown University" }, + { "value": "101514", "label": "John C Calhoun State Community College" }, + { "value": "203368", "label": "John Carroll University" }, + { "value": "116712", "label": "John F. Kennedy University" }, + { "value": "462354", "label": "John Paul the Great Catholic University" }, + { "value": "232450", "label": "John Tyler Community College" }, + { "value": "146278", "label": "John Wood Community College" }, + { "value": "162928", "label": "Johns Hopkins University" }, + { "value": "445708", "label": "Johnson & Wales University-Charlotte" }, + { "value": "439288", "label": "Johnson & Wales University-Denver" }, + { "value": "414823", "label": "Johnson & Wales University-North Miami" }, + { "value": "460349", "label": "Johnson & Wales University-Online" }, + { "value": "217235", "label": "Johnson & Wales University-Providence" }, + { "value": "198756", "label": "Johnson C Smith University" }, + { "value": "213233", "label": "Johnson College" }, + { "value": "155210", "label": "Johnson County Community College" }, + { "value": "230913", "label": "Johnson State College" }, + { "value": "220473", "label": "Johnson University" }, + { "value": "132879", "label": "Johnson University Florida" }, + { "value": "198774", "label": "Johnston Community College" }, + { "value": "146296", "label": "Joliet Junior College" }, + { "value": "135063", "label": "Jones College-Jacksonville" }, + { "value": "175883", "label": "Jones County Junior College" }, + { "value": "444723", "label": "Jones International University" }, + { "value": "461281", "label": "Jose Maria Vargas University" }, + { "value": "101541", "label": "Judson College" }, + { "value": "146339", "label": "Judson University" }, + { + "value": "461139", + "label": "Jung Tao School of Classical Chinese Medicine" + }, + { "value": "213251", "label": "Juniata College" }, + { "value": "170532", "label": "Kalamazoo College" }, + { "value": "170541", "label": "Kalamazoo Valley Community College" }, + { "value": "146348", "label": "Kankakee Community College" }, + { "value": "177746", "label": "Kansas City Art Institute" }, + { "value": "155308", "label": "Kansas City College & Bible School" }, + { "value": "155292", "label": "Kansas City Kansas Community College" }, + { + "value": "179812", + "label": "Kansas City University of Medicine and Biosciences" + }, + { "value": "155399", "label": "Kansas State University" }, + { "value": "155414", "label": "Kansas Wesleyan University" }, + { "value": "141796", "label": "Kapiolani Community College" }, + { "value": "458715", "label": "Kaplan College-Jacksonville" }, + { "value": "445346", "label": "Kaplan College-Lubbock" }, + { "value": "480064", "label": "Kaplan University-Augusta Campus" }, + { "value": "260910", "label": "Kaplan University-Cedar Falls Campus" }, + { "value": "153418", "label": "Kaplan University-Cedar Rapids Campus" }, + { "value": "260901", "label": "Kaplan University-Davenport Campus" }, + { "value": "367024", "label": "Kaplan University-Des Moines Campus" }, + { "value": "162681", "label": "Kaplan University-Hagerstown Campus" }, + { "value": "181242", "label": "Kaplan University-Lincoln Campus" }, + { "value": "160940", "label": "Kaplan University-Maine Campus" }, + { "value": "153409", "label": "Kaplan University-Mason City Campus" }, + { "value": "181400", "label": "Kaplan University-Omaha Campus" }, + { "value": "146366", "label": "Kaskaskia College" }, + { "value": "141802", "label": "Kauai Community College" }, + { + "value": "225991", + "label": "KD College Conservatory of Film and Dramatic Arts" + }, + { "value": "185262", "label": "Kean University" }, + { "value": "440031", "label": "Keck Graduate Institute" }, + { "value": "183062", "label": "Keene State College" }, + { "value": "192165", "label": "Kehilath Yakov Rabbinical Seminary" }, + { "value": "135081", "label": "Keiser University-Ft Lauderdale" }, + { "value": "170550", "label": "Kellogg Community College" }, + { "value": "146393", "label": "Kendall College" }, + { "value": "161192", "label": "Kennebec Valley Community College" }, + { "value": "140164", "label": "Kennesaw State University" }, + { "value": "177816", "label": "Kenrick Glennon Seminary" }, + { "value": "203447", "label": "Kent State University at Ashtabula" }, + { "value": "203456", "label": "Kent State University at East Liverpool" }, + { "value": "203526", "label": "Kent State University at Geauga" }, + { "value": "203517", "label": "Kent State University at Kent" }, + { "value": "203492", "label": "Kent State University at Salem" }, + { "value": "203465", "label": "Kent State University at Stark" }, + { "value": "203474", "label": "Kent State University at Trumbull" }, + { "value": "203483", "label": "Kent State University at Tuscarawas" }, + { "value": "157100", "label": "Kentucky Christian University" }, + { "value": "157030", "label": "Kentucky Mountain Bible College" }, + { "value": "157058", "label": "Kentucky State University" }, + { "value": "157076", "label": "Kentucky Wesleyan College" }, + { "value": "203535", "label": "Kenyon College" }, + { "value": "203544", "label": "Kettering College" }, + { "value": "169983", "label": "Kettering University" }, + { "value": "192192", "label": "Keuka College" }, + { "value": "461315", "label": "Keweenaw Bay Ojibwa Community College" }, + { "value": "134422", "label": "Key College" }, + { "value": "213303", "label": "Keystone College" }, + { "value": "210483", "label": "Keystone Technical Institute" }, + { "value": "226019", "label": "Kilgore College" }, + { "value": "219055", "label": "Kilian Community College" }, + { "value": "220516", "label": "King University" }, + { "value": "382504", "label": "King's College-Charlotte" }, + { "value": "213321", "label": "King's College-Wilkes-Barre" }, + { "value": "153737", "label": "Kirkwood Community College" }, + { "value": "170587", "label": "Kirtland Community College" }, + { "value": "146418", "label": "Kishwaukee College" }, + { "value": "428392", "label": "Klamath Community College" }, + { "value": "260956", "label": "Knowledge Systems Institute" }, + { "value": "146427", "label": "Knox College" }, + { "value": "484288", "label": "Knox Theological Seminary" }, + { "value": "213349", "label": "Kutztown University of Pennsylvania" }, + { "value": "171881", "label": "Kuyper College" }, + { "value": "213358", "label": "La Roche College" }, + { "value": "213367", "label": "La Salle University" }, + { "value": "117627", "label": "La Sierra University" }, + { "value": "155450", "label": "Labette Community College" }, + { "value": "165264", "label": "Laboure College" }, + { + "value": "260372", + "label": "Lac Courte Oreilles Ojibwa Community College" + }, + { "value": "213376", "label": "Lackawanna College" }, + { "value": "213385", "label": "Lafayette College" }, + { "value": "140234", "label": "LaGrange College" }, + { "value": "117168", "label": "Laguna College of Art and Design" }, + { "value": "219143", "label": "Lake Area Technical Institute" }, + { "value": "203580", "label": "Lake Erie College" }, + { "value": "407629", "label": "Lake Erie College of Osteopathic Medicine" }, + { "value": "146481", "label": "Lake Forest College" }, + { "value": "146490", "label": "Lake Forest Graduate School of Management" }, + { "value": "146506", "label": "Lake Land College" }, + { "value": "170620", "label": "Lake Michigan College" }, + { "value": "200192", "label": "Lake Region State College" }, + { "value": "173461", "label": "Lake Superior College" }, + { "value": "170639", "label": "Lake Superior State University" }, + { "value": "117195", "label": "Lake Tahoe Community College" }, + { "value": "235699", "label": "Lake Washington Institute of Technology" }, + { "value": "238980", "label": "Lakeland College" }, + { "value": "203599", "label": "Lakeland Community College" }, + { "value": "183123", "label": "Lakes Region Community College" }, + { "value": "239008", "label": "Lakeshore Technical College" }, + { "value": "135188", "label": "Lake-Sumter State College" }, + { "value": "146533", "label": "Lakeview College of Nursing" }, + { "value": "127389", "label": "Lamar Community College" }, + { "value": "441760", "label": "Lamar Institute of Technology" }, + { "value": "226107", "label": "Lamar State College-Orange" }, + { "value": "226116", "label": "Lamar State College-Port Arthur" }, + { "value": "226091", "label": "Lamar University" }, + { "value": "213400", "label": "Lancaster Bible College" }, + { + "value": "418533", + "label": "Lancaster County Career and Technology Center" + }, + { "value": "213446", "label": "Lancaster Theological Seminary" }, + { "value": "218229", "label": "Lander University" }, + { "value": "247649", "label": "Landmark College" }, + { "value": "220598", "label": "Lane College" }, + { "value": "209038", "label": "Lane Community College" }, + { "value": "117247", "label": "Laney College" }, + { "value": "207209", "label": "Langston University" }, + { "value": "140243", "label": "Lanier Technical College" }, + { "value": "213473", "label": "Lansdale School of Business" }, + { "value": "170657", "label": "Lansing Community College" }, + { "value": "240620", "label": "Laramie County Community College" }, + { "value": "226134", "label": "Laredo Community College" }, + { "value": "366401", "label": "Las Positas College" }, + { "value": "166391", "label": "Lasell College" }, + { "value": "117274", "label": "Lassen Community College" }, + { "value": "230418", "label": "Latter-day Saints Business College" }, + { "value": "250027", "label": "Laurel Business Institute" }, + { "value": "408729", "label": "Laurel Technical Institute-MEADVILLE" }, + { "value": "215992", "label": "Laurel Technical Institute-Sharon" }, + { "value": "198747", "label": "Laurel University" }, + { + "value": "166407", + "label": "Lawrence Memorial Hospital School of Nursing" + }, + { "value": "170675", "label": "Lawrence Technological University" }, + { "value": "239017", "label": "Lawrence University" }, + { + "value": "101569", + "label": "Lawson State Community College-Birmingham Campus" + }, + { + "value": "443623", + "label": "Le Cordon Bleu College of Culinary Arts-Atlanta" + }, + { + "value": "364973", + "label": "Le Cordon Bleu College of Culinary Arts-Austin" + }, + { + "value": "452054", + "label": "Le Cordon Bleu College of Culinary Arts-Cambridge" + }, + { + "value": "144467", + "label": "Le Cordon Bleu College of Culinary Arts-Chicago" + }, + { + "value": "452063", + "label": "Le Cordon Bleu College of Culinary Arts-Dallas" + }, + { + "value": "445115", + "label": "Le Cordon Bleu College of Culinary Arts-Las Vegas" + }, + { + "value": "446835", + "label": "Le Cordon Bleu College of Culinary Arts-Miami" + }, + { + "value": "446844", + "label": "Le Cordon Bleu College of Culinary Arts-Minneapolis" + }, + { + "value": "442231", + "label": "Le Cordon Bleu College of Culinary Arts-Orlando" + }, + { + "value": "423980", + "label": "Le Cordon Bleu College of Culinary Arts-Pasadena" + }, + { + "value": "375841", + "label": "Le Cordon Bleu College of Culinary Arts-Portland" + }, + { + "value": "111009", + "label": "Le Cordon Bleu College of Culinary Arts-San Francisco" + }, + { + "value": "262332", + "label": "Le Cordon Bleu College of Culinary Arts-Scottsdale" + }, + { "value": "192323", "label": "Le Moyne College" }, + { "value": "220604", "label": "Le Moyne-Owen College" }, + { "value": "213507", "label": "Lebanon Valley College" }, + { "value": "456940", "label": "L'Ecole Culinaire-Memphis" }, + { "value": "445726", "label": "L'Ecole Culinaire-St Louis" }, + { "value": "226204", "label": "Lee College" }, + { "value": "220613", "label": "Lee University" }, + { "value": "413626", "label": "Leech Lake Tribal College" }, + { "value": "198808", "label": "Lees-McRae College" }, + { "value": "141811", "label": "Leeward Community College" }, + { "value": "213525", "label": "Lehigh Carbon Community College" }, + { "value": "213543", "label": "Lehigh University" }, + { "value": "198817", "label": "Lenoir Community College" }, + { "value": "198835", "label": "Lenoir-Rhyne University" }, + { + "value": "218265", + "label": "Lenoir-Rhyne University-Lutheran Theological Southern Seminary" + }, + { "value": "166452", "label": "Lesley University" }, + { "value": "226231", "label": "LeTourneau University" }, + { "value": "209056", "label": "Lewis & Clark College" }, + { "value": "146603", "label": "Lewis and Clark Community College" }, + { "value": "146612", "label": "Lewis University" }, + { "value": "142328", "label": "Lewis-Clark State College" }, + { "value": "157207", "label": "Lexington Theological Seminary" }, + { "value": "232557", "label": "Liberty University" }, + { "value": "117520", "label": "Life Chiropractic College West" }, + { "value": "117104", "label": "Life Pacific College" }, + { "value": "140252", "label": "Life University" }, + { "value": "192271", "label": "LIM College" }, + { "value": "218238", "label": "Limestone College" }, + { "value": "146667", "label": "Lincoln Christian University" }, + { "value": "146676", "label": "Lincoln College" }, + { + "value": "128683", + "label": "Lincoln College of New England-Southington" + }, + { "value": "163028", "label": "Lincoln College of Technology-Columbia" }, + { "value": "126951", "label": "Lincoln College of Technology-Denver" }, + { + "value": "151661", + "label": "Lincoln College of Technology-Indianapolis" + }, + { "value": "434159", "label": "Lincoln College of Technology-Marietta" }, + { + "value": "146700", + "label": "Lincoln College of Technology-Melrose Park" + }, + { "value": "221148", "label": "Lincoln College of Technology-Nashville" }, + { + "value": "136066", + "label": "Lincoln College of Technology-West Palm Beach" + }, + { "value": "146685", "label": "Lincoln Land Community College" }, + { "value": "220631", "label": "Lincoln Memorial University" }, + { "value": "213570", "label": "Lincoln Technical Institute-Allentown" }, + { + "value": "442037", + "label": "Lincoln Technical Institute-Northeast Philadelphia" + }, + { "value": "213589", "label": "Lincoln Technical Institute-Philadelphia" }, + { "value": "403478", "label": "Lincoln Trail College" }, + { "value": "177940", "label": "Lincoln University-Jefferson City" }, + { "value": "117557", "label": "Lincoln University-Oakland" }, + { "value": "177968", "label": "Lindenwood University" }, + { "value": "157216", "label": "Lindsey Wilson College" }, + { "value": "437325", "label": "Linfield College-Adult Degree Program" }, + { "value": "209065", "label": "Linfield College-McMinnville Campus" }, + { "value": "437316", "label": "Linfield College-School of Nursing" }, + { "value": "209074", "label": "Linn-Benton Community College" }, + { "value": "219976", "label": "Lipscomb University" }, + { "value": "180328", "label": "Little Big Horn College" }, + { "value": "434016", "label": "Little Priest Tribal College" }, + { "value": "192563", "label": "LIU Brentwood" }, + { "value": "192439", "label": "LIU Brooklyn" }, + { "value": "192554", "label": "LIU Hudson at Rockland" }, + { "value": "432357", "label": "LIU Hudson at Westchester" }, + { "value": "192448", "label": "LIU Post" }, + { "value": "450766", "label": "LIU Riverhead" }, + { "value": "421832", "label": "Living Arts College" }, + { "value": "198862", "label": "Livingstone College" }, + { "value": "213613", "label": "Lock Haven University" }, + { "value": "177986", "label": "Logan University" }, + { "value": "117636", "label": "Loma Linda University" }, + { "value": "227182", "label": "Lone Star College System" }, + { "value": "117645", "label": "Long Beach City College" }, + { "value": "192509", "label": "Long Island Business Institute" }, + { "value": "232566", "label": "Longwood University" }, + { "value": "166489", "label": "Longy School of Music of Bard College" }, + { "value": "203748", "label": "Lorain County Community College" }, + { "value": "153825", "label": "Loras College" }, + { "value": "232575", "label": "Lord Fairfax Community College" }, + { "value": "117788", "label": "Los Angeles City College" }, + { "value": "446385", "label": "Los Angeles College of Music" }, + { + "value": "117803", + "label": "Los Angeles County College of Nursing and Allied Health" + }, + { "value": "436429", "label": "Los Angeles Film School" }, + { "value": "117690", "label": "Los Angeles Harbor College" }, + { "value": "117867", "label": "Los Angeles Mission College" }, + { + "value": "368780", + "label": "Los Angeles ORT College-Los Angeles Campus" + }, + { "value": "381945", "label": "Los Angeles ORT College-Van Nuys Campus" }, + { "value": "117706", "label": "Los Angeles Pierce College" }, + { "value": "117715", "label": "Los Angeles Southwest College" }, + { "value": "117724", "label": "Los Angeles Trade Technical College" }, + { "value": "117733", "label": "Los Angeles Valley College" }, + { "value": "117894", "label": "Los Medanos College" }, + { "value": "198871", "label": "Louisburg College" }, + { "value": "159568", "label": "Louisiana College" }, + { "value": "449612", "label": "Louisiana Culinary Institute" }, + { "value": "483212", "label": "Louisiana Delta Community College" }, + { + "value": "159391", + "label": "Louisiana State University and Agricultural & Mechanical College" + }, + { + "value": "159373", + "label": "Louisiana State University Health Sciences Center-New Orleans" + }, + { + "value": "435000", + "label": "Louisiana State University Health Sciences Center-Shreveport" + }, + { "value": "159382", "label": "Louisiana State University-Alexandria" }, + { "value": "159407", "label": "Louisiana State University-Eunice" }, + { "value": "159416", "label": "Louisiana State University-Shreveport" }, + { "value": "159647", "label": "Louisiana Tech University" }, + { + "value": "157298", + "label": "Louisville Presbyterian Theological Seminary" + }, + { "value": "203757", "label": "Lourdes University" }, + { "value": "235750", "label": "Lower Columbia College" }, + { "value": "117946", "label": "Loyola Marymount University" }, + { "value": "146719", "label": "Loyola University Chicago" }, + { "value": "163046", "label": "Loyola University Maryland" }, + { "value": "159656", "label": "Loyola University New Orleans" }, + { "value": "226383", "label": "Lubbock Christian University" }, + { "value": "363633", "label": "Luna Community College" }, + { "value": "101602", "label": "Lurleen B Wallace Community College" }, + { "value": "153834", "label": "Luther College" }, + { "value": "135364", "label": "Luther Rice University & Seminary" }, + { "value": "173896", "label": "Luther Seminary" }, + { "value": "146728", "label": "Lutheran School of Theology at Chicago" }, + { + "value": "213631", + "label": "Lutheran Theological Seminary at Gettysburg" + }, + { + "value": "213640", + "label": "Lutheran Theological Seminary at Philadelphia" + }, + { "value": "213659", "label": "Luzerne County Community College" }, + { "value": "213668", "label": "Lycoming College" }, + { "value": "232609", "label": "Lynchburg College" }, + { "value": "230931", "label": "Lyndon State College" }, + { "value": "132657", "label": "Lynn University" }, + { "value": "106342", "label": "Lyon College" }, + { "value": "173902", "label": "Macalester College" }, + { "value": "146816", "label": "MacCormac College" }, + { "value": "192624", "label": "Machzikei Hadath Rabbinical College" }, + { "value": "146825", "label": "MacMurray College" }, + { "value": "170790", "label": "Macomb Community College" }, + { "value": "238263", "label": "Madison Area Technical College" }, + { "value": "364168", "label": "Madison Media Institute" }, + { + "value": "148399", + "label": "Madison Media Institute-Rockford Career College" + }, + { "value": "157304", "label": "Madisonville Community College" }, + { "value": "170806", "label": "Madonna University" }, + { "value": "153861", "label": "Maharishi University of Management" }, + { "value": "161509", "label": "Maine College of Art" }, + { "value": "161022", "label": "Maine College of Health Professions" }, + { "value": "161299", "label": "Maine Maritime Academy" }, + { "value": "203775", "label": "Malone University" }, + { "value": "451103", "label": "Management Resources College" }, + { "value": "129695", "label": "Manchester Community College-Manchester" }, + { "value": "183132", "label": "Manchester Community College-Manchester" }, + { "value": "151777", "label": "Manchester University" }, + { "value": "192688", "label": "Mandl School-The College of Allied Health" }, + { "value": "155487", "label": "Manhattan Area Technical College" }, + { "value": "155496", "label": "Manhattan Christian College" }, + { "value": "192703", "label": "Manhattan College" }, + { "value": "192712", "label": "Manhattan School of Music" }, + { "value": "192749", "label": "Manhattanville College" }, + { "value": "213774", "label": "Manor College" }, + { "value": "213783", "label": "Mansfield University of Pennsylvania" }, + { + "value": "446394", + "label": "Maple Springs Baptist Bible College and Seminary" + }, + { "value": "239071", "label": "Maranatha Baptist University" }, + { "value": "192785", "label": "Maria College of Albany" }, + { "value": "166601", "label": "Marian Court College" }, + { "value": "239080", "label": "Marian University-Fond Du Lac" }, + { "value": "151786", "label": "Marian University-Indianapolis" }, + { "value": "203845", "label": "Marietta College" }, + { "value": "101648", "label": "Marion Military Institute" }, + { "value": "203881", "label": "Marion Technical College" }, + { "value": "192819", "label": "Marist College" }, + { "value": "230940", "label": "Marlboro College" }, + { + "value": "440411", + "label": "Marlboro College Graduate & Professional Studies" + }, + { "value": "239105", "label": "Marquette University" }, + { "value": "198899", "label": "Mars Hill University" }, + { "value": "123943", "label": "Marshall B Ketchum University" }, + { "value": "237525", "label": "Marshall University" }, + { "value": "153922", "label": "Marshalltown Community College" }, + { "value": "198905", "label": "Martin Community College" }, + { "value": "173452", "label": "Martin Luther College" }, + { "value": "220701", "label": "Martin Methodist College" }, + { "value": "151810", "label": "Martin University" }, + { "value": "232672", "label": "Mary Baldwin College" }, + { "value": "170842", "label": "Marygrove College" }, + { "value": "163295", "label": "Maryland Institute College of Art" }, + { "value": "164085", "label": "Maryland University of Integrative Health" }, + { "value": "209108", "label": "Marylhurst University" }, + { "value": "118541", "label": "Marymount California University" }, + { "value": "192864", "label": "Marymount Manhattan College" }, + { "value": "232706", "label": "Marymount University" }, + { "value": "220710", "label": "Maryville College" }, + { "value": "178059", "label": "Maryville University of Saint Louis" }, + { "value": "213826", "label": "Marywood University" }, + { "value": "166647", "label": "Massachusetts Bay Community College" }, + { "value": "166674", "label": "Massachusetts College of Art and Design" }, + { "value": "167288", "label": "Massachusetts College of Liberal Arts" }, + { "value": "166683", "label": "Massachusetts Institute of Technology" }, + { "value": "166692", "label": "Massachusetts Maritime Academy" }, + { "value": "369002", "label": "Massachusetts School of Law" }, + { "value": "166823", "label": "Massasoit Community College" }, + { "value": "436702", "label": "Mattia College" }, + { "value": "454698", "label": "Mayfield College" }, + { "value": "198914", "label": "Mayland Community College" }, + { "value": "365426", "label": "Mayo Graduate School" }, + { "value": "173957", "label": "Mayo Medical School" }, + { "value": "173966", "label": "Mayo School of Health Sciences" }, + { "value": "157331", "label": "Maysville Community and Technical College" }, + { "value": "200226", "label": "Mayville State University" }, + { "value": "438212", "label": "McCann School of Business & Technology" }, + { "value": "146977", "label": "McCormick Theological Seminary" }, + { "value": "164270", "label": "McDaniel College" }, + { "value": "198923", "label": "McDowell Technical Community College" }, + { "value": "147004", "label": "McHenry County College" }, + { "value": "147013", "label": "McKendree University" }, + { "value": "226578", "label": "McLennan Community College" }, + { "value": "226587", "label": "McMurry University" }, + { "value": "367194", "label": "McNally Smith College of Music" }, + { "value": "159717", "label": "McNeese State University" }, + { "value": "155511", "label": "McPherson College" }, + { "value": "166656", "label": "MCPHS University" }, + { "value": "147031", "label": "Meadville Lombard Theological School" }, + { "value": "414461", "label": "Mech-Tech College" }, + { "value": "192925", "label": "Medaille College" }, + { "value": "239169", "label": "Medical College of Wisconsin" }, + { "value": "218335", "label": "Medical University of South Carolina" }, + { "value": "448415", "label": "MedTech College" }, + { "value": "456366", "label": "MedTech College-Ft Wayne Campus" }, + { "value": "456357", "label": "MedTech College-Greenwood Campus" }, + { "value": "456375", "label": "MedTech College-Lexington Campus" }, + { "value": "131742", "label": "Medtech Institute" }, + { "value": "444714", "label": "MedTech Institute-Atlanta Campus" }, + { "value": "220792", "label": "Meharry Medical College" }, + { "value": "192961", "label": "Memorial School of Nursing" }, + { "value": "220808", "label": "Memphis College of Art" }, + { "value": "220871", "label": "Memphis Theological Seminary" }, + { "value": "118684", "label": "Mendocino College" }, + { "value": "118693", "label": "Menlo College" }, + { "value": "118718", "label": "Merced College" }, + { "value": "185509", "label": "Mercer County Community College" }, + { "value": "140447", "label": "Mercer University" }, + { "value": "193016", "label": "Mercy College" }, + { "value": "153977", "label": "Mercy College of Health Sciences" }, + { "value": "203960", "label": "Mercy College of Ohio" }, + { "value": "213987", "label": "Mercyhurst University" }, + { "value": "480189", "label": "Mercyhurst University-North East Campus" }, + { "value": "198950", "label": "Meredith College" }, + { "value": "244279", "label": "Meridian College" }, + { "value": "175935", "label": "Meridian Community College" }, + { "value": "166850", "label": "Merrimack College" }, + { "value": "118772", "label": "Merritt College" }, + { "value": "105154", "label": "Mesa Community College" }, + { "value": "173993", "label": "Mesabi Range College" }, + { "value": "188261", "label": "Mesalands Community College" }, + { "value": "461847", "label": "Mesivta Keser Torah" }, + { + "value": "193061", + "label": "Mesivta of Eastern Parkway-Yeshiva Zichron Meilech" + }, + { "value": "193052", "label": "Mesivta Torah Vodaath Rabbinical Seminary" }, + { "value": "193070", "label": "Mesivtha Tifereth Jerusalem of America" }, + { "value": "417752", "label": "Messenger College" }, + { "value": "213996", "label": "Messiah College" }, + { "value": "147129", "label": "Methodist College" }, + { "value": "203997", "label": "Methodist Theological School in Ohio" }, + { "value": "198969", "label": "Methodist University" }, + { "value": "455673", "label": "Metro Business College-Arnold" }, + { "value": "178110", "label": "Metro Business College-Cape Girardeau" }, + { "value": "245430", "label": "Metro Business College-Jefferson City" }, + { "value": "245421", "label": "Metro Business College-Rolla" }, + { + "value": "214023", + "label": "Metropolitan Career Center Computer Technology Institute" + }, + { "value": "190114", "label": "Metropolitan College of New York" }, + { "value": "181303", "label": "Metropolitan Community College Area" }, + { + "value": "177995", + "label": "Metropolitan Community College-Kansas City-Kansas City" + }, + { "value": "174020", "label": "Metropolitan State University" }, + { "value": "127565", "label": "Metropolitan State University of Denver" }, + { "value": "166869", "label": "MGH Institute of Health Professions" }, + { "value": "135717", "label": "Miami Dade College" }, + { "value": "204006", "label": "Miami University-Hamilton" }, + { "value": "204015", "label": "Miami University-Middletown" }, + { "value": "204024", "label": "Miami University-Oxford" }, + { "value": "369862", "label": "Miami-Jacobs Career College-Columbus" }, + { "value": "204060", "label": "Miami-Jacobs Career College-Dayton" }, + { "value": "200633", "label": "Miami-Jacobs Career College-Independence" }, + { "value": "441201", "label": "Miami-Jacobs Career College-Sharonville" }, + { "value": "449126", "label": "Miami-Jacobs Career College-Springboro" }, + { "value": "450003", "label": "Miami-Jacobs Career College-Troy" }, + { "value": "169655", "label": "MIAT College of Technology" }, + { "value": "434414", "label": "Michigan Jewish Institute" }, + { + "value": "169220", + "label": "Michigan School of Professional Psychology" + }, + { "value": "171100", "label": "Michigan State University" }, + { "value": "169628", "label": "Michigan State University-College of Law" }, + { "value": "171128", "label": "Michigan Technological University" }, + { "value": "171155", "label": "Mid Michigan Community College" }, + { "value": "245953", "label": "Mid-America Christian University" }, + { "value": "151962", "label": "Mid-America College of Funeral Service" }, + { "value": "155520", "label": "MidAmerica Nazarene University" }, + { "value": "199458", "label": "Mid-Atlantic Christian University" }, + { "value": "482158", "label": "Middle Georgia State College" }, + { "value": "220996", "label": "Middle Tennessee School of Anesthesia Inc" }, + { "value": "220978", "label": "Middle Tennessee State University" }, + { "value": "230959", "label": "Middlebury College" }, + { "value": "166887", "label": "Middlesex Community College-Bedford" }, + { "value": "129756", "label": "Middlesex Community College-Middletown" }, + { "value": "185536", "label": "Middlesex County College" }, + { "value": "226806", "label": "Midland College" }, + { "value": "181330", "label": "Midland University" }, + { "value": "218353", "label": "Midlands Technical College" }, + { "value": "181312", "label": "Mid-Plains Community College" }, + { "value": "481225", "label": "Mid-South Christian College" }, + { "value": "147165", "label": "Midstate College" }, + { "value": "239220", "label": "Mid-State Technical College" }, + { "value": "157377", "label": "Midway College" }, + { + "value": "439020", + "label": "Midwest College of Oriental Medicine-Chicago" + }, + { + "value": "383020", + "label": "Midwest College of Oriental Medicine-Racine" + }, + { "value": "178183", "label": "Midwest Institute" }, + { "value": "178208", "label": "Midwestern Baptist Theological Seminary" }, + { "value": "226833", "label": "Midwestern State University" }, + { "value": "143853", "label": "Midwestern University-Downers Grove" }, + { "value": "423643", "label": "Midwestern University-Glendale" }, + { "value": "480985", "label": "Midwives College of Utah" }, + { "value": "193201", "label": "Mildred Elley School-Albany Campus" }, + { "value": "461014", "label": "Mildred Elley-New York Campus" }, + { "value": "101675", "label": "Miles College" }, + { "value": "180373", "label": "Miles Community College" }, + { "value": "461883", "label": "Millennia Atlantic University" }, + { "value": "449117", "label": "Miller-Motte College-Cary" }, + { "value": "458405", "label": "Miller-Motte College-Fayetteville" }, + { "value": "455655", "label": "Miller-Motte College-Greenville" }, + { "value": "460817", "label": "Miller-Motte College-Jacksonville" }, + { "value": "456205", "label": "Miller-Motte College-Raleigh" }, + { "value": "198978", "label": "Miller-Motte College-Wilmington" }, + { "value": "460826", "label": "Miller-Motte Technical College-Augusta" }, + { "value": "441025", "label": "Miller-Motte Technical College-Charleston" }, + { + "value": "443650", + "label": "Miller-Motte Technical College-Chattanooga" + }, + { + "value": "382771", + "label": "Miller-Motte Technical College-Clarksville" + }, + { "value": "458441", "label": "Miller-Motte Technical College-Columbus" }, + { "value": "460835", "label": "Miller-Motte Technical College-Conway" }, + { "value": "475079", "label": "Miller-Motte Technical College-Gulfport" }, + { "value": "233091", "label": "Miller-Motte Technical College-Lynchburg" }, + { "value": "475060", "label": "Miller-Motte Technical College-Macon" }, + { "value": "448664", "label": "Miller-Motte Technical College-Madison" }, + { "value": "475194", "label": "Miller-Motte Technical College-Roanoke" }, + { "value": "214041", "label": "Millersville University of Pennsylvania" }, + { "value": "221014", "label": "Milligan College" }, + { "value": "147244", "label": "Millikin University" }, + { "value": "118888", "label": "Mills College" }, + { "value": "175980", "label": "Millsaps College" }, + { "value": "239248", "label": "Milwaukee Area Technical College" }, + { "value": "239309", "label": "Milwaukee Institute of Art & Design" }, + { "value": "239318", "label": "Milwaukee School of Engineering" }, + { "value": "178217", "label": "Mineral Area College" }, + { "value": "174118", "label": "Minneapolis Business College" }, + { "value": "174127", "label": "Minneapolis College of Art and Design" }, + { + "value": "174136", + "label": "Minneapolis Community and Technical College" + }, + { "value": "474881", "label": "Minneapolis Media Institute" }, + { "value": "451769", "label": "Minnesota School of Business-Blaine" }, + { + "value": "407285", + "label": "Minnesota School of Business-Brooklyn Center" + }, + { "value": "456782", "label": "Minnesota School of Business-Elk River" }, + { "value": "458742", "label": "Minnesota School of Business-Lakeville" }, + { "value": "455585", "label": "Minnesota School of Business-Moorhead" }, + { "value": "442578", "label": "Minnesota School of Business-Plymouth" }, + { "value": "174279", "label": "Minnesota School of Business-Richfield" }, + { "value": "447670", "label": "Minnesota School of Business-Rochester" }, + { "value": "445920", "label": "Minnesota School of Business-Waite Park" }, + { + "value": "175263", + "label": "Minnesota State College-Southeast Technical" + }, + { + "value": "173559", + "label": "Minnesota State Community and Technical College" + }, + { "value": "174358", "label": "Minnesota State University Moorhead" }, + { "value": "173920", "label": "Minnesota State University-Mankato" }, + { + "value": "173638", + "label": "Minnesota West Community and Technical College" + }, + { "value": "200253", "label": "Minot State University" }, + { "value": "118912", "label": "MiraCosta College" }, + { "value": "193247", "label": "Mirrer Yeshiva Cent Institute" }, + { "value": "214069", "label": "Misericordia University" }, + { "value": "118930", "label": "Mission College" }, + { "value": "176053", "label": "Mississippi College" }, + { "value": "176008", "label": "Mississippi Delta Community College" }, + { "value": "176071", "label": "Mississippi Gulf Coast Community College" }, + { "value": "176080", "label": "Mississippi State University" }, + { "value": "176035", "label": "Mississippi University for Women" }, + { "value": "176044", "label": "Mississippi Valley State University" }, + { "value": "178244", "label": "Missouri Baptist University" }, + { "value": "178305", "label": "Missouri College" }, + { "value": "178341", "label": "Missouri Southern State University" }, + { "value": "179566", "label": "Missouri State University-Springfield" }, + { "value": "179344", "label": "Missouri State University-West Plains" }, + { "value": "178350", "label": "Missouri Tech" }, + { + "value": "178411", + "label": "Missouri University of Science and Technology" + }, + { "value": "178369", "label": "Missouri Valley College" }, + { "value": "178387", "label": "Missouri Western State University" }, + { "value": "129774", "label": "Mitchell College" }, + { "value": "198987", "label": "Mitchell Community College" }, + { "value": "219189", "label": "Mitchell Technical Institute" }, + { "value": "178448", "label": "Moberly Area Community College" }, + { "value": "118976", "label": "Modesto Junior College" }, + { "value": "105206", "label": "Mohave Community College" }, + { "value": "193283", "label": "Mohawk Valley Community College" }, + { "value": "193292", "label": "Molloy College" }, + { "value": "147341", "label": "Monmouth College" }, + { "value": "185572", "label": "Monmouth University" }, + { "value": "193308", "label": "Monroe College" }, + { "value": "193326", "label": "Monroe Community College" }, + { "value": "171225", "label": "Monroe County Community College" }, + { "value": "262165", "label": "Montana Bible College" }, + { "value": "180461", "label": "Montana State University" }, + { "value": "180179", "label": "Montana State University-Billings" }, + { "value": "180522", "label": "Montana State University-Northern" }, + { "value": "180416", "label": "Montana Tech of the University of Montana" }, + { "value": "171234", "label": "Montcalm Community College" }, + { "value": "185590", "label": "Montclair State University" }, + { + "value": "119058", + "label": "Monterey Institute of International Studies" + }, + { "value": "119067", "label": "Monterey Peninsula College" }, + { "value": "163426", "label": "Montgomery College" }, + { "value": "199023", "label": "Montgomery Community College" }, + { "value": "214111", "label": "Montgomery County Community College" }, + { "value": "199032", "label": "Montreat College" }, + { "value": "166911", "label": "Montserrat College of Art" }, + { "value": "147369", "label": "Moody Bible Institute" }, + { "value": "214148", "label": "Moore College of Art and Design" }, + { "value": "119137", "label": "Moorpark College" }, + { "value": "239372", "label": "Moraine Park Technical College" }, + { "value": "147378", "label": "Moraine Valley Community College" }, + { "value": "214157", "label": "Moravian College" }, + { "value": "157386", "label": "Morehead State University" }, + { "value": "140553", "label": "Morehouse College" }, + { "value": "140562", "label": "Morehouse School of Medicine" }, + { "value": "460394", "label": "Moreno Valley College" }, + { "value": "127617", "label": "Morgan Community College" }, + { "value": "163453", "label": "Morgan State University" }, + { "value": "154004", "label": "Morningside College" }, + { "value": "218399", "label": "Morris College" }, + { "value": "147396", "label": "Morrison Institute of Technology" }, + { "value": "196051", "label": "Morrisville State College" }, + { "value": "147411", "label": "Morton College" }, + { "value": "221096", "label": "Motlow State Community College" }, + { "value": "169275", "label": "Mott Community College" }, + { "value": "140599", "label": "Moultrie Technical College" }, + { "value": "214166", "label": "Mount Aloysius College" }, + { "value": "209241", "label": "Mount Angel Seminary" }, + { "value": "204176", "label": "Mount Carmel College of Nursing" }, + { "value": "166939", "label": "Mount Holyoke College" }, + { "value": "166948", "label": "Mount Ida College" }, + { "value": "219198", "label": "Mount Marty College" }, + { "value": "239390", "label": "Mount Mary University" }, + { "value": "154013", "label": "Mount Mercy University" }, + { "value": "204200", "label": "Mount Saint Joseph University" }, + { "value": "193353", "label": "Mount Saint Mary College" }, + { "value": "119173", "label": "Mount Saint Mary's University" }, + { "value": "163462", "label": "Mount St Mary's University" }, + { "value": "204194", "label": "Mount Vernon Nazarene University" }, + { "value": "166957", "label": "Mount Wachusett Community College" }, + { "value": "182865", "label": "Mount Washington College" }, + { "value": "232788", "label": "Mountain Empire Community College" }, + { "value": "237598", "label": "Mountain State College" }, + { "value": "226930", "label": "Mountain View College" }, + { "value": "444954", "label": "Mountwest Community and Technical College" }, + { "value": "209250", "label": "Mt Hood Community College" }, + { "value": "119164", "label": "Mt San Antonio College" }, + { "value": "119216", "label": "Mt San Jacinto Community College District" }, + { "value": "398130", "label": "Mt Sierra College" }, + { "value": "118198", "label": "MTI College" }, + { "value": "214175", "label": "Muhlenberg College" }, + { "value": "209287", "label": "Multnomah University" }, + { "value": "207236", "label": "Murray State College" }, + { "value": "157401", "label": "Murray State University" }, + { "value": "119270", "label": "Musicians Institute" }, + { "value": "171304", "label": "Muskegon Community College" }, + { "value": "204264", "label": "Muskingum University" }, + { "value": "434432", "label": "Myotherapy Institute" }, + { "value": "119331", "label": "Napa Valley College" }, + { "value": "127653", "label": "Naropa University" }, + { "value": "199087", "label": "Nash Community College" }, + { "value": "239424", "label": "Nashotah House" }, + { "value": "183141", "label": "Nashua Community College" }, + { "value": "221184", "label": "Nashville State Community College" }, + { "value": "193478", "label": "Nassau Community College" }, + { "value": "248882", "label": "National American University-Albuquerque" }, + { + "value": "440758", + "label": "National American University-Albuquerque West" + }, + { "value": "451875", "label": "National American University-Austin" }, + { "value": "482307", "label": "National American University-Austin South" }, + { "value": "477996", "label": "National American University-Bellevue" }, + { "value": "436483", "label": "National American University-Bloomington" }, + { + "value": "440767", + "label": "National American University-Brooklyn Center" + }, + { "value": "478005", "label": "National American University-Burnsville" }, + { "value": "466161", "label": "National American University-Centennial" }, + { + "value": "127680", + "label": "National American University-Colorado Springs" + }, + { + "value": "466189", + "label": "National American University-Colorado Springs South" + }, + { "value": "127699", "label": "National American University-Denver" }, + { + "value": "440749", + "label": "National American University-Ellsworth AFB Extension" + }, + { "value": "482325", "label": "National American University-Georgetown" }, + { + "value": "485290", + "label": "National American University-Harold D. Buckingham Graduate School" + }, + { "value": "247700", "label": "National American University-Independence" }, + { "value": "482370", "label": "National American University-Indianapolis" }, + { "value": "466170", "label": "National American University-Lee's Summit" }, + { "value": "482316", "label": "National American University-Lewisville" }, + { + "value": "442718", + "label": "National American University-Overland Park" + }, + { "value": "219204", "label": "National American University-Rapid City" }, + { "value": "482343", "label": "National American University-Rochester" }, + { "value": "174385", "label": "National American University-Roseville" }, + { "value": "219213", "label": "National American University-Sioux Falls" }, + { "value": "466152", "label": "National American University-Tulsa" }, + { + "value": "482352", + "label": "National American University-Weldon Spring" + }, + { "value": "451884", "label": "National American University-Wichita" }, + { "value": "482361", "label": "National American University-Wichita West" }, + { "value": "448585", "label": "National American University-Zona Rosa" }, + { "value": "209296", "label": "National College of Natural Medicine" }, + { "value": "480480", "label": "National College-Canton" }, + { "value": "453473", "label": "National College-Cincinnati" }, + { "value": "457004", "label": "National College-Columbus" }, + { "value": "453455", "label": "National College-Dayton" }, + { "value": "157021", "label": "National College-Lexington" }, + { "value": "388043", "label": "National College-Nashville" }, + { "value": "453482", "label": "National College-Stow" }, + { "value": "459833", "label": "National College-Willoughby Hills" }, + { "value": "453464", "label": "National College-Youngstown" }, + { + "value": "441478", + "label": "National Graduate School of Quality Management" + }, + { "value": "412003", "label": "National Institute of Massotherapy" }, + { "value": "147536", "label": "National Louis University" }, + { "value": "448114", "label": "National Massage Therapy Institute" }, + { "value": "461023", "label": "National Paralegal College" }, + { "value": "106980", "label": "National Park Community College" }, + { "value": "119605", "label": "National University" }, + { "value": "242981", "label": "National University College-Arecibo" }, + { "value": "242972", "label": "National University College-Bayamon" }, + { "value": "468723", "label": "National University College-Caguas" }, + { "value": "458469", "label": "National University College-Ponce" }, + { "value": "444042", "label": "National University College-Rio Grande" }, + { "value": "147590", "label": "National University of Health Sciences" }, + { "value": "129729", "label": "Naugatuck Valley Community College" }, + { "value": "187596", "label": "Navajo Technical University" }, + { "value": "119678", "label": "Naval Postgraduate School" }, + { "value": "227146", "label": "Navarro College" }, + { "value": "127714", "label": "Nazarene Bible College" }, + { "value": "178518", "label": "Nazarene Theological Seminary" }, + { "value": "193584", "label": "Nazareth College" }, + { "value": "181376", "label": "Nebraska Christian College" }, + { "value": "181765", "label": "Nebraska College of Technical Agriculture" }, + { "value": "181419", "label": "Nebraska Indian Community College" }, + { + "value": "181297", + "label": "Nebraska Methodist College of Nursing & Allied Health" + }, + { "value": "181446", "label": "Nebraska Wesleyan University" }, + { "value": "155566", "label": "Neosho County Community College" }, + { "value": "163532", "label": "Ner Israel Rabbinical College" }, + { "value": "214272", "label": "Neumann University" }, + { "value": "445692", "label": "Neumont University" }, + { "value": "441900", "label": "Nevada State College" }, + { "value": "185758", "label": "New Brunswick Theological Seminary" }, + { "value": "214290", "label": "New Castle School of Trades" }, + { "value": "262129", "label": "New College of Florida" }, + { "value": "182980", "label": "New England College" }, + { + "value": "164438", + "label": "New England College of Business and Finance" + }, + { "value": "167093", "label": "New England College of Optometry" }, + { "value": "230977", "label": "New England Culinary Institute" }, + { "value": "217305", "label": "New England Institute of Technology" }, + { "value": "167215", "label": "New England Law-Boston" }, + { "value": "167181", "label": "New England School of Acupuncture" }, + { "value": "430810", "label": "New Hampshire Institute of Art" }, + { "value": "208725", "label": "New Hope Christian College-Eugene" }, + { "value": "185129", "label": "New Jersey City University" }, + { "value": "185828", "label": "New Jersey Institute of Technology" }, + { "value": "187897", "label": "New Mexico Highlands University" }, + { + "value": "187967", + "label": "New Mexico Institute of Mining and Technology" + }, + { "value": "187903", "label": "New Mexico Junior College" }, + { "value": "187912", "label": "New Mexico Military Institute" }, + { "value": "187994", "label": "New Mexico State University-Alamogordo" }, + { "value": "188003", "label": "New Mexico State University-Carlsbad" }, + { "value": "187620", "label": "New Mexico State University-Dona Ana" }, + { "value": "188021", "label": "New Mexico State University-Grants" }, + { "value": "188030", "label": "New Mexico State University-Main Campus" }, + { "value": "159948", "label": "New Orleans Baptist Theological Seminary" }, + { "value": "447582", "label": "New River Community and Technical College" }, + { "value": "232867", "label": "New River Community College" }, + { "value": "366368", "label": "New York Academy of Art" }, + { "value": "195845", "label": "New York Career Institute" }, + { "value": "193751", "label": "New York Chiropractic College" }, + { "value": "418126", "label": "New York College of Health Professions" }, + { "value": "194073", "label": "New York College of Podiatric Medicine" }, + { + "value": "439783", + "label": "New York College of Traditional Chinese Medicine" + }, + { "value": "421841", "label": "New York Conservatory for Dramatic Arts" }, + { "value": "461148", "label": "New York Film Academy" }, + { "value": "194091", "label": "New York Institute of Technology" }, + { "value": "193821", "label": "New York Law School" }, + { "value": "193830", "label": "New York Medical College" }, + { "value": "194116", "label": "New York School of Interior Design" }, + { "value": "193894", "label": "New York Theological Seminary" }, + { "value": "193900", "label": "New York University" }, + { "value": "218414", "label": "Newberry College" }, + { "value": "167251", "label": "Newbury College" }, + { "value": "155335", "label": "Newman University" }, + { "value": "119775", "label": "Newschool of Architecture and Design" }, + { "value": "183099", "label": "NHTI-Concord's Community College" }, + { "value": "193946", "label": "Niagara County Community College" }, + { "value": "193973", "label": "Niagara University" }, + { "value": "159966", "label": "Nicholls State University" }, + { "value": "167260", "label": "Nichols College" }, + { "value": "239442", "label": "Nicolet Area Technical College" }, + { "value": "444787", "label": "Nightingale College" }, + { "value": "460464", "label": "Norco College" }, + { "value": "232937", "label": "Norfolk State University" }, + { "value": "174428", "label": "Normandale Community College" }, + { "value": "461795", "label": "North American University" }, + { "value": "107460", "label": "North Arkansas College" }, + { "value": "199102", "label": "North Carolina A & T State University" }, + { "value": "199157", "label": "North Carolina Central University" }, + { + "value": "199193", + "label": "North Carolina State University at Raleigh" + }, + { "value": "199209", "label": "North Carolina Wesleyan College" }, + { "value": "147660", "label": "North Central College" }, + { "value": "418889", "label": "North Central Institute" }, + { "value": "155593", "label": "North Central Kansas Technical College" }, + { "value": "171395", "label": "North Central Michigan College" }, + { "value": "179715", "label": "North Central Missouri College" }, + { "value": "204422", "label": "North Central State College" }, + { "value": "224110", "label": "North Central Texas College" }, + { "value": "174437", "label": "North Central University" }, + { "value": "194028", "label": "North Country Community College" }, + { "value": "200305", "label": "North Dakota State College of Science" }, + { "value": "200332", "label": "North Dakota State University-Main Campus" }, + { "value": "136145", "label": "North Florida Community College" }, + { "value": "140678", "label": "North Georgia Technical College" }, + { "value": "218441", "label": "North Greenville University" }, + { "value": "174376", "label": "North Hennepin Community College" }, + { "value": "142443", "label": "North Idaho College" }, + { "value": "154059", "label": "North Iowa Area Community College" }, + { "value": "227191", "label": "North Lake College" }, + { "value": "147679", "label": "North Park University" }, + { "value": "236072", "label": "North Seattle College" }, + { "value": "167312", "label": "North Shore Community College" }, + { "value": "214379", "label": "Northampton County Area Community College" }, + { "value": "239460", "label": "Northcentral Technical College" }, + { "value": "444130", "label": "Northcentral University" }, + { "value": "101897", "label": "Northeast Alabama Community College" }, + { "value": "182917", "label": "Northeast Catholic College" }, + { "value": "181491", "label": "Northeast Community College" }, + { "value": "154110", "label": "Northeast Iowa Community College" }, + { "value": "176169", "label": "Northeast Mississippi Community College" }, + { "value": "204477", "label": "Northeast Ohio Medical University" }, + { "value": "221908", "label": "Northeast State Community College" }, + { "value": "227225", "label": "Northeast Texas Community College" }, + { "value": "239488", "label": "Northeast Wisconsin Technical College" }, + { "value": "147776", "label": "Northeastern Illinois University" }, + { "value": "127732", "label": "Northeastern Junior College" }, + { "value": "207290", "label": "Northeastern Oklahoma A&M College" }, + { "value": "439817", "label": "Northeastern Seminary" }, + { "value": "207263", "label": "Northeastern State University" }, + { "value": "217837", "label": "Northeastern Technical College" }, + { "value": "167358", "label": "Northeastern University" }, + { "value": "482705", "label": "Northeastern University Global Network" }, + { "value": "105330", "label": "Northern Arizona University" }, + { "value": "147697", "label": "Northern Baptist Theological Seminary" }, + { "value": "167376", "label": "Northern Essex Community College" }, + { "value": "147703", "label": "Northern Illinois University" }, + { "value": "157447", "label": "Northern Kentucky University" }, + { "value": "161484", "label": "Northern Maine Community College" }, + { "value": "240790", "label": "Northern Marianas College" }, + { "value": "171456", "label": "Northern Michigan University" }, + { "value": "188058", "label": "Northern New Mexico College" }, + { "value": "207281", "label": "Northern Oklahoma College" }, + { "value": "219259", "label": "Northern State University" }, + { "value": "232946", "label": "Northern Virginia Community College" }, + { "value": "239512", "label": "Northland College" }, + { "value": "174473", "label": "Northland Community and Technical College" }, + { "value": "239503", "label": "Northland International University" }, + { "value": "105349", "label": "Northland Pioneer College" }, + { "value": "217606", "label": "Northpoint Bible College" }, + { "value": "160667", "label": "Northshore Technical Community College" }, + { "value": "367459", "label": "NorthWest Arkansas Community College" }, + { "value": "445948", "label": "Northwest Career College" }, + { "value": "209409", "label": "Northwest Christian University" }, + { "value": "240657", "label": "Northwest College" }, + { "value": "377546", "label": "Northwest College of Art & Design" }, + { "value": "136233", "label": "Northwest Florida State College" }, + { "value": "380377", "label": "Northwest Indian College" }, + { "value": "460941", "label": "Northwest Institute of Literary Arts" }, + { "value": "154129", "label": "Northwest Iowa Community College" }, + { "value": "155618", "label": "Northwest Kansas Technical College" }, + { "value": "160010", "label": "Northwest Louisiana Technical College" }, + { "value": "176178", "label": "Northwest Mississippi Community College" }, + { "value": "178624", "label": "Northwest Missouri State University" }, + { "value": "142461", "label": "Northwest Nazarene University" }, + { "value": "458140", "label": "Northwest School of Wooden Boat Building" }, + { "value": "204440", "label": "Northwest State Community College" }, + { "value": "173115", "label": "Northwest Technical College" }, + { "value": "236133", "label": "Northwest University" }, + { "value": "420398", "label": "Northwest Vista College" }, + { "value": "154101", "label": "Northwestern College" }, + { "value": "147749", "label": "Northwestern College-Chicago Campus" }, + { "value": "260992", "label": "Northwestern College-Southwestern Campus" }, + { + "value": "130040", + "label": "Northwestern Connecticut Community College" + }, + { "value": "174507", "label": "Northwestern Health Sciences University" }, + { "value": "171483", "label": "Northwestern Michigan College" }, + { "value": "207306", "label": "Northwestern Oklahoma State University" }, + { + "value": "160038", + "label": "Northwestern State University of Louisiana" + }, + { "value": "147767", "label": "Northwestern University" }, + { "value": "101736", "label": "Northwest-Shoals Community College" }, + { "value": "136206", "label": "Northwood University-Florida" }, + { "value": "171492", "label": "Northwood University-Michigan" }, + { "value": "227243", "label": "Northwood University-Texas" }, + { "value": "130004", "label": "Norwalk Community College" }, + { "value": "230995", "label": "Norwich University" }, + { "value": "368452", "label": "Nossi College of Art" }, + { "value": "204468", "label": "Notre Dame College" }, + { "value": "120184", "label": "Notre Dame de Namur University" }, + { "value": "163578", "label": "Notre Dame of Maryland University" }, + { + "value": "160029", + "label": "Notre Dame Seminary Graduate School of Theology" + }, + { "value": "136215", "label": "Nova Southeastern University" }, + { "value": "200086", "label": "Nueta Hidatsa Sahnish College" }, + { "value": "158884", "label": "Nunez Community College" }, + { "value": "194161", "label": "Nyack College" }, + { "value": "174525", "label": "Oak Hills Christian College" }, + { "value": "152099", "label": "Oakland City University" }, + { "value": "171535", "label": "Oakland Community College" }, + { "value": "171571", "label": "Oakland University" }, + { "value": "147800", "label": "Oakton Community College" }, + { "value": "101912", "label": "Oakwood University" }, + { "value": "204501", "label": "Oberlin College" }, + { "value": "227289", "label": "Oblate School of Theology" }, + { "value": "120254", "label": "Occidental College" }, + { "value": "185873", "label": "Ocean County College" }, + { "value": "420431", "label": "Oconee Fall Line Technical College" }, + { "value": "227304", "label": "Odessa College" }, + { "value": "366465", "label": "Ogeechee Technical College" }, + { "value": "219277", "label": "Oglala Lakota College" }, + { "value": "140696", "label": "Oglethorpe University" }, + { "value": "453747", "label": "Ohio Business College-Hilliard" }, + { "value": "203739", "label": "Ohio Business College-Sandusky" }, + { "value": "203720", "label": "Ohio Business College-Sheffield" }, + { "value": "201964", "label": "Ohio Christian University" }, + { "value": "204592", "label": "Ohio College of Massotherapy Inc" }, + { "value": "204617", "label": "Ohio Dominican University" }, + { "value": "206002", "label": "Ohio Mid-Western College" }, + { "value": "204635", "label": "Ohio Northern University" }, + { + "value": "204662", + "label": "Ohio State University Agricultural Technical Institute" + }, + { "value": "204671", "label": "Ohio State University-Lima Campus" }, + { "value": "204796", "label": "Ohio State University-Main Campus" }, + { "value": "204680", "label": "Ohio State University-Mansfield Campus" }, + { "value": "204699", "label": "Ohio State University-Marion Campus" }, + { "value": "204705", "label": "Ohio State University-Newark Campus" }, + { "value": "204608", "label": "Ohio Technical College" }, + { + "value": "453817", + "label": "Ohio Technical College-PowerSport Institute" + }, + { "value": "204820", "label": "Ohio University-Chillicothe Campus" }, + { "value": "204802", "label": "Ohio University-Eastern Campus" }, + { "value": "204848", "label": "Ohio University-Lancaster Campus" }, + { "value": "204857", "label": "Ohio University-Main Campus" }, + { "value": "204839", "label": "Ohio University-Southern Campus" }, + { "value": "204866", "label": "Ohio University-Zanesville Campus" }, + { "value": "204884", "label": "Ohio Valley College of Technology" }, + { "value": "237640", "label": "Ohio Valley University" }, + { "value": "204909", "label": "Ohio Wesleyan University" }, + { "value": "120290", "label": "Ohlone College" }, + { "value": "194189", "label": "Ohr Hameir Theological Seminary" }, + { "value": "207403", "label": "Oklahoma Baptist University" }, + { "value": "207324", "label": "Oklahoma Christian University" }, + { "value": "207449", "label": "Oklahoma City Community College" }, + { "value": "207458", "label": "Oklahoma City University" }, + { "value": "207351", "label": "Oklahoma Panhandle State University" }, + { + "value": "207315", + "label": "Oklahoma State University Center for Health Sciences" + }, + { + "value": "207564", + "label": "Oklahoma State University Institute of Technology" + }, + { "value": "207388", "label": "Oklahoma State University-Main Campus" }, + { "value": "207397", "label": "Oklahoma State University-Oklahoma City" }, + { "value": "469629", "label": "Oklahoma Technical College" }, + { "value": "206835", "label": "Oklahoma Wesleyan University" }, + { "value": "232982", "label": "Old Dominion University" }, + { "value": "171599", "label": "Olivet College" }, + { "value": "147828", "label": "Olivet Nazarene University" }, + { "value": "145707", "label": "Olney Central College" }, + { "value": "236188", "label": "Olympic College" }, + { + "value": "407328", + "label": "Omaha School of Massage and Healthcare of Herzing University" + }, + { "value": "221254", "label": "O'More College of Design" }, + { "value": "194222", "label": "Onondaga Community College" }, + { "value": "207582", "label": "Oral Roberts University" }, + { "value": "120342", "label": "Orange Coast College" }, + { "value": "194240", "label": "Orange County Community College" }, + { "value": "218487", "label": "Orangeburg Calhoun Technical College" }, + { "value": "423652", "label": "Oregon Coast Community College" }, + { "value": "209533", "label": "Oregon College of Art and Craft" }, + { "value": "369659", "label": "Oregon College of Oriental Medicine" }, + { "value": "209490", "label": "Oregon Health & Science University" }, + { "value": "209506", "label": "Oregon Institute of Technology" }, + { "value": "209542", "label": "Oregon State University" }, + { "value": "454883", "label": "Orion College" }, + { "value": "214528", "label": "Orleans Technical Institute" }, + { "value": "127778", "label": "Otero Junior College" }, + { "value": "120403", "label": "Otis College of Art and Design" }, + { "value": "442897", "label": "Ottawa University-Jeffersonville" }, + { "value": "155636", "label": "Ottawa University-Kansas City" }, + { "value": "428259", "label": "Ottawa University-Milwaukee" }, + { "value": "454582", "label": "Ottawa University-Online" }, + { "value": "155627", "label": "Ottawa University-Ottawa" }, + { "value": "105367", "label": "Ottawa University-Phoenix" }, + { "value": "204936", "label": "Otterbein University" }, + { "value": "107512", "label": "Ouachita Baptist University" }, + { "value": "160074", "label": "Our Lady of the Lake College" }, + { "value": "227331", "label": "Our Lady of the Lake University" }, + { "value": "204945", "label": "Owens Community College" }, + { "value": "247940", "label": "Owensboro Community and Technical College" }, + { "value": "461120", "label": "Oxford Graduate School" }, + { "value": "120421", "label": "Oxnard College" }, + { "value": "178679", "label": "Ozark Christian College" }, + { "value": "107549", "label": "Ozarka College" }, + { "value": "177472", "label": "Ozarks Technical Community College" }, + { "value": "214838", "label": "Pace Institute" }, + { "value": "194310", "label": "Pace University-New York" }, + { "value": "422695", "label": "Pacific College" }, + { + "value": "442842", + "label": "Pacific College of Oriental Medicine-Chicago" + }, + { + "value": "414595", + "label": "Pacific College of Oriental Medicine-New York" + }, + { + "value": "378576", + "label": "Pacific College of Oriental Medicine-San Diego" + }, + { "value": "439862", "label": "Pacific Islands University" }, + { "value": "120740", "label": "Pacific Lutheran Theological Seminary" }, + { "value": "236230", "label": "Pacific Lutheran University" }, + { "value": "209603", "label": "Pacific Northwest College of Art" }, + { + "value": "455406", + "label": "Pacific Northwest University of Health Sciences" + }, + { "value": "120768", "label": "Pacific Oaks College" }, + { "value": "457484", "label": "Pacific Rim Christian University" }, + { "value": "120795", "label": "Pacific School of Religion" }, + { "value": "120838", "label": "Pacific States University" }, + { "value": "120865", "label": "Pacific Union College" }, + { "value": "209612", "label": "Pacific University" }, + { "value": "115746", "label": "Pacifica Graduate Institute" }, + { "value": "130110", "label": "Paier College of Art Inc" }, + { "value": "140720", "label": "Paine College" }, + { "value": "243647", "label": "Palau Community College" }, + { "value": "136330", "label": "Palm Beach Atlantic University" }, + { "value": "136358", "label": "Palm Beach State College" }, + { "value": "154174", "label": "Palmer College of Chiropractic" }, + { "value": "246354", "label": "Palo Alto College" }, + { "value": "120698", "label": "Palo Alto University" }, + { "value": "120953", "label": "Palo Verde College" }, + { "value": "120971", "label": "Palomar College" }, + { "value": "199263", "label": "Pamlico Community College" }, + { "value": "227386", "label": "Panola College" }, + { "value": "364016", "label": "Paradise Valley Community College" }, + { "value": "121628", "label": "Pardee RAND Graduate School" }, + { "value": "227401", "label": "Paris Junior College" }, + { "value": "178721", "label": "Park University" }, + { "value": "243823", "label": "Parker University" }, + { "value": "147916", "label": "Parkland College" }, + { "value": "121044", "label": "Pasadena City College" }, + { "value": "136400", "label": "Pasco-Hernando State College" }, + { "value": "186034", "label": "Passaic County Community College" }, + { "value": "666666", "label": "Patrick Henry College" }, + { "value": "233019", "label": "Patrick Henry Community College" }, + { "value": "233037", "label": "Paul D Camp Community College" }, + { "value": "227429", "label": "Paul Quinn College" }, + { "value": "194392", "label": "Paul Smiths College of Arts and Science" }, + { "value": "204990", "label": "Payne Theological Seminary" }, + { "value": "176239", "label": "Pearl River Community College" }, + { "value": "214883", "label": "Peirce College" }, + { "value": "221643", "label": "Pellissippi State Community College" }, + { "value": "236258", "label": "Peninsula College" }, + { "value": "214892", "label": "Penn Commercial Business/Technical School" }, + { "value": "214944", "label": "Pennco Tech-Bristol" }, + { "value": "214971", "label": "Pennsylvania Academy of the Fine Arts" }, + { "value": "215053", "label": "Pennsylvania College of Art and Design" }, + { "value": "442356", "label": "Pennsylvania College of Health Sciences" }, + { "value": "366252", "label": "Pennsylvania College of Technology" }, + { "value": "414911", "label": "Pennsylvania Highlands Community College" }, + { + "value": "261861", + "label": "Pennsylvania Institute of Health and Technology" + }, + { "value": "214582", "label": "Pennsylvania Institute of Technology" }, + { + "value": "214616", + "label": "Pennsylvania State University-College of Medicine" + }, + { + "value": "212018", + "label": "Pennsylvania State University-Dickinson Law" + }, + { "value": "214777", "label": "Pennsylvania State University-Main Campus" }, + { + "value": "214801", + "label": "Pennsylvania State University-Penn State Abington" + }, + { + "value": "214689", + "label": "Pennsylvania State University-Penn State Altoona" + }, + { + "value": "214698", + "label": "Pennsylvania State University-Penn State Beaver" + }, + { + "value": "214704", + "label": "Pennsylvania State University-Penn State Berks" + }, + { + "value": "214731", + "label": "Pennsylvania State University-Penn State Brandywine" + }, + { + "value": "214740", + "label": "Pennsylvania State University-Penn State DuBois" + }, + { + "value": "214591", + "label": "Pennsylvania State University-Penn State Erie-Behrend College" + }, + { + "value": "214759", + "label": "Pennsylvania State University-Penn State Fayette- Eberly" + }, + { + "value": "214607", + "label": "Pennsylvania State University-Penn State Great Valley" + }, + { + "value": "214786", + "label": "Pennsylvania State University-Penn State Greater Allegheny" + }, + { + "value": "214713", + "label": "Pennsylvania State University-Penn State Harrisburg" + }, + { + "value": "214768", + "label": "Pennsylvania State University-Penn State Hazleton" + }, + { + "value": "214670", + "label": "Pennsylvania State University-Penn State Lehigh Valley" + }, + { + "value": "214795", + "label": "Pennsylvania State University-Penn State Mont Alto" + }, + { + "value": "214625", + "label": "Pennsylvania State University-Penn State New Kensington" + }, + { + "value": "214810", + "label": "Pennsylvania State University-Penn State Schuylkill" + }, + { + "value": "214634", + "label": "Pennsylvania State University-Penn State Shenango" + }, + { + "value": "214643", + "label": "Pennsylvania State University-Penn State Wilkes-Barre" + }, + { + "value": "214652", + "label": "Pennsylvania State University-Penn State Worthington Scranton" + }, + { + "value": "214829", + "label": "Pennsylvania State University-Penn State York" + }, + { + "value": "479956", + "label": "Pennsylvania State University-World Campus" + }, + { "value": "136473", "label": "Pensacola State College" }, + { "value": "219842", "label": "Pentecostal Theological Seminary" }, + { "value": "121150", "label": "Pepperdine University" }, + { "value": "181534", "label": "Peru State College" }, + { "value": "199306", "label": "Pfeiffer University" }, + { + "value": "215123", + "label": "Philadelphia College of Osteopathic Medicine" + }, + { "value": "215099", "label": "Philadelphia University" }, + { "value": "107600", "label": "Philander Smith College" }, + { "value": "189282", "label": "Phillips Beth Israel School of Nursing" }, + { + "value": "107619", + "label": "Phillips Community College of the University of Arkansas" + }, + { "value": "110307", "label": "Phillips Graduate Institute" }, + { "value": "414966", "label": "Phillips Theological Seminary" }, + { "value": "105428", "label": "Phoenix College" }, + { + "value": "447698", + "label": "Phoenix Institute of Herbal Medicine & Acupuncture" + }, + { "value": "381459", "label": "Phoenix Seminary" }, + { "value": "140818", "label": "Piedmont College" }, + { "value": "199324", "label": "Piedmont Community College" }, + { "value": "199315", "label": "Piedmont International University" }, + { "value": "218520", "label": "Piedmont Technical College" }, + { "value": "233116", "label": "Piedmont Virginia Community College" }, + { "value": "235237", "label": "Pierce College-Fort Steilacoom" }, + { "value": "439145", "label": "Pierce College-Puyallup" }, + { "value": "443492", "label": "Pierpont Community and Technical College" }, + { "value": "127820", "label": "Pikes Peak Community College" }, + { "value": "440794", "label": "Pillar College" }, + { "value": "105525", "label": "Pima Community College" }, + { "value": "105543", "label": "Pima Medical Institute-Albuquerque" }, + { "value": "461689", "label": "Pima Medical Institute-Aurora" }, + { "value": "434140", "label": "Pima Medical Institute-Chula Vista" }, + { "value": "442134", "label": "Pima Medical Institute-Colorado Springs" }, + { "value": "404912", "label": "Pima Medical Institute-Denver" }, + { "value": "456038", "label": "Pima Medical Institute-East Valley" }, + { "value": "460136", "label": "Pima Medical Institute-Houston" }, + { "value": "445230", "label": "Pima Medical Institute-Las Vegas" }, + { "value": "260691", "label": "Pima Medical Institute-Mesa" }, + { "value": "449074", "label": "Pima Medical Institute-Renton" }, + { "value": "368629", "label": "Pima Medical Institute-Seattle" }, + { "value": "105534", "label": "Pima Medical Institute-Tucson" }, + { "value": "458159", "label": "Pinchot University" }, + { "value": "167455", "label": "Pine Manor College" }, + { "value": "174570", "label": "Pine Technical & Community College" }, + { "value": "367097", "label": "Pinnacle Career Institute-Lawrence" }, + { + "value": "453109", + "label": "Pinnacle Career Institute-North Kansas City" + }, + { + "value": "177302", + "label": "Pinnacle Career Institute-South Kansas City" + }, + { "value": "210076", "label": "Pioneer Pacific College" }, + { "value": "199333", "label": "Pitt Community College" }, + { "value": "155681", "label": "Pittsburg State University" }, + { "value": "216782", "label": "Pittsburgh Career Institute" }, + { "value": "215381", "label": "Pittsburgh Institute of Aeronautics" }, + { + "value": "215390", + "label": "Pittsburgh Institute of Mortuary Science Inc" + }, + { "value": "215415", "label": "Pittsburgh Technical Institute" }, + { "value": "215424", "label": "Pittsburgh Theological Seminary" }, + { "value": "121257", "label": "Pitzer College" }, + { "value": "260813", "label": "Platt College-Aurora" }, + { "value": "207625", "label": "Platt College-Central OKC" }, + { "value": "260789", "label": "Platt College-Los Angeles" }, + { "value": "447379", "label": "Platt College-Moore" }, + { "value": "445258", "label": "Platt College-North OKC" }, + { "value": "432384", "label": "Platt College-Ontario" }, + { "value": "480204", "label": "Platt College-Riverside" }, + { "value": "121275", "label": "Platt College-San Diego" }, + { "value": "245962", "label": "Platt College-Tulsa" }, + { "value": "194499", "label": "Plaza College" }, + { "value": "183080", "label": "Plymouth State University" }, + { "value": "121309", "label": "Point Loma Nazarene University" }, + { "value": "215442", "label": "Point Park University" }, + { "value": "138868", "label": "Point University" }, + { "value": "136516", "label": "Polk State College" }, + { + "value": "456481", + "label": "Polytechnic University of Puerto Rico-Miami" + }, + { + "value": "456490", + "label": "Polytechnic University of Puerto Rico-Orlando" + }, + { + "value": "190451", + "label": "Pomeroy College of Nursing at Crouse Hospital" + }, + { "value": "121345", "label": "Pomona College" }, + { "value": "243081", "label": "Ponce Health Sciences University" }, + { "value": "243072", "label": "Ponce Paramedical College Inc" }, + { + "value": "241395", + "label": "Pontifical Catholic University of Puerto Rico-Arecibo" + }, + { + "value": "243586", + "label": "Pontifical Catholic University of Puerto Rico-Mayaguez" + }, + { + "value": "241410", + "label": "Pontifical Catholic University of Puerto Rico-Ponce" + }, + { "value": "205027", "label": "Pontifical College Josephinum" }, + { + "value": "131405", + "label": "Pontifical Faculty of the Immaculate Conception at the Dominican House of Studies" + }, + { + "value": "455813", + "label": "Pontifical John Paul II Institute for Studies on Marriage and Family" + }, + { "value": "167464", "label": "Pope St John XXIII National Seminary" }, + { "value": "121363", "label": "Porterville College" }, + { "value": "209746", "label": "Portland Community College" }, + { "value": "209807", "label": "Portland State University" }, + { "value": "130183", "label": "Post University" }, + { + "value": "237701", + "label": "Potomac State College of West Virginia University" + }, + { "value": "148007", "label": "Prairie State College" }, + { "value": "227526", "label": "Prairie View A & M University" }, + { "value": "155715", "label": "Pratt Community College" }, + { "value": "194578", "label": "Pratt Institute-Main" }, + { "value": "218539", "label": "Presbyterian College" }, + { "value": "105589", "label": "Prescott College" }, + { "value": "219295", "label": "Presentation College" }, + { "value": "163657", "label": "Prince George's Community College" }, + { "value": "101958", "label": "Prince Institute-Southeast" }, + { "value": "186122", "label": "Princeton Theological Seminary" }, + { "value": "186131", "label": "Princeton University" }, + { "value": "148016", "label": "Principia College" }, + { "value": "215433", "label": "Prism Career Institute-Upper Darby" }, + { "value": "437750", "label": "Professional Golfers Career College" }, + { "value": "205054", "label": "Professional Skills Institute" }, + { "value": "455770", "label": "Providence Christian College" }, + { "value": "217402", "label": "Providence College" }, + { "value": "380438", "label": "Provo College" }, + { "value": "127884", "label": "Pueblo Community College" }, + { "value": "241766", "label": "Puerto Rico Conservatory of Music" }, + { "value": "107664", "label": "Pulaski Technical College" }, + { "value": "152248", "label": "Purdue University-Calumet Campus" }, + { "value": "243780", "label": "Purdue University-Main Campus" }, + { "value": "152266", "label": "Purdue University-North Central Campus" }, + { "value": "199412", "label": "Queens University of Charlotte" }, + { "value": "167525", "label": "Quincy College" }, + { "value": "148131", "label": "Quincy University" }, + { "value": "130217", "label": "Quinebaug Valley Community College" }, + { "value": "130226", "label": "Quinnipiac University" }, + { "value": "167534", "label": "Quinsigamond Community College" }, + { "value": "384421", "label": "Rabbi Jacob Joseph School" }, + { + "value": "194657", + "label": "Rabbinical Academy Mesivta Rabbi Chaim Berlin" + }, + { "value": "194693", "label": "Rabbinical College Beth Shraga" }, + { + "value": "194666", + "label": "Rabbinical College Bobover Yeshiva Bnei Zion" + }, + { "value": "186186", "label": "Rabbinical College of America" }, + { + "value": "194675", + "label": "Rabbinical College of Ch'san Sofer New York" + }, + { "value": "194736", "label": "Rabbinical College of Long Island" }, + { "value": "405854", "label": "Rabbinical College of Ohr Shimon Yisroel" }, + { "value": "484871", "label": "Rabbinical College Ohr Yisroel" }, + { "value": "205124", "label": "Rabbinical College Telshe" }, + { "value": "194763", "label": "Rabbinical Seminary of America" }, + { "value": "233277", "label": "Radford University" }, + { "value": "481119", "label": "Radians College" }, + { "value": "174604", "label": "Rainy River Community College" }, + { "value": "186201", "label": "Ramapo College of New Jersey" }, + { "value": "233301", "label": "Randolph College" }, + { "value": "199421", "label": "Randolph Community College" }, + { "value": "233295", "label": "Randolph-Macon College" }, + { "value": "227687", "label": "Ranger College" }, + { "value": "178891", "label": "Ranken Technical College" }, + { "value": "233310", "label": "Rappahannock Community College" }, + { "value": "186645", "label": "Raritan Valley Community College" }, + { "value": "138309", "label": "Rasmussen College-Florida" }, + { "value": "448673", "label": "Rasmussen College-Illinois" }, + { "value": "175014", "label": "Rasmussen College-Minnesota" }, + { "value": "200013", "label": "Rasmussen College-North Dakota" }, + { "value": "450571", "label": "Rasmussen College-Wisconsin" }, + { "value": "215585", "label": "Reading Area Community College" }, + { "value": "215619", "label": "Reconstructionist Rabbinical College" }, + { "value": "127909", "label": "Red Rocks Community College" }, + { "value": "207069", "label": "Redlands Community College" }, + { "value": "126605", "label": "Redstone College" }, + { "value": "209922", "label": "Reed College" }, + { "value": "117052", "label": "Reedley College" }, + { + "value": "215628", + "label": "Reformed Presbyterian Theological Seminary" + }, + { "value": "105659", "label": "Refrigeration School Inc" }, + { "value": "231651", "label": "Regent University" }, + { "value": "167598", "label": "Regis College" }, + { "value": "127918", "label": "Regis University" }, + { "value": "101994", "label": "Reid State Technical College" }, + { "value": "140872", "label": "Reinhardt University" }, + { "value": "475033", "label": "Relay Graduate School of Education" }, + { "value": "457183", "label": "Remington College of Nursing Orlando" }, + { "value": "440271", "label": "Remington College-Baton Rouge Campus" }, + { "value": "375416", "label": "Remington College-Cleveland Campus" }, + { "value": "223463", "label": "Remington College-Dallas Campus" }, + { "value": "377111", "label": "Remington College-Fort Worth Campus" }, + { "value": "460783", "label": "Remington College-Heathrow Campus" }, + { "value": "372958", "label": "Remington College-Honolulu Campus" }, + { "value": "380094", "label": "Remington College-Houston Campus" }, + { "value": "160524", "label": "Remington College-Lafayette Campus" }, + { "value": "438869", "label": "Remington College-Little Rock Campus" }, + { "value": "412599", "label": "Remington College-Memphis Campus" }, + { "value": "366535", "label": "Remington College-Mobile Campus" }, + { "value": "445249", "label": "Remington College-Nashville Campus" }, + { "value": "445203", "label": "Remington College-North Houston Campus" }, + { "value": "451866", "label": "Remington College-Shreveport Campus" }, + { "value": "135939", "label": "Remington College-Tampa Campus" }, + { "value": "148256", "label": "Rend Lake College" }, + { "value": "129428", "label": "Rensselaer Hartford Graduate Center Inc" }, + { "value": "194824", "label": "Rensselaer Polytechnic Institute" }, + { "value": "236382", "label": "Renton Technical College" }, + { "value": "178989", "label": "Research College of Nursing" }, + { "value": "149763", "label": "Resurrection University" }, + { "value": "217420", "label": "Rhode Island College" }, + { "value": "217493", "label": "Rhode Island School of Design" }, + { "value": "221351", "label": "Rhodes College" }, + { "value": "227757", "label": "Rice University" }, + { "value": "107743", "label": "Rich Mountain Community College" }, + { + "value": "233338", + "label": "Richard Bland College of the College of William and Mary" + }, + { "value": "227766", "label": "Richland College" }, + { "value": "148292", "label": "Richland Community College" }, + { "value": "199449", "label": "Richmond Community College" }, + { "value": "441104", "label": "Richmont Graduate University" }, + { "value": "186283", "label": "Rider University" }, + { "value": "175236", "label": "Ridgewater College" }, + { "value": "136774", "label": "Ringling College of Art and Design" }, + { "value": "475185", "label": "Rio Grande Bible Institute" }, + { "value": "121886", "label": "Rio Hondo College" }, + { "value": "105668", "label": "Rio Salado College" }, + { "value": "239628", "label": "Ripon College" }, + { "value": "436304", "label": "River Parishes Community College" }, + { "value": "183114", "label": "River Valley Community College" }, + { "value": "173063", "label": "Riverland Community College" }, + { "value": "121901", "label": "Riverside City College" }, + { "value": "233408", "label": "Riverside College of Health Careers" }, + { "value": "183211", "label": "Rivier University" }, + { "value": "221397", "label": "Roane State Community College" }, + { "value": "233426", "label": "Roanoke College" }, + { "value": "199467", "label": "Roanoke-Chowan Community College" }, + { "value": "215655", "label": "Robert Morris University" }, + { "value": "148335", "label": "Robert Morris University Illinois" }, + { "value": "194958", "label": "Roberts Wesleyan College" }, + { "value": "199476", "label": "Robeson Community College" }, + { "value": "170967", "label": "Rochester College" }, + { "value": "174738", "label": "Rochester Community and Technical College" }, + { "value": "195003", "label": "Rochester Institute of Technology" }, + { "value": "148380", "label": "Rock Valley College" }, + { "value": "195049", "label": "Rockefeller University" }, + { "value": "148405", "label": "Rockford University" }, + { "value": "179043", "label": "Rockhurst University" }, + { "value": "199485", "label": "Rockingham Community College" }, + { "value": "195058", "label": "Rockland Community College" }, + { "value": "180595", "label": "Rocky Mountain College" }, + { "value": "127945", "label": "Rocky Mountain College of Art and Design" }, + { + "value": "475495", + "label": "Rocky Mountain University of Health Professions" + }, + { "value": "480790", "label": "Rocky Vista University" }, + { "value": "217518", "label": "Roger Williams University" }, + { "value": "409616", "label": "Roger Williams University School of Law" }, + { "value": "207661", "label": "Rogers State University" }, + { "value": "209940", "label": "Rogue Community College" }, + { "value": "136950", "label": "Rollins College" }, + { "value": "148487", "label": "Roosevelt University" }, + { + "value": "145558", + "label": "Rosalind Franklin University of Medicine and Science" + }, + { "value": "207670", "label": "Rose State College" }, + { "value": "439899", "label": "Rosedale Bible College" }, + { "value": "215682", "label": "Rosedale Technical Institute" }, + { "value": "152318", "label": "Rose-Hulman Institute of Technology" }, + { "value": "445735", "label": "Roseman University of Health Sciences" }, + { "value": "215691", "label": "Rosemont College" }, + { "value": "452081", "label": "Ross College-Sylvania" }, + { "value": "183877", "label": "Rowan College at Burlington County" }, + { "value": "184791", "label": "Rowan College at Gloucester County" }, + { "value": "184782", "label": "Rowan University" }, + { "value": "199494", "label": "Rowan-Cabarrus Community College" }, + { "value": "167631", "label": "Roxbury Community College" }, + { "value": "148511", "label": "Rush University" }, + { "value": "176318", "label": "Rust College" }, + { "value": "186371", "label": "Rutgers University-Camden" }, + { "value": "186380", "label": "Rutgers University-New Brunswick" }, + { "value": "186399", "label": "Rutgers University-Newark" }, + { "value": "449506", "label": "SABER College" }, + { "value": "122180", "label": "Sacramento City College" }, + { "value": "172033", "label": "Sacred Heart Major Seminary" }, + { "value": "239637", "label": "Sacred Heart School of Theology" }, + { "value": "130253", "label": "Sacred Heart University" }, + { "value": "122205", "label": "Saddleback College" }, + { "value": "476948", "label": "SAE Institute of Technology-Atlanta" }, + { "value": "446525", "label": "SAE Institute of Technology-Nashville" }, + { "value": "410520", "label": "Sage College" }, + { "value": "441070", "label": "Saginaw Chippewa Tribal College" }, + { "value": "172051", "label": "Saginaw Valley State University" }, + { "value": "154235", "label": "Saint Ambrose University" }, + { "value": "183239", "label": "Saint Anselm College" }, + { "value": "149028", "label": "Saint Anthony College of Nursing" }, + { "value": "148876", "label": "Saint Augustine College" }, + { "value": "199582", "label": "Saint Augustine's University" }, + { "value": "157632", "label": "Saint Catharine College" }, + { "value": "216047", "label": "Saint Charles Borromeo Seminary-Overbrook" }, + { "value": "174783", "label": "Saint Cloud State University" }, + { "value": "227845", "label": "Saint Edward's University" }, + { "value": "195702", "label": "Saint Elizabeth College of Nursing-Utica" }, + { + "value": "148575", + "label": "Saint Francis Medical Center College of Nursing" + }, + { "value": "215743", "label": "Saint Francis University" }, + { "value": "195720", "label": "Saint John Fisher College" }, + { "value": "137272", "label": "Saint John Vianney College Seminary" }, + { "value": "137281", "label": "Saint Johns River State College" }, + { "value": "167677", "label": "Saint John's Seminary" }, + { "value": "174792", "label": "Saint Johns University" }, + { "value": "160409", "label": "Saint Joseph Seminary College" }, + { "value": "152363", "label": "Saint Josephs College" }, + { "value": "161518", "label": "Saint Joseph's College of Maine" }, + { "value": "195544", "label": "Saint Joseph's College-New York" }, + { "value": "215770", "label": "Saint Joseph's University" }, + { "value": "137032", "label": "Saint Leo University" }, + { "value": "179256", "label": "Saint Louis Christian College" }, + { "value": "179308", "label": "Saint Louis Community College" }, + { "value": "179159", "label": "Saint Louis University" }, + { "value": "179450", "label": "Saint Luke's College of Health Sciences" }, + { "value": "236452", "label": "Saint Martin's University" }, + { "value": "152381", "label": "Saint Mary-of-the-Woods College" }, + { "value": "152390", "label": "Saint Mary's College" }, + { "value": "123554", "label": "Saint Mary's College of California" }, + { "value": "174817", "label": "Saint Mary's University of Minnesota" }, + { "value": "152451", "label": "Saint Meinrad School of Theology" }, + { "value": "231059", "label": "Saint Michael's College" }, + { "value": "239716", "label": "Saint Norbert College" }, + { "value": "175041", "label": "Saint Paul College" }, + { "value": "179317", "label": "Saint Paul School of Theology" }, + { "value": "186432", "label": "Saint Peter's University" }, + { "value": "215798", "label": "Saint Vincent College" }, + { "value": "136701", "label": "Saint Vincent de Paul Regional Seminary" }, + { "value": "215813", "label": "Saint Vincent Seminary" }, + { + "value": "195580", + "label": "Saint Vladimirs Orthodox Theological Seminary" + }, + { "value": "148627", "label": "Saint Xavier University" }, + { "value": "199607", "label": "Salem College" }, + { "value": "186469", "label": "Salem Community College" }, + { "value": "237783", "label": "Salem International University" }, + { "value": "167729", "label": "Salem State University" }, + { "value": "155830", "label": "Salina Area Technical College" }, + { "value": "163851", "label": "Salisbury University" }, + { "value": "180647", "label": "Salish Kootenai College" }, + { "value": "230746", "label": "Salt Lake Community College" }, + { "value": "466523", "label": "Salter College-Chicopee" }, + { "value": "167738", "label": "Salter College-West Boylston" }, + { "value": "214564", "label": "Salus University" }, + { "value": "217536", "label": "Salve Regina University" }, + { "value": "227881", "label": "Sam Houston State University" }, + { "value": "195289", "label": "Samaritan Hospital School of Nursing" }, + { "value": "102049", "label": "Samford University" }, + { "value": "199625", "label": "Sampson Community College" }, + { "value": "122296", "label": "Samuel Merritt University" }, + { "value": "227924", "label": "San Antonio College" }, + { "value": "123527", "label": "San Bernardino Valley College" }, + { "value": "112084", "label": "San Diego Christian College" }, + { "value": "122339", "label": "San Diego City College" }, + { "value": "122375", "label": "San Diego Mesa College" }, + { "value": "122384", "label": "San Diego Miramar College" }, + { "value": "122409", "label": "San Diego State University" }, + { "value": "122454", "label": "San Francisco Art Institute" }, + { "value": "122506", "label": "San Francisco Conservatory of Music" }, + { "value": "122597", "label": "San Francisco State University" }, + { "value": "122603", "label": "San Francisco Theological Seminary" }, + { "value": "227979", "label": "San Jacinto Community College" }, + { "value": "122649", "label": "San Joaquin College of Law" }, + { "value": "122658", "label": "San Joaquin Delta College" }, + { "value": "122685", "label": "San Joaquin Valley College-Visalia" }, + { "value": "122746", "label": "San Jose City College" }, + { "value": "122755", "label": "San Jose State University" }, + { "value": "430670", "label": "San Juan Bautista School of Medicine" }, + { "value": "188100", "label": "San Juan College" }, + { "value": "199634", "label": "Sandhills Community College" }, + { + "value": "481535", + "label": "Sanford Burnham Prybis Medical Discovery Institute" + }, + { "value": "420495", "label": "Sanford-Brown College-Atlanta" }, + { "value": "475291", "label": "Sanford-Brown College-Brooklyn Center" }, + { "value": "146010", "label": "Sanford-Brown College-Chicago" }, + { "value": "404514", "label": "Sanford-Brown College-Dallas" }, + { "value": "179201", "label": "Sanford-Brown College-Fenton" }, + { "value": "404499", "label": "Sanford-Brown College-Houston" }, + { "value": "446792", "label": "Sanford-Brown College-Las Vegas" }, + { "value": "174394", "label": "Sanford-Brown College-Mendota Heights" }, + { "value": "420501", "label": "Sanford-Brown College-Middleburg Heights" }, + { "value": "456296", "label": "Sanford-Brown College-Online" }, + { "value": "440925", "label": "Sanford-Brown College-Orlando" }, + { + "value": "450465", + "label": "Sanford-Brown College-San Antonio-San Antonio" + }, + { "value": "446808", "label": "Sanford-Brown College-Seattle" }, + { "value": "134680", "label": "Sanford-Brown College-Tampa" }, + { "value": "234216", "label": "Sanford-Brown College-Tysons Corner" }, + { "value": "385008", "label": "Sanford-Brown Institute-Ft Lauderdale" }, + { "value": "404505", "label": "Sanford-Brown Institute-Jacksonville" }, + { "value": "121619", "label": "Santa Ana College" }, + { + "value": "122834", + "label": "Santa Barbara Business College-Bakersfield" + }, + { + "value": "122852", + "label": "Santa Barbara Business College-Santa Maria" + }, + { "value": "433420", "label": "Santa Barbara Business College-Ventura" }, + { "value": "122889", "label": "Santa Barbara City College" }, + { "value": "122931", "label": "Santa Clara University" }, + { "value": "137096", "label": "Santa Fe College" }, + { "value": "188137", "label": "Santa Fe Community College" }, + { "value": "188146", "label": "Santa Fe University of Art and Design" }, + { "value": "122977", "label": "Santa Monica College" }, + { "value": "123013", "label": "Santa Rosa Junior College" }, + { "value": "399212", "label": "Santiago Canyon College" }, + { "value": "195304", "label": "Sarah Lawrence College" }, + { "value": "148672", "label": "Sauk Valley Community College" }, + { "value": "140951", "label": "Savannah College of Art and Design" }, + { "value": "140960", "label": "Savannah State University" }, + { "value": "140942", "label": "Savannah Technical College" }, + { "value": "123095", "label": "Saybrook University" }, + { "value": "192156", "label": "SBI Campus-An Affiliate of Sanford-Brown" }, + { "value": "195322", "label": "Schenectady County Community College" }, + { "value": "404338", "label": "Schiller International University" }, + { "value": "143048", "label": "School of the Art Institute of Chicago" }, + { "value": "166984", "label": "School of the Museum of Fine Arts-Boston" }, + { "value": "197151", "label": "School of Visual Arts" }, + { "value": "172200", "label": "Schoolcraft College" }, + { "value": "228042", "label": "Schreiner University" }, + { "value": "105747", "label": "Scottsdale Community College" }, + { "value": "123165", "label": "Scripps College" }, + { "value": "236513", "label": "Seattle Central College" }, + { "value": "439914", "label": "Seattle Institute of Oriental Medicine" }, + { "value": "236577", "label": "Seattle Pacific University" }, + { "value": "236595", "label": "Seattle University" }, + { "value": "102058", "label": "Selma University" }, + { "value": "243498", "label": "Seminario Evangelico de Puerto Rico" }, + { "value": "207740", "label": "Seminole State College" }, + { "value": "137209", "label": "Seminole State College of Florida" }, + { "value": "232885", "label": "Sentara College of Health Sciences" }, + { "value": "475839", "label": "Sessions College for Professional Design" }, + { "value": "186584", "label": "Seton Hall University" }, + { "value": "215947", "label": "Seton Hill University" }, + { "value": "221519", "label": "Sewanee-The University of the South" }, + { + "value": "155858", + "label": "Seward County Community College and Area Technical School" + }, + { "value": "123280", "label": "Shasta Bible College and Graduate School" }, + { "value": "123299", "label": "Shasta College" }, + { "value": "199643", "label": "Shaw University" }, + { "value": "148821", "label": "Shawnee Community College" }, + { "value": "205443", "label": "Shawnee State University" }, + { "value": "102067", "label": "Shelton State Community College" }, + { "value": "233541", "label": "Shenandoah University" }, + { "value": "237792", "label": "Shepherd University" }, + { "value": "461485", "label": "Shepherds Theological Seminary" }, + { "value": "240666", "label": "Sheridan College" }, + { "value": "218751", "label": "Sherman College of Straight Chiropractic" }, + { "value": "480499", "label": "Shiloh University" }, + { "value": "148849", "label": "Shimer College" }, + { "value": "216010", "label": "Shippensburg University of Pennsylvania" }, + { "value": "195438", "label": "Sh'or Yoshuv Rabbinical College" }, + { "value": "236610", "label": "Shoreline Community College" }, + { "value": "107840", "label": "Shorter College" }, + { "value": "140988", "label": "Shorter University" }, + { + "value": "448309", + "label": "Shorter University-College of Adult & Professional Programs" + }, + { "value": "195474", "label": "Siena College" }, + { "value": "172264", "label": "Siena Heights University" }, + { "value": "123341", "label": "Sierra College" }, + { "value": "182458", "label": "Sierra Nevada College" }, + { "value": "239743", "label": "Silver Lake College of the Holy Family" }, + { "value": "167783", "label": "Simmons College" }, + { "value": "461759", "label": "Simmons College of Kentucky" }, + { "value": "154350", "label": "Simpson College" }, + { "value": "123457", "label": "Simpson University" }, + { "value": "205470", "label": "Sinclair Community College" }, + { "value": "219374", "label": "Sinte Gleska University" }, + { "value": "219240", "label": "Sioux Falls Seminary" }, + { "value": "219408", "label": "Sisseton Wahpeton College" }, + { "value": "231068", "label": "SIT Graduate Institute" }, + { "value": "200466", "label": "Sitting Bull College" }, + { "value": "236638", "label": "Skagit Valley College" }, + { "value": "195526", "label": "Skidmore College" }, + { "value": "123509", "label": "Skyline College" }, + { "value": "261931", "label": "Skyline College-Roanoke" }, + { "value": "216038", "label": "Slippery Rock University of Pennsylvania" }, + { "value": "167835", "label": "Smith College" }, + { "value": "102076", "label": "Snead State Community College" }, + { "value": "230597", "label": "Snow College" }, + { "value": "110778", "label": "Sofia University" }, + { "value": "163921", "label": "Sojourner-Douglass College" }, + { "value": "399911", "label": "Soka University of America" }, + { "value": "123563", "label": "Solano Community College" }, + { "value": "459356", "label": "SOLEX College" }, + { "value": "157711", "label": "Somerset Community College" }, + { "value": "123572", "label": "Sonoma State University" }, + { "value": "481094", "label": "Sotheby's Institute of Art-NY" }, + { "value": "107974", "label": "South Arkansas Community College" }, + { "value": "123633", "label": "South Baylo University" }, + { "value": "218733", "label": "South Carolina State University" }, + { "value": "173911", "label": "South Central College" }, + { + "value": "160913", + "label": "South Central Louisiana Technical College-Young Memorial Campus" + }, + { "value": "123642", "label": "South Coast College" }, + { "value": "220552", "label": "South College" }, + { "value": "198242", "label": "South College-Asheville" }, + { + "value": "219347", + "label": "South Dakota School of Mines and Technology" + }, + { "value": "219356", "label": "South Dakota State University" }, + { + "value": "366003", + "label": "South Florida Bible College and Theological Seminary" + }, + { "value": "137315", "label": "South Florida State College" }, + { "value": "482699", "label": "South Georgia State College" }, + { "value": "141006", "label": "South Georgia Technical College" }, + { + "value": "216083", + "label": "South Hills School of Business & Technology" + }, + { "value": "434061", "label": "South Louisiana Community College" }, + { "value": "105792", "label": "South Mountain Community College" }, + { "value": "197850", "label": "South Piedmont Community College" }, + { "value": "228158", "label": "South Plains College" }, + { "value": "236656", "label": "South Puget Sound Community College" }, + { "value": "236504", "label": "South Seattle College" }, + { "value": "149365", "label": "South Suburban College" }, + { "value": "409315", "label": "South Texas College" }, + { "value": "228194", "label": "South Texas College of Law" }, + { + "value": "468006", + "label": "South University-Accelerated Graduate Programs" + }, + { "value": "480073", "label": "South University-Austin" }, + { "value": "480082", "label": "South University-Cleveland" }, + { "value": "251312", "label": "South University-Columbia" }, + { "value": "481720", "label": "South University-High Point" }, + { "value": "101116", "label": "South University-Montgomery" }, + { "value": "468024", "label": "South University-Novi" }, + { "value": "459259", "label": "South University–Richmond" }, + { "value": "139579", "label": "South University-Savannah" }, + { "value": "475121", "label": "South University–Savannah Online" }, + { "value": "449898", "label": "South University-Tampa" }, + { + "value": "224776", + "label": "South University-The Art Institute of Dallas" + }, + { + "value": "468015", + "label": "South University-The Art Institute of Fort Worth" + }, + { "value": "459268", "label": "South University–Virginia Beach" }, + { "value": "133465", "label": "South University-West Palm Beach" }, + { + "value": "156338", + "label": "Southcentral Kentucky Community and Technical College" + }, + { "value": "107637", "label": "Southeast Arkansas College" }, + { "value": "181640", "label": "Southeast Community College Area" }, + { + "value": "157739", + "label": "Southeast Kentucky Community and Technical College" + }, + { + "value": "417734", + "label": "Southeast Missouri Hospital College of Nursing and Health Sciences" + }, + { "value": "179557", "label": "Southeast Missouri State University" }, + { "value": "219426", "label": "Southeast Technical Institute" }, + { "value": "176336", "label": "Southeastern Baptist College" }, + { "value": "199759", "label": "Southeastern Baptist Theological Seminary" }, + { "value": "102261", "label": "Southeastern Bible College" }, + { "value": "443270", "label": "Southeastern College-Jacksonville" }, + { "value": "428170", "label": "Southeastern College-West Palm Beach" }, + { + "value": "154378", + "label": "Southeastern Community College-West Burlington" + }, + { "value": "199722", "label": "Southeastern Community College-Whiteville" }, + { "value": "148937", "label": "Southeastern Illinois College" }, + { "value": "160612", "label": "Southeastern Louisiana University" }, + { "value": "207847", "label": "Southeastern Oklahoma State University" }, + { "value": "368911", "label": "Southeastern Technical College" }, + { "value": "137564", "label": "Southeastern University" }, + { "value": "221661", "label": "Southern Adventist University" }, + { "value": "107983", "label": "Southern Arkansas University Main Campus" }, + { "value": "107992", "label": "Southern Arkansas University Tech" }, + { + "value": "123952", + "label": "Southern California Institute of Architecture" + }, + { + "value": "399869", + "label": "Southern California Institute of Technology" + }, + { "value": "117575", "label": "Southern California Seminary" }, + { + "value": "117672", + "label": "Southern California University of Health Sciences" + }, + { "value": "459222", "label": "Southern California University SOMA" }, + { "value": "221670", "label": "Southern College of Optometry" }, + { "value": "130493", "label": "Southern Connecticut State University" }, + { "value": "139986", "label": "Southern Crescent Technical College" }, + { "value": "149222", "label": "Southern Illinois University-Carbondale" }, + { "value": "149231", "label": "Southern Illinois University-Edwardsville" }, + { "value": "161545", "label": "Southern Maine Community College" }, + { "value": "228246", "label": "Southern Methodist University" }, + { "value": "206862", "label": "Southern Nazarene University" }, + { "value": "183026", "label": "Southern New Hampshire University" }, + { "value": "210146", "label": "Southern Oregon University" }, + { "value": "141097", "label": "Southern Polytechnic State University" }, + { "value": "205966", "label": "Southern State Community College" }, + { "value": "366553", "label": "Southern Technical College-Fort Myers" }, + { "value": "446552", "label": "Southern Technical College-Orlando" }, + { "value": "251260", "label": "Southern Union State Community College" }, + { "value": "160621", "label": "Southern University and A & M College" }, + { "value": "160630", "label": "Southern University at New Orleans" }, + { "value": "160649", "label": "Southern University at Shreveport" }, + { "value": "440916", "label": "Southern University Law Center" }, + { "value": "230603", "label": "Southern Utah University" }, + { "value": "231086", "label": "Southern Vermont College" }, + { "value": "233611", "label": "Southern Virginia University" }, + { "value": "217776", "label": "Southern Wesleyan University" }, + { + "value": "237817", + "label": "Southern West Virginia Community and Technical College" + }, + { + "value": "233082", + "label": "Southside Regional Medical Center Professional Schools" + }, + { "value": "233639", "label": "Southside Virginia Community College" }, + { "value": "413644", "label": "Southwest Acupuncture College-Albuquerque" }, + { "value": "436261", "label": "Southwest Acupuncture College-Boulder" }, + { "value": "366605", "label": "Southwest Acupuncture College-Santa Fe" }, + { "value": "179326", "label": "Southwest Baptist University" }, + { + "value": "420246", + "label": "Southwest College of Naturopathic Medicine & Health Sciences" + }, + { + "value": "382911", + "label": "Southwest Collegiate Institute for the Deaf" + }, + { "value": "141158", "label": "Southwest Georgia Technical College" }, + { "value": "442879", "label": "Southwest Institute of Healing Arts" }, + { "value": "175078", "label": "Southwest Minnesota State University" }, + { "value": "176354", "label": "Southwest Mississippi Community College" }, + { "value": "221485", "label": "Southwest Tennessee Community College" }, + { "value": "228316", "label": "Southwest Texas Junior College" }, + { "value": "451556", "label": "Southwest University at El Paso" }, + { + "value": "402776", + "label": "Southwest University of Visual Arts-Albuquerque" + }, + { + "value": "104188", + "label": "Southwest University of Visual Arts-Tucson" + }, + { "value": "233648", "label": "Southwest Virginia Community College" }, + { "value": "239910", "label": "Southwest Wisconsin Technical College" }, + { "value": "228468", "label": "Southwestern Adventist University" }, + { "value": "228325", "label": "Southwestern Assemblies of God University" }, + { "value": "228486", "label": "Southwestern Christian College" }, + { "value": "207856", "label": "Southwestern Christian University" }, + { "value": "123800", "label": "Southwestern College-Chula Vista" }, + { "value": "188207", "label": "Southwestern College-Santa Fe" }, + { "value": "155900", "label": "Southwestern College-Winfield" }, + { "value": "154396", "label": "Southwestern Community College-Creston" }, + { "value": "199731", "label": "Southwestern Community College-Sylva" }, + { "value": "143215", "label": "Southwestern Illinois College" }, + { "value": "188216", "label": "Southwestern Indian Polytechnic Institute" }, + { "value": "123970", "label": "Southwestern Law School" }, + { "value": "172307", "label": "Southwestern Michigan College" }, + { "value": "207865", "label": "Southwestern Oklahoma State University" }, + { "value": "210155", "label": "Southwestern Oregon Community College" }, + { "value": "228343", "label": "Southwestern University" }, + { "value": "160579", "label": "SOWELA Technical Community College" }, + { "value": "157757", "label": "Spalding University" }, + { + "value": "207254", + "label": "Spartan College of Aeronautics and Technology" + }, + { "value": "218830", "label": "Spartanburg Community College" }, + { "value": "218821", "label": "Spartanburg Methodist College" }, + { "value": "141060", "label": "Spelman College" }, + { "value": "433563", "label": "Spencerian College-Lexington" }, + { "value": "157766", "label": "Spencerian College-Louisville" }, + { "value": "148982", "label": "Spertus College" }, + { "value": "236692", "label": "Spokane Community College" }, + { "value": "236708", "label": "Spokane Falls Community College" }, + { "value": "148991", "label": "Spoon River College" }, + { "value": "172334", "label": "Spring Arbor University" }, + { "value": "102234", "label": "Spring Hill College" }, + { "value": "167899", "label": "Springfield College" }, + { + "value": "475273", + "label": "Springfield College-School of Professional and Continuing Studies" + }, + { "value": "167905", "label": "Springfield Technical Community College" }, + { "value": "199698", "label": "St Andrews University" }, + { + "value": "195155", + "label": "St Bernard's School of Theology and Ministry" + }, + { "value": "195164", "label": "St Bonaventure University" }, + { "value": "175005", "label": "St Catherine University" }, + { "value": "262031", "label": "St Charles Community College" }, + { "value": "172291", "label": "St Clair County Community College" }, + { "value": "174756", "label": "St Cloud Technical and Community College" }, + { "value": "195173", "label": "St Francis College" }, + { "value": "163976", "label": "St John's College" }, + { "value": "123855", "label": "St John's Seminary" }, + { "value": "195809", "label": "St John's University-New York" }, + { "value": "183248", "label": "St Joseph School of Nursing-Nashua" }, + { + "value": "195191", + "label": "St Joseph's College of Nursing at St Joseph's Hospital Health Center" + }, + { "value": "195216", "label": "St Lawrence University" }, + { "value": "442426", "label": "St Louis College of Health Careers-Fenton" }, + { + "value": "179511", + "label": "St Louis College of Health Careers-St Louis" + }, + { "value": "179265", "label": "St Louis College of Pharmacy" }, + { "value": "154262", "label": "St Luke's College" }, + { "value": "163912", "label": "St Mary's College of Maryland" }, + { "value": "228149", "label": "St Mary's University" }, + { "value": "174844", "label": "St Olaf College" }, + { "value": "189811", "label": "St Paul's School of Nursing-Queens" }, + { "value": "195784", "label": "St Paul's School of Nursing-Staten Island" }, + { "value": "137078", "label": "St Petersburg College" }, + { "value": "227854", "label": "St Philip's College" }, + { "value": "137476", "label": "St Thomas University" }, + { "value": "130448", "label": "St Vincent's College" }, + { "value": "207689", "label": "St. Gregory's University" }, + { "value": "245652", "label": "St. John's College" }, + { "value": "148593", "label": "St. John's College-Department of Nursing" }, + { "value": "195243", "label": "St. Thomas Aquinas College" }, + { "value": "446561", "label": "Stanbridge College" }, + { + "value": "483814", + "label": "Standard Healthcare Services-College of Nursing" + }, + { "value": "243744", "label": "Stanford University" }, + { "value": "199740", "label": "Stanly Community College" }, + { "value": "205841", "label": "Stark State College" }, + { "value": "123916", "label": "Starr King School for Ministry" }, + { "value": "135391", "label": "State College of Florida-Manatee-Sarasota" }, + { "value": "179539", "label": "State Fair Community College" }, + { "value": "177977", "label": "State Technical College of Missouri" }, + { "value": "196176", "label": "State University of New York at New Paltz" }, + { "value": "448600", "label": "Stautzenberger College-Brecksville" }, + { "value": "205887", "label": "Stautzenberger College-Maumee" }, + { "value": "228431", "label": "Stephen F Austin State University" }, + { "value": "179548", "label": "Stephens College" }, + { "value": "231095", "label": "Sterling College-Craftsbury Common" }, + { "value": "155937", "label": "Sterling College-Sterling" }, + { "value": "137546", "label": "Stetson University" }, + { "value": "186867", "label": "Stevens Institute of Technology" }, + { "value": "460899", "label": "Stevens-Henager College-Boise" }, + { "value": "474906", "label": "Stevens-Henager College-Idaho Falls" }, + { "value": "446677", "label": "Stevens-Henager College-Logan" }, + { "value": "438151", "label": "Stevens-Henager College-Murray" }, + { "value": "230630", "label": "Stevens-Henager College-Orem" }, + { "value": "477950", "label": "Stevens-Henager College-St. George" }, + { "value": "230621", "label": "Stevens-Henager College-West Haven" }, + { "value": "164173", "label": "Stevenson University" }, + { "value": "178767", "label": "Stevens-The Institute of Business & Arts" }, + { "value": "102270", "label": "Stillman College" }, + { "value": "186876", "label": "Stockton University" }, + { "value": "366340", "label": "Stone Child College" }, + { "value": "167996", "label": "Stonehill College" }, + { "value": "196097", "label": "Stony Brook University" }, + { "value": "438498", "label": "Stratford University" }, + { "value": "450377", "label": "Strayer University-Alabama" }, + { "value": "458885", "label": "Strayer University-Arkansas" }, + { "value": "450298", "label": "Strayer University-Delaware" }, + { "value": "131803", "label": "Strayer University-District of Columbia" }, + { "value": "449038", "label": "Strayer University-Florida" }, + { "value": "458919", "label": "Strayer University-Georgia" }, + { "value": "459994", "label": "Strayer University-Global Region" }, + { "value": "458937", "label": "Strayer University-Louisiana" }, + { "value": "430184", "label": "Strayer University-Maryland" }, + { "value": "458955", "label": "Strayer University-Mississippi" }, + { "value": "453215", "label": "Strayer University-New Jersey" }, + { "value": "453163", "label": "Strayer University-North Carolina" }, + { "value": "443784", "label": "Strayer University-Pennsylvania" }, + { "value": "458964", "label": "Strayer University-South Carolina" }, + { "value": "443766", "label": "Strayer University-Tennessee" }, + { "value": "458973", "label": "Strayer University-Texas" }, + { "value": "233684", "label": "Strayer University-Virginia" }, + { "value": "456621", "label": "Strayer University-West Virginia" }, + { "value": "366395", "label": "Suffolk County Community College" }, + { "value": "168005", "label": "Suffolk University" }, + { "value": "228501", "label": "Sul Ross State University" }, + { "value": "157270", "label": "Sullivan College of Technology and Design" }, + { "value": "195988", "label": "Sullivan County Community College" }, + { "value": "157793", "label": "Sullivan University" }, + { + "value": "447953", + "label": "SUM Bible College and Theological Seminary" + }, + { "value": "181543", "label": "Summit Christian College" }, + { "value": "208512", "label": "Sumner College" }, + { "value": "196060", "label": "SUNY at Albany" }, + { "value": "196079", "label": "SUNY at Binghamton" }, + { "value": "196158", "label": "SUNY at Fredonia" }, + { "value": "196219", "label": "SUNY at Purchase College" }, + { "value": "189547", "label": "SUNY Broome Community College" }, + { "value": "196130", "label": "SUNY Buffalo State" }, + { "value": "196121", "label": "SUNY College at Brockport" }, + { "value": "196149", "label": "SUNY College at Cortland" }, + { "value": "196167", "label": "SUNY College at Geneseo" }, + { "value": "196237", "label": "SUNY College at Old Westbury" }, + { "value": "196194", "label": "SUNY College at Oswego" }, + { "value": "196246", "label": "SUNY College at Plattsburgh" }, + { "value": "196200", "label": "SUNY College at Potsdam" }, + { + "value": "196033", + "label": "SUNY College of Agriculture and Technology at Cobleskill" + }, + { + "value": "196103", + "label": "SUNY College of Environmental Science and Forestry" + }, + { "value": "196228", "label": "SUNY College of Optometry" }, + { "value": "196006", "label": "SUNY College of Technology at Alfred" }, + { "value": "196015", "label": "SUNY College of Technology at Canton" }, + { "value": "196024", "label": "SUNY College of Technology at Delhi" }, + { "value": "196255", "label": "SUNY Downstate Medical Center" }, + { "value": "196264", "label": "SUNY Empire State College" }, + { "value": "196291", "label": "SUNY Maritime College" }, + { "value": "196185", "label": "SUNY Oneonta" }, + { "value": "196112", "label": "SUNY Polytechnic Institute" }, + { "value": "197294", "label": "SUNY Westchester Community College" }, + { "value": "199768", "label": "Surry Community College" }, + { "value": "216278", "label": "Susquehanna University" }, + { "value": "247603", "label": "Sussex County Community College" }, + { "value": "216287", "label": "Swarthmore College" }, + { + "value": "196389", + "label": "Swedish Institute a College of Health Sciences" + }, + { "value": "233718", "label": "Sweet Briar College" }, + { "value": "196413", "label": "Syracuse University" }, + { "value": "155973", "label": "Tabor College" }, + { "value": "236753", "label": "Tacoma Community College" }, + { "value": "124113", "label": "Taft College" }, + { "value": "454689", "label": "Taft University System" }, + { "value": "102298", "label": "Talladega College" }, + { "value": "137759", "label": "Tallahassee Community College" }, + { "value": "137777", "label": "Talmudic College of Florida" }, + { "value": "186900", "label": "Talmudical Academy-New Jersey" }, + { "value": "196440", "label": "Talmudical Institute of Upstate New York" }, + { "value": "451404", "label": "Talmudical Seminary of Bobov" }, + { "value": "196431", "label": "Talmudical Seminary Oholei Torah" }, + { "value": "216311", "label": "Talmudical Yeshiva of Philadelphia" }, + { "value": "228529", "label": "Tarleton State University" }, + { "value": "228547", "label": "Tarrant County College District" }, + { "value": "149310", "label": "Taylor Business Institute" }, + { "value": "449524", "label": "Taylor College" }, + { "value": "152530", "label": "Taylor University" }, + { "value": "196468", "label": "Teachers College at Columbia University" }, + { "value": "196477", "label": "Technical Career Institutes" }, + { "value": "217712", "label": "Technical College of the Lowcountry" }, + { "value": "149329", "label": "Telshe Yeshiva-Chicago" }, + { "value": "228608", "label": "Temple College" }, + { "value": "216339", "label": "Temple University" }, + { "value": "221838", "label": "Tennessee State University" }, + { "value": "221847", "label": "Tennessee Technological University" }, + { "value": "221856", "label": "Tennessee Temple University" }, + { "value": "221731", "label": "Tennessee Wesleyan College" }, + { "value": "206011", "label": "Terra State Community College" }, + { "value": "228699", "label": "Texarkana College" }, + { "value": "226152", "label": "Texas A & M International University" }, + { "value": "483036", "label": "Texas A & M University-Central Texas" }, + { "value": "228723", "label": "Texas A & M University-College Station" }, + { "value": "224554", "label": "Texas A & M University-Commerce" }, + { "value": "224147", "label": "Texas A & M University-Corpus Christi" }, + { "value": "228705", "label": "Texas A & M University-Kingsville" }, + { "value": "224545", "label": "Texas A & M University-Texarkana" }, + { "value": "228866", "label": "Texas Chiropractic College Foundation Inc" }, + { "value": "228875", "label": "Texas Christian University" }, + { "value": "228884", "label": "Texas College" }, + { "value": "441487", "label": "Texas County Technical College" }, + { "value": "430704", "label": "Texas Health and Science University" }, + { "value": "228981", "label": "Texas Lutheran University" }, + { "value": "229063", "label": "Texas Southern University" }, + { "value": "229319", "label": "Texas State Technical College-Harlingen" }, + { "value": "408394", "label": "Texas State Technical College-Marshall" }, + { "value": "228680", "label": "Texas State Technical College-Waco" }, + { "value": "229328", "label": "Texas State Technical College-West Texas" }, + { "value": "228459", "label": "Texas State University" }, + { "value": "229115", "label": "Texas Tech University" }, + { + "value": "229337", + "label": "Texas Tech University Health Sciences Center" + }, + { "value": "229160", "label": "Texas Wesleyan University" }, + { "value": "229179", "label": "Texas Woman's University" }, + { "value": "216296", "label": "Thaddeus Stevens College of Technology" }, + { "value": "138813", "label": "The Art Institute of Atlanta" }, + { "value": "451820", "label": "The Art Institute of Austin" }, + { "value": "450085", "label": "The Art Institute of Charleston" }, + { "value": "197832", "label": "The Art Institute of Charlotte" }, + { + "value": "200624", + "label": "The Art Institute of Cincinnati-AIC College of Design" + }, + { "value": "126702", "label": "The Art Institute of Colorado" }, + { "value": "132338", "label": "The Art Institute of Fort Lauderdale" }, + { "value": "222938", "label": "The Art Institute of Houston" }, + { "value": "448345", "label": "The Art Institute of Indianapolis" }, + { "value": "182111", "label": "The Art Institute of Las Vegas" }, + { "value": "451796", "label": "The Art Institute of Michigan" }, + { "value": "365055", "label": "The Art Institute of New York City" }, + { "value": "446668", "label": "The Art Institute of Ohio-Cincinnati" }, + { "value": "210942", "label": "The Art Institute of Philadelphia" }, + { "value": "428444", "label": "The Art Institute of Phoenix" }, + { "value": "210960", "label": "The Art Institute of Pittsburgh" }, + { + "value": "451662", + "label": "The Art Institute of Pittsburgh-Online Division" + }, + { "value": "208239", "label": "The Art Institute of Portland" }, + { "value": "452027", "label": "The Art Institute of Raleigh-Durham" }, + { "value": "450049", "label": "The Art Institute of Salt Lake City" }, + { "value": "458982", "label": "The Art Institute of San Antonio" }, + { "value": "234492", "label": "The Art Institute of Seattle" }, + { "value": "482398", "label": "The Art Institute of St Louis" }, + { "value": "449010", "label": "The Art Institute of Tennessee-Nashville" }, + { "value": "444927", "label": "The Art Institute of Tucson" }, + { "value": "458496", "label": "The Art Institute of Virginia Beach" }, + { "value": "440341", "label": "The Art Institute of Washington" }, + { "value": "456010", "label": "The Art Institute of Washington-Dulles" }, + { "value": "470092", "label": "The Art Institute of Wisconsin" }, + { + "value": "452018", + "label": "The Art Institutes International–Kansas City" + }, + { + "value": "173887", + "label": "The Art Institutes International-Minnesota" + }, + { "value": "210906", "label": "The Art Institutes of York-PA" }, + { "value": "132408", "label": "The Baptist College of Florida" }, + { "value": "164933", "label": "The Boston Conservatory" }, + { "value": "111188", "label": "The California Maritime Academy" }, + { + "value": "143978", + "label": "The Chicago School of Professional Psychology at Chicago" + }, + { + "value": "455433", + "label": "The Chicago School of Professional Psychology at Irvine" + }, + { + "value": "455664", + "label": "The Chicago School of Professional Psychology at Los Angeles" + }, + { + "value": "459745", + "label": "The Chicago School of Professional Psychology at Washington DC" + }, + { + "value": "455682", + "label": "The Chicago School of Professional Psychology at Westwood" + }, + { + "value": "201821", + "label": "The Christ College of Nursing and Health Sciences" + }, + { + "value": "437635", + "label": "The College of Health Care Professions-Austin" + }, + { + "value": "480824", + "label": "The College of Health Care Professions-Dallas" + }, + { + "value": "480833", + "label": "The College of Health Care Professions-Fort Worth" + }, + { "value": "142294", "label": "The College of Idaho" }, + { "value": "187134", "label": "The College of New Jersey" }, + { "value": "193645", "label": "The College of New Rochelle" }, + { "value": "195234", "label": "The College of Saint Rose" }, + { "value": "174899", "label": "The College of Saint Scholastica" }, + { "value": "197285", "label": "The College of Westchester" }, + { "value": "206589", "label": "The College of Wooster" }, + { "value": "456542", "label": "The Commonwealth Medical College" }, + { "value": "434672", "label": "The Community College of Baltimore County" }, + { "value": "430485", "label": "The Creative Center" }, + { "value": "235167", "label": "The Evergreen State College" }, + { "value": "191320", "label": "The General Theological Seminary" }, + { "value": "148177", "label": "The Illinois Institute of Art-Chicago" }, + { "value": "428286", "label": "The Illinois Institute of Art-Schaumburg" }, + { "value": "146241", "label": "The John Marshall Law School" }, + { "value": "192110", "label": "The Juilliard School" }, + { "value": "454184", "label": "The King’s College" }, + { "value": "439701", "label": "The King's University" }, + { "value": "161208", "label": "The Landing School" }, + { "value": "213598", "label": "The Lincoln University" }, + { "value": "117751", "label": "The Master's College and Seminary" }, + { "value": "119544", "label": "The National Hispanic University" }, + { "value": "167057", "label": "The New England Conservatory of Music" }, + { "value": "167321", "label": "The New England Institute of Art" }, + { "value": "193654", "label": "The New School" }, + { + "value": "215637", + "label": "The Restaurant School at Walnut Hill College" + }, + { "value": "448804", "label": "The Robert B Miller College" }, + { "value": "195128", "label": "The Sage Colleges" }, + { + "value": "475228", + "label": "The Santa Barbara and Ventura Colleges of Law–Santa Barbara" + }, + { + "value": "125037", + "label": "The Santa Barbara and Ventura Colleges of Law-Ventura" + }, + { + "value": "441131", + "label": "The Seattle School of Theology & Psychology" + }, + { "value": "157748", "label": "The Southern Baptist Theological Seminary" }, + { "value": "100751", "label": "The University of Alabama" }, + { "value": "202763", "label": "The University of Findlay" }, + { "value": "180489", "label": "The University of Montana" }, + { "value": "180692", "label": "The University of Montana-Western" }, + { "value": "137847", "label": "The University of Tampa" }, + { "value": "221740", "label": "The University of Tennessee-Chattanooga" }, + { "value": "221759", "label": "The University of Tennessee-Knoxville" }, + { "value": "221768", "label": "The University of Tennessee-Martin" }, + { + "value": "227368", + "label": "The University of Texas - Rio Grande Valley" + }, + { "value": "228769", "label": "The University of Texas at Arlington" }, + { "value": "228778", "label": "The University of Texas at Austin" }, + { "value": "228787", "label": "The University of Texas at Dallas" }, + { "value": "228796", "label": "The University of Texas at El Paso" }, + { "value": "229027", "label": "The University of Texas at San Antonio" }, + { "value": "228802", "label": "The University of Texas at Tyler" }, + { + "value": "229300", + "label": "The University of Texas Health Science Center at Houston" + }, + { + "value": "228644", + "label": "The University of Texas Health Science Center at San Antonio" + }, + { + "value": "416801", + "label": "The University of Texas MD Anderson Cancer Center" + }, + { "value": "228653", "label": "The University of Texas Medical Branch" }, + { + "value": "229018", + "label": "The University of Texas of the Permian Basin" + }, + { "value": "215105", "label": "The University of the Arts" }, + { + "value": "233897", + "label": "The University of Virginia's College at Wise" + }, + { "value": "138354", "label": "The University of West Florida" }, + { "value": "126012", "label": "The Wright Institute" }, + { "value": "216357", "label": "Thiel College" }, + { "value": "124292", "label": "Thomas Aquinas College" }, + { "value": "161563", "label": "Thomas College" }, + { "value": "187046", "label": "Thomas Edison State University" }, + { "value": "126049", "label": "Thomas Jefferson School of Law" }, + { "value": "216366", "label": "Thomas Jefferson University" }, + { "value": "157809", "label": "Thomas More College" }, + { "value": "183275", "label": "Thomas More College of Liberal Arts" }, + { "value": "233754", "label": "Thomas Nelson Community College" }, + { "value": "141167", "label": "Thomas University" }, + { "value": "129808", "label": "Three Rivers Community College-Norwich" }, + { + "value": "179645", + "label": "Three Rivers Community College-Poplar Bluff" + }, + { "value": "103778", "label": "Thunderbird School of Global Management" }, + { "value": "233772", "label": "Tidewater Community College" }, + { "value": "206048", "label": "Tiffin University" }, + { "value": "420723", "label": "Tillamook Bay Community College" }, + { "value": "141185", "label": "Toccoa Falls College" }, + { "value": "442781", "label": "Tohono O'Odham Community College" }, + { "value": "196565", "label": "Tompkins Cortland Community College" }, + { "value": "196583", "label": "Torah Temimah Talmudical Seminary" }, + { "value": "176406", "label": "Tougaloo College" }, + { "value": "196592", "label": "Touro College" }, + { "value": "459736", "label": "Touro University California" }, + { "value": "459824", "label": "Touro University Nevada" }, + { "value": "459727", "label": "Touro University Worldwide" }, + { "value": "164076", "label": "Towson University" }, + { "value": "157818", "label": "Transylvania University" }, + { "value": "210234", "label": "Treasure Valley Community College" }, + { "value": "221892", "label": "Trevecca Nazarene University" }, + { "value": "448859", "label": "Triangle Tech Inc-Bethlehem" }, + { "value": "216454", "label": "Triangle Tech Inc-Dubois" }, + { "value": "216427", "label": "Triangle Tech Inc-Erie" }, + { "value": "216445", "label": "Triangle Tech Inc-Greensburg" }, + { "value": "216436", "label": "Triangle Tech Inc-Pittsburgh" }, + { "value": "443377", "label": "Triangle Tech Inc-Sunbury" }, + { "value": "460747", "label": "Tribeca Flashpoint College" }, + { "value": "199795", "label": "Tri-County Community College" }, + { "value": "218885", "label": "Tri-County Technical College" }, + { "value": "218894", "label": "Trident Technical College" }, + { "value": "450979", "label": "Trident University International" }, + { "value": "152567", "label": "Trine University" }, + { + "value": "414878", + "label": "Trine University-Regional/Non-Traditional Campuses" + }, + { "value": "128258", "label": "Trinidad State Junior College" }, + { "value": "137953", "label": "Trinity Baptist College" }, + { "value": "200484", "label": "Trinity Bible College" }, + { "value": "149505", "label": "Trinity Christian College" }, + { "value": "130590", "label": "Trinity College" }, + { "value": "137962", "label": "Trinity College of Florida" }, + { + "value": "146755", + "label": "Trinity College of Nursing & Health Sciences" + }, + { "value": "216463", "label": "Trinity Episcopal School for Ministry" }, + { "value": "135610", "label": "Trinity International University-Florida" }, + { "value": "149514", "label": "Trinity International University-Illinois" }, + { "value": "123448", "label": "Trinity Law School" }, + { "value": "235769", "label": "Trinity Lutheran College" }, + { "value": "206215", "label": "Trinity Lutheran Seminary" }, + { "value": "229267", "label": "Trinity University" }, + { "value": "225308", "label": "Trinity Valley Community College" }, + { "value": "131876", "label": "Trinity Washington University" }, + { "value": "206154", "label": "Tri-State Bible College" }, + { "value": "130581", "label": "Tri-State College of Acupuncture" }, + { "value": "149532", "label": "Triton College" }, + { "value": "196653", "label": "Trocaire College" }, + { "value": "102368", "label": "Troy University" }, + { "value": "182500", "label": "Truckee Meadows Community College" }, + { "value": "141237", "label": "Truett-McConnell College" }, + { "value": "178615", "label": "Truman State University" }, + { "value": "206224", "label": "Trumbull Business College" }, + { "value": "168148", "label": "Tufts University" }, + { "value": "160755", "label": "Tulane University of Louisiana" }, + { "value": "207935", "label": "Tulsa Community College" }, + { "value": "207962", "label": "Tulsa Welding School-Tulsa-Tulsa" }, + { "value": "130606", "label": "Tunxis Community College" }, + { "value": "200527", "label": "Turtle Mountain Community College" }, + { "value": "221953", "label": "Tusculum College" }, + { "value": "102377", "label": "Tuskegee University" }, + { "value": "229355", "label": "Tyler Junior College" }, + { "value": "196699", "label": "Ulster County Community College" }, + { "value": "441371", "label": "Ultimate Medical Academy-Clearwater" }, + { "value": "450173", "label": "Ultimate Medical Academy-Tampa" }, + { "value": "481252", "label": "Ultrasound Medical Institute" }, + { "value": "210270", "label": "Umpqua Community College" }, + { "value": "246789", "label": "Unification Theological Seminary" }, + { "value": "157863", "label": "Union College-Barbourville" }, + { "value": "181738", "label": "Union College-Lincoln" }, + { "value": "196866", "label": "Union College-Schenectady" }, + { "value": "187198", "label": "Union County College" }, + { "value": "446932", "label": "Union Graduate College" }, + { "value": "206279", "label": "Union Institute & University" }, + { "value": "233842", "label": "Union Presbyterian Seminary" }, + { + "value": "196884", + "label": "Union Theological Seminary in the City of New York" + }, + { "value": "221971", "label": "Union University" }, + { + "value": "124681", + "label": "United Education Institute-Huntington Park Campus" + }, + { "value": "128328", "label": "United States Air Force Academy" }, + { "value": "130624", "label": "United States Coast Guard Academy" }, + { "value": "197027", "label": "United States Merchant Marine Academy" }, + { "value": "197036", "label": "United States Military Academy" }, + { "value": "164155", "label": "United States Naval Academy" }, + { "value": "102395", "label": "United States Sports Academy" }, + { "value": "447050", "label": "United States University" }, + { "value": "197018", "label": "United Talmudical Seminary" }, + { "value": "206288", "label": "United Theological Seminary" }, + { + "value": "175139", + "label": "United Theological Seminary of the Twin Cities" + }, + { "value": "200554", "label": "United Tribes Technical College" }, + { "value": "459204", "label": "Unitek College" }, + { "value": "161572", "label": "Unity College" }, + { "value": "446598", "label": "Universal College of Healing Arts" }, + { + "value": "106041", + "label": "Universal Technical Institute of Arizona Inc" + }, + { + "value": "376385", + "label": "Universal Technology College of Puerto Rico" + }, + { "value": "241191", "label": "Universidad Adventista de las Antillas" }, + { "value": "241225", "label": "Universidad Central de Bayamon" }, + { "value": "243568", "label": "Universidad Central Del Caribe" }, + { "value": "243346", "label": "Universidad Del Este" }, + { "value": "243443", "label": "Universidad del Sagrado Corazon" }, + { "value": "243601", "label": "Universidad Del Turabo" }, + { "value": "475811", "label": "Universidad Internacional Iberoamericana" }, + { "value": "241739", "label": "Universidad Metropolitana" }, + { "value": "441690", "label": "Universidad Pentecostal Mizpa" }, + { "value": "243577", "label": "Universidad Politecnica de Puerto Rico" }, + { "value": "241614", "label": "Universidad Teologica del Caribe" }, + { "value": "196088", "label": "University at Buffalo" }, + { "value": "363934", "label": "University of Advancing Technology" }, + { "value": "200800", "label": "University of Akron Main Campus" }, + { "value": "200846", "label": "University of Akron Wayne College" }, + { "value": "100663", "label": "University of Alabama at Birmingham" }, + { "value": "100706", "label": "University of Alabama in Huntsville" }, + { "value": "102553", "label": "University of Alaska Anchorage" }, + { "value": "102614", "label": "University of Alaska Fairbanks" }, + { "value": "102632", "label": "University of Alaska Southeast" }, + { "value": "442930", "label": "University of Antelope Valley" }, + { "value": "104179", "label": "University of Arizona" }, + { "value": "106397", "label": "University of Arkansas" }, + { "value": "106245", "label": "University of Arkansas at Little Rock" }, + { "value": "106485", "label": "University of Arkansas at Monticello" }, + { "value": "106412", "label": "University of Arkansas at Pine Bluff" }, + { + "value": "106999", + "label": "University of Arkansas Community College-Batesville" + }, + { + "value": "107725", + "label": "University of Arkansas Community College-Hope" + }, + { + "value": "107585", + "label": "University of Arkansas Community College-Morrilton" + }, + { + "value": "106263", + "label": "University of Arkansas for Medical Sciences" + }, + { "value": "108092", "label": "University of Arkansas-Fort Smith" }, + { "value": "161873", "label": "University of Baltimore" }, + { "value": "128744", "label": "University of Bridgeport" }, + { "value": "110635", "label": "University of California-Berkeley" }, + { "value": "110644", "label": "University of California-Davis" }, + { + "value": "110398", + "label": "University of California-Hastings College of Law" + }, + { "value": "110653", "label": "University of California-Irvine" }, + { "value": "110662", "label": "University of California-Los Angeles" }, + { "value": "445188", "label": "University of California-Merced" }, + { "value": "110671", "label": "University of California-Riverside" }, + { "value": "110680", "label": "University of California-San Diego" }, + { "value": "110699", "label": "University of California-San Francisco" }, + { "value": "110705", "label": "University of California-Santa Barbara" }, + { "value": "110714", "label": "University of California-Santa Cruz" }, + { "value": "106704", "label": "University of Central Arkansas" }, + { "value": "132903", "label": "University of Central Florida" }, + { "value": "176965", "label": "University of Central Missouri" }, + { "value": "206941", "label": "University of Central Oklahoma" }, + { "value": "237312", "label": "University of Charleston" }, + { "value": "144050", "label": "University of Chicago" }, + { "value": "201955", "label": "University of Cincinnati-Blue Ash College" }, + { "value": "201946", "label": "University of Cincinnati-Clermont College" }, + { "value": "201885", "label": "University of Cincinnati-Main Campus" }, + { "value": "126614", "label": "University of Colorado Boulder" }, + { "value": "126580", "label": "University of Colorado Colorado Springs" }, + { "value": "126562", "label": "University of Colorado Denver" }, + { "value": "129020", "label": "University of Connecticut" }, + { "value": "224323", "label": "University of Dallas" }, + { "value": "202480", "label": "University of Dayton" }, + { "value": "130943", "label": "University of Delaware" }, + { "value": "127060", "label": "University of Denver" }, + { "value": "169716", "label": "University of Detroit Mercy" }, + { "value": "153278", "label": "University of Dubuque" }, + { "value": "447801", "label": "University of East-West Medicine" }, + { "value": "150534", "label": "University of Evansville" }, + { "value": "134130", "label": "University of Florida" }, + { "value": "457402", "label": "University of Fort Lauderdale" }, + { "value": "139959", "label": "University of Georgia" }, + { "value": "180258", "label": "University of Great Falls" }, + { "value": "240754", "label": "University of Guam" }, + { "value": "129525", "label": "University of Hartford" }, + { "value": "141565", "label": "University of Hawaii at Hilo" }, + { "value": "141574", "label": "University of Hawaii at Manoa" }, + { "value": "141839", "label": "University of Hawaii Maui College" }, + { "value": "141981", "label": "University of Hawaii-West Oahu" }, + { "value": "160065", "label": "University of Holy Cross" }, + { "value": "225511", "label": "University of Houston" }, + { "value": "225414", "label": "University of Houston-Clear Lake" }, + { "value": "225432", "label": "University of Houston-Downtown" }, + { "value": "225502", "label": "University of Houston-Victoria" }, + { "value": "142285", "label": "University of Idaho" }, + { "value": "145600", "label": "University of Illinois at Chicago" }, + { "value": "148654", "label": "University of Illinois at Springfield" }, + { + "value": "145637", + "label": "University of Illinois at Urbana-Champaign" + }, + { "value": "151263", "label": "University of Indianapolis" }, + { "value": "153658", "label": "University of Iowa" }, + { "value": "200156", "label": "University of Jamestown" }, + { "value": "155317", "label": "University of Kansas" }, + { "value": "157085", "label": "University of Kentucky" }, + { "value": "117140", "label": "University of La Verne" }, + { "value": "160658", "label": "University of Louisiana at Lafayette" }, + { "value": "159993", "label": "University of Louisiana at Monroe" }, + { "value": "157289", "label": "University of Louisville" }, + { "value": "161253", "label": "University of Maine" }, + { "value": "161217", "label": "University of Maine at Augusta" }, + { "value": "161226", "label": "University of Maine at Farmington" }, + { "value": "161235", "label": "University of Maine at Fort Kent" }, + { "value": "161244", "label": "University of Maine at Machias" }, + { "value": "161341", "label": "University of Maine at Presque Isle" }, + { "value": "437097", "label": "University of Management and Technology" }, + { "value": "200217", "label": "University of Mary" }, + { "value": "226471", "label": "University of Mary Hardin-Baylor" }, + { "value": "232681", "label": "University of Mary Washington" }, + { "value": "163338", "label": "University of Maryland Eastern Shore" }, + { "value": "163259", "label": "University of Maryland-Baltimore" }, + { "value": "163268", "label": "University of Maryland-Baltimore County" }, + { "value": "163286", "label": "University of Maryland-College Park" }, + { "value": "163204", "label": "University of Maryland-University College" }, + { + "value": "166708", + "label": "University of Massachusetts Medical School Worcester" + }, + { "value": "166629", "label": "University of Massachusetts-Amherst" }, + { "value": "166638", "label": "University of Massachusetts-Boston" }, + { "value": "167987", "label": "University of Massachusetts-Dartmouth" }, + { "value": "166513", "label": "University of Massachusetts-Lowell" }, + { "value": "220862", "label": "University of Memphis" }, + { "value": "135726", "label": "University of Miami" }, + { "value": "170976", "label": "University of Michigan-Ann Arbor" }, + { "value": "171137", "label": "University of Michigan-Dearborn" }, + { "value": "171146", "label": "University of Michigan-Flint" }, + { "value": "174075", "label": "University of Minnesota-Crookston" }, + { "value": "174233", "label": "University of Minnesota-Duluth" }, + { "value": "174251", "label": "University of Minnesota-Morris" }, + { "value": "456959", "label": "University of Minnesota-Rochester" }, + { "value": "174066", "label": "University of Minnesota-Twin Cities" }, + { "value": "176017", "label": "University of Mississippi" }, + { "value": "178396", "label": "University of Missouri-Columbia" }, + { "value": "178402", "label": "University of Missouri-Kansas City" }, + { "value": "178420", "label": "University of Missouri-St Louis" }, + { "value": "101693", "label": "University of Mobile" }, + { "value": "101709", "label": "University of Montevallo" }, + { "value": "199069", "label": "University of Mount Olive" }, + { "value": "204185", "label": "University of Mount Union" }, + { "value": "181215", "label": "University of Nebraska at Kearney" }, + { "value": "181394", "label": "University of Nebraska at Omaha" }, + { "value": "181428", "label": "University of Nebraska Medical Center" }, + { "value": "181464", "label": "University of Nebraska-Lincoln" }, + { "value": "182281", "label": "University of Nevada-Las Vegas" }, + { "value": "182290", "label": "University of Nevada-Reno" }, + { "value": "161457", "label": "University of New England" }, + { "value": "183071", "label": "University of New Hampshire at Manchester" }, + { "value": "183044", "label": "University of New Hampshire-Main Campus" }, + { "value": "182829", "label": "University of New Hampshire-School of Law" }, + { "value": "129941", "label": "University of New Haven" }, + { "value": "187958", "label": "University of New Mexico-Gallup Campus" }, + { + "value": "187976", + "label": "University of New Mexico-Los Alamos Campus" + }, + { "value": "187985", "label": "University of New Mexico-Main Campus" }, + { "value": "188225", "label": "University of New Mexico-Taos Campus" }, + { + "value": "188049", + "label": "University of New Mexico-Valencia County Campus" + }, + { "value": "159939", "label": "University of New Orleans" }, + { "value": "101879", "label": "University of North Alabama" }, + { "value": "199111", "label": "University of North Carolina at Asheville" }, + { + "value": "199120", + "label": "University of North Carolina at Chapel Hill" + }, + { "value": "199139", "label": "University of North Carolina at Charlotte" }, + { + "value": "199148", + "label": "University of North Carolina at Greensboro" + }, + { "value": "199281", "label": "University of North Carolina at Pembroke" }, + { + "value": "199184", + "label": "University of North Carolina School of the Arts" + }, + { "value": "199218", "label": "University of North Carolina Wilmington" }, + { "value": "200280", "label": "University of North Dakota" }, + { "value": "136172", "label": "University of North Florida" }, + { "value": "482680", "label": "University of North Georgia" }, + { "value": "227216", "label": "University of North Texas" }, + { "value": "484905", "label": "University of North Texas at Dallas" }, + { + "value": "228909", + "label": "University of North Texas Health Science Center" + }, + { "value": "127741", "label": "University of Northern Colorado" }, + { "value": "154095", "label": "University of Northern Iowa" }, + { "value": "204486", "label": "University of Northwestern Ohio" }, + { "value": "174491", "label": "University of Northwestern-St Paul" }, + { "value": "152080", "label": "University of Notre Dame" }, + { + "value": "207342", + "label": "University of Oklahoma-Health Sciences Center" + }, + { "value": "207500", "label": "University of Oklahoma-Norman Campus" }, + { "value": "209551", "label": "University of Oregon" }, + { "value": "215062", "label": "University of Pennsylvania" }, + { "value": "450456", "label": "University of Phoenix-Alabama" }, + { "value": "484613", "label": "University of Phoenix-Arizona" }, + { "value": "484622", "label": "University of Phoenix-Arkansas" }, + { "value": "484631", "label": "University of Phoenix-California" }, + { "value": "484640", "label": "University of Phoenix-Colorado" }, + { "value": "448822", "label": "University of Phoenix-Connecticut" }, + { "value": "484668", "label": "University of Phoenix-Florida" }, + { "value": "484677", "label": "University of Phoenix-Georgia" }, + { "value": "420042", "label": "University of Phoenix-Hawaii" }, + { "value": "440466", "label": "University of Phoenix-Idaho" }, + { "value": "442161", "label": "University of Phoenix-Illinois" }, + { "value": "443544", "label": "University of Phoenix-Indiana" }, + { "value": "446729", "label": "University of Phoenix-Iowa" }, + { "value": "445391", "label": "University of Phoenix-Kentucky" }, + { "value": "484686", "label": "University of Phoenix-Louisiana" }, + { "value": "434973", "label": "University of Phoenix-Maryland" }, + { "value": "440420", "label": "University of Phoenix-Massachusetts" }, + { "value": "484695", "label": "University of Phoenix-Michigan" }, + { "value": "445319", "label": "University of Phoenix-Minnesota" }, + { "value": "462390", "label": "University of Phoenix-Mississippi" }, + { "value": "484701", "label": "University of Phoenix-Missouri" }, + { "value": "484710", "label": "University of Phoenix-Nevada" }, + { "value": "445300", "label": "University of Phoenix-New Jersey" }, + { "value": "405997", "label": "University of Phoenix-New Mexico" }, + { "value": "484729", "label": "University of Phoenix-North Carolina" }, + { "value": "439297", "label": "University of Phoenix-Ohio" }, + { "value": "484738", "label": "University of Phoenix-Oklahoma" }, + { "value": "432241", "label": "University of Phoenix-Oregon" }, + { "value": "484783", "label": "University of Phoenix-Pennsylvania" }, + { "value": "382063", "label": "University of Phoenix-Puerto Rico" }, + { "value": "448567", "label": "University of Phoenix-South Carolina" }, + { "value": "484747", "label": "University of Phoenix-Tennessee" }, + { "value": "484756", "label": "University of Phoenix-Texas" }, + { "value": "380465", "label": "University of Phoenix-Utah" }, + { "value": "484765", "label": "University of Phoenix-Virginia" }, + { "value": "432223", "label": "University of Phoenix-Washington" }, + { "value": "450483", "label": "University of Phoenix-Washington DC" }, + { "value": "440457", "label": "University of Phoenix-Wisconsin" }, + { "value": "157535", "label": "University of Pikeville" }, + { "value": "215266", "label": "University of Pittsburgh-Bradford" }, + { "value": "215275", "label": "University of Pittsburgh-Greensburg" }, + { "value": "215284", "label": "University of Pittsburgh-Johnstown" }, + { + "value": "215293", + "label": "University of Pittsburgh-Pittsburgh Campus" + }, + { "value": "215309", "label": "University of Pittsburgh-Titusville" }, + { "value": "209825", "label": "University of Portland" }, + { "value": "243106", "label": "University of Puerto Rico-Aguadilla" }, + { "value": "243115", "label": "University of Puerto Rico-Arecibo" }, + { "value": "243133", "label": "University of Puerto Rico-Bayamon" }, + { "value": "243142", "label": "University of Puerto Rico-Carolina" }, + { "value": "243151", "label": "University of Puerto Rico-Cayey" }, + { "value": "243179", "label": "University of Puerto Rico-Humacao" }, + { "value": "243197", "label": "University of Puerto Rico-Mayaguez" }, + { + "value": "243203", + "label": "University of Puerto Rico-Medical Sciences" + }, + { "value": "243212", "label": "University of Puerto Rico-Ponce" }, + { "value": "243221", "label": "University of Puerto Rico-Rio Piedras" }, + { "value": "243188", "label": "University of Puerto Rico-Utuado" }, + { "value": "236328", "label": "University of Puget Sound" }, + { "value": "121691", "label": "University of Redlands" }, + { "value": "217484", "label": "University of Rhode Island" }, + { "value": "233374", "label": "University of Richmond" }, + { "value": "205203", "label": "University of Rio Grande" }, + { "value": "195030", "label": "University of Rochester" }, + { "value": "152336", "label": "University of Saint Francis-Fort Wayne" }, + { "value": "130314", "label": "University of Saint Joseph" }, + { "value": "155812", "label": "University of Saint Mary" }, + { "value": "148885", "label": "University of Saint Mary of the Lake" }, + { "value": "122436", "label": "University of San Diego" }, + { "value": "122612", "label": "University of San Francisco" }, + { + "value": "207722", + "label": "University of Science and Arts of Oklahoma" + }, + { "value": "215929", "label": "University of Scranton" }, + { "value": "219383", "label": "University of Sioux Falls" }, + { "value": "102094", "label": "University of South Alabama" }, + { "value": "218645", "label": "University of South Carolina-Aiken" }, + { "value": "218654", "label": "University of South Carolina-Beaufort" }, + { "value": "218663", "label": "University of South Carolina-Columbia" }, + { "value": "218672", "label": "University of South Carolina-Lancaster" }, + { "value": "218681", "label": "University of South Carolina-Salkehatchie" }, + { "value": "218690", "label": "University of South Carolina-Sumter" }, + { "value": "218706", "label": "University of South Carolina-Union" }, + { "value": "218742", "label": "University of South Carolina-Upstate" }, + { "value": "219471", "label": "University of South Dakota" }, + { "value": "137351", "label": "University of South Florida-Main Campus" }, + { + "value": "451671", + "label": "University of South Florida-Sarasota-Manatee" + }, + { "value": "448840", "label": "University of South Florida-St Petersburg" }, + { "value": "123961", "label": "University of Southern California" }, + { "value": "151306", "label": "University of Southern Indiana" }, + { "value": "161554", "label": "University of Southern Maine" }, + { "value": "176372", "label": "University of Southern Mississippi" }, + { "value": "134121", "label": "University of Southernmost Florida" }, + { + "value": "367954", + "label": "University of St Augustine for Health Sciences" + }, + { "value": "148584", "label": "University of St Francis" }, + { "value": "227863", "label": "University of St Thomas-Houston" }, + { "value": "174914", "label": "University of St Thomas-Saint Paul" }, + { + "value": "228635", + "label": "University of Texas Southwestern Medical Center" + }, + { "value": "156541", "label": "University of the Cumberlands" }, + { "value": "131399", "label": "University of the District of Columbia" }, + { + "value": "363721", + "label": "University of the District of Columbia-David A Clarke School of Law" + }, + { "value": "225627", "label": "University of the Incarnate Word" }, + { "value": "107558", "label": "University of the Ozarks" }, + { "value": "120883", "label": "University of the Pacific" }, + { "value": "442639", "label": "University of the Potomac-VA Campus" }, + { + "value": "384412", + "label": "University of the Potomac-Washington DC Campus" + }, + { "value": "441308", "label": "University of the Rockies" }, + { "value": "215132", "label": "University of the Sciences" }, + { "value": "188182", "label": "University of the Southwest" }, + { "value": "243665", "label": "University of the Virgin Islands" }, + { "value": "449870", "label": "University of the West" }, + { "value": "206084", "label": "University of Toledo" }, + { "value": "207971", "label": "University of Tulsa" }, + { "value": "230764", "label": "University of Utah" }, + { "value": "216542", "label": "University of Valley Forge" }, + { "value": "231174", "label": "University of Vermont" }, + { "value": "234076", "label": "University of Virginia-Main Campus" }, + { "value": "377555", "label": "University of Washington-Bothell Campus" }, + { "value": "236948", "label": "University of Washington-Seattle Campus" }, + { "value": "377564", "label": "University of Washington-Tacoma Campus" }, + { "value": "101587", "label": "University of West Alabama" }, + { "value": "141334", "label": "University of West Georgia" }, + { "value": "210438", "label": "University of Western States" }, + { "value": "240055", "label": "University of Wisconsin Colleges" }, + { "value": "240268", "label": "University of Wisconsin-Eau Claire" }, + { "value": "240277", "label": "University of Wisconsin-Green Bay" }, + { "value": "240329", "label": "University of Wisconsin-La Crosse" }, + { "value": "240444", "label": "University of Wisconsin-Madison" }, + { "value": "240453", "label": "University of Wisconsin-Milwaukee" }, + { "value": "240365", "label": "University of Wisconsin-Oshkosh" }, + { "value": "240374", "label": "University of Wisconsin-Parkside" }, + { "value": "240462", "label": "University of Wisconsin-Platteville" }, + { "value": "240471", "label": "University of Wisconsin-River Falls" }, + { "value": "240480", "label": "University of Wisconsin-Stevens Point" }, + { "value": "240417", "label": "University of Wisconsin-Stout" }, + { "value": "240426", "label": "University of Wisconsin-Superior" }, + { "value": "240189", "label": "University of Wisconsin-Whitewater" }, + { "value": "240727", "label": "University of Wyoming" }, + { "value": "154493", "label": "Upper Iowa University" }, + { "value": "196307", "label": "Upstate Medical University" }, + { "value": "429128", "label": "Urban College of Boston" }, + { "value": "206330", "label": "Urbana University" }, + { "value": "455099", "label": "Urshan Graduate School of Theology" }, + { "value": "216524", "label": "Ursinus College" }, + { "value": "206349", "label": "Ursuline College" }, + { "value": "446604", "label": "Uta Mesivta of Kiryas Joel" }, + { "value": "230728", "label": "Utah State University" }, + { "value": "230737", "label": "Utah Valley University" }, + { "value": "197045", "label": "Utica College" }, + { "value": "197081", "label": "Utica School of Commerce" }, + { "value": "141264", "label": "Valdosta State University" }, + { "value": "138187", "label": "Valencia College" }, + { "value": "200572", "label": "Valley City State University" }, + { "value": "377652", "label": "Valley College-Beckley" }, + { "value": "152600", "label": "Valparaiso University" }, + { "value": "199838", "label": "Vance-Granville Community College" }, + { "value": "221999", "label": "Vanderbilt University" }, + { "value": "149639", "label": "VanderCook College of Music" }, + { + "value": "123651", + "label": "Vanguard University of Southern California" + }, + { "value": "197133", "label": "Vassar College" }, + { "value": "455567", "label": "Vatterott College-Appling Farms" }, + { "value": "245342", "label": "Vatterott College-Berkeley" }, + { "value": "442408", "label": "Vatterott College-Cleveland" }, + { "value": "373058", "label": "Vatterott College-Des Moines" }, + { "value": "440873", "label": "Vatterott College-Dividend" }, + { + "value": "481988", + "label": "Vatterott College-ex'treme Institute by Nelly-St Louis" + }, + { "value": "404374", "label": "Vatterott College-Joplin" }, + { "value": "404383", "label": "Vatterott College-Kansas City" }, + { "value": "437060", "label": "Vatterott College-Oklahoma City" }, + { "value": "148140", "label": "Vatterott College-Quincy" }, + { "value": "181756", "label": "Vatterott College-Spring Valley" }, + { "value": "404365", "label": "Vatterott College-Springfield" }, + { "value": "445559", "label": "Vatterott College-St Charles" }, + { "value": "436182", "label": "Vatterott College-St Joseph" }, + { "value": "436191", "label": "Vatterott College-Sunset Hills" }, + { "value": "440882", "label": "Vatterott College-Tulsa" }, + { "value": "440891", "label": "Vatterott College-Wichita" }, + { + "value": "188340", + "label": "Vaughn College of Aeronautics and Technology" + }, + { "value": "125028", "label": "Ventura College" }, + { "value": "175157", "label": "Vermilion Community College" }, + { "value": "455992", "label": "Vermont College of Fine Arts" }, + { "value": "231147", "label": "Vermont Law School" }, + { "value": "231165", "label": "Vermont Technical College" }, + { "value": "229504", "label": "Vernon College" }, + { "value": "213914", "label": "Vet Tech Institute" }, + { "value": "223472", "label": "Vet Tech Institute of Houston" }, + { "value": "125091", "label": "Victor Valley College" }, + { "value": "229540", "label": "Victoria College" }, + { "value": "197142", "label": "Villa Maria College" }, + { "value": "216597", "label": "Villanova University" }, + { "value": "152637", "label": "Vincennes University" }, + { "value": "482228", "label": "Virginia Baptist College" }, + { "value": "458256", "label": "Virginia College-Augusta" }, + { "value": "441928", "label": "Virginia College-Austin" }, + { "value": "460774", "label": "Virginia College-Baton Rouge" }, + { "value": "450191", "label": "Virginia College-Biloxi" }, + { "value": "420307", "label": "Virginia College-Birmingham" }, + { "value": "456056", "label": "Virginia College-Charleston" }, + { "value": "458593", "label": "Virginia College-Columbia" }, + { "value": "475370", "label": "Virginia College-Columbus" }, + { "value": "480107", "label": "Virginia College-Florence" }, + { "value": "454625", "label": "Virginia College-Greenville" }, + { "value": "420316", "label": "Virginia College-Huntsville" }, + { "value": "441919", "label": "Virginia College-Jackson" }, + { "value": "455716", "label": "Virginia College-Jacksonville" }, + { "value": "475617", "label": "Virginia College-Knoxville" }, + { "value": "460844", "label": "Virginia College-Macon" }, + { "value": "445090", "label": "Virginia College-Mobile" }, + { "value": "452115", "label": "Virginia College-Montgomery" }, + { "value": "389727", "label": "Virginia College-Pensacola" }, + { "value": "460923", "label": "Virginia College-Richmond" }, + { "value": "475352", "label": "Virginia College-Savannah" }, + { + "value": "450289", + "label": "Virginia College-School of Business and Health-Chattanooga" + }, + { "value": "475866", "label": "Virginia College-Shreveport Bossier City" }, + { "value": "460853", "label": "Virginia College-Spartanburg" }, + { "value": "475592", "label": "Virginia College-Tulsa" }, + { "value": "234030", "label": "Virginia Commonwealth University" }, + { "value": "233903", "label": "Virginia Highlands Community College" }, + { "value": "206394", "label": "Virginia Marti College of Art and Design" }, + { "value": "234085", "label": "Virginia Military Institute" }, + { + "value": "233921", + "label": "Virginia Polytechnic Institute and State University" + }, + { "value": "234155", "label": "Virginia State University" }, + { "value": "459082", "label": "Virginia Tech Carilion School of Medicine" }, + { "value": "234164", "label": "Virginia Union University" }, + { "value": "234137", "label": "Virginia University of Lynchburg" }, + { "value": "234173", "label": "Virginia Wesleyan College" }, + { "value": "233949", "label": "Virginia Western Community College" }, + { "value": "449764", "label": "Visible Music College" }, + { "value": "365204", "label": "Vista College" }, + { "value": "377342", "label": "Vista College-Online" }, + { "value": "240107", "label": "Viterbo University" }, + { "value": "222053", "label": "Volunteer State Community College" }, + { "value": "218919", "label": "Voorhees College" }, + { "value": "152673", "label": "Wabash College" }, + { "value": "403487", "label": "Wabash Valley College" }, + { "value": "226879", "label": "Wade College" }, + { "value": "197197", "label": "Wagner College" }, + { "value": "199847", "label": "Wake Forest University" }, + { "value": "199856", "label": "Wake Technical Community College" }, + { "value": "125231", "label": "Walden University" }, + { "value": "154518", "label": "Waldorf College" }, + { "value": "236887", "label": "Walla Walla Community College" }, + { "value": "236896", "label": "Walla Walla University" }, + { + "value": "172608", + "label": "Walsh College of Accountancy and Business Administration" + }, + { "value": "206437", "label": "Walsh University" }, + { "value": "222062", "label": "Walters State Community College" }, + { "value": "210304", "label": "Warner Pacific College" }, + { + "value": "480198", + "label": "Warner Pacific College Adult Degree Program" + }, + { "value": "138275", "label": "Warner University" }, + { "value": "245625", "label": "Warren County Community College" }, + { "value": "199865", "label": "Warren Wilson College" }, + { "value": "154527", "label": "Wartburg College" }, + { "value": "154536", "label": "Wartburg Theological Seminary" }, + { "value": "156082", "label": "Washburn University" }, + { "value": "216667", "label": "Washington & Jefferson College" }, + { "value": "162210", "label": "Washington Adventist University" }, + { "value": "234207", "label": "Washington and Lee University" }, + { "value": "164216", "label": "Washington College" }, + { "value": "161581", "label": "Washington County Community College" }, + { "value": "206446", "label": "Washington State Community College" }, + { "value": "236939", "label": "Washington State University" }, + { "value": "179867", "label": "Washington University in St Louis" }, + { "value": "172617", "label": "Washtenaw Community College" }, + { "value": "392840", "label": "Watkins College of Art Design & Film" }, + { "value": "149727", "label": "Waubonsee Community College" }, + { "value": "240125", "label": "Waukesha County Technical College" }, + { "value": "229780", "label": "Wayland Baptist University" }, + { "value": "199892", "label": "Wayne Community College" }, + { "value": "172635", "label": "Wayne County Community College District" }, + { "value": "181783", "label": "Wayne State College" }, + { "value": "172644", "label": "Wayne State University" }, + { "value": "216694", "label": "Waynesburg University" }, + { "value": "229799", "label": "Weatherford College" }, + { "value": "197221", "label": "Webb Institute" }, + { "value": "138293", "label": "Webber International University" }, + { "value": "230782", "label": "Weber State University" }, + { "value": "179894", "label": "Webster University" }, + { "value": "190424", "label": "Weill Cornell Medicine" }, + { "value": "220206", "label": "Welch College" }, + { "value": "168218", "label": "Wellesley College" }, + { "value": "197230", "label": "Wells College" }, + { + "value": "447999", + "label": "WellSpring School of Allied Health-Kansas City" + }, + { "value": "236975", "label": "Wenatchee Valley College" }, + { "value": "168227", "label": "Wentworth Institute of Technology" }, + { "value": "179919", "label": "Wentworth Military Academy and College" }, + { "value": "176451", "label": "Wesley Biblical Seminary" }, + { "value": "131098", "label": "Wesley College" }, + { "value": "131973", "label": "Wesley Theological Seminary" }, + { "value": "141325", "label": "Wesleyan College" }, + { "value": "130697", "label": "Wesleyan University" }, + { "value": "216764", "label": "West Chester University of Pennsylvania" }, + { "value": "441229", "label": "West Coast Ultrasound Institute" }, + { "value": "477039", "label": "West Coast University-Dallas" }, + { "value": "443331", "label": "West Coast University-Los Angeles" }, + { "value": "458229", "label": "West Coast University-Ontario" }, + { "value": "458210", "label": "West Coast University-Orange County" }, + { "value": "139278", "label": "West Georgia Technical College" }, + { "value": "125462", "label": "West Hills College-Coalinga" }, + { "value": "448594", "label": "West Hills College-Lemoore" }, + { + "value": "157483", + "label": "West Kentucky Community and Technical College" + }, + { "value": "237932", "label": "West Liberty University" }, + { "value": "125471", "label": "West Los Angeles College" }, + { "value": "172671", "label": "West Shore Community College" }, + { "value": "222099", "label": "West Tennessee Business College" }, + { "value": "229814", "label": "West Texas A & M University" }, + { "value": "125499", "label": "West Valley College" }, + { "value": "237978", "label": "West Virginia Business College-Wheeling" }, + { "value": "442383", "label": "West Virginia Junior College-Bridgeport" }, + { "value": "237987", "label": "West Virginia Junior College-Charleston" }, + { "value": "237996", "label": "West Virginia Junior College-Morgantown" }, + { "value": "238014", "label": "West Virginia Northern Community College" }, + { + "value": "237880", + "label": "West Virginia School of Osteopathic Medicine" + }, + { "value": "237899", "label": "West Virginia State University" }, + { "value": "238032", "label": "West Virginia University" }, + { "value": "237686", "label": "West Virginia University at Parkersburg" }, + { + "value": "237950", + "label": "West Virginia University Institute of Technology" + }, + { "value": "237969", "label": "West Virginia Wesleyan College" }, + { "value": "200004", "label": "Western Carolina University" }, + { "value": "130776", "label": "Western Connecticut State University" }, + { "value": "219480", "label": "Western Dakota Technical Institute" }, + { "value": "433387", "label": "Western Governors University" }, + { "value": "149772", "label": "Western Illinois University" }, + { "value": "106102", "label": "Western International University" }, + { "value": "154572", "label": "Western Iowa Tech Community College" }, + { "value": "157951", "label": "Western Kentucky University" }, + { "value": "172699", "label": "Western Michigan University" }, + { + "value": "172477", + "label": "Western Michigan University-Thomas M. Cooley Law School" + }, + { "value": "181817", "label": "Western Nebraska Community College" }, + { "value": "182564", "label": "Western Nevada College" }, + { "value": "168254", "label": "Western New England University" }, + { "value": "188304", "label": "Western New Mexico University" }, + { "value": "208035", "label": "Western Oklahoma State College" }, + { "value": "210429", "label": "Western Oregon University" }, + { "value": "199908", "label": "Western Piedmont Community College" }, + { "value": "210368", "label": "Western Seminary" }, + { + "value": "126030", + "label": "Western State College of Law at Argosy University" + }, + { "value": "128391", "label": "Western State Colorado University" }, + { "value": "224660", "label": "Western Technical College-El Paso" }, + { "value": "224679", "label": "Western Technical College-El Paso" }, + { "value": "240170", "label": "Western Technical College-La Crosse" }, + { "value": "229832", "label": "Western Texas College" }, + { "value": "172705", "label": "Western Theological Seminary" }, + { "value": "112525", "label": "Western University of Health Sciences" }, + { "value": "237011", "label": "Western Washington University" }, + { "value": "240693", "label": "Western Wyoming Community College" }, + { "value": "168263", "label": "Westfield State University" }, + { "value": "179946", "label": "Westminster College-Fulton" }, + { "value": "216807", "label": "Westminster College-New Wilmington" }, + { "value": "230807", "label": "Westminster College-Salt Lake City" }, + { "value": "216816", "label": "Westminster Theological Seminary" }, + { + "value": "125718", + "label": "Westminster Theological Seminary in California" + }, + { "value": "125727", "label": "Westmont College" }, + { "value": "216825", "label": "Westmoreland County Community College" }, + { "value": "437848", "label": "Westwood College-Anaheim" }, + { "value": "448628", "label": "Westwood College-Annandale" }, + { "value": "447069", "label": "Westwood College-Arlington Ballston" }, + { "value": "445072", "label": "Westwood College-Atlanta Midtown" }, + { "value": "443687", "label": "Westwood College-Chicago Loop" }, + { "value": "127024", "label": "Westwood College-Denver North" }, + { "value": "381787", "label": "Westwood College-Denver South" }, + { "value": "406194", "label": "Westwood College-Dupage" }, + { "value": "440484", "label": "Westwood College-Inland Empire" }, + { "value": "122843", "label": "Westwood College-Los Angeles" }, + { "value": "445276", "label": "Westwood College-Northlake" }, + { "value": "178226", "label": "Westwood College-O'Hare Airport" }, + { "value": "440147", "label": "Westwood College-River Oaks" }, + { "value": "121381", "label": "Westwood College-South Bay" }, + { "value": "229841", "label": "Wharton County Junior College" }, + { "value": "237039", "label": "Whatcom Community College" }, + { "value": "168281", "label": "Wheaton College-Norton" }, + { "value": "149781", "label": "Wheaton College-Wheaton" }, + { "value": "238078", "label": "Wheeling Jesuit University" }, + { "value": "168290", "label": "Wheelock College" }, + { "value": "434751", "label": "White Earth Tribal and Community College" }, + { "value": "183105", "label": "White Mountains Community College" }, + { "value": "237057", "label": "Whitman College" }, + { "value": "125763", "label": "Whittier College" }, + { "value": "237066", "label": "Whitworth University" }, + { + "value": "475200", + "label": "Whitworth University-Adult Degree Programs" + }, + { "value": "156107", "label": "Wichita Area Technical College" }, + { "value": "156125", "label": "Wichita State University" }, + { "value": "156134", "label": "Wichita Technical Institute" }, + { "value": "244190", "label": "Widener University-Delaware Campus" }, + { "value": "402828", "label": "Widener University-Harrisburg Campus" }, + { "value": "216852", "label": "Widener University-Main Campus" }, + { "value": "206491", "label": "Wilberforce University" }, + { "value": "229887", "label": "Wiley College" }, + { "value": "199926", "label": "Wilkes Community College" }, + { "value": "216931", "label": "Wilkes University" }, + { "value": "210401", "label": "Willamette University" }, + { "value": "176479", "label": "William Carey University" }, + { "value": "166717", "label": "William James College" }, + { "value": "122728", "label": "William Jessup University" }, + { "value": "179955", "label": "William Jewell College" }, + { "value": "175281", "label": "William Mitchell College of Law" }, + { "value": "222105", "label": "William Moore College of Technology" }, + { "value": "187444", "label": "William Paterson University of New Jersey" }, + { "value": "199272", "label": "William Peace University" }, + { "value": "154590", "label": "William Penn University" }, + { "value": "149842", "label": "William Rainey Harper College" }, + { "value": "179964", "label": "William Woods University" }, + { "value": "107877", "label": "Williams Baptist College" }, + { "value": "168342", "label": "Williams College" }, + { "value": "218955", "label": "Williamsburg Technical College" }, + { "value": "443340", "label": "Williamson Christian College" }, + { "value": "200341", "label": "Williston State College" }, + { "value": "206507", "label": "Wilmington College" }, + { "value": "131113", "label": "Wilmington University" }, + { "value": "217013", "label": "Wilson College" }, + { "value": "199953", "label": "Wilson Community College" }, + { "value": "141990", "label": "Windward Community College" }, + { "value": "206516", "label": "Winebrenner Theological Seminary" }, + { "value": "199962", "label": "Wingate University" }, + { "value": "175272", "label": "Winona State University" }, + { "value": "199999", "label": "Winston-Salem State University" }, + { "value": "218964", "label": "Winthrop University" }, + { "value": "141255", "label": "Wiregrass Georgia Technical College" }, + { "value": "240198", "label": "Wisconsin Indianhead Technical College" }, + { "value": "240338", "label": "Wisconsin Lutheran College" }, + { + "value": "240213", + "label": "Wisconsin School of Professional Psychology" + }, + { "value": "206525", "label": "Wittenberg University" }, + { "value": "218973", "label": "Wofford College" }, + { "value": "451130", "label": "Wolford College" }, + { "value": "442064", "label": "Won Institute of Graduate Studies" }, + { "value": "197522", "label": "Wood Tobe-Coburn School" }, + { "value": "125897", "label": "Woodbury University" }, + { "value": "455512", "label": "Woodland Community College" }, + { "value": "168421", "label": "Worcester Polytechnic Institute" }, + { "value": "168430", "label": "Worcester State University" }, + { "value": "141936", "label": "World Medicine Institute" }, + { "value": "401223", "label": "World Mission University" }, + { "value": "369455", "label": "Worsham College of Mortuary Science" }, + { "value": "164313", "label": "Wor-Wic Community College" }, + { "value": "406200", "label": "Wright Career College" }, + { "value": "206613", "label": "Wright State University-Lake Campus" }, + { "value": "206604", "label": "Wright State University-Main Campus" }, + { "value": "441089", "label": "Wyo Tech-Blairsville" }, + { "value": "132268", "label": "Wyotech-Daytona" }, + { "value": "123208", "label": "Wyotech-Fremont" }, + { "value": "240718", "label": "Wyotech-Laramie" }, + { "value": "398574", "label": "Wyotech-Long Beach" }, + { "value": "234377", "label": "Wytheville Community College" }, + { "value": "206622", "label": "Xavier University" }, + { "value": "160904", "label": "Xavier University of Louisiana" }, + { "value": "237109", "label": "Yakima Valley Community College" }, + { "value": "130794", "label": "Yale University" }, + { "value": "106148", "label": "Yavapai College" }, + { "value": "245731", "label": "Yeshiva and Kollel Harbotzas Torah" }, + { "value": "434937", "label": "Yeshiva College of the Nations Capital" }, + { "value": "197647", "label": "Yeshiva Derech Chaim" }, + { "value": "420325", "label": "Yeshiva D'monsey Rabbinical College" }, + { "value": "375230", "label": "Yeshiva Gedolah Imrei Yosef D'spinka" }, + { "value": "481410", "label": "Yeshiva Gedolah Kesser Torah" }, + { "value": "247773", "label": "Yeshiva Gedolah of Greater Detroit" }, + { "value": "476692", "label": "Yeshiva Gedolah Zichron Leyma" }, + { "value": "197601", "label": "Yeshiva Karlin Stolin" }, + { + "value": "190752", + "label": "Yeshiva of Far Rockaway Derech Ayson Rabbinical Seminary" + }, + { "value": "455257", "label": "Yeshiva of Machzikai Hadas" }, + { "value": "197674", "label": "Yeshiva of Nitra Rabbinical College" }, + { "value": "431983", "label": "Yeshiva of the Telshe Alumni" }, + { + "value": "126076", + "label": "Yeshiva Ohr Elchonon Chabad West Coast Talmudical Seminary" + }, + { "value": "197692", "label": "Yeshiva Shaar Hatorah" }, + { "value": "441609", "label": "Yeshiva Shaarei Torah of Rockland" }, + { "value": "451398", "label": "Yeshiva Toras Chaim" }, + { "value": "128425", "label": "Yeshiva Toras Chaim Talmudical Seminary" }, + { "value": "197708", "label": "Yeshiva University" }, + { "value": "481438", "label": "Yeshiva Yesodei Hatorah" }, + { "value": "451370", "label": "Yeshivas Be'er Yitzchok" }, + { "value": "405058", "label": "Yeshivas Novominsk" }, + { "value": "197610", "label": "Yeshivat Mikdash Melech" }, + { "value": "217040", "label": "Yeshivath Beth Moshe" }, + { "value": "197735", "label": "Yeshivath Viznitz" }, + { "value": "197744", "label": "Yeshivath Zichron Moshe" }, + { + "value": "401250", + "label": "Yo San University of Traditional Chinese Medicine" + }, + { "value": "181853", "label": "York College" }, + { "value": "217059", "label": "York College Pennsylvania" }, + { "value": "420440", "label": "York County Community College" }, + { "value": "218991", "label": "York Technical College" }, + { "value": "217086", "label": "Yorktowne Business Institute" }, + { "value": "141361", "label": "Young Harris College" }, + { "value": "206695", "label": "Youngstown State University" }, + { "value": "375939", "label": "YTI Career Institute-Altoona" }, + { "value": "217077", "label": "YTI Career Institute-York" }, + { "value": "126119", "label": "Yuba College" }, + { "value": "204255", "label": "Zane State College" } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/jobTitles.json b/vite-app/src/apps/Auth2/resources/dataSources/jobTitles.json new file mode 100644 index 000000000..484c6a028 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/jobTitles.json @@ -0,0 +1,17 @@ +[ + { "value": "CEO", "label": "CEO" }, + { "value": "CSO", "label": "CSO" }, + { "value": "Scientific Director", "label": "Scientific Director" }, + { "value": "Principal Investigator", "label": "Principal Investigator" }, + { "value": "Co-investigator", "label": "Co-investigator" }, + { "value": "Staff Scientist", "label": "Staff Scientist" }, + { "value": "Research Associate", "label": "Research Associate" }, + { "value": "Postdoctoral Scientist", "label": "Postdoctoral Scientist" }, + { "value": "Graduate Student", "label": "Graduate Student" }, + { "value": "Undergraduate Student", "label": "Undergraduate Student" }, + { "value": "Assistant Professor", "label": "Assistant Professor" }, + { "value": "Associate Professor", "label": "Associate Professor" }, + { "value": "Professor", "label": "Professor" }, + { "value": "Physician", "label": "Physician" }, + { "value": "Other", "label": "Other" } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.json b/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.json new file mode 100644 index 000000000..c5b4e60ff --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.json @@ -0,0 +1,134 @@ +[ + { + "name": "Ames Laboratory", + "city": "Ames", + "state": "Iowa", + "initials": "Ames", + "type": "OSL" + }, + { + "name": "Argonne National Laboratory", + "city": "Argonne", + "state": "Illinois", + "initials": "ANL", + "type": "OSL" + }, + { + "name": "Brookhaven National Laboratory", + "city": "Upton", + "state": "New York", + "initials": "BNL", + "type": "OSL" + }, + { + "name": "Fermi National Accelerator Laboratory", + "city": "Berkeley", + "state": "California", + "initials": "FERMILAB", + "type": "OSL" + }, + { + "name": "Oak Ridge National Laboratory", + "city": "Oak Ridge", + "state": "Tennessee", + "initials": "ORNL", + "type": "OSL" + }, + { + "name": "Lawrence Berkeley National Laboratory", + "city": "Berkeley", + "state": "California", + "initials": "LBNL", + "type": "OSL" + }, + { + "name": "Pacific Northwest National Laboratory", + "city": "Richland", + "state": "Washington", + "initials": "PNNL", + "type": "OSL" + }, + { + "name": "Princeton Plasma Physics Laboratory", + "city": "Princeton", + "state": "New Jersey", + "initials": "PPPL", + "type": "OSL" + }, + { + "name": "SLAC National Accelerator Laboratory", + "city": "Newport News", + "state": "Virginia", + "initials": "SLAC", + "type": "OSL" + }, + { + "name": "Idaho National Laboratory", + "city": "Idaho Falls", + "state": "Idaho", + "initials": "INL", + "type": "OTHER" + }, + { + "name": "National Energy Technology Laboratory", + "locations": [ + { + "city": "Morgantown", + "state": "West Virginia" + }, + { + "city": "Pittsburgh", + "state": "Pennsylvania" + }, + { + "city": "Albany", + "state": "Orgegon" + } + ], + "initials": "NETL", + "type": "OTHER" + }, + { + "name": "National Renewable Energy Laboratory", + "city": "Golden", + "state": "Colorado", + "initials": "NREL", + "type": "OTHER" + }, + { + "name": "Savannah River National Laboratory", + "city": "Aiken", + "state": "South Carolina", + "initials": "SRNL", + "type": "OTHER" + }, + { + "name": "Lawrence Livermore National Laboratory", + "city": "Livermore", + "state": "California", + "initials": "LLNL", + "type": "NNSA" + }, + { + "name": "Los Alamos National Laboratory", + "city": "Los Alamos", + "state": "New Mexico", + "initials": "LANL", + "type": "NNSA" + }, + { + "name": "Sandia National Laboratory", + "locations": [ + { + "city": "Albequerque", + "state": "New Mexico" + }, + { + "city": "Livermore", + "state": "California" + } + ], + "initials": "SNL", + "type": "NNSA" + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.yaml b/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.yaml new file mode 100644 index 000000000..9031baf88 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/nationalLabs.yaml @@ -0,0 +1,91 @@ +# National Labs +--- +- name: Ames Laboratory + city: Ames + state: Iowa + initials: Ames + type: OSL +- name: Argonne National Laboratory + city: Argonne + state: Illinois + initials: ANL + type: OSL +- name: Brookhaven National Laboratory + city: Upton + state: New York + initials: BNL + type: OSL +- name: Fermi National Accelerator Laboratory + city: Berkeley + state: California + initials: FERMILAB + type: OSL +- name: Oak Ridge National Laboratory + city: Oak Ridge + state: Tennessee + initials: ORNL + type: OSL +- name: Lawrence Berkeley National Laboratory + city: Berkeley + state: California + initials: LBNL + type: OSL +- name: Pacific Northwest National Laboratory + city: Richland + state: Washington + initials: PNNL + type: OSL +- name: Princeton Plasma Physics Laboratory + city: Princeton + state: New Jersey + initials: PPPL + type: OSL +- name: SLAC National Accelerator Laboratory + city: Newport News + state: Virginia + initials: SLAC + type: OSL +- name: Idaho National Laboratory + city: Idaho Falls + state: Idaho + initials: INL + type: OTHER +- name: National Energy Technology Laboratory + locations: + - city: Morgantown + state: West Virginia + - city: Pittsburgh + state: Pennsylvania + - city: Albany + state: Orgegon + initials: NETL + type: OTHER +- name: National Renewable Energy Laboratory + city: Golden + state: Colorado + initials: NREL + type: OTHER +- name: Savannah River National Laboratory + city: Aiken + state: South Carolina + initials: SRNL + type: OTHER + +- name: Lawrence Livermore National Laboratory + city: Livermore + state: California + initials: LLNL + type: NNSA +- name: Los Alamos National Laboratory + city: Los Alamos + state: New Mexico + initials: LANL + type: NNSA +- name: Sandia National Laboratory + locations: + - city: Albequerque + state: New Mexico + - city: Livermore + state: California + initials: SNL + type: NNSA diff --git a/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.json b/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.json new file mode 100644 index 000000000..87283a4c9 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.json @@ -0,0 +1,16 @@ +[ + { + "name": "Cold Spring Harbor Laboratory", + "city": "Cold Spring Harbor", + "state": "New York", + "initials": "CSHL", + "type": "private" + }, + { + "name": "Joint Genome Institute", + "city": "Walnut Creek", + "state": "CA", + "initials": "JGI", + "type": "doe" + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.yaml b/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.yaml new file mode 100644 index 000000000..fae1188e9 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/otherLabs.yaml @@ -0,0 +1,12 @@ +# Other Labs +--- +- name: Cold Spring Harbor Laboratory + city: Cold Spring Harbor + state: New York + initials: CSHL + type: private +- name: Joint Genome Institute + city: Walnut Creek + state: CA + initials: JGI + type: doe diff --git a/vite-app/src/apps/Auth2/resources/dataSources/researchInterests.json b/vite-app/src/apps/Auth2/resources/dataSources/researchInterests.json new file mode 100644 index 000000000..b1f1f3bce --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/researchInterests.json @@ -0,0 +1,42 @@ +[ + { + "value": "annotation", + "label": "Genome Annotation" + }, + { + "value": "assembly", + "label": "Genome Assembly" + }, + { + "value": "communities", + "label": "Microbial Communities" + }, + { + "value": "comparative_genomics", + "label": "Comparative Genomics" + }, + { + "value": "expression", + "label": "Expression" + }, + { + "value": "metabolic_modeling", + "label": "Metabolic Modeling" + }, + { + "value": "reads", + "label": "Read Processing" + }, + { + "value": "sequence", + "label": "Sequence Analysis" + }, + { + "value": "util", + "label": "Utilities" + }, + { + "value": "other", + "label": "Other" + } +] diff --git a/vite-app/src/apps/Auth2/resources/dataSources/states.json b/vite-app/src/apps/Auth2/resources/dataSources/states.json new file mode 100644 index 000000000..16f0d63f1 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/dataSources/states.json @@ -0,0 +1,238 @@ +[ + { + "name": "Alabama", + "abbreviation": "AL" + }, + { + "name": "Alaska", + "abbreviation": "AK" + }, + { + "name": "American Samoa", + "abbreviation": "AS" + }, + { + "name": "Arizona", + "abbreviation": "AZ" + }, + { + "name": "Arkansas", + "abbreviation": "AR" + }, + { + "name": "California", + "abbreviation": "CA" + }, + { + "name": "Colorado", + "abbreviation": "CO" + }, + { + "name": "Connecticut", + "abbreviation": "CT" + }, + { + "name": "Delaware", + "abbreviation": "DE" + }, + { + "name": "District Of Columbia", + "abbreviation": "DC" + }, + { + "name": "Federated States Of Micronesia", + "abbreviation": "FM" + }, + { + "name": "Florida", + "abbreviation": "FL" + }, + { + "name": "Georgia", + "abbreviation": "GA" + }, + { + "name": "Guam", + "abbreviation": "GU" + }, + { + "name": "Hawaii", + "abbreviation": "HI" + }, + { + "name": "Idaho", + "abbreviation": "ID" + }, + { + "name": "Illinois", + "abbreviation": "IL" + }, + { + "name": "Indiana", + "abbreviation": "IN" + }, + { + "name": "Iowa", + "abbreviation": "IA" + }, + { + "name": "Kansas", + "abbreviation": "KS" + }, + { + "name": "Kentucky", + "abbreviation": "KY" + }, + { + "name": "Louisiana", + "abbreviation": "LA" + }, + { + "name": "Maine", + "abbreviation": "ME" + }, + { + "name": "Marshall Islands", + "abbreviation": "MH" + }, + { + "name": "Maryland", + "abbreviation": "MD" + }, + { + "name": "Massachusetts", + "abbreviation": "MA" + }, + { + "name": "Michigan", + "abbreviation": "MI" + }, + { + "name": "Minnesota", + "abbreviation": "MN" + }, + { + "name": "Mississippi", + "abbreviation": "MS" + }, + { + "name": "Missouri", + "abbreviation": "MO" + }, + { + "name": "Montana", + "abbreviation": "MT" + }, + { + "name": "Nebraska", + "abbreviation": "NE" + }, + { + "name": "Nevada", + "abbreviation": "NV" + }, + { + "name": "New Hampshire", + "abbreviation": "NH" + }, + { + "name": "New Jersey", + "abbreviation": "NJ" + }, + { + "name": "New Mexico", + "abbreviation": "NM" + }, + { + "name": "New York", + "abbreviation": "NY" + }, + { + "name": "North Carolina", + "abbreviation": "NC" + }, + { + "name": "North Dakota", + "abbreviation": "ND" + }, + { + "name": "Northern Mariana Islands", + "abbreviation": "MP" + }, + { + "name": "Ohio", + "abbreviation": "OH" + }, + { + "name": "Oklahoma", + "abbreviation": "OK" + }, + { + "name": "Oregon", + "abbreviation": "OR" + }, + { + "name": "Palau", + "abbreviation": "PW" + }, + { + "name": "Pennsylvania", + "abbreviation": "PA" + }, + { + "name": "Puerto Rico", + "abbreviation": "PR" + }, + { + "name": "Rhode Island", + "abbreviation": "RI" + }, + { + "name": "South Carolina", + "abbreviation": "SC" + }, + { + "name": "South Dakota", + "abbreviation": "SD" + }, + { + "name": "Tennessee", + "abbreviation": "TN" + }, + { + "name": "Texas", + "abbreviation": "TX" + }, + { + "name": "Utah", + "abbreviation": "UT" + }, + { + "name": "Vermont", + "abbreviation": "VT" + }, + { + "name": "Virgin Islands", + "abbreviation": "VI" + }, + { + "name": "Virginia", + "abbreviation": "VA" + }, + { + "name": "Washington", + "abbreviation": "WA" + }, + { + "name": "West Virginia", + "abbreviation": "WV" + }, + { + "name": "Wisconsin", + "abbreviation": "WI" + }, + { + "name": "Wyoming", + "abbreviation": "WY" + } +] diff --git a/vite-app/src/apps/Auth2/resources/docs/design.md b/vite-app/src/apps/Auth2/resources/docs/design.md new file mode 100644 index 000000000..8e3b75ad4 --- /dev/null +++ b/vite-app/src/apps/Auth2/resources/docs/design.md @@ -0,0 +1,78 @@ +# Auth2 Javascript Client Design Ideas + +## Lifecycle + +client created + +client queries auth2 service for session state + +- for now we need to extract the cookie manually and send that, + +so - to extract cookie or not - three ideas: + +1. for now - the cookie set by auth2, and read by the client. the client needs to know the cookie name, read it, and extract the token (the only value), to use with the api (e.g. introspection) + +pros: + +- the way it works now +- api usage same as non-browser clients + +cons: + +- requires client and auth service to be on same host (e.g. via proxy) and path (/). +- requires client to know the session cookie name (configuration sync) + +2. the auth2 service sets and reads the cookie, the client doesn't touch it. The cookie would be implicitly sent in all communication with the service. This simplifies the client, configuration (cookie name), and is symmetric (auth2 sets and reads the same cookie) + +pros: + +- cookie known only to auth service +- client does not need to be configured with cookie name +- client code is simpler +- client and auth server may be on different hosts +- in fact, by allowing the cookie be on a different host and/or path the cookie is protected from accidental meddling by the client + +cons: + +- api usage is different than non-browser apps which need to use token explicitly + +3. the auth2 service provides and receives the token via an api argument, and the client manages cookies. This has the advantage that the client is in control of the client environment, and the disadvantage of the same (duplication of the more complex client code across environments.) + +pros: + +- client environment controlled by client +- client api same across all environments + +cons: + +- token must be exposed in redirect response + (on the other hand, token is always exposed via the browser developer tools anyway) +- client coding more complex + (but this is the way we already do it) + +More detail + +1. cookie set by auth2, read by client + +- user requests client resource with browser +- client starts +- client reads session cookie by known name +- client asks auth2 service via api call for token info (aka "introspection") +- auth2 service may return either token error or token info +- token error is same as no token for this logic +- if token is required (none or error) send browser to login page +- on login page user selects auth provider and continues +- ... skip this part in which the user authenticates ... +- browser is redirected back to client either to one of: + 1. requested url with token + 2. auth canceled page + 3. more info needed page +- 1. successful case + - start back at top + +2. auth2 service sets and gets cookie, client session interaction solely through api + +- user requests client resource with browser +- client starts +- client makes api call to auth2 service +- diff --git a/vite-app/src/apps/Auth2/resources/doodle.png b/vite-app/src/apps/Auth2/resources/doodle.png new file mode 100755 index 000000000..23dd44486 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/doodle.png differ diff --git a/vite-app/src/apps/Auth2/resources/images/kbase-logo-99.png b/vite-app/src/apps/Auth2/resources/images/kbase-logo-99.png new file mode 100644 index 000000000..57832dea6 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/images/kbase-logo-99.png differ diff --git a/vite-app/src/apps/Auth2/resources/images/nouserpic.png b/vite-app/src/apps/Auth2/resources/images/nouserpic.png new file mode 100644 index 000000000..2debb6cc4 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/images/nouserpic.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/logo.png b/vite-app/src/apps/Auth2/resources/providers/globus/logo.png new file mode 100644 index 000000000..fa59b2780 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/logo.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/disabled.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/disabled.png new file mode 100644 index 000000000..484e2caf6 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/hover.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/hover.png new file mode 100644 index 000000000..62617d35a Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/normal.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/normal.png new file mode 100644 index 000000000..f363b91e4 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/pressed.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/pressed.png new file mode 100644 index 000000000..c082a8e35 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/200px/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/disabled.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/disabled.png new file mode 100644 index 000000000..9af02410e Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/hover.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/hover.png new file mode 100644 index 000000000..4e193df3e Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-disabled.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-disabled.png new file mode 100644 index 000000000..70db5ba64 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-focus.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-focus.png new file mode 100644 index 000000000..cba0ea427 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-focus.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-normal.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-normal.png new file mode 100644 index 000000000..8b432b975 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-pressed.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-pressed.png new file mode 100644 index 000000000..376b0da41 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/light/btn-pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/normal.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/normal.png new file mode 100644 index 000000000..460bc1000 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/pressed.png b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/pressed.png new file mode 100644 index 000000000..8e2b29bc3 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus/signin-button/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/globus_logo.png b/vite-app/src/apps/Auth2/resources/providers/globus_logo.png new file mode 100644 index 000000000..fa59b2780 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/globus_logo.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/logo.png b/vite-app/src/apps/Auth2/resources/providers/google/logo.png new file mode 100644 index 000000000..e795c0794 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/logo.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/disabled.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/disabled.png new file mode 100644 index 000000000..5a9c1815b Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/hover.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/hover.png new file mode 100644 index 000000000..b8bf773b0 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/normal.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/normal.png new file mode 100644 index 000000000..48b8ce6e8 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/pressed.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/pressed.png new file mode 100644 index 000000000..a78c42a5e Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/200px/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/disabled.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/disabled.png new file mode 100644 index 000000000..f57a56e40 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/hover.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/hover.png new file mode 100644 index 000000000..08a61c600 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-disabled.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-disabled.png new file mode 100644 index 000000000..735d17eea Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-focus.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-focus.png new file mode 100644 index 000000000..1bf1006f2 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-focus.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-normal.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-normal.png new file mode 100644 index 000000000..29ab51106 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-pressed.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-pressed.png new file mode 100644 index 000000000..e286c89ac Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/light/btn-pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/normal.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/normal.png new file mode 100644 index 000000000..db901c121 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google/signin-button/pressed.png b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/pressed.png new file mode 100644 index 000000000..e6d529b54 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google/signin-button/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/google_logo.png b/vite-app/src/apps/Auth2/resources/providers/google_logo.png new file mode 100644 index 000000000..e795c0794 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/google_logo.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/logo.png b/vite-app/src/apps/Auth2/resources/providers/orcid/logo.png new file mode 100644 index 000000000..eeb97949b Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/logo.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/logox.png b/vite-app/src/apps/Auth2/resources/providers/orcid/logox.png new file mode 100644 index 000000000..fa59b2780 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/logox.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/disabled.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/disabled.png new file mode 100644 index 000000000..cf7018f7d Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/hover.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/hover.png new file mode 100644 index 000000000..0b30c2d8b Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/normal.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/normal.png new file mode 100644 index 000000000..32150bdd7 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/pressed.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/pressed.png new file mode 100644 index 000000000..d6c24a2b0 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/200px/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/disabled.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/disabled.png new file mode 100644 index 000000000..c8d22bc5f Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/hover.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/hover.png new file mode 100644 index 000000000..bf2c5fb68 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/normal.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/normal.png new file mode 100644 index 000000000..e960c6627 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/pressed.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/pressed.png new file mode 100644 index 000000000..51d680994 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/darker/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/disabled.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/disabled.png new file mode 100644 index 000000000..5d6a4fb6a Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/hover.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/hover.png new file mode 100644 index 000000000..d243494d7 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/hover.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-disabled.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-disabled.png new file mode 100644 index 000000000..70db5ba64 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-disabled.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-focus.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-focus.png new file mode 100644 index 000000000..cba0ea427 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-focus.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-normal.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-normal.png new file mode 100644 index 000000000..8b432b975 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-pressed.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-pressed.png new file mode 100644 index 000000000..376b0da41 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/light/btn-pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/normal.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/normal.png new file mode 100644 index 000000000..2c8db80c5 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/normal.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/pressed.png b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/pressed.png new file mode 100644 index 000000000..9964cf96d Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid/signin-button/pressed.png differ diff --git a/vite-app/src/apps/Auth2/resources/providers/orcid_logo.png b/vite-app/src/apps/Auth2/resources/providers/orcid_logo.png new file mode 100644 index 000000000..fa59b2780 Binary files /dev/null and b/vite-app/src/apps/Auth2/resources/providers/orcid_logo.png differ diff --git a/vite-app/src/apps/Catalog.tsx b/vite-app/src/apps/Catalog.tsx index 0794799e9..33b810e6b 100644 --- a/vite-app/src/apps/Catalog.tsx +++ b/vite-app/src/apps/Catalog.tsx @@ -1,9 +1,10 @@ import { Component } from 'react'; import PluginWrapper2 from '../components/PluginWrapper/PluginWrapper2'; import { RouteProps, Router } from '../components/Router2'; -import { AuthenticationState } from '../contexts/Auth'; +import { AuthenticationState } from '../contexts/EuropaContext'; import { Route, SimplePluginRouteSpec } from '../lib/Route'; import { Config } from '../types/config'; +import { SignIn } from './Auth2/SignIn/SignIn'; export interface CatalogProps extends RouteProps { config: Config; @@ -11,106 +12,130 @@ export interface CatalogProps extends RouteProps { setTitle: (title: string) => void; } -interface CatalogState { -} - +interface CatalogState {} export default class Catalog extends Component { - - render() { const common = { - name: "catalog", + name: 'catalog', setTitle: this.props.setTitle, authState: this.props.authState, - config: this.props.config + config: this.props.config, }; const routeSpecs: Array = [ { path: '^(appcatalog|catalog)$/admin', auth: true, - view: 'catalogAdmin' + view: 'catalogAdmin', }, { path: 'catalog/queue', auth: true, - view: 'catalogQueue' + view: 'catalogQueue', }, { path: 'catalog', auth: false, - view: 'catalogIndex' + view: 'catalogIndex', }, { path: 'catalog/modules', auth: false, - view: 'moduleBrowser' + view: 'moduleBrowser', }, { path: 'catalog/services', auth: true, - view: 'serviceCatalog' + view: 'serviceCatalog', }, { path: 'catalog/datatypes', auth: false, - view: 'datatypeBrowser' + view: 'datatypeBrowser', }, { path: 'catalog/stats', auth: false, - view: 'catalogStatus' + view: 'catalogStats', }, { path: '^(appcatalog|catalog)$/^(app|apps)$/:namespace/:id/:tag?', auth: false, - view: 'appView' + view: 'appView', }, { path: '^(appcatalog|catalog)$/apps/:tag?', auth: false, - view: 'appsBrowser' + view: 'appsBrowser', }, { path: 'catalog/^(module|modules)$/:module_name', auth: false, - view: 'moduleView' + view: 'moduleView', }, { path: 'catalog/^(function|functions)/:module/:function_id/:ver?', auth: false, - view: 'functionView' + view: 'functionView', }, { path: 'catalog/functions/:tag?', auth: false, - view: 'functionBrowser' + view: 'functionBrowser', }, { path: 'catalog/register/:registration_id?', auth: true, - view: 'catalogRegistration' + view: 'catalogRegistration', }, { path: 'catalog/status/:module_names?', auth: false, - view: 'catalogStatus' - } + view: 'catalogStatus', + }, ]; const routes = routeSpecs.map(({ path, view, auth }) => { - return new Route(path, { authenticationRequired: auth }, (props: RouteProps) => { - return - }); + return new Route( + path, + { authenticationRequired: auth }, + (props: RouteProps) => { + return ( + + ); + }, + ); }); - return + const authRoute = new Route( + '^login|signin|signup$', + { authenticationRequired: false }, + (props: RouteProps) => { + return ( + + ); + }, + ); + return ( + + ); } } diff --git a/vite-app/src/apps/Feeds/api/Feeds.ts b/vite-app/src/apps/Feeds/api/Feeds.ts new file mode 100644 index 000000000..5c93f0a20 --- /dev/null +++ b/vite-app/src/apps/Feeds/api/Feeds.ts @@ -0,0 +1,179 @@ +import { RestClient } from './RestClient'; + +const API_PATH = 'api/V1/notification'; + +/** + * Instantiates the Feeds API. Requires both the endpoint (i.e. https://kbase.us/services/feeds) + * and a valid KBase Auth token. The token is NOT validated before use. + * @param {string} endpoint - the endpoint for the Feeds service + * @param {string} token - the user's auth token + */ + +export interface FeedEntity { + id: string; // e.g. username + name: string; // e.g. realname + type: string; // "user" +} + +export interface FeedActor extends FeedEntity { + // id: string; // e.g. username + // name: string // e.g. realname + // type: string // "user" +} + +export interface FeedObject extends FeedEntity { + // id: string; + // name: string; + // type: string ; // "group" +} + +export interface FeedTarget extends FeedEntity { + // id: string; + // name: string; + // type: string; +} + +export interface FeedItem { + actor: FeedActor; + context: null | Record; + created: number; + expires: number; + external_key: string; + id: string; + level: string; + object: FeedObject; + seen: boolean; + source: string; + target: Array; + verb: string; +} + +export interface Feed { + feed: Array; + name: string; + unseen: number; +} + +export type Notifications = Record; + +export interface GetNotificationsOptions { + reverseSort?: boolean; + verb?: string | number; + level?: string | number; + includeSeen?: boolean; +} + +export interface Notification { + verb: string; + object: string; + level: number; + context: Record; +} + +export interface GlobalNotification { + verb: string; + object: string; + level: number; + context: Record; + expires?: number; +} + +export interface UnseenNotificationCount { + global: number; + user: number; +} + +export interface UnseenNotificationCountResult { + unseen: UnseenNotificationCount; +} + +export class FeedsAPI extends RestClient { + /** + * Returns the list of notifications for a single user. + * @param {object} options + * - reverseSort - boolean + * - verb - string or int + * - level - string or int + * - includeSeen - boolean + */ + async getNotifications( + options: GetNotificationsOptions, + ): Promise { + const params = []; + if (options.reverseSort) { + params.push('rev=1'); + } + if (options.verb) { + params.push('v=' + options.verb); + } + if (options.level) { + params.push('l=' + options.level); + } + if (options.includeSeen) { + params.push('seen=1'); + } + const path = 'api/V1/notifications/?' + params.join('&'); + + return this.makeCall('GET', path); + } + + /** + * Posts a single notification. User's gotta be special. + * Note - this was mainly for early-stage debugging. Probably doesn't work + * anymore unless the user's auth token is really a service token. And if + * you're logging in with a service token.... don't. + * @param {object} data + * - verb + * - object + * - level + * - context (keys text, link) + */ + postNotification(data: Notification) { + return this.makeCall('POST', API_PATH, data); + } + + /** + * Posts a Global notification on behalf of an admin. Requires + * the used auth token to have the custom auth role FEEDS_ADMIN + * or an error will occur. + * @param {object} data + * - verb + * - object + * - level + * - context (keys: text, link) + * - expires (optional, default = 30 days after posting) + */ + postGlobalNotification(data: GlobalNotification) { + return this.makeCall('POST', `${API_PATH}/global`, data); + } + + /** + * Marks an array of notification ids as seen by the user. + * @param {Array} noteIds - array of note id strings + */ + markSeen(noteIds: Array) { + return this.makeCall('POST', `${API_PATH}/see`, { note_ids: noteIds }); + } + + /** + * Marks an array of notification ids as unseen by the given user. + * @param {Array} noteIds - array of note id strings + */ + markUnseen(noteIds: Array) { + return this.makeCall('POST', `${API_PATH}/unsee`, { + note_ids: noteIds, + }); + } + + /** + * Expires a single global notification from its id. + * Requires the user to have the custom auth role FEEDS_ADMIN, or an error + * will occur. + * @param {string} noteId - a single notification id + */ + expireGlobalNotification(noteId: string) { + return this.makeCall('POST', `${API_PATH}/expire`, { + note_ids: [noteId], + }); + } +} diff --git a/vite-app/src/apps/Feeds/api/Groups.ts b/vite-app/src/apps/Feeds/api/Groups.ts new file mode 100644 index 000000000..271ff14a1 --- /dev/null +++ b/vite-app/src/apps/Feeds/api/Groups.ts @@ -0,0 +1,30 @@ +import { RestClient } from './RestClient'; + +/** + * Groups API - some useful endpoints. + */ +export class GroupsAPI extends RestClient { + constructor(endpoint: string, token: string) { + super(endpoint, token); + } + + /** + * Returns the resource info from a groups request. + * From the Groups docs: + * + * GET /request/id//resource + * RETURNS: a resource entry (but see below). + * + * Resource entries are described in Resources above. The resource entry returned here is + * slightly different: a) there is no added field because presumably the resource has not + * yet been added to the group, and b) there is an additional resourcetype field that + * specifies the type of the resource. + * + * The request must be open and the type must be Request, the resource type cannot be + * user, and the user must be a group administrator. + * @param {string} requestId + */ + getResourceInfo(requestId: string) { + return this.makeCall('GET', `request/id/${requestId}/resource`); + } +} diff --git a/vite-app/src/apps/Feeds/api/RestClient.ts b/vite-app/src/apps/Feeds/api/RestClient.ts new file mode 100644 index 000000000..476fd6bba --- /dev/null +++ b/vite-app/src/apps/Feeds/api/RestClient.ts @@ -0,0 +1,83 @@ +/** + * A generic REST(ish) API caller. + * Really simple. This just ensures that a URL and token exist, + * it makes calls to them and returns the results. + * + * Child classes should implement what endpoints should be use + * and how to parse the final results, if at all. + */ +export class RestClient { + endpoint: string; + token: string; + constructor(endpoint: string, token: string) { + if (!endpoint) { + throw new Error('Feeds endpoint required!'); + } + if (!endpoint.endsWith('/')) { + endpoint = endpoint + '/'; + } + if (!token) { + throw new Error('Auth token required'); + } + + this.endpoint = endpoint; + this.token = token; + } + + /** + * Makes a generic API call to the feeds service. + * Really, this could probably be used for any RESTish service. + * It's also really really simple. Just given the method, path, + * and data, it crafts the REST call by using the Fetch API. + * If the method isn't one of the usual HTTP verbs (GET, POST, PUT, DELETE), + * this raises an error. + * This returns a Promise with either the result of the call de-JSONified, + * or it raises an error. + * @param {string} method + * @param {string} path + * @param {object} options + */ + async makeCall(method: string, path: string, data?: unknown) { + // remove the first slash, if present + if (path.startsWith('/')) { + path = path.substring(1); + } + method = method.toLocaleUpperCase(); + if (!['GET', 'POST', 'PUT', 'DELETE'].includes(method)) { + throw new Error('Method ' + method + ' not usable'); + } + const url = this.endpoint + path; + const request: RequestInit = { + method, + cache: 'no-cache', + headers: { + 'Content-type': 'application/json; charset=utf-8', + Authorization: this.token, + }, + redirect: 'follow', + referrer: 'no-referrer', + }; + if (data) { + request.body = JSON.stringify(data); + } + + const response = this.handleErrors(await fetch(url, request)); + + return await response.json(); + } + + /** + * Invisibly deals with errors from Fetch. Fetch is nice, but annoying in + * that the 400-level errors don't raise errors on their own. This wraps + * the call and deals with that before returning the response to whatever + * called this API. + * @param {object} response - a response from the Fetch API. + */ + handleErrors(response: Response) { + if (!response.ok) { + console.error(response); + throw Error(response.statusText); + } + return response; + } +} diff --git a/vite-app/src/apps/Feeds/components/Entity.tsx b/vite-app/src/apps/Feeds/components/Entity.tsx new file mode 100644 index 000000000..fae464125 --- /dev/null +++ b/vite-app/src/apps/Feeds/components/Entity.tsx @@ -0,0 +1,97 @@ +import UILink from 'components/UILink2'; +import { Component } from 'react'; +import { FeedEntity } from '../api/Feeds'; + +export type Variant = 'danger' | 'warning' | 'info'; + +export interface EntityIconProps { + type: string; +} + +const DEFAULT_ICON = 'cog'; + +const ENTITY_ICONS: Record = { + user: 'user', + narrative: 'file-o', + workspace: 'file-o', + job: 'suitcase', + group: 'users', +}; + +export class EntityIcon extends Component { + render() { + const iconClassFragment = ENTITY_ICONS[this.props.type] || DEFAULT_ICON; + return ; + } +} + +export interface EntityProps { + username: string; + entity: FeedEntity; +} + +export default class Entity extends Component { + renderNarrativeLink(id: string, name: string) { + name = name || id; + return ( + + {name} + + ); + } + + renderWorkspaceLink(id: string, name: string) { + name = name || id; + return ( + + {name} + + ); + } + + renderGroupLink(id: string, name: string) { + name = name || id; + return ( + + {name || '(name not accessible)'} + + ); + } + + renderUserLink(userId: string, name: string) { + let label = name ? name : userId; + if (userId === this.props.username) { + label += ' (you)'; + } + return ( + + {label} + + ); + } + + renderEntityLink(type: string, id: string, name: string) { + switch (type) { + case 'user': + return this.renderUserLink(id, name); + case 'group': + return this.renderGroupLink(id, name); + case 'workspace': + return this.renderWorkspaceLink(id, name); + case 'narrative': + return this.renderNarrativeLink(id, name); + default: + return name === null ? id : `${name} (${id})`; + } + } + + render() { + const { type, id, name } = this.props.entity; + return ( + + {' '} + {this.renderEntityLink(type, id, name)} + + ); + } +} diff --git a/vite-app/src/apps/Feeds/components/controller.tsx b/vite-app/src/apps/Feeds/components/controller.tsx new file mode 100644 index 000000000..08bb3a77d --- /dev/null +++ b/vite-app/src/apps/Feeds/components/controller.tsx @@ -0,0 +1,932 @@ +// define(['../api/feeds', './globalPoster', './feedTabs', '../util'], function (FeedsAPI, GlobalPoster, FeedTabs, Util) { + +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; + +import { RouteProps } from 'components/Router2'; +import { + AuthenticationStateAuthenticated, + notifyError, +} from 'contexts/EuropaContext'; +import { + RepeatAsyncProcess, + RepeatAsyncProcessStatus, +} from 'lib/RepeatableAsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { + Feed, + FeedNotification, + FeedsClient, + UnseenNotificationCount, +} from 'lib/clients/Feeds'; +import { Component } from 'react'; +import { Config } from 'types/config'; +// import { Feed, FeedsAPI, Notifications, UnseenNotificationCount } from "../api/Feeds"; +import AsyncQueue from 'lib/AsyncQueue'; +import { Monitor } from 'lib/Monitor'; +import { navigate2 } from 'lib/navigation'; +import FeedsView, { FeedsLayout } from './view'; + +const FEEDS_ADMIN_ROLE = 'FEEDS_ADMIN'; + +export interface FeedsControllerProps extends RouteProps { + config: Config; + authState: AuthenticationStateAuthenticated; + setTitle: (title: string) => void; +} + +export interface FeedWithId { + id: string; + feed: Feed; +} + +export interface Filterable { + show: boolean; + value: T; +} + +export type FeedsFilter = 'all' | 'unseen'; +export type NotificationsFilter = 'all' | 'unssen'; + +export interface FilterData { + feedsFilter: FeedsFilter; + allFeeds: Array>; + feedsMap: Record>; + + global?: FeedWithId; + user?: FeedWithId; + userFeeds: Array; + notifications: Array; + selectedFeed?: FeedWithId; +} + +export interface FeedData extends FilterData { + isAdmin: boolean; + // global: Filterable; + // user: Filterable; + // feeds: Array; + // userFeeds: Array>; + // allFeeds: Array>; + // feedsMap: Record>; + unseen: UnseenNotificationCount; + totalUnseenCount: number; + feedsLayout: FeedsLayout; + + // selectedFeed?: FeedWithId; + // feedsFilter: FeedsFilter; + notificationsFilter: NotificationsFilter; + feeds: Array; +} + +interface FeedsControllerState { + feedsState: RepeatAsyncProcess; +} + +export default class FeedsController extends Component< + FeedsControllerProps, + FeedsControllerState +> { + monitor: Monitor; + queue: AsyncQueue; + constructor(props: FeedsControllerProps) { + super(props); + + this.state = { + feedsState: { + status: RepeatAsyncProcessStatus.NONE, + }, + }; + + this.monitor = new Monitor({ + callback: this.doRefreshAlarm.bind(this), + interval: 10000, + }); + + this.queue = new AsyncQueue({ queuePauseTime: 250 }); + } + + async doRefreshAlarm() { + // TODO: if the reloadData is async, we could ensure it is accounted for in + // the monitor loop. Should not be a problem though, as the refresh time, + // dominated by fetching the notifications from the service, should be much + // shorter, far less than a second, than the refresh poll interval, which + // should be on the order of 10 secons. + this.doRefresh(); + } + + componentDidMount() { + this.props.setTitle('Notification Feeds'); + this.loadData(); + this.monitor.start(); + } + + componentWillUnmount(): void { + this.monitor.stop(); + } + + componentDidUpdate(prevProps: FeedsControllerProps) { + const prevSelectedFeedId = + prevProps.match.params.get('tab') || 'global'; + const selectedFeedId = this.props.match.params.get('tab') || 'global'; + + if (prevSelectedFeedId === selectedFeedId) { + return; + } + + if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + return; + } + + if (!(selectedFeedId in this.state.feedsState.value.feedsMap)) { + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: `Could not find feed ${selectedFeedId}`, + }, + }, + }); + return; + } + + this.setState({ + feedsState: { + ...this.state.feedsState, + value: { + ...this.state.feedsState.value, + selectedFeed: + this.state.feedsState.value.feedsMap[selectedFeedId]! + .value, + }, + }, + }); + } + + async fetchFeeds() { + const feedsClient2 = new FeedsClient({ + url: this.props.config.services.Feeds.url, + token: this.props.authState.authInfo.token, + }); + + // Get the initial feed. + const rawFeeds = await feedsClient2.getNotifications({ + limit: 100, + includeSeen: true, + }); + const { unseen } = await feedsClient2.getUnseenNotificationsCount(); + + // Determine if an admin. + const isAdmin = + this.props.authState.authInfo.account.customroles.includes( + FEEDS_ADMIN_ROLE, + ); + + // GLOBAL POSTER? + + const feeds: Array = Object.entries(rawFeeds).map( + ([id, feed]) => { + return { + id, + feed, + }; + }, + ); + + return { unseen, isAdmin, feeds }; + } + + async loadData() { + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.PENDING, + }, + }); + + try { + const { unseen, isAdmin, feeds } = await this.fetchFeeds(); + // // Get the initial feed. + // const rawFeeds = await feedsClient2.getNotifications({limit: 100, includeSeen: true}); + // const {unseen} = await feedsClient2.getUnseenNotificationsCount(); + + // // Determine if an admin. + // const isAdmin = this.props.authState.authInfo.account.customroles.includes(FEEDS_ADMIN_ROLE) + + // // GLOBAL POSTER? + + // const feeds: Array = Object.entries(rawFeeds) + // .map(([id, feed]) => { + // return { + // id, + // feed + // } + // }) + + // const notifications: Array = []; + + // for (const [id, feed] of Object.entries(rawFeeds)) { + // for (const notification of feed.feed) { + // notifications.push(notification) + // } + // } + + const feedsWithFilterApplied = this.applyFilter( + feeds, + 'all', + this.props.match.params.get('tab') || 'global', + ); + + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.SUCCESS, + value: { + isAdmin, + unseen, + totalUnseenCount: unseen.global + unseen.user, + notificationsFilter: 'all', + feedsLayout: 'source', + feeds, + ...feedsWithFilterApplied, + }, + }, + }); + } catch (ex) { + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: + ex instanceof Error ? ex.message : 'Unknown Error', + }, + }, + }); + } + // this.initializeData().then((feedData) => { + // const token = runtime.service('session').getAuthToken(); + // return runtime + // .service('session') + // .auth2Client.getMe(token) + // .then(({ customroles }) => { + // this.element.innerHTML = ''; + // if (customroles.includes('FEEDS_ADMIN')) { + // this.isAdmin = true; + // this.globalPoster = new GlobalPoster({ + // afterSubmitFn: this.refreshFeed.bind(this), + // runtime: runtime + // }); + // this.element.appendChild(this.globalPoster.element); + // } + + // this.myFeeds = {}; + // // make an object from all feeds where key = feed id, value = feed info + // Object.keys(feedData).forEach((feed) => { + // this.myFeeds[feed] = [feed, feedData[feed].name]; + // }); + // this.myFeeds.global[1] = 'KBase Announcements'; + // // make the order. Should be: + // // 0. global + // // 1. user + // // rest = other feeds in alphabetical order + // // seed with just global and user + // const feedOrder = Object.keys(this.myFeeds); + // feedOrder.splice(feedOrder.indexOf('global'), 1); + // feedOrder.splice(feedOrder.indexOf('user'), 1); + // feedOrder.sort((a, b) => { + // return feedData[a].name.localeCompare(feedData[b].name); + // }); + // feedOrder.unshift('user'); + // feedOrder.unshift('global'); + + // const feedList = feedOrder.map((feed) => this.myFeeds[feed]); + + // const unseenSet = {}; + // for (const f in feedData) { + // unseenSet[f] = feedData[f].unseen; + // } + + // this.feedTabs = new FeedTabs({ + // feeds: feedList, + // feedUpdateFn: this.updateFeed.bind(this), + // unseen: unseenSet, + // globalFeed: feedData.global.feed, + // runtime: runtime, + // isAdmin: this.isAdmin, + // userId: this.userId + // }); + // this.element.appendChild(this.feedTabs.element); + // }); + // }); + } + + async reloadData() { + if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + return; + } + // const feedFilter = this.state.feedsState.value.feedsFilter; + + this.setState({ + feedsState: { + ...this.state.feedsState, + status: RepeatAsyncProcessStatus.SUCCESS_PENDING, + }, + }); + // const feedsClient = new FeedsAPI(this.props.config.services.Feeds.url, this.props.authState.authInfo.token); + // const feedsClient2 = new FeedsClient({ + // url: this.props.config.services.Feeds.url, + // token: this.props.authState.authInfo.token + // }) + try { + const { unseen, isAdmin, feeds } = await this.fetchFeeds(); + // // Get the initial feed. + // const notifications = await feedsClient2.getNotifications({limit: 100, includeSeen: true}); + // const {unseen} = await feedsClient2.getUnseenNotificationsCount(); + + // // GLOBAL POSTER? + + // // Determine if an admin. + // const isAdmin = this.props.authState.authInfo.account.customroles.includes(FEEDS_ADMIN_ROLE) + + // // GLOBAL POSTER? + + // const feeds: Array = Object.entries(notifications) + // .map(([id, feed]) => { + // return { + // id, + // feed + // } + // }) + + const { feedsFilter, selectedFeed, feedsLayout } = + this.state.feedsState.value; + + const feedsWithFilterApplied = this.applyFilter( + feeds, + feedsFilter, + selectedFeed ? selectedFeed.id : undefined, + ); + + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.SUCCESS, + value: { + isAdmin, + unseen, + totalUnseenCount: unseen.global + unseen.user, + notificationsFilter: 'all', + feedsLayout, + feeds, + ...feedsWithFilterApplied, + }, + }, + }); + } catch (ex) { + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: + ex instanceof Error ? ex.message : 'Unknown Error', + }, + }, + }); + } + } + + // async reloadData2() { + // if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + // return; + // } + // const feedFilter = this.state.feedsState.value.feedsFilter; + + // await new Promise((resolve) => { + // if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + // return; + // } + // this.setState({ + // feedsState: { + // ...this.state.feedsState, + // status: RepeatAsyncProcessStatus.SUCCESS_PENDING + // } + // }, () => resolve); + // }); + + // // const feedsClient = new FeedsAPI(this.props.config.services.Feeds.url, this.props.authState.authInfo.token); + // const feedsClient2 = new FeedsClient({ + // url: this.props.config.services.Feeds.url, + // token: this.props.authState.authInfo.token + // }) + // try { + // // Get the initial feed. + // const notifications = await feedsClient2.getNotifications({limit: 100, includeSeen: true}); + // const {unseen} = await feedsClient2.getUnseenNotificationsCount(); + + // // GLOBAL POSTER? + + // function filterIt(feed: FeedWithId): Filterable { + // const show = (() => { + // switch (feedFilter) { + // case 'all': return true; + // case 'unseen': return feed.feed.unseen > 0; + // } + // })(); + // return {show, value: feed} + // } + + // const allFeeds: Array> = Object.entries(notifications) + // .map(([id, feed]) => { + // // Show if current feed filter is honored. + // return filterIt({id, feed}); + // }) + + // allFeeds.sort((a: Filterable, b: Filterable) => { + // return a.value.feed.name.localeCompare(b.value.feed.name); + // }) + + // const userFeeds = allFeeds.filter((feed) => { + // return feed.value.id !== "global" && feed.value.id !== "user" + // }) + + // const selectedFeedId = this.props.match.params.get('tab') || 'global' + + // const feedsMap = allFeeds.reduce< Record>>((accum, feed) => { + // accum[feed.value.id] = feed; + // return accum; + // },{}); + + // // const globalFeed: FeedWithId = {id: 'global', feed: notifications['global']!} + + // const global = feedsMap['global']; + + // // const global = { + // // show: true, + // // value: globalFeed + // // }; + + // // const userFeed: FeedWithId = {id: 'user', feed: notifications['user']!}; + // const user = feedsMap['user']; + + // return new Promise((resolve) => { + // if (this.state.feedsState.status === RepeatAsyncProcessStatus.SUCCESS_PENDING) { + // this.setState({ + // feedsState: { + // status: RepeatAsyncProcessStatus.SUCCESS, + // value: { + // ...this.state.feedsState.value, + // allFeeds, + // feedsMap, + // feeds: userFeeds, + // unseen, + // totalUnseenCount: unseen.global + unseen.user, + // global, + // user, + // selectedFeed: {id: selectedFeedId, feed: notifications[selectedFeedId]!}, + // } + // } + // }, () => resolve); + // } else { + // resolve(null); + // } + // }); + // } catch (ex) { + // return new Promise((resolve) => { + // this.setState({ + // feedsState: { + // status: RepeatAsyncProcessStatus.ERROR, + // error: { + // message: ex instanceof Error ? ex.message : 'Unknown Error' + // } + // } + // }, () => resolve) + // }); + // } + // } + + // updateFeed(feedKey) { + // return this.feedsApi + // .getNotifications({ includeSeen: true }) + // .then((feed) => { + // if (feed[feedKey]) { + // return feed[feedKey]; + // } else { + // return {}; + // } + // }) + // .catch((err) => { + // console.error(err); + // }); + // } + + // async initializeData() { + + // } + + /** + * + * @param {object} filters + * - reverseSort - boolean + * - verb - string or int + * - level - string or int + * - source - string + * - includeSeen - boolean + */ + // refreshFeed() { + // this.feedsApi + // .getNotifications({ includeSeen: true }) + // .then((feed) => { + // this.feedTabs.refresh(feed); + // const unseenSet = {}; + // for (const f in feed) { + // unseenSet[f] = feed[f].unseen; + // } + // this.feedTabs.setUnseenCounts(unseenSet); + // }) + // .catch((err) => { + // this.renderError(err); + // }); + // } + + // renderError(err) { + // console.error(err); + // // xss safe + // this.element.innerHTML = ` + //
    + // An error occurred while fetching your feed! + //
    + // `; + // } + + // doFilterFeeds(filter: string) { + // if (this.state.feedsState.status !== AsyncProcessStatus.SUCCESS) { + // return; + // } + // this.setState({ + // feedsState: { + // ...this.state.feedsState, + // value: { + // ...this.state.feedsState.value, + // feedsFilter: filter, + // feeds: this.state.feedsState.value.feeds.filter((value) => { + // // const {show, {id, feed}} = value; + // return true; + // }) + // } + // } + // }) + // } + + selectFeed(feed: FeedWithId) { + // TODO: refactor to select the feed item first, then set the navigation for + // Europa w/o actual navigation. + this.queue.addItem(async () => { + return new Promise((resolve) => { + if ( + this.state.feedsState.status !== + RepeatAsyncProcessStatus.SUCCESS + ) { + console.warn( + 'Feeds state not SUCCESS, so cannot select a feed', + ); + return; + } + + if (!(feed.id in this.state.feedsState.value.feedsMap)) { + this.setState({ + feedsState: { + status: RepeatAsyncProcessStatus.ERROR, + error: { + message: `Could not find feed ${feed.id}`, + }, + }, + }); + return; + } + + // $GlobalMessenger.send('europa', 'navigate', { + // path: 'feeds2', params: {tab: feed.id} + // }) + + navigate2({ + path: 'feeds', + params: { tab: feed.id }, + type: 'kbaseui', + newWindow: false, + }); + + this.setState( + { + feedsState: { + ...this.state.feedsState, + value: { + ...this.state.feedsState.value, + selectedFeed: + this.state.feedsState.value.feedsMap[ + feed.id + ]!.value, + }, + }, + }, + () => resolve(), + ); + }); + + // navigate2({path: 'feeds2', params: {tab: feed.id}, type: 'kbaseui', newWindow: false}); + }); + } + + // applyFilter(state: FeedData, feedsFilter: FeedsFilter): FeedData { + // function filterIt(feed: FeedWithId): Filterable { + // const show = (() => { + // switch (feedsFilter) { + // case 'all': return true; + // case 'unseen': return feed.feed.unseen > 0; + // } + // })(); + // return {show, value: feed} + // } + + // const allFeeds = state.allFeeds.map(({value}) => { + // return filterIt(value); + // }); + + // const feedsMap = allFeeds.reduce< Record>>((accum, feed) => { + // accum[feed.value.id] = feed; + // return accum; + // },{}); + + // const feeds = state.feeds.map(({value}) => { + // return filterIt(value); + // }); + + // const selectedFeed = (() => { + // if (state.selectedFeed) { + // const selectedFeed = state.selectedFeed; + // const filteredFeed = feedsMap[selectedFeed.id]; + // if (!filteredFeed || !filteredFeed.show) { + // const firstShown = allFeeds.filter(({show}) => show)[0]; + // if (firstShown) { + // return firstShown.value; + // } + // return; + // } + // return filteredFeed.value; + // } + // })(); + + // return { + // ...state, + // feedsFilter, + // feedsMap, + // allFeeds, + // global: filterIt(state.global.value), + // user: filterIt(state.user.value), + // feeds, + // selectedFeed + // }; + // } + + applyFilter( + feeds: Array, + feedsFilter: FeedsFilter, + selectedFeedId?: string, + ): FilterData { + function filterIt(feed: FeedWithId): Filterable { + const show = (() => { + switch (feedsFilter) { + case 'all': + return true; + case 'unseen': + return feed.feed.unseen > 0; + } + })(); + return { show, value: feed }; + } + + const allFeeds = feeds.map((feed) => { + return filterIt(feed); + }); + + const feedsMap = allFeeds.reduce< + Record> + >((accum, feed) => { + accum[feed.value.id] = feed; + return accum; + }, {}); + + allFeeds.sort( + (a: Filterable, b: Filterable) => { + return a.value.feed.name.localeCompare(b.value.feed.name); + }, + ); + + const userFeeds = allFeeds + .filter((feed) => { + return ( + feed.value.id !== 'global' && + feed.value.id !== 'user' && + feed.show + ); + }) + .map(({ value }) => value); + const global = feedsMap['global'].show + ? feedsMap['global'].value + : undefined; + const user = feedsMap['user'].show ? feedsMap['user'].value : undefined; + + // const selectedFeedId = this.props.match.params.get('tab') || 'global' + + const selectedFeed = (() => { + const feedId = selectedFeedId || this.props.match.params.get('tab'); + if (feedId) { + const selectedFeed = feedsMap[feedId]; + // const filteredFeed = feedsMap[selectedFeed.id]; + if (!selectedFeed || !selectedFeed.show) { + const firstShown = allFeeds.filter(({ show }) => show)[0]; + if (firstShown) { + return firstShown.value; + } + return; + } + return selectedFeed.value; + } + return ( + global || + user || + (userFeeds.length > 0 ? userFeeds[0] : undefined) + ); + })(); + + const notifications: Array = []; + + for (const feed of feeds) { + for (const notification of feed.feed.feed) { + if ( + !notification.seen || + (notification.seen && feedsFilter === 'all') + ) { + notifications.push(notification); + } + } + } + + return { + feedsFilter, + feedsMap, + allFeeds, + global, + user, + userFeeds, + notifications, + selectedFeed, + }; + } + + doFilterFeed(feedsFilter: FeedsFilter) { + this.queue.addItem(async () => { + return new Promise((resolve) => { + if ( + this.state.feedsState.status !== + RepeatAsyncProcessStatus.SUCCESS + ) { + console.warn( + 'Feeds state not SUCCESS, so cannot select a feed', + ); + return; + } + const { selectedFeed } = this.state.feedsState.value; + this.setState( + { + feedsState: { + ...this.state.feedsState, + value: { + ...this.state.feedsState.value, + ...this.applyFilter( + this.state.feedsState.value.feeds, + feedsFilter, + selectedFeed ? selectedFeed.id : undefined, + ), + }, + }, + }, + () => resolve(), + ); + }); + }); + } + + doFilterNotifications() { + if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + console.warn('Feeds state not SUCCESS, so cannot select a feed'); + return; + } + } + + async doToggleSeen(notification: FeedNotification) { + this.queue.addItem(async () => { + // But this won't trigger a re-render cascade right now, so + if ( + this.state.feedsState.status !== + RepeatAsyncProcessStatus.SUCCESS + ) { + return; + } + const feedsClient2 = new FeedsClient({ + url: this.props.config.services.Feeds.url, + token: this.props.authState.authInfo.token, + }); + try { + if (notification.seen) { + await feedsClient2.markUnseen([notification.id]); + } else { + await feedsClient2.markSeen([notification.id]); + } + this.reloadData(); + } catch (ex) { + const message = + ex instanceof Error ? ex.message : 'Unknown error'; + //{title, message, autodismiss, variant} + notifyError(message); + } + }); + } + + doRefresh() { + this.queue.addItem(async () => { + return this.reloadData(); + }); + } + + changeFeedsLayout(feedsLayout: FeedsLayout) { + if (this.state.feedsState.status !== RepeatAsyncProcessStatus.SUCCESS) { + console.warn( + 'Feeds state not SUCCESS, so cannot select a feed view', + ); + return; + } + this.setState({ + feedsState: { + ...this.state.feedsState, + value: { + ...this.state.feedsState.value, + feedsLayout, + }, + }, + }); + } + + render() { + switch (this.state.feedsState.status) { + case RepeatAsyncProcessStatus.NONE: + case RepeatAsyncProcessStatus.PENDING: + return ; + case RepeatAsyncProcessStatus.ERROR: + return ( + + ); + case RepeatAsyncProcessStatus.SUCCESS_PENDING: + case RepeatAsyncProcessStatus.SUCCESS: { + const { + isAdmin, + global, + user, + userFeeds, + notifications, + feedsFilter, + notificationsFilter, + selectedFeed, + feedsLayout, + } = this.state.feedsState.value; + return ( + + ); + } + } + } +} diff --git a/vite-app/src/apps/Feeds/components/feed.xts b/vite-app/src/apps/Feeds/components/feed.xts new file mode 100644 index 000000000..162ce4d20 --- /dev/null +++ b/vite-app/src/apps/Feeds/components/feed.xts @@ -0,0 +1,156 @@ +define([ + './notification', + '../util' +], (Notification, + Utils) => { + 'use strict'; + class Feed { + /** + * + * @param {object} config + * - runtime - the runtime object + * - refreshFn - gets invoked when the feed wants to be refreshed + * - feedName - the feed name, shown in the header + * - showControls - boolean, if true, shows controls. + * - showSeen - boolean, if true, gives the option to dismiss (mark as seen) notifications + */ + constructor(config) { + this.runtime = config.runtime; + this.refreshFn = config.refreshFn; + this.userName = config.feedName || ''; + this.showControls = config.showControls || false; + this.showSeen = (config.showSeen === undefined || config.showSeen === null) ? true : config.showSeen; + + this.element = document.createElement('div'); + this.element.classList.add('panel', 'panel-default'); + // xss safe + this.element.innerHTML = ` +
    + + ${Utils.cleanText(this.userName)} notifications + + ${this.showControls ? this.renderFilters() : ''} +
    +
    + `; + this.ctrlState = { + includeSeen: false, + reverseSort: false, + level: null, + verb: null, + source: null + }; + if (this.showControls) { + this.bindEvents(); + } + } + + bindEvents() { + const ctrls = this.element.querySelector('.panel-heading div#feed-inputs'); + // toggle eye + ctrls.querySelector('#seen-btn').onclick = () => { + const btnIcon = ctrls.querySelector('#seen-btn .fa'); + if (btnIcon.classList.contains('fa-eye-slash')) { + btnIcon.classList.replace('fa-eye-slash', 'fa-eye'); + this.ctrlState.includeSeen = true; + } + else { + btnIcon.classList.replace('fa-eye', 'fa-eye-slash'); + this.ctrlState.includeSeen = false; + } + this.refresh(); + }; + + // toggle order + ctrls.querySelector('#sort-btn').onclick = () => { + const btnIcon = ctrls.querySelector('#sort-btn .fa'); + if (btnIcon.classList.contains('fa-sort-numeric-desc')) { + btnIcon.classList.replace('fa-sort-numeric-desc', 'fa-sort-numeric-asc'); + this.ctrlState.reverseSort = false; + } + else { + btnIcon.classList.replace('fa-sort-numeric-asc', 'fa-sort-numeric-desc'); + this.ctrlState.reverseSort = true; + } + this.refresh(); + }; + + // level filter + ctrls.querySelector('#level-filter').onchange = (e) => { + if (e.target.selectedIndex === 0) { + this.ctrlState.level = null; + } + else { + this.ctrlState.level = e.target.value; + } + this.refresh(); + }; + + // source filter + ctrls.querySelector('#source-filter').onchange = (e) => { + if (e.target.selectedIndex === 0) { + this.ctrlState.source = null; + } + else { + this.ctrlState.source = e.target.value; + } + this.refresh(); + }; + } + + refresh() { + // get filter info from controls + // run the refresh function + // update this feed with the results + this.refreshFn(this.ctrlState); + } + + renderFilters() { + const levels = ['alert', 'warning', 'error', 'request'], services = ['groups', 'workspace', 'jobs', 'narrative'], filterHtml = ` +
    + + + + +
    + `; + + return filterHtml; + } + + remove() { + this.element.querySelector('.panel-body').innerHTML = ''; + } + + updateFeed(feed, token) { + this.remove(); + const userFeed = this.element.querySelector('.panel-body'); + feed.feed.forEach(note => { + const noteObj = new Notification(note, { + runtime: this.runtime, + token: token, + refreshFn: this.refresh.bind(this), + showSeen: this.showSeen + }); + userFeed.appendChild(noteObj.element); + }); + } + + setUserName(userName) { + this.userName = userName; + // xss safe + this.element.querySelector('#user-feed-name').innerHTML = Utils.cleanText(userName); + } + } + return Feed; +}); diff --git a/vite-app/src/apps/Feeds/components/feedTabs.xts b/vite-app/src/apps/Feeds/components/feedTabs.xts new file mode 100644 index 000000000..9ec2df35a --- /dev/null +++ b/vite-app/src/apps/Feeds/components/feedTabs.xts @@ -0,0 +1,237 @@ +/** + * + */ +define(['./notification', '../util', '../api/feeds'], function (Notification, Util, FeedsAPI) { + 'use strict'; + const SEEN_TIMEOUT = 10000; + + class FeedTabs { + /** + * + * @param {Object} config + * feeds = list of feeds in order they should appear (key and full name) + * - [[global, KBase], [user, Some User], [group1, My Special Group], ...] + * element = target DOM node to render in + * + */ + constructor(config) { + this.userId = config.userId; + this.isAdmin = config.isAdmin; + this.runtime = config.runtime; + this.feedUpdateFn = config.feedUpdateFn; + const feeds = config.feeds; + this.feeds = {}; + this.order = []; + this.element = document.createElement('div'); + this.element.classList.add('feeds-tabs-container'); + feeds.forEach((f) => { + this.feeds[f[0]] = f[1]; + this.order.push(f[0]); + }); + this.notes = config.globalFeed; + this.render(); + this.setUnseenCounts(config.unseen); + this.renderFeed(); + } + + render() { + // Make the general structure + // run addFeed on each element + // select the first one and refresh it + this.mainElem = document.createElement('div'); + this.element.appendChild(this.mainElem); + const structure = ` +
    +
    + `; + // xss safe + this.element.innerHTML = structure; + this.order.forEach((f) => this.addFeed(f, this.feeds[f])); + this.element.querySelector('.feed-tabs div:first-child').classList.add('feed-selected'); + } + + addFeed(feedKey, feedName) { + const tab = document.createElement('div'); + tab.classList.add('feed-tab-btn'); + // xss safe + tab.innerHTML = ` + ${Util.cleanText(feedName)} +
    + ); + } + render() { + return ( +
    + {this.renderToolbar()} + {this.renderJobLog()} +
    + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/JobStatusBadge.tsx b/vite-app/src/apps/JobBrowser/components/JobStatusBadge.tsx new file mode 100644 index 000000000..6577c5055 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/JobStatusBadge.tsx @@ -0,0 +1,227 @@ +import { InfoCircleOutlined, LoadingOutlined } from '@ant-design/icons'; +import { Tag, Tooltip } from 'antd'; +import NiceTimeDuration from 'components/NiceTimeDuration'; +import { Component } from 'react'; +import { Job } from '../store'; +import { JobEvent, JobStateType } from '../types/jobState'; +import NiceElapsedTime from './NiceElapsedTime'; +import NiceRelativeTime from './NiceRelativeTime'; + +const STALE_AFTER = 300000; + +function currentEvent(job: Job): JobEvent { + return job.eventHistory[job.eventHistory.length - 1]; +} + +/** + * Translates a job status value to a color value acceptable for the color + * prop for the job status tag. + * + * @param status - the status of the job + */ +export function jobColor(job: Job): string { + switch (currentEvent(job).type) { + case JobStateType.CREATE: + return 'purple'; + case JobStateType.QUEUE: + return 'orange'; + case JobStateType.RUN: + return 'blue'; + case JobStateType.COMPLETE: + return 'green'; + case JobStateType.ERROR: + return 'red'; + case JobStateType.TERMINATE: + return 'gray'; + default: + throw new Error('Invalid job status'); + } +} + +export interface JobStatusProps { + job: Job; + showTiming?: boolean; +} + +interface JobStatusState {} + +export default class JobStatusBadge extends Component< + JobStatusProps, + JobStatusState +> { + renderTag() { + const label = this.renderJobStatusLabel(); + const color = jobColor(this.props.job); + return ( + + {label} + + ); + } + /** + * Translates a job status value to a label, with optional icon, suitable for + * display as the child of the job status tag. + * + * @param status - the status of the job + * + * @note Since the switch is over an enum, we don't have to worry about the default case + */ + renderJobStatusLabel() { + switch (currentEvent(this.props.job).type) { + case JobStateType.CREATE: + return 'Created'; + case JobStateType.QUEUE: + return ( + + Queued + + ); + case JobStateType.RUN: + return ( + + Running + + ); + case JobStateType.COMPLETE: + return 'Completed'; + case JobStateType.ERROR: + return 'Errored'; + case JobStateType.TERMINATE: + return 'Canceled'; + default: + throw new Error('Invalid job status'); + } + } + + renderJobStatusTooltip() { + const event = currentEvent(this.props.job); + switch (event.type) { + case JobStateType.CREATE: { + // A created job is stale if over 5 minutes old + const stale = () => { + const now = new Date().getTime(); + const elapsed = now - event.at; + if (elapsed > STALE_AFTER) { + return ( +

    + This job is considered orphaned, since it + was created + {' '} + ago. A job should move into a queue within{' '} + {}. +

    + ); + } + }; + return ( +
    +

    + This job has been received by the execution engine, + but not yet queued for running. +

    + {stale()} +
    + ); + } + case JobStateType.QUEUE: + return ( +
    +

    + This job has been queued for running +

    +

    + You may inspect the job log by clicking the{' '} + button in the leftmost + column. +

    +
    + ); + case JobStateType.RUN: + return ( +
    +

    + This job is currently running. +

    +

    + You may inspect the job log by clicking the{' '} + button in the leftmost + column. +

    +
    + ); + case JobStateType.COMPLETE: + return ( +
    +

    + This job has completed successfully. +

    +

    + You may inspect the job log by clicking the{' '} + button in the leftmost + column. +

    +
    + ); + case JobStateType.ERROR: + return ( +
    +

    + This job experienced an error. +

    +

    + You may inspect the error and job log by clicking + the button in the leftmost + column. +

    +
    + ); + case JobStateType.TERMINATE: + return ( +
    +

    + This job has been canceled. +

    +

    + You may inspect the job log by clicking the{' '} + button in the leftmost + column. +

    +
    + ); + default: + throw new Error('Invalid job status'); + } + } + + renderTiming() { + const job = this.props.job; + const event = currentEvent(job); + switch (event.type) { + case JobStateType.CREATE: + return -; + case JobStateType.QUEUE: + case JobStateType.RUN: + return ; + default: + return ( + + + + ); + } + } + + render() { + const timing = this.props.showTiming ? this.renderTiming() : ''; + return ( + + {this.renderTag()} + {timing} + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/Main/index.tsx b/vite-app/src/apps/JobBrowser/components/Main/index.tsx new file mode 100644 index 000000000..937acd899 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/Main/index.tsx @@ -0,0 +1,114 @@ +import { Alert, Spin } from 'antd'; +import JobBrowserBFFClient from 'apps/JobBrowser/lib/JobBrowserBFFClient'; +import ErrorAlert from 'components/ErrorAlert'; +import { RouteProps } from 'components/Router2'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import * as React from 'react'; +import { Config } from 'types/config'; +import Main from './view'; + +export interface JobBrowserState { + isAdmin: boolean; +} + +export interface LoaderProps extends RouteProps { + config: Config; + authState: AuthenticationStateAuthenticated; + setTitle: (title: string) => void; +} + +type LoaderState = AsyncProcess; + +export default class Loader extends React.Component { + constructor(props: LoaderProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.props.setTitle('Job Browser'); + this.initialize(); + } + + async initialize() { + const jobBrowserBFF = new JobBrowserBFFClient({ + token: this.props.authState.authInfo.token, + url: this.props.config.services.ServiceWizard.url, + timeout: this.props.config.ui.constants.clientTimeout, + version: this.props.config.dynamicServices.JobBrowserBFF.version, + }); + + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + try { + const { is_admin } = await jobBrowserBFF.is_admin(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + isAdmin: is_admin, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + renderLoading() { + const message = ( +
    + Loading Job Browser ... +
    + ); + return ( + + ); + } + + renderError({ message }: SimpleError) { + return ; + } + + renderSuccess({ isAdmin }: JobBrowserState) { + return ( +
    + ); + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + return this.renderLoading(); + case AsyncProcessStatus.PENDING: + return this.renderLoading(); + case AsyncProcessStatus.ERROR: + return this.renderError(this.state.error); + case AsyncProcessStatus.SUCCESS: + return this.renderSuccess(this.state.value); + } + } +} diff --git a/vite-app/src/apps/JobBrowser/components/Main/style.css b/vite-app/src/apps/JobBrowser/components/Main/style.css new file mode 100644 index 000000000..e2f0d05cb --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/Main/style.css @@ -0,0 +1,47 @@ +.Main { + margin: 1rem; +} + +.FlexTabs { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.FlexTabs .ant-tabs-top-bar { + flex: 0 0 auto; +} + +.FlexTabs .ant-tabs-content { + flex: 1 1 0px; + overflow-y: auto; +} + +.Row { + flex: 0 0 auto; + display: flex; + flex-direction: row; +} + +.Row-fullheight { + flex: 1 1 0px; + display: flex; + flex-direction: row; +} + +.Row-scrollable { + min-height: 0; + min-width: 0; +} + +.Col-scrollable { + min-height: 0; + min-width: 0; +} + +.Col { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} diff --git a/vite-app/src/apps/JobBrowser/components/Main/view.tsx b/vite-app/src/apps/JobBrowser/components/Main/view.tsx new file mode 100644 index 000000000..b8c67a8c5 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/Main/view.tsx @@ -0,0 +1,168 @@ +import { faLockOpen } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import React, { CSSProperties, ReactNode } from 'react'; +import { Nav, Tab } from 'react-bootstrap'; +import { Config } from 'types/config'; +import AdminJobs from '../AdminJobs'; +import MyJobs from '../MyJobs'; +import PublicAppStats from '../PublicAppStats'; +import UserRunSummary from '../UserRunSummary'; +import './style.css'; + +export interface MainProps { + config: Config; + authState: AuthenticationStateAuthenticated; + isAdmin: boolean; + // params: MainParams; + // view: string; + tab?: string; + setTitle: (title: string) => void; + // setView: (view: string) => void; + // setParams: (params: MainParams) => void; +} + +interface MainState {} + +export default class Main extends React.Component { + defaultTabKey: string; + constructor(props: MainProps) { + super(props); + this.defaultTabKey = 'myJobs'; + } + + componentDidMount() { + this.props.setTitle('Job Browser'); + } + + renderTabs() { + const tabPaneStyle: CSSProperties = { + position: 'absolute', + top: '0', + right: '0', + bottom: '0', + left: '0', + display: 'flex', + flexDirection: 'column', + }; + const tabContentStyle: CSSProperties = { + flex: '1 1 0', + position: 'relative', + }; + return ( + +
    + +
    +
    + + + + + {((): ReactNode => { + if (!this.props.isAdmin) { + return; + } + return ( + + + + ); + })()} + + + + {((): ReactNode => { + if (!this.props.isAdmin) { + return; + } + return ( + + + + ); + })()} + +
    +
    + ); + } + + render() { + return ( +
    + {this.renderTabs()} +
    + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/Monitor.tsx b/vite-app/src/apps/JobBrowser/components/Monitor.tsx new file mode 100644 index 000000000..ea050f568 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/Monitor.tsx @@ -0,0 +1,184 @@ +import { Progress, Switch, Tooltip } from 'antd'; +import * as React from 'react'; +import { Poller } from '../lib/Poller'; +import PubSub, { PubSubProxy } from '../lib/PubSub'; + +const MONITORING_INTERVAL = 10000; +const MONITORING_FEEDBACK_STEPS = 100; +const WATCH_INTERVAL = 100; + +export interface MonitorProps { + defaultRunning: boolean; + pubsub: PubSub; + onPoll: () => void; +} + +export interface MonitorState { + /** Support for job monitoring */ + isMonitoring: boolean; + isPollingInitiated: boolean; + pollingStartedAt: number; + /** Monitoring progress */ + pollWaitProgress: number; + isPolling: boolean; + isOpen: boolean; +} + +export default class Monitor extends React.Component< + MonitorProps, + MonitorState +> { + monitoringTimer: number | null; + monitoringStatusTimer: number | null; + pollWatcherTimer: number | null; + searchListenerID: string | null; + pubsubProxy: PubSubProxy; + + poller: Poller; + + constructor(props: MonitorProps) { + super(props); + + this.monitoringTimer = null; + this.monitoringStatusTimer = null; + this.pollWatcherTimer = null; + this.searchListenerID = null; + this.pubsubProxy = new PubSubProxy(this.props.pubsub); + + this.poller = new Poller({ + onPoll: this.props.onPoll, + onProgress: this.onProgress.bind(this), + pubsub: this.props.pubsub, + pollInterval: MONITORING_INTERVAL, + progressSteps: MONITORING_FEEDBACK_STEPS, + watchInterval: WATCH_INTERVAL, + }); + + this.state = { + isMonitoring: false, + pollWaitProgress: 0, + isPollingInitiated: false, + pollingStartedAt: 0, + isPolling: false, + isOpen: this.props.defaultRunning, + }; + } + + onProgress(progress: number) { + this.setState({ + pollWaitProgress: progress, + }); + } + + componentDidMount() { + this.pubsubProxy.on('searching', (message: unknown) => { + const { is } = message as { is: boolean }; + if (is) { + this.setState({ + isPolling: true, + }); + } else { + this.setState({ + isPolling: false, + }); + } + }); + } + + componentWillUnmount() { + this.stopMonitoring(); + this.poller.stop(); + this.pubsubProxy.off(); + } + + componentDidUpdate() {} + + startMonitoring() { + this.setState({ + isMonitoring: true, + }); + this.poller.startPolling(); + } + + stopMonitoring() { + this.poller.stopPolling(); + this.setState({ + isMonitoring: false, + }); + } + + toggleMonitoring() { + if (this.state.isMonitoring) { + this.stopMonitoring(); + } else { + this.startMonitoring(); + } + } + + onToggleOpen(isOpen: boolean) { + this.setState({ isOpen }); + if (isOpen) { + this.startMonitoring(); + } else { + this.stopMonitoring(); + } + } + + render() { + let monitoringStatus; + const opener = ( + + ); + + if (this.state.isMonitoring) { + if (!this.state.isPolling) { + monitoringStatus = ( + + {' '} + + + ); + } else { + monitoringStatus = ( + + {' '} + + + ); + } + } + let title; + if (this.state.isMonitoring) { + title = `Polling is running, with an interval of ${MONITORING_INTERVAL}ms and ${MONITORING_FEEDBACK_STEPS} update steps.`; + } else { + title = 'Polling is currently stopped.'; + } + let monitor; + if (this.state.isOpen) { + monitor = {monitoringStatus}; + } + return ( + + {opener} {monitor} + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/MyJobs/MyJobsRequest.ts b/vite-app/src/apps/JobBrowser/components/MyJobs/MyJobsRequest.ts new file mode 100644 index 000000000..ff9722716 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/MyJobs/MyJobsRequest.ts @@ -0,0 +1,88 @@ +import { Job, JobsSearchExpression } from 'apps/JobBrowser/store'; +import { extractTimeRange, serviceJobToUIJob } from 'apps/JobBrowser/utils'; +import CancelableRequest, { Task } from '../../lib/CancelableRequest'; +import JobBrowserBFFClient, { + QueryJobsParams, +} from '../../lib/JobBrowserBFFClient'; + +interface MyJobsParam { + token: string; + searchExpression: JobsSearchExpression; + username: string; + serviceWizardURL: string; + timeout: number; + version: string; +} + +type MyJobsResult = { + jobs: Array; + foundCount: number; + totalCount: number; +}; + +export default class MyJobsRequest extends CancelableRequest< + MyJobsParam, + MyJobsResult +> { + request({ + token, + timeout, + searchExpression, + serviceWizardURL, + version, + }: MyJobsParam): Task { + const jobBrowserBFF = new JobBrowserBFFClient({ + token, + url: serviceWizardURL, + timeout, + version, + }); + + const [timeRangeStart, timeRangeEnd] = extractTimeRange( + searchExpression.timeRange, + ); + + const queryParams: QueryJobsParams = { + time_span: { + from: timeRangeStart, + to: timeRangeEnd, + }, // TODO: really handle sort + offset: searchExpression.offset, + limit: searchExpression.limit, + timeout, + filter: searchExpression.filter, + }; + + if (searchExpression.sort) { + switch (searchExpression.sort.field) { + case 'created': + queryParams.sort = [ + { + key: 'created', + direction: searchExpression.sort.direction, + }, + ]; + } + } + + const promise = jobBrowserBFF + .query_jobs(queryParams) + .then(({ jobs, found_count, total_count }) => { + return { + jobs: jobs.map((jobInfo) => { + return serviceJobToUIJob(jobInfo); + }), + foundCount: found_count, + totalCount: total_count, + }; + }); + + const task: Task = { + id: this.newID(), + promise, + isCanceled: false, + }; + this.pendingTasks.set(task.id, task); + return task; + } +} diff --git a/vite-app/src/apps/JobBrowser/components/MyJobs/index.tsx b/vite-app/src/apps/JobBrowser/components/MyJobs/index.tsx new file mode 100644 index 000000000..a15bee349 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/MyJobs/index.tsx @@ -0,0 +1,175 @@ +import { message } from 'antd'; +import { Job, JobsSearchExpression } from 'apps/JobBrowser/store'; +import { JobStateType } from 'apps/JobBrowser/types/jobState'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import React from 'react'; +import { Config } from 'types/config'; +import JobBrowserBFFClient from '../../lib/JobBrowserBFFClient'; +// import { JSONRPC20Exception } from '../../lib/comm/JSONRPC20/JSONRPC20'; +import { JSONRPC20Exception } from 'lib/kb_lib/comm/JSONRPC20/JSONRPC20'; +import { AsyncProcessState, DataSource } from '../Table'; +import MyJobsRequest from './MyJobsRequest'; +import View from './view'; + +export interface DataProps { + config: Config; + authState: AuthenticationStateAuthenticated; +} + +interface DataState { + dataSource: DataSource; +} + +const myJobsSearchRequests = new MyJobsRequest(); + +export default class Data extends React.Component { + constructor(props: DataProps) { + super(props); + this.state = { + dataSource: { + status: AsyncProcessState.NONE, + }, + }; + } + + async doSearch(searchExpression: JobsSearchExpression) { + if (this.state.dataSource.status === AsyncProcessState.SUCCESS) { + this.setState({ + dataSource: { + ...this.state.dataSource, + status: AsyncProcessState.REPROCESSING, + }, + }); + } else { + this.setState({ + dataSource: { + status: AsyncProcessState.PROCESSING, + }, + }); + } + + const task = myJobsSearchRequests.spawn({ + token: this.props.authState.authInfo.token, + username: this.props.authState.authInfo.account.user, + serviceWizardURL: this.props.config.services.ServiceWizard.url, + searchExpression, + version: this.props.config.dynamicServices.JobBrowserBFF.version, + timeout: this.props.config.ui.constants.clientTimeout, + }); + + try { + const { jobs, foundCount, totalCount } = await task.promise; + if (task.isCanceled) { + // just do nothing + return; + } + + myJobsSearchRequests.done(task); + + const { limit, offset } = searchExpression; + const page = Math.ceil((offset + limit) / limit); + const pageCount = Math.ceil(totalCount / limit); + + this.setState({ + dataSource: { + status: AsyncProcessState.SUCCESS, + data: jobs, + count: foundCount, + total: totalCount, + limit, + offset, + page, + pageCount, + }, + }); + } catch (ex) { + if (ex instanceof JSONRPC20Exception) { + console.error('error', ex.error); + this.setState({ + dataSource: { + status: AsyncProcessState.ERROR, + error: { + code: ex.error.code, + message: ex.error.message, + data: ex.error.data, + }, + }, + }); + } else { + this.setState({ + dataSource: { + status: AsyncProcessState.ERROR, + error: { + code: 0, + message: + ex instanceof Error + ? ex.message + : 'Unknown Error', + }, + }, + }); + } + } + } + + search(searchExpression: JobsSearchExpression) { + this.doSearch(searchExpression); + } + + cancelJob(jobId: string, timeout: number) { + // do it + const client = new JobBrowserBFFClient({ + url: this.props.config.services.ServiceWizard.url, + token: this.props.authState.authInfo.token, + timeout: this.props.config.ui.constants.clientTimeout, + version: this.props.config.dynamicServices.JobBrowserBFF.version, + }); + client + .cancel_job({ + job_id: jobId, + timeout, + admin: false, + }) + .then(() => { + const dataSource = this.state.dataSource; + message.success('Successfully canceled the job'); + if ( + this.state.dataSource.status === AsyncProcessState.SUCCESS + ) { + for (const datum of this.state.dataSource.data) { + if (datum.id === jobId) { + datum.eventHistory.push({ + at: new Date().getTime(), + type: JobStateType.TERMINATE, + code: 0, + }); + this.setState({ + dataSource, + }); + return; + } + } + } + }) + .catch((err) => { + console.error('error canceling job', err); + message.error('Error canceling job: ' + err.message); + }); + } + + refreshSearch() {} + + render() { + return ( + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/MyJobs/style.css b/vite-app/src/apps/JobBrowser/components/MyJobs/style.css new file mode 100644 index 000000000..8169042c7 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/MyJobs/style.css @@ -0,0 +1,403 @@ +.MyJobs { + min-height: 0; + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table { + table-layout: fixed; +} + +.MyJobs-tableCell, +.MyJobs-table td, +.MyJobs-table th { + max-width: 0; + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.MyJobs-table .ant-table-header-column { + /* max-width: 0; */ + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.MyJobs-filterArea { + padding: 6px; + margin: 0 20px 0 20px; + border: 1px solid rgba(150, 150, 150, 0.3); + box-shadow: 4px 4px 4px; + border-radius: 4px; + background-color: rgba(200, 200, 200, 0.95); +} + +.MyJobs-filterPanel { + position: absolute; + left: 0; + top: 0; + right: 0; + z-index: 1000; +} + +.ant-modal-wrap { + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper > .ant-spin-nested-loading { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-body { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table-pagination.ant-pagination { + flex: 0 0 auto; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + .ant-table-row { + height: 30px; +} + +.MyJobs .Table-row > .Table-cell:nth-child(1) { + flex: 0 0 4em; + align-items: center; +} + +.MyJobs .Table-row > .Table-cell:nth-child(2) { + flex: 1 1 0px; + min-width: 10em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(3) { + min-width: 10em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(4) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(5) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(6) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(7) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(8) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(9) { + flex: 0 0 4em; + align-items: center; +} + +.MyJobs .-controlBar { + margin: 10px; +} + +.ant-modal.FullScreenModal { + /* width: 80% !important; + top: 10% !important; + bottom: 10% !important; */ + flex: 1 1 0px; + display: flex; + flex-direction: column; + width: unset !important; + top: unset !important; + padding-bottom: 0; + margin: 5%; +} + +.ant-modal.FullScreenModal .ant-modal-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; + height: 90%; + top: unset; + min-height: 0; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-header { + flex: 0 0 auto; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-body { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-footer { + flex: 0 0 auto; +} + +.ant-tabs.FullHeightTabs { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ant-tabs.FullHeightTabs > .ant-tabs-content { + flex: 1 1 0px !important; + display: flex !important; + flex-direction: column !important; + min-height: 0; +} + +.ant-tabs.FullHeightTabs > .ant-tabs-content > .ant-tabs-tabpane { + flex: 1 1 0px !important; + display: flex !important; + flex-direction: column !important; + min-height: 0; +} + +/* flex table */ + +.FlexTable { + flex: 1 1 0px; + flex-basis: 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.FlexTable-header { + flex: 0 0 auto; + display: flex; + flex-direction: column; +} + +.FlexTable-row { + flex: 0 0 auto; + display: flex; + flex-direction: row; + /* padding: 4px; */ + /* margin: 4px; */ + border-bottom: 1px silver solid; +} + +.FlexTable-col { + flex: 0 0 auto; + /* border: 1px silver dashed; */ + padding: 4px; + overflow-wrap: break-word; + word-wrap: break-word; +} + +.FlexTable-col:last-child { + flex: 1 1 0px; +} + +.FlexTable-body { + flex: 1 1 0px; + overflow-y: auto; + display: flex; + flex-direction: column; + min-height: 0; +} + +/* .FlexTable-col:nth-child(1) { + flex: 0 0 4em; +} + +.FlexTable-col:nth-child(2) { + flex: 1 1 0px; + +} + +.FlexTable-body .Table-col:nth-child(2) { + font-family: monospace; + font-size: 90%; + white-space: pre-wrap +} */ + +.FullyCenteredBox { + flex: 1 1 0px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.ScrollingFlexTable.ant-table-wrapper { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper > .ant-spin-nested-loading { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-scroll { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-scroll + > .ant-table-header { + flex: 0 0 auto; +} + +/* */ +.PreciseTable { + table-layout: fixed; +} + +.PreciseTable-cell, +.PreciseTable td { + max-width: 0; + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.PreciseTable .ant-table-column-title { + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.NumericColumn { + text-align: right; + padding-right: 1em; +} + +.InfoTable { + display: flex; + flex-direction: column; +} + +.InfoTable-row { + display: flex; + flex-direction: row; + padding: 4px; +} + +.InfoTable-labelCol { + flex: 0 0 auto; + font-weight: bold; + color: rgba(150, 150, 150, 1); +} + +.InfoTable-dataCol { + flex: 1 1 0px; + text-align: left; +} diff --git a/vite-app/src/apps/JobBrowser/components/MyJobs/view.tsx b/vite-app/src/apps/JobBrowser/components/MyJobs/view.tsx new file mode 100644 index 000000000..366917536 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/MyJobs/view.tsx @@ -0,0 +1,965 @@ +/** + * A component for browsing through (search, filter, sort) jobs submitted by + * the current user. + */ + +import { + CloseOutlined, + InfoCircleOutlined, + SearchOutlined, +} from '@ant-design/icons'; +import { Button, Form, Modal, Popconfirm, Select, Switch, Tooltip } from 'antd'; +import { + Job, + JobContextType, + JobsSearchExpression, + SortSpec, + TimeRange, + TimeRangePresets, +} from 'apps/JobBrowser/store'; +import { JobEvent, JobStateType } from 'apps/JobBrowser/types/jobState'; +import UILink from 'components/UILink2'; +import { AuthenticationStatus, EuropaContext } from 'contexts/EuropaContext'; +import dayjs from 'dayjs'; +import { AsyncProcessStatus } from 'lib/AsyncProcess'; +import React from 'react'; +import { FilterSpec } from '../../lib/JobBrowserBFFClient'; +import PubSub from '../../lib/PubSub'; +import DatePicker from '../DatePicker'; +import FilterEditor from '../FilterEditor/controller'; +import JobDetail from '../JobDetail'; +import JobStatusBadge from '../JobStatusBadge'; +import Monitor from '../Monitor'; +import NarrativeLink from '../NarrativeLink'; +import NiceElapsedTime from '../NiceElapsedTime'; +import NiceRelativeTime from '../NiceRelativeTime'; +import Table2, { + AsyncProcessState, + Column, + DataSource, + TableConfig, +} from '../Table'; +import './style.css'; + +const CANCEL_TIMEOUT = 10000; + +/** + * This version of the job status defines the set of strings that may be used + * in the ui controls. + * + */ +// type JobStatusFilterKey = "queued" | "running" | "canceled" | "success" | "error"; + +/** + * Translates an array of job status filter keys, as provided by the ui job status + * filter checkboxes, to an array of job statuses suitable for passing to the job + * status search. + * + * @param filter - an array of job status filter keys + * + * @note Since the switch is over an enum, we don't have to worry about the default case + * + * @returns an array of job statuses + */ +// function jobStatusFilterOptionsToJobStatus(filter: Array): Array { +// let jobStatuses: Array = []; +// filter.forEach(status => { +// switch (status) { +// case "queued": +// jobStatuses.push(JobStatus.QUEUED); +// break; +// case "running": +// jobStatuses.push(JobStatus.RUNNING); +// break; +// case "canceled": +// jobStatuses.push(JobStatus.CANCELED_QUEUED); +// jobStatuses.push(JobStatus.CANCELED_RUNNING); +// break; +// case "success": +// jobStatuses.push(JobStatus.FINISHED); +// break; +// case "error": +// jobStatuses.push(JobStatus.ERRORED_QUEUED); +// jobStatuses.push(JobStatus.ERRORED_RUNNING); +// break; +// } +// }); +// return jobStatuses; +// } + +/** + * Semantic aliasing of for epoch time in milliseconds, as produced + * by Date.now(), new Date().getTime(), etc. + * + * @todo move to a common location + */ + +/** + * Props for the MyJobs component + */ +export interface MyJobsProps { + dataSource: DataSource; + + /** Triggers a redux action to search of the user's jobs according to the given search expression + * @remarks Since at present the service used to fetch the jobs can suffer performance issues, the + * default search action does not fetch search results each time (rather ??). + * @todo when job search is more performant, this function may be removed and redirected to the + * search function. + */ + search: (searchExpression: JobsSearchExpression) => void; + refreshSearch: () => void; + cancelJob: (jobID: string, timeout: number) => void; + narrativeMethodStoreURL: string; +} + +/** + * State for the MyJobs component + */ +interface MyJobsState { + /** Flag to show the date controls */ + showDates: boolean; + /** Contains the current selection of job statuses in the checkbox control */ + // currentJobStatusFilter: Array; + /** Contains the initial timestamp (ms epoch time) for time range */ + timeRange: TimeRange; + + isFilterOpen: boolean; + + selectedJob: Job | null; + currentSort: SortSpec | null; + // rowsPerPage: number; + + filter: FilterSpec; +} + +/** + * A View Component for browsing through the current user's jobs. + * + * @remarks + * This component is really just a tabular view into a user's jobs. It provides + * support for free text searching, filtering by job state, and date ranges. + * + */ +export default class MyJobs extends React.Component { + currentQuery?: string; + offset: number; + limit: number; + sorting: SortSpec; + currentPage: number; + // rowsPerPage: number; + + static defaultTimeRangePreset: TimeRangePresets = 'lastWeek'; + + pubsub: PubSub; + + constructor(props: MyJobsProps) { + super(props); + + this.currentQuery = ''; + this.pubsub = new PubSub(); + this.offset = 0; + this.limit = 1; + this.currentPage = 0; + this.sorting = { + field: 'created', + direction: 'descending', + }; + + this.state = { + showDates: false, + filter: { + status: [ + 'create', + 'queue', + 'run', + 'terminate', + 'complete', + 'error', + ], + }, + timeRange: { + kind: 'preset', + preset: MyJobs.defaultTimeRangePreset, + }, + isFilterOpen: false, + selectedJob: null, + currentSort: null, + // rowsPerPage: 1 + }; + } + + async componentDidMount() {} + + // onResize(rowsPerPage: number) { + // // It would be nice to rely upon the table component to trigger a + // // change even if we change the rows per page ... but we change the + // // rows per page via the table props, not by a trigger. + // // Perhaps by wrapping the table or subclassing it? + + // this.limit = rowsPerPage; + // this.offset = this.currentPage * rowsPerPage; + + // // This causes the table to rerender, but without triggering a + // // re-search; + // // this.setState({ + // // rowsPerPage + // // }); + + // // This triggers a fresh search. + // this.doSearch(false); + // } + + componentDidUpdate() { + if ( + this.props.dataSource.status === AsyncProcessState.PROCESSING || + this.props.dataSource.status === AsyncProcessState.REPROCESSING + ) { + this.pubsub.send('searching', { is: true }); + } else { + this.pubsub.send('searching', { is: false }); + } + } + + onChangeTimeRange(value: string) { + // TODO: should narrow the string value + if (value === 'customRange') { + // TODO: utilize dates from time range presets. + this.setState({ + showDates: true, + timeRange: { + kind: 'literal', + start: Date.now(), + end: Date.now(), + }, + }); + // nothing else to do. + return; + } else { + this.setState( + { + showDates: false, + timeRange: { + kind: 'preset', + preset: value as TimeRangePresets, + }, + }, + () => { + // Because this may obsolete the page. + // This is a simplification, for sure. + this.offset = 0; + this.doSearch(true); + }, + ); + } + } + + onChangeQuery(event: React.ChangeEvent) { + this.currentQuery = event.target.value; + } + + onSubmit() { + this.doSearch(true); + } + + onFirstPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page <= 1) { + return; + } + + // here we do it. + this.offset = 0; + + this.doSearch(false); + } + + onPreviousPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page <= 1) { + return; + } + + // here we do it. + this.offset = (dataSource.page - 2) * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onNextPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page >= dataSource.pageCount) { + return; + } + + // here we do it. + this.offset = dataSource.page * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onLastPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page >= dataSource.pageCount) { + return; + } + + // here we do it. + this.offset = (dataSource.pageCount - 1) * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onReset() { + this.offset = 0; + this.doSearch(true); + } + + doSearch(forceSearch: boolean) { + const searchExpression: JobsSearchExpression = { + query: this.currentQuery, + timeRange: this.state.timeRange, + filter: this.state.filter, + forceSearch, + sort: this.sorting, + offset: this.offset, + limit: this.limit, + }; + + // TODO: document wth is happening here. + this.pubsub.send('search', { is: true }); + + this.props.search(searchExpression); + return false; + } + + onRangeChange(range: [dayjs.Dayjs | null, dayjs.Dayjs | null] | null) { + if (!range) { + return; + } + + const [fromDate, toDate] = range; + + const existingTimeRange = this.state.timeRange; + let timeRange: TimeRange; + switch (existingTimeRange.kind) { + case 'preset': + timeRange = { + kind: 'literal', + start: fromDate ? fromDate.valueOf() : 0, + end: toDate ? toDate.valueOf() : Infinity, + }; + break; + case 'literal': + timeRange = { + kind: 'literal', + start: fromDate ? fromDate.valueOf() : 0, + end: toDate ? toDate.valueOf() : Infinity, + }; + break; + default: + return; + } + + this.setState({ + timeRange, + }); + } + + renderSearchInput() { + let dateControls; + if (this.state.showDates) { + const timeRange = this.state.timeRange; + if (timeRange.kind === 'literal') { + dateControls = ( + + + + + + ); + } + } + return ( +
    + + + + {dateControls} + + + + + ); + const title = ( + + Detail for Job{' '} + + {this.state.selectedJob.id} + + + ); + return ( + + + {(value) => { + if ( + value === null || + value.status !== AsyncProcessStatus.SUCCESS + ) { + return; + } + if ( + value.value.authState.status !== + AuthenticationStatus.AUTHENTICATED + ) { + return; + } + + const { + config, + authState: { + authInfo: { token }, + }, + } = value.value; + + return ( + + ); + }} + + + ); + } + + renderView() { + return ( + +
    {this.renderControlBar()}
    + {this.renderJobsTable()} + {this.renderJobDetail()} +
    + ); + } + + render() { + return ( +
    + {this.renderView()} +
    + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/NarrativeLink.tsx b/vite-app/src/apps/JobBrowser/components/NarrativeLink.tsx new file mode 100644 index 000000000..1626f6a45 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/NarrativeLink.tsx @@ -0,0 +1,20 @@ +import UILink from 'components/UILink2'; +import { Component, PropsWithChildren } from 'react'; + +export interface NarrativeLinkProps extends PropsWithChildren { + narrativeID: number; +} + +export default class NarrativeLink extends Component { + render() { + return ( + + {this.props.children} + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/NiceElapsedTime.tsx b/vite-app/src/apps/JobBrowser/components/NiceElapsedTime.tsx new file mode 100644 index 000000000..3c8e1fb0a --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/NiceElapsedTime.tsx @@ -0,0 +1,95 @@ +import { Tooltip } from 'antd'; +import * as React from 'react'; +import { niceElapsed } from '../lib/time'; + +const SECOND = 1000; +// const MINUTE = 60 * SECOND; +// const HOUR = 60 * MINUTE; +// const DAY = 24 * HOUR; +const CLOCK_INTERVAL_SECOND = SECOND / 4; +// const CLOCK_INTERVAL_MINUTE = MINUTE / 4; +// const CLOCK_INTERVAL_HOUR = HOUR / 4; + +export interface NiceElapsedTimeProps { + from: number; + to?: number; + precision?: number; + showTooltip?: boolean; + tooltipPrefix?: string; + useClock?: boolean; +} + +interface NiceElapsedTimeState { + clockTime: number; +} + +export default class NiceElapsedTime extends React.Component< + NiceElapsedTimeProps, + NiceElapsedTimeState +> { + clockTimer: number | null; + + constructor(props: NiceElapsedTimeProps) { + super(props); + this.clockTimer = null; + this.state = { + clockTime: Date.now(), + }; + } + + startClock() { + this.clockTimer = window.setInterval(() => { + this.setState({ + clockTime: Date.now(), + }); + }, CLOCK_INTERVAL_SECOND); + } + + stopClock() { + if (this.clockTimer) { + window.clearInterval(this.clockTimer); + } + } + + componentDidMount() { + if (!this.props.to && this.props.useClock) { + this.startClock(); + } + } + + componentWillUnmount() { + this.stopClock(); + } + render() { + let elapsed; + if (this.props.to) { + elapsed = this.props.to - this.props.from; + } else { + elapsed = this.state.clockTime - this.props.from; + } + const { label: content } = niceElapsed(elapsed, {}); + if (this.props.showTooltip === false) { + return {content}; + } + + let tooltip; + if (this.props.tooltipPrefix) { + tooltip = ( + + {this.props.tooltipPrefix} + {content} + + ); + } else { + tooltip = {content}; + } + const { label: tooltipContent } = niceElapsed(elapsed, { + precision: this.props.precision, + }); + return ( + + {tooltipContent} + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/NiceRelativeTime.tsx b/vite-app/src/apps/JobBrowser/components/NiceRelativeTime.tsx new file mode 100644 index 000000000..6f3732101 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/NiceRelativeTime.tsx @@ -0,0 +1,136 @@ +import * as React from 'react'; + +import { Tooltip } from 'antd'; +import { niceRelativeTime } from '../lib/time'; + +export interface NiceRelativeTimeProps { + time: Date; + showTooltip?: boolean; + tooltipPrefix?: string; + absoluteAfter?: number; +} + +interface NiceRelativeTimeState { + now: Date; +} + +// dynamic intervals, based on the range of elapsed time +// TODO: using intervals we should actually set the interval to +// trigger based on the datetime to display. +const intervals = [ + // below 1 minute, every 1/2 sec + [60 * 1000, 500], + // between 1 minute and 1 hour, every 30 seconds + [60 * 60 * 1000, 30 * 1000], + // between 1 hour and 1 day, every 30 minutes + [60 * 60 * 24 * 1000, 60 * 1000 * 30], + // over 1 day, once per day + [Infinity, 60 * 60 * 24 * 1000], +]; + +export default class NiceRelativeTime extends React.Component< + NiceRelativeTimeProps, + NiceRelativeTimeState +> { + nowTimer: number | null; + interval: number; + constructor(props: NiceRelativeTimeProps) { + super(props); + + this.nowTimer = null; + + this.state = { + now: new Date(), + }; + + this.interval = this.calcInterval(); + } + + calcInterval(): number { + const elapsed = this.state.now.getTime() - this.props.time.getTime(); + for (const [upto, interval] of intervals) { + if (elapsed < upto) { + return interval; + } + } + console.error('hmm again', elapsed, intervals); + throw new Error('did not find interval'); + } + + handleInterval() { + const now = new Date(); + this.setState({ now }, () => { + const interval = this.calcInterval(); + if (this.interval !== interval) { + this.interval = interval; + this.startIntervalTimer(); + } + }); + } + + startIntervalTimer() { + if (this.nowTimer) { + window.clearInterval(this.nowTimer); + } + this.nowTimer = window.setInterval(() => { + this.handleInterval(); + }, this.interval); + } + + componentDidMount() { + this.startIntervalTimer(); + } + + componentWillUnmount() { + if (this.nowTimer) { + window.clearInterval(this.nowTimer); + } + } + + render() { + if (this.props.showTooltip === false) { + return ( + + {niceRelativeTime(this.props.time, { + absoluteAfter: 30, + now: this.state.now, + })} + + ); + } + + const fullDate = ( + + {Intl.DateTimeFormat('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZoneName: 'short', + }).format(this.props.time)} + + ); + let tooltip; + if (this.props.tooltipPrefix) { + tooltip = ( + + {this.props.tooltipPrefix} + {fullDate} + + ); + } else { + tooltip = fullDate; + } + return ( + + + {niceRelativeTime(this.props.time, { + absoluteAfter: this.props.absoluteAfter || 30, + now: this.state.now, + })} + + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/PublicAppStats/index.tsx b/vite-app/src/apps/JobBrowser/components/PublicAppStats/index.tsx new file mode 100644 index 000000000..bc59ea2c7 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/PublicAppStats/index.tsx @@ -0,0 +1,195 @@ +import { PublicAppStatsQuery } from 'apps/JobBrowser/store/PublicAppStats'; +import { AppStat } from 'apps/JobBrowser/store/base'; +import { calcAverage, calcRate } from 'apps/JobBrowser/utils'; +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import CatalogClient from 'lib/kb_lib/comm/coreServices/Catalog'; +import React from 'react'; +import { Config } from 'types/config'; +import PublicAppStats from './view'; + +export interface ControllerProps { + config: Config; + auth: AuthenticationStateAuthenticated; +} + +export interface Filtered { + show: boolean; + value: T; +} + +export interface PublicAppStatsState { + stats: Array>; +} + +export type ControllerState = AsyncProcess; + +export default class Controller extends React.Component< + ControllerProps, + ControllerState +> { + constructor(props: ControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.initialize(); + } + + async initialize() { + // Start off by getting everything. + // Note that this was optimistic, in that I had hoped that ee2 would eventually + // support fully search semantics (offset, limit, sort, query), but for now I + // believe we still just have to get everything and perform it all client-side. + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + try { + const stats = await this.loadInitialData(); + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + stats, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + async loadInitialData() { + const catalogClient = new CatalogClient({ + token: this.props.auth.authInfo.token, + url: this.props.config.services.Catalog.url, + timeout: this.props.config.ui.constants.clientTimeout, + }); + + const rawStats = await catalogClient.get_exec_aggr_stats({}); + return rawStats.map>((stat) => { + const [moduleId, functionId] = stat.full_app_id.split('/'); + if (!moduleId || !functionId) { + console.warn('bad app!', stat); + } + const successRate = calcRate( + stat.number_of_calls - stat.number_of_errors, + stat.number_of_calls, + ); + const averageRunTime = calcAverage( + stat.total_exec_time, + stat.number_of_calls, + ); + const averageQueueTime = calcAverage( + stat.total_queue_time, + stat.number_of_calls, + ); + return { + show: true, + value: { + appId: stat.full_app_id, + moduleId, + functionId: functionId || '', + moduleTitle: moduleId, + functionTitle: functionId || '', + runCount: stat.number_of_calls, + errorCount: stat.number_of_errors, + successRate, + averageRunTime, + averageQueueTime, + totalRunTime: stat.total_queue_time, + }, + }; + }); + } + + async search(query: PublicAppStatsQuery) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + try { + const terms = query.query.split(/\s+/); + + const expression = terms.map((term) => { + return new RegExp(term, 'i'); + }); + + const stats = this.state.value.stats.map(({ value }) => { + const show = + expression.length === 0 || + expression.every((term) => { + return ( + term.test(value.moduleTitle) || + term.test(value.moduleId) || + term.test(value.functionTitle) || + term.test(value.functionId) + ); + }); + return { show, value }; + }); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + stats, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + renderLoading() { + return ; + } + + onSearch(query: PublicAppStatsQuery): void { + this.search(query); + } + + renderSuccess({ stats }: PublicAppStatsState) { + const filteredStats = stats + .filter(({ show }) => { + return show; + }) + .map(({ value }) => { + return value; + }); + return ( + + ); + } + + renderError(error: SimpleError) { + return ; + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return this.renderLoading(); + case AsyncProcessStatus.SUCCESS: + return this.renderSuccess(this.state.value); + case AsyncProcessStatus.ERROR: + return this.renderError(this.state.error); + } + } +} diff --git a/vite-app/src/apps/JobBrowser/components/PublicAppStats/style.css b/vite-app/src/apps/JobBrowser/components/PublicAppStats/style.css new file mode 100644 index 000000000..ab391d346 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/PublicAppStats/style.css @@ -0,0 +1,7 @@ +.PublicAppStats { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; + margin-top: 1rem; +} diff --git a/vite-app/src/apps/JobBrowser/components/PublicAppStats/view.tsx b/vite-app/src/apps/JobBrowser/components/PublicAppStats/view.tsx new file mode 100644 index 000000000..2455e9dbc --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/PublicAppStats/view.tsx @@ -0,0 +1,293 @@ +import { SearchOutlined } from '@ant-design/icons'; +import { Button, Form, Input, Progress, Spin, Table, Tooltip } from 'antd'; +import { PublicAppStatsQuery } from 'apps/JobBrowser/store/PublicAppStats'; +import { AppStat } from 'apps/JobBrowser/store/base'; +import NiceTimeDuration from 'components/NiceTimeDuration'; +import UILink from 'components/UILink2'; +import React from 'react'; +import './style.css'; + +export function nullableNumberCompare( + a: number | null, + b: number | null, +): number { + if (a === null) { + if (blur === null) { + return 0; + } else { + return -1; + } + } else { + if (b === null) { + return 1; + } else { + return a - b; + } + } +} + +export interface PublicAppStatsProps { + stats: Array; + // searchState: SearchState; + // appStats: Array; + onSearch: (query: PublicAppStatsQuery) => void; +} + +interface PublicAppStatsState { + appStats: Array; +} + +export default class PublicAppStats extends React.Component< + PublicAppStatsProps, + PublicAppStatsState +> { + currentQuery: string; + constructor(props: PublicAppStatsProps) { + super(props); + this.currentQuery = ''; + } + // componentDidMount() { + // this.props.onSearch({ + // query: this.currentQuery + // }); + // } + onSubmitSearch() { + // event.preventDefault(); + this.props.onSearch({ + query: this.currentQuery, + }); + } + + onChangeQuery(event: React.ChangeEvent) { + this.currentQuery = event.target.value; + } + + renderControlBar() { + // TODO: refactor - the clear does not resend the query. + return ( +
    + + + + + + +
    + } + /> + {this.renderErrorModal(dataSource)} + + ); + } + + renderErrorModal(dataSource: DataSourceError) { + const description = ( +
    +
    Code: {dataSource.error.code}
    +
    Message: {dataSource.error.message}
    +
    Data:
    +
    + {dataSource.error.data && + this.renderJSON(dataSource.error.data)} +
    +
    + ); + return ( + { + this.setState({ + showError: false, + }); + }} + style={{ + maxWidth: '50em', + top: '20px', + bottom: '20px', + flex: '1 1 0px', + display: 'flex', + flexDirection: 'column', + }} + width="50em" + bodyStyle={{ + flex: '1 1 0px', + display: 'flex', + flexDirection: 'column', + }} + footer={[ + , + , + ]} + > + {description} + + ); + } + + /* + + */ + + renderLoading() { + return ( + + + + ); + } + + renderBodyOverlay() { + switch (this.props.dataSource.status) { + case AsyncProcessState.NONE: + case AsyncProcessState.PROCESSING: + case AsyncProcessState.REPROCESSING: + return ( +
    +
    + + {this.props.loadingPhrase || 'Loading...'} +
    +
    + ); + case AsyncProcessState.SUCCESS: + case AsyncProcessState.ERROR: + } + } + + renderBody() { + const content = ((): ReactNode => { + switch (this.props.dataSource.status) { + case AsyncProcessState.NONE: + case AsyncProcessState.PROCESSING: + return; + case AsyncProcessState.REPROCESSING: + return this.renderTableRows(this.props.dataSource); + case AsyncProcessState.SUCCESS: + return this.renderTableRows(this.props.dataSource); + case AsyncProcessState.ERROR: + return this.renderError(this.props.dataSource); + } + })(); + + return ( +
    + {this.renderBodyOverlay()} + {content} +
    + ); + } + + renderNav() { + if (this.state.status === TableStatus.OK) { + switch (this.props.dataSource.status) { + case AsyncProcessState.NONE: + return ( + + ); + case AsyncProcessState.PROCESSING: + return ( + + ); + case AsyncProcessState.REPROCESSING: + case AsyncProcessState.SUCCESS: + return ( + + ); + case AsyncProcessState.ERROR: + return ( + + ); + } + } else { + return ( + + ); + } + } + + render() { + return ( +
    + {this.renderHeader()} + {this.renderBody()} + {this.renderNav()} +
    + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/UILink.xtsx b/vite-app/src/apps/JobBrowser/components/UILink.xtsx new file mode 100644 index 000000000..0de9c6518 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UILink.xtsx @@ -0,0 +1,26 @@ +import React from 'react'; + +export interface UILinkProps { + path: string; + openIn: 'same-window' | 'new-tab'; +} + +interface UILinkState { + +} + +export default class UILink extends React.Component { + render() { + const href = `/#${this.props.path}`; + switch (this.props.openIn) { + case 'same-window': + return + {this.props.children} + ; + case 'new-tab': + return + {this.props.children} + ; + } + } +} \ No newline at end of file diff --git a/vite-app/src/apps/JobBrowser/components/UserJobs/MyJobsRequest.ts b/vite-app/src/apps/JobBrowser/components/UserJobs/MyJobsRequest.ts new file mode 100644 index 000000000..ff9722716 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserJobs/MyJobsRequest.ts @@ -0,0 +1,88 @@ +import { Job, JobsSearchExpression } from 'apps/JobBrowser/store'; +import { extractTimeRange, serviceJobToUIJob } from 'apps/JobBrowser/utils'; +import CancelableRequest, { Task } from '../../lib/CancelableRequest'; +import JobBrowserBFFClient, { + QueryJobsParams, +} from '../../lib/JobBrowserBFFClient'; + +interface MyJobsParam { + token: string; + searchExpression: JobsSearchExpression; + username: string; + serviceWizardURL: string; + timeout: number; + version: string; +} + +type MyJobsResult = { + jobs: Array; + foundCount: number; + totalCount: number; +}; + +export default class MyJobsRequest extends CancelableRequest< + MyJobsParam, + MyJobsResult +> { + request({ + token, + timeout, + searchExpression, + serviceWizardURL, + version, + }: MyJobsParam): Task { + const jobBrowserBFF = new JobBrowserBFFClient({ + token, + url: serviceWizardURL, + timeout, + version, + }); + + const [timeRangeStart, timeRangeEnd] = extractTimeRange( + searchExpression.timeRange, + ); + + const queryParams: QueryJobsParams = { + time_span: { + from: timeRangeStart, + to: timeRangeEnd, + }, // TODO: really handle sort + offset: searchExpression.offset, + limit: searchExpression.limit, + timeout, + filter: searchExpression.filter, + }; + + if (searchExpression.sort) { + switch (searchExpression.sort.field) { + case 'created': + queryParams.sort = [ + { + key: 'created', + direction: searchExpression.sort.direction, + }, + ]; + } + } + + const promise = jobBrowserBFF + .query_jobs(queryParams) + .then(({ jobs, found_count, total_count }) => { + return { + jobs: jobs.map((jobInfo) => { + return serviceJobToUIJob(jobInfo); + }), + foundCount: found_count, + totalCount: total_count, + }; + }); + + const task: Task = { + id: this.newID(), + promise, + isCanceled: false, + }; + this.pendingTasks.set(task.id, task); + return task; + } +} diff --git a/vite-app/src/apps/JobBrowser/components/UserJobs/index.tsx b/vite-app/src/apps/JobBrowser/components/UserJobs/index.tsx new file mode 100644 index 000000000..762d5dcaa --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserJobs/index.tsx @@ -0,0 +1,187 @@ +import { message } from 'antd'; +import React from 'react'; +import View from './view'; + +// import { Job, JobsSearchExpression } from '../../redux/store'; +import JobBrowserBFFClient from '../../lib/JobBrowserBFFClient'; +import { AsyncProcessState, DataSource } from '../Table'; +import MyJobsRequest from './MyJobsRequest'; +// import { JobStateType } from '../../redux/types/jobState'; +// import { SERVICE_TIMEOUT } from '../../constants'; +import { Job, JobsSearchExpression } from 'apps/JobBrowser/store'; +import { JobStateType } from 'apps/JobBrowser/types/jobState'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { JSONRPC20Exception } from 'lib/kb_lib/comm/JSONRPC20/JSONRPC20'; +import { Config } from 'types/config'; +// import { JSONRPC20Exception } from '../../lib/comm/JSONRPC20/JSONRPC20'; +// import { DynamicServiceConfig } from '@kbase/ui-components/lib/redux/integration/store'; + +export interface DataProps { + config: Config; + authState: AuthenticationStateAuthenticated; + // token: string; + // username: string; + // serviceWizardURL: string; + // narrativeMethodStoreURL: string; + // jobBrowserBFFConfig: DynamicServiceConfig; +} + +interface DataState { + dataSource: DataSource; +} + +const myJobsSearchRequests = new MyJobsRequest(); + +export default class Data extends React.Component { + searchExpression: JobsSearchExpression | null; + constructor(props: DataProps) { + super(props); + this.searchExpression = null; + this.state = { + dataSource: { + status: AsyncProcessState.NONE, + }, + }; + } + async doSearch(searchExpression: JobsSearchExpression) { + if (this.state.dataSource.status === AsyncProcessState.SUCCESS) { + this.setState({ + dataSource: { + ...this.state.dataSource, + status: AsyncProcessState.REPROCESSING, + }, + }); + } else { + this.setState({ + dataSource: { + status: AsyncProcessState.PROCESSING, + }, + }); + } + + const task = myJobsSearchRequests.spawn({ + token: this.props.authState.authInfo.token, + username: this.props.authState.authInfo.account.user, + serviceWizardURL: this.props.config.services.ServiceWizard.url, + searchExpression, + version: this.props.config.dynamicServices.JobBrowserBFF.version, + timeout: this.props.config.ui.constants.clientTimeout, + }); + + try { + const { jobs, foundCount, totalCount } = await task.promise; + if (task.isCanceled) { + // just do nothing + return; + } + + myJobsSearchRequests.done(task); + + const { limit, offset } = searchExpression; + const page = Math.ceil((offset + limit) / limit); + const pageCount = Math.ceil(totalCount / limit); + + this.setState({ + dataSource: { + status: AsyncProcessState.SUCCESS, + data: jobs, + count: foundCount, + total: totalCount, + limit, + offset, + page, + pageCount, + }, + }); + } catch (ex) { + if (ex instanceof JSONRPC20Exception) { + // console.error('error', ex.error); + + this.setState({ + dataSource: { + status: AsyncProcessState.ERROR, + error: { + code: ex.error.code, + message: ex.error.message, + data: ex.error.data, + }, + }, + }); + } else { + this.setState({ + dataSource: { + status: AsyncProcessState.ERROR, + error: { + code: 0, + message: + ex instanceof Error + ? ex.message + : 'Unknown Error', + }, + }, + }); + } + } + } + + search(searchExpression: JobsSearchExpression) { + this.searchExpression = searchExpression; + this.doSearch(searchExpression); + } + + cancelJob(jobId: string, timeout: number) { + // do it + const client = new JobBrowserBFFClient({ + url: this.props.config.services.ServiceWizard.url, + token: this.props.authState.authInfo.token, + timeout: this.props.config.ui.constants.clientTimeout, + version: this.props.config.dynamicServices.JobBrowserBFF.version, + }); + client + .cancel_job({ + job_id: jobId, + timeout, + admin: false, + }) + .then(() => { + const dataSource = this.state.dataSource; + message.success('Successfully canceled the job'); + if ( + this.state.dataSource.status === AsyncProcessState.SUCCESS + ) { + for (const datum of this.state.dataSource.data) { + if (datum.id === jobId) { + datum.eventHistory.push({ + at: new Date().getTime(), + type: JobStateType.TERMINATE, + code: 0, + }); + this.setState({ + dataSource, + }); + return; + } + } + } + }) + .catch((err) => { + console.error('error canceling job', err); + message.error('Error canceling job: ' + err.message); + }); + } + + refreshSearch() {} + render() { + return ( + + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/UserJobs/index.xtsx b/vite-app/src/apps/JobBrowser/components/UserJobs/index.xtsx new file mode 100644 index 000000000..301cf6508 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserJobs/index.xtsx @@ -0,0 +1,61 @@ +import { Dispatch, Action } from 'redux'; +import { connect } from 'react-redux'; +import Data from './data'; + +import { + StoreState +} from '../../redux/store'; +import { DynamicServiceConfig } from '@kbase/ui-components/lib/redux/integration/store'; + +export interface OwnProps { +} + +interface StateProps { + token: string; + username: string; + serviceWizardURL: string; + narrativeMethodStoreURL: string; + jobBrowserBFFConfig: DynamicServiceConfig; +} + +interface DispatchProps { +} + +function mapStateToProps(state: StoreState, props: OwnProps): StateProps { + const { + auth: { userAuthorization }, + app: { + config: { + services: { + ServiceWizard: { url: serviceWizardURL }, + NarrativeMethodStore: { url: narrativeMethodStoreURL } + }, + dynamicServices: { + JobBrowserBFF: jobBrowserBFFConfig + } + } + } + } = state; + + if (!userAuthorization) { + throw new Error('Not authorized!'); + } + + const { token, username } = userAuthorization; + + return { + token, username, + serviceWizardURL, + narrativeMethodStoreURL, + jobBrowserBFFConfig + }; +} + +function mapDispatchToProps(dispatch: Dispatch, ownProps: OwnProps): DispatchProps { + return {}; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Data); diff --git a/vite-app/src/apps/JobBrowser/components/UserJobs/style.css b/vite-app/src/apps/JobBrowser/components/UserJobs/style.css new file mode 100644 index 000000000..8169042c7 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserJobs/style.css @@ -0,0 +1,403 @@ +.MyJobs { + min-height: 0; + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table { + table-layout: fixed; +} + +.MyJobs-tableCell, +.MyJobs-table td, +.MyJobs-table th { + max-width: 0; + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.MyJobs-table .ant-table-header-column { + /* max-width: 0; */ + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.MyJobs-filterArea { + padding: 6px; + margin: 0 20px 0 20px; + border: 1px solid rgba(150, 150, 150, 0.3); + box-shadow: 4px 4px 4px; + border-radius: 4px; + background-color: rgba(200, 200, 200, 0.95); +} + +.MyJobs-filterPanel { + position: absolute; + left: 0; + top: 0; + right: 0; + z-index: 1000; +} + +.ant-modal-wrap { + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper > .ant-spin-nested-loading { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-body { + flex: 1 1 0px; + display: flex; + flex-direction: column; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table-pagination.ant-pagination { + flex: 0 0 auto; +} + +.MyJobs-table.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + .ant-table-row { + height: 30px; +} + +.MyJobs .Table-row > .Table-cell:nth-child(1) { + flex: 0 0 4em; + align-items: center; +} + +.MyJobs .Table-row > .Table-cell:nth-child(2) { + flex: 1 1 0px; + min-width: 10em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(3) { + min-width: 10em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(4) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(5) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(6) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(7) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(8) { + flex: 0 0 8em; +} + +.MyJobs .Table-row > .Table-cell:nth-child(9) { + flex: 0 0 4em; + align-items: center; +} + +.MyJobs .-controlBar { + margin: 10px; +} + +.ant-modal.FullScreenModal { + /* width: 80% !important; + top: 10% !important; + bottom: 10% !important; */ + flex: 1 1 0px; + display: flex; + flex-direction: column; + width: unset !important; + top: unset !important; + padding-bottom: 0; + margin: 5%; +} + +.ant-modal.FullScreenModal .ant-modal-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; + height: 90%; + top: unset; + min-height: 0; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-header { + flex: 0 0 auto; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-body { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ant-modal.FullScreenModal .ant-modal-content .ant-modal-footer { + flex: 0 0 auto; +} + +.ant-tabs.FullHeightTabs { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ant-tabs.FullHeightTabs > .ant-tabs-content { + flex: 1 1 0px !important; + display: flex !important; + flex-direction: column !important; + min-height: 0; +} + +.ant-tabs.FullHeightTabs > .ant-tabs-content > .ant-tabs-tabpane { + flex: 1 1 0px !important; + display: flex !important; + flex-direction: column !important; + min-height: 0; +} + +/* flex table */ + +.FlexTable { + flex: 1 1 0px; + flex-basis: 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.FlexTable-header { + flex: 0 0 auto; + display: flex; + flex-direction: column; +} + +.FlexTable-row { + flex: 0 0 auto; + display: flex; + flex-direction: row; + /* padding: 4px; */ + /* margin: 4px; */ + border-bottom: 1px silver solid; +} + +.FlexTable-col { + flex: 0 0 auto; + /* border: 1px silver dashed; */ + padding: 4px; + overflow-wrap: break-word; + word-wrap: break-word; +} + +.FlexTable-col:last-child { + flex: 1 1 0px; +} + +.FlexTable-body { + flex: 1 1 0px; + overflow-y: auto; + display: flex; + flex-direction: column; + min-height: 0; +} + +/* .FlexTable-col:nth-child(1) { + flex: 0 0 4em; +} + +.FlexTable-col:nth-child(2) { + flex: 1 1 0px; + +} + +.FlexTable-body .Table-col:nth-child(2) { + font-family: monospace; + font-size: 90%; + white-space: pre-wrap +} */ + +.FullyCenteredBox { + flex: 1 1 0px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.ScrollingFlexTable.ant-table-wrapper { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper > .ant-spin-nested-loading { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-scroll { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; +} + +.ScrollingFlexTable.ant-table-wrapper + > .ant-spin-nested-loading + > .ant-spin-container + > .ant-table + > .ant-table-content + > .ant-table-scroll + > .ant-table-header { + flex: 0 0 auto; +} + +/* */ +.PreciseTable { + table-layout: fixed; +} + +.PreciseTable-cell, +.PreciseTable td { + max-width: 0; + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.PreciseTable .ant-table-column-title { + overflow-x: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.NumericColumn { + text-align: right; + padding-right: 1em; +} + +.InfoTable { + display: flex; + flex-direction: column; +} + +.InfoTable-row { + display: flex; + flex-direction: row; + padding: 4px; +} + +.InfoTable-labelCol { + flex: 0 0 auto; + font-weight: bold; + color: rgba(150, 150, 150, 1); +} + +.InfoTable-dataCol { + flex: 1 1 0px; + text-align: left; +} diff --git a/vite-app/src/apps/JobBrowser/components/UserJobs/view.tsx b/vite-app/src/apps/JobBrowser/components/UserJobs/view.tsx new file mode 100644 index 000000000..d5bb70e6f --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserJobs/view.tsx @@ -0,0 +1,989 @@ +/** + * A component for browsing through (search, filter, sort) jobs submitted by + * the current user. + */ + +/** imports */ +// 3rd party imports +import { Button, Form, Modal, Popconfirm, Select, Switch, Tooltip } from 'antd'; +import React from 'react'; + +// import moment, { Moment } from 'moment'; +import dayjs from 'dayjs'; + +// project imports + +import JobDetail from '../JobDetail'; + +// kbase imports (or should be kbase imports) +// import { NiceRelativeTime, NiceElapsedTime } from '@kbase/ui-components'; +import JobStatusBadge from '../JobStatusBadge'; + +// file imports +import { + CloseOutlined, + InfoCircleOutlined, + SearchOutlined, +} from '@ant-design/icons'; +import { + Job, + JobContextType, + JobsSearchExpression, + SortSpec, + TimeRange, + TimeRangePresets, +} from 'apps/JobBrowser/store'; +import { JobEvent, JobStateType } from 'apps/JobBrowser/types/jobState'; +import { FilterSpec } from '../../lib/JobBrowserBFFClient'; +import PubSub from '../../lib/PubSub'; +import DatePicker from '../DatePicker'; +// import FilterEditor, { JobFilter } from "../FilterEditor"; +import UILink from 'components/UILink2'; +import { AuthenticationStatus, EuropaContext } from 'contexts/EuropaContext'; +import { AsyncProcessStatus } from 'lib/AsyncProcess'; +import Monitor from '../Monitor'; +import NarrativeLink from '../NarrativeLink'; +import NiceElapsedTime from '../NiceElapsedTime'; +import NiceRelativeTime from '../NiceRelativeTime'; +import Table2, { + AsyncProcessState, + Column, + DataSource, + TableConfig, +} from '../Table'; +import './style.css'; + +const CANCEL_TIMEOUT = 10000; + +/** + * This version of the job status defines the set of strings that may be used + * in the ui controls. + * + */ +// type JobStatusFilterKey = "queued" | "running" | "canceled" | "success" | "error"; + +/** + * Translates an array of job status filter keys, as provided by the ui job status + * filter checkboxes, to an array of job statuses suitable for passing to the job + * status search. + * + * @param filter - an array of job status filter keys + * + * @note Since the switch is over an enum, we don't have to worry about the default case + * + * @returns an array of job statuses + */ +// function jobStatusFilterOptionsToJobStatus(filter: Array): Array { +// let jobStatuses: Array = []; +// filter.forEach(status => { +// switch (status) { +// case "queued": +// jobStatuses.push(JobStatus.QUEUED); +// break; +// case "running": +// jobStatuses.push(JobStatus.RUNNING); +// break; +// case "canceled": +// jobStatuses.push(JobStatus.CANCELED_QUEUED); +// jobStatuses.push(JobStatus.CANCELED_RUNNING); +// break; +// case "success": +// jobStatuses.push(JobStatus.FINISHED); +// break; +// case "error": +// jobStatuses.push(JobStatus.ERRORED_QUEUED); +// jobStatuses.push(JobStatus.ERRORED_RUNNING); +// break; +// } +// }); +// return jobStatuses; +// } + +/** + * Semantic aliasing of for epoch time in milliseconds, as produced + * by Date.now(), new Date().getTime(), etc. + * + * @todo move to a common location + */ + +/** + * Props for the MyJobs component + */ +export interface MyJobsProps { + dataSource: DataSource; + // view: MyJobsView; + /** The list of jobs to display */ + + // jobs: Array; + // foundCount: number; + // totalCount: number; + + /** The current search state, used to control the primary display (none, searching, searched, error) */ + + // searchState: SearchState; + // showMonitoringControls: boolean + + /** Triggers a redux action to search of the user's jobs according to the given search expression + * @remarks Since at present the service used to fetch the jobs can suffer performance issues, the + * default search action does not fetch search results each time (rather ??). + * @todo when job search is more performant, this function may be removed and redirected to the + * search function. + */ + search: (searchExpression: JobsSearchExpression) => void; + refreshSearch: () => void; + /** Triggers a redux action to cancel the indicated job */ + cancelJob: (jobID: string, timeout: number) => void; + // searchExpression: JobsSearchExpression; + narrativeMethodStoreURL: string; +} + +/** + * State for the MyJobs component + */ +interface MyJobsState { + /** Flag to show the date controls */ + showDates: boolean; + /** Contains the current selection of job statuses in the checkbox control */ + // currentJobStatusFilter: Array; + /** Contains the initial timestamp (ms epoch time) for time range */ + timeRange: TimeRange; + + isFilterOpen: boolean; + + selectedJob: Job | null; + currentSort: SortSpec | null; + // rowsPerPage: number; + + filter: FilterSpec; +} + +/** + * A View Component for browsing through the current user's jobs. + * + * @remarks + * This component is really just a tabular view into a user's jobs. It provides + * support for free text searching, filtering by job state, and date ranges. + * + */ +export default class MyJobs extends React.Component { + currentQuery?: string; + offset: number; + limit: number; + sorting: SortSpec; + currentPage: number; + // rowsPerPage: number; + + static defaultTimeRangePreset: TimeRangePresets = 'lastWeek'; + + pubsub: PubSub; + + constructor(props: MyJobsProps) { + super(props); + + this.currentQuery = ''; + this.pubsub = new PubSub(); + this.offset = 0; + this.limit = 1; + this.currentPage = 0; + this.sorting = { + field: 'created', + direction: 'descending', + }; + + this.state = { + showDates: false, + filter: { + status: [ + 'create', + 'queue', + 'run', + 'terminate', + 'complete', + 'error', + ], + }, + timeRange: { + kind: 'preset', + preset: MyJobs.defaultTimeRangePreset, + }, + isFilterOpen: false, + selectedJob: null, + currentSort: null, + // rowsPerPage: 1 + }; + } + + async componentDidMount() {} + + // onResize(rowsPerPage: number) { + // // It would be nice to rely upon the table component to trigger a + // // change even if we change the rows per page ... but we change the + // // rows per page via the table props, not by a trigger. + // // Perhaps by wrapping the table or subclassing it? + + // this.limit = rowsPerPage; + // this.offset = this.currentPage * rowsPerPage; + + // // This causes the table to rerender, but without triggering a + // // re-search; + // // this.setState({ + // // rowsPerPage + // // }); + + // // This triggers a fresh search. + // this.doSearch(false); + // } + + componentDidUpdate() { + if ( + this.props.dataSource.status === AsyncProcessState.PROCESSING || + this.props.dataSource.status === AsyncProcessState.REPROCESSING + ) { + this.pubsub.send('searching', { is: true }); + } else { + this.pubsub.send('searching', { is: false }); + } + } + + onChangeTimeRange(value: string) { + // TODO: should narrow the string value + if (value === 'customRange') { + // TODO: utilize dates from time range presets. + this.setState({ + showDates: true, + timeRange: { + kind: 'literal', + start: Date.now(), + end: Date.now(), + }, + }); + // nothing else to do. + return; + } else { + this.setState( + { + showDates: false, + timeRange: { + kind: 'preset', + preset: value as TimeRangePresets, + }, + }, + () => { + // Because this may obsolete the page. + // This is a simplification, for sure. + this.offset = 0; + this.doSearch(true); + }, + ); + } + } + + onChangeQuery(event: React.ChangeEvent) { + this.currentQuery = event.target.value; + } + + onSubmit() { + this.doSearch(true); + } + + onFirstPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page <= 1) { + return; + } + + // here we do it. + this.offset = 0; + + this.doSearch(false); + } + + onPreviousPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page <= 1) { + return; + } + + // here we do it. + this.offset = (dataSource.page - 2) * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onNextPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page >= dataSource.pageCount) { + return; + } + + // here we do it. + this.offset = dataSource.page * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onLastPage() { + if (this.props.dataSource.status !== AsyncProcessState.SUCCESS) { + return; + } + + const dataSource = this.props.dataSource; + + if (dataSource.page >= dataSource.pageCount) { + return; + } + + // here we do it. + this.offset = (dataSource.pageCount - 1) * dataSource.limit; + this.limit = dataSource.limit; + + this.doSearch(false); + } + + onReset() { + this.offset = 0; + this.doSearch(true); + } + + doSearch(forceSearch: boolean) { + const searchExpression: JobsSearchExpression = { + query: this.currentQuery, + timeRange: this.state.timeRange, + filter: this.state.filter, + forceSearch, + sort: this.sorting, + offset: this.offset, + limit: this.limit, + }; + + // TODO: document wth is happening here. + this.pubsub.send('search', { is: true }); + + this.props.search(searchExpression); + return false; + } + + onRangeChange(range: [dayjs.Dayjs | null, dayjs.Dayjs | null] | null) { + if (!range) { + return; + } + + const [fromDate, toDate] = range; + + const existingTimeRange = this.state.timeRange; + let timeRange: TimeRange; + switch (existingTimeRange.kind) { + case 'preset': + timeRange = { + kind: 'literal', + start: fromDate ? fromDate.valueOf() : 0, + end: toDate ? toDate.valueOf() : Infinity, + }; + break; + case 'literal': + timeRange = { + kind: 'literal', + start: fromDate ? fromDate.valueOf() : 0, + end: toDate ? toDate.valueOf() : Infinity, + }; + break; + default: + return; + } + + this.setState({ + timeRange, + }); + } + + renderSearchInput() { + let dateControls; + if (this.state.showDates) { + const timeRange = this.state.timeRange; + if (timeRange.kind === 'literal') { + dateControls = ( + + + + + + ); + } + } + return ( +
    + + + + {dateControls} + + + + + ); + const title = ( + + Detail for Job{' '} + + {this.state.selectedJob.id} + + + ); + return ( + + + {(value) => { + if ( + value === null || + value.status !== AsyncProcessStatus.SUCCESS + ) { + return; + } + if ( + value.value.authState.status !== + AuthenticationStatus.AUTHENTICATED + ) { + return; + } + + const { + config, + authState: { + authInfo: { token }, + }, + } = value.value; + + return ( + + ); + }} + + + ); + } + + renderView() { + return ( + +
    {this.renderControlBar()}
    + {this.renderJobsTable()} + {this.renderJobDetail()} +
    + ); + } + + render() { + return ( +
    + {this.renderView()} +
    + ); + } +} diff --git a/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.tsx b/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.tsx new file mode 100644 index 000000000..00624d25b --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.tsx @@ -0,0 +1,160 @@ +import { + UserRunSummaryQuery, + UserRunSummaryStat, +} from 'apps/JobBrowser/store/UserRunSummary'; +import ErrorAlert from 'components/ErrorAlert'; +import Loading from 'components/Loading'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +import { SimpleError } from 'lib/SimpleError'; +import CatalogClient from 'lib/kb_lib/comm/coreServices/Catalog'; +import React from 'react'; +import { Config } from 'types/config'; +import UserRunSummary from './view'; + +export interface UserRunSummaryControllerProps { + config: Config; + auth: AuthenticationStateAuthenticated; +} +export interface Filtered { + show: boolean; + value: T; +} +interface UserRunSummaryControllerData { + userRunSummary: Array>; + query: UserRunSummaryQuery; +} + +export type UserRunSummaryControllerState = AsyncProcess< + UserRunSummaryControllerData, + SimpleError +>; + +export default class UserRunSummaryController extends React.Component< + UserRunSummaryControllerProps, + UserRunSummaryControllerState +> { + constructor(props: UserRunSummaryControllerProps) { + super(props); + this.state = { + status: AsyncProcessStatus.NONE, + }; + } + + componentDidMount() { + this.initialize(); + } + + async initialize() { + this.fetchData(); + } + + async fetchData() { + this.setState({ + status: AsyncProcessStatus.PENDING, + }); + + try { + const catalogClient = new CatalogClient({ + token: this.props.auth.authInfo.token, + url: this.props.config.services.Catalog.url, + timeout: this.props.config.ui.constants.clientTimeout, + }); + const params = { + begin: 0, + end: Date.now(), + }; + const rawStats = await catalogClient.get_exec_aggr_table(params); + const userRunSummary: Array> = + rawStats.map>((stat) => { + let appId: string | null = stat.app; + if (!appId) { + appId = null; + } + + return { + show: true, + value: { + username: stat.user, + isApp: stat.app ? true : false, + appId: stat.app || null, + moduleName: stat.func_mod, + functionName: stat.func, + runCount: stat.n, + }, + }; + }); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + userRunSummary, + query: { query: '' }, + }, + }); + } catch (ex) { + this.setState({ + status: AsyncProcessStatus.ERROR, + error: { + message: ex instanceof Error ? ex.message : 'Unknown Error', + }, + }); + } + } + + search(query: UserRunSummaryQuery) { + if (this.state.status !== AsyncProcessStatus.SUCCESS) { + return; + } + + const expression = query.query.split(/\s+/).map((term) => { + return new RegExp(term, 'i'); + }); + const userRunSummary = this.state.value.userRunSummary.map( + ({ value }) => { + const show = + expression.length === 0 || + expression.every((term) => { + return ( + (value.appId && term.test(value.appId)) || + term.test(value.moduleName) || + term.test(value.functionName) || + term.test(value.username) + ); + }); + return { show, value }; + }, + ); + + this.setState({ + status: AsyncProcessStatus.SUCCESS, + value: { + userRunSummary, + query, + }, + }); + } + + renderSuccess({ userRunSummary }: UserRunSummaryControllerData) { + return ( + show) + .map(({ value }) => value)} + search={this.search.bind(this)} + /> + ); + } + + render() { + switch (this.state.status) { + case AsyncProcessStatus.NONE: + case AsyncProcessStatus.PENDING: + return ; + case AsyncProcessStatus.SUCCESS: + return this.renderSuccess(this.state.value); + case AsyncProcessStatus.ERROR: + return ; + } + } +} diff --git a/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.xtsx b/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.xtsx new file mode 100644 index 000000000..eb0ab8b94 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserRunSummary/index.xtsx @@ -0,0 +1,44 @@ +import { StoreState, SearchState, UserRunSummaryStat, UserRunSummaryQuery, ComponentLoadingState } from '../../redux/store'; +import { Action, Dispatch } from 'redux'; +import { connect } from 'react-redux'; +import Component from './view'; +import { search } from '../../redux/actions/userRunSummary'; + +export interface OwnProps { } + +interface StateProps { + searchState: SearchState; + userRunSummary: Array; +} + +interface DispatchProps { + search: (query: UserRunSummaryQuery) => void; +} + +function mapStateToProps(state: StoreState, props: OwnProps): StateProps { + const { + views: { + userRunSummaryView + } + } = state; + + if (userRunSummaryView.loadingState !== ComponentLoadingState.SUCCESS) { + throw new Error('Invalid component loading state'); + } + + const { searchState, userRunSummary } = userRunSummaryView; + return { searchState, userRunSummary }; +} + +function mapDispatchToProps(dispatch: Dispatch, ownProps: OwnProps): DispatchProps { + return { + search: (query: UserRunSummaryQuery) => { + dispatch(search(query) as any); + } + }; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Component); diff --git a/vite-app/src/apps/JobBrowser/components/UserRunSummary/style.css b/vite-app/src/apps/JobBrowser/components/UserRunSummary/style.css new file mode 100644 index 000000000..ac2cce580 --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserRunSummary/style.css @@ -0,0 +1,7 @@ +.UserRunSummary { + flex: 1 1 0px; + display: flex; + flex-direction: column; + min-height: 0; + margin-top: 1rem; +} diff --git a/vite-app/src/apps/JobBrowser/components/UserRunSummary/view.tsx b/vite-app/src/apps/JobBrowser/components/UserRunSummary/view.tsx new file mode 100644 index 000000000..6db44d48d --- /dev/null +++ b/vite-app/src/apps/JobBrowser/components/UserRunSummary/view.tsx @@ -0,0 +1,198 @@ +import { SearchOutlined } from '@ant-design/icons'; +import { Alert, Button, Form, Input, Spin, Table, Tooltip } from 'antd'; +import { + UserRunSummaryQuery, + UserRunSummaryStat, + UserRunSummaryViewDataError, +} from 'apps/JobBrowser/store/UserRunSummary'; +import UILink from 'components/UILink2'; +import { Component } from 'react'; +import './style.css'; + +export interface UserRunSummaryProps { + userRunSummary: UserRunSummaryStat[]; + search: (query: UserRunSummaryQuery) => void; +} + +interface UserRunSummaryState {} + +export default class UserRunSummary extends Component< + UserRunSummaryProps, + UserRunSummaryState +> { + currentQuery: UserRunSummaryQuery; + constructor(props: UserRunSummaryProps) { + super(props); + this.currentQuery = { + query: '', + }; + } + componentDidMount() { + this.props.search(this.currentQuery); + } + onSubmitSearch() { + this.props.search(this.currentQuery); + } + onChangeQuery(event: React.ChangeEvent) { + this.currentQuery.query = event.target.value; + } + renderControlBar() { + return ( +
    + + + + + - + , ); } diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/DeleteNarrative.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/DeleteNarrative.tsx index 82b67b2f2..f300958d7 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/DeleteNarrative.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/DeleteNarrative.tsx @@ -73,10 +73,11 @@ export default class DeleteNarrative extends Component< const client = new NarrativeModel({ workspaceURL: this.props.config.services.Workspace.url, token: this.props.authInfo.token, + timeout: this.props.config.ui.constants.clientTimeout, }); const perm = await client.getUserPermission( this.props.narrative.access_group, - this.props.authInfo.account.user + this.props.authInfo.account.user, ); if (perm === 'a') { this.setState({ @@ -118,9 +119,10 @@ export default class DeleteNarrative extends Component< timeout: this.props.config.ui.constants.clientTimeout, }); try { - await workspaceClient.delete_workspace( - { id: this.props.narrative.access_group } - ); + await workspaceClient.delete_workspace({ + id: this.props.narrative.access_group, + }); + // TODO: force an immediate refresh of the search. this.setState({ status: DeleteNarrativeStatus.SUCCESS, }); @@ -156,7 +158,7 @@ export default class DeleteNarrative extends Component< <>
    Error
    {messageContent} - + , ); } @@ -164,7 +166,7 @@ export default class DeleteNarrative extends Component< return this.renderModal(
    -
    +
    , ); } @@ -239,7 +241,7 @@ export default class DeleteNarrative extends Component< />{' '} Close
    - + , ); } diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/LinkOrgItem.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/LinkOrgItem.tsx index ad97cff69..f7c029896 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/LinkOrgItem.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/LinkOrgItem.tsx @@ -1,3 +1,4 @@ +import Well from 'components/Well'; import NarrativeModel from 'lib/clients/NarrativeModel'; import React, { Component } from 'react'; import { Button, Col, Container, Modal, Row } from 'react-bootstrap'; @@ -8,10 +9,11 @@ import { AsyncProcess, AsyncProcessError, AsyncProcessStatus, - AsyncProcessSuccess + AsyncProcessSuccess, } from '../../../../../lib/AsyncProcess'; import OrganizationsClient, { - GroupIdentity, GroupInfo + GroupIdentity, + GroupInfo, } from '../../../utils/OrganizationsClient'; import Model, { LinkOrgResult } from './Model'; import OrgSelect from './OrgSelect'; @@ -63,10 +65,11 @@ export default class LinkOrgItem extends Component< const narrativeModel = new NarrativeModel({ workspaceURL: this.props.config.services.Workspace.url, token: this.props.authInfo.token, + timeout: this.props.config.ui.constants.clientTimeout, }); const perm = await narrativeModel.getUserPermission( this.props.narrative.access_group, - this.props.authInfo.account.user + this.props.authInfo.account.user, ); const organizationsClient = new OrganizationsClient({ @@ -75,7 +78,7 @@ export default class LinkOrgItem extends Component< }); const linkedOrgs = await organizationsClient.getLinkedOrgs( - this.props.narrative.access_group + this.props.narrative.access_group, ); const linkedOrgIds: Set = new Set(); @@ -138,7 +141,7 @@ export default class LinkOrgItem extends Component< }, () => { this.updateState(); - } + }, ); } catch (ex) { const message = (() => { @@ -171,24 +174,24 @@ export default class LinkOrgItem extends Component< }; return ( -
    -
    + + Organizations this Narrative is Linked to -
    -
    {renderLinkedOrgs()}
    -
    + + {renderLinkedOrgs()} + ); } renderPending() { return this.renderModal( - + , ); } renderLinkPending() { return this.renderModal( - + , ); } @@ -243,9 +246,9 @@ export default class LinkOrgItem extends Component< if (loadProcess.value.perm !== 'a') { return this.renderModal(
    - You don't have permission to request to add this Narrative - to an Organization. -
    + You don't have permission to request to add this + Narrative to an Organization. +
    , ); } return this.renderModal( @@ -256,7 +259,7 @@ export default class LinkOrgItem extends Component< orgs={loadProcess.value.userOrgs} />
    {this.makeLinkedOrgsList(loadProcess.value)}
    -
    +
    , ); } @@ -326,7 +329,7 @@ const LinkedOrg = (props: LinkedOrgProps) => {
    diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/Model.ts b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/Model.ts index 96f44be23..8ec22a9cc 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/Model.ts +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/Model.ts @@ -1,6 +1,8 @@ -import OrganizationsClient, { OrgAPIError } from '../../../utils/OrganizationsClient'; -import {AuthInfo} from "../../../../../contexts/Auth"; -import {Config} from "../../../../../types/config"; +import { AuthInfo } from 'contexts/EuropaContext'; +import { Config } from '../../../../../types/config'; +import OrganizationsClient, { + OrgAPIError, +} from '../../../utils/OrganizationsClient'; /** * Holds the state for the overall Link Organizations item popup. @@ -8,52 +10,60 @@ import {Config} from "../../../../../types/config"; export type LinkOrgResult = 'requested' | 'completed'; export default class Model { - narrativeId: number; - authInfo: AuthInfo; - config: Config; - constructor({authInfo, narrativeId, config}: {authInfo: AuthInfo, narrativeId: number, config: Config}) { - this.narrativeId = narrativeId; - this.authInfo = authInfo; - this.config = config; - } - async linkOrg(orgId: string): Promise { - try { - const orgsClient = new OrganizationsClient({ - groupsURL: this.config.services.Groups.url, - token: this.authInfo.token - }); + narrativeId: number; + authInfo: AuthInfo; + config: Config; + constructor({ + authInfo, + narrativeId, + config, + }: { + authInfo: AuthInfo; + narrativeId: number; + config: Config; + }) { + this.narrativeId = narrativeId; + this.authInfo = authInfo; + this.config = config; + } + async linkOrg(orgId: string): Promise { + try { + const orgsClient = new OrganizationsClient({ + groupsURL: this.config.services.Groups.url, + token: this.authInfo.token, + }); - const request = await orgsClient.linkNarrativeToOrg( - this.narrativeId, - orgId - ); - if (request.complete) { - return 'completed'; - } - return 'requested'; - } catch (error) { - if (error instanceof OrgAPIError) { - const errJson = await (async () => { - try { - return await error.response.json(); - } catch (err) { - throw error; - } - })(); - if (errJson.error) { - switch (errJson.error.appcode) { - case 40010: - throw new Error( - 'A request has already been made to add this Narrative to this Organization. ' - ); - default: - throw new Error( - `An error (${errJson.error.appcode}) was made while processing your request.` - ); - } + const request = await orgsClient.linkNarrativeToOrg( + this.narrativeId, + orgId, + ); + if (request.complete) { + return 'completed'; + } + return 'requested'; + } catch (error) { + if (error instanceof OrgAPIError) { + const errJson = await (async () => { + try { + return await error.response.json(); + } catch (err) { + throw error; + } + })(); + if (errJson.error) { + switch (errJson.error.appcode) { + case 40010: + throw new Error( + 'A request has already been made to add this Narrative to this Organization. ', + ); + default: + throw new Error( + `An error (${errJson.error.appcode}) was made while processing your request.`, + ); + } + } + } + throw new Error('An error was made while processing your request'); } - } - throw new Error('An error was made while processing your request'); } - } } diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/OrgSelect.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/OrgSelect.tsx index 5b7126c3c..e7446d2b0 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/OrgSelect.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/OrgSelect.tsx @@ -1,6 +1,6 @@ import { Component } from 'react'; import { Button, Col, Container, Row } from 'react-bootstrap'; -import Select, { StylesConfig } from 'react-select'; +import Select from 'react-select'; import { GroupIdentity } from '../../../utils/OrganizationsClient'; interface OrgListProps { @@ -32,17 +32,17 @@ export default class OrgSelect extends Component { }; } - handleOrgChange = (selected: any) => { - this.setState({ selectedOrgId: selected?.value || '' }); + handleOrgChange = (selectedOrgId: string) => { + this.setState({ selectedOrgId }); }; render() { // const selectStyles: Partial> = { // menuPortal: (base) => ({ ...base, zIndex: 9999 }), // }; - const selectStyles: StylesConfig = { - menuPortal: (base) => ({ ...base, zIndex: 9999 }), - }; + // const selectStyles: StylesConfig = { + // menuPortal: (base) => ({ ...base, zIndex: 9999 }), + // }; return ( @@ -53,15 +53,17 @@ export default class OrgSelect extends Component { isClearable isSearchable placeholder="Select an Organization ..." - styles={{ - ...selectStyles, - container: (base) => ({ ...base, flex: 2 }), - }} + // styles={{ + // ...selectStyles, + // container: (base) => ({ ...base, flex: 2 }), + // }} menuPortalTarget={document.body} className="basic-single" classNamePrefix="select" options={this.orgOptions} - onChange={this.handleOrgChange} + onChange={(newValue) => { + this.handleOrgChange(newValue?.value || ''); + }} /> diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/RenameItem.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/RenameItem.tsx index cc8033e42..a8be13ff2 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/RenameItem.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/RenameItem.tsx @@ -6,7 +6,7 @@ import ErrorMessage from '../../../../../components/ErrorMessage'; import Loading from '../../../../../components/Loading'; import { AsyncProcess, - AsyncProcessStatus + AsyncProcessStatus, } from '../../../../../lib/AsyncProcess'; import { NarrativeService } from '../../../../../lib/clients/NarrativeService'; import RenameForm from './RenameForm'; @@ -52,10 +52,11 @@ export default class RenameItem extends Component< const client = new NarrativeModel({ token: this.props.authInfo.token, workspaceURL: this.props.config.services.Workspace.url, + timeout: this.props.config.ui.constants.clientTimeout, }); const userPerm = await client.getUserPermission( this.props.narrative.access_group, - this.props.authInfo.account.user + this.props.authInfo.account.user, ); if (userPerm === 'a') { this.setState({ @@ -70,7 +71,7 @@ export default class RenameItem extends Component< }); } else { throw new Error( - 'You do not have permission to rename this Narrative' + 'You do not have permission to rename this Narrative', ); } } catch (ex) { @@ -96,7 +97,7 @@ export default class RenameItem extends Component< const narrativeService = new NarrativeService({ url: this.props.config.services.ServiceWizard.url, token: this.props.authInfo.token, - timeout: 1000, + timeout: this.props.config.ui.constants.clientTimeout, }); try { await narrativeService.rename_narrative({ @@ -149,7 +150,7 @@ export default class RenameItem extends Component< Refresh the search results to see the new Narrative; it may take a few seconds for the change to propagate.

    - + , ); } @@ -222,11 +223,11 @@ export default class RenameItem extends Component< return this.renderRenamePending(); case AsyncProcessStatus.ERROR: return this.renderRenameError( - this.state.renameState.error + this.state.renameState.error, ); case AsyncProcessStatus.SUCCESS: return this.renderRenameSuccess( - this.state.renameState.value + this.state.renameState.value, ); } } diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenu.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenu.tsx index 1c7aeecfc..9e715324e 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenu.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenu.tsx @@ -1,7 +1,7 @@ +import { AuthInfo } from 'contexts/EuropaContext'; import { NarrativeSearchDoc } from 'lib/clients/NarrativeModel'; import { Component } from 'react'; import { Dropdown, Modal } from 'react-bootstrap'; -import { AuthInfo } from '../../../../../contexts/Auth'; import { Config } from '../../../../../types/config'; import CopyItem from './CopyItem'; import DeleteNarrative from './DeleteNarrative'; @@ -131,7 +131,7 @@ export default class ToolMenu extends Component { ); } - handleSelectMenuItem(eventKey: any) { + handleSelectMenuItem(eventKey: string) { const content = modalContent[eventKey]; if (!content) { return; @@ -146,7 +146,14 @@ export default class ToolMenu extends Component { renderMenu() { return ( - + { + if (!selection) { + return; + } + this.handleSelectMenuItem.bind(this); + }} + > @@ -179,6 +186,7 @@ export default class ToolMenu extends Component { {this.renderIcon('trash')} Delete diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenuWrapper.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenuWrapper.tsx index 875e81ea8..1f54dfddc 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenuWrapper.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/ToolMenuWrapper.tsx @@ -1,8 +1,10 @@ +import ErrorMessage from 'components/ErrorMessage'; +import { AuthInfo } from 'contexts/EuropaContext'; import { NarrativeSearchDoc } from 'lib/clients/NarrativeModel'; -import WorkspaceClient, { UserPermission } from 'lib/kb_lib/comm/coreServices/Workspace'; +import WorkspaceClient, { + UserPermission, +} from 'lib/kb_lib/comm/coreServices/Workspace'; import { Component } from 'react'; -import ErrorMessage from '../../../../../components/ErrorMessage'; -import { AuthInfo } from '../../../../../contexts/Auth'; import { AsyncProcess, AsyncProcessStatus, @@ -62,12 +64,12 @@ export default class ToolMenUWrapper extends Component< // get shared perms from workspace const ws = new WorkspaceClient({ url: this.props.config.services.Workspace.url, - timeout: 1000, - token: this.props.authInfo.token + timeout: this.props.config.ui.constants.clientTimeout, + token: this.props.authInfo.token, + }); + const result = await ws.get_permissions_mass({ + workspaces: [{ id: workspaceId }], }); - const result = await ws.get_permissions_mass( - { workspaces: [{ id: workspaceId }] }, - ) const perms = result.perms[0]; const isGlobal = '*' in perms && perms['*'] !== 'n'; diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/Definitions.ts b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/Definitions.ts index fa596b7ad..cf9545d25 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/Definitions.ts +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/Definitions.ts @@ -1,4 +1,4 @@ -import { UserPermission } from "lib/kb_lib/comm/coreServices/Workspace"; +import { UserPermission } from 'lib/kb_lib/comm/coreServices/Workspace'; export const PERM_MAPPING: { [key: string]: string } = { a: 'can view, edit, and share', diff --git a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/PermSearch.tsx b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/PermSearch.tsx index 55d3d673a..00c0c75f9 100644 --- a/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/PermSearch.tsx +++ b/vite-app/src/apps/Navigator/components/NarrativeDetails/ToolMenu/sharing/PermSearch.tsx @@ -1,9 +1,9 @@ +import { AuthInfo } from 'contexts/EuropaContext'; import { UserPermission } from 'lib/kb_lib/comm/coreServices/Workspace'; import { Component } from 'react'; import { Button, Col, Row } from 'react-bootstrap'; -import Select, { MultiValue } from 'react-select'; +import Select, { MultiValue, SingleValue } from 'react-select'; import AsyncSelect from 'react-select/async'; -import { AuthInfo } from '../../../../../../contexts/Auth'; import { Config } from '../../../../../../types/config'; import { AuthService } from '../../../../utils/AuthService'; import { PERM_MAPPING } from './Definitions'; @@ -40,13 +40,15 @@ export default class PermSearch extends Component< { value: 'a', label: PERM_MAPPING['a'] }, ]; - async searchUsers(term: string, _callback: any): Promise> { + async searchUsers( + term: string, + ): Promise> { if (term.length < 2) { return Promise.resolve([]); } const auth = new AuthService( this.props.config.services.Auth2.url, - this.props.authInfo.token + this.props.authInfo.token, ); const users = await auth.searchUsernames(term); return Object.entries(users) @@ -65,7 +67,7 @@ export default class PermSearch extends Component< } handleUserChange( - selectedUsers: MultiValue<{ value: string; label: string }> + selectedUsers: MultiValue<{ value: string; label: string }>, ) { if (!selectedUsers) { this.setState({ selectedUsers: [] }); @@ -74,8 +76,8 @@ export default class PermSearch extends Component< } } - handlePermChange(selected: any) { - this.setState({ perm: selected.value }); + handlePermChange(selected: { label: string; value: string }) { + this.setState({ perm: selected.value as UserPermission }); } async updatePerms() { @@ -101,13 +103,13 @@ export default class PermSearch extends Component< placeholder={ 'Select one or more users to share with...' } - styles={{ - menuPortal: (base) => ({ - ...base, - zIndex: 9999, - }), - container: (base) => ({ ...base, flex: 2 }), - }} + // styles={{ + // menuPortal: (base) => ({ + // ...base, + // zIndex: 9999, + // }), + // container: (base) => ({ ...base, flex: 2 }), + // }} noOptionsMessage={({ inputValue }) => { if (inputValue.length === 0) { return 'Search for a user by username or real name'; @@ -134,15 +136,19 @@ export default class PermSearch extends Component< - + return ( + { + noScriptTag(value); + }, + }, + ]} + > + + + ); } function renderDepartmentField() { - return { - noScriptTag(value); - } - } - ]} - > - - + return ( + { + noScriptTag(value); + }, + }, + ]} + > + + + ); } function renderOrganizationField() { - return + return ( + + ); } function renderCountryField() { - return - { + if (!option) { + return false; + } + return option.label + .toLowerCase() + .includes(inputValue.toLowerCase()); + }} + options={countryCodes} + /> + + ); } function renderStateField() { - return - { + if (!option) { + return false; + } + return option.label + .toLowerCase() + .includes(inputValue.toLowerCase()); + }} + options={statesOptions} + /> + + ); } function renderCityField() { - return - - + return ( + + + + ); } function renderPostalCode() { const [label, min, max, message] = (() => { if (countryWatched === 'United States') { - return ['Zip Code', 5, 10, `Zip code must be between 5 and 10 characters`]; + return [ + 'Zip Code', + 5, + 10, + `Zip code must be between 5 and 10 characters`, + ]; } - return ['Postal Code', 0, 16, 'Postal Code may be at most 16 characters'] + return [ + 'Postal Code', + 0, + 16, + 'Postal Code may be at most 16 characters', + ]; })(); - return { - noScriptTag(value); - } - } - ]} - > - - + return ( + { + noScriptTag(value); + }, + }, + ]} + > + + + ); } function renderPrimaryFundingSource() { - return - { + if (!option) { + return false; + } + return option.label + .toLowerCase() + .includes(inputValue.toLowerCase()); + }} + options={fundingSourceOptions} + /> + + ); } function renderJobTitleField() { - return - + + ); } function renderLocation() { - const location =
    - {renderCountryField()} - {/* State - only displayed if US is chosen for country */} - {countryWatched === 'United States' ? renderStateField() : ''} - - - {renderCityField()} - - - {renderPostalCode()} - - -
    + const location = ( +
    + {renderCountryField()} + {/* State - only displayed if US is chosen for country */} + {countryWatched === 'United States' ? renderStateField() : ''} + + {renderCityField()} + {renderPostalCode()} + +
    + ); return renderSection('location', location); } @@ -333,10 +378,14 @@ function Profile(props: ProfileProps) { // //
    // } - return <> - {renderJobTitleField()} - {jobTitleWatched === 'Other' ? renderJobTitleOtherField() : ''} - + return ( + <> + {renderJobTitleField()} + {jobTitleWatched === 'Other' + ? renderJobTitleOtherField() + : ''} + + ); } return ( <> @@ -349,23 +398,22 @@ function Profile(props: ProfileProps) { ); } - - function renderSection(title: string, body: string | undefined | JSX.Element) { - return
    -
    - {title} -
    -
    - {body} + function renderSection( + title: string, + body: string | undefined | JSX.Element, + ) { + return ( +
    +
    {title}
    +
    {body}
    -
    ; + ); } - /** * builds User Nutshell card - * - Choose between the non-auth user profile - * vs. editable user profile + * - Choose between the non-auth user profile + * vs. editable user profile * - Return either form or plain text */ function renderUserNutshell() { @@ -373,220 +421,379 @@ function Profile(props: ProfileProps) { } function renderResearchStatementField() { - return { - noScriptTag(value); - } - } - ]} - // validateStatus={this.state.status || undefined}> - > - + return ( + { + noScriptTag(value); + }, + }, + ]} + // validateStatus={this.state.status || undefined}> + > + + ); } - /** * builds research statement card - * - Choose between the non-auth user profile - * vs. editable user profile + * - Choose between the non-auth user profile + * vs. editable user profile * - Return either form or plain text */ function renderResearchStatement() { - return renderResearchStatementField() + return renderResearchStatementField(); } /** * builds affiliations card - * - Choose between the non-auth user profile - * vs. editable user profile + * - Choose between the non-auth user profile + * vs. editable user profile * - Return either form or plain text */ function renderAffiliationsEditor() { function addFirstAlert() { - return + return ( + + ); } - return
    -
    -
    -
    -
    Position
    -
    Organization
    -
    Start
    -
    End
    -
    + return ( +
    +
    +
    +
    +
    Position
    +
    Organization
    +
    Start
    +
    End
    +
    +
    +
    -
    -
    - - {(fields, { remove, add }) => { - // Note, some style tweaks for the alert below in order to match the first row of inputs. - return
    - {fields.length === 0 ? addFirstAlert() : fields.map((field, index) => { - return
    -
    - { - if (value.length <= 2) { - throw new Error('Position must be greater than 2 characters long') - } - } - }, - { max: 50, message: `Position must be less than ${50} characters long` }, - { - validator: async (_, value: string) => { - noScriptTag(value); - } - } - ]} - > - - -
    -
    - -
    -
    - { - const value = rawValue.trim(); - if (!(/[0-9]{4}/.test(value))) { - throw new Error('must be a 4-digit year'); - } - const year = parseInt(value, 10); - if ((year < 1900) || (year > 2100)) { - throw new Error('must be between 1900 and 2100'); - } - - const ended = form.getFieldValue(['affiliations', index, 'ended']); - if (!ended) { - return; - } - if (year > parseInt(ended, 10)) { - throw new Error('must be less than or equal to the end year'); - } - } - } - ]} - > - + {(fields, { remove, add }) => { + // Note, some style tweaks for the alert below in order to match the first row of inputs. + return ( +
    + {fields.length === 0 + ? addFirstAlert() + : fields.map((field, index) => { + return ( +
    +
    + { + if ( + value.length <= + 2 + ) { + throw new Error( + 'Position must be greater than 2 characters long', + ); + } + }, + }, + { + max: 50, + message: `Position must be less than ${50} characters long`, + }, + { + validator: + async ( + _, + value: string, + ) => { + noScriptTag( + value, + ); + }, + }, + ]} + > + + +
    +
    + +
    +
    + { + const value = + rawValue.trim(); + if ( + !/[0-9]{4}/.test( + value, + ) + ) { + throw new Error( + 'must be a 4-digit year', + ); + } + const year = + parseInt( + value, + 10, + ); + if ( + year < + 1900 || + year > + 2100 + ) { + throw new Error( + 'must be between 1900 and 2100', + ); + } + + const ended = + form.getFieldValue( + [ + 'affiliations', + index, + 'ended', + ], + ); + if ( + !ended + ) { + return; + } + if ( + year > + parseInt( + ended, + 10, + ) + ) { + throw new Error( + 'must be less than or equal to the end year', + ); + } + }, + }, + ]} + > + + +
    +
    + { + const value = + rawValue.trim(); + if ( + value.length === + 0 + ) { + return; + } + if ( + !/[0-9]{4}/.test( + value, + ) + ) { + throw new Error( + 'must bea a 4-digit year', + ); + } + const year = + parseInt( + value, + 10, + ); + if ( + year < + 1900 || + year > + 2100 + ) { + throw new Error( + 'must be between 1900 and 2100', + ); + } + + const started = + form.getFieldValue( + [ + 'affiliations', + index, + 'started', + ], + ); + if ( + !started + ) { + return; + } + if ( + year < + parseInt( + started, + 10, + ) + ) { + throw new Error( + 'must be greater than or equal to the start year', + ); + } + }, + }, + ]} + > + + +
    +
    +
    +
    + ); + })} +
    +
    +
    -
    - { - const value = rawValue.trim(); - if (value.length === 0) { - return; - } - if (!(/[0-9]{4}/.test(value))) { - throw new Error('must bea a 4-digit year'); - } - const year = parseInt(value, 10); - if ((year < 1900) || (year > 2100)) { - throw new Error('must be between 1900 and 2100'); - } - - const started = form.getFieldValue(['affiliations', index, 'started']); - if (!started) { - return; - } - if (year < parseInt(started, 10)) { - throw new Error('must be greater than or equal to the start year'); - } - } - } - ]} - > - - -
    -
    - +
    - })} -
    -
    - -
    -
    -
    - }} - -
    ; + ); + }} + +
    + ); } - function renderAffiliations() { return renderAffiliationsEditor(); } @@ -594,17 +801,20 @@ function Profile(props: ProfileProps) { /** * event Handlers * - * + * */ - // AVATAR function gravatarURL(gravatarHash: string, gravatarDefault: string) { return `https://www.gravatar.com/avatar/${gravatarHash}?s=300&r=pg&d=${gravatarDefault}`; } - function avatarImageSrc(avatarOption: string, gravatarDefault: string | null, gravatarHash?: string): string { + function avatarImageSrc( + avatarOption: string, + gravatarDefault: string | null, + gravatarHash?: string, + ): string { switch (avatarOption) { case 'silhouette': // Opting out of gravatar causes this one image to be shown, in all cases. @@ -614,101 +824,133 @@ function Profile(props: ProfileProps) { // Should never occur, but may in some old test profiles. return image('nouserpic'); } - return gravatarURL(gravatarHash, gravatarDefault || 'identicon'); + return gravatarURL( + gravatarHash, + gravatarDefault || 'identicon', + ); default: // should never occur, but may in some old test profiles. return image('nouserpic'); } } - // Set gravatarURL function avatarImageSrcEdit(): string { const { gravatarHash } = props.profileView.profile; - return avatarImageSrc(avatarOptionWatch, gravatarDefaultWatch, gravatarHash); + return avatarImageSrc( + avatarOptionWatch, + gravatarDefaultWatch, + gravatarHash, + ); } - function renderAvatarOptionsField() { - return - - - {avatarOptions.map(({ value, label, description }) => { - return {label} - {description} - })} - - - + return ( + + + + {avatarOptions.map(({ value, label, description }) => { + return ( + + {label} - {description} + + ); + })} + + + + ); } function renderGravatarDefaultField() { if (avatarOptionWatch !== 'gravatar') { return; } - const gravatarHelpLink =
    - generated or generic image - ; - return <> - - + +
    + If your email address is not registered at{' '} + + gravatar + + , the {gravatarHelpLink} you select above will be used + instead. +
    + + ); } function renderAvatarEditor() { - return <> -
    Avatar
    - {renderAvatarImage(avatarImageSrcEdit)} -
    - {renderAvatarOptionsField()} -
    -
    - {renderGravatarDefaultField()} -
    - + return ( + <> +
    + Avatar +
    + {renderAvatarImage(avatarImageSrcEdit)} +
    + {renderAvatarOptionsField()} +
    +
    + {renderGravatarDefaultField()} +
    + + ); } function renderAvatarImage(srcRenderer: () => string) { - return User avatar + return ( + User avatar + ); } function renderAvatar() { - return
    -
    - {renderAvatarEditor()} + return ( +
    +
    + {renderAvatarEditor()} +
    -
    + ); } async function saveForm() { - const update = formToUpdate(form.getFieldsValue()) + const update = formToUpdate(form.getFieldsValue()); await saveProfile(update); const { isValid, isTouched } = checkForm(); @@ -722,7 +964,7 @@ function Profile(props: ProfileProps) { if (fields) { return fields.every(({ errors }) => { return !errors || errors.length === 0; - }) + }); } const fieldsError = form.getFieldsError(); if (!fieldsError) { @@ -730,28 +972,30 @@ function Profile(props: ProfileProps) { } return fieldsError.every(({ errors }) => { return errors.length === 0; - }) + }); })(); const isTouched = form.isFieldsTouched(); - return { isValid, isTouched } + return { isValid, isTouched }; } function cancelForm() { const { isTouched } = checkForm(); if (isTouched) { - const title =
    -

    Close Form and Abandon Changes?

    -

    You will lose any changes that have been made.

    -
    + const title = ( +
    +

    Close Form and Abandon Changes?

    +

    You will lose any changes that have been made.

    +
    + ); Modal.confirm({ title, onOk: () => { resetForm(); disableEditing(); - } + }, }); } else { resetForm(); @@ -759,6 +1003,23 @@ function Profile(props: ProfileProps) { } } + function onORCIDLink() { + const params: Record = {}; + + const returnURL = new URL(window.location.href); + const returnLink = { + url: returnURL.toString(), + label: 'User Profile', + }; + params.return_link = JSON.stringify(returnLink); + + navigate2({ + path: 'orcidlink/link', + type: 'kbaseui', + params, + newWindow: false, + }); + } function resetForm() { form.resetFields(); @@ -768,26 +1029,6 @@ function Profile(props: ProfileProps) { setIsFormTouched(isTouched); } - function getLinkingLink() { - const linkingURL = new URL(`${props.uiOrigin}/#orcidlink/link`); - const returnURL = (() => { - if (window.parent) { - return new URL(window.parent.location.href); - } else { - return new URL(window.location.href); - } - })(); - const returnLink = { - type: 'link', - url: returnURL.toString(), - label: 'User Profile' - } - linkingURL.searchParams.set('return_link', JSON.stringify(returnLink)); - const hash = linkingURL.hash; - const query = linkingURL.search; - return `${hash}${query}` - } - function renderControls() { // const warnings = (() => { // if (props.profileView.warnings.length > 0) { @@ -812,81 +1053,83 @@ function Profile(props: ProfileProps) { if (props.orcidState.value.orcidId) { return; } - return - - + return ( + + + + ); } })(); - const button = - - - - {orcidLinkButton2} - - - - return
    -
    {button}
    -
    ; + const button = ( + + + + + {orcidLinkButton2} + + ); + + return ( +
    +
    {button}
    +
    + ); } function renderResearchInterests() { return renderResearchInterestsEditor(); - } function renderResearchInterestsEditor() { - return
    - - + - - {researchInterestsList.map(({ value, label }) => { - return - - {label} - - ; - })} - - - - - - -
    ; + + + {researchInterestsList.map(({ value, label }) => { + return ( + + + {label} + + + ); + })} + + + + + + +
    + ); } function hasORCIDId(): boolean { @@ -897,24 +1140,25 @@ function Profile(props: ProfileProps) { case AsyncProcessStatus.ERROR: return false; case AsyncProcessStatus.SUCCESS: - return !!(orcidState.value.orcidId); + return !!orcidState.value.orcidId; } } function renderORCIDIcon() { - return ORCID® icon - } - - function makeUIURL(path: string) { - const url = new URL(props.uiOrigin); - url.hash = `${path}`; - return url.toString(); + return ( + ORCID® icon + ); } - function renderORCIDIdLinkEdit(orcidId: string) { + function renderORCIDIdLinkEdit(orcidId: string, orcidURL: string) { // const visibilityMessage = (() => { // if (showORCIDIdWatched) { // return showing in profile @@ -922,43 +1166,61 @@ function Profile(props: ProfileProps) { // return not showing in profile // })(); - return
    -
    {renderORCIDIdLink(orcidId)}
    - {/*
    {visibilityMessage}
    */} -
    - - - -
    + return (
    - Your KBase ORCID® Link +
    {renderORCIDIdLink(orcidId, orcidURL)}
    + {/*
    {visibilityMessage}
    */} +
    + + + +
    +
    + + Your KBase ORCID® Link + +
    -
    - + ); } - function renderORCIDIdLink(orcidId: string) { - return - {renderORCIDIcon()} -
    - {ORCID_URL}/{orcidId} -
    - ; + function renderORCIDIdLink(orcidId: string, orcidURL: string) { + return ( + + {renderORCIDIcon()} +
    + {orcidURL}/{orcidId} +
    + + ); } - function renderORCIDId(orcidId: string | null) { + function renderORCIDId(orcidId: string | null, orcidURL: string) { if (orcidId) { - return renderORCIDIdLinkEdit(orcidId); + return renderORCIDIdLinkEdit(orcidId, orcidURL); } - const alertMessage =
    - Have an ORCID® account? Create an KBase ORCID® Link to - connect your KBase to ORCID® account, and show your ORCID® iD - right here in your profile. - -
    - return - + const alertMessage = ( +
    + Have an ORCID® account? Create an KBase ORCID® Link to + connect your KBase to ORCID® account, and show your ORCID® iD + right here in your profile. +
    + ); + return ; } function renderORCIDRow() { @@ -966,47 +1228,65 @@ function Profile(props: ProfileProps) { switch (orcidState.status) { case AsyncProcessStatus.NONE: case AsyncProcessStatus.PENDING: - return ; + return ( + + + + + + ); case AsyncProcessStatus.ERROR: // TODO: improve error - propagate error code. - return ; + return ( + + + + + + ); case AsyncProcessStatus.SUCCESS: - - return - - ORCID® iD - - - {renderORCIDId(orcidState.value.orcidId)} - - - + return ( + + ORCID® iD + + {renderORCIDId( + orcidState.value.orcidId, + orcidState.value.serviceInfo.runtime_info + .orcid_site_url, + )} + + + ); } } /** * Convert form values and state into a user profile update * data package. - * + * * Some notes about the user profile service here. - * + * * First, unlike the call to fetch the profile, which is made to the * user profile "bff" service, this call is directly to the user_profile service. - * I suspect this is due to the fact that the user profile refactor + * I suspect this is due to the fact that the user profile refactor * which converted from JS/knockout to TS/react was initially for a viewer, - * and later the scope was expanded to cover editing, but time constraints or + * and later the scope was expanded to cover editing, but time constraints or * simply the quite long duration of that project (6 mos or so iirc) required * shortcuts. - * + * * So the rules for submitting updates to the user profile service are ineffect here. - * - * So the user profile service is essentially a lightly validated passthrough to + * + * So the user profile service is essentially a lightly validated passthrough to * mongodb. - * - * The "user" field serves two purposes. It is used to verify that the + * + * The "user" field serves two purposes. It is used to verify that the * profile being updated has the same username as the username associated with the token. * And it is used to update the realname and thumbnail (unused) fields. - * + * * The "profile" field is used to update the user profile data. The service ensures that the entire * profile object is not overwritten, only the top level properties. That is, it creates an update object * in which each field name is "profile.PROP" where prop is a top level profile field. See the UserProfileProfile @@ -1014,15 +1294,15 @@ function Profile(props: ProfileProps) { * Of these, all that we are interested in are: * - userdata - the actual user-controlled display fields for the profile * - plugins - contains plugin-level preferences - we use this to set the user profile orcid display opt-in/out. - * + * * Note that each of these must be provided IN THEIR ENTIRETY, due to the fact that the the user profile * service does not accept a dotted field path. To this end, the best strategy is to fetch the user profile - * first, then apply any changes to userdata and plugin preferences, then send just those two back in - * an update object. - * + * first, then apply any changes to userdata and plugin preferences, then send just those two back in + * an update object. + * * Needless to say, this is not great, but this service has been hardly touched in nearly 10 years. - * - * @param allValues + * + * @param allValues */ // Okay, here is one way to model the form values (in our case). @@ -1030,22 +1310,21 @@ function Profile(props: ProfileProps) { // or this - function formToUpdate(allValues: unknown): UserProfileUpdate { - if (typeof allValues !== 'object' || allValues === null) { throw new Error('The update is not an object'); } // Blind Trust activated - const formUpdate = allValues as unknown as FormData - + const formUpdate = allValues as unknown as FormData; // Yes, I know. But we need full deep copy, and structuredClone has not been // around very long in 2023. - const userdata = JSON.parse(JSON.stringify(props.profileView.profile.userdata)) as UserProfileUserdata; + const userdata = JSON.parse( + JSON.stringify(props.profileView.profile.userdata), + ) as UserProfileUserdata; - // Okay, this is a bit of a cheat, using Required, otherwise the optional keys are + // Okay, this is a bit of a cheat, using Required, otherwise the optional keys are // not recognized. // TODO: make or find a better KeyOfType implementation. // const simpleUserdataFields: Array, string | null | Array>> = [ @@ -1080,8 +1359,6 @@ function Profile(props: ProfileProps) { // 'researchInterests' // ] - - // const nestedArrayFields = [ // { // name: 'affiliations', @@ -1089,7 +1366,7 @@ function Profile(props: ProfileProps) { // } // ] - // These fields are "required". This is self-discipline, as the user profile + // These fields are "required". This is self-discipline, as the user profile // service doesn't care. But the form requires these fields. userdata.avatarOption = formUpdate.avatarOption; @@ -1099,7 +1376,6 @@ function Profile(props: ProfileProps) { userdata.gravatarDefault = formUpdate.gravatarDefault; } - if (!formUpdate.organization) { delete userdata.organization; } else { @@ -1124,35 +1400,33 @@ function Profile(props: ProfileProps) { userdata.state = formUpdate.state; } - if (!formUpdate.postalCode) { delete userdata.postalCode; } else { userdata.postalCode = formUpdate.postalCode; } - if (!formUpdate.country) { delete userdata.country; } else { userdata.country = formUpdate.country; } - if (!formUpdate.researchStatement) { delete userdata.researchStatement; } else { userdata.researchStatement = formUpdate.researchStatement; } - - if (formUpdate.researchInterests && formUpdate.researchInterests.length > 0) { + if ( + formUpdate.researchInterests && + formUpdate.researchInterests.length > 0 + ) { userdata.researchInterests = formUpdate.researchInterests; } else { delete userdata.researchInterests; } - if (!formUpdate.researchInterestsOther) { delete userdata.researchInterestsOther; } else { @@ -1182,21 +1456,23 @@ function Profile(props: ProfileProps) { // in the affiliations array, other than, e.g., using all keys to form // a row identifier. In the end, probably not worth it as the form // values translate literally into the profile values. - userdata.affiliations = formUpdate.affiliations.map(({ title, organization, started, ended }) => { - const affiliation: UserProfileAffiliation = { - title, organization, started: parseInt(started, 10) - } - if (ended && ended.length) { - affiliation.ended = parseInt(ended); - } - return affiliation; - }) + userdata.affiliations = formUpdate.affiliations.map( + ({ title, organization, started, ended }) => { + const affiliation: UserProfileAffiliation = { + title, + organization, + started: parseInt(started, 10), + }; + if (ended && ended.length) { + affiliation.ended = parseInt(ended); + } + return affiliation; + }, + ); } else { delete userdata.affiliations; } - - // TODO: figure this out later. // for (const field of simpleUserdataFields) { // if (Object.prototype.hasOwnProperty.call(allValues, field)) { @@ -1225,17 +1501,17 @@ function Profile(props: ProfileProps) { preferences.showORCIDId = { ...preferences.showORCIDId, value: formUpdate.showORCIDId, - updatedAt: Date.now() - } + updatedAt: Date.now(), + }; } else { preferences.showORCIDId = { value: formUpdate.showORCIDId, createdAt: Date.now(), - updatedAt: Date.now() - } + updatedAt: Date.now(), + }; } } else if (preferences.showORCIDId) { - // Handles case of a user without orcid link - this + // Handles case of a user without orcid link - this // form field will be undefined. delete preferences.showORCIDId; } @@ -1244,11 +1520,11 @@ function Profile(props: ProfileProps) { user: props.profileView.user, profile: { userdata, - preferences - } - } + preferences, + }, + }; - return update + return update; } function onFieldsChange(_: Array, allFields: Array) { @@ -1258,12 +1534,23 @@ function Profile(props: ProfileProps) { } function renderOrganizations() { - - const message =
    -

    Organizations are not editable in your profile.

    -

    Please visit the Organizations page to manage your Organization memberships.

    -
    - return + const message = ( +
    +

    Organizations are not editable in your profile.

    +

    + Please visit the + + Organizations page + {' '} + to manage your Organization memberships. +

    +
    + ); + return ; } function onFormLoad() { @@ -1272,22 +1559,41 @@ function Profile(props: ProfileProps) { } function renderIdentityEditor() { - return
    -
    Identity
    - - - - - - - {renderORCIDRow()} - -
    - Username - - {props.profileView.user.username} -
    -
    + return ( +
    +
    + Identity +
    + + + + + + + {renderORCIDRow()} + +
    Username + + {props.profileView.user.username} + +
    +
    + ); } function renderIdentity() { @@ -1297,37 +1603,60 @@ function Profile(props: ProfileProps) { const { profile: { userdata: { - researchInterests, researchInterestsOther, jobTitle, jobTitleOther, department, organization, country, state, city, postalCode, - fundingSource, researchStatement, affiliations: rawAffiliations, avatarOption, gravatarDefault + researchInterests, + researchInterestsOther, + jobTitle, + jobTitleOther, + department, + organization, + country, + state, + city, + postalCode, + fundingSource, + researchStatement, + affiliations: rawAffiliations, + avatarOption, + gravatarDefault, }, - preferences - } - } = props.profileView + preferences, + }, + } = props.profileView; // Some adjustments. // Needs to be boolean for the control; defaults to false if not present - const showORCIDId = preferences ? (preferences['showORCIDId']?.value ? true : false) : false; + const showORCIDId = preferences + ? preferences['showORCIDId']?.value + ? true + : false + : false; // Needs to be string for the input control. - const affiliations = typeof rawAffiliations === 'undefined' ? [] : rawAffiliations - .filter(({ started, title, organization }) => { - return (title && title.length && organization && organization.length && - started); - }) - .map(({ - started, ended, title, organization - }) => { - const affiliation: FormDataAffiliation = { - title, organization, - started: String(started) - } - if (ended) { - affiliation.ended = String(ended); - } - return affiliation; - - }); + const affiliations = + typeof rawAffiliations === 'undefined' + ? [] + : rawAffiliations + .filter(({ started, title, organization }) => { + return ( + title && + title.length && + organization && + organization.length && + started + ); + }) + .map(({ started, ended, title, organization }) => { + const affiliation: FormDataAffiliation = { + title, + organization, + started: String(started), + }; + if (ended) { + affiliation.ended = String(ended); + } + return affiliation; + }); affiliations.sort((a: FormDataAffiliation, b: FormDataAffiliation) => { const startedSort = parseInt(a.started, 10) - parseInt(b.started, 10); @@ -1358,19 +1687,39 @@ function Profile(props: ProfileProps) { }); const initialValues = { - researchInterests, researchInterestsOther, jobTitle, jobTitleOther, - department, organization, country, state, city, postalCode, - fundingSource, researchStatement, affiliations, avatarOption, gravatarDefault, showORCIDId - } + researchInterests, + researchInterestsOther, + jobTitle, + jobTitleOther, + department, + organization, + country, + state, + city, + postalCode, + fundingSource, + researchStatement, + affiliations, + avatarOption, + gravatarDefault, + showORCIDId, + }; return ( <> {contextHolder}
    -
    +
    {renderControls()} -
    -
    +
    + {/* Padding below to fix antd rows with gutters. */} +
    - + - + + + + {props.profileView.user.realname}{' '} + + + } + /> + + + +
    + {renderIdentity()} +
    + {renderAvatar()} +
    +
    + {/*
    {renderIdentity()}
    {renderAvatar()} - + */} - - + + + + Research Interests + + + {renderResearchInterests()} + + + {/* {renderResearchInterests()} - + */} - - + + + + KBase Organizations + + + {renderOrganizations()} + + + {/* {renderOrganizations()} - + */}
    - - + + + + {renderUserNutshell()} + + + {/* {renderUserNutshell()} - + */} - - + + + + Research or Personal Statement + + + {renderResearchStatement()} + + + {/* {renderResearchStatement()} - + */} - - + + + + Affiliations + + + {renderAffiliations()} + + + {/* {renderAffiliations()} - + */} - +
    -
    +
    ); } diff --git a/vite-app/src/apps/UserProfile/Profile/ProfileViewer.tsx b/vite-app/src/apps/UserProfile/Profile/ProfileViewer.tsx index 0bcbe33dc..7797a93c6 100644 --- a/vite-app/src/apps/UserProfile/Profile/ProfileViewer.tsx +++ b/vite-app/src/apps/UserProfile/Profile/ProfileViewer.tsx @@ -1,7 +1,4 @@ -import { - EditOutlined, - ExclamationOutlined -} from '@ant-design/icons'; +import { EditOutlined, ExclamationOutlined } from '@ant-design/icons'; import { Alert, Button, @@ -13,27 +10,24 @@ import { Row, Space, Spin, - Tooltip + Tooltip, } from 'antd'; import Link from 'antd/es/typography/Link'; +import Well from 'components/Well'; import { image } from 'components/images'; import DOMPurify from 'dompurify'; import { AsyncProcessStatus } from 'lib/AsyncProcess'; -import { changeHash2 } from 'lib/navigation'; +import { navigate2 } from 'lib/navigation'; import { marked } from 'marked'; -import { v4 as uuidv4 } from 'uuid'; import { UserProfileAffiliation } from '../API'; -import Area from './Area'; import Orgs from './Orgs/controller'; import './Profile.css'; import { ORCIDState, OrgsState, ProfileView } from './controller'; - export interface ProfileProps { profileView: ProfileView; orcidState: ORCIDState; orgsState: OrgsState; - uiOrigin: string; checkORCID: (username: string) => void; fetchProfile: (username: string) => void; toggleEditing: () => void; @@ -44,35 +38,34 @@ export type KeyOfType = keyof { }; export interface FormDataAffiliation { - title: string - organization: string - started: string - ended?: string | null + title: string; + organization: string; + started: string; + ended?: string | null; } export interface FormData { - avatarOption: string - gravatarDefault?: string - jobTitle?: string - jobTitleOther?: string - department?: string - organization?: string - country?: string - state?: string - city?: string - postalCode?: string - fundingSource?: string - researchStatement?: string - researchInterests?: Array - researchInterestsOther?: string - affiliations?: Array - showORCIDId: boolean + avatarOption: string; + gravatarDefault?: string; + jobTitle?: string; + jobTitleOther?: string; + department?: string; + organization?: string; + country?: string; + state?: string; + city?: string; + postalCode?: string; + fundingSource?: string; + researchStatement?: string; + researchInterests?: Array; + researchInterestsOther?: string; + affiliations?: Array; + showORCIDId: boolean; } // Note that this should be exported from antd // TODO: investigate and possibly create issue on github; stretch - create PR. - export interface ReturnLink { type: string; origin: string; @@ -87,42 +80,58 @@ export interface ReturnLink { // class Profile extends React.Component { function ProfileViewer(props: ProfileProps) { function enableEditing() { - props.toggleEditing() + props.toggleEditing(); } function renderUserNutshellViewEmpty() { return ( - + ); } - function renderSection(title: string, body: string | undefined | JSX.Element) { - return
    -
    - {title} -
    -
    - {body} + function renderSection( + title: string, + body: string | undefined | JSX.Element, + ) { + return ( +
    +
    {title}
    +
    {body}
    -
    ; + ); } function renderJobTitleView() { if (props.profileView.profile.userdata.jobTitle) { - renderSection('position', - props.profileView.profile.userdata.jobTitle === 'Other' ? props.profileView.profile.userdata.jobTitleOther : props.profileView.profile.userdata.jobTitle - ) + renderSection( + 'position', + props.profileView.profile.userdata.jobTitle === 'Other' + ? props.profileView.profile.userdata.jobTitleOther + : props.profileView.profile.userdata.jobTitle, + ); } } function renderLocationSection() { - const { profileView: { profile } } = props; + const { + profileView: { profile }, + } = props; const location = (() => { if (profile.userdata.country === 'United States') { - return [profile.userdata.country, profile.userdata.state, profile.userdata.city].filter(x => x).join(', '); + return [ + profile.userdata.country, + profile.userdata.state, + profile.userdata.city, + ] + .filter((x) => x) + .join(', '); } else { - return [profile.userdata.country, profile.userdata.city].filter(x => x).join(', '); + return [profile.userdata.country, profile.userdata.city] + .filter((x) => x) + .join(', '); } })(); @@ -137,25 +146,46 @@ function ProfileViewer(props: ProfileProps) { if (!props.profileView.profile.userdata.department) { return; } - return renderSection('department', props.profileView.profile.userdata.department) + return renderSection( + 'department', + props.profileView.profile.userdata.department, + ); } function renderOrganizationSection() { if (!props.profileView.profile.userdata.organization) { return; } - return renderSection('organization', props.profileView.profile.userdata.organization); + return renderSection( + 'organization', + props.profileView.profile.userdata.organization, + ); } function renderFundingSourceSection() { if (!props.profileView.profile.userdata.fundingSource) { return; } - return renderSection('primary funding source', props.profileView.profile.userdata.fundingSource); + return renderSection( + 'primary funding source', + props.profileView.profile.userdata.fundingSource, + ); } function isNutshellEmpty() { - const { profile: { userdata: { jobTitle, department, organization, fundingSource, country, state, city } } } = props.profileView; + const { + profile: { + userdata: { + jobTitle, + department, + organization, + fundingSource, + country, + state, + city, + }, + }, + } = props.profileView; if (jobTitle || department || organization || fundingSource) { return false; } @@ -176,45 +206,56 @@ function ProfileViewer(props: ProfileProps) { return renderUserNutshellViewEmpty(); } - return <> - {renderJobTitleView()} - {renderDepartmentSection()} - {renderOrganizationSection()} - {renderFundingSourceSection()} - {renderLocationSection()} - ; + return ( + <> + {renderJobTitleView()} + {renderDepartmentSection()} + {renderOrganizationSection()} + {renderFundingSourceSection()} + {renderLocationSection()} + + ); } /** * builds User Nutshell card - * - Choose between the non-auth user profile - * vs. editable user profile + * - Choose between the non-auth user profile + * vs. editable user profile * - Return either form or plain text */ function renderUserNutshell() { return renderUserNutshellView(); } - - /** * builds research statement card - * - Choose between the non-auth user profile - * vs. editable user profile + * - Choose between the non-auth user profile + * vs. editable user profile * - Return either form or plain text */ function renderResearchStatement() { let statement; - const { profile: { userdata: { researchStatement } } } = props.profileView; + const { + profile: { + userdata: { researchStatement }, + }, + } = props.profileView; if (!researchStatement || researchStatement === '') { - statement = ; + statement = ( + + ); } else { // const fixed = this.props.profileUserdata.researchStatement.replace(/\n/, '
    '); // statement =

    {this.props.profileUserdata.researchStatement}

    ; marked.use({ - breaks: true + breaks: true, }); - const content = DOMPurify.sanitize(marked.parse(researchStatement)); + const content = DOMPurify.sanitize( + marked.parse(researchStatement, { async: false }) as string, + ); statement =
    ; } @@ -227,57 +268,73 @@ function ProfileViewer(props: ProfileProps) { // non-empty array // TODO: not sure about that last case -- at least explain it - if (!affiliations || affiliations.length === 0 || affiliations[0]['title'] === '') + if ( + !affiliations || + affiliations.length === 0 || + affiliations[0]['title'] === '' + ) return ( - + ); - affiliations.sort((a: UserProfileAffiliation, b: UserProfileAffiliation) => { - const startedSort = a.started - b.started; - if (startedSort !== 0) { - return startedSort; - } - - const endedSort = (() => { - if (!a.ended) { - return -1; + affiliations.sort( + (a: UserProfileAffiliation, b: UserProfileAffiliation) => { + const startedSort = a.started - b.started; + if (startedSort !== 0) { + return startedSort; } - if (!b.ended) { - return 1; - } - return a.ended - b.ended; - })(); - if (endedSort !== 0) { - return endedSort; - } + const endedSort = (() => { + if (!a.ended) { + return -1; + } + if (!b.ended) { + return 1; + } + return a.ended - b.ended; + })(); - const titleSort = a.title.localeCompare(b.title); - if (titleSort !== 0) { - return titleSort; - } + if (endedSort !== 0) { + return endedSort; + } - return a.organization.localeCompare(b.organization); - }); + const titleSort = a.title.localeCompare(b.title); + if (titleSort !== 0) { + return titleSort; + } + + return a.organization.localeCompare(b.organization); + }, + ); return ( - - - + + + {affiliations - .filter(affiliation => affiliation.title) + .filter((affiliation) => affiliation.title) .map((affiliation, index) => { - return - - - - ; + return ( + + + + + + ); })}
    positionorganizationtenurepositionorganizationtenure
    {affiliation.title}{affiliation.organization}{affiliation.started} - {affiliation.ended ? affiliation.ended : 'present'}
    {affiliation.title}{affiliation.organization} + {affiliation.started} -{' '} + {affiliation.ended + ? affiliation.ended + : 'present'} +
    @@ -287,17 +344,20 @@ function ProfileViewer(props: ProfileProps) { /** * event Handlers * - * + * */ - // AVATAR function gravatarURL(gravatarHash: string, gravatarDefault: string) { return `https://www.gravatar.com/avatar/${gravatarHash}?s=300&r=pg&d=${gravatarDefault}`; } - function avatarImageSrc(avatarOption: string, gravatarDefault: string | null, gravatarHash?: string): string { + function avatarImageSrc( + avatarOption: string, + gravatarDefault: string | null, + gravatarHash?: string, + ): string { switch (avatarOption) { case 'silhouette': // Opting out of gravatar causes this one image to be shown, in all cases. @@ -307,129 +367,69 @@ function ProfileViewer(props: ProfileProps) { // Should never occur, but may in some old test profiles. return image('nouserpic'); } - return gravatarURL(gravatarHash, gravatarDefault || 'identicon'); + return gravatarURL( + gravatarHash, + gravatarDefault || 'identicon', + ); default: // should never occur, but may in some old test profiles. return image('nouserpic'); } } - // Set gravatarURL function avatarImageSrcView(): string { - const { userdata: { avatarOption, gravatarDefault }, gravatarHash } = props.profileView.profile; - return avatarImageSrc(avatarOption, gravatarDefault || null, gravatarHash); + const { + userdata: { avatarOption, gravatarDefault }, + gravatarHash, + } = props.profileView.profile; + return avatarImageSrc( + avatarOption, + gravatarDefault || null, + gravatarHash, + ); } - function renderAvatarImage(srcRenderer: () => string) { - return User avatar - + return ( + User avatar + ); } function renderAvatarView() { - return renderAvatarImage(avatarImageSrcView) + return renderAvatarImage(avatarImageSrcView); } function renderAvatar() { - return
    -
    - {renderAvatarView()} + return ( +
    +
    {renderAvatarView()}
    -
    + ); } - function onORCIDLink() { - // open window, without much or any window decoration. - const eventId = uuidv4(); - // const url = new URL(`${document.location.origin}#orcidlink/link`); - // TODO: for better ergonomics in development, should be able to get the - // kbase environment host from the config... - - const url = new URL(props.uiOrigin); - // const url = new URL(window.location.href); - url.hash = '#orcidlink/link'; - - // TODO: if this works, we can give the window a unique uuid name when the app loads. - window.name = "FOOBAR"; - - // {id: string} is the ReturnFromWindow type expected by ORCIDLink. - const origin = window.location.origin; - // const origin = "https://ci.kbase.us"; - url.searchParams.set('ui_options', "hide-ui"); - url.searchParams.set('return_link', JSON.stringify({ - type: 'window', - origin, - id: eventId, - label: 'User Profile' - })); - const newWindow = window.open(url.toString(), '_blank', "popup,width=1079,height=960"); - if (newWindow === null) { - // what to do? - // return - console.error('Cannot open new window for linking'); - return; - } - const handleEvent = ({ data }: MessageEvent) => { - if (typeof data === 'object' && data !== null) { - const { id } = data; - if (eventId === id) { - // this.evaluate(); - // do something here... - props.checkORCID(props.profileView.user.username); - props.fetchProfile(props.profileView.user.username); - if (newWindow) { - newWindow.close(); - window.removeEventListener('message', handleEvent); - } - } - } - }; - window.addEventListener('message', handleEvent); - } + function onORCIDLink() { + const params: Record = {}; - function getLinkingLink() { - const linkingURL = new URL(`${props.uiOrigin}/#orcidlink/link`); - const returnURL = (() => { - if (window.parent) { - return new URL(window.parent.location.href); - } else { - return new URL(window.location.href); - } - })(); + const returnURL = new URL(window.location.href); const returnLink = { - type: 'link', url: returnURL.toString(), - label: 'User Profile' - } - linkingURL.searchParams.set('return_link', JSON.stringify(returnLink)); - const hash = linkingURL.hash; - const query = linkingURL.search; - return `${hash}${query}` - } + label: 'User Profile', + }; + params.return_link = JSON.stringify(returnLink); - function onORCIDLink2() { - // const onOk = () => { - // window.location.href = getLinkingLink(); - // } - - // Modal.confirm({ - // title: 'Proceed to ORCID Link', - // onOk, - // content: <> - //

    - // In order to create your ORCID Link, your browser will leave this page, then return - // to it when you have completed the linking process. - //

    - // - // }); - changeHash2(window.location.href = getLinkingLink()); + navigate2({ + path: 'orcidlink/link', + type: 'kbaseui', + params, + newWindow: false, + }); } function renderControls() { @@ -442,63 +442,66 @@ function ProfileViewer(props: ProfileProps) { const showWarnings = () => { Modal.warning({ title: 'Warnings', - content: { - return {warning} - }} /> - }) - } - return + content: ( + { + return {warning}; + }} + /> + ), + }); + }; + return ( + + ); } })(); - let button; - - // const orcidLinkButton = (() => { - // if (props.orcidState.status === AsyncProcessStatus.SUCCESS) { - // if (props.orcidState.value.orcidId) { - // return; - // } - // return - // - // - // } - // })(); const orcidLinkButton2 = (() => { if (props.orcidState.status === AsyncProcessStatus.SUCCESS) { if (props.orcidState.value.orcidId) { return; } - return - - + return ( + + + + ); } })(); - button = - - {/* {orcidLinkButton} */} - {orcidLinkButton2} - {warnings} - ; - - return
    -
    {button}
    -
    ; + const button = ( + + + {orcidLinkButton2} + {warnings} + + ); + + return ( +
    +
    {button}
    +
    + ); } function renderResearchInterests() { @@ -506,12 +509,15 @@ function ProfileViewer(props: ProfileProps) { } function renderResearchInterestsView() { - const researchInterests = props.profileView.profile.userdata.researchInterests; - if (Array.isArray(researchInterests) && - researchInterests.length > 0) { + const researchInterests = + props.profileView.profile.userdata.researchInterests; + if (Array.isArray(researchInterests) && researchInterests.length > 0) { const normalized = researchInterests.map((interest) => { if (interest === 'Other') { - return props.profileView.profile.userdata.researchInterestsOther || interest; + return ( + props.profileView.profile.userdata + .researchInterestsOther || interest + ); } else { return interest; } @@ -521,7 +527,7 @@ function ProfileViewer(props: ProfileProps) { }); return ( -
      +
        {normalized.map((interest) => { return
      • {interest}
      • ; })} @@ -529,26 +535,46 @@ function ProfileViewer(props: ProfileProps) { ); } else { return ( - + ); } } function renderORCIDIcon() { - return ORCID® icon + return ( + ORCID® icon + ); } function renderORCIDIdLink(orcidId: string, orcidSiteURL: string) { - return - {renderORCIDIcon()} -
        - {orcidSiteURL}/{orcidId} -
        - ; + return ( + + {renderORCIDIcon()} +
        + {orcidSiteURL}/{orcidId} +
        + + ); } function renderORCIDIdLinkView(orcidId: string, orcidSiteURL: string) { @@ -572,7 +598,11 @@ function ProfileViewer(props: ProfileProps) { case AsyncProcessStatus.ERROR: return false; case AsyncProcessStatus.SUCCESS: - return !!(orcidState.value.orcidId && props.profileView.profile.preferences?.showORCIDId?.value && props.profileView.profile.preferences?.showORCIDId.value); + return !!( + orcidState.value.orcidId && + props.profileView.profile.preferences?.showORCIDId?.value && + props.profileView.profile.preferences?.showORCIDId.value + ); } } @@ -581,69 +611,104 @@ function ProfileViewer(props: ProfileProps) { switch (orcidState.status) { case AsyncProcessStatus.NONE: case AsyncProcessStatus.PENDING: - return ; + return ( + + + + + + ); case AsyncProcessStatus.ERROR: // TODO: improve error - propagate error code. - return ; - case AsyncProcessStatus.SUCCESS: - if (orcidState.value.orcidId && props.profileView.profile.preferences?.showORCIDId?.value) { - return - - ORCID® iD - - - {renderORCIDId(orcidState.value.orcidId, orcidState.value.serviceInfo.runtime_info.orcid_site_url)} + return ( + + + + ); + case AsyncProcessStatus.SUCCESS: + if ( + orcidState.value.orcidId && + props.profileView.profile.preferences?.showORCIDId?.value + ) { + return ( + + ORCID® iD + + {renderORCIDId( + orcidState.value.orcidId, + orcidState.value.serviceInfo.runtime_info + .orcid_site_url, + )} + + + ); } } } function renderIdentityView() { - return
        - - - - - - - {renderORCIDRow()} - -
        - Username - - {props.profileView.user.username} -
        -
        + return ( +
        + + + + + + + {renderORCIDRow()} + +
        Username + + {props.profileView.user.username} + +
        +
        + ); } const { profile: { - userdata: { - affiliations: rawAffiliations - } - } - } = props.profileView + userdata: { affiliations: rawAffiliations }, + }, + } = props.profileView; // Needs to be string for the input control. - const affiliations = typeof rawAffiliations === 'undefined' ? [] : rawAffiliations - .filter(({ started, title, organization }) => { - return (title && title.length && organization && organization.length && - started); - }) - .map(({ - started, ended, title, organization - }) => { - const affiliation: FormDataAffiliation = { - title, organization, - started: String(started) - } - if (ended) { - affiliation.ended = String(ended); - } - return affiliation; - - }); + const affiliations = + typeof rawAffiliations === 'undefined' + ? [] + : rawAffiliations + .filter(({ started, title, organization }) => { + return ( + title && + title.length && + organization && + organization.length && + started + ); + }) + .map(({ started, ended, title, organization }) => { + const affiliation: FormDataAffiliation = { + title, + organization, + started: String(started), + }; + if (ended) { + affiliation.ended = String(ended); + } + return affiliation; + }); affiliations.sort((a: FormDataAffiliation, b: FormDataAffiliation) => { const startedSort = parseInt(a.started, 10) - parseInt(b.started, 10); @@ -675,50 +740,110 @@ function ProfileViewer(props: ProfileProps) { return (
        -
        +
        {renderControls()} -
        -
        - - +
        + {/* Padding below to fix antd rows with gutters. */} +
        + - + + + {props.profileView.user.realname} + + +
        + {renderIdentityView()} +
        + {renderAvatar()} +
        +
        + {/*
        {renderIdentityView()}
        {renderAvatar()} - + */} - - + + + + Research Interests + + {renderResearchInterests()} + + {/* {renderResearchInterests()} - + */} - - + + + + KBase Organizations + + + + + + {/* - + */}
        - - + + + {renderUserNutshell()} + + {/* {renderUserNutshell()} - + */} - - + + + + Research or Personal Statement + + {renderResearchStatement()} + + {/* {renderResearchStatement()} - + */} - - + + + + Affiliations + + {renderAffiliations()} + + {/* {renderAffiliations()} - + */} - +
        -
        +
        ); } diff --git a/vite-app/src/apps/UserProfile/Profile/controller.tsx b/vite-app/src/apps/UserProfile/Profile/controller.tsx index 65cd0f579..35d0dc200 100644 --- a/vite-app/src/apps/UserProfile/Profile/controller.tsx +++ b/vite-app/src/apps/UserProfile/Profile/controller.tsx @@ -1,27 +1,35 @@ -import { ErrorCode } from "apps/ORCIDLink/lib/ORCIDLinkClient"; -import ErrorMessage from "components/ErrorMessage"; -import Loading from "components/Loading"; -import { AuthenticationStateAuthenticated } from "contexts/Auth"; -import { AsyncProcess, AsyncProcessStatus } from "lib/AsyncProcess"; -import { JSONRPC20Exception } from "lib/kb_lib/comm/JSONRPC20/JSONRPC20"; -import ORCIDLinkAPI, { InfoResult } from "lib/kb_lib/comm/coreServices/ORCIDLInk"; -import { Component } from "react"; -import { Config } from "types/config"; +import { ErrorCode } from 'apps/ORCIDLink/lib/ORCIDLinkClient'; +import ErrorMessage from 'components/ErrorMessage'; +import Loading from 'components/Loading'; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { AsyncProcess, AsyncProcessStatus } from 'lib/AsyncProcess'; +// import { JSONRPC20Exception } from "lib/kb_lib/comm/JSONRPC20/JSONRPC20"; +import { JSONRPC20Exception } from 'lib/kb_lib/comm/JSONRPC20/JSONRPC20'; +import ORCIDLinkAPI, { + InfoResult, +} from 'lib/kb_lib/comm/coreServices/ORCIDLInk'; +import { Component } from 'react'; +import { Config } from 'types/config'; import { - ProfileWarnings, UserProfileBFFService, UserProfileSubset, UserProfileUpdate, - UserProfileUser, fetchProfileAPI2, updateProfileAPI -} from "../API"; -import { AsyncFetchState, AsyncFetchStatus } from "../asyncFetchState"; -import { SERVICE_CALL_TIMEOUT } from "../constants"; -import ProfileEditor from "./ProfileEditor"; -import ProfileViewer from "./ProfileViewer"; + ProfileWarnings, + UserProfileBFFService, + UserProfileSubset, + UserProfileUpdate, + UserProfileUser, + fetchProfileAPI2, + updateProfileAPI, +} from '../API'; +import { AsyncFetchState, AsyncFetchStatus } from '../asyncFetchState'; +import { SERVICE_CALL_TIMEOUT } from '../constants'; +import ProfileEditor from './ProfileEditor'; +import ProfileViewer from './ProfileViewer'; // ORCiD export type ORCIDView = { orcidId: string | null; serviceInfo: InfoResult; -} +}; export interface SimpleError { message: string; @@ -33,24 +41,25 @@ export type ORCIDState = AsyncProcess; export interface Org { name: string; - url: string; + id: string; logoURL?: string; } export type OrgsState = AsyncProcess<{ orgs: Array }, SimpleError>; - // PROFILE - export interface ProfileView { - user: UserProfileUser - profile: UserProfileSubset - editEnable: boolean, - warnings: ProfileWarnings + user: UserProfileUser; + profile: UserProfileSubset; + editEnable: boolean; + warnings: ProfileWarnings; } -export type ProfileState = AsyncFetchState<{ profileView: ProfileView }, SimpleError> +export type ProfileState = AsyncFetchState< + { profileView: ProfileView }, + SimpleError +>; export interface ProfileControllerProps { authState: AuthenticationStateAuthenticated; @@ -60,30 +69,35 @@ export interface ProfileControllerProps { } interface ProfileControllerState { - orgsState: OrgsState, - orcidState: ORCIDState, + orgsState: OrgsState; + orcidState: ORCIDState; profileState: ProfileState; isEditing: boolean; } -export default class ProfileController extends Component { +export default class ProfileController extends Component< + ProfileControllerProps, + ProfileControllerState +> { constructor(props: ProfileControllerProps) { super(props); this.state = { orgsState: { - status: AsyncProcessStatus.NONE + status: AsyncProcessStatus.NONE, }, profileState: { - status: AsyncFetchStatus.NONE + status: AsyncFetchStatus.NONE, }, orcidState: { - status: AsyncProcessStatus.NONE + status: AsyncProcessStatus.NONE, }, - isEditing: false - } + isEditing: false, + }; } componentDidMount() { + // These will all run on their own, updating state as they see fit. We don't + // need to parallelize them with Promise.any or such business. this.loadOrgs(); this.fetchProfile(this.props.username); this.checkORCID(this.props.username); @@ -92,19 +106,19 @@ export default class ProfileController extends Component { @@ -117,41 +131,38 @@ export default class ProfileController extends Component { - return { - name, - url: "/#orgs/" + id, - logoURL: custom.logourl, - }; - }); + return orgs.map(({ name, id, custom }) => { + return { + name, + id, + logoURL: custom.logourl, + }; + }); } async updateProfile(updatedProfile: UserProfileUpdate) { @@ -159,54 +170,61 @@ export default class ProfileController extends Component { if (ex instanceof Error) { @@ -237,9 +255,9 @@ export default class ProfileController extends Component { if (ex instanceof Error) { @@ -411,50 +437,60 @@ export default class ProfileController extends Component + return ; case AsyncFetchStatus.FETCHING: - return + return ; case AsyncFetchStatus.ERROR: - return + return ( + + ); case AsyncFetchStatus.REFETCHING: case AsyncFetchStatus.SUCCESS: if (this.state.isEditing) { - return + return ( + + ); } else { - return + return ( + + ); } } } diff --git a/vite-app/src/apps/UserProfile/Profile/fields/Organization.tsx b/vite-app/src/apps/UserProfile/Profile/fields/Organization.tsx index 5c5d83d9a..5d65bc34c 100644 --- a/vite-app/src/apps/UserProfile/Profile/fields/Organization.tsx +++ b/vite-app/src/apps/UserProfile/Profile/fields/Organization.tsx @@ -1,14 +1,18 @@ import { AutoComplete, Form } from 'antd'; import Search from 'antd/es/input/Search'; import React from 'react'; -import { MAX_INSTITUTIONS_TO_SHOW, MIN_ORGANIZATION_CHARS } from '../../constants'; +import { + MAX_INSTITUTIONS_TO_SHOW, + MIN_ORGANIZATION_CHARS, +} from '../../constants'; import institutions from '../../dataSources/institutions'; import { AntDesignValidationStatus } from '../../types'; import { noScriptTag } from '../../utils'; export interface OrganizationProps { name: number | string | Array; - label?: string + label?: string; + hasFeedback?: boolean; required: boolean; } @@ -16,72 +20,84 @@ interface OrganizationState { message: string; status: AntDesignValidationStatus; tooManyInstitutionsToRender: [boolean, number?]; - institutionFiltered: Array<{ value: string, label: string }>; + institutionFiltered: Array<{ value: string; label: string }>; } -export default class Organization extends React.Component { +export default class Organization extends React.Component< + OrganizationProps, + OrganizationState +> { constructor(props: OrganizationProps) { - super(props) + super(props); this.state = { message: '', status: '', tooManyInstitutionsToRender: [false], - institutionFiltered: [] + institutionFiltered: [], }; } onSearch(searchValue: string) { const searchValueLower = searchValue.toLowerCase(); if (searchValue.length >= MIN_ORGANIZATION_CHARS) { - const filtered = institutions.filter(({ value, label }) => - value.toLowerCase().includes(searchValueLower) || - label.toLowerCase().includes(searchValueLower) + const filtered = institutions.filter( + ({ value, label }) => + value.toLowerCase().includes(searchValueLower) || + label.toLowerCase().includes(searchValueLower), ); if (filtered.length <= MAX_INSTITUTIONS_TO_SHOW) { this.setState({ tooManyInstitutionsToRender: [false], - institutionFiltered: filtered + institutionFiltered: filtered, }); } else { this.setState({ tooManyInstitutionsToRender: [true, filtered.length], - institutionFiltered: [{ - value: "", label: `Too Many Institutions to Render (${filtered.length}) - keep typing!` - }] + institutionFiltered: [ + { + value: '', + label: `Too Many Institutions to Render (${filtered.length}) - keep typing!`, + }, + ], }); } } else { this.setState({ tooManyInstitutionsToRender: [false], - institutionFiltered: [{ - value: "", - label: `Enter at least ${MIN_ORGANIZATION_CHARS} characters for search - keep typing!!` - }] + institutionFiltered: [ + { + value: '', + label: `Enter at least ${MIN_ORGANIZATION_CHARS} characters for search - keep typing!!`, + }, + ], }); } } render() { - return { - noScriptTag(value); - } - } - ]} - > - { + noScriptTag(value); + }, + }, + ]} > - - - ; + + + + + ); } } diff --git a/vite-app/src/apps/UserProfile/SearchUsers/controller.tsx b/vite-app/src/apps/UserProfile/SearchUsers/controller.tsx index da8dcd74c..2a2ef5271 100644 --- a/vite-app/src/apps/UserProfile/SearchUsers/controller.tsx +++ b/vite-app/src/apps/UserProfile/SearchUsers/controller.tsx @@ -1,16 +1,20 @@ -import { SimpleError } from "components/MainWindow"; -import { AsyncSearchProcess, AsyncSearchProcessStatus } from "lib/AsyncSearchProcess"; -import { Component } from "react"; +import { + AsyncSearchProcess, + AsyncSearchProcessStatus, +} from 'lib/AsyncSearchProcess'; +import { SimpleError } from 'lib/SimpleError'; +import { Component } from 'react'; import { UserProfileUser, filteredUserAPI } from '../API'; -import { MINIMUM_SEARCH_CHARS } from "../constants"; -import { containsScriptTag } from "../utils"; -import SearchUsersView from "./view"; - +import { MINIMUM_SEARCH_CHARS } from '../constants'; +import { containsScriptTag } from '../utils'; +import SearchUsersView from './view'; // export type SearchUsersStatus = "none" | "searching" | "found" | "needmore" | "error"; -export type SearchState = AsyncSearchProcess<{ foundUsers: Array }, SimpleError>; - +export type SearchState = AsyncSearchProcess< + { foundUsers: Array }, + SimpleError +>; export interface SearchUsersControllerProps { // token: string; @@ -19,29 +23,32 @@ export interface SearchUsersControllerProps { interface SearchUsersControllerState { searchText: string; - searchState: SearchState + searchState: SearchState; // message: string; // status: SearchUsersStatus; // foundUsers: Array } -export default class SearchUsersController extends Component { +export default class SearchUsersController extends Component< + SearchUsersControllerProps, + SearchUsersControllerState +> { constructor(props: SearchUsersControllerProps) { super(props); this.state = { searchText: '', searchState: { - status: AsyncSearchProcessStatus.NONE - } - } + status: AsyncSearchProcessStatus.NONE, + }, + }; } /** - * when search value is more than 2 charactors, - * make API call and returns filtered list of users - * - * @param value - */ + * when search value is more than 2 charactors, + * make API call and returns filtered list of users + * + * @param value + */ async search(value: string) { // should never get this. if (value.length === 0) { @@ -69,34 +76,43 @@ export default class SearchUsersController extends Component + return ( + + ); } -} \ No newline at end of file +} diff --git a/vite-app/src/apps/UserProfile/SearchUsers/view.tsx b/vite-app/src/apps/UserProfile/SearchUsers/view.tsx index 39d16d082..1467d1d5d 100644 --- a/vite-app/src/apps/UserProfile/SearchUsers/view.tsx +++ b/vite-app/src/apps/UserProfile/SearchUsers/view.tsx @@ -1,5 +1,6 @@ import { Alert, Empty, Select } from 'antd'; +import { navigationPathToURL } from 'contexts/RouterContext'; import { AsyncSearchProcessStatus } from 'lib/AsyncSearchProcess'; import { Component } from 'react'; import { MINIMUM_SEARCH_CHARS } from '../constants'; @@ -7,66 +8,69 @@ import { SearchState } from './controller'; interface SearchUsersViewProps { // foundUsers: Array; - searchUsersState: SearchState + searchUsersState: SearchState; search: (value: string) => void; } export interface OptionItem { value: string; label: string; - disabled?: boolean + disabled?: boolean; } interface SearchUsersViewState { searchText: string; - message?: string + message?: string; needsMore: boolean; } export interface OptionItem { value: string; label: string; - disabled?: boolean + disabled?: boolean; } - /** * View component with user search feature. * @param props */ -export default class SearchUsersView extends Component { +export default class SearchUsersView extends Component< + SearchUsersViewProps, + SearchUsersViewState +> { constructor(props: SearchUsersViewProps) { super(props); this.state = { searchText: '', - needsMore: true + needsMore: true, }; } - onChangeHandler(value: string): void { if (value.length === 0) { return; } - const url = `/#user/${value}`; + const url = navigationPathToURL( + { path: `user/${value}`, type: 'kbaseui' }, + true, + ); window.open(url, '_blank'); } onSearch(value: string): void { if (value.length < MINIMUM_SEARCH_CHARS) { this.setState({ - needsMore: true + needsMore: true, }); return; } this.setState({ - needsMore: false + needsMore: false, }); this.props.search(value); } render() { - const options: Array = ((): Array => { if (this.state.needsMore) { return []; @@ -78,31 +82,51 @@ export default class SearchUsersView extends Component { - return { - value: username, - label: `${realname} (${username})` - }; - }); + return this.props.searchUsersState.value.foundUsers.map( + ({ username, realname }) => { + return { + value: username, + label: `${realname} (${username})`, + }; + }, + ); } })(); const notFoundContent = (() => { if (this.state.needsMore) { - return + return ( + + ); } switch (this.props.searchUsersState.status) { case AsyncSearchProcessStatus.NONE: return; case AsyncSearchProcessStatus.ERROR: - return + return ; case AsyncSearchProcessStatus.PENDING: case AsyncSearchProcessStatus.SUCCESS: - if (this.props.searchUsersState.value.foundUsers.length === 0) { + if ( + this.props.searchUsersState.value.foundUsers.length === + 0 + ) { if (this.state.searchText.length === 0) { - return + return ( + + ); } - return + return ( + + ); } } })(); @@ -124,4 +148,3 @@ export default class SearchUsersView extends Component { status: AsyncFetchStatus.REFETCHING; - value: T + value: T; } export interface AsyncFetchStateSuccess { status: AsyncFetchStatus.SUCCESS; - value: T + value: T; } export interface AsyncFetchStateError { status: AsyncFetchStatus.ERROR; - error: E + error: E; } export type AsyncFetchState = - AsyncFetchStateNone | - AsyncFetchStateFetching | - AsyncFetchStateSuccess | - AsyncFetchStateRefetching | - AsyncFetchStateError; + | AsyncFetchStateNone + | AsyncFetchStateFetching + | AsyncFetchStateSuccess + | AsyncFetchStateRefetching + | AsyncFetchStateError; diff --git a/vite-app/src/apps/UserProfile/constants.ts b/vite-app/src/apps/UserProfile/constants.ts index 7dcccceba..416bc5f12 100644 --- a/vite-app/src/apps/UserProfile/constants.ts +++ b/vite-app/src/apps/UserProfile/constants.ts @@ -17,9 +17,4 @@ export const DEFAULT_MAX_TEXT_LENGTH = 1000; export const SERVICE_CALL_TIMEOUT = 10000; - - export const MINIMUM_SEARCH_CHARS = 3; - -// TODO: move to config? -export const ORCID_URL = 'https://sandbox.orcid.org'; \ No newline at end of file diff --git a/vite-app/src/apps/UserProfile/dataSources/USStates.ts b/vite-app/src/apps/UserProfile/dataSources/USStates.ts index 3d401af15..2dd3f7338 100644 --- a/vite-app/src/apps/UserProfile/dataSources/USStates.ts +++ b/vite-app/src/apps/UserProfile/dataSources/USStates.ts @@ -3,7 +3,7 @@ import statesData from './data/USStatesData.json'; const states = statesData as unknown as Array; const options = states.map((value) => { - return { value, label: value } -}) + return { value, label: value }; +}); export { options, states }; diff --git a/vite-app/src/apps/UserProfile/dataSources/avatarOptions.ts b/vite-app/src/apps/UserProfile/dataSources/avatarOptions.ts index 1aa91c45f..dc04e0542 100644 --- a/vite-app/src/apps/UserProfile/dataSources/avatarOptions.ts +++ b/vite-app/src/apps/UserProfile/dataSources/avatarOptions.ts @@ -1,13 +1,14 @@ const avatarOptions = [ { - "value": "gravatar", - "label": "Gravatar", - "description": "Image from Gravatar service" - }, { - "value": "silhouette", - "label": "silhouette", - "description": "Anonymous portrait" - } + value: 'gravatar', + label: 'Gravatar', + description: 'Image from Gravatar service', + }, + { + value: 'silhouette', + label: 'silhouette', + description: 'Anonymous portrait', + }, ]; -export default avatarOptions; \ No newline at end of file +export default avatarOptions; diff --git a/vite-app/src/apps/UserProfile/dataSources/data/USStatesData.json b/vite-app/src/apps/UserProfile/dataSources/data/USStatesData.json index 440cb65c2..5c9b4cdf9 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/USStatesData.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/USStatesData.json @@ -58,4 +58,4 @@ "West Virginia", "Wisconsin", "Wyoming" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/countryCodesData.json b/vite-app/src/apps/UserProfile/dataSources/data/countryCodesData.json index 550d5a1ba..00f21b3d5 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/countryCodesData.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/countryCodesData.json @@ -1,994 +1,250 @@ [ - [ - "Andorra", - "and" - ], - [ - "Afghanistan", - "afg" - ], - [ - "Antigua and Barbuda", - "atg" - ], - [ - "Anguilla", - "aia" - ], - [ - "Albania", - "alb" - ], - [ - "Armenia", - "arm" - ], - [ - "Angola", - "ago" - ], - [ - "Antarctica", - "ata" - ], - [ - "Argentina", - "arg" - ], - [ - "American Samoa", - "asm" - ], - [ - "Australia", - "aus" - ], - [ - "Aruba", - "abw" - ], - [ - "Åland Islands", - "ala" - ], - [ - "Azerbaijan", - "aze" - ], - [ - "Austria", - "aut" - ], - [ - "Algeria", - "dza" - ], - [ - "Bahamas", - "bhs" - ], - [ - "Bahrain", - "bhr" - ], - [ - "Bangladesh", - "bgd" - ], - [ - "Barbados", - "brb" - ], - [ - "Belarus", - "blr" - ], - [ - "Belgium", - "bel" - ], - [ - "Belize", - "blz" - ], - [ - "Benin", - "ben" - ], - [ - "Bermuda", - "bmu" - ], - [ - "Bhutan", - "btn" - ], - [ - "Plurinational State of Bolivia", - "bol" - ], - [ - "Sint Eustatius and Saba Bonaire", - "bes" - ], - [ - "Bosnia and Herzegowina", - "bih" - ], - [ - "Botswana", - "bwa" - ], - [ - "Bouvet Island", - "bvt" - ], - [ - "Brazil", - "bra" - ], - [ - "British Indian Ocean Territory", - "iot" - ], - [ - "Brunei Darussalam", - "brn" - ], - [ - "Bulgaria", - "bgr" - ], - [ - "Burkina Faso", - "bfa" - ], - [ - "Burundi", - "bdi" - ], - [ - "Cambodia", - "khm" - ], - [ - "Cameroon", - "cmr" - ], - [ - "Canada", - "can" - ], - [ - "Cape Verde", - "cpv" - ], - [ - "Cayman Islands", - "cym" - ], - [ - "Central African Republic", - "caf" - ], - [ - "Chad", - "tcd" - ], - [ - "Chile", - "chl" - ], - [ - "China", - "chn" - ], - [ - "Christmas Island", - "cxr" - ], - [ - "Cocos Islands", - "cck" - ], - [ - "Colombia", - "col" - ], - [ - "Comoros", - "com" - ], - [ - "Congo", - "cog" - ], - [ - "The Democratic Republic of The Congo", - "cod" - ], - [ - "Cook Islands", - "cok" - ], - [ - "Costa Rica", - "cri" - ], - [ - "Côte d'Ivoire", - "civ" - ], - [ - "Croatia ", - "hrv" - ], - [ - "Cuba", - "cub" - ], - [ - "Curaçao", - "cuw" - ], - [ - "Cyprus", - "cyp" - ], - [ - "Czech Republic", - "cze" - ], - [ - "Denmark", - "dnk" - ], - [ - "Djibouti", - "dji" - ], - [ - "Dominica", - "dma" - ], - [ - "Dominican Republic", - "dom" - ], - [ - "Ecuador", - "ecu" - ], - [ - "Egypt", - "egy" - ], - [ - "El Salvador", - "slv" - ], - [ - "Equatorial Guinea", - "gnq" - ], - [ - "Eritrea", - "eri" - ], - [ - "Estonia", - "est" - ], - [ - "Ethiopia", - "eth" - ], - [ - "Falkland Islands ", - "flk" - ], - [ - "Faroe Islands", - "fro" - ], - [ - "Fiji", - "fji" - ], - [ - "Finland", - "fin" - ], - [ - "France", - "fra" - ], - [ - "French Guiana", - "guf" - ], - [ - "French Polynesia", - "pyf" - ], - [ - "French Southern Territories", - "atf" - ], - [ - "Gabon", - "gab" - ], - [ - "Gambia", - "gmb" - ], - [ - "Georgia", - "geo" - ], - [ - "Germany", - "deu" - ], - [ - "Ghana", - "gha" - ], - [ - "Gibraltar", - "gib" - ], - [ - "Greece", - "grc" - ], - [ - "Greenland", - "grl" - ], - [ - "Grenada", - "grd" - ], - [ - "Guadeloupe", - "glp" - ], - [ - "Guam", - "gum" - ], - [ - "Guatemala", - "gtm" - ], - [ - "Guernsey", - "ggy" - ], - [ - "Guinea", - "gin" - ], - [ - "Guinea-bissau", - "gnb" - ], - [ - "Guyana", - "guy" - ], - [ - "Haiti", - "hti" - ], - [ - "Heard and McDonald Islands", - "hmd" - ], - [ - "Holy See ", - "vat" - ], - [ - "Honduras", - "hnd" - ], - [ - "Hong Kong", - "hkg" - ], - [ - "Hungary", - "hun" - ], - [ - "Iceland", - "isl" - ], - [ - "India", - "ind" - ], - [ - "Indonesia", - "idn" - ], - [ - "Iran ", - "irn" - ], - [ - "Iraq", - "irq" - ], - [ - "Ireland", - "irl" - ], - [ - "Isle of Man", - "imn" - ], - [ - "Israel", - "isr" - ], - [ - "Italy", - "ita" - ], - [ - "Jamaica", - "jam" - ], - [ - "Japan", - "jpn" - ], - [ - "Jersey", - "jey" - ], - [ - "Jordan", - "jor" - ], - [ - "Kazakhstan", - "kaz" - ], - [ - "Kenya", - "ken" - ], - [ - "Kiribati", - "kir" - ], - [ - "Democratic People's Republic of Korea", - "prk" - ], - [ - "Republic of Korea", - "kor" - ], - [ - "Kuwait", - "kwt" - ], - [ - "Kyrgyzstan", - "kgz" - ], - [ - "Lao People's Democratic Republic", - "lao" - ], - [ - "Latvia", - "lva" - ], - [ - "Lebanon", - "lbn" - ], - [ - "Lesotho", - "lso" - ], - [ - "Liberia", - "lbr" - ], - [ - "Libya", - "lby" - ], - [ - "Liechtenstein", - "lie" - ], - [ - "Lithuania", - "ltu" - ], - [ - "Luxembourg", - "lux" - ], - [ - "Macao", - "mac" - ], - [ - "The Former Yugoslav Republic of Macedonia", - "mkd" - ], - [ - "Madagascar", - "mdg" - ], - [ - "Malawi", - "mwi" - ], - [ - "Malaysia", - "mys" - ], - [ - "Maldives", - "mdv" - ], - [ - "Mali", - "mli" - ], - [ - "Malta", - "mlt" - ], - [ - "Marshall Islands", - "mhl" - ], - [ - "Martinique", - "mtq" - ], - [ - "Mauritania", - "mrt" - ], - [ - "Mauritius", - "mus" - ], - [ - "Mayotte", - "myt" - ], - [ - "Mexico", - "mex" - ], - [ - "Federated States of Micronesia", - "fsm" - ], - [ - "Republic of Moldova", - "mda" - ], - [ - "Monaco", - "mco" - ], - [ - "Mongolia", - "mng" - ], - [ - "Montenegro", - "mne" - ], - [ - "Montserrat", - "msr" - ], - [ - "Morocco", - "mar" - ], - [ - "Mozambique", - "moz" - ], - [ - "Myanmar", - "mmr" - ], - [ - "Namibia", - "nam" - ], - [ - "Nauru", - "nru" - ], - [ - "Nepal", - "npl" - ], - [ - "Netherlands", - "nld" - ], - [ - "New Caledonia", - "ncl" - ], - [ - "New Zealand", - "nzl" - ], - [ - "Nicaragua", - "nic" - ], - [ - "Niger", - "ner" - ], - [ - "Nigeria", - "nga" - ], - [ - "Niue", - "niu" - ], - [ - "Norfolk Island", - "nfk" - ], - [ - "Northern Mariana Islands", - "mnp" - ], - [ - "Norway", - "nor" - ], - [ - "Oman", - "omn" - ], - [ - "Pakistan", - "pak" - ], - [ - "Palau", - "plw" - ], - [ - "State of Palestine", - "pse" - ], - [ - "Panama", - "pan" - ], - [ - "Papua New Guinea", - "png" - ], - [ - "Paraguay", - "pry" - ], - [ - "Peru", - "per" - ], - [ - "Philippines", - "phl" - ], - [ - "Pitcairn", - "pcn" - ], - [ - "Poland", - "pol" - ], - [ - "Portugal", - "prt" - ], - [ - "Puerto Rico", - "pri" - ], - [ - "Qatar", - "qat" - ], - [ - "Réunion", - "reu" - ], - [ - "Romania", - "rou" - ], - [ - "Russian Federation", - "rus" - ], - [ - "Rwanda", - "rwa" - ], - [ - "Ascension and Tristan Da Cunha Saint Helena", - "shn" - ], - [ - "Saint Barthélemy", - "blm" - ], - [ - "Saint Kitts and Nevis", - "kna" - ], - [ - "Saint Lucia", - "lca" - ], - [ - "Saint Pierre and Miquelon", - "spm" - ], - [ - "Saint Vincent and The Grenadines", - "vct" - ], - [ - "Samoa", - "wsm" - ], - [ - "San Marino", - "smr" - ], - [ - "Sao Tome and Principe", - "stp" - ], - [ - "Saudi Arabia", - "sau" - ], - [ - "Senegal", - "sen" - ], - [ - "Serbia", - "srb" - ], - [ - "Seychelles", - "syc" - ], - [ - "Sierra Leone", - "sle" - ], - [ - "Singapore", - "sgp" - ], - [ - "Sint Maarten ", - "sxm" - ], - [ - "Slovakia", - "svk" - ], - [ - "Slovenia", - "svn" - ], - [ - "Solomon Islands", - "slb" - ], - [ - "Somalia", - "som" - ], - [ - "South Africa", - "zaf" - ], - [ - "South Georgia and The South Sandwich Islands", - "sgs" - ], - [ - "South Sudan", - "ssd" - ], - [ - "Spain", - "esp" - ], - [ - "Sri Lanka", - "lka" - ], - [ - "Sudan", - "sdn" - ], - [ - "Suriname", - "sur" - ], - [ - "Svalbard and Jan Mayen Islands", - "sjm" - ], - [ - "Swaziland", - "swz" - ], - [ - "Sweden", - "swe" - ], - [ - "Switzerland", - "che" - ], - [ - "Syrian Arab Republic", - "syr" - ], - [ - "Province of China Taiwan", - "twn" - ], - [ - "Tajikistan", - "tjk" - ], - [ - "United Republic of Tanzania", - "tza" - ], - [ - "Thailand", - "tha" - ], - [ - "Timor-leste", - "tls" - ], - [ - "Togo", - "tgo" - ], - [ - "Tokelau", - "tkl" - ], - [ - "Tonga", - "ton" - ], - [ - "Trinidad and Tobago", - "tto" - ], - [ - "Tunisia", - "tun" - ], - [ - "Turkey", - "tur" - ], - [ - "Turkmenistan", - "tkm" - ], - [ - "Turks and Caicos Islands", - "tca" - ], - [ - "Tuvalu", - "tuv" - ], - [ - "Uganda", - "uga" - ], - [ - "Ukraine", - "ukr" - ], - [ - "United Arab Emirates", - "are" - ], - [ - "United Kingdom", - "gbr" - ], - [ - "United States", - "usa" - ], - [ - "United States Minor Outlying Islands", - "umi" - ], - [ - "Uruguay", - "ury" - ], - [ - "Uzbekistan", - "uzb" - ], - [ - "Vanuatu", - "vut" - ], - [ - "Bolivarian Republic of Venezuela", - "ven" - ], - [ - "Vietnam", - "vnm" - ], - [ - "Virgin Islands (British)", - "vgb" - ], - [ - "Virgin Islands (US)", - "vir" - ], - [ - "Wallis and Futuna Islands", - "wlf" - ], - [ - "Western Sahara", - "esh" - ], - [ - "Yemen", - "yem" - ], - [ - "Zambia", - "zmb" - ], - [ - "Zimbabwe", - "zwe" - ] -] \ No newline at end of file + ["Andorra", "and"], + ["Afghanistan", "afg"], + ["Antigua and Barbuda", "atg"], + ["Anguilla", "aia"], + ["Albania", "alb"], + ["Armenia", "arm"], + ["Angola", "ago"], + ["Antarctica", "ata"], + ["Argentina", "arg"], + ["American Samoa", "asm"], + ["Australia", "aus"], + ["Aruba", "abw"], + ["Åland Islands", "ala"], + ["Azerbaijan", "aze"], + ["Austria", "aut"], + ["Algeria", "dza"], + ["Bahamas", "bhs"], + ["Bahrain", "bhr"], + ["Bangladesh", "bgd"], + ["Barbados", "brb"], + ["Belarus", "blr"], + ["Belgium", "bel"], + ["Belize", "blz"], + ["Benin", "ben"], + ["Bermuda", "bmu"], + ["Bhutan", "btn"], + ["Plurinational State of Bolivia", "bol"], + ["Sint Eustatius and Saba Bonaire", "bes"], + ["Bosnia and Herzegowina", "bih"], + ["Botswana", "bwa"], + ["Bouvet Island", "bvt"], + ["Brazil", "bra"], + ["British Indian Ocean Territory", "iot"], + ["Brunei Darussalam", "brn"], + ["Bulgaria", "bgr"], + ["Burkina Faso", "bfa"], + ["Burundi", "bdi"], + ["Cambodia", "khm"], + ["Cameroon", "cmr"], + ["Canada", "can"], + ["Cape Verde", "cpv"], + ["Cayman Islands", "cym"], + ["Central African Republic", "caf"], + ["Chad", "tcd"], + ["Chile", "chl"], + ["China", "chn"], + ["Christmas Island", "cxr"], + ["Cocos Islands", "cck"], + ["Colombia", "col"], + ["Comoros", "com"], + ["Congo", "cog"], + ["The Democratic Republic of The Congo", "cod"], + ["Cook Islands", "cok"], + ["Costa Rica", "cri"], + ["Côte d'Ivoire", "civ"], + ["Croatia ", "hrv"], + ["Cuba", "cub"], + ["Curaçao", "cuw"], + ["Cyprus", "cyp"], + ["Czech Republic", "cze"], + ["Denmark", "dnk"], + ["Djibouti", "dji"], + ["Dominica", "dma"], + ["Dominican Republic", "dom"], + ["Ecuador", "ecu"], + ["Egypt", "egy"], + ["El Salvador", "slv"], + ["Equatorial Guinea", "gnq"], + ["Eritrea", "eri"], + ["Estonia", "est"], + ["Ethiopia", "eth"], + ["Falkland Islands ", "flk"], + ["Faroe Islands", "fro"], + ["Fiji", "fji"], + ["Finland", "fin"], + ["France", "fra"], + ["French Guiana", "guf"], + ["French Polynesia", "pyf"], + ["French Southern Territories", "atf"], + ["Gabon", "gab"], + ["Gambia", "gmb"], + ["Georgia", "geo"], + ["Germany", "deu"], + ["Ghana", "gha"], + ["Gibraltar", "gib"], + ["Greece", "grc"], + ["Greenland", "grl"], + ["Grenada", "grd"], + ["Guadeloupe", "glp"], + ["Guam", "gum"], + ["Guatemala", "gtm"], + ["Guernsey", "ggy"], + ["Guinea", "gin"], + ["Guinea-bissau", "gnb"], + ["Guyana", "guy"], + ["Haiti", "hti"], + ["Heard and McDonald Islands", "hmd"], + ["Holy See ", "vat"], + ["Honduras", "hnd"], + ["Hong Kong", "hkg"], + ["Hungary", "hun"], + ["Iceland", "isl"], + ["India", "ind"], + ["Indonesia", "idn"], + ["Iran ", "irn"], + ["Iraq", "irq"], + ["Ireland", "irl"], + ["Isle of Man", "imn"], + ["Israel", "isr"], + ["Italy", "ita"], + ["Jamaica", "jam"], + ["Japan", "jpn"], + ["Jersey", "jey"], + ["Jordan", "jor"], + ["Kazakhstan", "kaz"], + ["Kenya", "ken"], + ["Kiribati", "kir"], + ["Democratic People's Republic of Korea", "prk"], + ["Republic of Korea", "kor"], + ["Kuwait", "kwt"], + ["Kyrgyzstan", "kgz"], + ["Lao People's Democratic Republic", "lao"], + ["Latvia", "lva"], + ["Lebanon", "lbn"], + ["Lesotho", "lso"], + ["Liberia", "lbr"], + ["Libya", "lby"], + ["Liechtenstein", "lie"], + ["Lithuania", "ltu"], + ["Luxembourg", "lux"], + ["Macao", "mac"], + ["The Former Yugoslav Republic of Macedonia", "mkd"], + ["Madagascar", "mdg"], + ["Malawi", "mwi"], + ["Malaysia", "mys"], + ["Maldives", "mdv"], + ["Mali", "mli"], + ["Malta", "mlt"], + ["Marshall Islands", "mhl"], + ["Martinique", "mtq"], + ["Mauritania", "mrt"], + ["Mauritius", "mus"], + ["Mayotte", "myt"], + ["Mexico", "mex"], + ["Federated States of Micronesia", "fsm"], + ["Republic of Moldova", "mda"], + ["Monaco", "mco"], + ["Mongolia", "mng"], + ["Montenegro", "mne"], + ["Montserrat", "msr"], + ["Morocco", "mar"], + ["Mozambique", "moz"], + ["Myanmar", "mmr"], + ["Namibia", "nam"], + ["Nauru", "nru"], + ["Nepal", "npl"], + ["Netherlands", "nld"], + ["New Caledonia", "ncl"], + ["New Zealand", "nzl"], + ["Nicaragua", "nic"], + ["Niger", "ner"], + ["Nigeria", "nga"], + ["Niue", "niu"], + ["Norfolk Island", "nfk"], + ["Northern Mariana Islands", "mnp"], + ["Norway", "nor"], + ["Oman", "omn"], + ["Pakistan", "pak"], + ["Palau", "plw"], + ["State of Palestine", "pse"], + ["Panama", "pan"], + ["Papua New Guinea", "png"], + ["Paraguay", "pry"], + ["Peru", "per"], + ["Philippines", "phl"], + ["Pitcairn", "pcn"], + ["Poland", "pol"], + ["Portugal", "prt"], + ["Puerto Rico", "pri"], + ["Qatar", "qat"], + ["Réunion", "reu"], + ["Romania", "rou"], + ["Russian Federation", "rus"], + ["Rwanda", "rwa"], + ["Ascension and Tristan Da Cunha Saint Helena", "shn"], + ["Saint Barthélemy", "blm"], + ["Saint Kitts and Nevis", "kna"], + ["Saint Lucia", "lca"], + ["Saint Pierre and Miquelon", "spm"], + ["Saint Vincent and The Grenadines", "vct"], + ["Samoa", "wsm"], + ["San Marino", "smr"], + ["Sao Tome and Principe", "stp"], + ["Saudi Arabia", "sau"], + ["Senegal", "sen"], + ["Serbia", "srb"], + ["Seychelles", "syc"], + ["Sierra Leone", "sle"], + ["Singapore", "sgp"], + ["Sint Maarten ", "sxm"], + ["Slovakia", "svk"], + ["Slovenia", "svn"], + ["Solomon Islands", "slb"], + ["Somalia", "som"], + ["South Africa", "zaf"], + ["South Georgia and The South Sandwich Islands", "sgs"], + ["South Sudan", "ssd"], + ["Spain", "esp"], + ["Sri Lanka", "lka"], + ["Sudan", "sdn"], + ["Suriname", "sur"], + ["Svalbard and Jan Mayen Islands", "sjm"], + ["Swaziland", "swz"], + ["Sweden", "swe"], + ["Switzerland", "che"], + ["Syrian Arab Republic", "syr"], + ["Province of China Taiwan", "twn"], + ["Tajikistan", "tjk"], + ["United Republic of Tanzania", "tza"], + ["Thailand", "tha"], + ["Timor-leste", "tls"], + ["Togo", "tgo"], + ["Tokelau", "tkl"], + ["Tonga", "ton"], + ["Trinidad and Tobago", "tto"], + ["Tunisia", "tun"], + ["Turkey", "tur"], + ["Turkmenistan", "tkm"], + ["Turks and Caicos Islands", "tca"], + ["Tuvalu", "tuv"], + ["Uganda", "uga"], + ["Ukraine", "ukr"], + ["United Arab Emirates", "are"], + ["United Kingdom", "gbr"], + ["United States", "usa"], + ["United States Minor Outlying Islands", "umi"], + ["Uruguay", "ury"], + ["Uzbekistan", "uzb"], + ["Vanuatu", "vut"], + ["Bolivarian Republic of Venezuela", "ven"], + ["Vietnam", "vnm"], + ["Virgin Islands (British)", "vgb"], + ["Virgin Islands (US)", "vir"], + ["Wallis and Futuna Islands", "wlf"], + ["Western Sahara", "esh"], + ["Yemen", "yem"], + ["Zambia", "zmb"], + ["Zimbabwe", "zwe"] +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/fundingSourcesData.json b/vite-app/src/apps/UserProfile/dataSources/data/fundingSourcesData.json index b10bf19b5..1dcc8663d 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/fundingSourcesData.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/fundingSourcesData.json @@ -38,4 +38,4 @@ "Federally Funded Research and Development Center (FFRDC) - (Specify)", "None", "Other" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/higherEdData.json b/vite-app/src/apps/UserProfile/dataSources/data/higherEdData.json index 3f74719bf..014477629 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/higherEdData.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/higherEdData.json @@ -4320,4 +4320,4 @@ "YTI Career Institute-Altoona", "YTI Career Institute-York", "Yuba College,Zane State College" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/jobTitles.json b/vite-app/src/apps/UserProfile/dataSources/data/jobTitles.json index bd150283d..28506fd28 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/jobTitles.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/jobTitles.json @@ -14,4 +14,4 @@ "Professor", "Physician", "Other" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/nationalLabsData.json b/vite-app/src/apps/UserProfile/dataSources/data/nationalLabsData.json index 1dba073d6..fee1efa81 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/nationalLabsData.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/nationalLabsData.json @@ -16,4 +16,4 @@ "Los Alamos National Laboratory (LANL)", "Sandia National Laboratory(SNL)", "Thomas Jefferson National Accelerator Facility(TJNAF)" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/data/researchInterests.json b/vite-app/src/apps/UserProfile/dataSources/data/researchInterests.json index 03029f275..674de5fd8 100644 --- a/vite-app/src/apps/UserProfile/dataSources/data/researchInterests.json +++ b/vite-app/src/apps/UserProfile/dataSources/data/researchInterests.json @@ -9,4 +9,4 @@ "Sequence Analysis", "Utilities", "Other" -] \ No newline at end of file +] diff --git a/vite-app/src/apps/UserProfile/dataSources/fundingSources.ts b/vite-app/src/apps/UserProfile/dataSources/fundingSources.ts index aef5504a6..432028ead 100644 --- a/vite-app/src/apps/UserProfile/dataSources/fundingSources.ts +++ b/vite-app/src/apps/UserProfile/dataSources/fundingSources.ts @@ -3,7 +3,7 @@ import fundingSourcesData from './data/fundingSourcesData.json'; const fundingSources = fundingSourcesData as unknown as Array; const options = fundingSources.sort().map((value) => { - return { value, label: value } -}) + return { value, label: value }; +}); export { fundingSources, options }; diff --git a/vite-app/src/apps/UserProfile/dataSources/gravatarDefaults.ts b/vite-app/src/apps/UserProfile/dataSources/gravatarDefaults.ts index 48a8a3410..0563b845b 100644 --- a/vite-app/src/apps/UserProfile/dataSources/gravatarDefaults.ts +++ b/vite-app/src/apps/UserProfile/dataSources/gravatarDefaults.ts @@ -1,13 +1,15 @@ const gravatarDefaults = [ { - "value": "404", - "label": "404", - "description": "do not load any image if none is associated with the email hash, instead return an HTTP 404 (File Not Found) response" + value: '404', + label: '404', + description: + 'do not load any image if none is associated with the email hash, instead return an HTTP 404 (File Not Found) response', }, { - "value": "mp", - "label": "Mystery Person", - "description": "(mystery-person) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)e" + value: 'mp', + label: 'Mystery Person', + description: + '(mystery-person) a simple, cartoon-style silhouetted outline of a person (does not vary by email hash)e', }, // { // "value": "mm", @@ -15,30 +17,30 @@ const gravatarDefaults = [ // "description": "simple, cartoon-style silhouetted outline" // }, { - "value": "identicon", - "label": "Identicon", - "description": "a geometric pattern based on an email hash" + value: 'identicon', + label: 'Identicon', + description: 'a geometric pattern based on an email hash', }, { - "value": "monsterid", - "label": "MonsterID", - "description": "generated \"monster\" with different colors, faces, etc" + value: 'monsterid', + label: 'MonsterID', + description: 'generated "monster" with different colors, faces, etc', }, { - "value": "wavatar", - "label": "Wavatar", - "description": "generated faces with differing features and backgrounds" + value: 'wavatar', + label: 'Wavatar', + description: 'generated faces with differing features and backgrounds', }, { - "value": "retro", - "label": "Retro", - "description": "8-bit arcade-style pixelated faces" + value: 'retro', + label: 'Retro', + description: '8-bit arcade-style pixelated faces', }, { - "value": "robohash", - "label": "Robohash", - "description": "a generated robot with different colors, faces, etcs" - } + value: 'robohash', + label: 'Robohash', + description: 'a generated robot with different colors, faces, etcs', + }, ]; -export default gravatarDefaults \ No newline at end of file +export default gravatarDefaults; diff --git a/vite-app/src/apps/UserProfile/dataSources/institutions.ts b/vite-app/src/apps/UserProfile/dataSources/institutions.ts index 65b374fc4..e7c583872 100644 --- a/vite-app/src/apps/UserProfile/dataSources/institutions.ts +++ b/vite-app/src/apps/UserProfile/dataSources/institutions.ts @@ -4,8 +4,11 @@ import nationalLabsData from './data/nationalLabsData.json'; const nationalLabs = nationalLabsData as unknown as Array; const higherEd = higherEdData as unknown as Array; -const institutions = nationalLabs.concat(higherEd).sort().map((value) => { - return { value, label: value } -}); +const institutions = nationalLabs + .concat(higherEd) + .sort() + .map((value) => { + return { value, label: value }; + }); export default institutions; diff --git a/vite-app/src/apps/UserProfile/dataSources/jobTitlesOptions.ts b/vite-app/src/apps/UserProfile/dataSources/jobTitlesOptions.ts index 0510d17bf..fc79e70f0 100644 --- a/vite-app/src/apps/UserProfile/dataSources/jobTitlesOptions.ts +++ b/vite-app/src/apps/UserProfile/dataSources/jobTitlesOptions.ts @@ -3,8 +3,8 @@ import jobTitles from './data/jobTitles.json'; const options = jobTitles.map((option) => { return { value: option, - label: option + label: option, }; }); -export default options; \ No newline at end of file +export default options; diff --git a/vite-app/src/apps/UserProfile/dataSources/listOfHigherEd.ts b/vite-app/src/apps/UserProfile/dataSources/listOfHigherEd.ts index e739536f5..f5ace7b66 100644 --- a/vite-app/src/apps/UserProfile/dataSources/listOfHigherEd.ts +++ b/vite-app/src/apps/UserProfile/dataSources/listOfHigherEd.ts @@ -1,3 +1,3 @@ import higherEdData from './data/higherEdData.json'; -export const higherEd = higherEdData as Array; \ No newline at end of file +export const higherEd = higherEdData as Array; diff --git a/vite-app/src/apps/UserProfile/dataSources/researchInterestsOptions.ts b/vite-app/src/apps/UserProfile/dataSources/researchInterestsOptions.ts index 7524aa28a..61b2933d7 100644 --- a/vite-app/src/apps/UserProfile/dataSources/researchInterestsOptions.ts +++ b/vite-app/src/apps/UserProfile/dataSources/researchInterestsOptions.ts @@ -3,8 +3,8 @@ import researchInterests from './data/researchInterests.json'; const options = researchInterests.map((option) => { return { value: option, - label: option + label: option, }; }); -export default options; \ No newline at end of file +export default options; diff --git a/vite-app/src/apps/UserProfile/index.module.css b/vite-app/src/apps/UserProfile/index.module.css index 0f87742b6..cc8664236 100644 --- a/vite-app/src/apps/UserProfile/index.module.css +++ b/vite-app/src/apps/UserProfile/index.module.css @@ -4,4 +4,4 @@ display: flex; flex-direction: column; min-height: 0; -} \ No newline at end of file +} diff --git a/vite-app/src/apps/UserProfile/index.tsx b/vite-app/src/apps/UserProfile/index.tsx index b90cc1067..25fd4e40f 100644 --- a/vite-app/src/apps/UserProfile/index.tsx +++ b/vite-app/src/apps/UserProfile/index.tsx @@ -1,8 +1,8 @@ import { Tabs, TabsProps } from 'antd'; import { RouteProps } from 'components/Router2'; -import { AuthenticationStateAuthenticated } from "contexts/Auth"; -import { Component } from "react"; -import { Config } from "types/config"; +import { AuthenticationStateAuthenticated } from 'contexts/EuropaContext'; +import { Component } from 'react'; +import { Config } from 'types/config'; import NarrativesController from './Narratives/controller'; import ProfileController from './Profile/controller'; import SearchUsersController from './SearchUsers/controller'; @@ -11,51 +11,69 @@ import styles from './index.module.css'; export interface UserProfileProps extends RouteProps { authState: AuthenticationStateAuthenticated; config: Config; - username: string, + username: string; setTitle: (title: string) => void; } -interface UserProfileState { +interface UserProfileState {} -} - -export default class UserProfile extends Component { +export default class UserProfile extends Component< + UserProfileProps, + UserProfileState +> { componentDidMount(): void { - this.props.setTitle('User Profile - IN PROGRESS'); + this.props.setTitle('User Profile'); } renderUserSearch() { const { services: { - UserProfile: { - url - } - } + UserProfile: { url }, + }, } = this.props.config; - return
        Search for users
        ; + return ( +
        + Search for users +
        + ); } render() { + const username = + this.props.username || this.props.authState.authInfo.account.user; - const username = this.props.username || this.props.authState.authInfo.account.user; + const items: TabsProps['items'] = [ + { + key: 'profile', + label: 'Profile', + children: ( + + ), + }, + { + key: 'narratives', + label: 'Narratives', + children: ( + + ), + }, + ]; - const items: TabsProps['items'] = [{ - key: 'profile', - label: 'Profile', - children: - }, { - key: 'narratives', - label: 'Narratives', - children: - }] return (
        - ); } -} \ No newline at end of file +} diff --git a/vite-app/src/apps/UserProfile/types.ts b/vite-app/src/apps/UserProfile/types.ts index 4d7bd7466..bc2b5a5b9 100644 --- a/vite-app/src/apps/UserProfile/types.ts +++ b/vite-app/src/apps/UserProfile/types.ts @@ -1,4 +1,10 @@ -export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; +export type JSONValue = + | string + | number + | boolean + | null + | JSONObject + | JSONArray; // export interface JSONArray extends Array { }; export type JSONArray = Array; @@ -7,14 +13,12 @@ export interface JSONObject { [x: string]: JSONValue; } - - export enum ValidationStatus { NONE, SUCCESS, ERROR, WARNING, - VALIDATING + VALIDATING, } export interface ValidationStateBase { @@ -22,12 +26,12 @@ export interface ValidationStateBase { } export interface ValidationStateSuccess extends ValidationStateBase { - status: ValidationStatus.SUCCESS, + status: ValidationStatus.SUCCESS; value: T; } export interface ValidationStateError extends ValidationStateBase { - status: ValidationStatus.ERROR, + status: ValidationStatus.ERROR; message: string; } @@ -44,11 +48,16 @@ export interface ValidationStateNone extends ValidationStateBase { } export type ValidationState = - ValidationStateSuccess | - ValidationStateError | - ValidationStateWarning | - ValidationStateValidating | - ValidationStateNone; - - -export type AntDesignValidationStatus = "" | "error" | "success" | "warning" | "validating" | undefined; + | ValidationStateSuccess + | ValidationStateError + | ValidationStateWarning + | ValidationStateValidating + | ValidationStateNone; + +export type AntDesignValidationStatus = + | '' + | 'error' + | 'success' + | 'warning' + | 'validating' + | undefined; diff --git a/vite-app/src/apps/UserProfile/utils.ts b/vite-app/src/apps/UserProfile/utils.ts index 92a60f791..870f7f26e 100644 --- a/vite-app/src/apps/UserProfile/utils.ts +++ b/vite-app/src/apps/UserProfile/utils.ts @@ -1,5 +1,4 @@ - -export function arraysEqual(a: any, b: any): boolean { +export function arraysEqual(a: unknown, b: unknown): boolean { if (!Array.isArray(a)) { return false; } @@ -19,18 +18,18 @@ export function arraysEqual(a: any, b: any): boolean { } export function noScriptTag(value: string) { - if (/]*>/ig.test(value)) { - throw Error('the "script" tag (