diff --git a/.github/actions/build-docker-images/action.yml b/.github/actions/build-docker-images/action.yml index a16b9c608..37432506f 100644 --- a/.github/actions/build-docker-images/action.yml +++ b/.github/actions/build-docker-images/action.yml @@ -74,6 +74,10 @@ runs: SHA_CLIENT=$(git rev-parse HEAD:packages/client) SHA_RAILS=$(git rev-parse HEAD:packages/rails) SHORT_SHA=$(echo "${SHA_CLIENT}_${SHA_RAILS}" | sha1sum | cut -c1-7) + elif [ "${{ inputs.package }}" == "nginx" ]; then + SHA_CLIENT=$(git rev-parse HEAD:packages/client) + SHA_NGINX=$(git rev-parse HEAD:packages/nginx) + SHORT_SHA=$(echo "${SHA_CLIENT}_${SHA_NGINX}" | sha1sum | cut -c1-7) else SHORT_SHA=$(git rev-parse --short HEAD:packages/${{ inputs.package }}) fi diff --git a/.gitignore b/.gitignore index 038b7358c..643106d54 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,7 @@ vendor/assets/bower_components/ .cursor/ .specify/ .playwright-cli + +# GSRS seed data (downloaded via `make gsrs-seed-data`) +packages/gsrs/seed-data/ +docker/misc/gsrs-db-init/02-gsrsdb-data.sql diff --git a/Makefile b/Makefile index 5a35b4c8d..8e0a68d3a 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ check-unpublished-env-variables: # └───────────────────────┘ PFDA_SHOULD_RUN_GSRS ?= 0 +GSRS_FRONTEND_DEV ?= false # ┌───────────┐ # │ │ @@ -67,9 +68,12 @@ DB_WIPE_VOLUMES := db-pfda-mysql-volume # Conditionally defined if gsrs should be included in the stack ifneq (,$(filter-out 0,$(PFDA_SHOULD_RUN_GSRS))) DOCKER_COMPOSE_FILE_FLAGS := $(DOCKER_COMPOSE_FILE_FLAGS) -f $(EXTERNAL_DOCKER_COMPOSE_FILE) -SERVICES := $(SERVICES) gsrs gsrsdb +SERVICES := $(SERVICES) gsrs gsrs-nginx gsrsdb DB_WIPE_SERVICES := $(DB_WIPE_SERVICES) gsrsdb DB_WIPE_VOLUMES := $(DB_WIPE_VOLUMES) db-gsrs-mariadb-volume +ifeq (true,$(GSRS_FRONTEND_DEV)) +DOCKER_COMPOSE_FILE_FLAGS := $(DOCKER_COMPOSE_FILE_FLAGS) --profile frontend-dev +endif endif # Recursive `=` so DOCKER_COMPOSE_FILE_FLAGS is re-expanded at every call @@ -90,7 +94,14 @@ prepare-db: $(COMPOSE) run -T --rm --no-deps --build -e PFDA_DB_INIT_ONLY=1 web prepare-db-test: $(COMPOSE) up --build $(PREPARE_DB_TEST_SERVICES) +gsrs-seed-data: + ./packages/gsrs/scripts/fetch-seed-data.sh run: +ifneq (0,$(PFDA_SHOULD_RUN_GSRS)) +ifneq (,$(PFDA_SHOULD_RUN_GSRS)) + @mkdir -p packages/gsrs/seed-data/ginas.ix +endif +endif $(COMPOSE) up --build stop: $(COMPOSE) down diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..be417abbc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,39 @@ +# Security Policy + +## Reporting Security Vulnerabilities + +The U.S. Food and Drug Administration (FDA) takes security vulnerabilities seriously. If you believe you have found a security vulnerability in this repository, please report it to us through coordinated disclosure. + +**Please do NOT report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +--- + +## How to Report + +FDA follows the HHS Vulnerability Disclosure Policy. Submit your report through the official HHS reporting portal: + +- **HHS Vulnerability Disclosure Policy:** [https://www.hhs.gov/vulnerability-disclosure-policy/index.html] +- **Submit a Report:** [https://hhs.responsibledisclosure.com] + +### Contact + +For general security questions or concerns about FDA systems, contact: +- **Repository Maintainer:** precisionfda@fda.hhs.gov + +--- +## Security Best Practices for Contributors + +When contributing to this repository: + +- Follow the principle of least privilege +- Validate and sanitize all inputs +- Use parameterized queries for database access +- Keep dependencies up to date +- Never commit secrets, API keys, or credentials +- Review security advisories for dependencies + +--- + +**Disclaimer:** This repository contains code developed for research, regulatory science, or public health purposes. The code is provided "as-is" without warranty. Use in production systems should follow your organization's security assessment processes. + +**Last Updated:** June 09, 2026 diff --git a/docker/.env.example b/docker/.env.example index d6baf9a6f..46de7ce61 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -22,12 +22,18 @@ SKIP_DB_SETUP=0 NODEJS_DB_POLLING_INTERVAL=5 # When 0, Nest dev runs without --watch (faster container stops). Default 1 (watch enabled). -NODE_DEV_WATCH=1 +NODE_DEV_WATCH=0 -# URL - nodejs API url -NODE_API_URL=https://host.docker.internal:3001 -# URL - ruby API url -RUBY_API_URL=https://host.docker.internal:5012 -DOCS_URL=http://host.docker.internal:4040 -# for native node +# Upstream URLs for the nginx container (Docker Compose service names, not host ports). +# Do NOT use host.docker.internal here — host port 3001 is often occupied by a local +# Node/Vite process speaking plain HTTP, which causes SSL handshake failures (502). +NODE_API_URL=https://nodejs-api:3001 +RUBY_API_URL=https://web:3000 +DOCS_URL=http://docs:4040 + +RECAPTCHA_SITE_KEY=NEED_A_KEY_4_TEST + +# VITE_OUT_DIR=dist +# Only when running Node/Rails natively on the host (outside Docker): # NODE_API_URL=https://host.docker.internal:3001 +# RUBY_API_URL=https://host.docker.internal:3005 diff --git a/docker/base.services.yml b/docker/base.services.yml index 15d52732d..4a85aaebb 100644 --- a/docker/base.services.yml +++ b/docker/base.services.yml @@ -30,7 +30,7 @@ services: - ../key.pem:/key.pem working_dir: /precision-fda ports: - - "5012:3000" + - "3005:3000" extra_hosts: - "host.docker.internal:host-gateway" entrypoint: ./docker/entrypoint/dev.entrypoint.sh @@ -45,11 +45,10 @@ services: args: - FRONTEND_IMAGE_TAG=24.15.0-slim environment: - - VITE_OUT_DIR=dist - SKIP_FRONTEND_DEPS_SETUP=${SKIP_FRONTEND_DEPS_SETUP} volumes: - type: bind - source: ../packages/rails/public/packs + source: ../packages/client/dist target: /precision-fda/dist working_dir: /precision-fda command: pnpm run build @@ -121,5 +120,6 @@ services: - ../cert.pem:/keys/cert.pem - ../key.pem:/keys/key.pem - ../packages/nginx:/etc/nginx/templates + - ../packages/client/dist:/usr/share/nginx/html:ro ports: - "3000:443" diff --git a/docker/dev.docker-compose.yml b/docker/dev.docker-compose.yml index 881cd94c5..3870dad3c 100644 --- a/docker/dev.docker-compose.yml +++ b/docker/dev.docker-compose.yml @@ -40,6 +40,7 @@ services: dockerfile: ./docker/images/dev.Dockerfile environment: - SKIP_FRONTEND_DEPS_SETUP=${SKIP_FRONTEND_DEPS_SETUP} + - VITE_OUT_DIR=dist volumes: - type: volume source: vite-cache-client @@ -141,3 +142,10 @@ services: extends: file: ./base.services.yml service: nginx + depends_on: + nodejs-api: + condition: service_started + web: + condition: service_started + docs: + condition: service_started diff --git a/docker/external.docker-compose.yml b/docker/external.docker-compose.yml index 0125734c2..5f01b3e4b 100644 --- a/docker/external.docker-compose.yml +++ b/docker/external.docker-compose.yml @@ -1,13 +1,17 @@ volumes: db-gsrs-mariadb-volume: + gsrs-frontend-node-modules: services: web: depends_on: - - gsrs + - gsrs-nginx environment: - - GSRS_URL=http://gsrs:8080 + - GSRS_URL=http://gsrs-nginx:80 - GSRS_ENABLED=true + nginx: + depends_on: + - gsrs-nginx gsrs: depends_on: gsrsdb: @@ -15,9 +19,19 @@ services: extends: file: ./external.services.yml service: gsrs + gsrs-nginx: + depends_on: + - gsrs + extends: + file: ./external.services.yml + service: gsrs-nginx + gsrs-frontend-dev: + extends: + file: ./external.services.yml + service: gsrs-frontend-dev gsrsdb: extends: file: ./external.services.yml service: gsrsdb volumes: - - db-gsrs-mariadb-volume:/var/lib/mariadb + - db-gsrs-mariadb-volume:/var/lib/mysql diff --git a/docker/external.services.yml b/docker/external.services.yml index e6d1a9204..68dc8a97f 100644 --- a/docker/external.services.yml +++ b/docker/external.services.yml @@ -1,24 +1,45 @@ services: gsrs: build: - context: ../packages/rails - dockerfile: docker/images/gsrs.Dockerfile - ports: - - "8080:8080" + context: ../packages/gsrs/web + dockerfile: Dockerfile + args: + GSRS3_MAIN_BRANCH: ${GSRS3_MAIN_BRANCH:-GSRSv3.1.2PUB} + FRONTEND_TAG: ${GSRS_FRONTEND_TAG:-pfda} + # Alias as gsrs-web so gsrs-nginx config works unchanged (matches cloud service name) + networks: + default: + aliases: + - gsrs-web + environment: + - HOST=${GSRS_HOST:-https://localhost:3000} + - GSRS_DATABASE_HOST=${GSRS_DATABASE_HOST:-gsrsdb:3306} + - GSRS_DATABASE_NAME=${GSRS_DATABASE_NAME:-ixginas_local} + - GSRS_DATABASE_USERNAME=${GSRS_DATABASE_USERNAME:-root} + - GSRS_DATABASE_PASSWORD=${GSRS_DATABASE_PASSWORD:-${GSRS_DB_ROOT_PASSWORD:-password}} + - GSRS_LOCAL_MODE=${GSRS_LOCAL_MODE:-true} volumes: + # Lucene index; entrypoint symlinks this to /opt/gsrs/ginas.ix - type: bind - source: ${GSRS_FRONTEND_PATH:-/dev/null} - target: /usr/local/GSRSFrontend - - type: bind - source: ${GSRS_INDEX_PATH:-/dev/null} - target: /ginas.ix + source: ${GSRS_INDEX_PATH:-../packages/gsrs/seed-data/ginas.ix} + target: /tmp/read-only-base + + gsrs-nginx: + build: + context: ../packages/gsrs/nginx + depends_on: + - gsrs + environment: + - GSRS_FRONTEND_DEV=${GSRS_FRONTEND_DEV:-false} + ports: + - 8081:80 gsrsdb: image: "mariadb:10.6.15" tmpfs: - /tmp environment: - MYSQL_DATABASE: ixginas + MYSQL_DATABASE: ixginas_local MYSQL_ROOT_PASSWORD: ${GSRS_DB_ROOT_PASSWORD:-password} ports: - "32900:3306" @@ -30,4 +51,23 @@ services: start_period: 20s volumes: # Script for the DB initialization (creating the tables) - - ../packages/rails/docker/misc/gsrs-db-init:/docker-entrypoint-initdb.d + - ./misc/gsrs-db-init:/docker-entrypoint-initdb.d + gsrsdb_emulated: + extends: + service: gsrsdb + image: amd64/mariadb:10.6.15 + + gsrs-frontend-dev: + profiles: + - frontend-dev + build: + context: ../packages/gsrs/frontend-dev + mem_limit: 6g + volumes: + - type: bind + source: ${GSRS_FRONTEND_PATH:-.} + target: /app + # Separate node_modules to avoid overwriting host's (different platform) + - gsrs-frontend-node-modules:/app/node_modules + ports: + - 4200:4200 diff --git a/docker/misc/gsrs-db-init/01-gsrsdb-schema.sql b/docker/misc/gsrs-db-init/01-gsrsdb-schema.sql new file mode 100644 index 000000000..e49825bba --- /dev/null +++ b/docker/misc/gsrs-db-init/01-gsrsdb-schema.sql @@ -0,0 +1,2310 @@ +-- MariaDB dump 10.19 Distrib 10.6.15-MariaDB, for debian-linux-gnu (aarch64) +-- +-- Host: localhost Database: ixginas_local +-- ------------------------------------------------------ +-- Server version 10.6.15-MariaDB-1:10.6.15+maria~ubu2004 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Sequence structure for `LONG_SEQ_ID` +-- + +DROP SEQUENCE IF EXISTS `LONG_SEQ_ID`; +CREATE SEQUENCE `LONG_SEQ_ID` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`LONG_SEQ_ID`, 1, 0); + +-- +-- Sequence structure for `db_gsrs_version_seq` +-- + +DROP SEQUENCE IF EXISTS `db_gsrs_version_seq`; +CREATE SEQUENCE `db_gsrs_version_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`db_gsrs_version_seq`, 1, 0); + +-- +-- Sequence structure for `ix_core_acl_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_acl_seq`; +CREATE SEQUENCE `ix_core_acl_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_acl_seq`, 1, 0); + +-- +-- Sequence structure for `ix_core_backup_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_backup_seq`; +CREATE SEQUENCE `ix_core_backup_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_backup_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_etag_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_etag_seq`; +CREATE SEQUENCE `ix_core_etag_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_etag_seq`, 2001, 0); + +-- +-- Sequence structure for `ix_core_group_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_group_seq`; +CREATE SEQUENCE `ix_core_group_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_group_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_namespace_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_namespace_seq`; +CREATE SEQUENCE `ix_core_namespace_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_namespace_seq`, 1, 0); + +-- +-- Sequence structure for `ix_core_principal_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_principal_seq`; +CREATE SEQUENCE `ix_core_principal_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_principal_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_procjob_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_procjob_seq`; +CREATE SEQUENCE `ix_core_procjob_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_procjob_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_procrec_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_procrec_seq`; +CREATE SEQUENCE `ix_core_procrec_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_procrec_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_userprof_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_userprof_seq`; +CREATE SEQUENCE `ix_core_userprof_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_userprof_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_value_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_value_seq`; +CREATE SEQUENCE `ix_core_value_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_value_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_core_xref_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_core_xref_seq`; +CREATE SEQUENCE `ix_core_xref_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_core_xref_seq`, 1, 0); + +-- +-- Sequence structure for `ix_ginas_controlled_vocab_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_ginas_controlled_vocab_seq`; +CREATE SEQUENCE `ix_ginas_controlled_vocab_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_ginas_controlled_vocab_seq`, 1001, 0); + +-- +-- Sequence structure for `ix_ginas_vocabulary_term_seq` +-- + +DROP SEQUENCE IF EXISTS `ix_ginas_vocabulary_term_seq`; +CREATE SEQUENCE `ix_ginas_vocabulary_term_seq` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; +SELECT SETVAL(`ix_ginas_vocabulary_term_seq`, 4001, 0); + +-- +-- Table structure for table `ix_batch_processingjob` +-- + +DROP TABLE IF EXISTS `ix_batch_processingjob`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_batch_processingjob` ( + `id` varchar(40) NOT NULL, + `category` varchar(255) DEFAULT NULL, + `completed_record_count` int(11) NOT NULL, + `data` longtext DEFAULT NULL, + `finish_date` datetime(6) DEFAULT NULL, + `job_status` varchar(255) DEFAULT NULL, + `results` longtext DEFAULT NULL, + `start_date` datetime(6) DEFAULT NULL, + `status_message` varchar(255) DEFAULT NULL, + `total_records` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_acl` +-- + +DROP TABLE IF EXISTS `ix_core_acl`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_acl` ( + `id` bigint(20) NOT NULL, + `perm` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_acl_group` +-- + +DROP TABLE IF EXISTS `ix_core_acl_group`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_acl_group` ( + `ix_core_acl_id` bigint(20) NOT NULL, + `ix_core_group_id` bigint(20) NOT NULL, + KEY `fkffablaywfq4inuntnok9otle` (`ix_core_group_id`), + KEY `fk8a5l9ehfusnoigq1r4robs2da` (`ix_core_acl_id`), + CONSTRAINT `fk8a5l9ehfusnoigq1r4robs2da` FOREIGN KEY (`ix_core_acl_id`) REFERENCES `ix_core_acl` (`id`), + CONSTRAINT `fkffablaywfq4inuntnok9otle` FOREIGN KEY (`ix_core_group_id`) REFERENCES `ix_core_group` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_acl_principal` +-- + +DROP TABLE IF EXISTS `ix_core_acl_principal`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_acl_principal` ( + `ix_core_acl_id` bigint(20) NOT NULL, + `ix_core_principal_id` bigint(20) NOT NULL, + KEY `fkpf5d4mu9td8et6k5pgt78jma8` (`ix_core_principal_id`), + KEY `fkc9bo2bwjfcf7djff6coigl2b1` (`ix_core_acl_id`), + CONSTRAINT `fkc9bo2bwjfcf7djff6coigl2b1` FOREIGN KEY (`ix_core_acl_id`) REFERENCES `ix_core_acl` (`id`), + CONSTRAINT `fkpf5d4mu9td8et6k5pgt78jma8` FOREIGN KEY (`ix_core_principal_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_backup` +-- + +DROP TABLE IF EXISTS `ix_core_backup`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_backup` ( + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `compressed` bit(1) NOT NULL, + `data` longblob DEFAULT NULL, + `kind` varchar(255) DEFAULT NULL, + `refid` varchar(255) DEFAULT NULL, + `sha1` varchar(255) DEFAULT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_6n0ebodjb5t7yoxowli7t5qud` (`refid`), + KEY `fknulpohkjr0e7imml16hnmcl2c` (`namespace_id`), + CONSTRAINT `fknulpohkjr0e7imml16hnmcl2c` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_db_gsrs_version` +-- + +DROP TABLE IF EXISTS `ix_core_db_gsrs_version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_db_gsrs_version` ( + `id` bigint(20) NOT NULL, + `entity` varchar(255) NOT NULL, + `hash` varchar(255) DEFAULT NULL, + `modified` datetime(6) DEFAULT NULL, + `version_info` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_edit` +-- + +DROP TABLE IF EXISTS `ix_core_edit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_edit` ( + `id` varchar(40) NOT NULL, + `batch` varchar(64) DEFAULT NULL, + `comments` longtext DEFAULT NULL, + `created` bigint(20) DEFAULT NULL, + `kind` varchar(255) DEFAULT NULL, + `new_value` longtext DEFAULT NULL, + `old_value` longtext DEFAULT NULL, + `path` varchar(1024) DEFAULT NULL, + `refid` varchar(255) DEFAULT NULL, + `version` varchar(255) DEFAULT NULL, + `editor_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `refid_core_edit_index` (`refid`), + KEY `kind_core_edit_index` (`kind`), + KEY `fkj2b3ncg8uek4q4tjua17gvkgi` (`editor_id`), + CONSTRAINT `fkj2b3ncg8uek4q4tjua17gvkgi` FOREIGN KEY (`editor_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_etag` +-- + +DROP TABLE IF EXISTS `ix_core_etag`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_etag` ( + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `count` int(11) DEFAULT NULL, + `etag` varchar(16) DEFAULT NULL, + `filter` varchar(4000) DEFAULT NULL, + `method` varchar(10) DEFAULT NULL, + `path` varchar(255) DEFAULT NULL, + `query` varchar(2048) DEFAULT NULL, + `sha1` varchar(40) DEFAULT NULL, + `skip` int(11) DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `top` int(11) DEFAULT NULL, + `total` int(11) DEFAULT NULL, + `uri` varchar(4000) DEFAULT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_hvark3ftc0xax8dcbjuftcn7v` (`etag`), + KEY `fk22kqxphqlg1d1hmsi2wtm6k0c` (`namespace_id`), + CONSTRAINT `fk22kqxphqlg1d1hmsi2wtm6k0c` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_figure` +-- + +DROP TABLE IF EXISTS `ix_core_figure`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_figure` ( + `DTYPE` varchar(31) NOT NULL, + `id` bigint(20) NOT NULL, + `caption` varchar(255) DEFAULT NULL, + `data` longblob DEFAULT NULL, + `mime_type` varchar(255) DEFAULT NULL, + `sha1` varchar(140) DEFAULT NULL, + `data_size` int(11) DEFAULT NULL, + `url` varchar(1024) DEFAULT NULL, + `parent_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fk911xrg14bag2m8e096i9d75lu` (`parent_id`), + CONSTRAINT `fk911xrg14bag2m8e096i9d75lu` FOREIGN KEY (`parent_id`) REFERENCES `ix_core_figure` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_filedata` +-- + +DROP TABLE IF EXISTS `ix_core_filedata`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_filedata` ( + `DTYPE` varchar(31) NOT NULL, + `id` varchar(40) NOT NULL, + `data` longblob DEFAULT NULL, + `mime_type` varchar(255) DEFAULT NULL, + `sha1` varchar(140) DEFAULT NULL, + `data_size` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_group` +-- + +DROP TABLE IF EXISTS `ix_core_group`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_group` ( + `id` bigint(20) NOT NULL, + `name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_pm62da77mybok0t03dd0a9oum` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_group_principal` +-- + +DROP TABLE IF EXISTS `ix_core_group_principal`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_group_principal` ( + `ix_core_group_id` bigint(20) NOT NULL, + `ix_core_principal_id` bigint(20) NOT NULL, + PRIMARY KEY (`ix_core_group_id`,`ix_core_principal_id`), + KEY `fkp21u3ryjg094idoi9alrg90p7` (`ix_core_principal_id`), + CONSTRAINT `fk1voeekm54sy5sc3et2fqo0unx` FOREIGN KEY (`ix_core_group_id`) REFERENCES `ix_core_group` (`id`), + CONSTRAINT `fkp21u3ryjg094idoi9alrg90p7` FOREIGN KEY (`ix_core_principal_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_key_user_list` +-- + +DROP TABLE IF EXISTS `ix_core_key_user_list`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_key_user_list` ( + `id` bigint(20) NOT NULL, + `entity_key` varchar(255) DEFAULT NULL, + `kind` varchar(255) DEFAULT NULL, + `list_name` varchar(255) NOT NULL, + `user_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ukq0ipvkfn4lc8e88hi3900bytv` (`entity_key`,`list_name`,`user_id`,`kind`), + KEY `fk7q0vtv7ajevho6v75n57jy0dj` (`user_id`), + CONSTRAINT `fk7q0vtv7ajevho6v75n57jy0dj` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_namespace` +-- + +DROP TABLE IF EXISTS `ix_core_namespace`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_namespace` ( + `id` bigint(20) NOT NULL, + `location` varchar(1024) DEFAULT NULL, + `modifier` int(11) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `owner_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_t3wv0p58vflh5n2vnj6rjan75` (`name`), + KEY `fkdgo5yjubgilh1nauv1t69gslx` (`owner_id`), + CONSTRAINT `fkdgo5yjubgilh1nauv1t69gslx` FOREIGN KEY (`owner_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_payload` +-- + +DROP TABLE IF EXISTS `ix_core_payload`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_payload` ( + `id` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `mime_type` varchar(128) DEFAULT NULL, + `name` varchar(1024) DEFAULT NULL, + `sha1` varchar(40) DEFAULT NULL, + `capacity` bigint(20) DEFAULT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fkd150c5llpyncrqgpmqvvj8c9g` (`namespace_id`), + CONSTRAINT `fkd150c5llpyncrqgpmqvvj8c9g` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_payload_property` +-- + +DROP TABLE IF EXISTS `ix_core_payload_property`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_payload_property` ( + `ix_core_payload_id` varchar(40) NOT NULL, + `ix_core_value_id` bigint(20) NOT NULL, + KEY `fki6ubcj55u3pq0gm70ay7umle1` (`ix_core_value_id`), + KEY `fk6j2diflggrmws0k3suo8ms215` (`ix_core_payload_id`), + CONSTRAINT `fk6j2diflggrmws0k3suo8ms215` FOREIGN KEY (`ix_core_payload_id`) REFERENCES `ix_core_payload` (`id`), + CONSTRAINT `fki6ubcj55u3pq0gm70ay7umle1` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_principal` +-- + +DROP TABLE IF EXISTS `ix_core_principal`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_principal` ( + `DTYPE` varchar(31) NOT NULL, + `id` bigint(20) NOT NULL, + `is_admin` bit(1) DEFAULT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `email` varchar(255) DEFAULT NULL, + `modified` datetime(6) DEFAULT NULL, + `provider` varchar(255) DEFAULT NULL, + `uri` varchar(1024) DEFAULT NULL, + `username` varchar(255) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `selfie_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_p8p720bdp9bkws54yip7x1t47` (`username`), + KEY `fk6th1516rd9u5crfw7r12qtypk` (`selfie_id`), + CONSTRAINT `fk6th1516rd9u5crfw7r12qtypk` FOREIGN KEY (`selfie_id`) REFERENCES `ix_core_figure` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_procjob` +-- + +DROP TABLE IF EXISTS `ix_core_procjob`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_procjob` ( + `id` bigint(20) NOT NULL, + `last_update` datetime(6) DEFAULT NULL, + `message` longtext DEFAULT NULL, + `job_start` bigint(20) DEFAULT NULL, + `statistics` longtext DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `job_stop` bigint(20) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `owner_id` bigint(20) DEFAULT NULL, + `payload_id` varchar(40) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fkkx6oorfim5n6bhuy3j8wogyl5` (`owner_id`), + KEY `fkoxadf72bp8jsiuh1v42gx1t71` (`payload_id`), + CONSTRAINT `fkkx6oorfim5n6bhuy3j8wogyl5` FOREIGN KEY (`owner_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkoxadf72bp8jsiuh1v42gx1t71` FOREIGN KEY (`payload_id`) REFERENCES `ix_core_payload` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_procjob_key` +-- + +DROP TABLE IF EXISTS `ix_core_procjob_key`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_procjob_key` ( + `ix_core_procjob_id` bigint(20) NOT NULL, + `keys_id` bigint(20) NOT NULL, + KEY `fkr2mo13ikjb3bfw91uuwf7n5aw` (`keys_id`), + KEY `fk70h2uyrhvkuo84bwag5vljg9s` (`ix_core_procjob_id`), + CONSTRAINT `fk70h2uyrhvkuo84bwag5vljg9s` FOREIGN KEY (`ix_core_procjob_id`) REFERENCES `ix_core_procjob` (`id`), + CONSTRAINT `fkr2mo13ikjb3bfw91uuwf7n5aw` FOREIGN KEY (`keys_id`) REFERENCES `ix_core_value` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_procrec` +-- + +DROP TABLE IF EXISTS `ix_core_procrec`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_procrec` ( + `id` bigint(20) NOT NULL, + `last_update` datetime(6) DEFAULT NULL, + `message` longtext DEFAULT NULL, + `name` varchar(128) DEFAULT NULL, + `rec_start` bigint(20) DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `rec_stop` bigint(20) DEFAULT NULL, + `job_id` bigint(20) DEFAULT NULL, + `xref_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fkpsv2ie5f4qjkar6kgis359efe` (`job_id`), + KEY `fkabpfcuyjcycb86bmc06xps4j6` (`xref_id`), + CONSTRAINT `fkabpfcuyjcycb86bmc06xps4j6` FOREIGN KEY (`xref_id`) REFERENCES `ix_core_xref` (`id`), + CONSTRAINT `fkpsv2ie5f4qjkar6kgis359efe` FOREIGN KEY (`job_id`) REFERENCES `ix_core_procjob` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_procrec_prop` +-- + +DROP TABLE IF EXISTS `ix_core_procrec_prop`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_procrec_prop` ( + `ix_core_procrec_id` bigint(20) NOT NULL, + `properties_id` bigint(20) NOT NULL, + KEY `fkjg8tmtxlf4d2vnb90e6i7exg0` (`properties_id`), + KEY `fktnw4u7w89a21880hmtva47pta` (`ix_core_procrec_id`), + CONSTRAINT `fkjg8tmtxlf4d2vnb90e6i7exg0` FOREIGN KEY (`properties_id`) REFERENCES `ix_core_value` (`id`), + CONSTRAINT `fktnw4u7w89a21880hmtva47pta` FOREIGN KEY (`ix_core_procrec_id`) REFERENCES `ix_core_procrec` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_session` +-- + +DROP TABLE IF EXISTS `ix_core_session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_session` ( + `id` varchar(40) NOT NULL, + `accessed` bigint(20) NOT NULL, + `created` bigint(20) NOT NULL, + `expired` bit(1) NOT NULL, + `location` varchar(255) DEFAULT NULL, + `profile_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fkfxn2t6y3dre527h1eymkt8lur` (`profile_id`), + CONSTRAINT `fkfxn2t6y3dre527h1eymkt8lur` FOREIGN KEY (`profile_id`) REFERENCES `ix_core_userprof` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_structure` +-- + +DROP TABLE IF EXISTS `ix_core_structure`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_structure` ( + `DTYPE` varchar(31) NOT NULL, + `id` varchar(40) NOT NULL, + `atropi` int(11) DEFAULT NULL, + `charge` int(11) DEFAULT NULL, + `count` int(11) DEFAULT NULL, + `created` datetime(6) DEFAULT NULL, + `defined_stereo` int(11) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `digest` varchar(128) DEFAULT NULL, + `ez_centers` int(11) DEFAULT NULL, + `formula` varchar(255) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `molfile` longtext DEFAULT NULL, + `mwt` double DEFAULT NULL, + `optical` int(11) DEFAULT NULL, + `smiles` longtext DEFAULT NULL, + `stereo_centers` int(11) DEFAULT NULL, + `stereo` varchar(255) DEFAULT NULL, + `stereo_comments` longtext DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fksobht0ese9794r3q9k1q6i7gp` (`created_by_id`), + KEY `fk37rfonx9x7vmkwsru7dxxqhhk` (`last_edited_by_id`), + CONSTRAINT `fk37rfonx9x7vmkwsru7dxxqhhk` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fksobht0ese9794r3q9k1q6i7gp` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_structure_link` +-- + +DROP TABLE IF EXISTS `ix_core_structure_link`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_structure_link` ( + `ix_core_structure_id` varchar(40) NOT NULL, + `ix_core_xref_id` bigint(20) NOT NULL, + KEY `fkdca3xgv2a5p344i74yc7sk89v` (`ix_core_xref_id`), + KEY `fk44si68uocnubt6vaobd4mgmmy` (`ix_core_structure_id`), + CONSTRAINT `fk44si68uocnubt6vaobd4mgmmy` FOREIGN KEY (`ix_core_structure_id`) REFERENCES `ix_core_structure` (`id`), + CONSTRAINT `fkdca3xgv2a5p344i74yc7sk89v` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_structure_property` +-- + +DROP TABLE IF EXISTS `ix_core_structure_property`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_structure_property` ( + `ix_core_structure_id` varchar(40) NOT NULL, + `ix_core_value_id` bigint(20) NOT NULL, + KEY `property_structure_id_index` (`ix_core_structure_id`), + KEY `property_value_id_index` (`ix_core_value_id`), + CONSTRAINT `fk4n49941jj4uufoosy5n1g9rg6` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), + CONSTRAINT `fkok4h9jsov59dh00wnrmsnd12x` FOREIGN KEY (`ix_core_structure_id`) REFERENCES `ix_core_structure` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_user_saved_list` +-- + +DROP TABLE IF EXISTS `ix_core_user_saved_list`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_user_saved_list` ( + `id` bigint(20) NOT NULL, + `kind` varchar(255) DEFAULT NULL, + `list` longtext DEFAULT NULL, + `name` varchar(255) NOT NULL, + `user_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ukg72w8umh72yn9lnpxxycln5jd` (`name`,`user_id`,`kind`), + KEY `fkhd1bc5m9wxca27lxoexqjfwei` (`user_id`), + CONSTRAINT `fkhd1bc5m9wxca27lxoexqjfwei` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_userprof` +-- + +DROP TABLE IF EXISTS `ix_core_userprof`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_userprof` ( + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `active` bit(1) NOT NULL, + `hashp` varchar(255) DEFAULT NULL, + `apikey` varchar(255) DEFAULT NULL, + `ROLES_JSON` longtext DEFAULT NULL, + `salt` varchar(255) DEFAULT NULL, + `system_auth` bit(1) NOT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + `user_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fks5bqupbwldu7843qnt8tuntnu` (`namespace_id`), + KEY `fknq0obnfqd9j3uh1uxdqn3ouq7` (`user_id`), + CONSTRAINT `fknq0obnfqd9j3uh1uxdqn3ouq7` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fks5bqupbwldu7843qnt8tuntnu` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = latin1 */ ; +/*!50003 SET character_set_results = latin1 */ ; +/*!50003 SET collation_connection = latin1_swedish_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER ix_core_userprof_update_roles BEFORE UPDATE ON ix_core_userprof +FOR EACH ROW +BEGIN + IF NEW.roles_json IS NULL THEN + SET NEW.roles_json = '["Query","Updater","SuperUpdate","DataEntry","SuperDataEntry"]'; + END IF; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; + +-- +-- Table structure for table `ix_core_userprof_prop` +-- + +DROP TABLE IF EXISTS `ix_core_userprof_prop`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_userprof_prop` ( + `ix_core_userprof_id` bigint(20) NOT NULL, + `ix_core_value_id` bigint(20) NOT NULL, + KEY `fknfow9qqryxbxgppprcum5khf8` (`ix_core_value_id`), + KEY `fklloqe5wbjywhajh4tw6ilfnvg` (`ix_core_userprof_id`), + CONSTRAINT `fklloqe5wbjywhajh4tw6ilfnvg` FOREIGN KEY (`ix_core_userprof_id`) REFERENCES `ix_core_userprof` (`id`), + CONSTRAINT `fknfow9qqryxbxgppprcum5khf8` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_value` +-- + +DROP TABLE IF EXISTS `ix_core_value`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_value` ( + `DTYPE` varchar(31) NOT NULL, + `id` bigint(20) NOT NULL, + `label` varchar(255) DEFAULT NULL, + `intval` bigint(20) DEFAULT NULL, + `average` double DEFAULT NULL, + `lval` double DEFAULT NULL, + `rval` double DEFAULT NULL, + `data` longblob DEFAULT NULL, + `mime_type` varchar(32) DEFAULT NULL, + `sha1` varchar(40) DEFAULT NULL, + `data_size` int(11) DEFAULT NULL, + `strval` varchar(1024) DEFAULT NULL, + `href` longtext DEFAULT NULL, + `term` varchar(255) DEFAULT NULL, + `numval` double DEFAULT NULL, + `unit` varchar(255) DEFAULT NULL, + `heading` varchar(1024) DEFAULT NULL, + `major_topic` bit(1) DEFAULT NULL, + `text` longtext DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `value_label_index` (`label`), + KEY `value_term_index` (`term`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_xref` +-- + +DROP TABLE IF EXISTS `ix_core_xref`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_xref` ( + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `kind` varchar(255) NOT NULL, + `refid` varchar(40) NOT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `xref_refid_index` (`refid`), + KEY `xref_kind_index` (`kind`), + KEY `fk6g9t8ugidjwe166t5nk7x2wqm` (`namespace_id`), + CONSTRAINT `fk6g9t8ugidjwe166t5nk7x2wqm` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_core_xref_property` +-- + +DROP TABLE IF EXISTS `ix_core_xref_property`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_core_xref_property` ( + `ix_core_xref_id` bigint(20) NOT NULL, + `ix_core_value_id` bigint(20) NOT NULL, + KEY `fkaucrto6dcvyyq1n6jo332gqsf` (`ix_core_value_id`), + KEY `fkmr6or6lteb684kq2e1dgsxl1w` (`ix_core_xref_id`), + CONSTRAINT `fkaucrto6dcvyyq1n6jo332gqsf` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), + CONSTRAINT `fkmr6or6lteb684kq2e1dgsxl1w` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_agentmod` +-- + +DROP TABLE IF EXISTS `ix_ginas_agentmod`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_agentmod` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `agent_modification_process` varchar(255) DEFAULT NULL, + `agent_modification_role` varchar(255) DEFAULT NULL, + `agent_modification_type` varchar(255) DEFAULT NULL, + `modification_group` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `agent_substance_uuid` varchar(40) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk837ol47m9wstcu74fp5toniam` (`created_by_id`), + KEY `fk2prhrnc5vlo55jxu1rxgpfdw1` (`last_edited_by_id`), + KEY `fk2x5f4lw85tpkym1r3urwp2u3w` (`agent_substance_uuid`), + KEY `fki7hwi4cyu1hi7yjo2ddwkig51` (`amount_uuid`), + KEY `fk9ybw4linkblw3p4u25cq6qs0d` (`owner_uuid`), + CONSTRAINT `fk2prhrnc5vlo55jxu1rxgpfdw1` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk2x5f4lw85tpkym1r3urwp2u3w` FOREIGN KEY (`agent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fk837ol47m9wstcu74fp5toniam` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk9ybw4linkblw3p4u25cq6qs0d` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), + CONSTRAINT `fki7hwi4cyu1hi7yjo2ddwkig51` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_amount` +-- + +DROP TABLE IF EXISTS `ix_ginas_amount`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_amount` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `approval_id` varchar(10) DEFAULT NULL, + `average` double DEFAULT NULL, + `high` double DEFAULT NULL, + `high_limit` double DEFAULT NULL, + `low` double DEFAULT NULL, + `low_limit` double DEFAULT NULL, + `non_numeric_value` varchar(255) DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `units` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkqsmrbuknll0fmv6jthf4cycy5` (`created_by_id`), + KEY `fk9leptgx7incy9twmrwcpeo2bm` (`last_edited_by_id`), + CONSTRAINT `fk9leptgx7incy9twmrwcpeo2bm` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkqsmrbuknll0fmv6jthf4cycy5` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_code` +-- + +DROP TABLE IF EXISTS `ix_ginas_code`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_code` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `code` varchar(255) NOT NULL, + `code_system` varchar(255) DEFAULT NULL, + `code_text` longtext DEFAULT NULL, + `comments` longtext DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `url` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `ix_ix_ginas_code_code` (`code`), + KEY `ix_ix_ginas_code_code_system` (`code_system`), + KEY `ix_ix_ginas_code_type` (`type`), + KEY `ix_ix_ginas_code_owner` (`owner_uuid`), + KEY `fkfwn6blkrhusg1xhrue0u820p` (`created_by_id`), + KEY `fkpio633txjf8p5soyujcrtbx9v` (`last_edited_by_id`), + CONSTRAINT `fke9p0ygr5drc93bxry80f9y215` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkfwn6blkrhusg1xhrue0u820p` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkpio633txjf8p5soyujcrtbx9v` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_component` +-- + +DROP TABLE IF EXISTS `ix_ginas_component`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_component` ( + `DTYPE` varchar(31) NOT NULL, + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `role` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `substance_uuid` varchar(40) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkodvtp4qvwc7nyfr3lbc893o6m` (`created_by_id`), + KEY `fkbbvqudmdnm60le1imuwb2uj5x` (`last_edited_by_id`), + KEY `fkql4nn094peyvxrwctj1ga2wp2` (`substance_uuid`), + KEY `fksqa51pxp5tbk6vyu34qbr8c5u` (`amount_uuid`), + CONSTRAINT `fkbbvqudmdnm60le1imuwb2uj5x` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkodvtp4qvwc7nyfr3lbc893o6m` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkql4nn094peyvxrwctj1ga2wp2` FOREIGN KEY (`substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fksqa51pxp5tbk6vyu34qbr8c5u` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_controlled_vocab` +-- + +DROP TABLE IF EXISTS `ix_ginas_controlled_vocab`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_controlled_vocab` ( + `DTYPE` varchar(31) NOT NULL, + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `domain` varchar(255) DEFAULT NULL, + `editable` bit(1) NOT NULL, + `filterable` bit(1) NOT NULL, + `vocabulary_term_type` varchar(255) DEFAULT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `UK_ytqxax1bcj99cxs7tos6l26k` (`domain`), + KEY `fk68jp62s2i2745esqr9px9s5a2` (`namespace_id`), + CONSTRAINT `fk68jp62s2i2745esqr9px9s5a2` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_definition` +-- + +DROP TABLE IF EXISTS `ix_ginas_definition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_definition` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `definition` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk4kcslc98jcqx137enxl5fgs5t` (`created_by_id`), + KEY `fk9wxg9p9i1bi7qoxfcu9gkg9og` (`last_edited_by_id`), + CONSTRAINT `fk4kcslc98jcqx137enxl5fgs5t` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk9wxg9p9i1bi7qoxfcu9gkg9og` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_glycosylation` +-- + +DROP TABLE IF EXISTS `ix_ginas_glycosylation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_glycosylation` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `glycosylation_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `c_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, + `n_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, + `o_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk6dapjdumuglm11xxawpupefqm` (`created_by_id`), + KEY `fkpglm1avjx8n78aom78j3ju3bf` (`last_edited_by_id`), + KEY `fkqiim2s89ddjuxbkhpv3xa023j` (`c_glycosylation_sites_uuid`), + KEY `fkffabrw84stgayaui9g1a4wk1g` (`n_glycosylation_sites_uuid`), + KEY `fkmt1ufykgpny0dlxj36h6tgxwr` (`o_glycosylation_sites_uuid`), + CONSTRAINT `fk6dapjdumuglm11xxawpupefqm` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkffabrw84stgayaui9g1a4wk1g` FOREIGN KEY (`n_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), + CONSTRAINT `fkmt1ufykgpny0dlxj36h6tgxwr` FOREIGN KEY (`o_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), + CONSTRAINT `fkpglm1avjx8n78aom78j3ju3bf` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkqiim2s89ddjuxbkhpv3xa023j` FOREIGN KEY (`c_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_linkage` +-- + +DROP TABLE IF EXISTS `ix_ginas_linkage`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_linkage` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `linkage` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `site_container_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkq619bp0y4e8y3c6efgyp2k8ux` (`created_by_id`), + KEY `fkfctm6wmaejthxy8y5gtbaqd80` (`last_edited_by_id`), + KEY `fkotqo99g96i7epg4s384xushll` (`owner_uuid`), + KEY `fkaao7lfx6xsyc4l1cpmsga4vre` (`site_container_uuid`), + CONSTRAINT `fkaao7lfx6xsyc4l1cpmsga4vre` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), + CONSTRAINT `fkfctm6wmaejthxy8y5gtbaqd80` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkotqo99g96i7epg4s384xushll` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`), + CONSTRAINT `fkq619bp0y4e8y3c6efgyp2k8ux` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_material` +-- + +DROP TABLE IF EXISTS `ix_ginas_material`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_material` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `defining` bit(1) DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + `monomer_substance_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk6ts531mold2ibya0c038hebea` (`created_by_id`), + KEY `fkpab2df5aaru3riy5vxd86uve3` (`last_edited_by_id`), + KEY `fkipvr7dsgmt37oig421t41o385` (`amount_uuid`), + KEY `fkegxevel4526aib74sesmtu25e` (`monomer_substance_uuid`), + KEY `fkuvsb9isctq5ela0dqy2hhwti` (`owner_uuid`), + CONSTRAINT `fk6ts531mold2ibya0c038hebea` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkegxevel4526aib74sesmtu25e` FOREIGN KEY (`monomer_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkipvr7dsgmt37oig421t41o385` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fkpab2df5aaru3riy5vxd86uve3` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkuvsb9isctq5ela0dqy2hhwti` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_mixture` +-- + +DROP TABLE IF EXISTS `ix_ginas_mixture`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_mixture` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `parent_substance_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk4tqay4hgaqpm3sq8rx9184jat` (`created_by_id`), + KEY `fkjfwb6hqmtuoadhdx7wpkhxaju` (`last_edited_by_id`), + KEY `fko0yqo20vk9l8tqybgp75o23km` (`parent_substance_uuid`), + CONSTRAINT `fk4tqay4hgaqpm3sq8rx9184jat` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkjfwb6hqmtuoadhdx7wpkhxaju` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fko0yqo20vk9l8tqybgp75o23km` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_modifications` +-- + +DROP TABLE IF EXISTS `ix_ginas_modifications`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_modifications` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fknt72fojjxifrwa7bfwjw8cpm5` (`created_by_id`), + KEY `fkpod9b4pm2tw1e4llfvayoivw4` (`last_edited_by_id`), + CONSTRAINT `fknt72fojjxifrwa7bfwjw8cpm5` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkpod9b4pm2tw1e4llfvayoivw4` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_moiety` +-- + +DROP TABLE IF EXISTS `ix_ginas_moiety`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_moiety` ( + `inner_uuid` varchar(255) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `uuid` varchar(40) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `count_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `structure_id` varchar(40) DEFAULT NULL, + PRIMARY KEY (`inner_uuid`), + UNIQUE KEY `UK_8cr4axbsithvjxcfhnltaejsp` (`uuid`), + KEY `moiety_owner_index` (`owner_uuid`), + KEY `fkkw3ljg8rkiv07pcn0o0n3o02a` (`created_by_id`), + KEY `fk3a5dgbi1pmatnvuta5a4wy3aq` (`last_edited_by_id`), + KEY `fkf0mktcfnu1ly1x7ubmf41lh2n` (`count_uuid`), + KEY `fkc3r993grtkv5al4opvpv554ga` (`structure_id`), + CONSTRAINT `fk3a5dgbi1pmatnvuta5a4wy3aq` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk8olyp6rpiq8yxtuk3mxsnbels` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkc3r993grtkv5al4opvpv554ga` FOREIGN KEY (`structure_id`) REFERENCES `ix_core_structure` (`id`), + CONSTRAINT `fkf0mktcfnu1ly1x7ubmf41lh2n` FOREIGN KEY (`count_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fkkw3ljg8rkiv07pcn0o0n3o02a` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_name` +-- + +DROP TABLE IF EXISTS `ix_ginas_name`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_name` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `display_name` bit(1) NOT NULL, + `domains` longtext DEFAULT NULL, + `full_name` longtext DEFAULT NULL, + `languages` longtext DEFAULT NULL, + `name` varchar(1024) NOT NULL, + `name_jurisdiction` longtext DEFAULT NULL, + `preferred` bit(1) NOT NULL, + `std_name` longtext DEFAULT NULL, + `type` varchar(32) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `name_index` (`name`(768)), + KEY `name_owner_index` (`owner_uuid`), + KEY `fklhhdrsy7v2qr1amwmw0981mv2` (`created_by_id`), + KEY `fkgwls3gldgeqmgliev3kcvhjml` (`last_edited_by_id`), + CONSTRAINT `fkeqm42ow1b2o1c3uhu3d1k2efm` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkgwls3gldgeqmgliev3kcvhjml` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fklhhdrsy7v2qr1amwmw0981mv2` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_nameorg` +-- + +DROP TABLE IF EXISTS `ix_ginas_nameorg`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_nameorg` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `deprecated_date` datetime(6) DEFAULT NULL, + `name_org` varchar(255) NOT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `nameorg_owner_index` (`owner_uuid`), + KEY `fkk77bj1lax07ocd00s3sfmn6ot` (`created_by_id`), + KEY `fkm5w47bga21kw55x56q7jbbguj` (`last_edited_by_id`), + CONSTRAINT `fkk77bj1lax07ocd00s3sfmn6ot` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkm5w47bga21kw55x56q7jbbguj` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkqtmeq2vb6siyu40vxnw4c8vq` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_name` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_note` +-- + +DROP TABLE IF EXISTS `ix_ginas_note`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_note` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `note` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `note_owner_index` (`owner_uuid`), + KEY `fkge1aq2fv84ucy1ilwx97vpuwu` (`created_by_id`), + KEY `fkpg2o4yxwwlbbw1rro1c5df60` (`last_edited_by_id`), + CONSTRAINT `fkge1aq2fv84ucy1ilwx97vpuwu` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkj3nrt8342rqojj5d4k24w5tgm` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkpg2o4yxwwlbbw1rro1c5df60` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_nucleicacid` +-- + +DROP TABLE IF EXISTS `ix_ginas_nucleicacid`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_nucleicacid` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `nucleic_acid_sub_type` varchar(255) DEFAULT NULL, + `nucleic_acid_type` varchar(255) DEFAULT NULL, + `sequence_origin` varchar(255) DEFAULT NULL, + `sequence_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `modifications_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkm9yv3dunytjgyjfiq6r503lyr` (`created_by_id`), + KEY `fk6jk9rw9co4676wg98pvseggxc` (`last_edited_by_id`), + KEY `fkck0ay4di4y12vsqd9gqw4qh4b` (`modifications_uuid`), + CONSTRAINT `fk6jk9rw9co4676wg98pvseggxc` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkck0ay4di4y12vsqd9gqw4qh4b` FOREIGN KEY (`modifications_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), + CONSTRAINT `fkm9yv3dunytjgyjfiq6r503lyr` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_nucleicacid_subunits` +-- + +DROP TABLE IF EXISTS `ix_ginas_nucleicacid_subunits`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_nucleicacid_subunits` ( + `ix_ginas_nucleicacid_uuid` varchar(40) NOT NULL, + `ix_ginas_subunit_uuid` varchar(40) NOT NULL, + KEY `fkjun57ycd07jv8oe3h8566r488` (`ix_ginas_subunit_uuid`), + KEY `fkdby8ustw4fo38x6e98cg814td` (`ix_ginas_nucleicacid_uuid`), + CONSTRAINT `fkdby8ustw4fo38x6e98cg814td` FOREIGN KEY (`ix_ginas_nucleicacid_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`), + CONSTRAINT `fkjun57ycd07jv8oe3h8566r488` FOREIGN KEY (`ix_ginas_subunit_uuid`) REFERENCES `ix_ginas_subunit` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_otherlinks` +-- + +DROP TABLE IF EXISTS `ix_ginas_otherlinks`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_otherlinks` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `linkage_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `site_container_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk9sukhdr4s0yje92m8hp82hitx` (`created_by_id`), + KEY `fkigwh0j2irewbpsb1xgael3pim` (`last_edited_by_id`), + KEY `fkdub4td7p5ki0u4dl83j4u9ysr` (`owner_uuid`), + KEY `fk5nj85bcu54jc56se3hm4q3chm` (`site_container_uuid`), + CONSTRAINT `fk5nj85bcu54jc56se3hm4q3chm` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), + CONSTRAINT `fk9sukhdr4s0yje92m8hp82hitx` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkdub4td7p5ki0u4dl83j4u9ysr` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_protein` (`uuid`), + CONSTRAINT `fkigwh0j2irewbpsb1xgael3pim` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_parameter` +-- + +DROP TABLE IF EXISTS `ix_ginas_parameter`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_parameter` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `name` varchar(255) NOT NULL, + `type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `referenced_substance_uuid` varchar(40) DEFAULT NULL, + `value_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fklbuqth4cgx61sh4rcci2mdl1o` (`created_by_id`), + KEY `fklj93g1oplslasut6r924dft2l` (`last_edited_by_id`), + KEY `fk9ixg1ch1e0hueyta2dh4vlidg` (`owner_uuid`), + KEY `fkdxnyu34iqqponnw4bnj9hk8rb` (`referenced_substance_uuid`), + KEY `fkix1d880p7x7v51quhcre616af` (`value_uuid`), + CONSTRAINT `fk9ixg1ch1e0hueyta2dh4vlidg` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_property` (`uuid`), + CONSTRAINT `fkdxnyu34iqqponnw4bnj9hk8rb` FOREIGN KEY (`referenced_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkix1d880p7x7v51quhcre616af` FOREIGN KEY (`value_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fklbuqth4cgx61sh4rcci2mdl1o` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fklj93g1oplslasut6r924dft2l` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_physicalmod` +-- + +DROP TABLE IF EXISTS `ix_ginas_physicalmod`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_physicalmod` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `modification_group` varchar(255) DEFAULT NULL, + `physical_modification_role` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk32ojpkiiy03fk8ro0eyclrbkh` (`created_by_id`), + KEY `fk23yuiouuyqodtlxmjxopv0ybf` (`last_edited_by_id`), + KEY `fkd8fg9mm0ilkfdii08s5qsonde` (`owner_uuid`), + CONSTRAINT `fk23yuiouuyqodtlxmjxopv0ybf` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk32ojpkiiy03fk8ro0eyclrbkh` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkd8fg9mm0ilkfdii08s5qsonde` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_physicalpar` +-- + +DROP TABLE IF EXISTS `ix_ginas_physicalpar`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_physicalpar` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `parameter_name` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkrfgl3mys5n5wiknd32enb7hmb` (`created_by_id`), + KEY `fkd1w1xyqt12divo39phpoi2113` (`last_edited_by_id`), + KEY `fk4ce1vbnehe206ru4gctnlkidh` (`amount_uuid`), + KEY `fk1e30fjxi7rv1m875713tges77` (`owner_uuid`), + CONSTRAINT `fk1e30fjxi7rv1m875713tges77` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_physicalmod` (`uuid`), + CONSTRAINT `fk4ce1vbnehe206ru4gctnlkidh` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fkd1w1xyqt12divo39phpoi2113` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkrfgl3mys5n5wiknd32enb7hmb` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_polymer` +-- + +DROP TABLE IF EXISTS `ix_ginas_polymer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_polymer` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `classification_uuid` varchar(40) DEFAULT NULL, + `display_structure_id` varchar(40) DEFAULT NULL, + `idealized_structure_id` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk8axkm0cbpwpc43krkhw8y6tad` (`created_by_id`), + KEY `fk5o81f597yvub0mf1b6cnqx8ev` (`last_edited_by_id`), + KEY `fktn8tft3hwqnpv8tkfhtbh5jsm` (`classification_uuid`), + KEY `fkcd56mdyyo9bvrrd80w0y8iixl` (`display_structure_id`), + KEY `fk264hsvr9c8q3w1e51j99ua2d0` (`idealized_structure_id`), + CONSTRAINT `fk264hsvr9c8q3w1e51j99ua2d0` FOREIGN KEY (`idealized_structure_id`) REFERENCES `ix_core_structure` (`id`), + CONSTRAINT `fk5o81f597yvub0mf1b6cnqx8ev` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk8axkm0cbpwpc43krkhw8y6tad` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkcd56mdyyo9bvrrd80w0y8iixl` FOREIGN KEY (`display_structure_id`) REFERENCES `ix_core_structure` (`id`), + CONSTRAINT `fktn8tft3hwqnpv8tkfhtbh5jsm` FOREIGN KEY (`classification_uuid`) REFERENCES `polymer_classification` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_property` +-- + +DROP TABLE IF EXISTS `ix_ginas_property`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_property` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `defining` bit(1) DEFAULT NULL, + `name` varchar(255) NOT NULL, + `property_type` varchar(255) DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `referenced_substance_uuid` varchar(40) DEFAULT NULL, + `value_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `property_owner_index` (`owner_uuid`), + KEY `fktla10hxba7smca0g675soamsq` (`created_by_id`), + KEY `fkafltirwo87s1so6vigtf1s8mn` (`last_edited_by_id`), + KEY `fkoh8nhvrowpdthcxj69pwkke9t` (`referenced_substance_uuid`), + KEY `fkpbekqdofak8ol2fq92f5onn1t` (`value_uuid`), + CONSTRAINT `fkafltirwo87s1so6vigtf1s8mn` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkoh8nhvrowpdthcxj69pwkke9t` FOREIGN KEY (`referenced_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkpbekqdofak8ol2fq92f5onn1t` FOREIGN KEY (`value_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fkrlu3e72lq9y59122xd75q51vt` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fktla10hxba7smca0g675soamsq` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_protein` +-- + +DROP TABLE IF EXISTS `ix_ginas_protein`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_protein` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `disulf_json` longtext DEFAULT NULL, + `protein_sub_type` varchar(255) DEFAULT NULL, + `protein_type` varchar(255) DEFAULT NULL, + `sequence_origin` varchar(255) DEFAULT NULL, + `sequence_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `glycosylation_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk6ay15bqty5r2xmk13a4ld75rm` (`created_by_id`), + KEY `fkpovxe3t3ycsa1x6xivr20ukbh` (`last_edited_by_id`), + KEY `fkec7ms0paeosyymbpsnbu5pjfb` (`glycosylation_uuid`), + CONSTRAINT `fk6ay15bqty5r2xmk13a4ld75rm` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkec7ms0paeosyymbpsnbu5pjfb` FOREIGN KEY (`glycosylation_uuid`) REFERENCES `ix_ginas_glycosylation` (`uuid`), + CONSTRAINT `fkpovxe3t3ycsa1x6xivr20ukbh` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_protein_subunit` +-- + +DROP TABLE IF EXISTS `ix_ginas_protein_subunit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_protein_subunit` ( + `ix_ginas_protein_uuid` varchar(40) NOT NULL, + `ix_ginas_subunit_uuid` varchar(40) NOT NULL, + KEY `fklk7qxuwt9o7g8k6rphr5jj7ey` (`ix_ginas_subunit_uuid`), + KEY `fk39xyg6fxghld06apb91xc1xt6` (`ix_ginas_protein_uuid`), + CONSTRAINT `fk39xyg6fxghld06apb91xc1xt6` FOREIGN KEY (`ix_ginas_protein_uuid`) REFERENCES `ix_ginas_protein` (`uuid`), + CONSTRAINT `fklk7qxuwt9o7g8k6rphr5jj7ey` FOREIGN KEY (`ix_ginas_subunit_uuid`) REFERENCES `ix_ginas_subunit` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_reference` +-- + +DROP TABLE IF EXISTS `ix_ginas_reference`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_reference` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `citation` longtext DEFAULT NULL, + `doc_type` varchar(255) DEFAULT NULL, + `document_date` datetime(6) DEFAULT NULL, + `id` varchar(255) DEFAULT NULL, + `public_domain` bit(1) NOT NULL, + `tags` longtext DEFAULT NULL, + `uploaded_file` varchar(1024) DEFAULT NULL, + `url` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `ref_id_index` (`id`), + KEY `ref_owner_index` (`owner_uuid`), + KEY `fkpv1epn9el8d1fpqct4px1nio7` (`created_by_id`), + KEY `fk975dqn3b674b23ga0igmmct25` (`last_edited_by_id`), + CONSTRAINT `fk975dqn3b674b23ga0igmmct25` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkk7kui3q4qm7pwdq679ibkyi5h` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkpv1epn9el8d1fpqct4px1nio7` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_relationship` +-- + +DROP TABLE IF EXISTS `ix_ginas_relationship`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_relationship` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `comments` longtext DEFAULT NULL, + `interaction_type` varchar(255) DEFAULT NULL, + `originator_uuid` varchar(255) DEFAULT NULL, + `qualification` varchar(255) DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + `mediator_substance_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `related_substance_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `interaction_index` (`interaction_type`), + KEY `qualification_index` (`qualification`), + KEY `type_index` (`type`), + KEY `relate_originate_index` (`originator_uuid`), + KEY `rel_owner_index` (`owner_uuid`), + KEY `fk70gmjxu8uevujxd4uetj6nfm3` (`created_by_id`), + KEY `fkmsd9lm6ayae7qbwp1iv50ftbb` (`last_edited_by_id`), + KEY `fk492eul84p3uecmkpqmd8ujvkb` (`amount_uuid`), + KEY `fksim8mqlrevhpl0aa0hrdh3wwe` (`mediator_substance_uuid`), + KEY `fkb6yhrsc7dprxg0apyknpue5ij` (`related_substance_uuid`), + CONSTRAINT `fk492eul84p3uecmkpqmd8ujvkb` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fk70gmjxu8uevujxd4uetj6nfm3` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkb6yhrsc7dprxg0apyknpue5ij` FOREIGN KEY (`related_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkmsd9lm6ayae7qbwp1iv50ftbb` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkr1msd0rheudj2srgokqrftrek` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fksim8mqlrevhpl0aa0hrdh3wwe` FOREIGN KEY (`mediator_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_site_lob` +-- + +DROP TABLE IF EXISTS `ix_ginas_site_lob`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_site_lob` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `site_count` bigint(20) NOT NULL, + `site_type` varchar(255) DEFAULT NULL, + `sites_json` longtext DEFAULT NULL, + `sites_short_hand` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkfbc7le8ehsxj39t2yikmmy3py` (`created_by_id`), + KEY `fkh2cg1v3f9ha8t0w4l8iprib2g` (`last_edited_by_id`), + CONSTRAINT `fkfbc7le8ehsxj39t2yikmmy3py` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkh2cg1v3f9ha8t0w4l8iprib2g` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_ssg1` +-- + +DROP TABLE IF EXISTS `ix_ginas_ssg1`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_ssg1` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk3tljtp4q2e94j2q27hgnnhse4` (`created_by_id`), + KEY `fkle7gsf4fuf75tsrvksgvkjc25` (`last_edited_by_id`), + CONSTRAINT `fk3tljtp4q2e94j2q27hgnnhse4` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkle7gsf4fuf75tsrvksgvkjc25` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_strucdiv` +-- + +DROP TABLE IF EXISTS `ix_ginas_strucdiv`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_strucdiv` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `developmental_stage` varchar(255) DEFAULT NULL, + `fraction_material_type` varchar(255) DEFAULT NULL, + `fraction_name` varchar(255) DEFAULT NULL, + `infra_specific_name` varchar(255) DEFAULT NULL, + `infra_specific_type` varchar(255) DEFAULT NULL, + `organism_author` varchar(255) DEFAULT NULL, + `organism_family` varchar(255) DEFAULT NULL, + `organism_genus` varchar(255) DEFAULT NULL, + `organism_species` varchar(255) DEFAULT NULL, + `part` longtext DEFAULT NULL, + `part_location` varchar(255) DEFAULT NULL, + `source_material_class` varchar(255) DEFAULT NULL, + `source_material_state` varchar(255) DEFAULT NULL, + `source_material_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `maternal_uuid` varchar(40) DEFAULT NULL, + `paternal_uuid` varchar(40) DEFAULT NULL, + `parent_substance_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkqpk4af5q91r4nsm521kd57298` (`created_by_id`), + KEY `fk4epq4o38ci57y71dxu7ootl41` (`last_edited_by_id`), + KEY `fkhh72pwq35aaqgv370uavhtnjh` (`maternal_uuid`), + KEY `fk6lcu1945kbaxi6fmir3qt5ugk` (`paternal_uuid`), + KEY `fk27p7qapsxr5d2efscf8k7521` (`parent_substance_uuid`), + CONSTRAINT `fk27p7qapsxr5d2efscf8k7521` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fk4epq4o38ci57y71dxu7ootl41` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk6lcu1945kbaxi6fmir3qt5ugk` FOREIGN KEY (`paternal_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkhh72pwq35aaqgv370uavhtnjh` FOREIGN KEY (`maternal_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkqpk4af5q91r4nsm521kd57298` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_structuralmod` +-- + +DROP TABLE IF EXISTS `ix_ginas_structuralmod`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_structuralmod` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `extent` varchar(255) DEFAULT NULL, + `location_type` varchar(255) DEFAULT NULL, + `modification_group` varchar(255) DEFAULT NULL, + `moleculare_fragment_role` varchar(255) DEFAULT NULL, + `residue_modified` varchar(255) DEFAULT NULL, + `structural_modification_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `extent_amount_uuid` varchar(40) DEFAULT NULL, + `molecular_fragment_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `site_container_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkndd0pxjud610e953hg730emw` (`created_by_id`), + KEY `fk1ysjs1dx6uo8flj8rkiscscx4` (`last_edited_by_id`), + KEY `fktkmtm9vpmaklmypp3jad1pspp` (`extent_amount_uuid`), + KEY `fk6n3mtotuwqi717fr2evp3dfxi` (`molecular_fragment_uuid`), + KEY `fkoi4vt2lg0x2v3s4urckwjb3s3` (`owner_uuid`), + KEY `fkb94sjca6cclvcwtx2osvdeuu` (`site_container_uuid`), + CONSTRAINT `fk1ysjs1dx6uo8flj8rkiscscx4` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk6n3mtotuwqi717fr2evp3dfxi` FOREIGN KEY (`molecular_fragment_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), + CONSTRAINT `fkb94sjca6cclvcwtx2osvdeuu` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), + CONSTRAINT `fkndd0pxjud610e953hg730emw` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkoi4vt2lg0x2v3s4urckwjb3s3` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), + CONSTRAINT `fktkmtm9vpmaklmypp3jad1pspp` FOREIGN KEY (`extent_amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_substance` +-- + +DROP TABLE IF EXISTS `ix_ginas_substance`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_substance` ( + `DTYPE` varchar(31) NOT NULL, + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `approval_id` varchar(20) DEFAULT NULL, + `approved` datetime(6) DEFAULT NULL, + `change_reason` varchar(255) DEFAULT NULL, + `definition_level` int(11) DEFAULT NULL, + `definition_type` int(11) DEFAULT NULL, + `status` varchar(255) DEFAULT NULL, + `class` int(11) DEFAULT NULL, + `version` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `approved_by_id` bigint(20) DEFAULT NULL, + `modifications_uuid` varchar(40) DEFAULT NULL, + `structure_id` varchar(40) DEFAULT NULL, + `specified_substance_uuid` varchar(40) DEFAULT NULL, + `nucleic_acid_uuid` varchar(40) DEFAULT NULL, + `polymer_uuid` varchar(40) DEFAULT NULL, + `structurally_diverse_uuid` varchar(40) DEFAULT NULL, + `protein_uuid` varchar(40) DEFAULT NULL, + `mixture_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `sub_approval_index` (`approval_id`), + KEY `sub_dtype_index` (`DTYPE`), + KEY `fka9b6lpf9y3l0t04rviskjs8o1` (`created_by_id`), + KEY `fk9hlo5n1alfg4rgloypq8agc3e` (`last_edited_by_id`), + KEY `fkmb0vxvmui506xtkh18lw1ucym` (`approved_by_id`), + KEY `fk30b2jg1r8dr4ibvt3f4h7ui3b` (`modifications_uuid`), + KEY `fkau9cajhw1nffg9w1vh0am4ls4` (`structure_id`), + KEY `fkd29meikxu3elfx1w5dket3ia5` (`specified_substance_uuid`), + KEY `fk8lglxcodtpv6nj0wbw61cpdk9` (`nucleic_acid_uuid`), + KEY `fkncdqbv3ilcg21bws3e3y0xwg4` (`polymer_uuid`), + KEY `fkhrs798kf99tmayeg8hjbo9vdl` (`structurally_diverse_uuid`), + KEY `fkcw3qqer4es16onh3qgcuf6jb8` (`protein_uuid`), + KEY `fkekk08a5uheng9eocf61xo4m2l` (`mixture_uuid`), + CONSTRAINT `fk30b2jg1r8dr4ibvt3f4h7ui3b` FOREIGN KEY (`modifications_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), + CONSTRAINT `fk8lglxcodtpv6nj0wbw61cpdk9` FOREIGN KEY (`nucleic_acid_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`), + CONSTRAINT `fk9hlo5n1alfg4rgloypq8agc3e` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fka9b6lpf9y3l0t04rviskjs8o1` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkau9cajhw1nffg9w1vh0am4ls4` FOREIGN KEY (`structure_id`) REFERENCES `ix_core_structure` (`id`), + CONSTRAINT `fkcw3qqer4es16onh3qgcuf6jb8` FOREIGN KEY (`protein_uuid`) REFERENCES `ix_ginas_protein` (`uuid`), + CONSTRAINT `fkd29meikxu3elfx1w5dket3ia5` FOREIGN KEY (`specified_substance_uuid`) REFERENCES `ix_ginas_ssg1` (`uuid`), + CONSTRAINT `fkekk08a5uheng9eocf61xo4m2l` FOREIGN KEY (`mixture_uuid`) REFERENCES `ix_ginas_mixture` (`uuid`), + CONSTRAINT `fkhrs798kf99tmayeg8hjbo9vdl` FOREIGN KEY (`structurally_diverse_uuid`) REFERENCES `ix_ginas_strucdiv` (`uuid`), + CONSTRAINT `fkmb0vxvmui506xtkh18lw1ucym` FOREIGN KEY (`approved_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkncdqbv3ilcg21bws3e3y0xwg4` FOREIGN KEY (`polymer_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_substance_mix_comp` +-- + +DROP TABLE IF EXISTS `ix_ginas_substance_mix_comp`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_substance_mix_comp` ( + `ix_ginas_mixture_uuid` varchar(40) NOT NULL, + `ix_ginas_component_uuid` varchar(40) NOT NULL, + KEY `fkjsfcmh12rru7tls24cbkbmb0t` (`ix_ginas_component_uuid`), + KEY `fkpubptahgdm25hadwlf3pwlfap` (`ix_ginas_mixture_uuid`), + CONSTRAINT `fkjsfcmh12rru7tls24cbkbmb0t` FOREIGN KEY (`ix_ginas_component_uuid`) REFERENCES `ix_ginas_component` (`uuid`), + CONSTRAINT `fkpubptahgdm25hadwlf3pwlfap` FOREIGN KEY (`ix_ginas_mixture_uuid`) REFERENCES `ix_ginas_mixture` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_substance_ss_comp` +-- + +DROP TABLE IF EXISTS `ix_ginas_substance_ss_comp`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_substance_ss_comp` ( + `ix_ginas_ssg1_uuid` varchar(40) NOT NULL, + `ix_ginas_component_uuid` varchar(40) NOT NULL, + KEY `fkb8ofx08elpr455o7a72rrr9tm` (`ix_ginas_component_uuid`), + KEY `fkaf57kow6qnxnp2ya35n21jiyo` (`ix_ginas_ssg1_uuid`), + CONSTRAINT `fkaf57kow6qnxnp2ya35n21jiyo` FOREIGN KEY (`ix_ginas_ssg1_uuid`) REFERENCES `ix_ginas_ssg1` (`uuid`), + CONSTRAINT `fkb8ofx08elpr455o7a72rrr9tm` FOREIGN KEY (`ix_ginas_component_uuid`) REFERENCES `ix_ginas_component` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_substance_tags` +-- + +DROP TABLE IF EXISTS `ix_ginas_substance_tags`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_substance_tags` ( + `ix_ginas_substance_uuid` varchar(40) NOT NULL, + `ix_core_value_id` bigint(20) NOT NULL, + KEY `fkjlsvy9nlwl3vf5mvhcvf0y80k` (`ix_core_value_id`), + KEY `fk2hyjvdeqia2qiemoagh6yjq6b` (`ix_ginas_substance_uuid`), + CONSTRAINT `fk2hyjvdeqia2qiemoagh6yjq6b` FOREIGN KEY (`ix_ginas_substance_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), + CONSTRAINT `fkjlsvy9nlwl3vf5mvhcvf0y80k` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_substanceref` +-- + +DROP TABLE IF EXISTS `ix_ginas_substanceref`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_substanceref` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `approval_ID` varchar(32) DEFAULT NULL, + `ref_pname` varchar(1024) DEFAULT NULL, + `refuuid` varchar(128) DEFAULT NULL, + `substance_class` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `sub_ref_index` (`refuuid`), + KEY `fko2bjxrp2qi847appx7ecf65vc` (`created_by_id`), + KEY `fkm6qbi1moehd7wqh9w2ip412us` (`last_edited_by_id`), + CONSTRAINT `fkm6qbi1moehd7wqh9w2ip412us` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fko2bjxrp2qi847appx7ecf65vc` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_subunit` +-- + +DROP TABLE IF EXISTS `ix_ginas_subunit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_subunit` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `sequence` longtext DEFAULT NULL, + `subunit_index` int(11) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk7kjfdjus3twoyg4vd2jp367n6` (`created_by_id`), + KEY `fk9pyegqu1n4ekd45fdmitw12t7` (`last_edited_by_id`), + CONSTRAINT `fk7kjfdjus3twoyg4vd2jp367n6` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk9pyegqu1n4ekd45fdmitw12t7` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_sugar` +-- + +DROP TABLE IF EXISTS `ix_ginas_sugar`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_sugar` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `sugar` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + `site_container_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fke6ndxx94bjimsgux4lygsh51f` (`created_by_id`), + KEY `fk1p4pfd811kxxjqfxbiuu9sknv` (`last_edited_by_id`), + KEY `fkkx0aeyak8r0byugf719kqu7ms` (`owner_uuid`), + KEY `fkpx5dhn0168ipbpu04xgmby97y` (`site_container_uuid`), + CONSTRAINT `fk1p4pfd811kxxjqfxbiuu9sknv` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fke6ndxx94bjimsgux4lygsh51f` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkkx0aeyak8r0byugf719kqu7ms` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`), + CONSTRAINT `fkpx5dhn0168ipbpu04xgmby97y` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_unit` +-- + +DROP TABLE IF EXISTS `ix_ginas_unit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_unit` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `attachmentMap` longtext DEFAULT NULL, + `attachment_count` int(11) DEFAULT NULL, + `label` varchar(255) DEFAULT NULL, + `structure` longtext DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `amap_id` bigint(20) DEFAULT NULL, + `amount_uuid` varchar(40) DEFAULT NULL, + `owner_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fkl4qe419byvtxe3epgd4a50glc` (`created_by_id`), + KEY `fknbsd63mfulnly1dtk7f6vxcq4` (`last_edited_by_id`), + KEY `fkq8b5gi5r7thxi8vyrli5lrtu2` (`amap_id`), + KEY `fk2x4h6n93ud35rtm5nxt7xrcmw` (`amount_uuid`), + KEY `fkf3rxpagehygabef32q3kn4am` (`owner_uuid`), + CONSTRAINT `fk2x4h6n93ud35rtm5nxt7xrcmw` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), + CONSTRAINT `fkf3rxpagehygabef32q3kn4am` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`), + CONSTRAINT `fkl4qe419byvtxe3epgd4a50glc` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fknbsd63mfulnly1dtk7f6vxcq4` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkq8b5gi5r7thxi8vyrli5lrtu2` FOREIGN KEY (`amap_id`) REFERENCES `ix_core_value` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_ginas_vocabulary_term` +-- + +DROP TABLE IF EXISTS `ix_ginas_vocabulary_term`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_ginas_vocabulary_term` ( + `DTYPE` varchar(31) NOT NULL, + `id` bigint(20) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `deprecated` bit(1) NOT NULL, + `modified` datetime(6) DEFAULT NULL, + `version` bigint(20) DEFAULT NULL, + `description` varchar(4000) DEFAULT NULL, + `display` varchar(3000) DEFAULT NULL, + `filters` longtext DEFAULT NULL, + `hidden` bit(1) NOT NULL, + `origin` varchar(255) DEFAULT NULL, + `regex` varchar(3000) DEFAULT NULL, + `selected` bit(1) NOT NULL, + `term_value` varchar(3000) DEFAULT NULL, + `system_category` varchar(255) DEFAULT NULL, + `fragment_structure` varchar(255) DEFAULT NULL, + `simplified_structure` varchar(255) DEFAULT NULL, + `namespace_id` bigint(20) DEFAULT NULL, + `owner_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `vocabulary_term_owner_index` (`owner_id`), + KEY `fk3t5cvdqdtqn0eqc1654fbxhqt` (`namespace_id`), + CONSTRAINT `fk3t5cvdqdtqn0eqc1654fbxhqt` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`), + CONSTRAINT `fkbk04rq7l3tav8pey5rm2j14hm` FOREIGN KEY (`owner_id`) REFERENCES `ix_ginas_controlled_vocab` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_import_data` +-- + +DROP TABLE IF EXISTS `ix_import_data`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_import_data` ( + `instance_id` varchar(40) NOT NULL, + `data` longtext DEFAULT NULL, + `entity_class_name` varchar(255) DEFAULT NULL, + `record_id` varchar(40) DEFAULT NULL, + `save_date` datetime(6) DEFAULT NULL, + `version` int(11) NOT NULL, + PRIMARY KEY (`instance_id`), + KEY `idx_ix_import_data_entity_class_name` (`entity_class_name`), + KEY `idx_ix_import_data_version` (`version`), + KEY `idx_ix_import_data_record_id` (`record_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_import_mapping` +-- + +DROP TABLE IF EXISTS `ix_import_mapping`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_import_mapping` ( + `mapping_id` varchar(40) NOT NULL, + `data_location` varchar(255) DEFAULT NULL, + `entity_class` varchar(255) DEFAULT NULL, + `instance_id` varchar(40) DEFAULT NULL, + `mapping_key` varchar(255) DEFAULT NULL, + `qualifier` varchar(255) DEFAULT NULL, + `record_id` varchar(40) DEFAULT NULL, + `mapping_value` varchar(512) DEFAULT NULL, + PRIMARY KEY (`mapping_id`), + KEY `idx_ix_import_mapping_key` (`mapping_key`), + KEY `idx_ix_import_mapping_value` (`mapping_value`), + KEY `idx_ix_import_mapping_instance_id` (`instance_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_import_metadata` +-- + +DROP TABLE IF EXISTS `ix_import_metadata`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_import_metadata` ( + `record_id` varchar(40) NOT NULL, + `data_format` varchar(255) DEFAULT NULL, + `entity_class_name` varchar(255) DEFAULT NULL, + `import_adapter` varchar(255) DEFAULT NULL, + `import_status` int(11) DEFAULT NULL, + `import_type` int(11) DEFAULT NULL, + `instance_id` varchar(40) DEFAULT NULL, + `process_status` int(11) DEFAULT NULL, + `reason` varchar(255) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `source_name` varchar(255) DEFAULT NULL, + `validation_status` int(11) DEFAULT NULL, + `version` int(11) NOT NULL, + `version_creation_date` datetime(6) DEFAULT NULL, + `version_status` int(11) DEFAULT NULL, + `imported_by_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`record_id`), + UNIQUE KEY `UK_b3wth3q98eiauf3rngwjybxve` (`instance_id`), + KEY `idx_ix_import_metadata_entity_class_name` (`entity_class_name`), + KEY `fkn75dm5x09m6wvk7uq5q74do9c` (`imported_by_id`), + CONSTRAINT `fkn75dm5x09m6wvk7uq5q74do9c` FOREIGN KEY (`imported_by_id`) REFERENCES `ix_core_principal` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_import_raw` +-- + +DROP TABLE IF EXISTS `ix_import_raw`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_import_raw` ( + `record_id` varchar(40) NOT NULL, + `raw_data` longblob DEFAULT NULL, + `record_format` varchar(255) DEFAULT NULL, + PRIMARY KEY (`record_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ix_import_validation` +-- + +DROP TABLE IF EXISTS `ix_import_validation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ix_import_validation` ( + `validation_id` varchar(40) NOT NULL, + `validation_date` datetime(6) DEFAULT NULL, + `validation_json` longtext DEFAULT NULL, + `validation_message` varchar(2048) DEFAULT NULL, + `validation_type` int(11) DEFAULT NULL, + `entity_class_name` varchar(255) DEFAULT NULL, + `instance_id` varchar(40) DEFAULT NULL, + `version` int(11) NOT NULL, + PRIMARY KEY (`validation_id`), + KEY `idx_ix_import_validation_entity_class_name` (`entity_class_name`), + KEY `idx_ix_import_validation_version` (`version`), + KEY `idx_ix_import_validation_instance_id` (`instance_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `polymer_classification` +-- + +DROP TABLE IF EXISTS `polymer_classification`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `polymer_classification` ( + `uuid` varchar(40) NOT NULL, + `created` datetime(6) DEFAULT NULL, + `current_version` int(11) NOT NULL, + `deprecated` bit(1) NOT NULL, + `internal_version` bigint(20) DEFAULT NULL, + `last_edited` datetime(6) DEFAULT NULL, + `record_access` mediumblob DEFAULT NULL, + `internal_references` longtext DEFAULT NULL, + `polymer_class` varchar(255) DEFAULT NULL, + `polymer_geometry` varchar(255) DEFAULT NULL, + `polymer_subclass` longtext DEFAULT NULL, + `source_type` varchar(255) DEFAULT NULL, + `created_by_id` bigint(20) DEFAULT NULL, + `last_edited_by_id` bigint(20) DEFAULT NULL, + `parent_substance_uuid` varchar(40) DEFAULT NULL, + PRIMARY KEY (`uuid`), + KEY `fk9tp2yhc5vdofsdnx5cit45hdy` (`created_by_id`), + KEY `fk6bup6ku2dri7cl4rgno4fd6dd` (`last_edited_by_id`), + KEY `fkl3chbblh2guqlw9ikn9grc3vb` (`parent_substance_uuid`), + CONSTRAINT `fk6bup6ku2dri7cl4rgno4fd6dd` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fk9tp2yhc5vdofsdnx5cit45hdy` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), + CONSTRAINT `fkl3chbblh2guqlw9ikn9grc3vb` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping routines for database 'ixginas_local' +-- +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-05-21 13:18:49 diff --git a/docs/COLIMA_GUIDE.md b/docs/COLIMA_GUIDE.md index 27d45598a..b626df105 100644 --- a/docs/COLIMA_GUIDE.md +++ b/docs/COLIMA_GUIDE.md @@ -15,6 +15,11 @@ _Last updated: 17.12.2024_ ## Start Colima - `colima start -f --cpu 4 --memory 10 --disk 30 --arch aarch64 --vz-rosetta --mount-type=virtiofs` +> **Note:** If you also run GSRS locally (`PFDA_SHOULD_RUN_GSRS=1`), increase the disk to at least 50 GiB: +> ``` +> colima start -f --cpu 4 --memory 10 --disk 50 --arch aarch64 --vz-rosetta --mount-type=virtiofs +> ``` + ## Run PFDA - From inside the project root `make run` diff --git a/docs/DOCKER_BASED_SETUP.md b/docs/DOCKER_BASED_SETUP.md index 068bba5d3..7e0886293 100644 --- a/docs/DOCKER_BASED_SETUP.md +++ b/docs/DOCKER_BASED_SETUP.md @@ -105,40 +105,95 @@ make stop ### Running application with external services (GSRS) -To include GSRS in the local stack, set `PFDA_SHOULD_RUN_GSRS=1` for the command or export it in your shell profile: +GSRS runs as part of the local Docker stack. A schema-only database is included in the repo so GSRS can start empty without any downloads. For a fully populated instance (substance data + Lucene search index), run `make gsrs-seed-data` first — this downloads the data from S3 and requires the AWS CLI to be installed and configured: ```bash -PFDA_SHOULD_RUN_GSRS=1 make run +# Install the AWS CLI (macOS) +brew install awscli + +# Configure credentials (use your access key from the AWS console) +aws configure +``` + +#### Quick start + +```bash +# Add to ~/.bashrc or ~/.zshrc +export PFDA_SHOULD_RUN_GSRS=1 ``` -#### Switch GSRS version running in the container +Then run as usual: + +```bash +make run +``` + +To populate with full substance data and search index: + +```bash +make gsrs-seed-data +make run +``` + +This starts the GSRS backend, MariaDB (schema from `docker/misc/gsrs-db-init/01-gsrsdb-schema.sql`), and nginx sidecar. If you ran `make gsrs-seed-data`, the full data dump and Lucene index are also loaded. + +GSRS UI is available at `https://localhost:3000/ginas/app/ui/`. + +#### Environment variables -1. Connect to the running container. -2. Run script _run-version.sh_. -3. When prompted, paste the required GSRS version branch name from the [gsrs-play-dist repo](https://github.com/dnanexus/gsrs-play-dist). +| Variable | Default | Description | +|----------|---------|-------------| +| `PFDA_SHOULD_RUN_GSRS` | _(unset)_ | Set to `1` to include GSRS containers | +| `GSRS_LOCAL_MODE` | `true` | Symlinks index directly (required for macOS) | +| `GSRS_INDEX_PATH` | `packages/gsrs/seed-data/ginas.ix` | Path to Lucene index directory | +| `GSRS_FRONTEND_DEV` | `false` | Set to `true` to enable live frontend dev server | +| `GSRS_FRONTEND_PATH` | _(unset)_ | Absolute path to GSRSFrontend repo (required when `GSRS_FRONTEND_DEV=true`) | -#### GSRS frontend development live update +#### Resetting GSRS data -Once the _gsrs_ container is running, you can use it for GSRS frontend development: +To start fresh (wipe DB and index): -1. Clone the [GSRSFrontend repo](https://github.com/ncats/GSRSFrontend/tree/precision_new), branch _precision_new_. -2. Create `GSRS_FRONTEND_PATH` (for example in `~/.zshrc`) with an absolute path to the repo, such as _/Users/pbarta@dnanexus.com/ncats/GSRSFrontend_. -3. Restart the _gsrs_ container. -4. Edit several config files in the cloned repo. These changes are not supposed to be committed: - * `angular.json` - add line `"baseHref": "/ginas/app/ui/",` under `projects.gsrs-client.architect.options` - * `src/app/fda/config/config.json` - add line `"customToolbarComponent": "precisionFDA",` - * `src/environments/environment.fda.local.ts` - set the following variables: - ```bash +```bash +make stop +docker volume rm precision-fda_db-gsrs-mariadb-volume +``` + +Then `make run` again to recreate with seed data. + +#### GSRS frontend development (live hot reload) + +A dedicated container runs the Angular dev server with hot reload. No manual config edits needed. + +1. Clone [GSRSFrontend repo](https://github.com/ncats/GSRSFrontend), branch `pfda`: + ```bash + git clone -b pfda https://github.com/ncats/GSRSFrontend.git ~/Projects/GSRSFrontend + ``` + +2. Edit several config files in the cloned repo (these changes are not supposed to be committed): + - `angular.json` - add line `"baseHref": "/ginas/app/ui/",` under `projects.gsrs-client.architect.options` + - `src/app/fda/config/config.json` - add lines `"customToolbarComponent": "precisionFDA",` and `"isPfdaVersion": true,` + - `src/environments/environment.fda.local.ts` - set following variables: + ```typescript environment.apiBaseUrl = 'https://localhost:3000/ginas/app/'; environment.baseHref = '/ginas/app/ui/'; ``` -5. Connect to the running _gsrs_ container, run script `switch-frontend.sh` (located in root), and follow the instructions. + +3. Set environment variables (e.g., in `~/.zshrc`): + ```bash + export PFDA_SHOULD_RUN_GSRS=1 + export GSRS_FRONTEND_DEV=true + export GSRS_FRONTEND_PATH=~/Projects/GSRSFrontend + ``` + +4. Run: ```bash - docker exec -it bash - cd / - ./switch-frontend.sh + make run ``` +The frontend dev container installs dependencies and runs `ng serve` with the `fda.local` configuration. Changes to source files in your local GSRSFrontend repo are picked up automatically via polling. + +> **Note:** The first startup takes a few minutes while Angular compiles. Subsequent starts reuse the cached `node_modules` volume. + ## (Optional) Skip cache rebuilds for faster startup After the Docker setup runs successfully, you can save startup time by using [`docker/.env.example`](../docker/.env.example) as a reference and setting skip flags in `docker/.env`. These flags only work if the relevant deps and caches have already been built by a previous successful startup. diff --git a/docs/backend/backend-coding-guide.md b/docs/backend/backend-coding-guide.md index dc5539fdb..975783db8 100644 --- a/docs/backend/backend-coding-guide.md +++ b/docs/backend/backend-coding-guide.md @@ -145,6 +145,11 @@ await this.spaceMembershipRepository.transactional(async () => { }) ``` +- Do not pass transaction-scoped `EntityManager` instances between service/facade methods. +- Start transaction boundaries in the owning service/facade (`this.em.transactional(...)` or repository `.transactional(...)`) and use `this.em` plus constructor-injected repositories inside called methods. +- Prefer repository reads/writes over direct `em.find*` calls for domain entities. + + **Persist pattern:** ```ts // Stage + flush separately (preferred - easy to mock) @@ -367,6 +372,29 @@ Examples: - `entity.type.ts` exports `EntityType` - `entity-instance.ts` exports `EntityInstance` +### File Naming Convention + +General rule for files that act on a domain (facades, DTOs, services, etc.): + +> **`-..ts`** — domain name first (preferably **plural**), then the specifics (action, role, etc.), then the suffix. + +The exported class/symbol must be the PascalCase form of the file name without the suffix (e.g. `cli-assets-list.facade.ts` exports `CliAssetsListFacade`). + +| Component | Pattern | Examples | +|-----------|---------|----------| +| **Facade** | `-[-].facade.ts` | `user-files-list.facade.ts`, `db-clusters-list.facade.ts`, `space-memberships-update-api.facade.ts`, `cli-assets-list.facade.ts` (CLI prefix counts as the qualifier; the domain stays plural and `-list` stays last) | +| **Controller** | `.controller.ts` (use a qualifier suffix only when one controller per domain is not enough, e.g. CLI vs. web) | `space-memberships.controller.ts`, `cli-jobs.controller.ts` | +| **Service** | `.service.ts` for the main domain service; `-.service.ts` for additional internal services | `space-membership.service.ts`, `job-synchronization.service.ts` | +| **Repository** | `.repository.ts` (one repository per entity) | `user.repository.ts`, `setting.repository.ts` | +| **Entity** | `.entity.ts` | `space-membership.entity.ts` | +| **Module** | `.module.ts` for domain modules; `.module.ts` for facade modules (matches the facade file) | `space-membership.module.ts`, `cli-assets-list-facade.module.ts` | +| **DTO** | `-.dto.ts` (action describes the operation/shape, not pluralized) | `app-get.dto.ts`, `update-space-membership.dto.ts`, `pending-user.dto.ts` | +| **Enum** | `.enum.ts` | `space-membership.enum.ts` | + +**Rationale for plural on facades/controllers:** facades and controllers operate on collections/resources, so the plural domain name reads naturally with the action suffix (`db-clusters-list`, `user-files-bulk-download`). Services, repositories, entities, and DTOs describe a single domain concept, so they remain singular. + +**Action verb position:** the action goes **after** the domain (`admin-memberships-list.facade.ts`, not `list-admin-memberships.facade.ts`). This keeps related files sorted together alphabetically by domain. + ## Types - **interface** - default choice diff --git a/docs/guides/frontend.md b/docs/guides/frontend.md index 20240db1e..b01371615 100644 --- a/docs/guides/frontend.md +++ b/docs/guides/frontend.md @@ -438,11 +438,7 @@ export async function deleteItem(id: number) { } ``` -CSRF tokens are set globally in `src/index.tsx`: - -```tsx -Axios.defaults.headers.common['X-CSRF-Token'] = getAuthenticityToken() -``` +CSRF tokens are attached per request in `src/index.tsx` via an axios interceptor that calls `getCsrfToken()` from `@/utils/csrf` for non-GET requests. Fetch-based code (e.g. upload workers) should import helpers from the same module. --- diff --git a/infra/ecs/deploy-ecs-service.py b/infra/ecs/deploy-ecs-service.py index 78237697f..b5a472b77 100644 --- a/infra/ecs/deploy-ecs-service.py +++ b/infra/ecs/deploy-ecs-service.py @@ -73,7 +73,8 @@ def __init__(self, services_file="services.yml"): self.stages = [ ["pfda-db-migrate"], ["pfda-nodejs-api", "pfda-nodejs-api-internal", "pfda-nodejs-worker", - "pfda-nodejs-admin-platform-client", "pfda-web", "pfda-docs", "pfda-nginx"] + "pfda-nodejs-admin-platform-client", "pfda-docs", "pfda-nginx"], + ["pfda-web"] ] if self.deployment_type == "gsrs": @@ -725,6 +726,8 @@ def _get_ssm_secrets(self, service_name, service_config): ecs_secrets.append({"name": "SSL_CERT", "valueFrom": param["Name"]}) elif param["Name"].endswith("/environment/UNII_HOST"): ecs_secrets.append({"name": "UNII_HOST", "valueFrom": param["Name"]}) + elif param["Name"].endswith("RECAPTCHA_SITE_KEY"): + ecs_secrets.append({"name": "RECAPTCHA_SITE_KEY", "valueFrom": param["Name"]}) elif not any(excl in service_name.lower() for excl in exclusions): # Include other parameters only if service is not Nginx ecs_secrets.append({"name": param["Name"].split("/")[-1], "valueFrom": param["Name"]}) diff --git a/package.json b/package.json index f43c3b84b..339ef5d18 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "packageManager": "pnpm@11.1.1", "scripts": { "build": "turbo run build", - "test": "turbo run test" + "test": "turbo run test", + "compose:up": "docker compose --env-file docker/.env -p precision-fda -f docker/arm64v8.dev.docker-compose.yml up --build" }, "repository": {}, "author": "", diff --git a/packages/client/README.md b/packages/client/README.md index be4716cc0..e129ebabd 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -65,7 +65,7 @@ docker compose -p precision-fda --env-file docker/.env -f docker/dev.docker-comp | Service | Description | Port | |-----------------|-----------------------|----------------------| | `frontend` | Vite build for client | - | -| `web` | Rails API server | 5012 (internal 3000) | +| `web` | Rails API server | 3005 (internal 3000) | | `nodejs-api` | Node.js API server | 3001 | | `nodejs-worker` | Background worker | - | | `nginx` | Reverse proxy | 3000 (HTTPS) | diff --git a/packages/client/index.html b/packages/client/index.html index e6b258025..18a32efd5 100644 --- a/packages/client/index.html +++ b/packages/client/index.html @@ -1,9 +1,31 @@ - - - pFDA + + + + + + + + + + + + + + + precisionFDA + diff --git a/packages/client/public/assets/beta-release.png b/packages/client/public/assets/beta-release.png new file mode 100644 index 000000000..f7998e943 Binary files /dev/null and b/packages/client/public/assets/beta-release.png differ diff --git a/packages/rails/app/assets/images/participants/23andme.png b/packages/client/public/assets/participants/23andme.png similarity index 100% rename from packages/rails/app/assets/images/participants/23andme.png rename to packages/client/public/assets/participants/23andme.png diff --git a/packages/rails/app/assets/images/participants/aacr.jpg b/packages/client/public/assets/participants/aacr.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/aacr.jpg rename to packages/client/public/assets/participants/aacr.jpg diff --git a/packages/rails/app/assets/images/participants/aha.png b/packages/client/public/assets/participants/aha.png similarity index 100% rename from packages/rails/app/assets/images/participants/aha.png rename to packages/client/public/assets/participants/aha.png diff --git a/packages/rails/app/assets/images/participants/baylor.png b/packages/client/public/assets/participants/baylor.png similarity index 100% rename from packages/rails/app/assets/images/participants/baylor.png rename to packages/client/public/assets/participants/baylor.png diff --git a/packages/rails/app/assets/images/participants/blueprint_genetics.png b/packages/client/public/assets/participants/blueprint_genetics.png similarity index 100% rename from packages/rails/app/assets/images/participants/blueprint_genetics.png rename to packages/client/public/assets/participants/blueprint_genetics.png diff --git a/packages/rails/app/assets/images/participants/broad.png b/packages/client/public/assets/participants/broad.png similarity index 100% rename from packages/rails/app/assets/images/participants/broad.png rename to packages/client/public/assets/participants/broad.png diff --git a/packages/rails/app/assets/images/participants/cdc.png b/packages/client/public/assets/participants/cdc.png similarity index 100% rename from packages/rails/app/assets/images/participants/cdc.png rename to packages/client/public/assets/participants/cdc.png diff --git a/packages/rails/app/assets/images/participants/counsyl.png b/packages/client/public/assets/participants/counsyl.png similarity index 100% rename from packages/rails/app/assets/images/participants/counsyl.png rename to packages/client/public/assets/participants/counsyl.png diff --git a/packages/rails/app/assets/images/participants/crystal_genetics.png b/packages/client/public/assets/participants/crystal_genetics.png similarity index 100% rename from packages/rails/app/assets/images/participants/crystal_genetics.png rename to packages/client/public/assets/participants/crystal_genetics.png diff --git a/packages/rails/app/assets/images/participants/dennis_wall.jpg b/packages/client/public/assets/participants/dennis_wall.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/dennis_wall.jpg rename to packages/client/public/assets/participants/dennis_wall.jpg diff --git a/packages/rails/app/assets/images/participants/dnanexus.png b/packages/client/public/assets/participants/dnanexus.png similarity index 100% rename from packages/rails/app/assets/images/participants/dnanexus.png rename to packages/client/public/assets/participants/dnanexus.png diff --git a/packages/rails/app/assets/images/participants/dream.png b/packages/client/public/assets/participants/dream.png similarity index 100% rename from packages/rails/app/assets/images/participants/dream.png rename to packages/client/public/assets/participants/dream.png diff --git a/packages/rails/app/assets/images/participants/edico.png b/packages/client/public/assets/participants/edico.png similarity index 100% rename from packages/rails/app/assets/images/participants/edico.png rename to packages/client/public/assets/participants/edico.png diff --git a/packages/rails/app/assets/images/participants/emory.png b/packages/client/public/assets/participants/emory.png similarity index 100% rename from packages/rails/app/assets/images/participants/emory.png rename to packages/client/public/assets/participants/emory.png diff --git a/packages/rails/app/assets/images/participants/euan_ashley.jpg b/packages/client/public/assets/participants/euan_ashley.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/euan_ashley.jpg rename to packages/client/public/assets/participants/euan_ashley.jpg diff --git a/packages/rails/app/assets/images/participants/fda.png b/packages/client/public/assets/participants/fda.png similarity index 100% rename from packages/rails/app/assets/images/participants/fda.png rename to packages/client/public/assets/participants/fda.png diff --git a/packages/rails/app/assets/images/participants/friends_of_cancer_research.png b/packages/client/public/assets/participants/friends_of_cancer_research.png similarity index 100% rename from packages/rails/app/assets/images/participants/friends_of_cancer_research.png rename to packages/client/public/assets/participants/friends_of_cancer_research.png diff --git a/packages/rails/app/assets/images/participants/frontline.png b/packages/client/public/assets/participants/frontline.png similarity index 100% rename from packages/rails/app/assets/images/participants/frontline.png rename to packages/client/public/assets/participants/frontline.png diff --git a/packages/rails/app/assets/images/participants/garvan.png b/packages/client/public/assets/participants/garvan.png similarity index 100% rename from packages/rails/app/assets/images/participants/garvan.png rename to packages/client/public/assets/participants/garvan.png diff --git a/packages/rails/app/assets/images/participants/genedx.png b/packages/client/public/assets/participants/genedx.png similarity index 100% rename from packages/rails/app/assets/images/participants/genedx.png rename to packages/client/public/assets/participants/genedx.png diff --git a/packages/rails/app/assets/images/participants/george_washington_university.png b/packages/client/public/assets/participants/george_washington_university.png similarity index 100% rename from packages/rails/app/assets/images/participants/george_washington_university.png rename to packages/client/public/assets/participants/george_washington_university.png diff --git a/packages/rails/app/assets/images/participants/georgetown_university.png b/packages/client/public/assets/participants/georgetown_university.png similarity index 100% rename from packages/rails/app/assets/images/participants/georgetown_university.png rename to packages/client/public/assets/participants/georgetown_university.png diff --git a/packages/rails/app/assets/images/participants/hans_nelsen.jpg b/packages/client/public/assets/participants/hans_nelsen.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/hans_nelsen.jpg rename to packages/client/public/assets/participants/hans_nelsen.jpg diff --git a/packages/rails/app/assets/images/participants/humanlongevity.png b/packages/client/public/assets/participants/humanlongevity.png similarity index 100% rename from packages/rails/app/assets/images/participants/humanlongevity.png rename to packages/client/public/assets/participants/humanlongevity.png diff --git a/packages/rails/app/assets/images/participants/illumina.png b/packages/client/public/assets/participants/illumina.png similarity index 100% rename from packages/rails/app/assets/images/participants/illumina.png rename to packages/client/public/assets/participants/illumina.png diff --git a/packages/rails/app/assets/images/participants/intel.png b/packages/client/public/assets/participants/intel.png similarity index 100% rename from packages/rails/app/assets/images/participants/intel.png rename to packages/client/public/assets/participants/intel.png diff --git a/packages/rails/app/assets/images/participants/ireceptor.png b/packages/client/public/assets/participants/ireceptor.png similarity index 100% rename from packages/rails/app/assets/images/participants/ireceptor.png rename to packages/client/public/assets/participants/ireceptor.png diff --git a/packages/rails/app/assets/images/participants/lester_carter.jpg b/packages/client/public/assets/participants/lester_carter.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/lester_carter.jpg rename to packages/client/public/assets/participants/lester_carter.jpg diff --git a/packages/rails/app/assets/images/participants/macrogen.png b/packages/client/public/assets/participants/macrogen.png similarity index 100% rename from packages/rails/app/assets/images/participants/macrogen.png rename to packages/client/public/assets/participants/macrogen.png diff --git a/packages/rails/app/assets/images/participants/mark_woon.jpg b/packages/client/public/assets/participants/mark_woon.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/mark_woon.jpg rename to packages/client/public/assets/participants/mark_woon.jpg diff --git a/packages/rails/app/assets/images/participants/mark_wright.jpg b/packages/client/public/assets/participants/mark_wright.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/mark_wright.jpg rename to packages/client/public/assets/participants/mark_wright.jpg diff --git a/packages/rails/app/assets/images/participants/miodx.png b/packages/client/public/assets/participants/miodx.png similarity index 100% rename from packages/rails/app/assets/images/participants/miodx.png rename to packages/client/public/assets/participants/miodx.png diff --git a/packages/rails/app/assets/images/participants/natera.png b/packages/client/public/assets/participants/natera.png similarity index 100% rename from packages/rails/app/assets/images/participants/natera.png rename to packages/client/public/assets/participants/natera.png diff --git a/packages/rails/app/assets/images/participants/nci.png b/packages/client/public/assets/participants/nci.png similarity index 100% rename from packages/rails/app/assets/images/participants/nci.png rename to packages/client/public/assets/participants/nci.png diff --git a/packages/rails/app/assets/images/participants/nih.png b/packages/client/public/assets/participants/nih.png similarity index 100% rename from packages/rails/app/assets/images/participants/nih.png rename to packages/client/public/assets/participants/nih.png diff --git a/packages/rails/app/assets/images/participants/nist.png b/packages/client/public/assets/participants/nist.png similarity index 100% rename from packages/rails/app/assets/images/participants/nist.png rename to packages/client/public/assets/participants/nist.png diff --git a/packages/rails/app/assets/images/participants/ostp.png b/packages/client/public/assets/participants/ostp.png similarity index 100% rename from packages/rails/app/assets/images/participants/ostp.png rename to packages/client/public/assets/participants/ostp.png diff --git a/packages/rails/app/assets/images/participants/personalis.png b/packages/client/public/assets/participants/personalis.png similarity index 100% rename from packages/rails/app/assets/images/participants/personalis.png rename to packages/client/public/assets/participants/personalis.png diff --git a/packages/rails/app/assets/images/participants/peter_tonellato.jpg b/packages/client/public/assets/participants/peter_tonellato.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/peter_tonellato.jpg rename to packages/client/public/assets/participants/peter_tonellato.jpg diff --git a/packages/rails/app/assets/images/participants/pharmgkb.png b/packages/client/public/assets/participants/pharmgkb.png similarity index 100% rename from packages/rails/app/assets/images/participants/pharmgkb.png rename to packages/client/public/assets/participants/pharmgkb.png diff --git a/packages/rails/app/assets/images/participants/placeholder.png b/packages/client/public/assets/participants/placeholder.png similarity index 100% rename from packages/rails/app/assets/images/participants/placeholder.png rename to packages/client/public/assets/participants/placeholder.png diff --git a/packages/rails/app/assets/images/participants/qiagen.png b/packages/client/public/assets/participants/qiagen.png similarity index 100% rename from packages/rails/app/assets/images/participants/qiagen.png rename to packages/client/public/assets/participants/qiagen.png diff --git a/packages/rails/app/assets/images/participants/rachel_goldfeder.png b/packages/client/public/assets/participants/rachel_goldfeder.png similarity index 100% rename from packages/rails/app/assets/images/participants/rachel_goldfeder.png rename to packages/client/public/assets/participants/rachel_goldfeder.png diff --git a/packages/rails/app/assets/images/participants/roche.png b/packages/client/public/assets/participants/roche.png similarity index 100% rename from packages/rails/app/assets/images/participants/roche.png rename to packages/client/public/assets/participants/roche.png diff --git a/packages/rails/app/assets/images/participants/rtg.png b/packages/client/public/assets/participants/rtg.png similarity index 100% rename from packages/rails/app/assets/images/participants/rtg.png rename to packages/client/public/assets/participants/rtg.png diff --git a/packages/rails/app/assets/images/participants/russ_altman.jpg b/packages/client/public/assets/participants/russ_altman.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/russ_altman.jpg rename to packages/client/public/assets/participants/russ_altman.jpg diff --git a/packages/rails/app/assets/images/participants/sequenom.png b/packages/client/public/assets/participants/sequenom.png similarity index 100% rename from packages/rails/app/assets/images/participants/sequenom.png rename to packages/client/public/assets/participants/sequenom.png diff --git a/packages/rails/app/assets/images/participants/seracare.png b/packages/client/public/assets/participants/seracare.png similarity index 100% rename from packages/rails/app/assets/images/participants/seracare.png rename to packages/client/public/assets/participants/seracare.png diff --git a/packages/rails/app/assets/images/participants/snehit_prabhu.jpg b/packages/client/public/assets/participants/snehit_prabhu.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/snehit_prabhu.jpg rename to packages/client/public/assets/participants/snehit_prabhu.jpg diff --git a/packages/rails/app/assets/images/participants/stanford.png b/packages/client/public/assets/participants/stanford.png similarity index 100% rename from packages/rails/app/assets/images/participants/stanford.png rename to packages/client/public/assets/participants/stanford.png diff --git a/packages/rails/app/assets/images/participants/teri_klein.jpg b/packages/client/public/assets/participants/teri_klein.jpg similarity index 100% rename from packages/rails/app/assets/images/participants/teri_klein.jpg rename to packages/client/public/assets/participants/teri_klein.jpg diff --git a/packages/rails/app/assets/images/participants/us-house-of-representatives.png b/packages/client/public/assets/participants/us-house-of-representatives.png similarity index 100% rename from packages/rails/app/assets/images/participants/us-house-of-representatives.png rename to packages/client/public/assets/participants/us-house-of-representatives.png diff --git a/packages/rails/app/assets/images/participants/vha_ie.png b/packages/client/public/assets/participants/vha_ie.png similarity index 100% rename from packages/rails/app/assets/images/participants/vha_ie.png rename to packages/client/public/assets/participants/vha_ie.png diff --git a/packages/client/public/favicon.png b/packages/client/public/favicon.png new file mode 100644 index 000000000..c00daeea7 Binary files /dev/null and b/packages/client/public/favicon.png differ diff --git a/packages/client/public/og-image.png b/packages/client/public/og-image.png new file mode 100644 index 000000000..9d856b74b Binary files /dev/null and b/packages/client/public/og-image.png differ diff --git a/packages/client/src/AuthWall.tsx b/packages/client/src/AuthWall.tsx index bf09e2b79..75d344339 100644 --- a/packages/client/src/AuthWall.tsx +++ b/packages/client/src/AuthWall.tsx @@ -4,8 +4,8 @@ import { useAuthUser } from './features/auth/useAuthUser' import { useModal } from './features/modal/useModal' import PublicLayout from './layouts/PublicLayout' import NavigationBar, { NavigationBarBanner, NavigationBarPublicLandingTitle } from './components/NavigationBar/NavigationBar' -import { PageContainerMargin } from './components/Page/styles' -import { PageLoaderWrapper } from './components/Public/styles' +import { PageContainerMargin } from './components/Page/page.styles' +import { PageLoaderWrapper } from './components/Public/public-layout.styles' import { LayoutLoader } from './layouts/UserLayout' import { AuthPickerModal } from './features/auth/AuthPickerModal' diff --git a/packages/client/src/api/files.ts b/packages/client/src/api/files.ts index a6331c7f0..bbf49233a 100644 --- a/packages/client/src/api/files.ts +++ b/packages/client/src/api/files.ts @@ -1,12 +1,14 @@ import axios from 'axios' -import { ServerScope } from '../features/home/types' +import type { ServerScope } from '../features/home/types' export const createFile = (name: string, scope?: ServerScope, folderId?: string | number) => - axios.post('/api/create_file', { name, scope, folder_id: folderId }).then(response => ({ status: response.status, payload: response.data })) + axios + .post('/api/v2/files', { name, scope, folderId }) + .then(response => ({ status: response.status, payload: response.data })) export const getUploadURL = (uid: string | number, index: number, size: number, md5: string) => axios - .get(`/api/v2/files/${uid}/upload-url`, { params: { index, size, md5 }}) + .get(`/api/v2/files/${uid}/upload-url`, { params: { index, size, md5 } }) .then(response => ({ status: response.status, payload: response.data })) export const uploadChunk = (url: string, chunk: Blob | ArrayBuffer | string, headers?: Record) => { diff --git a/packages/client/src/api/types.ts b/packages/client/src/api/types.ts index eec69ee6a..6e65b19ca 100644 --- a/packages/client/src/api/types.ts +++ b/packages/client/src/api/types.ts @@ -49,3 +49,7 @@ export function getBackendErrorMessage(error: unknown, fallback: string, statusM } return fallback } + +export type EntityUidResponse = { + uid: string +} diff --git a/packages/client/src/assets/beta-release.png b/packages/client/src/assets/beta-release.png new file mode 100644 index 000000000..f7998e943 Binary files /dev/null and b/packages/client/src/assets/beta-release.png differ diff --git a/packages/client/src/assets/precisionFDA-dp.png b/packages/client/src/assets/precisionFDA-dp.png index 17f81aee1..9d856b74b 100644 Binary files a/packages/client/src/assets/precisionFDA-dp.png and b/packages/client/src/assets/precisionFDA-dp.png differ diff --git a/packages/client/src/components/Controls/ExternalLink/index.tsx b/packages/client/src/components/Controls/ExternalLink/index.tsx index 9833e6582..a378fa805 100644 --- a/packages/client/src/components/Controls/ExternalLink/index.tsx +++ b/packages/client/src/components/Controls/ExternalLink/index.tsx @@ -1,7 +1,7 @@ import React, { FunctionComponent, useState } from 'react' import styled from 'styled-components' import { ModalHeaderTop, ModalNext } from '../../../features/modal/ModalNext' -import { ButtonRow, Footer } from '../../../features/modal/styles' +import { ButtonRow, Footer } from '../../../features/modal/modal.styles' import { Button } from '../../Button' const StyledLink = styled.a` diff --git a/packages/client/src/components/Markdown/styles.tsx b/packages/client/src/components/Markdown/markdown.styles.tsx similarity index 100% rename from packages/client/src/components/Markdown/styles.tsx rename to packages/client/src/components/Markdown/markdown.styles.tsx diff --git a/packages/client/src/components/NavigationBar/NavigationBar/index.tsx b/packages/client/src/components/NavigationBar/NavigationBar/index.tsx index b6899314e..a0bdb52f7 100644 --- a/packages/client/src/components/NavigationBar/NavigationBar/index.tsx +++ b/packages/client/src/components/NavigationBar/NavigationBar/index.tsx @@ -5,7 +5,7 @@ import styled from 'styled-components' import { MailButton, StyledSocialMediaButtons } from '../SocialMediaButtons' import { PublicNavbar } from '../PublicNavbar' import { MainBanner } from '../../Banner' -import { PageContainerMargin } from '../../Page/styles' +import { PageContainerMargin } from '../../Page/page.styles' import { IUser } from '../../../types/user' const NavigationBarBanner = styled(PageContainerMargin)` diff --git a/packages/client/src/components/NavigationBar/PublicNavbar/index.tsx b/packages/client/src/components/NavigationBar/PublicNavbar/index.tsx index ce352b98f..2264b7912 100644 --- a/packages/client/src/components/NavigationBar/PublicNavbar/index.tsx +++ b/packages/client/src/components/NavigationBar/PublicNavbar/index.tsx @@ -4,7 +4,7 @@ import { Link, useLocation } from 'react-router' import { onLogInWithSSO, useSiteSettingsQuery } from '../../../features/auth/useSiteSettingsQuery' import { Button } from '../../Button' import { PFDALogoDark, PFDALogoLight } from '../PFDALogo' -import { MobileMenuOverlay, PageContainer, StyledPublicNavbar } from './styles' +import { MobileMenuOverlay, PageContainer, StyledPublicNavbar } from './public-navbar.styles' type PublicNavbarProps = { shouldShowLogo?: boolean diff --git a/packages/client/src/components/NavigationBar/PublicNavbar/styles.ts b/packages/client/src/components/NavigationBar/PublicNavbar/public-navbar.styles.ts similarity index 99% rename from packages/client/src/components/NavigationBar/PublicNavbar/styles.ts rename to packages/client/src/components/NavigationBar/PublicNavbar/public-navbar.styles.ts index 744ba8126..cb9e1f416 100644 --- a/packages/client/src/components/NavigationBar/PublicNavbar/styles.ts +++ b/packages/client/src/components/NavigationBar/PublicNavbar/public-navbar.styles.ts @@ -1,5 +1,5 @@ import styled, { css } from 'styled-components' -import { PageContainerMargin } from '../../Page/styles' +import { PageContainerMargin } from '../../Page/page.styles' import { fallback } from './fallback.styles' export const PageContainer = styled(PageContainerMargin)` diff --git a/packages/client/src/components/NotAllowed.tsx b/packages/client/src/components/NotAllowed.tsx index 1ada30df9..7c13446b2 100644 --- a/packages/client/src/components/NotAllowed.tsx +++ b/packages/client/src/components/NotAllowed.tsx @@ -1,6 +1,6 @@ import React from 'react' import styled from 'styled-components' -import { PageContainer } from './Page/styles' +import { PageContainer } from './Page/page.styles' export const Warning = styled.div` border: solid 1px #f0ad4e; diff --git a/packages/client/src/components/Page/styles.tsx b/packages/client/src/components/Page/page.styles.tsx similarity index 100% rename from packages/client/src/components/Page/styles.tsx rename to packages/client/src/components/Page/page.styles.tsx diff --git a/packages/client/src/components/Pagination/index.tsx b/packages/client/src/components/Pagination/index.tsx index 3cf753339..620e567da 100644 --- a/packages/client/src/components/Pagination/index.tsx +++ b/packages/client/src/components/Pagination/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react' import styled from 'styled-components' -import { inputFocus, InputSelect } from '../form/styles' +import { inputFocus, InputSelect } from '../form/form.styles' import { Button } from '../Button' export const StyledInputJumpTo = styled.input` diff --git a/packages/client/src/components/Public/styles.ts b/packages/client/src/components/Public/public-layout.styles.ts similarity index 98% rename from packages/client/src/components/Public/styles.ts rename to packages/client/src/components/Public/public-layout.styles.ts index abd9b9c06..1793ecf35 100644 --- a/packages/client/src/components/Public/styles.ts +++ b/packages/client/src/components/Public/public-layout.styles.ts @@ -1,7 +1,7 @@ import { Link } from 'react-router' import styled, { css } from 'styled-components' import { breakPoints } from '../../styles/theme' -import { compactScrollBarV2 } from '../Page/styles' +import { compactScrollBarV2 } from '../Page/page.styles' export const ButtonRow = styled.div` display: flex; diff --git a/packages/client/src/components/Table/components/styles.tsx b/packages/client/src/components/Table/components/table.styles.tsx similarity index 98% rename from packages/client/src/components/Table/components/styles.tsx rename to packages/client/src/components/Table/components/table.styles.tsx index 929aa0630..9a183889c 100644 --- a/packages/client/src/components/Table/components/styles.tsx +++ b/packages/client/src/components/Table/components/table.styles.tsx @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components' import { ArrowIcon } from '../../icons/ArrowIcon' -import { compactScrollBarV2 } from '../../Page/styles' +import { compactScrollBarV2 } from '../../Page/page.styles' export const StyledPageTable = styled.div` font-size: 14px; diff --git a/packages/client/src/components/Table/expanderColumnDef.tsx b/packages/client/src/components/Table/expanderColumnDef.tsx index 955b1ea9c..5be39f229 100644 --- a/packages/client/src/components/Table/expanderColumnDef.tsx +++ b/packages/client/src/components/Table/expanderColumnDef.tsx @@ -1,7 +1,7 @@ import { ColumnDef } from '@tanstack/react-table' import React from 'react' import { TransparentButton } from '../Button' -import { ExpandArrowIcon } from './components/styles' +import { ExpandArrowIcon } from './components/table.styles' export function expanderColumnDef(): ColumnDef { return { diff --git a/packages/client/src/components/Table/index.tsx b/packages/client/src/components/Table/index.tsx index 4a18e84e8..734cd674d 100644 --- a/packages/client/src/components/Table/index.tsx +++ b/packages/client/src/components/Table/index.tsx @@ -23,7 +23,7 @@ import { import React, { type DragEventHandler, useMemo } from 'react' import CustomTable from './components/CustomTable' -import { TableStyles } from './components/styles' +import { TableStyles } from './components/table.styles' import { useComponentWidth } from './useComponentWidth' function Table({ diff --git a/packages/client/src/components/Tags.tsx b/packages/client/src/components/Tags.tsx index 096960932..024e07ecb 100644 --- a/packages/client/src/components/Tags.tsx +++ b/packages/client/src/components/Tags.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { compactScrollBar } from './Page/styles' +import { compactScrollBar } from './Page/page.styles' export const StyledTags = styled.div` display: flex; diff --git a/packages/client/src/components/form/FieldGroup.tsx b/packages/client/src/components/form/FieldGroup.tsx index c4b2a42b1..fb4405bbb 100644 --- a/packages/client/src/components/form/FieldGroup.tsx +++ b/packages/client/src/components/form/FieldGroup.tsx @@ -1,6 +1,6 @@ import React, { ReactNode } from 'react' import styled from 'styled-components' -import { FieldGroup as StyledFieldGroup } from './styles' +import { FieldGroup as StyledFieldGroup } from './form.styles' const Row = styled.div` display: flex; diff --git a/packages/client/src/components/form/styles.ts b/packages/client/src/components/form/form.styles.ts similarity index 100% rename from packages/client/src/components/form/styles.ts rename to packages/client/src/components/form/form.styles.ts diff --git a/packages/client/src/components/EntityIcon.tsx b/packages/client/src/components/icons/EntityIcon.tsx similarity index 66% rename from packages/client/src/components/EntityIcon.tsx rename to packages/client/src/components/icons/EntityIcon.tsx index aa40d664c..7ec2b5087 100644 --- a/packages/client/src/components/EntityIcon.tsx +++ b/packages/client/src/components/icons/EntityIcon.tsx @@ -1,12 +1,12 @@ import React from 'react' -import { AreaChartIcon } from './icons/AreaChartIcon' -import { CogsIcon } from './icons/Cogs' -import { CubeIcon } from './icons/CubeIcon' -import { DatabaseIcon } from './icons/DatabaseIcon' -import { FileIcon } from './icons/FileIcon' -import { FileZipIcon } from './icons/FileZipIcon' -import { StickyNoteIcon } from './icons/StickyNote' -import { FolderIcon } from './icons/FolderIcon' +import { AreaChartIcon } from './AreaChartIcon' +import { CogsIcon } from './Cogs' +import { CubeIcon } from './CubeIcon' +import { DatabaseIcon } from './DatabaseIcon' +import { FileIcon } from './FileIcon' +import { FileZipIcon } from './FileZipIcon' +import { StickyNoteIcon } from './StickyNote' +import { FolderIcon } from './FolderIcon' export type EntityType = 'file' | 'app' | 'job' | 'database' | 'comparison' | 'note' | 'asset' | 'folder' diff --git a/packages/client/src/features/spaces/FdaRestrictedIcon.tsx b/packages/client/src/components/icons/FdaRestrictedIcon.tsx similarity index 92% rename from packages/client/src/features/spaces/FdaRestrictedIcon.tsx rename to packages/client/src/components/icons/FdaRestrictedIcon.tsx index 665bd38a6..33182319c 100644 --- a/packages/client/src/features/spaces/FdaRestrictedIcon.tsx +++ b/packages/client/src/components/icons/FdaRestrictedIcon.tsx @@ -1,7 +1,7 @@ import React, { useId } from 'react' import { Tooltip } from 'react-tooltip' import styled from 'styled-components' -import { FdaIcon } from '../../components/icons/FdaIcon' +import { FdaIcon } from './FdaIcon' const StyledFdaRestrictedIcon = styled.span` flex-shrink: 0; diff --git a/packages/client/src/features/spaces/ProtectedIcon.tsx b/packages/client/src/components/icons/ProtectedIcon.tsx similarity index 91% rename from packages/client/src/features/spaces/ProtectedIcon.tsx rename to packages/client/src/components/icons/ProtectedIcon.tsx index ca0350510..603ea5164 100644 --- a/packages/client/src/features/spaces/ProtectedIcon.tsx +++ b/packages/client/src/components/icons/ProtectedIcon.tsx @@ -1,7 +1,7 @@ import React, { useId } from 'react' import { Tooltip } from 'react-tooltip' import styled from 'styled-components' -import { LockIcon } from '../../components/icons/LockIcon' +import { LockIcon } from './LockIcon' const StyledProtectedIcon = styled.span` flex-shrink: 0; diff --git a/packages/client/src/features/actionModals/AttachToModal/styles.ts b/packages/client/src/features/actionModals/AttachToModal/attach-to-modal.styles.ts similarity index 100% rename from packages/client/src/features/actionModals/AttachToModal/styles.ts rename to packages/client/src/features/actionModals/AttachToModal/attach-to-modal.styles.ts diff --git a/packages/client/src/features/actionModals/ScopeList.tsx b/packages/client/src/features/actionModals/ScopeList.tsx index 0275266ac..20d06709e 100644 --- a/packages/client/src/features/actionModals/ScopeList.tsx +++ b/packages/client/src/features/actionModals/ScopeList.tsx @@ -5,12 +5,12 @@ import { Button } from '@/components/Button' import { InputText } from '@/components/InputText' import { HomeIcon } from '@/components/icons/HomeIcon' import { Col, ColBody, HeaderRow, Table, TableRow } from '../modal/ModalCheckList' -import { ModalScroll } from '../modal/styles' -import { FdaRestrictedIcon } from '../spaces/FdaRestrictedIcon' -import { ProtectedIcon } from '../spaces/ProtectedIcon' +import { ModalScroll } from '../modal/modal.styles' +import { FdaRestrictedIcon } from '@/components/icons/FdaRestrictedIcon' +import { ProtectedIcon } from '@/components/icons/ProtectedIcon' import { type EditableSpace, fetchEditableSpacesList } from '../spaces/spaces.api' import { findSpaceTypeIcon } from '../spaces/useSpacesColumns' -import { ColScopeTitle, ModalSearchBar, ScopeIcon } from './styles' +import { ColScopeTitle, ModalSearchBar, ScopeIcon } from './action-modals.styles' export const MY_HOME = { title: 'My Home', diff --git a/packages/client/src/features/actionModals/styles.ts b/packages/client/src/features/actionModals/action-modals.styles.ts similarity index 96% rename from packages/client/src/features/actionModals/styles.ts rename to packages/client/src/features/actionModals/action-modals.styles.ts index 198cf6391..fb363b79c 100644 --- a/packages/client/src/features/actionModals/styles.ts +++ b/packages/client/src/features/actionModals/action-modals.styles.ts @@ -1,6 +1,6 @@ import styled from 'styled-components' -import { compactScrollBarV2 } from '../../components/Page/styles' -import { SearchBar } from '../resources/styles' +import { compactScrollBarV2 } from '../../components/Page/page.styles' +import { SearchBar } from '../resources/resources.styles' export const StyledSubtitle = styled.div` color: var(--c-text-500); diff --git a/packages/client/src/features/actionModals/useAddResourceToSpace.tsx b/packages/client/src/features/actionModals/useAddResourceToSpace.tsx index dd4cfece2..de4e01dbd 100644 --- a/packages/client/src/features/actionModals/useAddResourceToSpace.tsx +++ b/packages/client/src/features/actionModals/useAddResourceToSpace.tsx @@ -10,7 +10,7 @@ import { selectColumnDef } from '../../components/Table/selectColumnDef' import { getSelectedObjectsFromIndexes } from '../../utils/object' import { useListSelect } from '../home/useListSelect' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { Empty } from '../home/home.styles' import { toastError } from '../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/actionModals/useAssetAttachModal.tsx b/packages/client/src/features/actionModals/useAssetAttachModal.tsx index faf32c0d0..5c6865731 100644 --- a/packages/client/src/features/actionModals/useAssetAttachModal.tsx +++ b/packages/client/src/features/actionModals/useAssetAttachModal.tsx @@ -6,7 +6,7 @@ import { CrossIcon } from '@/components/icons/PlusIcon' import { SearchIcon } from '@/components/icons/SearchIcon' import { Loader } from '@/components/Loader' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, HeaderText, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, HeaderText, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { LeftBar, @@ -15,7 +15,7 @@ import { NotesMarkdown, SearchInput, StyledAttachToModal, -} from './AttachToModal/styles' +} from './AttachToModal/attach-to-modal.styles' import { type Asset, useListAssetsQuery } from './AttachToModal/useListAssetsQuery' interface AssetAttachModalProps { diff --git a/packages/client/src/features/actionModals/useCopyToPrivateModal.tsx b/packages/client/src/features/actionModals/useCopyToPrivateModal.tsx index bd0e2da6c..148eb95dd 100644 --- a/packages/client/src/features/actionModals/useCopyToPrivateModal.tsx +++ b/packages/client/src/features/actionModals/useCopyToPrivateModal.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components' import { AxiosError } from 'axios' import { Loader } from '../../components/Loader' import { ResourceTable } from '../../components/ResourceTable' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { APIResource } from '../home/types' import { resourceCountString } from '../../utils/formatting' diff --git a/packages/client/src/features/actionModals/useCopyToSpace.tsx b/packages/client/src/features/actionModals/useCopyToSpace.tsx index 1fc287117..74077a491 100644 --- a/packages/client/src/features/actionModals/useCopyToSpace.tsx +++ b/packages/client/src/features/actionModals/useCopyToSpace.tsx @@ -12,10 +12,10 @@ import { displayPayloadMessage, type Payload } from '@/utils/api' import { useConfirmModal } from '../files/actionModals/useConfirmModal' import type { APIResource, ApiErrorResponse, ApiResponse } from '../home/types' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { SpaceSelectionList } from '../spaces/SpaceSelectionList' -import { ModalSearchBar } from './styles' +import { ModalSearchBar } from './action-modals.styles' export interface CopyToSpaceProperties { createAppRevision?: boolean diff --git a/packages/client/src/features/actionModals/useDeleteModal.tsx b/packages/client/src/features/actionModals/useDeleteModal.tsx index 15db33e2b..220d2bc96 100644 --- a/packages/client/src/features/actionModals/useDeleteModal.tsx +++ b/packages/client/src/features/actionModals/useDeleteModal.tsx @@ -6,7 +6,7 @@ import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastH import { ResourceTable } from '@/components/ResourceTable' import { itemsCountString } from '@/utils/formatting' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' export interface DeleteResponse { diff --git a/packages/client/src/features/actionModals/useEditPropertiesModal.tsx b/packages/client/src/features/actionModals/useEditPropertiesModal.tsx index e1b8a69a3..4b640ff6b 100644 --- a/packages/client/src/features/actionModals/useEditPropertiesModal.tsx +++ b/packages/client/src/features/actionModals/useEditPropertiesModal.tsx @@ -9,14 +9,14 @@ import { Tooltip } from 'react-tooltip' import styled from 'styled-components' import * as Yup from 'yup' import { Button, TransparentButton } from '@/components/Button' -import { FieldGroup } from '@/components/form/styles' +import { FieldGroup } from '@/components/form/form.styles' import { CrossIcon } from '@/components/icons/PlusIcon' import '../../utils/yupValidators' import { toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { InputTextS } from '../apps/form/Fields' import type { ServerScope } from '../home/types' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import type { RequestResponse } from './useFeatureMutation' diff --git a/packages/client/src/features/actionModals/useEditTagsModal.tsx b/packages/client/src/features/actionModals/useEditTagsModal.tsx index c4c87467d..ed53e4b4e 100644 --- a/packages/client/src/features/actionModals/useEditTagsModal.tsx +++ b/packages/client/src/features/actionModals/useEditTagsModal.tsx @@ -2,10 +2,10 @@ import { useMutation } from '@tanstack/react-query' import React, { useMemo } from 'react' import { useForm } from 'react-hook-form' import styled from 'styled-components' -import { FieldGroup } from '../../components/form/styles' +import { FieldGroup } from '../../components/form/form.styles' import { InputText } from '../../components/InputText' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer } from '../modal/styles' +import { ButtonRow, Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { APIResource } from '../home/types' import { Button } from '../../components/Button' diff --git a/packages/client/src/features/actionModals/useForkAppToModal.tsx b/packages/client/src/features/actionModals/useForkAppToModal.tsx index 85787359e..987ad1c02 100644 --- a/packages/client/src/features/actionModals/useForkAppToModal.tsx +++ b/packages/client/src/features/actionModals/useForkAppToModal.tsx @@ -6,7 +6,7 @@ import { getSpaceIdFromScope } from '@/utils' import type { IApp } from '../apps/apps.types' import { getBaseLink } from '../apps/run/utils' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalContentPadding } from '../modal/styles' +import { ButtonRow, Footer, ModalContentPadding } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import type { EditableSpace } from '../spaces/spaces.api' import { ScopeList } from './ScopeList' diff --git a/packages/client/src/features/admin/AdminListPage.tsx b/packages/client/src/features/admin/AdminListPage.tsx index 325489cf9..098730b96 100644 --- a/packages/client/src/features/admin/AdminListPage.tsx +++ b/packages/client/src/features/admin/AdminListPage.tsx @@ -4,7 +4,7 @@ import { HoverDNAnexusLogo } from '@/components/icons/DNAnexusLogo' import { hidePagination, Pagination } from '@/components/Pagination' import { Button } from '@/components/ui/button' import type { MetaV2 } from '@/features/home/types' -import { AdminContentFooter, AdminStyledPageTable, Title, Topbox } from './styles' +import { AdminContentFooter, AdminStyledPageTable, Title, Topbox } from './admin.styles' import { AdminTablePlaceholderLoader, getAdminTableLoadingState } from './tableLoading' type ListShape = { data: unknown[]; meta: MetaV2 } diff --git a/packages/client/src/features/admin/Breadcrumbs.tsx b/packages/client/src/features/admin/Breadcrumbs.tsx index 989b33a6a..bd754cb6e 100644 --- a/packages/client/src/features/admin/Breadcrumbs.tsx +++ b/packages/client/src/features/admin/Breadcrumbs.tsx @@ -1,6 +1,6 @@ import React from 'react' import { Link } from 'react-router' -import { AdminSectionBreadcrumbDivider, AdminSectionBreadcrumbs } from './styles' +import { AdminSectionBreadcrumbDivider, AdminSectionBreadcrumbs } from './admin.styles' export type BreadcrumbItem = { path: string diff --git a/packages/client/src/features/admin/styles.ts b/packages/client/src/features/admin/admin.styles.ts similarity index 94% rename from packages/client/src/features/admin/styles.ts rename to packages/client/src/features/admin/admin.styles.ts index d6b6e7556..aca070b5c 100644 --- a/packages/client/src/features/admin/styles.ts +++ b/packages/client/src/features/admin/admin.styles.ts @@ -2,7 +2,7 @@ import styled from 'styled-components' import { BreadcrumbDivider, StyledBreadcrumbs } from '@/components/Breadcrumb' import { Svg } from '@/components/icons/Svg' import { ContentFooter } from '@/components/Page/ContentFooter' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' export const Title = styled.div` display: flex; diff --git a/packages/client/src/features/admin/alerts/EditAlertForm.tsx b/packages/client/src/features/admin/alerts/EditAlertForm.tsx index 666b6ffad..f2fc22f6a 100644 --- a/packages/client/src/features/admin/alerts/EditAlertForm.tsx +++ b/packages/client/src/features/admin/alerts/EditAlertForm.tsx @@ -7,7 +7,7 @@ import { useForm } from 'react-hook-form' import { getBackendErrorMessage } from '@/api/types' import { AlertBanner } from '@/components/AlertBanner' import { Button } from '@/components/Button' -import { FieldGroup, FieldLabel, InputError, InputSelect } from '@/components/form/styles' +import { FieldGroup, FieldLabel, InputError, InputSelect } from '@/components/form/form.styles' import { InputDateTime, InputText } from '@/components/InputText' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { createAlertRequest, deleteAlertRequest, updateAlertRequest } from './alerts.api' diff --git a/packages/client/src/features/admin/alerts/alerts.styles.ts b/packages/client/src/features/admin/alerts/alerts.styles.ts index 49a1ee610..cd4ce22f9 100644 --- a/packages/client/src/features/admin/alerts/alerts.styles.ts +++ b/packages/client/src/features/admin/alerts/alerts.styles.ts @@ -1,6 +1,6 @@ import styled from 'styled-components' -import { InputSelect } from '@/components/form/styles' -import { ButtonRow } from '../../modal/styles' +import { InputSelect } from '@/components/form/form.styles' +import { ButtonRow } from '../../modal/modal.styles' export const Form = styled.form` align-self: center; diff --git a/packages/client/src/features/admin/invitations/modals/useEditInvitationModal.tsx b/packages/client/src/features/admin/invitations/modals/useEditInvitationModal.tsx index 424f6f448..531cd0784 100644 --- a/packages/client/src/features/admin/invitations/modals/useEditInvitationModal.tsx +++ b/packages/client/src/features/admin/invitations/modals/useEditInvitationModal.tsx @@ -6,11 +6,11 @@ import { useForm } from 'react-hook-form' import * as Yup from 'yup' import { getBackendErrorMessage } from '@/api/types' import { Button } from '@/components/Button' -import { FieldGroup, InputError } from '@/components/form/styles' +import { FieldGroup, InputError } from '@/components/form/form.styles' import { InputText } from '@/components/InputText' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { ModalHeaderTop, ModalNext } from '../../../modal/ModalNext' -import { ButtonRow, Footer, StyledForm, StyledModalScroll } from '../../../modal/styles' +import { ButtonRow, Footer, StyledForm, StyledModalScroll } from '../../../modal/modal.styles' import { useModal } from '../../../modal/useModal' import { editInvitationBasicInfo, type Invitation } from '../../users/api' diff --git a/packages/client/src/features/admin/invitations/useInvitationColumns.tsx b/packages/client/src/features/admin/invitations/useInvitationColumns.tsx index 1310cf314..1f0891dbd 100644 --- a/packages/client/src/features/admin/invitations/useInvitationColumns.tsx +++ b/packages/client/src/features/admin/invitations/useInvitationColumns.tsx @@ -5,7 +5,7 @@ import { selectColumnDef } from '@/components/Table/selectColumnDef' import { convertDateToUserTime } from '@/utils/datetime' import DateTimeRangeFilter, { dateRangeFilterFn } from '../../../components/Table/components/DateTimeRangeFilter' import SelectFilter, { selectFilterFn } from '../../../components/Table/components/SelectFilter' -import { StateLabel } from '../styles' +import { StateLabel } from '../admin.styles' import type { Invitation } from '../users/api' export const ProvisionStateCell = ({ provisionState }: { provisionState: string }) => { diff --git a/packages/client/src/features/admin/spaces/SpacesListActionRow.tsx b/packages/client/src/features/admin/spaces/SpacesListActionRow.tsx index ada770803..c60e8237c 100644 --- a/packages/client/src/features/admin/spaces/SpacesListActionRow.tsx +++ b/packages/client/src/features/admin/spaces/SpacesListActionRow.tsx @@ -5,7 +5,7 @@ import { getBackendErrorMessage } from '@/api/types' import { Button } from '@/components/Button' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import type { MetaV2 } from '../../home/types' -import { ModalScroll } from '../../modal/styles' +import { ModalScroll } from '../../modal/modal.styles' import { useConfirm } from '../../modal/useConfirm' import type { ISpaceV2 } from '../../spaces/spaces.types' import { useSpaceHiddenMutation } from '../../spaces/useSpaceHiddenMutation' diff --git a/packages/client/src/features/admin/spaces/index.tsx b/packages/client/src/features/admin/spaces/index.tsx index 7c3dee833..d36627932 100644 --- a/packages/client/src/features/admin/spaces/index.tsx +++ b/packages/client/src/features/admin/spaces/index.tsx @@ -12,7 +12,7 @@ import { type Params, prepareListFetchV2 } from '../../home/utils' import { type ISpaceV2, columnFilters as spaceListColumnFilters } from '../../spaces/spaces.types' import { useSpacesColumns } from '../../spaces/useSpacesColumns' import { AdminListErrorState } from '../AdminListPage' -import { AdminContentFooter, AdminStyledPageTable, Title, Topbox, TopLeft } from '../styles' +import { AdminContentFooter, AdminStyledPageTable, Title, Topbox, TopLeft } from '../admin.styles' import { AdminTablePlaceholderLoader, getAdminTableLoadingState } from '../tableLoading' import { SpacesListActionRow } from './SpacesListActionRow' diff --git a/packages/client/src/features/admin/spaces/useRecoverSpaceLeadModal.tsx b/packages/client/src/features/admin/spaces/useRecoverSpaceLeadModal.tsx index bd3c52189..ac8bda040 100644 --- a/packages/client/src/features/admin/spaces/useRecoverSpaceLeadModal.tsx +++ b/packages/client/src/features/admin/spaces/useRecoverSpaceLeadModal.tsx @@ -7,7 +7,7 @@ import { Controller, useForm } from 'react-hook-form' import * as Yup from 'yup' import { getBackendErrorMessage } from '@/api/types' import { Button } from '@/components/Button' -import { FieldGroup, InputError } from '@/components/form/styles' +import { FieldGroup, InputError } from '@/components/form/form.styles' import { InputText } from '@/components/InputText' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { @@ -19,7 +19,7 @@ import { ComboboxList, } from '@/components/ui/combobox' import { ModalHeaderTop, ModalNext, useModalFloatingPortalHost } from '../../modal/ModalNext' -import { Footer } from '../../modal/styles' +import { Footer } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { fetchSpaceMemberships } from '../../spaces/members/members.api' import { StyledFields } from '../../spaces/members/members.styles' diff --git a/packages/client/src/features/admin/users/AdminUserDetailsDrawer.tsx b/packages/client/src/features/admin/users/AdminUserDetailsDrawer.tsx index 41319d8da..4e26588ea 100644 --- a/packages/client/src/features/admin/users/AdminUserDetailsDrawer.tsx +++ b/packages/client/src/features/admin/users/AdminUserDetailsDrawer.tsx @@ -12,7 +12,7 @@ import { relativeTimeAgo } from '@/utils/datetime' import { formatDate } from '@/utils/formatting' import { useAuthUser } from '../../auth/useAuthUser' import { formatNumberUS } from '../../home/utils' -import { ModalScroll } from '../../modal/styles' +import { ModalScroll } from '../../modal/modal.styles' import { useConfirm } from '../../modal/useConfirm' import { bulkDeactivate, diff --git a/packages/client/src/features/apps/AppExecutionsList.tsx b/packages/client/src/features/apps/AppExecutionsList.tsx index c56262d13..e095a19e6 100644 --- a/packages/client/src/features/apps/AppExecutionsList.tsx +++ b/packages/client/src/features/apps/AppExecutionsList.tsx @@ -9,7 +9,7 @@ import type { import { useEffect, useMemo } from 'react' import { ContentFooter } from '@/components/Page/ContentFooter' import { hidePagination, Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { useColumnWidthLocalStorage } from '@/hooks/useColumnWidthLocalStorage' import { useHiddenColumnLocalStorage } from '@/hooks/useHiddenColumnLocalStorage' import { useLastWSNotification } from '@/hooks/useLastWSNotification' diff --git a/packages/client/src/features/apps/AppList.tsx b/packages/client/src/features/apps/AppList.tsx index 26fe8fcbd..028363269 100644 --- a/packages/client/src/features/apps/AppList.tsx +++ b/packages/client/src/features/apps/AppList.tsx @@ -13,7 +13,7 @@ import { PlusIcon } from '@/components/icons/PlusIcon' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' import Table from '../../components/Table' import { ActionsMenuContent } from '../home/ActionMenuContent' diff --git a/packages/client/src/features/apps/SelectMultiFileInput.tsx b/packages/client/src/features/apps/SelectMultiFileInput.tsx index c0bbe0ecd..7b75965e8 100644 --- a/packages/client/src/features/apps/SelectMultiFileInput.tsx +++ b/packages/client/src/features/apps/SelectMultiFileInput.tsx @@ -5,7 +5,7 @@ import { pluralize } from '../../utils/formatting' import type { IAccessibleFile } from '../databases/databases.api' import { useSelectFileModal } from '../files/actionModals/useSelectFileModal' import type { DialogType } from '../home/types' -import { ButtonRow } from '../modal/styles' +import { ButtonRow } from '../modal/modal.styles' const StyledButtonRow = styled(ButtonRow)` justify-content: flex-start; diff --git a/packages/client/src/features/apps/SpecTab/styles.ts b/packages/client/src/features/apps/SpecTab/apps-spec-tab.styles.ts similarity index 100% rename from packages/client/src/features/apps/SpecTab/styles.ts rename to packages/client/src/features/apps/SpecTab/apps-spec-tab.styles.ts diff --git a/packages/client/src/features/apps/SpecTab/index.tsx b/packages/client/src/features/apps/SpecTab/index.tsx index 71a7d649a..c45c178a3 100644 --- a/packages/client/src/features/apps/SpecTab/index.tsx +++ b/packages/client/src/features/apps/SpecTab/index.tsx @@ -3,7 +3,7 @@ import { COMPUTE_RESOURCE_LABELS } from '@/types/user' import { MetadataKey } from '../../home/show.styles' import { AppSpec } from '../apps.types' import { SpecTable } from './SpecTable' -import { StyledSpecTab } from './styles' +import { StyledSpecTab } from './apps-spec-tab.styles' export const SpecTab = ({ spec, spaceId }: { spec: AppSpec; spaceId?: string }): React.JSX.Element => { if (!spec) { diff --git a/packages/client/src/features/apps/actionsModals/useSelectAppModal.tsx b/packages/client/src/features/apps/actionsModals/useSelectAppModal.tsx index 79d819b74..66f9193d1 100644 --- a/packages/client/src/features/apps/actionsModals/useSelectAppModal.tsx +++ b/packages/client/src/features/apps/actionsModals/useSelectAppModal.tsx @@ -10,7 +10,7 @@ import { Tabs } from '../../../components/Tabs/Tabs' import { FileIcon } from '../../../components/icons/FileIcon' import { useAuthUser } from '../../auth/useAuthUser' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ButtonBadge, @@ -22,7 +22,7 @@ import { StyledRow, StyledSubtitle, Tab, -} from '../../actionModals/styles' +} from '../../actionModals/action-modals.styles' import { DialogType, ServerScope } from '../../home/types' import { fetchFilteredApps } from '../apps.api' import { IApp } from '../apps.types' diff --git a/packages/client/src/features/apps/form/AppForm.tsx b/packages/client/src/features/apps/form/AppForm.tsx index d78d199c5..7e2eceac2 100644 --- a/packages/client/src/features/apps/form/AppForm.tsx +++ b/packages/client/src/features/apps/form/AppForm.tsx @@ -6,13 +6,13 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { type ComputeResourceKey, RESOURCE_LABELS } from '@/types/user' import { cn } from '@/utils/cn' import { Button } from '../../../components/Button' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { ArrowLeftIcon } from '../../../components/icons/ArrowLeftIcon' import { Loader } from '../../../components/Loader' import MonacoEditor from '../../../components/MonacoEditor/MonacoEditor' -import { PageTitle } from '../../../components/Page/styles' -import { ButtonRow } from '../../../components/Public/styles' +import { PageTitle } from '../../../components/Page/page.styles' +import { ButtonRow } from '../../../components/Public/public-layout.styles' import { PfTabContent } from '../../../components/Tabs/PfTab' import { APP_REVISION_CREATION_NOT_REQUESTED, APP_SERIES_CREATION_NOT_REQUESTED } from '../../../constants' import { CONFIRM_APP_REVISION, CONFIRM_APP_SERIES } from '../../../constants/consts' @@ -43,7 +43,7 @@ import { TopFieldGroup, TopFieldGroupTarget, TopFieldGroupUbuntu, -} from './styles' +} from './apps-form.styles' import { VmEnvTab } from './VmEnvTab' type SelectedSection = 'io' | 'vm' | 'script' | 'readme' diff --git a/packages/client/src/features/apps/form/Fields.tsx b/packages/client/src/features/apps/form/Fields.tsx index 8dc6cf0bd..10e44c826 100644 --- a/packages/client/src/features/apps/form/Fields.tsx +++ b/packages/client/src/features/apps/form/Fields.tsx @@ -7,7 +7,7 @@ import styled, { css } from 'styled-components' import { Button } from '../../../components/Button' import { BoolButton, BoolButtonGroup } from '../../../components/Button/BoolButtons' import { Checkbox } from '../../../components/CheckboxNext' -import { InputError } from '../../../components/form/styles' +import { InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { PlusIcon } from '../../../components/icons/PlusIcon' import Menu from '../../../components/Menu/Menu' diff --git a/packages/client/src/features/apps/form/Inputs.tsx b/packages/client/src/features/apps/form/Inputs.tsx index fe7dbfb43..1674a1f6b 100644 --- a/packages/client/src/features/apps/form/Inputs.tsx +++ b/packages/client/src/features/apps/form/Inputs.tsx @@ -21,7 +21,7 @@ import { SpecProps, StringInput, } from './Fields' -import { SectionTitle, SectionTitleRow, StyledClassTd, StyledInputOutputBox, StyledRemove, TableStyles } from './styles' +import { SectionTitle, SectionTitleRow, StyledClassTd, StyledInputOutputBox, StyledRemove, TableStyles } from './apps-form.styles' import { CreateAppForm, IOSpec } from '../apps.types' import { removeArrayStringFromClassType, setClassVal } from './common' import { useSkipFirstRenderUseEffect } from '../../../hooks/useSkipFirstRender' diff --git a/packages/client/src/features/apps/form/Outputs.tsx b/packages/client/src/features/apps/form/Outputs.tsx index 314aca767..87e9bda0a 100644 --- a/packages/client/src/features/apps/form/Outputs.tsx +++ b/packages/client/src/features/apps/form/Outputs.tsx @@ -21,7 +21,7 @@ import { StyledInputOutputBox, StyledRemove, TableStyles, -} from './styles' +} from './apps-form.styles' import { CreateAppForm, IOSpec } from '../apps.types' import { removeArrayStringFromClassType, setClassVal } from './common' diff --git a/packages/client/src/features/apps/form/ReadMeInput.tsx b/packages/client/src/features/apps/form/ReadMeInput.tsx index 37a99b2d8..f2235a949 100644 --- a/packages/client/src/features/apps/form/ReadMeInput.tsx +++ b/packages/client/src/features/apps/form/ReadMeInput.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import styled from 'styled-components' import { Button } from '../../../components/Button' import { Markdown } from '../../../components/Markdown' -import { FormFields, Help, StyledMarkdownAppShow } from './styles' +import { FormFields, Help, StyledMarkdownAppShow } from './apps-form.styles' import ExternalLink from '../../../components/Controls/ExternalLink' import MonacoEditor from '../../../components/MonacoEditor/MonacoEditor' diff --git a/packages/client/src/features/apps/form/VmEnvTab.tsx b/packages/client/src/features/apps/form/VmEnvTab.tsx index c2fdfbec8..a267ddd09 100644 --- a/packages/client/src/features/apps/form/VmEnvTab.tsx +++ b/packages/client/src/features/apps/form/VmEnvTab.tsx @@ -3,7 +3,7 @@ import { type KeyboardEventHandler, type ReactNode, useRef } from 'react' import { type Control, Controller, type FieldErrors, type UseFormTrigger } from 'react-hook-form' import { Link } from 'react-router' import { Checkbox } from '@/components/CheckboxNext' -import { FieldGroup, FieldLabelRow, InputError, SelectFieldLabel } from '@/components/form/styles' +import { FieldGroup, FieldLabelRow, InputError, SelectFieldLabel } from '@/components/form/form.styles' import { ArrowLeftIcon } from '@/components/icons/ArrowLeftIcon' import { CrossIcon } from '@/components/icons/PlusIcon' import { Button } from '@/components/ui/button' @@ -12,7 +12,7 @@ import ExternalLink from '../../../components/Controls/ExternalLink' import { useAssetAttachModal } from '../../actionModals/useAssetAttachModal' import type { CreateAppForm } from '../apps.types' import { InstanceTypeSelect } from './InstanceTypeSelect' -import { FormFields, Help } from './styles' +import { FormFields, Help } from './apps-form.styles' const SectionLabelRow = ({ label, diff --git a/packages/client/src/features/apps/form/styles.ts b/packages/client/src/features/apps/form/apps-form.styles.ts similarity index 98% rename from packages/client/src/features/apps/form/styles.ts rename to packages/client/src/features/apps/form/apps-form.styles.ts index 998a4e1b8..16a60a03c 100644 --- a/packages/client/src/features/apps/form/styles.ts +++ b/packages/client/src/features/apps/form/apps-form.styles.ts @@ -1,5 +1,5 @@ import styled, { css } from 'styled-components' -import { FieldGroup } from '../../../components/form/styles' +import { FieldGroup } from '../../../components/form/form.styles' import { PfTab } from '../../../components/Tabs/PfTab' import { StyledMarkdown } from '../../../styles/commonStyles' diff --git a/packages/client/src/features/apps/run/RunJobForm.tsx b/packages/client/src/features/apps/run/RunJobForm.tsx index df4004a3e..58a43b3c9 100644 --- a/packages/client/src/features/apps/run/RunJobForm.tsx +++ b/packages/client/src/features/apps/run/RunJobForm.tsx @@ -28,7 +28,7 @@ import { SelectContext } from './SelectContext' import { SelectInstanceType } from './SelectInstanceType' import { SelectSpaceScope } from './SelectSpaceScope' import { SetOutputFolder } from './SetOutputFolder' -import { RightGroup, StyledActionsContainer, StyledGrid, StyledJobName } from './styles' +import { RightGroup, StyledActionsContainer, StyledGrid, StyledJobName } from './apps-run.styles' import { useExportInputsModal } from './useExportInputsModal' import { useRunJobMutation } from './useRunJobMutation' import { diff --git a/packages/client/src/features/apps/run/SelectInstanceType.tsx b/packages/client/src/features/apps/run/SelectInstanceType.tsx index ae9a3bdf9..26545af97 100644 --- a/packages/client/src/features/apps/run/SelectInstanceType.tsx +++ b/packages/client/src/features/apps/run/SelectInstanceType.tsx @@ -7,7 +7,7 @@ import { cn } from '@/utils/cn' import type { ComputeInstance, RunJobFormType } from '../apps.types' import { getVisibleComputeInstances } from '../instanceTypeAvailability' import { ErrorMessageForField } from './ErrorMessageForField' -import { StyledMaxRuntime } from './styles' +import { StyledMaxRuntime } from './apps-run.styles' export const SelectInstanceType = ({ control, diff --git a/packages/client/src/features/apps/run/styles.ts b/packages/client/src/features/apps/run/apps-run.styles.ts similarity index 100% rename from packages/client/src/features/apps/run/styles.ts rename to packages/client/src/features/apps/run/apps-run.styles.ts diff --git a/packages/client/src/features/apps/run/useExportInputsModal.tsx b/packages/client/src/features/apps/run/useExportInputsModal.tsx index 13faa82fb..27a04b670 100644 --- a/packages/client/src/features/apps/run/useExportInputsModal.tsx +++ b/packages/client/src/features/apps/run/useExportInputsModal.tsx @@ -6,7 +6,7 @@ import MonacoEditor from '../../../components/MonacoEditor/MonacoEditor' import { toastSuccess } from '../../../components/NotificationCenter/ToastHelper' import { useFetchFilesByUIDQuery } from '../../files/query/useFetchFilesByUIDQuery' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import type { IApp } from '../apps.types' import { generateCopyUrl } from './utils' diff --git a/packages/client/src/features/apps/useAttachToChallengeModal.tsx b/packages/client/src/features/apps/useAttachToChallengeModal.tsx index 8c36209ac..09cbd3a89 100644 --- a/packages/client/src/features/apps/useAttachToChallengeModal.tsx +++ b/packages/client/src/features/apps/useAttachToChallengeModal.tsx @@ -8,7 +8,7 @@ import { breakPoints } from '../../styles/theme' import { displayPayloadMessage, Payload } from '../../utils/api' import { CheckCol, ColBody, HeaderRow, Table, TableRow, TitleCol } from '../modal/ModalCheckList' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { APIResource } from '../home/types' import { assignToChallengeRequest, fetchApp } from './apps.api' diff --git a/packages/client/src/features/apps/useExportToModal.tsx b/packages/client/src/features/apps/useExportToModal.tsx index c0bb699e4..728e2eb9b 100644 --- a/packages/client/src/features/apps/useExportToModal.tsx +++ b/packages/client/src/features/apps/useExportToModal.tsx @@ -2,7 +2,7 @@ import React from 'react' import styled from 'styled-components' import { Button } from '../../components/Button' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { IWorkflow } from '../workflows/workflows.types' import { IApp } from './apps.types' diff --git a/packages/client/src/features/apps/useUploadAppConfigFile.tsx b/packages/client/src/features/apps/useUploadAppConfigFile.tsx index e67d48223..99373f74e 100644 --- a/packages/client/src/features/apps/useUploadAppConfigFile.tsx +++ b/packages/client/src/features/apps/useUploadAppConfigFile.tsx @@ -7,7 +7,7 @@ import { Loader } from '../../components/Loader' import MonacoEditor from '../../components/MonacoEditor/MonacoEditor' import { toastSuccess } from '../../components/NotificationCenter/ToastHelper' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { Footer } from '../modal/styles' +import { Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { uploadAppConfigFileRequest } from './apps.api' import { FileType } from './apps.types' diff --git a/packages/client/src/features/assets/AssetList.tsx b/packages/client/src/features/assets/AssetList.tsx index 03712e9a5..58a4d3a3a 100644 --- a/packages/client/src/features/assets/AssetList.tsx +++ b/packages/client/src/features/assets/AssetList.tsx @@ -12,7 +12,7 @@ import { QuestionIcon } from '@/components/icons/QuestionIcon' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' import Table from '../../components/Table' import { useGenerateKeyModal } from '../auth/useGenerateKeyModal' diff --git a/packages/client/src/features/assets/AssetShow.tsx b/packages/client/src/features/assets/AssetShow.tsx index b861608bd..010dfbf7a 100644 --- a/packages/client/src/features/assets/AssetShow.tsx +++ b/packages/client/src/features/assets/AssetShow.tsx @@ -6,7 +6,7 @@ import { FileIcon } from '@/components/icons/FileIcon' import { Markdown, MarkdownStyle } from '@/components/Markdown' import { ActionsMenu } from '@/components/Menu' import { toastInfo } from '@/components/NotificationCenter/ToastHelper' -import { Filler } from '@/components/Page/styles' +import { Filler } from '@/components/Page/page.styles' import { type ITab, TabsSwitch } from '@/components/TabsSwitch' import { StyledPropertyItem, StyledPropertyKey, StyledTagItem, StyledTags } from '@/components/Tags' import { ActionsMenuContent } from '../home/ActionMenuContent' diff --git a/packages/client/src/features/assets/actionModals/useDownloadAssetsModal.tsx b/packages/client/src/features/assets/actionModals/useDownloadAssetsModal.tsx index 730d03749..1b500dbd3 100644 --- a/packages/client/src/features/assets/actionModals/useDownloadAssetsModal.tsx +++ b/packages/client/src/features/assets/actionModals/useDownloadAssetsModal.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' import { Button } from '../../../components/Button' import { DownloadIcon } from '../../../components/icons/DownloadIcon' import { FileIcon } from '../../../components/icons/FileIcon' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { ResourceTable, StyledAction, @@ -11,7 +11,7 @@ import { } from '../../../components/ResourceTable' import { itemsCountString } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { IAsset } from '../assets.types' diff --git a/packages/client/src/features/assets/actionModals/useEditAssetModal.tsx b/packages/client/src/features/assets/actionModals/useEditAssetModal.tsx index f405398d4..dcfb695fd 100644 --- a/packages/client/src/features/assets/actionModals/useEditAssetModal.tsx +++ b/packages/client/src/features/assets/actionModals/useEditAssetModal.tsx @@ -2,9 +2,9 @@ import { ErrorMessage } from '@hookform/error-message' import React, { useMemo } from 'react' import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from '@tanstack/react-query' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' -import { ButtonRow, Footer, StyledForm } from '../../modal/styles' +import { ButtonRow, Footer, StyledForm } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { editAssetRequest } from '../assets.api' import { IAsset } from '../assets.types' diff --git a/packages/client/src/features/assets/actionModals/useSelectAssetModal.tsx b/packages/client/src/features/assets/actionModals/useSelectAssetModal.tsx index 520a2d4d2..6afe0265b 100644 --- a/packages/client/src/features/assets/actionModals/useSelectAssetModal.tsx +++ b/packages/client/src/features/assets/actionModals/useSelectAssetModal.tsx @@ -12,7 +12,7 @@ import { FileIcon } from '../../../components/icons/FileIcon' import { GlobeIcon } from '../../../components/icons/GlobeIcon' import { useAuthUser } from '../../auth/useAuthUser' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ButtonBadge, @@ -27,7 +27,7 @@ import { StyledRow, StyledSubtitle, Tab, -} from '../../actionModals/styles' +} from '../../actionModals/action-modals.styles' import { DialogType, ServerScope } from '../../home/types' import { fetchFilteredAssets } from '../assets.api' import { IAsset } from '../assets.types' diff --git a/packages/client/src/features/auth/AuthPickerModal.tsx b/packages/client/src/features/auth/AuthPickerModal.tsx index 8521432ea..fe8485b7e 100644 --- a/packages/client/src/features/auth/AuthPickerModal.tsx +++ b/packages/client/src/features/auth/AuthPickerModal.tsx @@ -1,6 +1,6 @@ import React from 'react' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { Content, Footer } from '../modal/styles' +import { Content, Footer } from '../modal/modal.styles' import { UseModal } from '../modal/useModal' import { onLogInWithSSO, useSiteSettingsQuery, diff --git a/packages/client/src/features/auth/ExpiringSessionModal.tsx b/packages/client/src/features/auth/ExpiringSessionModal.tsx index 30201ac6f..050a2e104 100644 --- a/packages/client/src/features/auth/ExpiringSessionModal.tsx +++ b/packages/client/src/features/auth/ExpiringSessionModal.tsx @@ -6,7 +6,7 @@ import { getSessionExpiredAt } from '../../utils/cookies' import { pluralize } from '../../utils/formatting' import { useSessionRefresh } from '../../utils/useSessionRefresh' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { Content, Footer } from '../modal/styles' +import { Content, Footer } from '../modal/modal.styles' import { UseModal } from '../modal/useModal' import { useAuthUserQuery } from './api' import { onLogInWithSSO, useSiteSettingsQuery } from './useSiteSettingsQuery' diff --git a/packages/client/src/features/auth/SessionExpiredModal.tsx b/packages/client/src/features/auth/SessionExpiredModal.tsx index 3c93bae03..99ff6447f 100644 --- a/packages/client/src/features/auth/SessionExpiredModal.tsx +++ b/packages/client/src/features/auth/SessionExpiredModal.tsx @@ -1,6 +1,6 @@ import React from 'react' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Content, Footer } from '../modal/styles' +import { ButtonRow, Content, Footer } from '../modal/modal.styles' import { UseModal } from '../modal/useModal' import { onLogInWithSSO, useSiteSettingsQuery } from './useSiteSettingsQuery' import { Button } from '../../components/Button' diff --git a/packages/client/src/features/auth/api.ts b/packages/client/src/features/auth/api.ts index 1903f95ac..6720e2ace 100644 --- a/packages/client/src/features/auth/api.ts +++ b/packages/client/src/features/auth/api.ts @@ -1,8 +1,9 @@ -import { useQuery, UseQueryResult } from '@tanstack/react-query' +import { type UseQueryResult, useQuery } from '@tanstack/react-query' import axios from 'axios' -import { IUser } from '@/types/user' +import type { IUser } from '@/types/user' import { getCookie } from '@/utils/cookies' -import { SiteSettingsResponse } from './useSiteSettingsQuery' +import { clearCsrfToken } from '@/utils/csrf' +import type { SiteSettingsResponse } from './useSiteSettingsQuery' /** * Do not use directly - use the `useAuthUser` hook from './useAuthUser' instead. @@ -34,8 +35,10 @@ export function useAuthUserQuery(): UseQueryResult<{ user: IUser; meta: any }, E }) } -export function logout() { - return axios.delete('/logout') +export async function logout() { + const response = await axios.delete('/logout') + clearCsrfToken() + return response } export type CDMHKey = 'cdmhPortal' | 'cdrBrowser' | 'cdrAdmin' | 'connectPortal' diff --git a/packages/client/src/features/auth/useGenerateKeyModal.tsx b/packages/client/src/features/auth/useGenerateKeyModal.tsx index 8b52540e9..f7481842f 100644 --- a/packages/client/src/features/auth/useGenerateKeyModal.tsx +++ b/packages/client/src/features/auth/useGenerateKeyModal.tsx @@ -6,7 +6,7 @@ import { Svg } from '../../components/icons/Svg' import { Loader } from '../../components/Loader' import { theme } from '../../styles/theme' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ModalScroll } from '../modal/styles' +import { ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { generateKeyRequest } from './api' import { Button } from '../../components/Button' diff --git a/packages/client/src/features/challenges/styles.ts b/packages/client/src/features/challenges/challenges.styles.ts similarity index 100% rename from packages/client/src/features/challenges/styles.ts rename to packages/client/src/features/challenges/challenges.styles.ts diff --git a/packages/client/src/features/challenges/details/ChallengeDetails.tsx b/packages/client/src/features/challenges/details/ChallengeDetails.tsx index 74cface7e..b4ca5ab1b 100644 --- a/packages/client/src/features/challenges/details/ChallengeDetails.tsx +++ b/packages/client/src/features/challenges/details/ChallengeDetails.tsx @@ -1,15 +1,18 @@ -/* eslint-disable no-nested-ternary */ -import React, { useCallback, useRef, useState } from 'react' +import { useCallback, useRef, useState } from 'react' import { Link, Navigate, Route, Routes, useParams } from 'react-router' -import { Loader } from '../../../components/Loader' -import { AddIdsToHeaders } from '../../../components/Markdown/AddIdsToHeaders' -import { PageContainerMargin } from '../../../components/Page/styles' -import { usePageMeta } from '../../../hooks/usePageMeta' -import { cleanObject } from '../../../utils/object' +import { Loader } from '@/components/Loader' +import { AddIdsToHeaders } from '@/components/Markdown/AddIdsToHeaders' +import { MDStyles } from '@/components/Markdown/markdown.styles' +import { PageContainerMargin } from '@/components/Page/page.styles' +import { usePageMeta } from '@/hooks/usePageMeta' +import { cleanObject } from '@/utils/object' import { useAuthUser } from '../../auth/useAuthUser' -import { IToCItem, ToC } from '../../markdown/TocNext' +import { type IToCItem, ToC } from '../../markdown/TocNext' +import type { Meta } from '../types' import { useChallengeByIDQuery } from '../useChallengeDetailsQuery' import { ChallengeDetailsBanner } from './ChallengeDetailsBanner' +import { ChallengeMyEntriesTable } from './ChallengeMyEntriesTable' +import { ChallengeSubmissionsTable } from './ChallengeSubmissionsTable' import { ChallengePageRow, ChallengeRightSide, @@ -18,17 +21,12 @@ import { NoInfo, StyledChallengeNavigation, StyledChallengeNavigationItem, -} from './styles' -import { ChallengeSubmissionsTable } from './ChallengeSubmissionsTable' -import { ChallengeMyEntriesTable } from './ChallengeMyEntriesTable' -import { useNumberParams } from '../../../utils/useNumberParams' -import { MDStyles } from '../../../components/Markdown/styles' -import { Meta } from '../types' +} from './challenges-details.styles' export const ChallengeDetails = () => { usePageMeta({ title: 'Challenge - precisionFDA' }) - const { challengeId } = useNumberParams() + const { challengeId } = useParams<{ challengeId: string }>() const user = useAuthUser() const { data: challenge, isLoading, error } = useChallengeByIDQuery(challengeId!) @@ -70,7 +68,8 @@ export const ChallengeDetails = () => { const userIsChallengeAdmin = isLoggedIn && canCreate - const userCanSeePreRegistration = challengePreRegistration || (userIsChallengeAdmin && challengeSetupOrPreRegistration) + const userCanSeePreRegistration = + challengePreRegistration || (userIsChallengeAdmin && challengeSetupOrPreRegistration) // Introduction is visible to: // - everyone when a challenge is not in pre-registration phase @@ -84,7 +83,8 @@ export const ChallengeDetails = () => { // Results are visible to: // - challenge admins // - everyone when results are announced or challenge is archived - const userCanSeeResults = userIsChallengeAdmin || challenge.status === 'result_announced' || challenge.status === 'archived' + const userCanSeeResults = + userIsChallengeAdmin || challenge.status === 'result_announced' || challenge.status === 'archived' let regions: { intro: string; results: string; preReg: string } if (challenge.meta) { @@ -150,13 +150,23 @@ export const ChallengeDetails = () => { } + element={ + + } /> + ) } /> diff --git a/packages/client/src/features/challenges/details/ChallengeDetailsBanner.tsx b/packages/client/src/features/challenges/details/ChallengeDetailsBanner.tsx index dff002150..7a4d461bd 100644 --- a/packages/client/src/features/challenges/details/ChallengeDetailsBanner.tsx +++ b/packages/client/src/features/challenges/details/ChallengeDetailsBanner.tsx @@ -6,7 +6,7 @@ import { Link } from 'react-router' import styled from 'styled-components' import { Button, OutlineButton } from '../../../components/Button' import NavigationBar from '../../../components/NavigationBar/NavigationBar' -import { PageContainer, pagePadding } from '../../../components/Page/styles' +import { PageContainer, pagePadding } from '../../../components/Page/page.styles' import { ArrowLeftIcon } from '../../../components/icons/ArrowLeftIcon' import { CogsIcon } from '../../../components/icons/Cogs' import { ObjectGroupIcon } from '../../../components/icons/ObjectGroupIcon' @@ -28,7 +28,7 @@ import { RightColumn, StartEnd, StyledChallengeDetailsBanner, -} from './styles' +} from './challenges-details.styles' const ChallengeActionRow = styled(PageContainer)` ${pagePadding} diff --git a/packages/client/src/features/challenges/details/ChallengeNotFound.tsx b/packages/client/src/features/challenges/details/ChallengeNotFound.tsx index 3253f8230..137f5904e 100644 --- a/packages/client/src/features/challenges/details/ChallengeNotFound.tsx +++ b/packages/client/src/features/challenges/details/ChallengeNotFound.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' import { BackLink } from '../../../components/Page/PageBackLink' import { PageContainerMargin, -} from '../../../components/Page/styles' +} from '../../../components/Page/page.styles' export const Warning = styled.div` border: solid 1px #f0ad4e; diff --git a/packages/client/src/features/challenges/details/SubmissionTable.tsx b/packages/client/src/features/challenges/details/SubmissionTable.tsx index a6ad8fe30..ac84b2da3 100644 --- a/packages/client/src/features/challenges/details/SubmissionTable.tsx +++ b/packages/client/src/features/challenges/details/SubmissionTable.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' import { Button } from '../../../components/Button' import { Markdown, MarkdownStyle } from '../../../components/Markdown' import { IUser } from '../../../types/user' -import { ButtonRow, Footer } from '../../modal/styles' +import { ButtonRow, Footer } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { SubmissionInputFile, SubmissionV2 } from './submission.types' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' diff --git a/packages/client/src/features/challenges/details/styles.tsx b/packages/client/src/features/challenges/details/challenges-details.styles.tsx similarity index 99% rename from packages/client/src/features/challenges/details/styles.tsx rename to packages/client/src/features/challenges/details/challenges-details.styles.tsx index 57a90aa01..48c7ee7ad 100644 --- a/packages/client/src/features/challenges/details/styles.tsx +++ b/packages/client/src/features/challenges/details/challenges-details.styles.tsx @@ -1,6 +1,6 @@ import { Link } from 'react-router' import styled, { css } from 'styled-components' -import { PageContainer, pagePaddingLR } from '../../../components/Page/styles' +import { PageContainer, pagePaddingLR } from '../../../components/Page/page.styles' import { breakPoints, colors, theme } from '../../../styles/theme' import { TimeStatus } from '../types' import { Button } from '../../../components/Button' diff --git a/packages/client/src/features/challenges/form/ChallengeCreateUpdateModal.tsx b/packages/client/src/features/challenges/form/ChallengeCreateUpdateModal.tsx index bae6c8842..1dd7aab43 100644 --- a/packages/client/src/features/challenges/form/ChallengeCreateUpdateModal.tsx +++ b/packages/client/src/features/challenges/form/ChallengeCreateUpdateModal.tsx @@ -1,6 +1,6 @@ import React from 'react' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { Content } from '../../modal/styles' +import { Content } from '../../modal/modal.styles' export const ChallengeCreateUpdateModal = ({ isEditMode, diff --git a/packages/client/src/features/challenges/form/ChallengeForm.tsx b/packages/client/src/features/challenges/form/ChallengeForm.tsx index d0e5da597..a10af6855 100644 --- a/packages/client/src/features/challenges/form/ChallengeForm.tsx +++ b/packages/client/src/features/challenges/form/ChallengeForm.tsx @@ -6,7 +6,7 @@ import { Controller, useForm } from 'react-hook-form' import styled from 'styled-components' import { unstable_usePrompt } from 'react-router' import { FieldGroup } from '../../../components/form/FieldGroup' -import { FieldLabel, InputError } from '../../../components/form/styles' +import { FieldLabel, InputError } from '../../../components/form/form.styles' import { InputDateTime, InputFile, InputText } from '../../../components/InputText' import { Loader } from '../../../components/Loader' import { Challenge } from '../types' diff --git a/packages/client/src/features/challenges/form/CreateChallengePage.tsx b/packages/client/src/features/challenges/form/CreateChallengePage.tsx index e57ff59b2..1577c097e 100644 --- a/packages/client/src/features/challenges/form/CreateChallengePage.tsx +++ b/packages/client/src/features/challenges/form/CreateChallengePage.tsx @@ -4,10 +4,10 @@ import { useNavigate } from 'react-router' import NavigationBar from '../../../components/NavigationBar/NavigationBar' import { NotAllowedPage } from '../../../components/NotAllowed' import { BackLinkMargin } from '../../../components/Page/PageBackLink' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { UserLayout } from '../../../layouts/UserLayout' import { useAuthUser } from '../../auth/useAuthUser' -import { StyledPageCenter, StyledPageContent } from '../../spaces/form/styles' +import { StyledPageCenter, StyledPageContent } from '../../spaces/form/spaces-form.styles' import { ChallengePayload, createChallengeRequest } from '../api' import { IChallengeForm, ChallengeForm } from './ChallengeForm' import { mapFormToPayload, subtitle, title } from './common' diff --git a/packages/client/src/features/challenges/form/EditChallengePage.tsx b/packages/client/src/features/challenges/form/EditChallengePage.tsx index cb1d43dc9..6d91b8adc 100644 --- a/packages/client/src/features/challenges/form/EditChallengePage.tsx +++ b/packages/client/src/features/challenges/form/EditChallengePage.tsx @@ -5,11 +5,11 @@ import { useNavigate, useParams } from 'react-router' import { Loader } from '../../../components/Loader' import { NotAllowedPage } from '../../../components/NotAllowed' import { BackLinkMargin } from '../../../components/Page/PageBackLink' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { UserLayout } from '../../../layouts/UserLayout' import { dateToInput } from '../../../utils/datetime' import { useAuthUser } from '../../auth/useAuthUser' -import { StyledPageCenter, StyledPageContent } from '../../spaces/form/styles' +import { StyledPageCenter, StyledPageContent } from '../../spaces/form/spaces-form.styles' import { ChallengePayload, editChallengeRequest } from '../api' import { useChallengeDetailsQuery } from '../useChallengeDetailsQuery' import { ChallengeForm, IChallengeForm } from './ChallengeForm' diff --git a/packages/client/src/features/challenges/form/ProposeChallengeForm.tsx b/packages/client/src/features/challenges/form/ProposeChallengeForm.tsx index 99bfbea1f..94899fec8 100644 --- a/packages/client/src/features/challenges/form/ProposeChallengeForm.tsx +++ b/packages/client/src/features/challenges/form/ProposeChallengeForm.tsx @@ -5,14 +5,14 @@ import React, { useEffect } from 'react' import { unstable_usePrompt } from 'react-router' import { Controller, useForm } from 'react-hook-form' import styled from 'styled-components' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { Loader } from '../../../components/Loader' import { useMutationErrorEffect } from '../../../hooks/useMutationErrorEffect' import { MutationErrors } from '../../../types/utils' import { RadioButtonGroup } from '../../../components/form/RadioButtonGroup' import { proposeValidationSchema } from './common' -import { SectionTitle } from '../../../components/Public/styles' +import { SectionTitle } from '../../../components/Public/public-layout.styles' import { Button } from '../../../components/Button' diff --git a/packages/client/src/features/challenges/list/ChallengeListItem.tsx b/packages/client/src/features/challenges/list/ChallengeListItem.tsx index d787bd9da..5fa565a27 100644 --- a/packages/client/src/features/challenges/list/ChallengeListItem.tsx +++ b/packages/client/src/features/challenges/list/ChallengeListItem.tsx @@ -2,8 +2,8 @@ import { format } from 'date-fns' import React from 'react' import { Link } from 'react-router' import styled from 'styled-components' -import { Content, ItemBody } from '../../../components/Public/styles' -import { DateArea, ItemImage, ViewDetailsButton } from '../styles' +import { Content, ItemBody } from '../../../components/Public/public-layout.styles' +import { DateArea, ItemImage, ViewDetailsButton } from '../challenges.styles' import { Challenge } from '../types' import { getChallengeTimeRemaining, getTimeStatus } from '../util' diff --git a/packages/client/src/features/challenges/list/ChallengesList.tsx b/packages/client/src/features/challenges/list/ChallengesList.tsx index 819c04dd5..fccc340a0 100644 --- a/packages/client/src/features/challenges/list/ChallengesList.tsx +++ b/packages/client/src/features/challenges/list/ChallengesList.tsx @@ -6,7 +6,7 @@ import styled from 'styled-components' import { Button } from '../../../components/Button' import { Loader } from '../../../components/Loader' import NavigationBar from '../../../components/NavigationBar/NavigationBar' -import { PageContainerMargin } from '../../../components/Page/styles' +import { PageContainerMargin } from '../../../components/Page/page.styles' import { hidePagination, Pagination } from '../../../components/Pagination' import { ButtonRow, @@ -20,7 +20,7 @@ import { RightSide, RightSideItem, SectionTitle, -} from '../../../components/Public/styles' +} from '../../../components/Public/public-layout.styles' import { usePageMeta } from '../../../hooks/usePageMeta' import { usePaginationParamsV2 } from '../../../hooks/usePaginationState' import { useLastWSNotification } from '../../../hooks/useLastWSNotification' diff --git a/packages/client/src/features/challenges/useChallengeDetailsQuery.ts b/packages/client/src/features/challenges/useChallengeDetailsQuery.ts index a2a8336b1..7540c1560 100644 --- a/packages/client/src/features/challenges/useChallengeDetailsQuery.ts +++ b/packages/client/src/features/challenges/useChallengeDetailsQuery.ts @@ -1,9 +1,9 @@ import { useQuery } from '@tanstack/react-query' -import { AxiosError } from 'axios' -import { challengeByID, challengeDetailsRequest, ContentType } from './api' -import { Challenge, ChallengeOld } from './types' -import { ApiErrorResponse } from '../home/types' -import { toastError } from '../../components/NotificationCenter/ToastHelper' +import type { AxiosError } from 'axios' +import { toastError } from '@/components/NotificationCenter/ToastHelper' +import type { ApiErrorResponse } from '../home/types' +import { type ContentType, challengeByID, challengeDetailsRequest } from './api' +import type { Challenge, ChallengeOld } from './types' export const useChallengeDetailsQuery = (id: string) => useQuery>({ diff --git a/packages/client/src/features/comparators/useComparatorModal.tsx b/packages/client/src/features/comparators/useComparatorModal.tsx index 90fe74f13..09247efbc 100644 --- a/packages/client/src/features/comparators/useComparatorModal.tsx +++ b/packages/client/src/features/comparators/useComparatorModal.tsx @@ -1,7 +1,7 @@ import React from 'react' import { useMutation } from '@tanstack/react-query' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, StyledModalContent } from '../modal/styles' +import { ButtonRow, Footer, StyledModalContent } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { FileLicense } from '../assets/assets.types' import { Button } from '../../components/Button' diff --git a/packages/client/src/features/comparisons/actionModals/useSelectComparisonModal.tsx b/packages/client/src/features/comparisons/actionModals/useSelectComparisonModal.tsx index 213bbc584..5676e96c9 100644 --- a/packages/client/src/features/comparisons/actionModals/useSelectComparisonModal.tsx +++ b/packages/client/src/features/comparisons/actionModals/useSelectComparisonModal.tsx @@ -12,7 +12,7 @@ import { FileIcon } from '../../../components/icons/FileIcon' import { GlobeIcon } from '../../../components/icons/GlobeIcon' import { useAuthUser } from '../../auth/useAuthUser' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ButtonBadge, @@ -27,7 +27,7 @@ import { StyledRow, StyledSubtitle, Tab, -} from '../../actionModals/styles' +} from '../../actionModals/action-modals.styles' import { DialogType, ServerScope } from '../../home/types' import { fetchFilteredComparisons } from '../comparisons.api' import { IComparison } from '../comparisons.types' diff --git a/packages/client/src/features/data-portals/api.ts b/packages/client/src/features/data-portals/api.ts index 9dbabcc06..0cd91de3e 100644 --- a/packages/client/src/features/data-portals/api.ts +++ b/packages/client/src/features/data-portals/api.ts @@ -1,7 +1,7 @@ import axios from 'axios' import { createFile } from '../files/files.api' import { processFile } from '../resources/uploadImage' -import { CreateDataPortalData, DataPortal, UpdateDataPortalData } from './types' +import type { CreateDataPortalData, DataPortal, UpdateDataPortalData } from './types' export async function fetchGovUsers(): Promise<[]> { return axios.get('/api/v2/users/government').then(r => r.data) diff --git a/packages/client/src/features/data-portals/details/DataPortalDetails.tsx b/packages/client/src/features/data-portals/details/DataPortalDetails.tsx index be56e8730..cc36646fc 100644 --- a/packages/client/src/features/data-portals/details/DataPortalDetails.tsx +++ b/packages/client/src/features/data-portals/details/DataPortalDetails.tsx @@ -1,19 +1,19 @@ import React, { useCallback, useRef, useState } from 'react' import { Link, Route, Routes } from 'react-router' import { Button } from '../../../components/Button' -import { ListItem, NoContent } from '../../../components/Public/styles' +import { ListItem, NoContent } from '../../../components/Public/public-layout.styles' import { DataPortalCard } from '../DataPortalCard' import { DataPortal } from '../types' import { AlertText } from './DataPortalNotFound' import { AddIdsToHeaders } from '../../../components/Markdown/AddIdsToHeaders' -import { Filler } from '../../../components/Page/styles' -import { StyledInnerHTML } from '../../lexi/styles' +import { Filler } from '../../../components/Page/page.styles' +import { StyledInnerHTML } from '../../lexi/lexi.styles' import '../../lexi/themes/PlaygroundEditorTheme.css' import { IToCItem, ToC } from '../../markdown/TocNext' import { useDataPortalResourceModal } from '../../resources/useDataPortalResourceModal' import DataPortalContentEditPage from '../form/DataPortalContentEditPage' -import { BodyContent, DataPortalPageMainBody, DPSettings, PageWrap, RightSideItem, RightSideScroll, Row } from './styles' +import { BodyContent, DataPortalPageMainBody, DPSettings, PageWrap, RightSideItem, RightSideScroll, Row } from './data-portals-details.styles' export const DataPortalDetails = ({ portal, diff --git a/packages/client/src/features/data-portals/details/DataPortalDetailsPage.tsx b/packages/client/src/features/data-portals/details/DataPortalDetailsPage.tsx index 2bc479ac7..9356a8cdb 100644 --- a/packages/client/src/features/data-portals/details/DataPortalDetailsPage.tsx +++ b/packages/client/src/features/data-portals/details/DataPortalDetailsPage.tsx @@ -2,7 +2,7 @@ import { useQueryClient } from '@tanstack/react-query' import React, { useEffect } from 'react' import { useNavigate, useParams } from 'react-router' import { Loader, LoaderMargin } from '../../../components/Loader' -import { PageContainerMargin } from '../../../components/Page/styles' +import { PageContainerMargin } from '../../../components/Page/page.styles' import { UserLayout } from '../../../layouts/UserLayout' import { useAuthUser } from '../../auth/useAuthUser' import { NOTIFICATION_ACTION } from '../../home/types' diff --git a/packages/client/src/features/data-portals/details/DataPortalNotFound.tsx b/packages/client/src/features/data-portals/details/DataPortalNotFound.tsx index 49e117cfa..bc8b60346 100644 --- a/packages/client/src/features/data-portals/details/DataPortalNotFound.tsx +++ b/packages/client/src/features/data-portals/details/DataPortalNotFound.tsx @@ -1,6 +1,6 @@ import React from 'react' import styled from 'styled-components' -import { PageContainerMargin } from '../../../components/Page/styles' +import { PageContainerMargin } from '../../../components/Page/page.styles' export const Warning = styled.div` border: solid 1px #f0ad4e; diff --git a/packages/client/src/features/data-portals/details/styles.ts b/packages/client/src/features/data-portals/details/data-portals-details.styles.ts similarity index 94% rename from packages/client/src/features/data-portals/details/styles.ts rename to packages/client/src/features/data-portals/details/data-portals-details.styles.ts index b3b2a62a7..59c05e08d 100644 --- a/packages/client/src/features/data-portals/details/styles.ts +++ b/packages/client/src/features/data-portals/details/data-portals-details.styles.ts @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { compactScrollBarV2 } from '../../../components/Page/styles' +import { compactScrollBarV2 } from '../../../components/Page/page.styles' export const RightSideItem = styled.div` display: flex; diff --git a/packages/client/src/features/data-portals/form/CreateDataPortalPage.tsx b/packages/client/src/features/data-portals/form/CreateDataPortalPage.tsx index cbd939f03..762351d96 100644 --- a/packages/client/src/features/data-portals/form/CreateDataPortalPage.tsx +++ b/packages/client/src/features/data-portals/form/CreateDataPortalPage.tsx @@ -5,11 +5,11 @@ import { useNavigate } from 'react-router' import { NotAllowedPage } from '../../../components/NotAllowed' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' import { BackLinkMargin } from '../../../components/Page/PageBackLink' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { UserLayout } from '../../../layouts/UserLayout' import { useAuthUser } from '../../auth/useAuthUser' import { ApiErrorResponse } from '../../home/types' -import { StyledPageCenter, StyledPageContent } from '../../spaces/form/styles' +import { StyledPageCenter, StyledPageContent } from '../../spaces/form/spaces-form.styles' import { createDataPortalRequest } from '../api' import { CreateDataPortalData } from '../types' import { CreateDataPortalForm, DataPortalForm } from './DataPortalForm' diff --git a/packages/client/src/features/data-portals/form/DataPortalForm.tsx b/packages/client/src/features/data-portals/form/DataPortalForm.tsx index 0b58ac6ec..3f6e92a96 100644 --- a/packages/client/src/features/data-portals/form/DataPortalForm.tsx +++ b/packages/client/src/features/data-portals/form/DataPortalForm.tsx @@ -11,7 +11,7 @@ import { InputFile, InputNumber, InputText } from '../../../components/InputText import { Loader } from '../../../components/Loader' import { FieldGroup } from '../../../components/form/FieldGroup' import { FieldInfo } from '../../../components/form/FieldInfo' -import { InputError } from '../../../components/form/styles' +import { InputError } from '../../../components/form/form.styles' import { useAuthUser } from '../../auth/useAuthUser' import { ApiErrorResponse } from '../../home/types' import { SavingModal } from '../../modal/SavingModal' diff --git a/packages/client/src/features/data-portals/form/EditDataPortalPage.tsx b/packages/client/src/features/data-portals/form/EditDataPortalPage.tsx index a26dabd65..590189685 100644 --- a/packages/client/src/features/data-portals/form/EditDataPortalPage.tsx +++ b/packages/client/src/features/data-portals/form/EditDataPortalPage.tsx @@ -6,11 +6,11 @@ import { Loader } from '../../../components/Loader' import { NotAllowedPage } from '../../../components/NotAllowed' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' import { BackLinkMargin } from '../../../components/Page/PageBackLink' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { UserLayout } from '../../../layouts/UserLayout' import { useAuthUser } from '../../auth/useAuthUser' import { ApiErrorResponse } from '../../home/types' -import { StyledPageCenter, StyledPageContent } from '../../spaces/form/styles' +import { StyledPageCenter, StyledPageContent } from '../../spaces/form/spaces-form.styles' import { editDataPortalRequest, UpdateDataPortalRequest } from '../api' import { useDataPortalByIdQuery } from '../queries' import { UpdateDataPortalData } from '../types' diff --git a/packages/client/src/features/data-portals/list/DataPortalsListPage.tsx b/packages/client/src/features/data-portals/list/DataPortalsListPage.tsx index 22e6ec728..4d09b9876 100644 --- a/packages/client/src/features/data-portals/list/DataPortalsListPage.tsx +++ b/packages/client/src/features/data-portals/list/DataPortalsListPage.tsx @@ -1,18 +1,18 @@ import { useQuery, useQueryClient } from '@tanstack/react-query' -import React, { useEffect } from 'react' +import { useEffect } from 'react' import { Link } from 'react-router' import styled from 'styled-components' -import { Button } from '../../../components/Button' -import { Loader } from '../../../components/Loader' -import { PageContainerMargin, PageTitle } from '../../../components/Page/styles' -import { PageLoaderWrapper } from '../../../components/Public/styles' -import { usePageMeta } from '../../../hooks/usePageMeta' -import { useLastWSNotification } from '../../../hooks/useLastWSNotification' -import { UserLayout } from '../../../layouts/UserLayout' -import { theme } from '../../../styles/theme' +import { Button } from '@/components/Button' +import { Loader } from '@/components/Loader' +import { PageContainerMargin, PageTitle } from '@/components/Page/page.styles' +import { PageLoaderWrapper } from '@/components/Public/public-layout.styles' +import { useLastWSNotification } from '@/hooks/useLastWSNotification' +import { usePageMeta } from '@/hooks/usePageMeta' +import { UserLayout } from '@/layouts/UserLayout' +import { theme } from '@/styles/theme' import { useAuthUser } from '../../auth/useAuthUser' import { NOTIFICATION_ACTION } from '../../home/types' -import { StyledPageCenter } from '../../spaces/form/styles' +import { StyledPageCenter } from '../../spaces/form/spaces-form.styles' import { dataPortalsListRequest } from '../api' import { AlertText } from '../details/DataPortalNotFound' import { DataPortalListItem } from './DataPortalListItem' diff --git a/packages/client/src/features/databases/DatabaseList.tsx b/packages/client/src/features/databases/DatabaseList.tsx index 18e11da4e..55cf1fb42 100644 --- a/packages/client/src/features/databases/DatabaseList.tsx +++ b/packages/client/src/features/databases/DatabaseList.tsx @@ -9,9 +9,9 @@ import { SyncIcon } from '@/components/icons/SyncIcon' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' import { BackLink } from '@/components/Page/PageBackLink' -import { Refresh } from '@/components/Page/styles' +import { Refresh } from '@/components/Page/page.styles' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { useLastWSNotification } from '@/hooks/useLastWSNotification' import { getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' import Table from '../../components/Table' diff --git a/packages/client/src/features/databases/create/CreateDatabase.tsx b/packages/client/src/features/databases/create/CreateDatabase.tsx index a11408a95..8a6763ad1 100644 --- a/packages/client/src/features/databases/create/CreateDatabase.tsx +++ b/packages/client/src/features/databases/create/CreateDatabase.tsx @@ -9,7 +9,7 @@ import { useCreateDatabaseMutation } from '@/api/mutations/database' import { Button } from '@/components/Button' import { FieldGroup } from '@/components/form/FieldGroup' import { RadioButtonGroup } from '@/components/form/RadioButtonGroup' -import { InputError } from '@/components/form/styles' +import { InputError } from '@/components/form/form.styles' import { InputText } from '@/components/InputText' import { Loader } from '@/components/Loader' import { SelectContent, SelectItem, SelectTrigger, SelectValue, Select as UiSelect } from '@/components/ui/select' diff --git a/packages/client/src/features/databases/useEditDatabaseModal.tsx b/packages/client/src/features/databases/useEditDatabaseModal.tsx index a9c62d86d..9e37d2a78 100644 --- a/packages/client/src/features/databases/useEditDatabaseModal.tsx +++ b/packages/client/src/features/databases/useEditDatabaseModal.tsx @@ -2,9 +2,9 @@ import { ErrorMessage } from '@hookform/error-message' import React, { useMemo } from 'react' import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from '@tanstack/react-query' -import { FieldGroup, InputError } from '../../components/form/styles' +import { FieldGroup, InputError } from '../../components/form/form.styles' import { InputText } from '../../components/InputText' -import { ButtonRow, Footer, ModalScroll, StyledForm } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll, StyledForm } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { EditDatabasePayload, editDatabaseRequest } from './databases.api' import { IDatabase } from './databases.types' diff --git a/packages/client/src/features/databases/useMethodModal.tsx b/packages/client/src/features/databases/useMethodModal.tsx index 7d88338d2..d46ce6cdb 100644 --- a/packages/client/src/features/databases/useMethodModal.tsx +++ b/packages/client/src/features/databases/useMethodModal.tsx @@ -6,7 +6,7 @@ import { Loader } from '../../components/Loader' import { ResourceTable } from '../../components/ResourceTable' import { pluralize } from '../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Content, Footer } from '../modal/styles' +import { ButtonRow, Content, Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { databaseMethodRequest } from './databases.api' import { MethodType } from './databases.types' diff --git a/packages/client/src/features/discussions/AttachmentsList.tsx b/packages/client/src/features/discussions/AttachmentsList.tsx index 23909fcc8..ee7846f33 100644 --- a/packages/client/src/features/discussions/AttachmentsList.tsx +++ b/packages/client/src/features/discussions/AttachmentsList.tsx @@ -11,7 +11,7 @@ import { FolderIcon } from '../../components/icons/FolderIcon' import { TrashIcon } from '../../components/icons/TrashIcon' import { Attachment, AttachmentKey, AttachmentType, FormAttachments } from './discussions.types' import { areAttachmentsEmpty, typeAttachmentKey } from './helpers' -import { AttachmentsLabel } from './styles' +import { AttachmentsLabel } from './discussions.styles' const StyledAttachmentsContainer = styled.div`` diff --git a/packages/client/src/features/discussions/DiscussionAnswer.tsx b/packages/client/src/features/discussions/DiscussionAnswer.tsx index aadcc1d3f..2cdf33c57 100644 --- a/packages/client/src/features/discussions/DiscussionAnswer.tsx +++ b/packages/client/src/features/discussions/DiscussionAnswer.tsx @@ -3,7 +3,7 @@ import { NoteScope } from './api' import { ReplyCard } from './card/ReplyCard' import { Answer } from './discussions.types' import { CreateReplyEntity } from './form/CreateReplyEntity' -import { StyledCardList } from './styles' +import { StyledCardList } from './discussions.styles' export const DiscussionAnswer = ({ canEdit, diff --git a/packages/client/src/features/discussions/DiscussionList.tsx b/packages/client/src/features/discussions/DiscussionList.tsx index c6dbfafd8..8565afe8e 100644 --- a/packages/client/src/features/discussions/DiscussionList.tsx +++ b/packages/client/src/features/discussions/DiscussionList.tsx @@ -11,7 +11,7 @@ import { Button } from '@/components/Button' import { DiscussionIcon } from '@/components/icons/DiscussionIcon' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { toArrayFromObject } from '@/utils/object' import Table from '../../components/Table' import { ActionsRow, QuickActions } from '../home/home.styles' diff --git a/packages/client/src/features/discussions/DiscussionShow.tsx b/packages/client/src/features/discussions/DiscussionShow.tsx index 1f3fb72eb..ced73bb6d 100644 --- a/packages/client/src/features/discussions/DiscussionShow.tsx +++ b/packages/client/src/features/discussions/DiscussionShow.tsx @@ -26,7 +26,7 @@ import { ReplyCard } from './card/ReplyCard' import { Attachment } from './discussions.types' import { CreateReplyEntity } from './form/CreateReplyEntity' import { EditDiscussionTitle } from './form/EditDiscussionTitle' -import { CommentCount, DiscussionTitle, PageContent, StyledCardList, StyledTitle, UsernameLink } from './styles' +import { CommentCount, DiscussionTitle, PageContent, StyledCardList, StyledTitle, UsernameLink } from './discussions.styles' interface DiscussionContextType { attachments: Record diff --git a/packages/client/src/features/discussions/card/CardHeader.tsx b/packages/client/src/features/discussions/card/CardHeader.tsx index 03ccbf4cc..ccd212089 100644 --- a/packages/client/src/features/discussions/card/CardHeader.tsx +++ b/packages/client/src/features/discussions/card/CardHeader.tsx @@ -3,7 +3,7 @@ import Menu from '../../../components/Menu/Menu' import { StarIcon } from '../../../components/icons/StarIcon' import { ThreeDotsIcon } from '../../../components/icons/ThreeDotsIcon' import { formatDiscussionDate } from '../helpers' -import { CardLeft, CardRight, StyledAnswerLabel, StyledCardHeader, StyledEditButton, UsernameLink } from '../styles' +import { CardLeft, CardRight, StyledAnswerLabel, StyledCardHeader, StyledEditButton, UsernameLink } from '../discussions.styles' import { CardType } from '../discussions.types' import { SimpleUser } from '../../../types/user' import styles from '../styles.module.css' diff --git a/packages/client/src/features/discussions/card/DiscussionCard.tsx b/packages/client/src/features/discussions/card/DiscussionCard.tsx index 80013c36b..fc4313b1c 100644 --- a/packages/client/src/features/discussions/card/DiscussionCard.tsx +++ b/packages/client/src/features/discussions/card/DiscussionCard.tsx @@ -9,7 +9,7 @@ import { deleteDiscussionRequest } from '../api' import { Attachment, Discussion } from '../discussions.types' import { EditNoteEntity } from '../form/EditNoteEntity' import { groupByAttachmentType } from '../helpers' -import { StyledCommentCard, StyledReplyButton } from '../styles' +import { StyledCommentCard, StyledReplyButton } from '../discussions.styles' import { CardHeader } from './CardHeader' export function DiscussionCard({ diff --git a/packages/client/src/features/discussions/card/ReplyCard.tsx b/packages/client/src/features/discussions/card/ReplyCard.tsx index 9c70ee319..1e5135242 100644 --- a/packages/client/src/features/discussions/card/ReplyCard.tsx +++ b/packages/client/src/features/discussions/card/ReplyCard.tsx @@ -11,7 +11,7 @@ import { deleteReplyRequest, NoteScope } from '../api' import { DiscussionReply } from '../discussions.types' import { EditNoteEntity } from '../form/EditNoteEntity' import { groupByAttachmentType } from '../helpers' -import { StyledCommentCard, StyledReplyButton } from '../styles' +import { StyledCommentCard, StyledReplyButton } from '../discussions.styles' import { CardHeader } from './CardHeader' export function ReplyCard({ diff --git a/packages/client/src/features/discussions/styles.tsx b/packages/client/src/features/discussions/discussions.styles.tsx similarity index 100% rename from packages/client/src/features/discussions/styles.tsx rename to packages/client/src/features/discussions/discussions.styles.tsx diff --git a/packages/client/src/features/discussions/form/CreateDiscussionPage.tsx b/packages/client/src/features/discussions/form/CreateDiscussionPage.tsx index 7138deb3c..85ea05c58 100644 --- a/packages/client/src/features/discussions/form/CreateDiscussionPage.tsx +++ b/packages/client/src/features/discussions/form/CreateDiscussionPage.tsx @@ -2,10 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import React from 'react' import { useLocation, useNavigate } from 'react-router' import styled from 'styled-components' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { getSpaceIdFromScope } from '../../../utils' import { StyledBackLink } from '../../home/home.styles' -import { FormPageContainer } from '../../news/form/styles' +import { FormPageContainer } from '../../news/form/news-form.styles' import { createDiscussionRequest, NoteScope } from '../api' import { DiscussionForm as DiscussionFormType } from '../discussions.types' import { pickIdsFromFormAttachments } from '../helpers' diff --git a/packages/client/src/features/discussions/form/DiscussionForm.tsx b/packages/client/src/features/discussions/form/DiscussionForm.tsx index 5cd1661e8..8e01f8c09 100644 --- a/packages/client/src/features/discussions/form/DiscussionForm.tsx +++ b/packages/client/src/features/discussions/form/DiscussionForm.tsx @@ -8,12 +8,12 @@ import { Button } from '../../../components/Button' import { InputText } from '../../../components/InputText' import { MarkdownEditor } from '../../../components/Markdown/MarkdownEditor' import { FieldGroup } from '../../../components/form/FieldGroup' -import { InputError } from '../../../components/form/styles' +import { InputError } from '../../../components/form/form.styles' import { AttachmentsList } from '../AttachmentsList' import { NoteScope } from '../api' import { AttachmentKey, DiscussionForm as DiscussionFormType, NoteForm } from '../discussions.types' import { Attachments } from './Attachments' -import { StyledPage } from './styles' +import { StyledPage } from './discussions-form.styles' import { NotifyMembersSelect } from './NotifyMembersSelect' const StyledAttachments = styled.div` diff --git a/packages/client/src/features/discussions/form/EditNoteEntity.tsx b/packages/client/src/features/discussions/form/EditNoteEntity.tsx index 15f048364..c69e338e7 100644 --- a/packages/client/src/features/discussions/form/EditNoteEntity.tsx +++ b/packages/client/src/features/discussions/form/EditNoteEntity.tsx @@ -10,8 +10,8 @@ import { NotePayload, NoteScope, editDiscussionRequest, editReplyRequest, fetchD import { Button } from '../../../components/Button' import { MarkdownEditor } from '../../../components/Markdown/MarkdownEditor' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' -import { InputError } from '../../../components/form/styles' -import { ButtonRow } from '../../modal/styles' +import { InputError } from '../../../components/form/form.styles' +import { ButtonRow } from '../../modal/modal.styles' import { AttachmentsList } from '../AttachmentsList' import { AttachmentKey, NoteForm } from '../discussions.types' import { groupByAttachmentType, pickIdsFromFormAttachments } from '../helpers' diff --git a/packages/client/src/features/discussions/form/MarkdownForm.tsx b/packages/client/src/features/discussions/form/MarkdownForm.tsx index 6ba01da5f..3573e65a0 100644 --- a/packages/client/src/features/discussions/form/MarkdownForm.tsx +++ b/packages/client/src/features/discussions/form/MarkdownForm.tsx @@ -9,7 +9,7 @@ import { Button } from '../../../components/Button' import { Checkbox } from '../../../components/Checkbox' import ExternalLink from '../../../components/Controls/ExternalLink' import { MarkdownEditor, StyledMarkdownHelper, WeMarkdown } from '../../../components/Markdown/MarkdownEditor' -import { CheckboxLabel, InputError } from '../../../components/form/styles' +import { CheckboxLabel, InputError } from '../../../components/form/form.styles' import { MarkdownIcon } from '../../../components/icons/MarkdownIcon' import { AttachmentsList } from '../AttachmentsList' import { NoteScope } from '../api' diff --git a/packages/client/src/features/discussions/form/styles.ts b/packages/client/src/features/discussions/form/discussions-form.styles.ts similarity index 100% rename from packages/client/src/features/discussions/form/styles.ts rename to packages/client/src/features/discussions/form/discussions-form.styles.ts diff --git a/packages/client/src/features/executions/ExecutionActionsRow.tsx b/packages/client/src/features/executions/ExecutionActionsRow.tsx index 34f302922..24a5f3a83 100644 --- a/packages/client/src/features/executions/ExecutionActionsRow.tsx +++ b/packages/client/src/features/executions/ExecutionActionsRow.tsx @@ -12,7 +12,7 @@ import { useAuthUser } from '../auth/useAuthUser' import { ActionsMenuContent } from '../home/ActionMenuContent' import { ActionModalsRenderer } from '../home/ActionModalsRenderer' import { HomeScope } from '../home/types' -import { StyledRefresh, StyledStatusText } from './details/styles' +import { StyledRefresh, StyledStatusText } from './details/executions-details.styles' import { IExecution } from './executions.types' import { getOpenExternalUrl, isOpenExternalAvailable } from './executions.util' import { useExecutionSelectActions } from './useExecutionSelectActions' diff --git a/packages/client/src/features/executions/ExecutionList.tsx b/packages/client/src/features/executions/ExecutionList.tsx index 282218e7b..706cf5bc7 100644 --- a/packages/client/src/features/executions/ExecutionList.tsx +++ b/packages/client/src/features/executions/ExecutionList.tsx @@ -11,7 +11,7 @@ import { useEffect, useState } from 'react' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { useLastWSNotification } from '@/hooks/useLastWSNotification' import { ErrorBoundary } from '@/utils/ErrorBoundary' import { getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' diff --git a/packages/client/src/features/executions/actionModals/useSelectJobModal.tsx b/packages/client/src/features/executions/actionModals/useSelectJobModal.tsx index 160f0e081..74f7ac8f5 100644 --- a/packages/client/src/features/executions/actionModals/useSelectJobModal.tsx +++ b/packages/client/src/features/executions/actionModals/useSelectJobModal.tsx @@ -12,7 +12,7 @@ import { FileIcon } from '../../../components/icons/FileIcon' import { GlobeIcon } from '../../../components/icons/GlobeIcon' import { useAuthUser } from '../../auth/useAuthUser' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ButtonBadge, @@ -27,7 +27,7 @@ import { StyledRow, StyledSubtitle, Tab, -} from '../../actionModals/styles' +} from '../../actionModals/action-modals.styles' import { DialogType } from '../../home/types' import { fetchFilteredJobs } from '../executions.api' import { IJob } from '../executions.types' diff --git a/packages/client/src/features/executions/details/ExecutionDetails.tsx b/packages/client/src/features/executions/details/ExecutionDetails.tsx index 132b18377..b273b6124 100644 --- a/packages/client/src/features/executions/details/ExecutionDetails.tsx +++ b/packages/client/src/features/executions/details/ExecutionDetails.tsx @@ -36,7 +36,7 @@ import { getUserLink } from '../executions.util' import { InputsAndOutputs } from '../InputsAndOutputs' import { Logs } from '../Log' import { StateCell } from '../StateCell' -import { FailureMessage, TitleLeft } from './styles' +import { FailureMessage, TitleLeft } from './executions-details.styles' const calculateCost = (durationInSeconds: number, instanceType: string): string => { const runtimeHours = durationInSeconds / 3600 diff --git a/packages/client/src/features/executions/details/styles.tsx b/packages/client/src/features/executions/details/executions-details.styles.tsx similarity index 90% rename from packages/client/src/features/executions/details/styles.tsx rename to packages/client/src/features/executions/details/executions-details.styles.tsx index b66f8bcb6..0efe35217 100644 --- a/packages/client/src/features/executions/details/styles.tsx +++ b/packages/client/src/features/executions/details/executions-details.styles.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { Refresh } from '../../../components/Page/styles' +import { Refresh } from '../../../components/Page/page.styles' export const StyledRefresh = styled(Refresh)` margin-right: 16px; diff --git a/packages/client/src/features/executions/useSnapshotModal.tsx b/packages/client/src/features/executions/useSnapshotModal.tsx index 991d3f8f7..afcb1ae86 100644 --- a/packages/client/src/features/executions/useSnapshotModal.tsx +++ b/packages/client/src/features/executions/useSnapshotModal.tsx @@ -9,13 +9,13 @@ import * as Yup from 'yup' import { Button } from '../../components/Button' import { Checkbox } from '../../components/Checkbox' import { FieldGroup } from '../../components/form/FieldGroup' -import { CheckboxLabel, InputError } from '../../components/form/styles' +import { CheckboxLabel, InputError } from '../../components/form/form.styles' import { InputText } from '../../components/InputText' import { Loader } from '../../components/Loader' import { toastError, toastSuccess } from '../../components/NotificationCenter/ToastHelper' import { colors } from '../../styles/theme' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { workstationSnapshotRequest } from './executions.api' import { IExecution } from './executions.types' diff --git a/packages/client/src/features/executions/useTerminateModal.tsx b/packages/client/src/features/executions/useTerminateModal.tsx index 03e2c8b97..20ea37a71 100644 --- a/packages/client/src/features/executions/useTerminateModal.tsx +++ b/packages/client/src/features/executions/useTerminateModal.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components' import { Loader } from '../../components/Loader' import { ResourceTable } from '../../components/ResourceTable' import { ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { terminateJobsRequest } from './executions.api' import { IExecution } from './executions.types' diff --git a/packages/client/src/features/experts/ExpertsCondensedList/ExpertsCondensedList.tsx b/packages/client/src/features/experts/ExpertsCondensedList/ExpertsCondensedList.tsx index 627ff4a3c..c624adeec 100644 --- a/packages/client/src/features/experts/ExpertsCondensedList/ExpertsCondensedList.tsx +++ b/packages/client/src/features/experts/ExpertsCondensedList/ExpertsCondensedList.tsx @@ -3,7 +3,7 @@ import { Link } from 'react-router' import { Loader } from '../../../components/Loader' import { usePaginationState } from '../../../hooks/usePaginationState' import { pluralize } from '../../../utils/formatting' -import { ExpertImageCircleSmall, ExpertMeta, ExpertRow, StyledCondensedList } from './styles' +import { ExpertImageCircleSmall, ExpertMeta, ExpertRow, StyledCondensedList } from './experts-condensed-list.styles' import { useExpertsListCondensedQuery } from '../useExpertsListQuery' export const ExpertsCondensedList = ({ pick }: { pick?: number }) => { diff --git a/packages/client/src/features/experts/ExpertsCondensedList/styles.tsx b/packages/client/src/features/experts/ExpertsCondensedList/experts-condensed-list.styles.tsx similarity index 100% rename from packages/client/src/features/experts/ExpertsCondensedList/styles.tsx rename to packages/client/src/features/experts/ExpertsCondensedList/experts-condensed-list.styles.tsx diff --git a/packages/client/src/features/experts/ExpertsList.tsx b/packages/client/src/features/experts/ExpertsList.tsx index ce74b6108..2eaabba58 100644 --- a/packages/client/src/features/experts/ExpertsList.tsx +++ b/packages/client/src/features/experts/ExpertsList.tsx @@ -7,7 +7,7 @@ import { Button } from '../../components/Button' import { LightBulbIcon } from '../../components/icons/LightBulbIcon' import { Loader } from '../../components/Loader' import NavigationBar from '../../components/NavigationBar/NavigationBar' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' import { Pagination } from '../../components/Pagination' import { ButtonRow, @@ -23,7 +23,7 @@ import { RightSideItem, SectionTitle, Title, -} from '../../components/Public/styles' +} from '../../components/Public/public-layout.styles' import { usePageMeta } from '../../hooks/usePageMeta' import { usePaginationParamsV2 } from '../../hooks/usePaginationState' import PublicLayout from '../../layouts/PublicLayout' diff --git a/packages/client/src/features/experts/details/Blog.tsx b/packages/client/src/features/experts/details/Blog.tsx index 51a09c186..cd1905861 100644 --- a/packages/client/src/features/experts/details/Blog.tsx +++ b/packages/client/src/features/experts/details/Blog.tsx @@ -5,7 +5,7 @@ import { Markdown, MarkdownStyle } from '../../../components/Markdown' import { IUser } from '../../../types/user' import { ExpertDetails } from '../types' import { ExpertColumnRight } from './ExpertColumnRight' -import { ExpertPageRow } from './styles' +import { ExpertPageRow } from './experts-details.styles' import { useMarkdownToc } from '../../markdown/Toc' const ExpertName = styled.span` diff --git a/packages/client/src/features/experts/details/ExpertAskQuestionModal.tsx b/packages/client/src/features/experts/details/ExpertAskQuestionModal.tsx index 68ce88799..65b40fe39 100644 --- a/packages/client/src/features/experts/details/ExpertAskQuestionModal.tsx +++ b/packages/client/src/features/experts/details/ExpertAskQuestionModal.tsx @@ -6,7 +6,7 @@ import { GoogleReCaptchaV3 } from '../../../components/ReCaptchaV3' import { theme } from '../../../styles/theme' import { getRuntimeEnv } from '@/utils/runtimeEnv' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer as ModalFooter } from '../../modal/styles' +import { ButtonRow, Footer as ModalFooter } from '../../modal/modal.styles' const Asking = styled.div` display: flex; diff --git a/packages/client/src/features/experts/details/ExpertColumnRight.tsx b/packages/client/src/features/experts/details/ExpertColumnRight.tsx index ab84c6c7d..bf22f74ff 100644 --- a/packages/client/src/features/experts/details/ExpertColumnRight.tsx +++ b/packages/client/src/features/experts/details/ExpertColumnRight.tsx @@ -9,7 +9,7 @@ import { useModal } from '../../modal/useModal' import { askQuestion, deleteExpertRequest } from '../api' import { ExpertDetails } from '../types' import { ExpertAskQuestionModal } from './ExpertAskQuestionModal' -import { StyledPageRightColumn } from './styles' +import { StyledPageRightColumn } from './experts-details.styles' import { Button } from '../../../components/Button' import { useConfirm } from '../../modal/useConfirm' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/experts/details/styles.ts b/packages/client/src/features/experts/details/experts-details.styles.ts similarity index 96% rename from packages/client/src/features/experts/details/styles.ts rename to packages/client/src/features/experts/details/experts-details.styles.ts index 6a6448a32..857521695 100644 --- a/packages/client/src/features/experts/details/styles.ts +++ b/packages/client/src/features/experts/details/experts-details.styles.ts @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { PageContainer, PageLeftColumn, PageRightColumn, pagePadding, PageContainerMargin } from '../../../components/Page/styles' +import { PageContainer, PageLeftColumn, PageRightColumn, pagePadding, PageContainerMargin } from '../../../components/Page/page.styles' import { breakPoints } from '../../../styles/theme' import { StyledToC } from '../../markdown/Toc' diff --git a/packages/client/src/features/experts/details/index.tsx b/packages/client/src/features/experts/details/index.tsx index 71fe509d8..2ba3e7740 100644 --- a/packages/client/src/features/experts/details/index.tsx +++ b/packages/client/src/features/experts/details/index.tsx @@ -4,7 +4,7 @@ import { Link, Navigate, Route, Routes, useParams } from 'react-router' import 'react-toastify/dist/ReactToastify.css' import styled from 'styled-components' import { Loader } from '../../../components/Loader' -import { PageContainerMargin } from '../../../components/Page/styles' +import { PageContainerMargin } from '../../../components/Page/page.styles' import { usePageMeta } from '../../../hooks/usePageMeta' import { colors } from '../../../styles/theme' import NavigationBar from '../../../components/NavigationBar/NavigationBar' @@ -15,7 +15,7 @@ import { expertDetailsRequest } from '../api' import { ExpertDetails } from '../types' import { ExpertAbout } from './About' import { ExpertBlog } from './Blog' -import { ExpertData, ExpertImage, ExpertRow, Filler, StyledTab, StyledTabList } from './styles' +import { ExpertData, ExpertImage, ExpertRow, Filler, StyledTab, StyledTabList } from './experts-details.styles' import { NavLink } from '../../../components/NavLink' const StyledNavigationBar = styled.div` diff --git a/packages/client/src/features/experts/styles.ts b/packages/client/src/features/experts/experts.styles.ts similarity index 100% rename from packages/client/src/features/experts/styles.ts rename to packages/client/src/features/experts/experts.styles.ts diff --git a/packages/client/src/features/experts/list/ExpertListItem.tsx b/packages/client/src/features/experts/list/ExpertListItem.tsx index 156a660a1..91924d423 100644 --- a/packages/client/src/features/experts/list/ExpertListItem.tsx +++ b/packages/client/src/features/experts/list/ExpertListItem.tsx @@ -2,9 +2,9 @@ import { format } from 'date-fns' import React from 'react' import { Link } from 'react-router' import { Button } from '../../../components/Button' -import { Content, ItemBody, Title } from '../../../components/Public/styles' +import { Content, ItemBody, Title } from '../../../components/Public/public-layout.styles' import { Expert } from '../types' -import { ExpertButtonRow, ExpertButtonRowWrap, Info, ItemImage, Name, StyledExpertListItem } from './styles' +import { ExpertButtonRow, ExpertButtonRowWrap, Info, ItemImage, Name, StyledExpertListItem } from './experts-list.styles' export const ExpertListItem = ({ expert, isAdmin = false }: { expert: Expert, isAdmin?: boolean }) => ( diff --git a/packages/client/src/features/experts/list/styles.tsx b/packages/client/src/features/experts/list/experts-list.styles.tsx similarity index 100% rename from packages/client/src/features/experts/list/styles.tsx rename to packages/client/src/features/experts/list/experts-list.styles.tsx diff --git a/packages/client/src/features/files/FileList.tsx b/packages/client/src/features/files/FileList.tsx index 769d60043..9098a5a8c 100644 --- a/packages/client/src/features/files/FileList.tsx +++ b/packages/client/src/features/files/FileList.tsx @@ -19,7 +19,7 @@ import { toastInfo } from '@/components/NotificationCenter/ToastHelper' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' import Table from '@/components/Table' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { Button, buttonVariants } from '@/components/ui/button' import { cleanObject, getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' import { ActionsMenuContent } from '../home/ActionMenuContent' diff --git a/packages/client/src/features/files/actionModals/useAddFolderModal.tsx b/packages/client/src/features/files/actionModals/useAddFolderModal.tsx index 407198f48..df703a1ef 100644 --- a/packages/client/src/features/files/actionModals/useAddFolderModal.tsx +++ b/packages/client/src/features/files/actionModals/useAddFolderModal.tsx @@ -11,7 +11,7 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' import type { HomeScope } from '../../home/types' diff --git a/packages/client/src/features/files/actionModals/useConfirmModal.tsx b/packages/client/src/features/files/actionModals/useConfirmModal.tsx index b7600fe6c..b63448efc 100644 --- a/packages/client/src/features/files/actionModals/useConfirmModal.tsx +++ b/packages/client/src/features/files/actionModals/useConfirmModal.tsx @@ -2,7 +2,7 @@ import React from 'react' import styled from 'styled-components' import { useModal } from '../../modal/useModal' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer } from '../../modal/styles' +import { ButtonRow, Footer } from '../../modal/modal.styles' import { Button } from '../../../components/Button' const StyledMessage = styled.div` diff --git a/packages/client/src/features/files/actionModals/useCopyFilesModal/index.tsx b/packages/client/src/features/files/actionModals/useCopyFilesModal/index.tsx index b24812376..fc801222e 100644 --- a/packages/client/src/features/files/actionModals/useCopyFilesModal/index.tsx +++ b/packages/client/src/features/files/actionModals/useCopyFilesModal/index.tsx @@ -15,7 +15,7 @@ import { copyFilesRequest, fetchSelectedFiles, validateCopyingFiles } from '../. import { IExistingFileSet, ISelectedFile, ISelectedFolder, SelectedNode } from '../../files.types' import { ScopeAndFolderSelection } from './ScopeAndFolderSelection' import styles from './CopyFilesModal.module.css' -import { Footer } from '../../../modal/styles' +import { Footer } from '../../../modal/modal.styles' import { toastError, toastSuccess } from '../../../../components/NotificationCenter/ToastHelper' interface FileListItemContentProps { diff --git a/packages/client/src/features/files/actionModals/useCopyFilesToSpaceModal.tsx b/packages/client/src/features/files/actionModals/useCopyFilesToSpaceModal.tsx index c4897c220..b88f9badd 100644 --- a/packages/client/src/features/files/actionModals/useCopyFilesToSpaceModal.tsx +++ b/packages/client/src/features/files/actionModals/useCopyFilesToSpaceModal.tsx @@ -8,7 +8,7 @@ import { BackendError } from '@/api/types' import { Button } from '@/components/Button' import { toastError } from '@/components/NotificationCenter/ToastHelper' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, StyledModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, StyledModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { findById } from '../file.utils' import { copyFilesRequest, fetchFolderChildren } from '../files.api' diff --git a/packages/client/src/features/files/actionModals/useDeleteFileModal.tsx b/packages/client/src/features/files/actionModals/useDeleteFileModal.tsx index 6ecbbb99e..dfa869736 100644 --- a/packages/client/src/features/files/actionModals/useDeleteFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useDeleteFileModal.tsx @@ -4,13 +4,13 @@ import React, { useEffect, useMemo, useState } from 'react' import styled from 'styled-components' import { Button } from '../../../components/Button' import { Loader } from '../../../components/Loader' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { ResourceTable, StyledName } from '../../../components/ResourceTable' import { FileIcon } from '../../../components/icons/FileIcon' import { FolderIcon } from '../../../components/icons/FolderIcon' import { itemsCountString } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ApiErrorResponse, DownloadListResponse } from '../../home/types' import { deleteFilesRequest, fetchFilesDownloadList } from '../files.api' diff --git a/packages/client/src/features/files/actionModals/useDnDMoveFileModal.tsx b/packages/client/src/features/files/actionModals/useDnDMoveFileModal.tsx index 4b3097b22..e441293b5 100644 --- a/packages/client/src/features/files/actionModals/useDnDMoveFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useDnDMoveFileModal.tsx @@ -5,13 +5,13 @@ import { Link } from 'react-router' import styled from 'styled-components' import { Button } from '../../../components/Button' import { Loader } from '../../../components/Loader' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { FileIcon } from '../../../components/icons/FileIcon' import { FolderIcon } from '../../../components/icons/FolderIcon' import { itemsCountString, pluralize } from '../../../utils/formatting' import { getBasePath } from '../../home/utils' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { moveFilesRequest } from '../files.api' import { IFile } from '../files.types' diff --git a/packages/client/src/features/files/actionModals/useDownloadFileModal.tsx b/packages/client/src/features/files/actionModals/useDownloadFileModal.tsx index a4509ed48..bf4c83ed3 100644 --- a/packages/client/src/features/files/actionModals/useDownloadFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useDownloadFileModal.tsx @@ -2,13 +2,13 @@ import { useQuery } from '@tanstack/react-query' import React, { useMemo, useState } from 'react' import styled from 'styled-components' import { Button } from '../../../components/Button' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { ResourceTable, StyledAction, StyledName } from '../../../components/ResourceTable' import { FileIcon } from '../../../components/icons/FileIcon' import { FolderIcon } from '../../../components/icons/FolderIcon' import { itemsCountString } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { DownloadListResponse, ServerScope } from '../../home/types' import { fetchFilesDownloadList } from '../files.api' diff --git a/packages/client/src/features/files/actionModals/useEditFileModal.tsx b/packages/client/src/features/files/actionModals/useEditFileModal.tsx index c2ddacd96..12c1f5d1b 100644 --- a/packages/client/src/features/files/actionModals/useEditFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useEditFileModal.tsx @@ -4,9 +4,9 @@ import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from '@tanstack/react-query' import { ErrorMessage } from '@hookform/error-message' import { yupResolver } from '@hookform/resolvers/yup' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText, InputTextArea } from '../../../components/InputText' -import { ButtonRow, Footer, StyledForm, StyledModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, StyledForm, StyledModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { editFileRequest } from '../files.api' import { IFile } from '../files.types' diff --git a/packages/client/src/features/files/actionModals/useEditFolderModal.tsx b/packages/client/src/features/files/actionModals/useEditFolderModal.tsx index d792afa49..c3cb72568 100644 --- a/packages/client/src/features/files/actionModals/useEditFolderModal.tsx +++ b/packages/client/src/features/files/actionModals/useEditFolderModal.tsx @@ -2,10 +2,10 @@ import { ErrorMessage } from '@hookform/error-message' import React, { useMemo } from 'react' import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from '@tanstack/react-query' -import { FieldGroup, InputError } from '../../../components/form/styles' +import { FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, StyledForm } from '../../modal/styles' +import { ButtonRow, Footer, StyledForm } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { editFolderRequest } from '../files.api' import { IFile } from '../files.types' diff --git a/packages/client/src/features/files/actionModals/useFileUploadModal/FileUploadModal.tsx b/packages/client/src/features/files/actionModals/useFileUploadModal/FileUploadModal.tsx index 676cb3f3b..00af3f463 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModal/FileUploadModal.tsx +++ b/packages/client/src/features/files/actionModals/useFileUploadModal/FileUploadModal.tsx @@ -3,11 +3,11 @@ import clsx from 'clsx' import { useDropzone } from 'react-dropzone' import { useNavigate } from 'react-router' import { Button } from '@/components/Button' -import { InputError } from '@/components/form/styles' +import { InputError } from '@/components/form/form.styles' import { itemsCountString } from '@/utils/formatting' import { HomeScope, MetaPath } from '../../../home/types' import { ModalHeaderTop, ModalNext } from '../../../modal/ModalNext' -import { ButtonRow, Footer, ModalScrollAutoHeight } from '../../../modal/styles' +import { ButtonRow, Footer, ModalScrollAutoHeight } from '../../../modal/modal.styles' import { MAX_UPLOADABLE_FILES } from './constants' import styles from './FileUploadModal.module.css' import { FileUploadStore } from './FileUploadStore' diff --git a/packages/client/src/features/files/actionModals/useFileUploadModal/UploadConflictModal.tsx b/packages/client/src/features/files/actionModals/useFileUploadModal/UploadConflictModal.tsx index dcf7846c9..3c9957ca1 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModal/UploadConflictModal.tsx +++ b/packages/client/src/features/files/actionModals/useFileUploadModal/UploadConflictModal.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Button } from '@/components/Button' import { ModalHeaderTop, ModalNext } from '@/features/modal/ModalNext' -import { ButtonRow, Footer } from '@/features/modal/styles' +import { ButtonRow, Footer } from '@/features/modal/modal.styles' interface UploadConflictModalProps { isShown: boolean diff --git a/packages/client/src/features/files/actionModals/useFileUploadModal/fileUpload.ts b/packages/client/src/features/files/actionModals/useFileUploadModal/fileUpload.ts index ed078a060..360c6da0b 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModal/fileUpload.ts +++ b/packages/client/src/features/files/actionModals/useFileUploadModal/fileUpload.ts @@ -6,7 +6,7 @@ * */ -import { getAuthenticityToken } from '@/utils/api' +import { getCsrfToken } from '@/utils/csrf' import type { HomeScope } from '../../../home/types' import { DEFAULT_CHUNK_CONCURRENCY, @@ -75,6 +75,8 @@ export class FileUploadController { throw new Error('Upload already in progress') } + const csrfToken = (await getCsrfToken()) ?? undefined + return new Promise((resolve, reject) => { this.resolveStart = resolve this.rejectStart = reject @@ -107,7 +109,7 @@ export class FileUploadController { baseDelayMs: this.config.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS, }, concurrency: this.config.concurrency ?? DEFAULT_CHUNK_CONCURRENCY, - csrfToken: getAuthenticityToken() ?? undefined, + csrfToken: csrfToken, } this.worker.postMessage({ diff --git a/packages/client/src/features/files/actionModals/useFileUploadModal/multiFileUploadCoordinator.ts b/packages/client/src/features/files/actionModals/useFileUploadModal/multiFileUploadCoordinator.ts index db7efa9e9..92175bcf7 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModal/multiFileUploadCoordinator.ts +++ b/packages/client/src/features/files/actionModals/useFileUploadModal/multiFileUploadCoordinator.ts @@ -9,7 +9,7 @@ import { Micro } from 'effect' import type { HomeScope } from '@/features/home/types' import { MAX_UPLOAD_WORKER_CONCURRENCY, type PauseReason } from './constants' -import { createFileUpload, FileUploadController, type FileUploadConfig, type UploadState } from './fileUpload' +import { createFileUpload, type FileUploadConfig, type FileUploadController, type UploadState } from './fileUpload' import { extractDirectory, RemoteFolderManager, RemoteRootFolderExistsError } from './remoteFolderManager' export interface UploadFileDescriptor { @@ -48,7 +48,6 @@ export class MultiFileUploadCoordinator { private disposed = false private readonly maxConcurrency: number private readonly isSingleFileUpload: boolean - private uploadEffect: Micro.Micro | null = null private uploadAbortController: AbortController | null = null constructor(private readonly config: MultiFileUploadConfig) { @@ -130,8 +129,6 @@ export class MultiFileUploadCoordinator { ) }) - this.uploadEffect = uploadProgram - let caughtError: unknown = null try { @@ -140,7 +137,6 @@ export class MultiFileUploadCoordinator { caughtError = error console.error('Coordinator encountered an error:', error) } finally { - this.uploadEffect = null this.uploadAbortController = null } diff --git a/packages/client/src/features/files/actionModals/useFileUploadModal/worker/api.ts b/packages/client/src/features/files/actionModals/useFileUploadModal/worker/api.ts index 9692305e9..c7655430f 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModal/worker/api.ts +++ b/packages/client/src/features/files/actionModals/useFileUploadModal/worker/api.ts @@ -2,20 +2,16 @@ * API request functions for file upload operations */ +import { buildCsrfHeaders, fetchCsrfToken } from '@/utils/csrf' import { ChunkUploadError, CreateFileError } from './errors' import type { UploadUrlResponse, WorkerSession } from './types' import { cleanObject, toError } from './utils' function buildRequestHeaders(csrfToken?: string): Record { - const headers: Record = { + return { 'Content-Type': 'application/json', + ...buildCsrfHeaders(csrfToken), } - - if (csrfToken) { - headers['X-CSRF-Token'] = csrfToken - } - - return headers } /** @@ -34,7 +30,7 @@ export async function createFileRequest(session: WorkerSession): Promise { session.currentControllers.add(controller) try { - const response = await fetch('/api/create_file', { + const response = await fetch('/api/v2/files', { method: 'POST', headers: buildRequestHeaders(session.csrfToken), body: JSON.stringify(data), @@ -134,10 +130,14 @@ export async function requestUploadUrl( /** * Close a file after all chunks are uploaded */ -export async function closeFileRequest(uid: string, csrfToken?: string): Promise { +export async function closeFileRequest(uid: string, _csrfToken?: string): Promise { + // Always fetch a fresh CSRF token before closing — the original token may + // have been null at the start of the upload, or may have been rotated + // during a long-running upload. + const freshToken = (await fetchCsrfToken()) ?? _csrfToken ?? undefined const response = await fetch(`/api/v2/files/${uid}/close`, { method: 'PATCH', - headers: buildRequestHeaders(csrfToken), + headers: buildRequestHeaders(freshToken), }) if (!response.ok) { diff --git a/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/styles.ts b/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/file-upload-legacy.styles.ts similarity index 100% rename from packages/client/src/features/files/actionModals/useFileUploadModalLegacy/styles.ts rename to packages/client/src/features/files/actionModals/useFileUploadModalLegacy/file-upload-legacy.styles.ts diff --git a/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/index.tsx b/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/index.tsx index da55970f3..c1c57bbe3 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/index.tsx +++ b/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/index.tsx @@ -1,5 +1,5 @@ import { Button } from '@/components/Button' -import { InputError } from '@/components/form/styles' +import { InputError } from '@/components/form/form.styles' import { Done, Failed, Running } from '@/components/icons/StateIcons' import { TrashIcon } from '@/components/icons/TrashIcon' import { UploadIcon } from '@/components/icons/UploadIcon' @@ -13,7 +13,7 @@ import { useDropzone } from 'react-dropzone' import { useImmer } from 'use-immer' import { HomeScope } from '../../../home/types' import { ModalHeaderTop, ModalNext } from '../../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../../modal/modal.styles' import { useConditionalModal } from '../../../modal/useModal' import { FILE_STATUS, FilesMeta, FileStatusTypes, IUploadInfo, MAX_UPLOADABLE_FILES } from './constants' import { multiFileUpload } from './multiFileUpload' @@ -31,7 +31,7 @@ import { StatusWrapper, UploadFilesContainer, UploadFilesHeader, -} from './styles' +} from './file-upload-legacy.styles' interface FileUploadTableProps { filesMeta: FilesMeta[] diff --git a/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/multiFileUpload.ts b/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/multiFileUpload.ts index 7a9297379..cde532084 100644 --- a/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/multiFileUpload.ts +++ b/packages/client/src/features/files/actionModals/useFileUploadModalLegacy/multiFileUpload.ts @@ -1,7 +1,7 @@ +import sparkMD5 from 'spark-md5' import { closeFile, createFile, getUploadURL, uploadChunk } from '@/api/files' import { HTTP_STATUS } from '@/constants' -import sparkMD5 from 'spark-md5' -import { CHUNK_SIZE, FILE_STATUS, FilesMeta, IUploadFile, IUploadInfo } from './constants' +import { CHUNK_SIZE, FILE_STATUS, type FilesMeta, type IUploadFile, type IUploadInfo } from './constants' const filterFiles = (filesBlob: any[], filesMeta: any[]) => filesBlob.filter(b => { @@ -14,7 +14,7 @@ const filterFiles = (filesBlob: any[], filesMeta: any[]) => }) const throwIfError = (status: number, payload?: any) => { - if (status !== HTTP_STATUS.OK) { + if (![HTTP_STATUS.OK, HTTP_STATUS.CREATED].includes(status)) { const errorMessage = payload?.error?.message ?? 'Unknown upload failure' throw new Error(errorMessage) } @@ -29,7 +29,14 @@ interface IMultiFileUpload { folderId?: string } -export const multiFileUpload = async ({ filesBlob, filesMeta, updateFileStatus, spaceId, scope, folderId }: IMultiFileUpload) => { +export const multiFileUpload = async ({ + filesBlob, + filesMeta, + updateFileStatus, + spaceId, + scope, + folderId, +}: IMultiFileUpload) => { const scopeToUpload = scope || `space-${spaceId}` const filteredFiles: IUploadFile[] = filterFiles(filesBlob, filesMeta) diff --git a/packages/client/src/features/files/actionModals/useLockUnlockFileModal.tsx b/packages/client/src/features/files/actionModals/useLockUnlockFileModal.tsx index f0779e6a6..a145f1a47 100644 --- a/packages/client/src/features/files/actionModals/useLockUnlockFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useLockUnlockFileModal.tsx @@ -5,11 +5,11 @@ import styled from 'styled-components' import { FileIcon } from '../../../components/icons/FileIcon' import { FolderIcon } from '../../../components/icons/FolderIcon' import { Loader } from '../../../components/Loader' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { ResourceTable, StyledName } from '../../../components/ResourceTable' import { itemsCountString, pluralize } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { Footer, ModalScroll } from '../../modal/styles' +import { Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ApiErrorResponse, DownloadListResponse, ServerScope } from '../../home/types' import { fetchFilesListLockingRequest, LockUnlockActionType, lockUnlockFilesRequest } from '../files.api' diff --git a/packages/client/src/features/files/actionModals/useOpenFileModal.tsx b/packages/client/src/features/files/actionModals/useOpenFileModal.tsx index 100114ed0..e8cf49cb3 100644 --- a/packages/client/src/features/files/actionModals/useOpenFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useOpenFileModal.tsx @@ -4,12 +4,12 @@ import { useState } from 'react' import styled from 'styled-components' import { Button } from '@/components/Button' import { FileIcon } from '@/components/icons/FileIcon' -import { VerticalCenter } from '@/components/Page/styles' +import { VerticalCenter } from '@/components/Page/page.styles' import { ResourceTable, StyledAction, StyledName } from '@/components/ResourceTable' import { pluralize, sanitizeFileName } from '@/utils/formatting' import type { DownloadListResponse } from '../../home/types' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { fetchFilesDownloadList } from '../files.api' import type { IFile } from '../files.types' diff --git a/packages/client/src/features/files/actionModals/useSelectFileModal.tsx b/packages/client/src/features/files/actionModals/useSelectFileModal.tsx index ab762c4c0..0ce1cb766 100644 --- a/packages/client/src/features/files/actionModals/useSelectFileModal.tsx +++ b/packages/client/src/features/files/actionModals/useSelectFileModal.tsx @@ -38,13 +38,13 @@ import { SyledFilterWrapper, SyledUid, TabContent, -} from '../../actionModals/styles' +} from '../../actionModals/action-modals.styles' import { fetchFilteredFiles } from '../../apps/apps.api' import { useAuthUser } from '../../auth/useAuthUser' import { IAccessibleFile } from '../../databases/databases.api' import { DialogType } from '../../home/types' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer } from '../../modal/styles' +import { ButtonRow, Footer } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { noAccessText } from '../file.utils' import { useFetchFilesByUIDQuery } from '../query/useFetchFilesByUIDQuery' diff --git a/packages/client/src/features/files/actionModals/useSelectFolderModal.tsx b/packages/client/src/features/files/actionModals/useSelectFolderModal.tsx index a800675b4..248683184 100644 --- a/packages/client/src/features/files/actionModals/useSelectFolderModal.tsx +++ b/packages/client/src/features/files/actionModals/useSelectFolderModal.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components' import { useImmer } from 'use-immer' import { Button } from '../../../components/Button' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { ServerScope } from '../../home/types' import { fetchFolderChildren } from '../files.api' diff --git a/packages/client/src/features/files/file.utils.ts b/packages/client/src/features/files/file.utils.ts index 38991e9dc..f7da195c1 100644 --- a/packages/client/src/features/files/file.utils.ts +++ b/packages/client/src/features/files/file.utils.ts @@ -2,8 +2,6 @@ import * as React from 'react' import { DataNode } from 'rc-tree/lib/interface' import type { OriginObject } from './files.types' -const assertNever = (_value: never): string | null => null - export function findById(tree: DataNode[], nodeId: React.Key): DataNode | null { for (let i = 0; i < tree.length; i++) { const node = tree[i] @@ -74,7 +72,7 @@ export const getOriginHref = (originObject?: OriginObject): string | null => { switch (originObject.originType) { case 'Job': - return `/jobs/${originObject.originUid}` + return `/home/executions/${originObject.originUid}` case 'Comparison': return `/home/comparisons/${originObject.originUid}` case 'UserFile': @@ -83,8 +81,8 @@ export const getOriginHref = (originObject?: OriginObject): string | null => { case 'User': case 'Folder': return null - default: - return assertNever(originObject.originType) + default: { + return originObject.originType + } } } - diff --git a/packages/client/src/features/files/files.api.ts b/packages/client/src/features/files/files.api.ts index 87635c695..e294d2478 100644 --- a/packages/client/src/features/files/files.api.ts +++ b/packages/client/src/features/files/files.api.ts @@ -1,8 +1,8 @@ import axios from 'axios' +import type { EntityUidResponse } from '@/api/types' import { cleanObject } from '@/utils/object' import type { DownloadListResponse, HomeScope, IFilter, IMeta, ServerScope } from '../home/types' -import type { Params } from '../home/utils' -import { formatScopeQ, prepareListFetch } from '../home/utils' +import { formatScopeQ, type Params, prepareListFetch } from '../home/utils' import type { FileType, IExistingFileSet, IFile, IFolder, SelectedNode } from './files.types' interface RailsFileLinks { @@ -106,7 +106,8 @@ function mapRailsFile(raw: RailsFile): IFile { show_license_pending: raw.show_license_pending, requestApprovalLicenseLink: typeof raw.links?.request_approval_license === 'string' ? raw.links.request_approval_license : undefined, - acceptLicenseActionLink: typeof raw.links?.accept_license_action === 'string' ? raw.links.accept_license_action : undefined, + acceptLicenseActionLink: + typeof raw.links?.accept_license_action === 'string' ? raw.links.accept_license_action : undefined, downloadLink: raw.links?.download, } } @@ -289,8 +290,8 @@ export const moveFilesRequest = async ( return axios.post(url, body).then(res => res.data as MoveFilesResponse) } -export async function createFile(name: string, scope: string, folder_id: string | null): Promise { - return axios.post('/api/create_file', { name, scope, folder_id }).then(r => r.data) +export async function createFile(name: string, scope: string, folder_id: string | null): Promise { + return axios.post('/api/v2/files', { name, scope, folderId: folder_id }).then(r => r.data) } export async function fetchSelectedFiles(ids: number[]): Promise { diff --git a/packages/client/src/features/files/files.types.ts b/packages/client/src/features/files/files.types.ts index e0aa0cf39..84843a789 100644 --- a/packages/client/src/features/files/files.types.ts +++ b/packages/client/src/features/files/files.types.ts @@ -2,8 +2,8 @@ import type { TreeProps } from 'rc-tree' import type { BasicDataNode } from 'rc-tree/es/interface' import type { DataNode } from 'rc-tree/lib/interface' import type { FileOrg, FileUser } from '../apps/apps.types' -import type { ServerScope } from '../home/types' import type { FileLicense } from '../assets/assets.types' +import type { ServerScope } from '../home/types' export interface NodePermissions { canDelete: boolean diff --git a/packages/client/src/features/files/show/FileShow.tsx b/packages/client/src/features/files/show/FileShow.tsx index f441c02d6..584933e64 100644 --- a/packages/client/src/features/files/show/FileShow.tsx +++ b/packages/client/src/features/files/show/FileShow.tsx @@ -8,15 +8,15 @@ import { FileIcon } from '@/components/icons/FileIcon' import { LockIcon } from '@/components/icons/LockIcon' import { ActionsMenu } from '@/components/Menu' import { toastInfo } from '@/components/NotificationCenter/ToastHelper' -import { Filler } from '@/components/Page/styles' +import { Filler } from '@/components/Page/page.styles' import { type ITab, TabsSwitch } from '@/components/TabsSwitch' import { StyledPropertyItem, StyledPropertyKey, StyledTagItem, StyledTags } from '@/components/Tags' import { theme } from '@/styles/theme' import { sanitizeFileName } from '@/utils/formatting' import { getBackPathNext } from '@/utils/getBackPath' +import { useAuthUser } from '../../auth/useAuthUser' import { ActionsMenuContent } from '../../home/ActionMenuContent' import { ActionModalsRenderer } from '../../home/ActionModalsRenderer' -import { useAuthUser } from '../../auth/useAuthUser' import { defaultHomeContext, type HomeScopeContextValue } from '../../home/HomeScopeContext' import { StyledBackLink } from '../../home/home.styles' import { @@ -39,12 +39,12 @@ import { License } from '../../licenses/License' import type { License as ILicense } from '../../licenses/types' import type { ISpace } from '../../spaces/spaces.types' import { FileBreadcrumb } from '../FileBreadcrumb' -import { fetchFile } from '../files.api' import { getOriginHref } from '../file.utils' +import { fetchFile } from '../files.api' import type { IFile } from '../files.types' import { normalizePermissions } from '../normalizePermissions' import { useFilesSelectActions } from '../useFilesSelectActions' -import { FileDescription, HeaderActions } from './styles' +import { FileDescription, HeaderActions } from './files-show.styles' const FileActionsDropdown = ({ homeScope, @@ -76,6 +76,10 @@ const FileActionsDropdown = ({ ) } +const getOriginLinkText = (file: IFile): string | undefined => { + return typeof file.origin === 'object' && file.origin ? file.origin.text : undefined +} + export const FileShow = ({ fileId, space, @@ -130,7 +134,7 @@ export const FileShow = ({ const filePermissions = normalizePermissions(file, user, space) const showLicensePending = file.fileLicense?.acceptanceStatus === 'pending' const originHref = getOriginHref(file.originObject) - const originText = typeof file.origin === 'object' && file.origin ? file.origin.text : undefined + const originLinkText = getOriginLinkText(file) return ( <> @@ -227,9 +231,9 @@ export const FileShow = ({ Origin - {originHref && originText != null ? ( + {originHref ? ( - {originText || originHref} + {originLinkText || originHref} ) : typeof file.origin === 'object' ? ( file.origin?.text diff --git a/packages/client/src/features/files/show/styles.ts b/packages/client/src/features/files/show/files-show.styles.ts similarity index 100% rename from packages/client/src/features/files/show/styles.ts rename to packages/client/src/features/files/show/files-show.styles.ts diff --git a/packages/client/src/features/home/home.styles.ts b/packages/client/src/features/home/home.styles.ts index 41dc1284a..cc2eadc24 100644 --- a/packages/client/src/features/home/home.styles.ts +++ b/packages/client/src/features/home/home.styles.ts @@ -3,7 +3,7 @@ import styled, { css } from 'styled-components' import { Svg } from '../../components/icons/Svg' import { NavLink } from '../../components/NavLink' import { BackLink } from '../../components/Page/PageBackLink' -import { compactScrollBarV2 } from '../../components/Page/styles' +import { compactScrollBarV2 } from '../../components/Page/page.styles' export const StyledBackLink = styled(BackLink)` margin: 16px 16px; diff --git a/packages/client/src/features/lexi/styles.ts b/packages/client/src/features/lexi/lexi.styles.ts similarity index 100% rename from packages/client/src/features/lexi/styles.ts rename to packages/client/src/features/lexi/lexi.styles.ts diff --git a/packages/client/src/features/licenses/useAcceptLicenseModal.tsx b/packages/client/src/features/licenses/useAcceptLicenseModal.tsx index 1ebafa5d5..577dc8aac 100644 --- a/packages/client/src/features/licenses/useAcceptLicenseModal.tsx +++ b/packages/client/src/features/licenses/useAcceptLicenseModal.tsx @@ -1,7 +1,7 @@ import { useMutation } from '@tanstack/react-query' import styled from 'styled-components' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer } from '../modal/styles' +import { ButtonRow, Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import type { APIResource } from '../home/types' import { acceptLicenseRequest } from './api' diff --git a/packages/client/src/features/licenses/useAcceptLicensesModal.tsx b/packages/client/src/features/licenses/useAcceptLicensesModal.tsx index 8168fd991..9059938e0 100644 --- a/packages/client/src/features/licenses/useAcceptLicensesModal.tsx +++ b/packages/client/src/features/licenses/useAcceptLicensesModal.tsx @@ -5,7 +5,7 @@ import { Checkbox } from '../../components/Checkbox' import { SideTabs } from '../../components/SideTab/SideTabs' import { colors } from '../../styles/theme' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer } from '../modal/styles' +import { ButtonRow, Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { acceptLicensesRequest } from './api' import { License } from './types' diff --git a/packages/client/src/features/licenses/useAttachLicensesModal.tsx b/packages/client/src/features/licenses/useAttachLicensesModal.tsx index ea62059d4..0b3f66a9b 100644 --- a/packages/client/src/features/licenses/useAttachLicensesModal.tsx +++ b/packages/client/src/features/licenses/useAttachLicensesModal.tsx @@ -9,7 +9,7 @@ import { attachLicenseRequest } from './api' import type { License } from './types' import { useLicensesListQuery } from './queries' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { Button } from '@/components/Button' import { Empty } from '../home/home.styles' import type { IFile } from '../files/files.types' diff --git a/packages/client/src/features/licenses/useDetachLicenseModal.tsx b/packages/client/src/features/licenses/useDetachLicenseModal.tsx index 7a3fdb296..661dbc146 100644 --- a/packages/client/src/features/licenses/useDetachLicenseModal.tsx +++ b/packages/client/src/features/licenses/useDetachLicenseModal.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/Button' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import type { APIResource } from '../home/types' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, StyledModalContent } from '../modal/styles' +import { ButtonRow, Footer, StyledModalContent } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { detachLicenseRequest } from './api' diff --git a/packages/client/src/features/modal/ModalNext.tsx b/packages/client/src/features/modal/ModalNext.tsx index ebd39a7ab..95d8453c7 100644 --- a/packages/client/src/features/modal/ModalNext.tsx +++ b/packages/client/src/features/modal/ModalNext.tsx @@ -4,7 +4,7 @@ import { CSSTransition } from 'react-transition-group' import styled, { css } from 'styled-components' import { PlusIcon } from '../../components/icons/PlusIcon' import { useKeyPress } from '../../hooks/useKeyPress' -import { CloseButton, HeaderText, HeaderTop } from './styles' +import { CloseButton, HeaderText, HeaderTop } from './modal.styles' /** * Full-screen layer inside the modal where portaled popups (Combobox, etc.) can mount above the panel diff --git a/packages/client/src/features/modal/SavingModal.tsx b/packages/client/src/features/modal/SavingModal.tsx index fe90f8f0e..1aabc2468 100644 --- a/packages/client/src/features/modal/SavingModal.tsx +++ b/packages/client/src/features/modal/SavingModal.tsx @@ -1,6 +1,6 @@ import React from 'react' import { ModalHeaderTop, ModalNext } from './ModalNext' -import { Content } from './styles' +import { Content } from './modal.styles' // TODO how about a different name for this? like Processing modal, because it doesn't have to be just saving export const SavingModal = ({ diff --git a/packages/client/src/features/modal/styles.ts b/packages/client/src/features/modal/modal.styles.ts similarity index 85% rename from packages/client/src/features/modal/styles.ts rename to packages/client/src/features/modal/modal.styles.ts index fed2d05e0..592e3e1e8 100644 --- a/packages/client/src/features/modal/styles.ts +++ b/packages/client/src/features/modal/modal.styles.ts @@ -1,7 +1,7 @@ import styled from 'styled-components' -import { TransparentButton } from '../../components/Button' -import { compactScrollBarV2 } from '../../components/Page/styles' -import { Svg } from '../../components/icons/Svg' +import { TransparentButton } from '@/components/Button' +import { Svg } from '@/components/icons/Svg' +import { compactScrollBarV2 } from '@/components/Page/page.styles' export const HeaderTop = styled.div` border-radius: 8px 8px 0 0; @@ -109,17 +109,3 @@ export const ModalLoaderWrapper = styled.div` align-items: center; min-height: 200px; ` - -export const ModalPageRow = styled.div` - display: grid; - grid-template-columns: auto auto; -` - -export const ModalPageCol = styled.div` - align-self: stretch; - min-width: 350px; - width: 50vw; - &:last-child { - border: 0; - } -` diff --git a/packages/client/src/features/modal/useConfirm/Dialog.tsx b/packages/client/src/features/modal/useConfirm/Dialog.tsx index 067162e22..21508c0d9 100644 --- a/packages/client/src/features/modal/useConfirm/Dialog.tsx +++ b/packages/client/src/features/modal/useConfirm/Dialog.tsx @@ -1,7 +1,7 @@ -import React, { ReactNode } from 'react' +import type { ReactNode } from 'react' import styled from 'styled-components' -import { ButtonRow } from '../styles' -import { Button } from '../../../components/Button' +import { Button } from '@/components/Button' +import { ButtonRow } from '../modal.styles' export const StyledConfirmDialog = styled.div` padding: 12px 12px 12px 24px; @@ -29,7 +29,9 @@ export const Dialog = (props: IDialogProps) => { {body} - + ) diff --git a/packages/client/src/features/news/ListAdminNews.tsx b/packages/client/src/features/news/ListAdminNews.tsx index ad2e78db9..06a5799f6 100644 --- a/packages/client/src/features/news/ListAdminNews.tsx +++ b/packages/client/src/features/news/ListAdminNews.tsx @@ -10,10 +10,10 @@ import { NewspaperIcon } from '@/components/icons/NewspaperIcon' import { Svg } from '@/components/icons/Svg' import { Loader } from '@/components/Loader' import { BackLink } from '@/components/Page/PageBackLink' -import { PageContainerMargin, PageTitle } from '@/components/Page/styles' +import { PageContainerMargin, PageTitle } from '@/components/Page/page.styles' import { useAuthUser } from '@/features/auth/useAuthUser' import ExternalLink from '../../components/Controls/ExternalLink' -import { ButtonRow } from '../modal/styles' +import { ButtonRow } from '../modal/modal.styles' import { NewsItem } from './types' import { useNewsAdminAllRequest } from './useNewsListQuery' diff --git a/packages/client/src/features/news/NewsPage.tsx b/packages/client/src/features/news/NewsPage.tsx index 54afc01b2..fc4555c5f 100644 --- a/packages/client/src/features/news/NewsPage.tsx +++ b/packages/client/src/features/news/NewsPage.tsx @@ -7,7 +7,7 @@ import ExternalLink from '../../components/Controls/ExternalLink' import { InlineError } from '../../components/Error' import { Loader } from '../../components/Loader' import NavigationBar from '../../components/NavigationBar/NavigationBar' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' import { hidePagination, Pagination } from '../../components/Pagination' import { ButtonRow, @@ -23,13 +23,13 @@ import { RightSideItem, SectionTitle, Title, -} from '../../components/Public/styles' +} from '../../components/Public/public-layout.styles' import { usePageMeta } from '../../hooks/usePageMeta' import { usePaginationParamsV2 } from '../../hooks/usePaginationState' import PublicLayout from '../../layouts/PublicLayout' import { useAuthUser } from '../auth/useAuthUser' import { newsYearsListRequest } from './api' -import { ItemBody, ItemDate, NewsListItem } from './styles' +import { ItemBody, ItemDate, NewsListItem } from './news.styles' import { useNewsListQuery } from './useNewsListQuery' const NewsPage = () => { diff --git a/packages/client/src/features/news/form/CreateNewsItemPage.tsx b/packages/client/src/features/news/form/CreateNewsItemPage.tsx index d30c16171..0e2763dff 100644 --- a/packages/client/src/features/news/form/CreateNewsItemPage.tsx +++ b/packages/client/src/features/news/form/CreateNewsItemPage.tsx @@ -2,12 +2,12 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useNavigate } from 'react-router' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { BackLink } from '@/components/Page/PageBackLink' -import { PageTitle } from '@/components/Page/styles' +import { PageTitle } from '@/components/Page/page.styles' import { AdminWrapper } from '../../admin/AdminWrapper' import { createNewsItemRequest } from '../api' import { NewsItemPayload } from '../types' import { NewsItemForm } from './NewsItemForm' -import { FormPageContainer } from './styles' +import { FormPageContainer } from './news-form.styles' const CreateNewsItemPage = () => { const navigate = useNavigate() diff --git a/packages/client/src/features/news/form/EditNewsItemPage.tsx b/packages/client/src/features/news/form/EditNewsItemPage.tsx index 8a915c2d0..42f5ebc15 100644 --- a/packages/client/src/features/news/form/EditNewsItemPage.tsx +++ b/packages/client/src/features/news/form/EditNewsItemPage.tsx @@ -3,12 +3,12 @@ import { useNavigate, useParams } from 'react-router' import { Loader } from '@/components/Loader' import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastHelper' import { BackLinkMargin } from '@/components/Page/PageBackLink' -import { PageTitle } from '@/components/Page/styles' +import { PageTitle } from '@/components/Page/page.styles' import { AdminWrapper } from '../../admin/AdminWrapper' import { deleteNewsItemRequest, editNewsItemRequest, newsItemRequest } from '../api' import { NewsItem, NewsItemPayload } from '../types' import { NewsItemForm } from './NewsItemForm' -import { FormPageContainer } from './styles' +import { FormPageContainer } from './news-form.styles' const useNewsItemRequest = (id: string) => { return useQuery({ diff --git a/packages/client/src/features/news/form/NewsItemForm.tsx b/packages/client/src/features/news/form/NewsItemForm.tsx index 349a58cee..0502251c2 100644 --- a/packages/client/src/features/news/form/NewsItemForm.tsx +++ b/packages/client/src/features/news/form/NewsItemForm.tsx @@ -7,9 +7,9 @@ import * as Yup from 'yup' import { Button } from '../../../components/Button' import { Checkbox } from '../../../components/Checkbox' import { InputDate } from '../../../components/form/InputDate' -import { CheckboxLabel, FieldGroup, InputError } from '../../../components/form/styles' +import { CheckboxLabel, FieldGroup, InputError } from '../../../components/form/form.styles' import { InputText, InputTextArea } from '../../../components/InputText' -import { ButtonRow } from '../../modal/styles' +import { ButtonRow } from '../../modal/modal.styles' import { NewsItemPayload } from '../types' const StyledForm = styled.form` diff --git a/packages/client/src/features/news/form/styles.ts b/packages/client/src/features/news/form/news-form.styles.ts similarity index 94% rename from packages/client/src/features/news/form/styles.ts rename to packages/client/src/features/news/form/news-form.styles.ts index 1355e5f42..b837c09a2 100644 --- a/packages/client/src/features/news/form/styles.ts +++ b/packages/client/src/features/news/form/news-form.styles.ts @@ -1,6 +1,6 @@ import styled from 'styled-components' import { StyledBackLink } from '../../../components/Page/PageBackLink' -import { PageContainerMargin, PageTitle } from '../../../components/Page/styles' +import { PageContainerMargin, PageTitle } from '../../../components/Page/page.styles' export const FormPageContainer = styled(PageContainerMargin)` --container-width: 600px; diff --git a/packages/client/src/features/news/styles.ts b/packages/client/src/features/news/news.styles.ts similarity index 100% rename from packages/client/src/features/news/styles.ts rename to packages/client/src/features/news/news.styles.ts diff --git a/packages/client/src/features/overview/ChallengesBanner.tsx b/packages/client/src/features/overview/ChallengesBanner.tsx index 53e7244d5..a34fe217b 100644 --- a/packages/client/src/features/overview/ChallengesBanner.tsx +++ b/packages/client/src/features/overview/ChallengesBanner.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components' import challengesBannerLeft from '../../assets/ChallengesBannerBackground-Left.png' import challengesBannerRight from '../../assets/ChallengesBannerBackground-Right.png' import { colors } from '../../styles/theme' -import { ViewAllButton } from './styles' +import { ViewAllButton } from './overview.styles' const StyledChallengesBanner = styled.div` display: flex; diff --git a/packages/client/src/features/overview/ChallengesOverviewList.tsx b/packages/client/src/features/overview/ChallengesOverviewList.tsx index f49021c82..d93369cf7 100644 --- a/packages/client/src/features/overview/ChallengesOverviewList.tsx +++ b/packages/client/src/features/overview/ChallengesOverviewList.tsx @@ -2,11 +2,11 @@ import React from 'react' import { Link } from 'react-router' import styled from 'styled-components' import { Loader } from '../../components/Loader' -import { SectionTitle } from '../../components/Public/styles' +import { SectionTitle } from '../../components/Public/public-layout.styles' import { ChallengeListItem } from '../challenges/list/ChallengeListItem' import { useChallengesListQuery } from '../challenges/list/useChallengesListQuery' import { getTimeStatusColor } from '../challenges/util' -import { ViewAllButton } from './styles' +import { ViewAllButton } from './overview.styles' const StyledChallengesOverview = styled.div` margin-bottom: 64px; diff --git a/packages/client/src/features/overview/OverviewAuthed.tsx b/packages/client/src/features/overview/OverviewAuthed.tsx index e79f040d3..f5458e322 100644 --- a/packages/client/src/features/overview/OverviewAuthed.tsx +++ b/packages/client/src/features/overview/OverviewAuthed.tsx @@ -4,8 +4,8 @@ import { useQuery } from '@tanstack/react-query' import { Link } from 'react-router' import styled from 'styled-components' import { Loader } from '../../components/Loader' -import { PageContainerMargin } from '../../components/Page/styles' -import { OverviewCenterSection, PageRow, RightSide, RightSideItem, SectionTitle } from '../../components/Public/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' +import { OverviewCenterSection, PageRow, RightSide, RightSideItem, SectionTitle } from '../../components/Public/public-layout.styles' import { usePageMeta } from '../../hooks/usePageMeta' import { IUser } from '../../types/user' import NavigationBar from '../../components/NavigationBar/NavigationBar' @@ -19,7 +19,7 @@ import { ChallengesBanner } from './ChallengesBanner' import ChallengesOverviewList from './ChallengesOverviewList' import { OverviewNewsList } from './OverviewNewsList' import { ParticipantOrgsList } from './ParticipantsOrgsList' -import { CommunityParticipants, ExpertSection, Hr, InfoRow, PageOverviewMainBody } from './styles' +import { CommunityParticipants, ExpertSection, Hr, InfoRow, PageOverviewMainBody } from './overview.styles' import { AppTypeIconBlue } from '../../components/icons/AppTypeIconBlue' import { AppTypeIconYellow } from '../../components/icons/AppTypeIconYellow' import { Button } from '../../components/Button' diff --git a/packages/client/src/features/overview/OverviewExpertsListCondensed.tsx b/packages/client/src/features/overview/OverviewExpertsListCondensed.tsx index 24ff3b751..c0097536b 100644 --- a/packages/client/src/features/overview/OverviewExpertsListCondensed.tsx +++ b/packages/client/src/features/overview/OverviewExpertsListCondensed.tsx @@ -10,7 +10,7 @@ import { Name, StyledCondensedList, StyledPreview, -} from '../experts/ExpertsCondensedList/styles' +} from '../experts/ExpertsCondensedList/experts-condensed-list.styles' import { useExpertsListCondensedQuery } from '../experts/useExpertsListQuery' export const OverviewExpertsCondensedList = ({ pick }: { pick?: number }) => { diff --git a/packages/client/src/features/overview/OverviewPublic.tsx b/packages/client/src/features/overview/OverviewPublic.tsx index d777ed8f6..ac7f74a4e 100644 --- a/packages/client/src/features/overview/OverviewPublic.tsx +++ b/packages/client/src/features/overview/OverviewPublic.tsx @@ -1,8 +1,8 @@ import React from 'react' import styled from 'styled-components' import { Button } from '@/components/Button' -import { PageContainerMargin } from '@/components/Page/styles' -import { OverviewCenterSection, PageRow } from '@/components/Public/styles' +import { PageContainerMargin } from '@/components/Page/page.styles' +import { OverviewCenterSection, PageRow } from '@/components/Public/public-layout.styles' import { usePageMeta } from '@/hooks/usePageMeta' import NavigationBar, { NavigationBarBanner, @@ -10,7 +10,7 @@ import NavigationBar, { } from '../../components/NavigationBar/NavigationBar' import MailButton from '../../components/NavigationBar/SocialMediaButtons' import PublicLayout from '../../layouts/PublicLayout' -import { PageOverviewMainBody } from './styles' +import { PageOverviewMainBody } from './overview.styles' const HeroContent = styled.div` text-align: center; diff --git a/packages/client/src/features/overview/ParticipantsOrgsList.tsx b/packages/client/src/features/overview/ParticipantsOrgsList.tsx index d9f6392be..865711669 100644 --- a/packages/client/src/features/overview/ParticipantsOrgsList.tsx +++ b/packages/client/src/features/overview/ParticipantsOrgsList.tsx @@ -1,7 +1,7 @@ import React from 'react' import styled from 'styled-components' import { Loader } from '../../components/Loader' -import { compactScrollBar } from '../../components/Page/styles' +import { compactScrollBar } from '../../components/Page/page.styles' import { useParticipantsQuery } from './useParticipantsQuery' const StyledParticipantsList = styled.ul` diff --git a/packages/client/src/features/overview/styles.ts b/packages/client/src/features/overview/overview.styles.ts similarity index 97% rename from packages/client/src/features/overview/styles.ts rename to packages/client/src/features/overview/overview.styles.ts index e11254f9c..fd44e48af 100644 --- a/packages/client/src/features/overview/styles.ts +++ b/packages/client/src/features/overview/overview.styles.ts @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { PageMainBody, SectionTitle } from '../../components/Public/styles' +import { PageMainBody, SectionTitle } from '../../components/Public/public-layout.styles' export const InfoRow = styled.div` display: flex; diff --git a/packages/client/src/features/publishing/PublishingPage.tsx b/packages/client/src/features/publishing/PublishingPage.tsx index 3977bc859..4c06147e9 100644 --- a/packages/client/src/features/publishing/PublishingPage.tsx +++ b/packages/client/src/features/publishing/PublishingPage.tsx @@ -3,7 +3,7 @@ import React, { useState } from 'react' import { Link, useNavigate, useSearchParams } from 'react-router' import { Button } from '../../components/Button' import { Checkbox } from '../../components/Checkbox' -import { EntityIcon } from '../../components/EntityIcon' +import { EntityIcon } from '../../components/icons/EntityIcon' import { UserLayout } from '../../layouts/UserLayout' import { HomeLoader, NotFound } from '../home/show.styles' import { getEntityTypeFromIdentifier } from '../tracks/TrackProvenanceContent' @@ -21,7 +21,7 @@ import { PublishingWrapper, StyledCallout, StyledPageContainer, -} from './styles' +} from './publishing.styles' import { usePublishingTreeRootQuery } from './usePublishingTreeQuery' import { AxiosError } from 'axios' import { toastError, toastSuccess } from '../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/publishing/styles.ts b/packages/client/src/features/publishing/publishing.styles.ts similarity index 99% rename from packages/client/src/features/publishing/styles.ts rename to packages/client/src/features/publishing/publishing.styles.ts index 9da061721..809c96358 100644 --- a/packages/client/src/features/publishing/styles.ts +++ b/packages/client/src/features/publishing/publishing.styles.ts @@ -1,6 +1,6 @@ import styled from 'styled-components' import { Callout } from '../../components/Callout' -import { PageContainer, pagePadding } from '../../components/Page/styles' +import { PageContainer, pagePadding } from '../../components/Page/page.styles' export const StyledPageContainer = styled(PageContainer)` ${pagePadding} diff --git a/packages/client/src/features/request-access/RequestAccessPage.tsx b/packages/client/src/features/request-access/RequestAccessPage.tsx index ab47ac998..5db464a3a 100644 --- a/packages/client/src/features/request-access/RequestAccessPage.tsx +++ b/packages/client/src/features/request-access/RequestAccessPage.tsx @@ -10,7 +10,7 @@ import * as Yup from 'yup' import { Button } from '../../components/Button' import { Checkbox } from '../../components/Checkbox' import { FieldGroup } from '../../components/form/FieldGroup' -import { CheckboxLabel, InputError } from '../../components/form/styles' +import { CheckboxLabel, InputError } from '../../components/form/form.styles' import { InputText } from '../../components/InputText' import { Loader } from '../../components/Loader' import { PFDALogoDark, PFDALogoLight } from '../../components/NavigationBar/PFDALogo' diff --git a/packages/client/src/features/request-access/style.ts b/packages/client/src/features/request-access/style.ts index 3aed65a4c..d90becd67 100644 --- a/packages/client/src/features/request-access/style.ts +++ b/packages/client/src/features/request-access/style.ts @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components' import { Callout } from '../../components/Callout' -import { PageContainer } from '../../components/Page/styles' +import { PageContainer } from '../../components/Page/page.styles' export const LogoBar = styled.div` display: flex; diff --git a/packages/client/src/features/resources/CreateResource.tsx b/packages/client/src/features/resources/CreateResource.tsx index 0389bb994..a60c098ac 100644 --- a/packages/client/src/features/resources/CreateResource.tsx +++ b/packages/client/src/features/resources/CreateResource.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components' import { Button } from '../../components/Button' import { Loader } from '../../components/Loader' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { Footer, ModalScroll } from '../modal/styles' +import { Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { Item, useUploadResource } from './useUploadResource' diff --git a/packages/client/src/features/resources/ResourceItem.tsx b/packages/client/src/features/resources/ResourceItem.tsx index ee7fe2616..d73b20119 100644 --- a/packages/client/src/features/resources/ResourceItem.tsx +++ b/packages/client/src/features/resources/ResourceItem.tsx @@ -1,7 +1,7 @@ import React from 'react' import { FileIcon } from '../../components/icons/FileIcon' import { Resource } from '../data-portals/resources/resources.types' -import { FileThumbSmall, ImageContainer, ItemName, StyledResourceItem } from './styles' +import { FileThumbSmall, ImageContainer, ItemName, StyledResourceItem } from './resources.styles' import { getExt, isImageFromExt } from './util' diff --git a/packages/client/src/features/resources/styles.ts b/packages/client/src/features/resources/resources.styles.ts similarity index 100% rename from packages/client/src/features/resources/styles.ts rename to packages/client/src/features/resources/resources.styles.ts diff --git a/packages/client/src/features/resources/uploadImage.ts b/packages/client/src/features/resources/uploadImage.ts index f40380329..70ad4186d 100644 --- a/packages/client/src/features/resources/uploadImage.ts +++ b/packages/client/src/features/resources/uploadImage.ts @@ -1,8 +1,7 @@ import axios from 'axios' import sparkMD5 from 'spark-md5' -import { GetUploadURLResponse } from './resources.types' -import { HTTP_STATUS } from '../../constants' import { getUploadURL } from '../../api/files' +import { HTTP_STATUS } from '../../constants' export const CHUNK_SIZE = 100 * 1024 ** 2 // 100Mb @@ -13,14 +12,12 @@ const throwIfError = (status: number, payload?: any) => { } } -const uploadChunk = (url: string, chunk: ArrayBuffer, headers: HeadersInit) => ( - +const uploadChunk = (url: string, chunk: ArrayBuffer, headers: HeadersInit) => fetch(url, { method: 'PUT', body: chunk, headers, }) -) const closeFile = (uid: string, followUpAction?: string) => axios.post('/api/close_file', { @@ -32,7 +29,13 @@ function getNumChunks(file: File) { return Math.ceil(file.size / CHUNK_SIZE) } -async function processChunk(file: File, fileUid: string, chunkIndex: number, reader: FileReader, spark: sparkMD5.ArrayBuffer) { +async function processChunk( + file: File, + fileUid: string, + chunkIndex: number, + reader: FileReader, + spark: sparkMD5.ArrayBuffer, +) { const firstByte = chunkIndex * CHUNK_SIZE const lastByte = (chunkIndex + 1) * CHUNK_SIZE @@ -56,7 +59,9 @@ function readAndProcessFile(file: File, fileUid: string) { const spark = new sparkMD5.ArrayBuffer() reader.onload = async () => { - const promises = Array.from({ length: getNumChunks(file) }, (_, i) => processChunk(file, fileUid, i, reader, spark)) + const promises = Array.from({ length: getNumChunks(file) }, (_, i) => + processChunk(file, fileUid, i, reader, spark), + ) try { await Promise.all(promises) diff --git a/packages/client/src/features/resources/useDataPortalResourceModal.tsx b/packages/client/src/features/resources/useDataPortalResourceModal.tsx index 9ab436a5a..a6c4ad760 100644 --- a/packages/client/src/features/resources/useDataPortalResourceModal.tsx +++ b/packages/client/src/features/resources/useDataPortalResourceModal.tsx @@ -5,7 +5,7 @@ import { Button } from '../../components/Button' import { InputText } from '../../components/InputText' import { Loader } from '../../components/Loader' import { NotAllowedPage } from '../../components/NotAllowed' -import { NoContent } from '../../components/Public/styles' +import { NoContent } from '../../components/Public/public-layout.styles' import { CopyIcon } from '../../components/icons/CopyIcon' import { FileIcon } from '../../components/icons/FileIcon' import { useAuthUser } from '../auth/useAuthUser' @@ -15,7 +15,7 @@ import { RemovePayload, Resource } from '../data-portals/resources/resources.typ import { canEditResources } from '../data-portals/utils' import { NOTIFICATION_ACTION } from '../home/types' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ModalLoaderWrapper } from '../modal/styles' +import { ModalLoaderWrapper } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { CreateResource } from './CreateResource' import ResourceItem from './ResourceItem' @@ -37,7 +37,7 @@ import { StyledSide, TopCol, TopRow, -} from './styles' +} from './resources.styles' import { getExt, isImageFromExt } from './util' import { useLastWSNotification } from '../../hooks/useLastWSNotification' import { toastSuccess } from '../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/resources/useUploadResource.tsx b/packages/client/src/features/resources/useUploadResource.tsx index d92ac4a57..0e6f27020 100644 --- a/packages/client/src/features/resources/useUploadResource.tsx +++ b/packages/client/src/features/resources/useUploadResource.tsx @@ -5,7 +5,7 @@ import { processFile } from './uploadImage' import { useCreateResourceMutation } from './useCreateResourceMutation' import { getExt, isImageFromExt } from './util' import { FileIcon } from '../../components/icons/FileIcon' -import { FileThumb } from './styles' +import { FileThumb } from './resources.styles' import { FileWithPreview } from './resources.types' import { Button } from '../../components/Button' import { toastError, toastSuccess } from '../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/space-groups/form/SpaceGroupForm.tsx b/packages/client/src/features/space-groups/form/SpaceGroupForm.tsx index 3c2c6de34..cdc8f943a 100644 --- a/packages/client/src/features/space-groups/form/SpaceGroupForm.tsx +++ b/packages/client/src/features/space-groups/form/SpaceGroupForm.tsx @@ -5,11 +5,11 @@ import React, { useEffect } from 'react' import { useForm } from 'react-hook-form' import { Button } from '../../../components/Button' import { FieldGroup } from '../../../components/form/FieldGroup' -import { InputError } from '../../../components/form/styles' +import { InputError } from '../../../components/form/form.styles' import { InputText, InputTextArea } from '../../../components/InputText' import { Loader } from '../../../components/Loader' import { ApiErrorResponse } from '../../home/types' -import { Footer, StyledForm, StyledModalScroll } from '../../modal/styles' +import { Footer, StyledForm, StyledModalScroll } from '../../modal/modal.styles' import { SpaceGroupFormData } from '../types' import { spaceGroupValidationSchema } from './helpers' diff --git a/packages/client/src/features/space-groups/modals/useDeleteSpaceGroupModal.tsx b/packages/client/src/features/space-groups/modals/useDeleteSpaceGroupModal.tsx index a1f13ced7..92f451d9a 100644 --- a/packages/client/src/features/space-groups/modals/useDeleteSpaceGroupModal.tsx +++ b/packages/client/src/features/space-groups/modals/useDeleteSpaceGroupModal.tsx @@ -7,7 +7,7 @@ import { Button } from '../../../components/Button' import { InfoCircleIcon } from '../../../components/icons/InfoCircleIcon' import { Loader } from '../../../components/Loader' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer } from '../../modal/styles' +import { ButtonRow, Footer } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { deleteSpaceGroupRequest } from '../api' import { ISpaceGroup } from '../types' diff --git a/packages/client/src/features/space-reports/SpaceReportList.tsx b/packages/client/src/features/space-reports/SpaceReportList.tsx index f3b2e6067..7997d7f89 100644 --- a/packages/client/src/features/space-reports/SpaceReportList.tsx +++ b/packages/client/src/features/space-reports/SpaceReportList.tsx @@ -5,7 +5,7 @@ import { Button } from '@/components/Button' import { SpaceReportIcon } from '@/components/icons/SpaceReportIcon' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { useLastWSNotification } from '@/hooks/useLastWSNotification' import { getSelectedObjectsFromIndexes } from '@/utils/object' import Table from '../../components/Table' diff --git a/packages/client/src/features/space-reports/useDeleteSpaceReportModal.tsx b/packages/client/src/features/space-reports/useDeleteSpaceReportModal.tsx index 0ebfcf40c..ad7447035 100644 --- a/packages/client/src/features/space-reports/useDeleteSpaceReportModal.tsx +++ b/packages/client/src/features/space-reports/useDeleteSpaceReportModal.tsx @@ -7,7 +7,7 @@ import { toastError, toastSuccess } from '@/components/NotificationCenter/ToastH import { StyledTable, StyledTD } from '@/components/ResourceTable' import { formatDate, itemsCountString } from '@/utils/formatting' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { ISpaceReport } from './space-report.types' import { deleteReports } from './space-reports.api' diff --git a/packages/client/src/features/space-reports/useGenerateSpaceReportModal.tsx b/packages/client/src/features/space-reports/useGenerateSpaceReportModal.tsx index 7baea320b..a29c9b968 100644 --- a/packages/client/src/features/space-reports/useGenerateSpaceReportModal.tsx +++ b/packages/client/src/features/space-reports/useGenerateSpaceReportModal.tsx @@ -4,12 +4,12 @@ import { AxiosError } from 'axios' import styled from 'styled-components' import { Button } from '@/components/Button' import { Checkbox } from '@/components/CheckboxNext' -import { FieldGroup, FieldLabelRow } from '@/components/form/styles' +import { FieldGroup, FieldLabelRow } from '@/components/form/form.styles' import { Loader } from '@/components/Loader' import { toastError } from '@/components/NotificationCenter/ToastHelper' import { Radio } from '@/components/Radio' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer, ModalScroll, StyledForm } from '../modal/styles' +import { ButtonRow, Footer, ModalScroll, StyledForm } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { SpaceReportFormat, SpaceReportFormatToOptionsMap } from './space-report.types' import { createReport } from './space-reports.api' diff --git a/packages/client/src/features/spaces/SpaceSelectionList.tsx b/packages/client/src/features/spaces/SpaceSelectionList.tsx index 46bd19f7e..79311df2f 100644 --- a/packages/client/src/features/spaces/SpaceSelectionList.tsx +++ b/packages/client/src/features/spaces/SpaceSelectionList.tsx @@ -1,8 +1,8 @@ import { useQuery } from '@tanstack/react-query' import type React from 'react' import { HomeIcon } from '@/components/icons/HomeIcon' -import { FdaRestrictedIcon } from './FdaRestrictedIcon' -import { ProtectedIcon } from './ProtectedIcon' +import { FdaRestrictedIcon } from '@/components/icons/FdaRestrictedIcon' +import { ProtectedIcon } from '@/components/icons/ProtectedIcon' import { type EditableSpace, fetchEditableSpacesList } from './spaces.api' import styles from './spaces.module.css' import { findSpaceTypeIcon } from './useSpacesColumns' @@ -12,6 +12,21 @@ interface MyHomeProps { onSelect: () => void } +const highlightMatch = (text: string, query: string): React.ReactNode => { + if (!query) return text + const lower = text.toLowerCase() + const q = query.toLowerCase() + const idx = lower.indexOf(q) + if (idx === -1) return text + return ( + <> + {text.slice(0, idx)} + {text.slice(idx, idx + q.length)} + {text.slice(idx + q.length)} + + ) +} + interface SpaceSelectionListProps { excludeScopes?: string[] filterString?: string @@ -34,7 +49,11 @@ export const SpaceSelectionList = ({ const spaces = data .filter(s => !excludeScopes.includes(s.scope)) - .filter(s => !filterString || s.title.toLowerCase().includes(filterString.toLowerCase())) + .filter(s => { + if (!filterString) return true + const q = filterString.toLowerCase() + return s.title.toLowerCase().includes(q) || s.scope.toLowerCase().includes(q) + }) if (isLoading) { return
Loading...
@@ -80,9 +99,9 @@ export const SpaceSelectionList = ({ {s.protected && } {s.restrictedReviewer && } - {s.title} + {highlightMatch(s.title, filterString)} - {s.scope} + {highlightMatch(s.scope, filterString)} ))} diff --git a/packages/client/src/features/spaces/form/CreateSpace.tsx b/packages/client/src/features/spaces/form/CreateSpace.tsx index 993812652..5f8419e1b 100644 --- a/packages/client/src/features/spaces/form/CreateSpace.tsx +++ b/packages/client/src/features/spaces/form/CreateSpace.tsx @@ -2,10 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import React from 'react' import { useNavigate } from 'react-router' import { AxiosError } from 'axios' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { createSpaceRequest, spaceRequest } from '../spaces.api' import { SpaceForm } from './CreateSpaceForm' -import { StyledBack, StyledPageCenter, StyledPageContent } from './styles' +import { StyledBack, StyledPageCenter, StyledPageContent } from './spaces-form.styles' import { UserLayout } from '../../../layouts/UserLayout' import { ApiErrorResponse } from '../../home/types' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/spaces/form/CreateSpaceForm.tsx b/packages/client/src/features/spaces/form/CreateSpaceForm.tsx index b2312d5ae..204ab6698 100644 --- a/packages/client/src/features/spaces/form/CreateSpaceForm.tsx +++ b/packages/client/src/features/spaces/form/CreateSpaceForm.tsx @@ -7,14 +7,14 @@ import { Button } from '../../../components/Button' import { Checkbox } from '../../../components/Checkbox' import { FieldGroup } from '../../../components/form/FieldGroup' import { RadioButtonGroup } from '../../../components/form/RadioButtonGroup' -import { Divider, FieldLabelRow, InputError } from '../../../components/form/styles' +import { Divider, FieldLabelRow, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { Loader } from '../../../components/Loader' import { useAuthUser } from '../../auth/useAuthUser' import { useConfirm } from '../../modal/useConfirm' import { CreateSpacePayload, CreateSpaceResponse } from '../spaces.api' import { getSpaceTypeOptions, SPACE_TYPE_HINT, validationSchema } from './helpers' -import { HintText, Row, StyledForm } from './styles' +import { HintText, Row, StyledForm } from './spaces-form.styles' export interface ISpaceForm { mutation: UseMutationResult diff --git a/packages/client/src/features/spaces/form/SpaceSettings.tsx b/packages/client/src/features/spaces/form/SpaceSettings.tsx index 0b2ae927d..b93e6fde8 100644 --- a/packages/client/src/features/spaces/form/SpaceSettings.tsx +++ b/packages/client/src/features/spaces/form/SpaceSettings.tsx @@ -5,11 +5,11 @@ import { useForm } from 'react-hook-form' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useNavigate, useParams } from 'react-router' import { FieldGroup } from '../../../components/form/FieldGroup' -import { Divider, InputError } from '../../../components/form/styles' +import { Divider, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { Loader } from '../../../components/Loader' import { BackLinkMargin } from '../../../components/Page/PageBackLink' -import { PageTitle } from '../../../components/Page/styles' +import { PageTitle } from '../../../components/Page/page.styles' import { StyledTagItem, StyledTags } from '../../../components/Tags' import { useEditTagsModal } from '../../actionModals/useEditTagsModal' import { SpaceTypeName } from '../common' @@ -17,7 +17,7 @@ import { EditSpacePayload, editSpaceRequest, spaceRequest } from '../spaces.api' import { ISpace } from '../spaces.types' import { useSpaceActions } from '../useSpaceActions' import { editValidationSchema } from './helpers' -import { HintText, Row, StyledButton, StyledForm, StyledPageCenter, StyledPageContent } from './styles' +import { HintText, Row, StyledButton, StyledForm, StyledPageCenter, StyledPageContent } from './spaces-form.styles' import { UserLayout } from '../../../layouts/UserLayout' import { Button } from '../../../components/Button' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/spaces/form/styles.ts b/packages/client/src/features/spaces/form/spaces-form.styles.ts similarity index 100% rename from packages/client/src/features/spaces/form/styles.ts rename to packages/client/src/features/spaces/form/spaces-form.styles.ts diff --git a/packages/client/src/features/spaces/members/MemberEditButton.tsx b/packages/client/src/features/spaces/members/MemberEditButton.tsx index d44b5f192..408b5b083 100644 --- a/packages/client/src/features/spaces/members/MemberEditButton.tsx +++ b/packages/client/src/features/spaces/members/MemberEditButton.tsx @@ -1,7 +1,7 @@ import React from 'react' import { ThreeDotsIcon } from '../../../components/icons/ThreeDotsIcon' import Menu from '../../../components/Menu/Menu' -import { StyledEditButton } from '../../discussions/styles' +import { StyledEditButton } from '../../discussions/discussions.styles' import { SpaceMembership } from './members.types' import { useChangeMemberRoleModal } from './useChangeMemberRoleModal' diff --git a/packages/client/src/features/spaces/members/MembersListTable.tsx b/packages/client/src/features/spaces/members/MembersListTable.tsx index 8b3cc09de..40bd6384b 100644 --- a/packages/client/src/features/spaces/members/MembersListTable.tsx +++ b/packages/client/src/features/spaces/members/MembersListTable.tsx @@ -7,7 +7,7 @@ import { } from '@tanstack/react-table' import React from 'react' import Table from '../../../components/Table' -import { StyledPageTable } from '../../../components/Table/components/styles' +import { StyledPageTable } from '../../../components/Table/components/table.styles' import { SpaceMembership } from './members.types' import { ISpace } from '../spaces.types' import { useMembersColumns } from './useMembersColumns' diff --git a/packages/client/src/features/spaces/members/members.styles.ts b/packages/client/src/features/spaces/members/members.styles.ts index d530d61e7..43866d273 100644 --- a/packages/client/src/features/spaces/members/members.styles.ts +++ b/packages/client/src/features/spaces/members/members.styles.ts @@ -1,5 +1,5 @@ import styled, { css } from 'styled-components' -import { Footer } from '../../modal/styles' +import { Footer } from '../../modal/modal.styles' export const StyledFields = styled.div` display: flex; diff --git a/packages/client/src/features/spaces/members/useAddMembersModal.tsx b/packages/client/src/features/spaces/members/useAddMembersModal.tsx index 3c5a76355..52a19f0c8 100644 --- a/packages/client/src/features/spaces/members/useAddMembersModal.tsx +++ b/packages/client/src/features/spaces/members/useAddMembersModal.tsx @@ -8,12 +8,12 @@ import * as Yup from 'yup' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { cn } from '@/utils/cn' import { Button } from '../../../components/Button' -import { FieldGroup, Hint, InputError } from '../../../components/form/styles' +import { FieldGroup, Hint, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' import type { ApiRailsError } from '../../home/types' import { ModalHeaderTop, ModalNext, useModalFloatingPortalHost } from '../../modal/ModalNext' -import { ButtonRow } from '../../modal/styles' +import { ButtonRow } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { addMembersToSpaceRequest } from './members.api' import { StyledFields, StyledFooter } from './members.styles' diff --git a/packages/client/src/features/spaces/members/useBulkChangeMemberRolesModal.tsx b/packages/client/src/features/spaces/members/useBulkChangeMemberRolesModal.tsx index ac8b00f67..0fc91db3f 100644 --- a/packages/client/src/features/spaces/members/useBulkChangeMemberRolesModal.tsx +++ b/packages/client/src/features/spaces/members/useBulkChangeMemberRolesModal.tsx @@ -7,7 +7,7 @@ import * as Yup from 'yup' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { cn } from '@/utils/cn' import { Button } from '../../../components/Button' -import { ErrorHint, FieldGroup, Hint, InputError } from '../../../components/form/styles' +import { ErrorHint, FieldGroup, Hint, InputError } from '../../../components/form/form.styles' import { ModalHeaderTop, ModalNext, useModalFloatingPortalHost } from '../../modal/ModalNext' import { useModal } from '../../modal/useModal' import { diff --git a/packages/client/src/features/spaces/members/useChangeMemberRoleModal.tsx b/packages/client/src/features/spaces/members/useChangeMemberRoleModal.tsx index f0d38fb9a..63117735f 100644 --- a/packages/client/src/features/spaces/members/useChangeMemberRoleModal.tsx +++ b/packages/client/src/features/spaces/members/useChangeMemberRoleModal.tsx @@ -7,7 +7,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { cn } from '@/utils/cn' import { Button } from '../../../components/Button' import { Callout } from '../../../components/Callout' -import { ErrorHint, FieldGroup, Hint, InputError } from '../../../components/form/styles' +import { ErrorHint, FieldGroup, Hint, InputError } from '../../../components/form/form.styles' import { InputText } from '../../../components/InputText' import { ModalHeaderTop, ModalNext, useModalFloatingPortalHost } from '../../modal/ModalNext' import { useModal } from '../../modal/useModal' diff --git a/packages/client/src/features/spaces/modals/ModalSpaceList.tsx b/packages/client/src/features/spaces/modals/ModalSpaceList.tsx index 0b657b659..bd3ab410f 100644 --- a/packages/client/src/features/spaces/modals/ModalSpaceList.tsx +++ b/packages/client/src/features/spaces/modals/ModalSpaceList.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Link } from 'react-router' import styled from 'styled-components' -import { VerticalCenter } from '../../../components/Page/styles' +import { VerticalCenter } from '../../../components/Page/page.styles' import { ISpaceV2 } from '../spaces.types' import { findSpaceTypeIcon } from '../useSpacesColumns' diff --git a/packages/client/src/features/spaces/modals/useAddSpacesToSpaceGroupModal.tsx b/packages/client/src/features/spaces/modals/useAddSpacesToSpaceGroupModal.tsx index b03686049..ca121ea3f 100644 --- a/packages/client/src/features/spaces/modals/useAddSpacesToSpaceGroupModal.tsx +++ b/packages/client/src/features/spaces/modals/useAddSpacesToSpaceGroupModal.tsx @@ -8,7 +8,7 @@ import { Callout } from '../../../components/Callout' import { Loader } from '../../../components/Loader' import { itemsCountString } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScrollPadding } from '../../modal/styles' +import { ButtonRow, Footer, ModalScrollPadding } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { addSpacesToSpaceGroup } from '../../space-groups/api' import { ISpaceV2 } from '../spaces.types' diff --git a/packages/client/src/features/spaces/modals/useRemoveSpacesFromSpaceGroupModal.tsx b/packages/client/src/features/spaces/modals/useRemoveSpacesFromSpaceGroupModal.tsx index 661126cd7..bd9d59e9b 100644 --- a/packages/client/src/features/spaces/modals/useRemoveSpacesFromSpaceGroupModal.tsx +++ b/packages/client/src/features/spaces/modals/useRemoveSpacesFromSpaceGroupModal.tsx @@ -5,7 +5,7 @@ import { Button } from '../../../components/Button' import { Loader } from '../../../components/Loader' import { itemsCountString } from '../../../utils/formatting' import { ModalHeaderTop, ModalNext } from '../../modal/ModalNext' -import { ButtonRow, Footer, ModalScrollPadding } from '../../modal/styles' +import { ButtonRow, Footer, ModalScrollPadding } from '../../modal/modal.styles' import { useModal } from '../../modal/useModal' import { removeSpaces } from '../../space-groups/api' import { ISpaceGroup } from '../../space-groups/types' diff --git a/packages/client/src/features/spaces/show/SpaceActivation.tsx b/packages/client/src/features/spaces/show/SpaceActivation.tsx index 35ad80085..d2de0149a 100644 --- a/packages/client/src/features/spaces/show/SpaceActivation.tsx +++ b/packages/client/src/features/spaces/show/SpaceActivation.tsx @@ -2,13 +2,13 @@ import React from 'react' import { useMutation, useQueryClient } from '@tanstack/react-query' import styled from 'styled-components' import { Loader } from '../../../components/Loader' -import { PageContainer } from '../../../components/Page/styles' +import { PageContainer } from '../../../components/Page/page.styles' import { useAuthUser } from '../../auth/useAuthUser' import { acceptSpaceRequest } from '../spaces.api' import { ISpace } from '../spaces.types' -import { SpaceHeaderDescrip, SpaceHeaderTitle, SpaceMainInfo } from './styles' -import { ProtectedIcon } from '../ProtectedIcon' -import { FdaRestrictedIcon } from '../FdaRestrictedIcon' +import { SpaceHeaderDescrip, SpaceHeaderTitle, SpaceMainInfo } from './spaces-show.styles' +import { ProtectedIcon } from '@/components/icons/ProtectedIcon' +import { FdaRestrictedIcon } from '@/components/icons/FdaRestrictedIcon' import { Button } from '../../../components/Button' import { ApiErrorResponse } from '../../home/types' import { toastError, toastSuccess } from '../../../components/NotificationCenter/ToastHelper' diff --git a/packages/client/src/features/spaces/show/SpaceLocked.tsx b/packages/client/src/features/spaces/show/SpaceLocked.tsx index b5009ac62..3ddd282f0 100644 --- a/packages/client/src/features/spaces/show/SpaceLocked.tsx +++ b/packages/client/src/features/spaces/show/SpaceLocked.tsx @@ -2,9 +2,9 @@ import React from 'react' import { useNavigate } from 'react-router' import styled from 'styled-components' import { AlertText, Col, Warning } from '../../../components/NotAllowed' -import { PageContainer } from '../../../components/Page/styles' +import { PageContainer } from '../../../components/Page/page.styles' import { ISpace } from '../spaces.types' -import { ActionButton } from './styles' +import { ActionButton } from './spaces-show.styles' export const ButtonWrapper = styled.div` diff --git a/packages/client/src/features/spaces/show/SpaceNotAllowed.tsx b/packages/client/src/features/spaces/show/SpaceNotAllowed.tsx index 36090ce51..a01ff993a 100644 --- a/packages/client/src/features/spaces/show/SpaceNotAllowed.tsx +++ b/packages/client/src/features/spaces/show/SpaceNotAllowed.tsx @@ -1,6 +1,6 @@ import React from 'react' import { ActionText, AlertText, Col, Warning } from '../../../components/NotAllowed' -import { PageContainer } from '../../../components/Page/styles' +import { PageContainer } from '../../../components/Page/page.styles' export function SpaceNotAllowed() { return ( diff --git a/packages/client/src/features/spaces/show/SpaceShowLayout.tsx b/packages/client/src/features/spaces/show/SpaceShowLayout.tsx index 8c02d4927..fa52c1e35 100644 --- a/packages/client/src/features/spaces/show/SpaceShowLayout.tsx +++ b/packages/client/src/features/spaces/show/SpaceShowLayout.tsx @@ -18,8 +18,8 @@ import { ErrorBoundary } from '@/utils/ErrorBoundary' import { Expand, Fill, Main, MenuItem, MenuText, Row, StyledMenu } from '../../home/home.styles' import type { ApiErrorResponse } from '../../home/types' import { useActiveResourceFromUrl } from '../../home/useActiveResourceFromUrl' -import { FdaRestrictedIcon } from '../FdaRestrictedIcon' -import { ProtectedIcon } from '../ProtectedIcon' +import { FdaRestrictedIcon } from '@/components/icons/FdaRestrictedIcon' +import { ProtectedIcon } from '@/components/icons/ProtectedIcon' import { fixGuestPermissions } from '../spaces.api' import { useSpaceActions } from '../useSpaceActions' import { SpaceTypeTabs } from './SpaceTypeTabs' @@ -34,7 +34,7 @@ import { SpaceMainInfo, SpaceTopRight, TopSpaceHeader, -} from './styles' +} from './spaces-show.styles' export const SpaceShowLayout = () => { const context = useOutletContext() diff --git a/packages/client/src/features/spaces/show/SpaceTypeTabs.tsx b/packages/client/src/features/spaces/show/SpaceTypeTabs.tsx index f6de682bd..b0e92c51f 100644 --- a/packages/client/src/features/spaces/show/SpaceTypeTabs.tsx +++ b/packages/client/src/features/spaces/show/SpaceTypeTabs.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Link } from 'react-router' import { ISpace } from '../spaces.types' -import { Tab, Tabs } from './styles' +import { Tab, Tabs } from './spaces-show.styles' import { ResourceTypeUrlNames } from '../../home/types' const privateTextShort = 'Only you can view and edit resources.' diff --git a/packages/client/src/features/spaces/show/styles.ts b/packages/client/src/features/spaces/show/spaces-show.styles.ts similarity index 100% rename from packages/client/src/features/spaces/show/styles.ts rename to packages/client/src/features/spaces/show/spaces-show.styles.ts diff --git a/packages/client/src/features/spaces/spaces.module.css b/packages/client/src/features/spaces/spaces.module.css index 67cbd5331..c9b44d640 100644 --- a/packages/client/src/features/spaces/spaces.module.css +++ b/packages/client/src/features/spaces/spaces.module.css @@ -147,3 +147,10 @@ padding: 16px 12px; color: var(--c-text-500); } + +.spaceSelectionMatch { + background-color: var(--highlight-100); + color: inherit; + border-radius: 2px; + padding: 0 1px; +} diff --git a/packages/client/src/features/spaces/useSpacesColumns.tsx b/packages/client/src/features/spaces/useSpacesColumns.tsx index bcd255f4a..9ff9b047c 100644 --- a/packages/client/src/features/spaces/useSpacesColumns.tsx +++ b/packages/client/src/features/spaces/useSpacesColumns.tsx @@ -13,8 +13,8 @@ import { StyledTagItem, StyledTags } from '@/components/Tags' import { formatDateOnly } from '@/utils/formatting' import SelectFilter, { selectFilterFn } from '../../components/Table/components/SelectFilter' import { SpaceTypeName } from './common' -import { FdaRestrictedIcon } from './FdaRestrictedIcon' -import { ProtectedIcon } from './ProtectedIcon' +import { FdaRestrictedIcon } from '@/components/icons/FdaRestrictedIcon' +import { ProtectedIcon } from '@/components/icons/ProtectedIcon' import type { ISpaceV2 } from './spaces.types' import { useSpaceHiddenMutation } from './useSpaceHiddenMutation' diff --git a/packages/client/src/features/spaces/useUnlockSpaceModal.tsx b/packages/client/src/features/spaces/useUnlockSpaceModal.tsx index 634599bc4..d352802f2 100644 --- a/packages/client/src/features/spaces/useUnlockSpaceModal.tsx +++ b/packages/client/src/features/spaces/useUnlockSpaceModal.tsx @@ -3,7 +3,7 @@ import React from 'react' import { styled } from 'styled-components' import { Button } from '../../components/Button' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { Footer } from '../modal/styles' +import { Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { unlockSpaceRequest } from './spaces.api' import { ISpace } from './spaces.types' diff --git a/packages/client/src/features/tracks/TrackProvenanceContent.tsx b/packages/client/src/features/tracks/TrackProvenanceContent.tsx index 67192bcff..30c8babf6 100644 --- a/packages/client/src/features/tracks/TrackProvenanceContent.tsx +++ b/packages/client/src/features/tracks/TrackProvenanceContent.tsx @@ -7,7 +7,7 @@ import { DatabaseIcon } from '../../components/icons/DatabaseIcon' import { FileIcon } from '../../components/icons/FileIcon' import { SitemapIcon } from '../../components/icons/SitemapIcon' import { StickyNoteIcon } from '../../components/icons/StickyNote' -import { Help } from '../apps/form/styles' +import { Help } from '../apps/form/apps-form.styles' import { NotFound } from '../home/show.styles' export type EntityType = 'file' | 'app' | 'execution' | 'database' | 'comparison' | 'note' diff --git a/packages/client/src/features/workflows/WorkflowExecutionsList.tsx b/packages/client/src/features/workflows/WorkflowExecutionsList.tsx index 2554016f2..61f254b58 100644 --- a/packages/client/src/features/workflows/WorkflowExecutionsList.tsx +++ b/packages/client/src/features/workflows/WorkflowExecutionsList.tsx @@ -10,7 +10,7 @@ import type { import { useEffect, useState } from 'react' import { ContentFooter } from '@/components/Page/ContentFooter' import { hidePagination, Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { useColumnWidthLocalStorage } from '@/hooks/useColumnWidthLocalStorage' import { useHiddenColumnLocalStorage } from '@/hooks/useHiddenColumnLocalStorage' import { useLastWSNotification } from '@/hooks/useLastWSNotification' diff --git a/packages/client/src/features/workflows/WorkflowList.tsx b/packages/client/src/features/workflows/WorkflowList.tsx index 8140331d8..04c1ccf76 100644 --- a/packages/client/src/features/workflows/WorkflowList.tsx +++ b/packages/client/src/features/workflows/WorkflowList.tsx @@ -11,7 +11,7 @@ import { PlusIcon } from '@/components/icons/PlusIcon' import { ActionsMenu } from '@/components/Menu' import { ContentFooter } from '@/components/Page/ContentFooter' import { Pagination } from '@/components/Pagination' -import { StyledPageTable } from '@/components/Table/components/styles' +import { StyledPageTable } from '@/components/Table/components/table.styles' import { ErrorBoundary } from '@/utils/ErrorBoundary' import { getSelectedObjectsFromIndexes, toArrayFromObject } from '@/utils/object' import Table from '../../components/Table' diff --git a/packages/client/src/features/workflows/WorkflowSpec/WorkflowSpec.tsx b/packages/client/src/features/workflows/WorkflowSpec/WorkflowSpec.tsx index 88c4adfd7..4d51f7c7f 100644 --- a/packages/client/src/features/workflows/WorkflowSpec/WorkflowSpec.tsx +++ b/packages/client/src/features/workflows/WorkflowSpec/WorkflowSpec.tsx @@ -1,6 +1,6 @@ import React from 'react' import { COMPUTE_RESOURCE_LABELS } from '@/types/user' -import { StyledSpecTab } from '../../apps/SpecTab/styles' +import { StyledSpecTab } from '../../apps/SpecTab/apps-spec-tab.styles' import { MetadataKey, MetadataVal } from '../../home/show.styles' import { Spec, Stage } from '../workflows.types' import { WorkflowSpecTable } from './WorkflowSpecTable' diff --git a/packages/client/src/features/workflows/WorkflowsDiagram/index.tsx b/packages/client/src/features/workflows/WorkflowsDiagram/index.tsx index 08b3fd88c..83ffc7601 100644 --- a/packages/client/src/features/workflows/WorkflowsDiagram/index.tsx +++ b/packages/client/src/features/workflows/WorkflowsDiagram/index.tsx @@ -4,7 +4,7 @@ import Xarrow from 'react-xarrows' import { CubeIcon } from '../../../components/icons/CubeIcon' import { Loader } from '../../../components/Loader' import type { InputOutput, Stage as WorkflowStage } from '../workflows.types' -import { StyledWorkflowDiagram } from './styles' +import { StyledWorkflowDiagram } from './workflows-diagram.styles' import { useWorkflowDiagramQuery } from './useWorkflowDiagramQuery' const NoData = () => { diff --git a/packages/client/src/features/workflows/WorkflowsDiagram/styles.ts b/packages/client/src/features/workflows/WorkflowsDiagram/workflows-diagram.styles.ts similarity index 100% rename from packages/client/src/features/workflows/WorkflowsDiagram/styles.ts rename to packages/client/src/features/workflows/WorkflowsDiagram/workflows-diagram.styles.ts diff --git a/packages/client/src/features/workflows/run/RunWorkflowForm.tsx b/packages/client/src/features/workflows/run/RunWorkflowForm.tsx index f03a55b1f..bf5741415 100644 --- a/packages/client/src/features/workflows/run/RunWorkflowForm.tsx +++ b/packages/client/src/features/workflows/run/RunWorkflowForm.tsx @@ -17,7 +17,7 @@ import { CubeIcon } from '@/components/icons/CubeIcon' import { GearIcon } from '@/components/icons/GearIcon' import { toastError } from '@/components/NotificationCenter/ToastHelper' import { BackLink } from '@/components/Page/PageBackLink' -import { FormPageContainer } from '@/components/Page/styles' +import { FormPageContainer } from '@/components/Page/page.styles' import type { IUser } from '@/types/user' import { getSpaceIdFromScope } from '@/utils' import type { AcceptedLicense, IApp, InputSpec, SelectType } from '../../apps/apps.types' @@ -25,7 +25,7 @@ import { getDefaultValueFromServer } from '../../apps/form/common' import { ErrorMessageForField } from '../../apps/run/ErrorMessageForField' import { JobRunInput } from '../../apps/run/JobRunInput' import { SelectSpaceScope } from '../../apps/run/SelectSpaceScope' -import { Section, SectionBody, SectionHeader, StyledGrid, Topbox, TopboxItem } from '../../apps/run/styles' +import { Section, SectionBody, SectionHeader, StyledGrid, Topbox, TopboxItem } from '../../apps/run/apps-run.styles' import { extractFileUids, getValue, useDefaultScopeSelection, useSelectableSpaces } from '../../apps/run/utils' import { useAuthUser } from '../../auth/useAuthUser' import type { FileUid } from '../../files/files.types' @@ -42,7 +42,7 @@ import { runWorkflow, } from '../workflows.api' import type { App, InputOutput, IWorkflow, Stage, WorkflowMeta } from '../workflows.types' -import { StyledAnalysisName, StyledStageHeader, WorkflowConfiguration } from './styles' +import { StyledAnalysisName, StyledStageHeader, WorkflowConfiguration } from './workflows-run.styles' export interface RunWorkflowFormType { analysisName: string diff --git a/packages/client/src/features/workflows/run/styles.ts b/packages/client/src/features/workflows/run/workflows-run.styles.ts similarity index 100% rename from packages/client/src/features/workflows/run/styles.ts rename to packages/client/src/features/workflows/run/workflows-run.styles.ts diff --git a/packages/client/src/features/workflows/useCreateWorkflowModal.tsx b/packages/client/src/features/workflows/useCreateWorkflowModal.tsx index f188acbba..1ad7dc109 100644 --- a/packages/client/src/features/workflows/useCreateWorkflowModal.tsx +++ b/packages/client/src/features/workflows/useCreateWorkflowModal.tsx @@ -5,7 +5,7 @@ import { Button } from '@/components/Button' import { FieldGroup } from '@/components/form/FieldGroup' import { InputText } from '@/components/InputText' import { ModalHeaderTop, ModalNext } from '../modal/ModalNext' -import { ButtonRow, Footer } from '../modal/styles' +import { ButtonRow, Footer } from '../modal/modal.styles' import { useModal } from '../modal/useModal' import { createWorkflowRequest } from './workflows.api' diff --git a/packages/client/src/hooks/useMutationErrorEffect.ts b/packages/client/src/hooks/useMutationErrorEffect.ts index 05d4dff48..386a1b790 100644 --- a/packages/client/src/hooks/useMutationErrorEffect.ts +++ b/packages/client/src/hooks/useMutationErrorEffect.ts @@ -1,21 +1,23 @@ import { useEffect } from 'react' -import { FieldValues, Path, UseFormSetError } from 'react-hook-form' -import { MutationErrors } from '../types/utils' +import type { FieldValues, Path, UseFormSetError } from 'react-hook-form' +import type { MutationErrors } from '@/types/utils' -export function formatMutationErrors( - obj?: Record, -): MutationErrors | undefined { +export function formatMutationErrors(obj?: Record): MutationErrors | undefined { const nObj = obj if (nObj) { return { errors: [], - fieldErrors: Object.keys(nObj).length > 0 ? ({ ...nObj }) : {}, + fieldErrors: Object.keys(nObj).length > 0 ? { ...nObj } : {}, } } return undefined } -export const useMutationErrorEffect = (setError: UseFormSetError, mutationErrors?: MutationErrors) => useEffect(() => { +export const useMutationErrorEffect = ( + setError: UseFormSetError, + mutationErrors?: MutationErrors, +) => + useEffect(() => { if (mutationErrors) { Object.keys(mutationErrors.fieldErrors).forEach((e: string) => { setError(e as Path, { message: mutationErrors.fieldErrors[e].join('; '), type: 'onChange' }) diff --git a/packages/client/src/hooks/usePageMeta.tsx b/packages/client/src/hooks/usePageMeta.tsx index dc36d4ae7..3b1402f59 100644 --- a/packages/client/src/hooks/usePageMeta.tsx +++ b/packages/client/src/hooks/usePageMeta.tsx @@ -1,12 +1,15 @@ import { useEffect } from 'react' +import { applyPageMeta, PAGE_META, type PageMetaInput } from '@/lib/pageMeta' -const defaultDescription = 'Advancing regulatory standards for bioinformatics, RWD, and AI, through community-sourced science.' +export type UsePageMetaOptions = PageMetaInput -export const usePageMeta = ({ title = 'PFDA', description = defaultDescription }: { title?: string; description?: string }) => { +export const usePageMeta = ({ + title = PAGE_META.defaultTitle, + description = PAGE_META.defaultDescription, + imagePath, + url, +}: UsePageMetaOptions = {}) => { useEffect(() => { - if (document) { - document.title = title - document.querySelector("meta[name='description']")?.setAttribute('content', description) - } - }, [title, description]) + applyPageMeta({ title, description, imagePath, url }) + }, [title, description, imagePath, url]) } diff --git a/packages/client/src/hooks/useRailsFlashMessages.ts b/packages/client/src/hooks/useRailsFlashMessages.ts new file mode 100644 index 000000000..c28f7a945 --- /dev/null +++ b/packages/client/src/hooks/useRailsFlashMessages.ts @@ -0,0 +1,28 @@ +import { useEffect } from 'react' +import { displayPayloadMessage, type Payload } from '@/utils/api' + +export function useRailsFlashMessages() { + useEffect(() => { + let isCancelled = false + + const fetchFlashMessages = async () => { + try { + const response = await fetch('/api/flash_messages', { credentials: 'same-origin' }) + if (!response.ok) return + + const payload: Payload = await response.json() + if (!isCancelled) { + displayPayloadMessage(payload) + } + } catch (error) { + console.error('Failed to fetch Rails flash messages', error) + } + } + + void fetchFlashMessages() + + return () => { + isCancelled = true + } + }, []) +} diff --git a/packages/client/src/index.html b/packages/client/src/index.html deleted file mode 100644 index d16e39169..000000000 --- a/packages/client/src/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - pFDA - - - -
- - diff --git a/packages/client/src/index.tsx b/packages/client/src/index.tsx index 69dd1ae0c..46070ba00 100644 --- a/packages/client/src/index.tsx +++ b/packages/client/src/index.tsx @@ -6,8 +6,9 @@ import { loadRuntimeEnv } from '@/utils/runtimeEnv' import './styles/tailwind.css' import './styles/variables.css' import './styles/app-globals.css' +import { applyPageMeta } from '@/lib/pageMeta' import Root from './routes/root' -import { getAuthenticityToken } from './utils/api' +import { getCsrfToken } from './utils/csrf' async function enableMocking() { if (!ENABLE_DEV_MSW) { @@ -26,20 +27,34 @@ async function enableMocking() { }) } -Axios.defaults.headers.common['X-CSRF-Token'] = getAuthenticityToken() +Axios.interceptors.request.use(async config => { + const method = config.method?.toLowerCase() + if (method && !['get', 'head', 'options'].includes(method)) { + const token = await getCsrfToken() + if (token) { + config.headers['X-CSRF-Token'] = token + } + } + return config +}) const renderApp = () => { + applyPageMeta() + const container = document.getElementById('app-root') - const root = createRoot(container!) + if (!container) { + return + } - if (container) { - ReactModal.setAppElement('#app-root') - loadRuntimeEnv().then(() => { + const root = createRoot(container) + ReactModal.setAppElement('#app-root') + loadRuntimeEnv().then(() => { + getCsrfToken().then(() => { enableMocking().then(() => { root.render() }) }) - } + }) } document.addEventListener('DOMContentLoaded', renderApp) document.addEventListener('page:load', renderApp) diff --git a/packages/client/src/lib/pageMeta.ts b/packages/client/src/lib/pageMeta.ts new file mode 100644 index 000000000..14b74879d --- /dev/null +++ b/packages/client/src/lib/pageMeta.ts @@ -0,0 +1,85 @@ +export const PAGE_META = { + siteName: 'precisionFDA', + defaultTitle: 'precisionFDA', + defaultDescription: + 'A secure, collaborative, cloud-based high-performance computing environment advancing regulatory science and AI innovation for the FDA.', + imageFile: 'og-image.png', + type: 'website', + locale: 'en_US', + twitterCard: 'summary_large_image', +} as const + +export type PageMetaInput = { + title?: string + description?: string + imagePath?: string + url?: string +} + +const metaAttribute = (attribute: 'name' | 'property', key: string): string => `meta[${attribute}="${key}"]` + +const setMetaContent = (attribute: 'name' | 'property', key: string, content: string): void => { + if (typeof document === 'undefined') { + return + } + + let element = document.querySelector(metaAttribute(attribute, key)) + if (!element) { + element = document.createElement('meta') + element.setAttribute(attribute, key) + document.head.appendChild(element) + } + element.setAttribute('content', content) +} + +export const resolveAssetUrl = (path: string): string => { + const base = import.meta.env.BASE_URL || '/' + const normalizedBase = base.endsWith('/') ? base : `${base}/` + const normalizedPath = path.startsWith('/') ? path.slice(1) : path + return new URL(`${normalizedBase}${normalizedPath}`, window.location.origin).href +} + +export const resolvePageMeta = ({ + title = PAGE_META.defaultTitle, + description = PAGE_META.defaultDescription, + imagePath = PAGE_META.imageFile, + url, +}: PageMetaInput = {}) => { + const pageUrl = url ?? (typeof window !== 'undefined' ? window.location.href : undefined) + + return { + title, + description, + imageUrl: typeof window !== 'undefined' ? resolveAssetUrl(imagePath) : undefined, + url: pageUrl, + } +} + +export const applyPageMeta = (input: PageMetaInput = {}): void => { + if (typeof document === 'undefined') { + return + } + + const { title, description, imageUrl, url } = resolvePageMeta(input) + + document.title = title + + setMetaContent('name', 'description', description) + setMetaContent('property', 'og:title', title) + setMetaContent('property', 'og:description', description) + setMetaContent('property', 'og:site_name', PAGE_META.siteName) + setMetaContent('property', 'og:type', PAGE_META.type) + setMetaContent('property', 'og:locale', PAGE_META.locale) + setMetaContent('name', 'twitter:card', PAGE_META.twitterCard) + setMetaContent('name', 'twitter:title', title) + setMetaContent('name', 'twitter:description', description) + + if (imageUrl) { + setMetaContent('property', 'og:image', imageUrl) + setMetaContent('name', 'twitter:image', imageUrl) + } + + if (url) { + setMetaContent('property', 'og:url', url) + } +} diff --git a/packages/client/src/mocks/handlers/assets.handlers.ts b/packages/client/src/mocks/handlers/assets.handlers.ts index e064256d3..d86c799ee 100644 --- a/packages/client/src/mocks/handlers/assets.handlers.ts +++ b/packages/client/src/mocks/handlers/assets.handlers.ts @@ -1,6 +1,6 @@ -import { http, HttpResponse } from 'msw' -import { IAsset } from '../../features/assets/assets.types' -import { Asset } from '../../features/actionModals/AttachToModal/useListAssetsQuery' +import { HttpResponse, http } from 'msw' +import type { Asset } from '../../features/actionModals/AttachToModal/useListAssetsQuery' +import type { IAsset } from '../../features/assets/assets.types' // Mock asset data for useSelectAssetModal (IAsset interface) export const mockSelectAssets: IAsset[] = [ @@ -191,7 +191,8 @@ export const mockAttachAssets: Asset[] = [ prefix: 'asset', description: 'A comprehensive guide for project documentation', file_paths: ['/assets/documentation-guide.md'], - content: '# Documentation Guide\n\nThis is a comprehensive guide for creating and maintaining project documentation.\n\n## Getting Started\n\n1. Create clear headings\n2. Use bullet points for lists\n3. Include code examples\n\n```javascript\nconst example = "Hello World";\nconsole.log(example);\n```\n\n## Best Practices\n\n- Keep it simple and clear\n- Update regularly\n- Include examples', + content: + '# Documentation Guide\n\nThis is a comprehensive guide for creating and maintaining project documentation.\n\n## Getting Started\n\n1. Create clear headings\n2. Use bullet points for lists\n3. Include code examples\n\n```javascript\nconst example = "Hello World";\nconsole.log(example);\n```\n\n## Best Practices\n\n- Keep it simple and clear\n- Update regularly\n- Include examples', }, { id: 2, @@ -215,7 +216,8 @@ export const mockAttachAssets: Asset[] = [ prefix: 'asset', description: 'Complete API documentation and reference', file_paths: ['/assets/api-reference.md'], - content: '# API Reference\n\n## Authentication\n\nAll API requests require authentication using an API key.\n\n```bash\ncurl -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/endpoint\n```\n\n## Endpoints\n\n### GET /api/users\n\nRetrieve a list of users.\n\n**Response:**\n```json\n{\n "users": [\n {\n "id": 1,\n "name": "John Doe",\n "email": "john@example.com"\n }\n ]\n}\n```', + content: + '# API Reference\n\n## Authentication\n\nAll API requests require authentication using an API key.\n\n```bash\ncurl -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/endpoint\n```\n\n## Endpoints\n\n### GET /api/users\n\nRetrieve a list of users.\n\n**Response:**\n```json\n{\n "users": [\n {\n "id": 1,\n "name": "John Doe",\n "email": "john@example.com"\n }\n ]\n}\n```', }, { id: 3, @@ -239,7 +241,8 @@ export const mockAttachAssets: Asset[] = [ prefix: 'asset', description: 'Template for application configuration files', file_paths: ['/assets/configuration-template.md'], - content: '# Configuration Template\n\nUse this template to configure your application.\n\n## Environment Variables\n\n```env\nDATABASE_URL=postgresql://localhost:5432/mydb\nAPP_SECRET=your-secret-key\nPORT=3000\n```\n\n## Configuration File\n\n```yaml\nserver:\n port: 3000\n host: localhost\n\ndatabase:\n url: postgresql://localhost:5432/mydb\n pool_size: 10\n\nlogging:\n level: info\n format: json\n```', + content: + '# Configuration Template\n\nUse this template to configure your application.\n\n## Environment Variables\n\n```env\nDATABASE_URL=postgresql://localhost:5432/mydb\nAPP_SECRET=your-secret-key\nPORT=3000\n```\n\n## Configuration File\n\n```yaml\nserver:\n port: 3000\n host: localhost\n\ndatabase:\n url: postgresql://localhost:5432/mydb\n pool_size: 10\n\nlogging:\n level: info\n format: json\n```', }, { id: 4, @@ -263,7 +266,8 @@ export const mockAttachAssets: Asset[] = [ prefix: 'asset', description: 'Basic tutorial for new users', file_paths: ['/assets/tutorial-basics.md'], - content: '# Getting Started Tutorial\n\nWelcome to our platform! This tutorial will guide you through the basics.\n\n## Step 1: Setup\n\nFirst, make sure you have all the prerequisites installed:\n\n- Node.js (v16 or higher)\n- npm or yarn\n- Git\n\n## Step 2: Installation\n\n```bash\nnpm install\nnpm start\n```\n\n## Step 3: Your First Project\n\nCreate your first project by following these steps...', + content: + '# Getting Started Tutorial\n\nWelcome to our platform! This tutorial will guide you through the basics.\n\n## Step 1: Setup\n\nFirst, make sure you have all the prerequisites installed:\n\n- Node.js (v16 or higher)\n- npm or yarn\n- Git\n\n## Step 2: Installation\n\n```bash\nnpm install\nnpm start\n```\n\n## Step 3: Your First Project\n\nCreate your first project by following these steps...', }, ] @@ -291,7 +295,11 @@ export const assetsHandlers = [ scope: 'private', space_id: null, locked: false, - origin: { href: '/home/assets/file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1', fa: 'fa fa-file-zip-o fa-fw', text: ' shoudFail' }, + origin: { + href: '/home/assets/file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1', + fa: 'fa fa-file-zip-o fa-fw', + text: ' shoudFail', + }, tags: ['tags', 'are', 'cool'], uid: 'file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1', file_size: '190 Bytes', @@ -303,7 +311,6 @@ export const assetsHandlers = [ user: '/users/minch.yoda', track: '/track?id=file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1', download_list: '/api/files/download_list', - add_file: '/api/create_file', add_folder: '/api/files/create_folder', update: '/api/assets/file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1', download: '/api/files/file-GBKx2kj0JqyZgZGbK9bVZ7jJ-1/download', @@ -340,14 +347,14 @@ export const assetsHandlers = [ uid: 'file-GBPj0980JqyVVyk9699jY41p-1', file_size: '10 KB', created_at_date_time: '2022-06-07 18:43:17 CEST', - description: '# Testing asset content\nThis content was created for testing purposes.\n\nThanks for reaching out!\n', + description: + '# Testing asset content\nThis content was created for testing purposes.\n\nThanks for reaching out!\n', links: { origin_object: { origin_type: 'Asset', origin_uid: 'file-GBPj0980JqyVVyk9699jY41p-1' }, show: '/api/assets/file-GBPj0980JqyVVyk9699jY41p-1', user: '/users/minch.yoda', track: '/track?id=file-GBPj0980JqyVVyk9699jY41p-1', download_list: '/api/files/download_list', - add_file: '/api/create_file', add_folder: '/api/files/create_folder', update: '/api/assets/file-GBPj0980JqyVVyk9699jY41p-1', download: '/api/files/file-GBPj0980JqyVVyk9699jY41p-1/download', @@ -373,20 +380,20 @@ export const assetsHandlers = [ { status: 200 }, ), ), - + // Handler for /api/list_assets (used by useSelectAssetModal and useAssetAttachModal) http.post('/api/list_assets', async ({ request }) => { - const body = await request.json().catch(() => ({})) as Record - + const body = (await request.json().catch(() => ({}))) as Record + // If request has scopes/search_string/states, return IAsset[] format (useSelectAssetModal) if (body && ('scopes' in body || 'search_string' in body || 'states' in body)) { return HttpResponse.json(mockSelectAssets) } - + // Otherwise return Asset[] format (useAssetAttachModal) return HttpResponse.json(mockAttachAssets) }), - + // Handler for /api/assets/delete (used by useDeleteModal) http.post('/api/assets/delete', () => HttpResponse.json({ diff --git a/packages/client/src/mocks/handlers/files.handlers.ts b/packages/client/src/mocks/handlers/files.handlers.ts index 0c7305c6e..fcc81a606 100644 --- a/packages/client/src/mocks/handlers/files.handlers.ts +++ b/packages/client/src/mocks/handlers/files.handlers.ts @@ -386,9 +386,7 @@ export const filesMocks = [ }), ), - http.post('/api/list_files', () => - HttpResponse.json(mockCopyFiles), - ), + http.post('/api/list_files', () => HttpResponse.json(mockCopyFiles)), http.post('/api/files/copy', () => HttpResponse.json({ meta: { diff --git a/packages/client/src/pages/AboutPage/index.tsx b/packages/client/src/pages/AboutPage/index.tsx index 614f91390..c59b29c2e 100644 --- a/packages/client/src/pages/AboutPage/index.tsx +++ b/packages/client/src/pages/AboutPage/index.tsx @@ -1,12 +1,13 @@ import { useState } from 'react' +import betaReleaseTimeline from '../../assets/beta-release.png' import { Button } from '../../components/Button' import NavigationBar from '../../components/NavigationBar/NavigationBar' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' import { PfTab, PfTabContent, PfTabRow, PfTabTitle } from '../../components/Tabs/PfTab' import { useAuthUser } from '../../features/auth/useAuthUser' import { usePageMeta } from '../../hooks/usePageMeta' import PublicLayout from '../../layouts/PublicLayout' -import { RichText } from '../styles' +import { RichText } from '../pages.styles' //TODO JIRI: TO BE DELETED COMPLETELY @@ -73,7 +74,7 @@ const AboutPage = () => {

- Beta release Timeline: Beta launch on Dec 2015 + Beta release Timeline: Beta launch on Dec 2015

diff --git a/packages/client/src/pages/Account/Notifications/index.tsx b/packages/client/src/pages/Account/Notifications/index.tsx index a3b3a42ed..b689fefdb 100644 --- a/packages/client/src/pages/Account/Notifications/index.tsx +++ b/packages/client/src/pages/Account/Notifications/index.tsx @@ -2,10 +2,10 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { Controller, type Path, type PathValue, useForm } from 'react-hook-form' import { Button } from '@/components/Button' import { Checkbox } from '@/components/CheckboxNext' -import { FieldLabelRow } from '@/components/form/styles' +import { FieldLabelRow } from '@/components/form/form.styles' import { Loader } from '@/components/Loader' import { toastSuccess } from '@/components/NotificationCenter/ToastHelper' -import { PageActions, PageHeader, PageTitle } from '@/components/Page/styles' +import { PageActions, PageHeader, PageTitle } from '@/components/Page/page.styles' import { usePageMeta } from '@/hooks/usePageMeta' import { fetchNotificationsPreferences, saveNotificationsPreferences } from './api' import { @@ -16,7 +16,7 @@ import { SectionTitleSmall, StyledNotifications, StyledPageContainer, -} from './styles' +} from './notifications.styles' import type { AllNotification, NotificationPreferences } from './types' type NotificationLabelType = Record diff --git a/packages/client/src/pages/Account/Notifications/styles.ts b/packages/client/src/pages/Account/Notifications/notifications.styles.ts similarity index 98% rename from packages/client/src/pages/Account/Notifications/styles.ts rename to packages/client/src/pages/Account/Notifications/notifications.styles.ts index 822021178..c9a14883b 100644 --- a/packages/client/src/pages/Account/Notifications/styles.ts +++ b/packages/client/src/pages/Account/Notifications/notifications.styles.ts @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { PageContainer, pagePadding } from '../../../components/Page/styles' +import { PageContainer, pagePadding } from '../../../components/Page/page.styles' export const StyledNotifications = styled.div` display: flex; diff --git a/packages/client/src/pages/NoFoundPage/index.tsx b/packages/client/src/pages/NoFoundPage/index.tsx index 3680a2511..c6fecbbeb 100644 --- a/packages/client/src/pages/NoFoundPage/index.tsx +++ b/packages/client/src/pages/NoFoundPage/index.tsx @@ -1,7 +1,7 @@ import React from 'react' import styled from 'styled-components' import { UserLayout } from '../../layouts/UserLayout' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' const Text = styled.div` text-align: center; diff --git a/packages/client/src/pages/Security/index.tsx b/packages/client/src/pages/Security/index.tsx index 47628809e..d7373cbdf 100644 --- a/packages/client/src/pages/Security/index.tsx +++ b/packages/client/src/pages/Security/index.tsx @@ -1,11 +1,11 @@ import React from 'react' import { Link } from 'react-router' import styled from 'styled-components' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' import { useAuthUser } from '../../features/auth/useAuthUser' import NavigationBar from '../../components/NavigationBar/NavigationBar' import PublicLayout from '../../layouts/PublicLayout' -import { RichText } from '../styles' +import { RichText } from '../pages.styles' const StyledRichText = styled(RichText)` padding-top: 32px; diff --git a/packages/client/src/pages/ToS/index.tsx b/packages/client/src/pages/ToS/index.tsx index 7a74c90a7..0592e73a0 100644 --- a/packages/client/src/pages/ToS/index.tsx +++ b/packages/client/src/pages/ToS/index.tsx @@ -1,10 +1,10 @@ import React from 'react' import styled from 'styled-components' -import { PageContainerMargin } from '../../components/Page/styles' +import { PageContainerMargin } from '../../components/Page/page.styles' import { useAuthUser } from '../../features/auth/useAuthUser' import NavigationBar from '../../components/NavigationBar/NavigationBar' import PublicLayout from '../../layouts/PublicLayout' -import { RichText } from '../styles' +import { RichText } from '../pages.styles' const StyledRichText = styled(RichText)` padding-top: 32px; diff --git a/packages/client/src/pages/styles.tsx b/packages/client/src/pages/pages.styles.tsx similarity index 100% rename from packages/client/src/pages/styles.tsx rename to packages/client/src/pages/pages.styles.tsx diff --git a/packages/client/src/routes/account/index.tsx b/packages/client/src/routes/account/index.tsx index 2e1476dcc..b3416948a 100644 --- a/packages/client/src/routes/account/index.tsx +++ b/packages/client/src/routes/account/index.tsx @@ -1,26 +1,46 @@ +import React from 'react' import { Navigate, Outlet } from 'react-router' import { AccountLayout } from '@/features/account/AccountLayout' -import { AccountSettings } from '@/features/account/AccountSettings' -import { ApiKeys } from '@/features/account/ApiKeys' -import { CloudResources } from '@/features/account/CloudResources' -import { Dashboard } from '@/features/account/Dashboard' -import { Licenses } from '@/features/account/Licenses' -import { ActivityReportsPage } from '@/features/admin/activity-reports/ActivityReportsPage' -import { AlertsPage } from '@/features/admin/alerts/AlertsPage' -import { AdminDashboard } from '@/features/admin/dashboard/Dashboard' -import { InvitationsList } from '@/features/admin/invitations' -import { ProvisioningList } from '@/features/admin/invitations/ProvisioningList' -import AdminMembershipsPage from '@/features/admin/memberships' -import { SpacesList } from '@/features/admin/spaces' -import { AdminUsersLayout } from '@/features/admin/users/AdminUsersLayout' import { useAuthUser } from '@/features/auth/useAuthUser' import { LayoutLoader } from '@/layouts/UserLayout' -import PendingUsersList from '../../features/admin/pendingUsers' -import UsersList from '../../features/admin/users' -import CreateNewsItemPage from '../../features/news/form/CreateNewsItemPage' -import EditNewsItemPage from '../../features/news/form/EditNewsItemPage' -import ListAdminNews from '../../features/news/ListAdminNews' -import NotificationsPage from '../../pages/Account/Notifications' + +const AccountSettings = React.lazy(() => + import('@/features/account/AccountSettings').then(m => ({ default: m.AccountSettings })), +) +const ApiKeys = React.lazy(() => import('@/features/account/ApiKeys').then(m => ({ default: m.ApiKeys }))) +const CloudResources = React.lazy(() => + import('@/features/account/CloudResources').then(m => ({ default: m.CloudResources })), +) +const Dashboard = React.lazy(() => import('@/features/account/Dashboard').then(m => ({ default: m.Dashboard }))) +const Licenses = React.lazy(() => import('@/features/account/Licenses').then(m => ({ default: m.Licenses }))) +const ActivityReportsPage = React.lazy(() => + import('@/features/admin/activity-reports/ActivityReportsPage').then(m => ({ + default: m.ActivityReportsPage, + })), +) +const AlertsPage = React.lazy(() => import('@/features/admin/alerts/AlertsPage').then(m => ({ default: m.AlertsPage }))) +const AdminDashboard = React.lazy(() => + import('@/features/admin/dashboard/Dashboard').then(m => ({ default: m.AdminDashboard })), +) +const InvitationsList = React.lazy(() => + import('@/features/admin/invitations').then(m => ({ default: m.InvitationsList })), +) +const ProvisioningList = React.lazy(() => + import('@/features/admin/invitations/ProvisioningList').then(m => ({ + default: m.ProvisioningList, + })), +) +const AdminMembershipsPage = React.lazy(() => import('@/features/admin/memberships')) +const SpacesList = React.lazy(() => import('@/features/admin/spaces').then(m => ({ default: m.SpacesList }))) +const AdminUsersLayout = React.lazy(() => + import('@/features/admin/users/AdminUsersLayout').then(m => ({ default: m.AdminUsersLayout })), +) +const PendingUsersList = React.lazy(() => import('../../features/admin/pendingUsers')) +const UsersList = React.lazy(() => import('../../features/admin/users')) +const CreateNewsItemPage = React.lazy(() => import('../../features/news/form/CreateNewsItemPage')) +const EditNewsItemPage = React.lazy(() => import('../../features/news/form/EditNewsItemPage')) +const ListAdminNews = React.lazy(() => import('../../features/news/ListAdminNews')) +const NotificationsPage = React.lazy(() => import('../../pages/Account/Notifications')) const AdminRouteGuard = () => { const { user, loading } = useAuthUser(true) @@ -41,36 +61,36 @@ const accountRoutes = [ element: , children: [ { index: true, element: }, - { path: 'dashboard', element: }, - { path: 'cloud-resources', element: }, - { path: 'notifications', element: }, - { path: 'settings', element: }, - { path: 'licenses', element: }, - { path: 'api-keys', element: }, + { path: 'dashboard', Component: Dashboard }, + { path: 'cloud-resources', Component: CloudResources }, + { path: 'notifications', Component: NotificationsPage }, + { path: 'settings', Component: AccountSettings }, + { path: 'licenses', Component: Licenses }, + { path: 'api-keys', Component: ApiKeys }, { path: 'admin', element: , children: [ - { index: true, element: }, - { path: 'alerts', element: }, + { index: true, Component: AdminDashboard }, + { path: 'alerts', Component: AlertsPage }, { path: 'users', - element: , + Component: AdminUsersLayout, children: [ - { index: true, element: }, - { path: 'invitations', element: }, - { path: 'invitations/provisioning', element: }, - { path: 'pending', element: }, - { path: 'memberships', element: }, + { index: true, Component: UsersList }, + { path: 'invitations', Component: InvitationsList }, + { path: 'invitations/provisioning', Component: ProvisioningList }, + { path: 'pending', Component: PendingUsersList }, + { path: 'memberships', Component: AdminMembershipsPage }, ], }, { path: 'invitations', element: }, - { path: 'spaces', element: }, - { path: 'activity-reports', element: }, + { path: 'spaces', Component: SpacesList }, + { path: 'activity-reports', Component: ActivityReportsPage }, { path: 'invitations/provisioning', element: }, - { path: 'news', element: }, - { path: 'news/create', element: }, - { path: 'news/:id/edit', element: }, + { path: 'news', Component: ListAdminNews }, + { path: 'news/create', Component: CreateNewsItemPage }, + { path: 'news/:id/edit', Component: EditNewsItemPage }, ], }, ], diff --git a/packages/client/src/routes/resource-pages.tsx b/packages/client/src/routes/resource-pages.tsx index b4212e183..bb823c701 100644 --- a/packages/client/src/routes/resource-pages.tsx +++ b/packages/client/src/routes/resource-pages.tsx @@ -1,13 +1,12 @@ import React from 'react' import { Navigate, useLocation, useOutletContext, useParams, useSearchParams } from 'react-router' -import { Markdown } from '@/components/Markdown' -import { AppShowOutletContext } from '@/features/apps/AppsShow' -import { StyledMarkdownAppShow } from '@/features/apps/form/styles' +import type { AppShowOutletContext } from '@/features/apps/AppsShow' +import { StyledMarkdownAppShow } from '@/features/apps/form/apps-form.styles' import { useAuthUser } from '@/features/auth/useAuthUser' -import { HomeScopeContextValue, useHomeScope } from '@/features/home/HomeScopeContext' +import { type HomeScopeContextValue, useHomeScope } from '@/features/home/HomeScopeContext' import { isContributorOrHigherRole } from '@/features/spaces/common' -import { ISpace } from '@/features/spaces/spaces.types' -import { SpaceOutletContext } from './spaces' +import type { ISpace } from '@/features/spaces/spaces.types' +import type { SpaceOutletContext } from './spaces' const MembersList = React.lazy(() => import('../features/spaces/members/MembersList').then(m => ({ default: m.MembersList })), @@ -63,6 +62,7 @@ const SpaceReportList = React.lazy(() => const TrackInHome = React.lazy(() => import('../features/tracks/TrackInHome').then(m => ({ default: m.TrackInHome }))) const FileList = React.lazy(() => import('../features/files/FileList').then(m => ({ default: m.FileList }))) const FileShow = React.lazy(() => import('../features/files/show/FileShow').then(m => ({ default: m.FileShow }))) +const Markdown = React.lazy(() => import('@/components/Markdown').then(m => ({ default: m.Markdown }))) /** * Result of useUnifiedRouteContext when in home context. diff --git a/packages/client/src/routes/root.tsx b/packages/client/src/routes/root.tsx index 4a32095b5..c274c6e34 100644 --- a/packages/client/src/routes/root.tsx +++ b/packages/client/src/routes/root.tsx @@ -1,8 +1,6 @@ -import React, { useEffect, useState } from 'react' +import React, { useEffect } from 'react' import 'react-tooltip/dist/react-tooltip.css' -import { TanStackDevtools } from '@tanstack/react-devtools' import { QueryClientProvider } from '@tanstack/react-query' -import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools' import { createBrowserRouter, Navigate, Outlet, useLocation } from 'react-router' import { RouterProvider } from 'react-router/dom' import { AlertDismissedProvider } from '@/features/admin/alerts/useAlertDismissedLocalStorage' @@ -10,6 +8,7 @@ import { ExpiringSessionModal } from '@/features/auth/ExpiringSessionModal' import { SessionExpiredModal } from '@/features/auth/SessionExpiredModal' import { FileUploadModalProvider } from '@/features/files/actionModals/useFileUploadModal' import { useModal } from '@/features/modal/useModal' +import { useRailsFlashMessages } from '@/hooks/useRailsFlashMessages' import { LayoutLoader, UserLayout } from '@/layouts/UserLayout' import { OnlineStatusProvider } from '@/utils/OnlineStatusContext' import { PFDAToastContainer } from '@/utils/PFDAToastContainer' @@ -17,15 +16,25 @@ import queryClientInstance, { setAuthFailureCallback } from '@/utils/queryClient import { ThemeProvider } from '@/utils/ThemeContext' import AuthWall from '../AuthWall' import Header from '../components/Header/Header' -import HomeShowLayout from '../features/home/HomeShowLayout' -import RequestAccessPage from '../features/request-access/RequestAccessPage' import NoFoundPage from '../pages/NoFoundPage' import GlobalStyle from '../styles/global' import accountRoutes from './account' import { homeRoutes } from './home' import spacesRoutes from './spaces' +const Noop = (): null => null + +const TanStackDevtools = import.meta.env.DEV + ? React.lazy(() => import('@tanstack/react-devtools').then(m => ({ default: m.TanStackDevtools }))) + : Noop + +const ReactQueryDevtoolsPanel = import.meta.env.DEV + ? React.lazy(() => import('@tanstack/react-query-devtools').then(m => ({ default: m.ReactQueryDevtoolsPanel }))) + : Noop + const DataPortalRoutes = React.lazy(() => import('../features/data-portals/routes')) +const HomeShowLayout = React.lazy(() => import('../features/home/HomeShowLayout')) +const RequestAccessPage = React.lazy(() => import('../features/request-access/RequestAccessPage')) const ExpertsSinglePage = React.lazy(() => import('../features/experts/details/index')) const EditChallengePage = React.lazy(() => import('../features/challenges/form/EditChallengePage')) const ChallengeDetailsLayout = React.lazy(() => import('../features/challenges/details/ChallengeDetailsLayout')) @@ -61,23 +70,16 @@ const AdminRouteRedirect = () => { const RootComponent = () => { const sessionExpiredModal = useModal() const expiringSessionModal = useModal() - const [railsAlertHeight, setRailsAlertHeight] = useState(0) useEffect(() => { setAuthFailureCallback(() => sessionExpiredModal.setShowModal(true)) }, []) - useEffect(() => { - // Calculate the height of the rails-alert element - const alertElement = document.querySelector('.rails-alert') - if (alertElement) { - setRailsAlertHeight(alertElement.clientHeight as number) - } - }, []) + useRailsFlashMessages() return ( - + @@ -89,14 +91,16 @@ const RootComponent = () => { - , - }, - ]} - /> + + , + }, + ]} + /> + diff --git a/packages/client/src/stories/styles.ts b/packages/client/src/stories/stories.styles.ts similarity index 100% rename from packages/client/src/stories/styles.ts rename to packages/client/src/stories/stories.styles.ts diff --git a/packages/client/src/styles/tailwind.css b/packages/client/src/styles/tailwind.css index 0941140b5..08e2c8b59 100644 --- a/packages/client/src/styles/tailwind.css +++ b/packages/client/src/styles/tailwind.css @@ -1,5 +1,3 @@ -@import "@fontsource/lato/100.css"; -@import "@fontsource/lato/100-italic.css"; @import "@fontsource/lato/300.css"; @import "@fontsource/lato/300-italic.css"; @import "@fontsource/lato/400.css"; diff --git a/packages/client/src/utils/api.ts b/packages/client/src/utils/api.ts index 28ff7d399..8ee54923d 100644 --- a/packages/client/src/utils/api.ts +++ b/packages/client/src/utils/api.ts @@ -1,10 +1,11 @@ import axios from 'axios' -import { toastError, toastSuccess, toastWarning } from '../components/NotificationCenter/ToastHelper' +import { toastError, toastInfo, toastSuccess, toastWarning } from '../components/NotificationCenter/ToastHelper' export enum MESSAGE_TYPE { SUCCESS = 'success', WARNING = 'warning', ERROR = 'error', + INFO = 'info', } interface PayloadMessage { @@ -23,44 +24,55 @@ export interface Payload { } } -export const displayPayloadMessage = (payload: Payload) => { - // The response messaging from the API is a bit eclectic, as seen with the following scenarios that - // we've seen (so far). Thus this function needs to be able to handle the delivery of messages to - // the user under all scenarios. - // - // In general: { message: { type: "success", text: "hello" }} - // /api/files/copy: { message: { type: "success", text: ["hello1", ... ]}} - // /api/spaces/{id}/files/move_nodes: { meta: { messages: [ { type: "success", message: "hello" }, ... ]}} +const getMessageTexts = (message: PayloadMessage): string[] => { + const text = message.text ?? message.message + if (Array.isArray(text)) return text.filter(Boolean) + return text ? [text] : [] +} - // TODO: consolidate backend message format, perhaps making messages a string[] for all responses +const displayMessage = (message: PayloadMessage) => { + const texts = getMessageTexts(message) - const message = Array.isArray(payload.meta?.messages) ? payload.meta.messages[0] : payload.message - if (message) { - const errorMessage = Array.isArray(message.text) ? message.text[0] : (message.text ?? message.message) - console.log(errorMessage) + texts.forEach(text => { switch (message.type) { case MESSAGE_TYPE.SUCCESS: - toastSuccess(errorMessage) + toastSuccess(text) break case MESSAGE_TYPE.WARNING: - toastWarning(errorMessage) + toastWarning(text) + break + case MESSAGE_TYPE.INFO: + toastInfo(text) break case MESSAGE_TYPE.ERROR: - toastError(errorMessage) + toastError(text) break default: break } + }) +} + +export const displayPayloadMessage = (payload: Payload) => { + // The response messaging from the API is a bit eclectic, as seen with the following scenarios that + // we've seen (so far). Thus this function needs to be able to handle the delivery of messages to + // the user under all scenarios. + // + // In general: { message: { type: "success", text: "hello" }} + // /api/files/copy: { message: { type: "success", text: ["hello1", ... ]}} + // /api/spaces/{id}/files/move_nodes: { meta: { messages: [ { type: "success", message: "hello" }, ... ]}} + + // TODO: consolidate backend message format, perhaps making messages a string[] for all responses + + if (Array.isArray(payload.meta?.messages) && payload.meta.messages.length > 0) { + payload.meta.messages.forEach(displayMessage) + } else if (payload.message) { + displayMessage(payload.message) } else if (payload.error) { toastError(payload.error.message) } } -export const getAuthenticityToken = () => { - const CSRFHolder = document.getElementsByName('csrf-token')[0] as HTMLMetaElement - return CSRFHolder ? CSRFHolder.content : null -} - export const refreshSession = async (): Promise => { return axios.get('/api/v2/session/refresh').then(() => {}) } diff --git a/packages/client/src/utils/csrf.ts b/packages/client/src/utils/csrf.ts new file mode 100644 index 000000000..7445651f0 --- /dev/null +++ b/packages/client/src/utils/csrf.ts @@ -0,0 +1,52 @@ +const CSRF_TOKEN_URL = '/api/v2/csrf-token' + +let cachedCsrfToken: string | null = null +let csrfTokenPromise: Promise | null = null + +/** + * Fetch a CSRF token from the server without using the cache. + * Use when a fresh token is required (e.g. end of a long upload). + */ +export async function fetchCsrfToken(): Promise { + try { + const response = await fetch(CSRF_TOKEN_URL, { credentials: 'same-origin' }) + if (!response.ok) return null + const data = await response.json() + return data.token ?? null + } catch { + return null + } +} + +/** + * Return a cached CSRF token, coalescing concurrent cache misses into one request. + */ +export const getCsrfToken = async (): Promise => { + if (cachedCsrfToken) return cachedCsrfToken + if (csrfTokenPromise) return csrfTokenPromise + + csrfTokenPromise = fetchCsrfToken() + .then(token => { + cachedCsrfToken = token + return token + }) + .catch(e => { + console.error('Failed to fetch CSRF token', e) + return null + }) + .finally(() => { + csrfTokenPromise = null + }) + + return csrfTokenPromise +} + +export const clearCsrfToken = (): void => { + cachedCsrfToken = null + csrfTokenPromise = null +} + +export function buildCsrfHeaders(token?: string | null): Record { + if (!token) return {} + return { 'X-CSRF-Token': token } +} diff --git a/packages/client/src/utils/useNumberParams.ts b/packages/client/src/utils/useNumberParams.ts deleted file mode 100644 index bb542d200..000000000 --- a/packages/client/src/utils/useNumberParams.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Params, useParams } from 'react-router' -import { map, when } from 'ramda' - -type RecordUndefinedVal = Record - -export function useNumberParams>(): RecordUndefinedVal { - const params = useParams>() - - const convertedParams = map( - when( - (value) => !Number.isNaN(Number(value)), - Number, - ), - params, - ) - - return convertedParams as RecordUndefinedVal -} diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index f6c6e9dc4..29af0a60a 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -36,8 +36,8 @@ export default defineConfig(({ command, mode }) => { ] return { - // Base path for rails production - chunks will be loaded from /packs/ - base: isProduction ? '/packs/' : '/', + // Base path: defaults to '/'. Set VITE_BASE_PATH='/packs/' when building for Rails. + base: env.VITE_BASE_PATH || '/', resolve: { tsconfigPaths: true, @@ -71,28 +71,146 @@ export default defineConfig(({ command, mode }) => { }, build: { + target: 'es2022', assetsInlineLimit: filePath => (fontAssetPattern.test(filePath) ? false : undefined), - outDir: env.VITE_OUT_DIR || (isProduction ? '../rails/public/packs' : 'dist'), + outDir: env.VITE_OUT_DIR || 'dist', + assetsDir: 'static', emptyOutDir: true, manifest: true, sourcemap: !isProduction, rolldownOptions: { - input: path.resolve(__dirname, 'src/index.tsx'), + // Temporary adding input for transitioning to hosting through nginx. + ...(env.VITE_BASE_PATH && { + input: path.resolve(__dirname, 'src/index.tsx'), + }), output: { format: 'es', entryFileNames: 'bundle-[hash].js', chunkFileNames: '[name]-[hash].js', assetFileNames: assetInfo => { - if (assetInfo.name?.endsWith('.css')) { - return 'bundle-[hash].css' + // names is always a single-element array here + if (assetInfo.names[0]?.endsWith('.css')) { + return '[name]-[hash][extname]' } return '[name][extname]' }, codeSplitting: { + minSize: 10_000, groups: [ { - name: 'vendor', + name: 'vendor-react', test: /node_modules[\\/](react|react-dom|react-router)([\\/]|$)/, + priority: 50, + }, + { + name: 'vendor-tanstack', + test: /node_modules[\\/]@tanstack[\\/]/, + priority: 40, + }, + { + name: 'vendor-forms', + test: /node_modules[\\/](react-hook-form|yup|@hookform)([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-styled', + test: /node_modules[\\/]styled-components([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-axios', + test: /node_modules[\\/]axios([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-select', + test: /node_modules[\\/]react-select([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-charts', + test: /node_modules[\\/]recharts([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-dnd', + test: /node_modules[\\/]@dnd-kit[\\/]/, + priority: 30, + }, + { + name: 'vendor-fp', + test: /node_modules[\\/](lodash|ramda|effect|immer|use-immer)([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-date', + test: /node_modules[\\/](date-fns|@date-fns)([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-icons', + test: /node_modules[\\/]lucide-react([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-ui', + test: /node_modules[\\/](@base-ui|clsx|tailwind-merge|class-variance-authority|dompurify|react-toastify|react-tooltip|react-modal|react-transition-group)([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-prettier', + test: /node_modules[\\/]prettier([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-lexical', + test: /node_modules[\\/](@lexical|lexical)([\\/]|$)/, + priority: 30, + }, + { + name: 'vendor-markdown', + test: /node_modules[\\/](react-markdown|rehype-.*|remark-.*|unified|hast-.*|mdast-.*|micromark.*|vfile|unist-.*)([\\/]|$)/, + priority: 30, + }, + + // ── App source groups ──────────────────────────────── + { + name: 'app-icons', + test: /src[\\/]components[\\/]icons[\\/]/, + priority: 25, + }, + // Shared components (excluding icons and Markdown, handled separately) + { + name: 'app-components', + test: /src[\\/]components[\\/](?!icons[\\/]|Markdown[\\/])/, + priority: 22, + }, + // Shared utils, hooks, services, constants + { + name: 'app-utilities', + test: /src[\\/](utils|hooks|services|constants)[\\/]/, + priority: 20, + }, + // Feature API files — three patterns, all excluding admin (which stays in app-admin): + // 1. dot-prefixed: *.api.ts / *.types.ts (e.g. apps.api.ts, spaces.types.ts) + // 2. plain api.ts: features/*/api.ts (e.g. challenges/api.ts) + // 3. query hooks: use*Query.ts (e.g. useFetchAppQuery.ts) + { + name: 'app-api-layer', + test: /src[\\/]features[\\/](?!admin[\\/]).+\.(api|types)\.(ts|tsx)$|src[\\/]features[\\/](?!admin[\\/]).*[\\/]api\.(ts|tsx)$|src[\\/]features[\\/](?!admin[\\/]).+use\w+Query\.(ts|tsx)$/, + priority: 18, + }, + // Admin-only features — never loaded by regular users + { + name: 'app-admin', + test: /src[\\/]features[\\/]admin[\\/]/, + priority: 15, + }, + // Lexical rich text editor — large feature, lazy-loaded + { + name: 'app-lexi', + test: /src[\\/]features[\\/]lexi[\\/]/, + priority: 15, }, ], }, @@ -109,128 +227,25 @@ export default defineConfig(({ command, mode }) => { cert: fs.readFileSync(certPath), } : undefined, - proxy: { - '/docs': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/logout': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/return_from_login': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/login': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/api': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/pdfs': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/assets': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/discussions': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/apps': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/workflows/new': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/notes': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/comparisons': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/licenses': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/users': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/profile': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/guidelines': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '^/workflows/.+/edit$': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '^/experts/.+/edit$': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/experts/new': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/admin/comparator_settings': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/admin/org_action_requests': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/admin/participants': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/admin/admin_memberships': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - '/admin/activity_reports': { - target: 'https://localhost:3000', - secure: false, - changeOrigin: true, - }, - }, + proxy: (() => { + const toRails = { target: 'https://localhost:3000', secure: false, changeOrigin: true } + const routes = [ + // Auth / session + '/login', '/logout', '/return_from_login', + // Rails-rendered pages still served by Rails + '/docs', '/pdfs', '/assets', '/guidelines', '/profile', + '/users', '/licenses', '/notes', '/comparisons', + '/discussions', '/apps', '/workflows/new', '/experts/new', + // Admin pages (Rails-rendered) + '/admin/comparator_settings', '/admin/org_action_requests', + '/admin/participants', '/admin/admin_memberships', '/admin/activity_reports', + // API + '/api', + // Regex routes (Rails edit forms) + '^/workflows/.+/edit$', '^/experts/.+/edit$', + ] + return Object.fromEntries(routes.map(r => [r, toRails])) + })(), }, publicDir: 'public', diff --git a/packages/gsrs/README.md b/packages/gsrs/README.md index 63dbcd81c..260f25c2b 100644 --- a/packages/gsrs/README.md +++ b/packages/gsrs/README.md @@ -55,7 +55,33 @@ Some parameters need to be specified to run this container. These are typically | `GSRS_DATABASE_PASSWORD` | (database password) | | `GSRS_DATABASE_NAME` | (database name) | +## Local Development Setup +Before running GSRS locally, you can download the seed data (Lucene index + DB dump) from S3, but the GSRS runs without populated db and index as well: + +```bash +make gsrs-seed-data +``` + +This downloads: +- **Lucene index** → `packages/gsrs/seed-data/ginas.ix/` +- **DB data dump** → `docker/misc/gsrs-db-init/02-gsrsdb-data.sql` + +The repo already ships a schema-only file (`docker/misc/gsrs-db-init/01-gsrsdb-schema.sql`), so GSRS can start with an empty DB even without running this script. The seed data adds ~18 substances for a fully populated local instance. + +**Prerequisites**: AWS CLI configured with access to the `gsrs-database-dumps-dev` bucket. + +You can override the S3 source with environment variables: + +| Variable | Default | Description | +|----------|---------|-------------| +| `GSRS_SEED_S3_BUCKET` | `gsrs-database-dumps-dev` | S3 bucket name | +| `GSRS_SEED_INDEX_KEY` | `local/ginas_ix.tar.gz` | S3 key for the Lucene index archive | +| `GSRS_SEED_DB_DUMP_KEY` | `local/gsrsdb.sql.gz` | S3 key for the gzipped SQL dump | + +The script is idempotent — it skips downloads if the files already exist. Delete the local files to force a re-download. + +--- ## Database & Index Restore Workflow Within the data_update folder, we have the dockerfile and script for restoring the database and index. diff --git a/packages/gsrs/frontend-dev/Dockerfile b/packages/gsrs/frontend-dev/Dockerfile new file mode 100644 index 000000000..7e758cf65 --- /dev/null +++ b/packages/gsrs/frontend-dev/Dockerfile @@ -0,0 +1,15 @@ +FROM node:22-bullseye-slim + +RUN apt-get update && \ + apt-get install -y --no-install-recommends git python3 make g++ && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Dependencies are installed at container startup (from bind-mounted source) +EXPOSE 4200 + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/packages/gsrs/frontend-dev/entrypoint.sh b/packages/gsrs/frontend-dev/entrypoint.sh new file mode 100644 index 000000000..760ee78e3 --- /dev/null +++ b/packages/gsrs/frontend-dev/entrypoint.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +cd /app + +echo "=== GSRS Frontend Dev Server ===" + +# Install deps if node_modules is missing or outdated +if [ ! -d "node_modules/.bin/ng" ]; then + echo "Installing dependencies (first run — this may take a few minutes)..." + npm install --legacy-peer-deps + # @types/deep-equal uses 'export =' which is incompatible with 'import * as' + # in newer Angular/TS. Remove it — the code works fine without types for deep-equal. + rm -rf node_modules/@types/deep-equal +fi + +# Patch environment file for local development if not already patched +ENV_FILE="src/environments/environment.fda.local.ts" +if [ ! -f "$ENV_FILE" ]; then + echo "Creating $ENV_FILE for local development..." + cat > "$ENV_FILE" <<'EOF' +import { environment as fdaEnv } from './environment.fda'; +export const environment = { + ...fdaEnv, + apiBaseUrl: 'https://localhost:3000/ginas/app/', + baseHref: '/ginas/app/ui/', +}; +EOF +fi + +echo "Starting Angular dev server on port 4200..." +echo "Live reload enabled — changes to source files will auto-rebuild." +export NODE_OPTIONS="--max-old-space-size=4096" +exec npx ng serve \ + --host 0.0.0.0 \ + --port 4200 \ + --disable-host-check \ + --configuration fda.local \ + --poll 2000 diff --git a/packages/gsrs/nginx/Dockerfile b/packages/gsrs/nginx/Dockerfile index 283114a4b..7d42ae8a6 100644 --- a/packages/gsrs/nginx/Dockerfile +++ b/packages/gsrs/nginx/Dockerfile @@ -3,5 +3,7 @@ FROM nginx:alpine RUN apk update && apk upgrade --no-cache COPY nginx.conf /etc/nginx/nginx.conf +COPY entrypoint.sh /docker-entrypoint.d/99-frontend-dev.sh +RUN chmod +x /docker-entrypoint.d/99-frontend-dev.sh EXPOSE 80 \ No newline at end of file diff --git a/packages/gsrs/nginx/entrypoint.sh b/packages/gsrs/nginx/entrypoint.sh new file mode 100644 index 000000000..1344845af --- /dev/null +++ b/packages/gsrs/nginx/entrypoint.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Generate frontend location config based on GSRS_FRONTEND_DEV env var +mkdir -p /etc/nginx/conf.d + +if [ "$GSRS_FRONTEND_DEV" = "true" ]; then + echo 'GSRS nginx: Frontend dev mode ENABLED (routing /ginas/app/ui → gsrs-frontend-dev:4200)' + cat > /etc/nginx/conf.d/frontend-location.conf <<'EOF' +location /ginas/app/ui { + resolver 127.0.0.11 valid=10s; + set $frontend http://gsrs-frontend-dev:4200; + proxy_pass $frontend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 300s; +} +EOF +else + echo 'GSRS nginx: Frontend dev mode DISABLED (routing /ginas/app/ui → gsrs-web WAR)' + cat > /etc/nginx/conf.d/frontend-location.conf <<'EOF' +location /ginas/app/ui { + proxy_pass http://gsrs-web:8080/frontend/ginas/app/ui; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +EOF +fi diff --git a/packages/gsrs/nginx/nginx.conf b/packages/gsrs/nginx/nginx.conf index ef204f1db..9f25336f0 100644 --- a/packages/gsrs/nginx/nginx.conf +++ b/packages/gsrs/nginx/nginx.conf @@ -87,13 +87,11 @@ http { return 200 "OK\n"; } - # Replacement for ROOT routing module - location /ginas/app/ui { - proxy_pass http://gsrs-web:8080/frontend/ginas/app/ui; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + # Frontend routing: dev server or pre-built WAR + # Controlled by GSRS_FRONTEND_DEV env var via entrypoint script + # Default: gsrs-web:8080/frontend (pre-built WAR) + # Dev mode: gsrs-frontend-dev:4200 (Angular dev server with HMR) + include /etc/nginx/conf.d/frontend-location.conf; location /ginas/app/beta { proxy_pass http://gsrs-web:8080/frontend/ginas/app/ui; diff --git a/packages/gsrs/scripts/fetch-seed-data.sh b/packages/gsrs/scripts/fetch-seed-data.sh new file mode 100755 index 000000000..ec5f9a80a --- /dev/null +++ b/packages/gsrs/scripts/fetch-seed-data.sh @@ -0,0 +1,74 @@ +#!/bin/bash +set -euo pipefail + +# Downloads GSRS seed data (Lucene index + full DB dump) from S3. +# +# The repo ships a schema-only SQL file so GSRS can start with an empty DB. +# Running this script downloads the data dump (18 substances) and the Lucene index for a fully populated local instance. +# +# Prerequisites: +# - AWS CLI configured with access to the gsrs-database-dumps-dev bucket +# - tar, gunzip available (standard on macOS/Linux) +# +# Usage: +# ./packages/gsrs/scripts/fetch-seed-data.sh +# make gsrs-seed-data + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +GSRS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$GSRS_DIR/../.." && pwd)" + +S3_BUCKET="${GSRS_SEED_S3_BUCKET:-gsrs-database-dumps-dev}" +S3_INDEX_KEY="${GSRS_SEED_INDEX_KEY:-local/ginas_ix.tar.gz}" +S3_DB_DUMP_KEY="${GSRS_SEED_DB_DUMP_KEY:-local/gsrsdb.sql.gz}" + +INDEX_DIR="$GSRS_DIR/seed-data/ginas.ix" +DB_INIT_DIR="$REPO_ROOT/docker/misc/gsrs-db-init" + +echo "=== GSRS Seed Data Download ===" +echo "S3 bucket: $S3_BUCKET" +echo "" + +# --- Lucene Index --- +if [ -d "$INDEX_DIR" ] && [ "$(ls -A "$INDEX_DIR" 2>/dev/null)" ]; then + echo "[index] Already exists at $INDEX_DIR — skipping (delete to re-download)" +else + echo "[index] Downloading Lucene index from s3://$S3_BUCKET/$S3_INDEX_KEY ..." + mkdir -p "$INDEX_DIR" + + TMP_ARCHIVE=$(mktemp /tmp/ginas_ix.XXXXXX.tar.gz) + trap 'rm -f "$TMP_ARCHIVE"' EXIT + + aws s3 cp "s3://$S3_BUCKET/$S3_INDEX_KEY" "$TMP_ARCHIVE" + + echo "[index] Extracting to $INDEX_DIR ..." + tar -xzf "$TMP_ARCHIVE" -C "$GSRS_DIR/seed-data" + + rm -f "$TMP_ARCHIVE" + echo "[index] Done." +fi + +echo "" + +# --- Database Dump (full data — runs after schema via numerical ordering) --- +DB_DUMP_FILE="$DB_INIT_DIR/02-gsrsdb-data.sql" +if [ -f "$DB_DUMP_FILE" ]; then + echo "[db] Full dump already exists at $DB_DUMP_FILE — skipping (delete to re-download)" +else + echo "[db] Downloading full DB dump from s3://$S3_BUCKET/$S3_DB_DUMP_KEY ..." + mkdir -p "$DB_INIT_DIR" + + TMP_DUMP=$(mktemp /tmp/gsrsdb.XXXXXX.sql.gz) + trap 'rm -f "$TMP_DUMP"' EXIT + + aws s3 cp "s3://$S3_BUCKET/$S3_DB_DUMP_KEY" "$TMP_DUMP" + + echo "[db] Decompressing to $DB_DUMP_FILE ..." + gunzip -c "$TMP_DUMP" > "$DB_DUMP_FILE" + + rm -f "$TMP_DUMP" + echo "[db] Done." +fi + +echo "" +echo "=== Seed data ready. You can now run: make run ===" diff --git a/packages/gsrs/web/entrypoint.sh b/packages/gsrs/web/entrypoint.sh index a57f4d6df..07952f057 100644 --- a/packages/gsrs/web/entrypoint.sh +++ b/packages/gsrs/web/entrypoint.sh @@ -1,23 +1,34 @@ #!/bin/bash set -e -# --- OverlayFS Setup --- -# Use the unique hostname (container ID) to prevent collisions if you run multiple tasks -UNIQUE_ID=$(hostname) -UPPER="/tmp/overlay-data/${UNIQUE_ID}/upper" -WORK="/tmp/overlay-data/${UNIQUE_ID}/work" -MERGED="/opt/gsrs/ginas.ix" - -echo "Configuring OverlayFS for GSRS Index..." -mkdir -p "$UPPER" "$WORK" "$MERGED" - -# The Actual Mount Command -mount -t overlay overlay \ - -o lowerdir=/tmp/read-only-base,upperdir="$UPPER",workdir="$WORK" \ - "$MERGED" - -# Lucene cleanup: ensure no stale locks from the base index block startup -rm -f "$MERGED/write.lock" +# --- Index Setup --- +# Index is always bind-mounted to /tmp/read-only-base. +# Production (ECS): OverlayFS keeps the shared index read-only with a writable upper layer. +# Local dev: symlink directly. +if [ "${GSRS_LOCAL_MODE}" = "true" ]; then + echo "Local mode — symlinking index directly" + mkdir -p /opt/gsrs + ln -sfn /tmp/read-only-base /opt/gsrs/ginas.ix + find /opt/gsrs/ginas.ix -name "write.lock" -delete 2>/dev/null || true +else + UNIQUE_ID=$(hostname) + UPPER="/tmp/overlay-data/${UNIQUE_ID}/upper" + WORK="/tmp/overlay-data/${UNIQUE_ID}/work" + MERGED="/opt/gsrs/ginas.ix" + + echo "Configuring OverlayFS for GSRS Index..." + mkdir -p "$UPPER" "$WORK" "$MERGED" + + if ! mount -t overlay overlay \ + -o "lowerdir=/tmp/read-only-base,upperdir=$UPPER,workdir=$WORK" \ + "$MERGED"; then + echo "ERROR: OverlayFS mount failed." + exit 1 + fi + echo "OverlayFS mounted" + + rm -f "$MERGED/write.lock" +fi # --- Original GSRS Configuration --- TC_PATH="/usr/local/tomcat" diff --git a/packages/nginx/default.conf.template b/packages/nginx/default.conf.template index 0a5900e9f..6b3dfa02e 100644 --- a/packages/nginx/default.conf.template +++ b/packages/nginx/default.conf.template @@ -7,6 +7,9 @@ server { ssl_certificate /keys/cert.pem; ssl_certificate_key /keys/key.pem; + root /usr/share/nginx/html; + index index.html; + location /docs { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; @@ -23,10 +26,14 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } - - # This is a simulation of AWS ALB rule for GSRS static assets + + # GSRS static assets served directly via gsrs-nginx (no auth needed, faster) + # All other /ginas/* requests fall through to Rails (location /) which injects + # AUTHENTICATION_USERNAME/EMAIL headers and reverse-proxies to GSRS location ~ ^/ginas/.*((\.(js|css|png|jpg|jpeg|gif))|(manifest\.json))$ { - proxy_pass http://host.docker.internal:8080; + resolver 127.0.0.11 valid=10s; + set $gsrs_upstream http://gsrs-nginx:80; + proxy_pass $gsrs_upstream; } location ~ ^/api/files/([^/]+)/download$ { @@ -45,11 +52,13 @@ server { return 301 $scheme://$http_host/api/v2/files/$1/$2$is_args$args; } - location / { - proxy_pass ${RUBY_API_URL}; - proxy_set_header Host $http_host; + location = /api/create_file { + proxy_pass ${NODE_API_URL}/files; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; proxy_http_version 1.1; + proxy_redirect off; } # Redirect deprecated singular /job/ path to plural /jobs/ @@ -60,6 +69,163 @@ server { location /api/v2/ { proxy_pass ${NODE_API_URL}/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location /api/docs/ { + proxy_pass ${NODE_API_URL}/api/docs/; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/(logout|return_from_login|login|pdfs|notes|comparisons|licenses|users|profile|guidelines|jobs|set_tags|presskit)(/|$) { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_redirect off; + } + + location ~ ^/(apps|workflows|jobs|files|assets|comparisons|notes)/.+/comments(/.*)?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location = /experts/new { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location = /experts/create { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/experts/.+/(edit|qa)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/challenges/.+/(editor/resources|challenge_resources/new)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location = /workflows/new { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/workflows/.+/(edit|fork)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/workflows/.+/(batch_workflow|run_batch|terminate_batch|output_folders_list|output_folder_create|output_folder_update)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location = /workflows/convert_file_with_strings { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/apps/.+/(export|cwl_export|wdl_export)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/workflows/.+/(cwl_export|wdl_export)/?$ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location ~ ^/admin/(comparator_settings|org_action_requests)(/|$) { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_redirect off; + } + + location ~ ^/admin/activity_reports(/|$) { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_redirect off; + } + + location = /admin/users_list { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; proxy_http_version 1.1; } + + # Client build ships /assets/participants/* etc.; Rails asset pipeline serves the rest. + location /assets/ { + try_files $uri @rails_assets; + } + + location @rails_assets { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + } + + location /api/ { + proxy_pass ${RUBY_API_URL}; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_redirect off; + } + + location / { + try_files $uri $uri/ /index.html; + } } diff --git a/packages/nginx/docker/images/Dockerfile b/packages/nginx/docker/images/Dockerfile index 96c6bd034..b66fe9d54 100644 --- a/packages/nginx/docker/images/Dockerfile +++ b/packages/nginx/docker/images/Dockerfile @@ -1,3 +1,24 @@ +FROM node:22.15.0-slim AS client-builder + +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y --no-install-recommends build-essential python3 && \ + rm -rf /var/lib/apt/lists/* + +RUN npm install -g pnpm@10.10.0 + +COPY packages/client/package.json ./package.json +COPY packages/client/pnpm-lock.yaml ./pnpm-lock.yaml +COPY packages/client/pnpm-workspace.yaml ./pnpm-workspace.yaml + +RUN pnpm install --frozen-lockfile + +COPY packages/client/ . + +ENV VITE_OUT_DIR=/app/dist +RUN pnpm run build + FROM nginx:stable-alpine # Create SSL directory @@ -12,6 +33,13 @@ RUN adduser -S -G www-data www-data COPY packages/nginx/nginx.conf /etc/nginx/nginx.conf COPY packages/nginx/json_analytics_log_format_for_prometheus.conf /etc/nginx/conf.d/ + +# Remove default nginx content +RUN rm -rf /usr/share/nginx/html/* + +# Copy built client assets +COPY --from=client-builder /app/dist /usr/share/nginx/html + # Entrypoint COPY packages/nginx/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh diff --git a/packages/nginx/entrypoint.sh b/packages/nginx/entrypoint.sh index 92523a92d..69e3295e4 100644 --- a/packages/nginx/entrypoint.sh +++ b/packages/nginx/entrypoint.sh @@ -7,5 +7,19 @@ echo "$SSL_KEY" > /etc/nginx/ssl/pfda.key sed -i "s|\${UNII_HOST}|$UNII_HOST|g" /etc/nginx/nginx.conf +RUNTIME_ENV_DIR="/usr/share/nginx/html/env" +RUNTIME_ENV_PATH="${RUNTIME_ENV_DIR}/keys.json" + +mkdir -p "$RUNTIME_ENV_DIR" + +cat > "$RUNTIME_ENV_PATH" < - # - # Outputs: - # - # id (string, "file-xxxx") - # - def create_file - fail "User is not allowed to create public files" if params[:scope] == "public" && !current_user.site_admin? - - project = UserFile.publication_project!(current_user, @scope) - - parent = current_user - # file could be uploaded by CLI inside job; fall back to current_user if job is not found - if params[:parent_type] == "Job" && params[:parent_id] != "" - parent = Job.find_by(dxid: params[:parent_id]) || current_user - end - - api = DNAnexusAPI.new(RequestContext.instance.token) - file_dxid = api.file_new(params[:name], project)["id"] - - file = UserFile.create!( - dxid: file_dxid, - project: project, - name: params[:name], - state: "open", - description: params[:description], - user: current_user, - parent: parent, - scope: @scope, - UserFile.scope_column_name(@scope) => @folder&.id, - ) - - render json: { id: file.uid } - end - # Creates a challenge logo - to be visible as a challenge card image # @return [Hash] - a uid of a file uploaded as a card image # @@ -1561,61 +1521,6 @@ def validate_create_asset end end - # Validates and initializes parameters for a file creation. - # rubocop:todo Metrics/MethodLength - def validate_create_file - folder_id = params[:folder_id].presence - @folder = - begin - folder_id && Folder.find(folder_id) - rescue ActiveRecord::RecordNotFound - raise_api_error "The folder doesn't exist." - end - - # If folder is present, its scope rules everything - params[:scope] = @folder.scope if @folder - - if @folder && !@folder.editable_by?(@context) - raise_api_error "You don't have permissions to add files to the folder." - end - - if @folder && @folder.state == "removing" - raise_api_error "The target folder is being removed." - end - - # user specified only folder id, but the folder is in space - set it for him - if @folder && (@folder.scope.match(/^space-(\d+)$/)) && !params[:space_id] - params[:scope] = @folder.scope - end - - file_name = params[:name].presence - if file_name.blank? || !file_name.is_a?(String) - raise_api_error "File name needs to be a non-empty String" - end - - description = params[:description].presence - if description && !description.is_a?(String) - raise_api_error "File description needs to be a String" - end - - @scope = if ActiveModel::Type::Boolean.new.cast(params[:public_scope]) - Scopes::SCOPE_PUBLIC - else - params[:scope].presence || Scopes::SCOPE_PRIVATE - end - - unless [Scopes::SCOPE_PUBLIC, Scopes::SCOPE_PRIVATE].include?(@scope) || Space.valid_scope?(@scope) - raise_api_error "Scope is invalid" - end - - if Space.valid_scope?(@scope) && !Space.from_scope(@scope).editable_by?(current_user) - raise_api_error "You don't have permissions to add files to the space." - end - - return if @folder.nil? || @folder.scope == @scope - - raise_api_error "The folder doesn't belong to a scope #{@scope}." - end # rubocop:enable Metrics/MethodLength # rubocop:enable Style/SignalException diff --git a/packages/rails/app/controllers/main_controller.rb b/packages/rails/app/controllers/main_controller.rb index 38b19d1e4..48857fa2d 100644 --- a/packages/rails/app/controllers/main_controller.rb +++ b/packages/rails/app/controllers/main_controller.rb @@ -480,7 +480,7 @@ def logout_from_gsrs end def oauth2_redirect_url - URI.join(request.base_url, "/return_from_login").to_s + URI.join(HOST, "/return_from_login").to_s end # Concat item path with '/home' to create a link to Home - for specific items diff --git a/packages/rails/app/extras/https_apps_client.rb b/packages/rails/app/extras/https_apps_client.rb index 5906cd8f7..753bd48aa 100644 --- a/packages/rails/app/extras/https_apps_client.rb +++ b/packages/rails/app/extras/https_apps_client.rb @@ -789,6 +789,15 @@ def track_provenance(identifier) ) end + def get_file_download_link(uid, options = {}) + request( + "/files/#{uid}/download/legacy", + {}, + Net::HTTP::Get::METHOD, + options, + ) + end + def file_download(uid, filename, options = {}) request( "/files/#{uid}/#{URI.encode_www_form_component(filename)}", diff --git a/packages/rails/app/helpers/vite_helper.rb b/packages/rails/app/helpers/vite_helper.rb deleted file mode 100644 index 6f161abfa..000000000 --- a/packages/rails/app/helpers/vite_helper.rb +++ /dev/null @@ -1,51 +0,0 @@ -require "set" - -module ViteHelper - MANIFEST_PATH = "public/packs/.vite/manifest.json" - - # Look up the hashed JS path for a Vite entry point. - def vite_asset_path(entry) - file = manifest.dig(entry, "file") - raise missing_manifest_error if manifest.nil? - raise missing_entry_error(entry) if file.nil? - - "/packs/#{file}" - end - - # Look up the hashed CSS paths for a Vite entry point. - def vite_css_paths(entry) - resolve_css_paths(entry).map { |path| "/packs/#{path}" } - end - - private - - def resolve_css_paths(entry, seen = Set.new) - return [] if seen.include?(entry) - - seen.add(entry) - - entry_data = manifest&.[](entry) || {} - css_paths = entry_data.fetch("css", []) - - imported_css_paths = entry_data.fetch("imports", []).flat_map do |import_entry| - resolve_css_paths(import_entry, seen) - end - - (css_paths + imported_css_paths).uniq - end - - def manifest - @manifest ||= begin - path = Rails.root.join(MANIFEST_PATH) - JSON.parse(File.read(path)) if File.exist?(path) - end - end - - def missing_manifest_error - "Vite manifest not found at #{MANIFEST_PATH}. Run `pnpm build` in packages/client." - end - - def missing_entry_error(entry) - "Entry '#{entry}' not found in Vite manifest." - end -end diff --git a/packages/rails/app/serializers/user_file_serializer.rb b/packages/rails/app/serializers/user_file_serializer.rb index ca3a963da..63f20ab06 100644 --- a/packages/rails/app/serializers/user_file_serializer.rb +++ b/packages/rails/app/serializers/user_file_serializer.rb @@ -62,8 +62,6 @@ def links # POST download_list files links[:download_list] = download_list_api_files_path - # POST: Add file - links[:add_file] = api_create_file_path # POST: Add folder links[:add_folder] = create_folder_api_files_path # PUT edit a single file diff --git a/packages/rails/app/views/_partials/_btn_publish.html.erb b/packages/rails/app/views/_partials/_btn_publish.html.erb index 01919e038..7ee38f617 100644 --- a/packages/rails/app/views/_partials/_btn_publish.html.erb +++ b/packages/rails/app/views/_partials/_btn_publish.html.erb @@ -3,7 +3,7 @@ %> <% if can_be_public %> - <%= link_to publish_path + "?" + { identifier: item.uid, type: item.klass }.to_param, method: :get, class: "btn btn-success #{defined?(classes) ? classes : ''}" do %> + <%= link_to publish_path + "?" + { identifier: item.uid, type: item.klass }.to_param, data: { turbolinks: false }, class: "btn btn-success #{defined?(classes) ? classes : ''}" do %> Publish publicly <% end %> <% end %> diff --git a/packages/rails/app/views/_partials/_head_react.html.erb b/packages/rails/app/views/_partials/_head_react.html.erb index fb9673f0f..ff0fc35fe 100644 --- a/packages/rails/app/views/_partials/_head_react.html.erb +++ b/packages/rails/app/views/_partials/_head_react.html.erb @@ -1,8 +1,3 @@ <%= render '_partials/head_common' %> <%= javascript_include_tag 'next_application' %> - -<% vite_css_paths("src/index.tsx").each do |css_path| %> - -<% end %> - diff --git a/packages/rails/app/views/experts/edit.html.erb b/packages/rails/app/views/experts/edit.html.erb index 366e4fa3b..e5379d684 100644 --- a/packages/rails/app/views/experts/edit.html.erb +++ b/packages/rails/app/views/experts/edit.html.erb @@ -10,7 +10,7 @@
- <%= form_for @expert, url: expert_path(@expert), method: :put, html: {class: 'form form-horizontal'} do |f| %> + <%= form_for @expert, url: update_expert_path(@expert), method: :post, html: {class: 'form form-horizontal'} do |f| %> <%= render "experts/form_fields", f: f %> diff --git a/packages/rails/app/views/experts/new.html.erb b/packages/rails/app/views/experts/new.html.erb index 09d13f742..b3e077ee9 100644 --- a/packages/rails/app/views/experts/new.html.erb +++ b/packages/rails/app/views/experts/new.html.erb @@ -10,7 +10,7 @@
- <%= form_for @expert, url: experts_path, html: {class: 'form form-horizontal'} do |f| %> + <%= form_for @expert, url: create_experts_path, html: {class: 'form form-horizontal'} do |f| %> <%= render "experts/form_fields", f: f %> diff --git a/packages/rails/config/routes.rb b/packages/rails/config/routes.rb index 82a9eab86..5c0a715c1 100644 --- a/packages/rails/config/routes.rb +++ b/packages/rails/config/routes.rb @@ -162,6 +162,7 @@ # API namespace "api" do get "auth_key" => "base#auth_key" + get "flash_messages" => "base#flash_messages" get "update_active", to: "base#update_active" resource :user, only: %i(show) @@ -393,7 +394,6 @@ end end - post "create_file" post "create_challenge_card_image" post "create_image_file" post "get_upload_url" @@ -588,6 +588,9 @@ via: %i(get post) end + post "/experts/create", to: "experts#create", as: :create_experts + post "/experts/:id/edit", to: "experts#update", as: :update_expert + resources :experts do post "ask_question", on: :member post "open", on: :member diff --git a/packages/rails/docker/entrypoint/prod.entrypoint.sh b/packages/rails/docker/entrypoint/prod.entrypoint.sh index a504e5b5d..deec23bd8 100644 --- a/packages/rails/docker/entrypoint/prod.entrypoint.sh +++ b/packages/rails/docker/entrypoint/prod.entrypoint.sh @@ -4,7 +4,6 @@ set -e # ------------------------------ # Generate runtime environment for frontend # ------------------------------ -source /precision-fda/docker/entrypoint/runtime-env.sh source /precision-fda/docker/entrypoint/robots-txt.sh # ------------------------------ # Generate database.yml from DATABASE_URL diff --git a/packages/rails/docker/images/Dockerfile b/packages/rails/docker/images/Dockerfile index 20e529ac8..9202a2cfb 100644 --- a/packages/rails/docker/images/Dockerfile +++ b/packages/rails/docker/images/Dockerfile @@ -69,25 +69,6 @@ RUN chmod +x ./docker/entrypoint/prod.entrypoint.sh RUN chmod +x ./docker/entrypoint/runtime-env.sh RUN chmod +x ./docker/entrypoint/robots-txt.sh -# ========================= -# Build frontend assets -# ========================= - -# Copy only dependency files for caching Node modules -WORKDIR $APP_DIR/frontend -COPY packages/client/package.json $APP_DIR/frontend/package.json -COPY packages/client/pnpm-lock.yaml $APP_DIR/frontend/pnpm-lock.yaml -COPY packages/client/pnpm-workspace.yaml $APP_DIR/frontend/pnpm-workspace.yaml -RUN pnpm install --frozen-lockfile - -# Copy the rest of the frontend code and build -COPY packages/client/ $APP_DIR/frontend -# Override VITE_OUT_DIR since the default '../rails/public/packs' is relative to packages/client -# but in Docker, frontend is at /precision-fda/frontend and Rails is at /precision-fda -ENV VITE_OUT_DIR=$APP_DIR/public/packs -ENV CI=true -RUN pnpm run build - WORKDIR $APP_DIR RUN mv .env.do_not_delete .env RUN mv config/database.do_not_delete.yml config/database.yml diff --git a/packages/rails/docker/misc/gsrs-db-init/gsrsdb.sql b/packages/rails/docker/misc/gsrs-db-init/gsrsdb.sql deleted file mode 100644 index 415dadb16..000000000 --- a/packages/rails/docker/misc/gsrs-db-init/gsrsdb.sql +++ /dev/null @@ -1,2943 +0,0 @@ --- MySQL dump 10.13 Distrib 8.0.34, for Linux (x86_64) --- --- Host: gsrs-dev-db.cyy6pahwar0b.us-west-2.rds.amazonaws.com Database: ixginas20230708 --- ------------------------------------------------------ --- Server version 5.5.5-10.6.14-MariaDB-log - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!50503 SET NAMES utf8mb4 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `LONG_SEQ_ID` --- - -DROP TABLE IF EXISTS `LONG_SEQ_ID`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `LONG_SEQ_ID` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_batch_processingjob` --- - -DROP TABLE IF EXISTS `ix_batch_processingjob`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_batch_processingjob` ( - `id` varchar(40) NOT NULL, - `category` varchar(255) DEFAULT NULL, - `completed_record_count` int(11) NOT NULL, - `data` longtext DEFAULT NULL, - `finish_date` datetime(6) DEFAULT NULL, - `job_status` varchar(255) DEFAULT NULL, - `results` longtext DEFAULT NULL, - `start_date` datetime(6) DEFAULT NULL, - `status_message` varchar(255) DEFAULT NULL, - `total_records` int(11) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_acl` --- - -DROP TABLE IF EXISTS `ix_core_acl`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_acl` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `perm` int(11) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_acl_group` --- - -DROP TABLE IF EXISTS `ix_core_acl_group`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_acl_group` ( - `ix_core_acl_id` bigint(20) NOT NULL, - `ix_core_group_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_acl_id`,`ix_core_group_id`), - KEY `c_37918c15` (`ix_core_group_id`), - CONSTRAINT `c_37918c15` FOREIGN KEY (`ix_core_group_id`) REFERENCES `ix_core_group` (`id`), - CONSTRAINT `c_8334ae69` FOREIGN KEY (`ix_core_acl_id`) REFERENCES `ix_core_acl` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_acl_principal` --- - -DROP TABLE IF EXISTS `ix_core_acl_principal`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_acl_principal` ( - `ix_core_acl_id` bigint(20) NOT NULL, - `ix_core_principal_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_acl_id`,`ix_core_principal_id`), - KEY `c_0563d198` (`ix_core_principal_id`), - CONSTRAINT `c_0563d198` FOREIGN KEY (`ix_core_principal_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_edb5bbb8` FOREIGN KEY (`ix_core_acl_id`) REFERENCES `ix_core_acl` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_acl_seq` --- - -DROP TABLE IF EXISTS `ix_core_acl_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_acl_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_attribute` --- - -DROP TABLE IF EXISTS `ix_core_attribute`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_attribute` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - `value` varchar(1024) DEFAULT NULL, - `namespace_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_2e0d49bb` (`namespace_id`), - CONSTRAINT `c_5de71e45` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_backup` --- - -DROP TABLE IF EXISTS `ix_core_backup`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_backup` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `refid` varchar(255) DEFAULT NULL, - `kind` varchar(255) DEFAULT NULL, - `data` longblob DEFAULT NULL, - `sha1` varchar(255) DEFAULT NULL, - `compressed` tinyint(1) DEFAULT 0, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_2884574a` (`refid`), - KEY `i_abc97ed9` (`namespace_id`), - CONSTRAINT `c_d73bb54b` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=5158265 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_backup_seq` --- - -DROP TABLE IF EXISTS `ix_core_backup_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_backup_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_curation` --- - -DROP TABLE IF EXISTS `ix_core_curation`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_curation` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `curator_id` bigint(20) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `timestamp` datetime DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_c639b9b3` (`curator_id`), - CONSTRAINT `c_a6783131` FOREIGN KEY (`curator_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_db_gsrs_version` --- - -DROP TABLE IF EXISTS `ix_core_db_gsrs_version`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_db_gsrs_version` ( - `id` bigint(20) NOT NULL, - `entity` varchar(255) NOT NULL, - `hash` varchar(255) DEFAULT NULL, - `modified` datetime(6) DEFAULT NULL, - `version_info` varchar(255) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_edit` --- - -DROP TABLE IF EXISTS `ix_core_edit`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_edit` ( - `id` varchar(40) NOT NULL, - `created` bigint(20) DEFAULT NULL, - `refid` varchar(255) DEFAULT NULL, - `kind` varchar(255) DEFAULT NULL, - `batch` varchar(64) DEFAULT NULL, - `editor_id` bigint(20) DEFAULT NULL, - `path` varchar(1024) DEFAULT NULL, - `comments` longtext DEFAULT NULL, - `version` varchar(255) DEFAULT NULL, - `old_value` longtext DEFAULT NULL, - `new_value` longtext DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_7aee51ce` (`editor_id`), - KEY `refid_core_edit_index` (`refid`), - KEY `kind_core_edit_index` (`kind`), - CONSTRAINT `c_12a5334f` FOREIGN KEY (`editor_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_etag` --- - -DROP TABLE IF EXISTS `ix_core_etag`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_etag` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `etag` varchar(16) DEFAULT NULL, - `uri` varchar(4000) DEFAULT NULL, - `path` varchar(255) DEFAULT NULL, - `method` varchar(10) DEFAULT NULL, - `sha1` varchar(40) DEFAULT NULL, - `total` int(11) DEFAULT NULL, - `count` int(11) DEFAULT NULL, - `skip` int(11) DEFAULT NULL, - `top` int(11) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `query` varchar(2048) DEFAULT NULL, - `filter` varchar(4000) DEFAULT NULL, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_116a77ea` (`etag`), - KEY `i_2713cf1c` (`namespace_id`), - CONSTRAINT `c_d104ddaf` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=36300825 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_etag_seq` --- - -DROP TABLE IF EXISTS `ix_core_etag_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_etag_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_etagref` --- - -DROP TABLE IF EXISTS `ix_core_etagref`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_etagref` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `etag_id` bigint(20) DEFAULT NULL, - `ref_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_5e1fe842` (`etag_id`), - CONSTRAINT `c_aa5f10b2` FOREIGN KEY (`etag_id`) REFERENCES `ix_core_etag` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_event` --- - -DROP TABLE IF EXISTS `ix_core_event`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_event` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `title` varchar(255) DEFAULT NULL, - `description` longtext DEFAULT NULL, - `url` varchar(1024) DEFAULT NULL, - `start_time` bigint(20) DEFAULT NULL, - `end_time` bigint(20) DEFAULT NULL, - `unit` int(11) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_event_link` --- - -DROP TABLE IF EXISTS `ix_core_event_link`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_event_link` ( - `ix_core_event_id` bigint(20) NOT NULL, - `ix_core_xref_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_event_id`,`ix_core_xref_id`), - KEY `c_80f406a0` (`ix_core_xref_id`), - CONSTRAINT `c_80f406a0` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`), - CONSTRAINT `c_98366c6b` FOREIGN KEY (`ix_core_event_id`) REFERENCES `ix_core_event` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_event_prop` --- - -DROP TABLE IF EXISTS `ix_core_event_prop`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_event_prop` ( - `ix_core_event_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_event_id`,`ix_core_value_id`), - KEY `c_2d292e00` (`ix_core_value_id`), - CONSTRAINT `c_2d292e00` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_32e7a523` FOREIGN KEY (`ix_core_event_id`) REFERENCES `ix_core_event` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_figure` --- - -DROP TABLE IF EXISTS `ix_core_figure`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_figure` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `caption` varchar(255) DEFAULT NULL, - `mime_type` varchar(255) DEFAULT NULL, - `url` varchar(1024) DEFAULT NULL, - `data` longblob DEFAULT NULL, - `data_size` int(11) DEFAULT NULL, - `sha1` varchar(140) DEFAULT NULL, - `parent_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_bcc29d98` (`parent_id`), - CONSTRAINT `c_933ce9dc` FOREIGN KEY (`parent_id`) REFERENCES `ix_core_figure` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_filedata` --- - -DROP TABLE IF EXISTS `ix_core_filedata`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_filedata` ( - `dtype` varchar(10) NOT NULL, - `id` varchar(40) NOT NULL, - `mime_type` varchar(255) DEFAULT NULL, - `data` longblob DEFAULT NULL, - `data_size` bigint(20) DEFAULT NULL, - `sha1` varchar(140) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_group` --- - -DROP TABLE IF EXISTS `ix_core_group`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_group` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_3aa2c124` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_group_principal` --- - -DROP TABLE IF EXISTS `ix_core_group_principal`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_group_principal` ( - `ix_core_group_id` bigint(20) NOT NULL, - `ix_core_principal_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_group_id`,`ix_core_principal_id`), - KEY `c_045e1ef9` (`ix_core_principal_id`), - CONSTRAINT `c_045e1ef9` FOREIGN KEY (`ix_core_principal_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_2223dcea` FOREIGN KEY (`ix_core_group_id`) REFERENCES `ix_core_group` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_group_seq` --- - -DROP TABLE IF EXISTS `ix_core_group_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_group_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_investigator` --- - -DROP TABLE IF EXISTS `ix_core_investigator`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_investigator` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - `pi_id` bigint(20) DEFAULT NULL, - `organization_id` bigint(20) DEFAULT NULL, - `role` int(11) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_1bcd7f25` (`organization_id`), - CONSTRAINT `c_71245644` FOREIGN KEY (`organization_id`) REFERENCES `ix_core_organization` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_journal` --- - -DROP TABLE IF EXISTS `ix_core_journal`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_journal` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `issn` varchar(10) DEFAULT NULL, - `volume` varchar(255) DEFAULT NULL, - `issue` varchar(255) DEFAULT NULL, - `year` int(11) DEFAULT NULL, - `month` varchar(10) DEFAULT NULL, - `title` varchar(1024) DEFAULT NULL, - `iso_abbr` varchar(255) DEFAULT NULL, - `factor` double DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_key_user_list` --- - -DROP TABLE IF EXISTS `ix_core_key_user_list`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_key_user_list` ( - `id` bigint(20) NOT NULL, - `entity_key` varchar(255) DEFAULT NULL, - `list_name` varchar(255) NOT NULL, - `user_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ukbomijjxdp2cmjttgrnqtoucvo` (`entity_key`,`list_name`,`user_id`), - KEY `fk7q0vtv7ajevho6v75n57jy0dj` (`user_id`), - CONSTRAINT `fk7q0vtv7ajevho6v75n57jy0dj` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_namespace` --- - -DROP TABLE IF EXISTS `ix_core_namespace`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_namespace` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - `owner_id` bigint(20) DEFAULT NULL, - `location` varchar(1024) DEFAULT NULL, - `modifier` int(11) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_2b9ef5c1` (`name`), - KEY `i_b77ca179` (`owner_id`), - CONSTRAINT `c_d7342e64` FOREIGN KEY (`owner_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_namespace_seq` --- - -DROP TABLE IF EXISTS `ix_core_namespace_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_namespace_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_organization` --- - -DROP TABLE IF EXISTS `ix_core_organization`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_organization` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `duns` varchar(10) DEFAULT NULL, - `name` varchar(255) DEFAULT NULL, - `department` varchar(255) DEFAULT NULL, - `city` varchar(255) DEFAULT NULL, - `state` varchar(128) DEFAULT NULL, - `zipcode` varchar(64) DEFAULT NULL, - `district` varchar(255) DEFAULT NULL, - `country` varchar(255) DEFAULT NULL, - `fips` varchar(3) DEFAULT NULL, - `longitude` double DEFAULT NULL, - `latitude` double DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_payload` --- - -DROP TABLE IF EXISTS `ix_core_payload`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_payload` ( - `id` varchar(40) NOT NULL, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `name` varchar(1024) DEFAULT NULL, - `sha1` varchar(40) DEFAULT NULL, - `mime_type` varchar(128) DEFAULT NULL, - `capacity` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_14e619fc` (`namespace_id`), - CONSTRAINT `c_3f780616` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_payload_property` --- - -DROP TABLE IF EXISTS `ix_core_payload_property`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_payload_property` ( - `ix_core_payload_id` varchar(40) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_payload_id`,`ix_core_value_id`), - KEY `c_c378137b` (`ix_core_value_id`), - CONSTRAINT `c_99d3e052` FOREIGN KEY (`ix_core_payload_id`) REFERENCES `ix_core_payload` (`id`), - CONSTRAINT `c_c378137b` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_predicate` --- - -DROP TABLE IF EXISTS `ix_core_predicate`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_predicate` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `subject_id` bigint(20) DEFAULT NULL, - `predicate` varchar(255) NOT NULL, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - KEY `i_ea60b9c5` (`namespace_id`), - KEY `i_f051e6a6` (`subject_id`), - CONSTRAINT `c_8380c650` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`), - CONSTRAINT `c_c61aacd9` FOREIGN KEY (`subject_id`) REFERENCES `ix_core_xref` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_predicate_object` --- - -DROP TABLE IF EXISTS `ix_core_predicate_object`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_predicate_object` ( - `ix_core_predicate_id` bigint(20) NOT NULL, - `ix_core_xref_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_predicate_id`,`ix_core_xref_id`), - KEY `c_9e293820` (`ix_core_xref_id`), - CONSTRAINT `c_8e0804d7` FOREIGN KEY (`ix_core_predicate_id`) REFERENCES `ix_core_predicate` (`id`), - CONSTRAINT `c_9e293820` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_predicate_property` --- - -DROP TABLE IF EXISTS `ix_core_predicate_property`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_predicate_property` ( - `ix_core_predicate_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_predicate_id`,`ix_core_value_id`), - KEY `c_62edfd42` (`ix_core_value_id`), - CONSTRAINT `c_62edfd42` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_6b1b65df` FOREIGN KEY (`ix_core_predicate_id`) REFERENCES `ix_core_predicate` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_principal` --- - -DROP TABLE IF EXISTS `ix_core_principal`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_principal` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `provider` varchar(255) DEFAULT NULL, - `username` varchar(255) DEFAULT NULL, - `email` varchar(255) DEFAULT NULL, - `is_admin` tinyint(1) DEFAULT 0, - `uri` varchar(1024) DEFAULT NULL, - `selfie_id` bigint(20) DEFAULT NULL, - `version` bigint(20) NOT NULL, - `lastname` varchar(255) DEFAULT NULL, - `forename` varchar(255) DEFAULT NULL, - `initials` varchar(255) DEFAULT NULL, - `prefname` varchar(255) DEFAULT NULL, - `suffix` varchar(20) DEFAULT NULL, - `affiliation` longtext DEFAULT NULL, - `orcid` varchar(255) DEFAULT NULL, - `institution_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_117ea9e1` (`username`), - KEY `i_d3ad08f2` (`namespace_id`), - KEY `i_087afcf1` (`selfie_id`), - KEY `i_c164584e` (`institution_id`), - CONSTRAINT `c_16a08d9e` FOREIGN KEY (`institution_id`) REFERENCES `ix_core_organization` (`id`), - CONSTRAINT `c_8fbeac5e` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`), - CONSTRAINT `c_a2c06c5d` FOREIGN KEY (`selfie_id`) REFERENCES `ix_core_figure` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=10037 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_principal_seq` --- - -DROP TABLE IF EXISTS `ix_core_principal_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_principal_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procjob` --- - -DROP TABLE IF EXISTS `ix_core_procjob`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procjob` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `status` int(11) DEFAULT NULL, - `job_start` bigint(20) DEFAULT NULL, - `job_stop` bigint(20) DEFAULT NULL, - `message` longtext DEFAULT NULL, - `statistics` longtext DEFAULT NULL, - `owner_id` bigint(20) DEFAULT NULL, - `payload_id` varchar(40) DEFAULT NULL, - `last_update` datetime DEFAULT NULL, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - KEY `i_cdaeb7ec` (`owner_id`), - KEY `i_015ac682` (`payload_id`), - CONSTRAINT `c_f3fe89eb` FOREIGN KEY (`owner_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_fe6f1c1b` FOREIGN KEY (`payload_id`) REFERENCES `ix_core_payload` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=85 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procjob_key` --- - -DROP TABLE IF EXISTS `ix_core_procjob_key`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procjob_key` ( - `ix_core_procjob_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - `keys_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_procjob_id`,`ix_core_value_id`), - KEY `c_437a9cfc` (`ix_core_value_id`), - CONSTRAINT `c_437a9cfc` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_67a7c278` FOREIGN KEY (`ix_core_procjob_id`) REFERENCES `ix_core_procjob` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procjob_seq` --- - -DROP TABLE IF EXISTS `ix_core_procjob_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procjob_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procrec` --- - -DROP TABLE IF EXISTS `ix_core_procrec`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procrec` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `rec_start` bigint(20) DEFAULT NULL, - `rec_stop` bigint(20) DEFAULT NULL, - `name` varchar(128) DEFAULT NULL, - `status` int(11) DEFAULT NULL, - `message` longtext DEFAULT NULL, - `xref_id` bigint(20) DEFAULT NULL, - `job_id` bigint(20) DEFAULT NULL, - `last_update` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `i_208a1bba` (`xref_id`), - KEY `i_caa0d4b8` (`job_id`), - CONSTRAINT `c_75776597` FOREIGN KEY (`job_id`) REFERENCES `ix_core_procjob` (`id`), - CONSTRAINT `c_a187d219` FOREIGN KEY (`xref_id`) REFERENCES `ix_core_xref` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=6411033 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procrec_prop` --- - -DROP TABLE IF EXISTS `ix_core_procrec_prop`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procrec_prop` ( - `ix_core_procrec_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - `properties_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_procrec_id`,`ix_core_value_id`), - KEY `c_13ac23dd` (`ix_core_value_id`), - KEY `fkjg8tmtxlf4d2vnb90e6i7exg0` (`properties_id`), - CONSTRAINT `c_13ac23dd` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_633c0170` FOREIGN KEY (`ix_core_procrec_id`) REFERENCES `ix_core_procrec` (`id`), - CONSTRAINT `fkjg8tmtxlf4d2vnb90e6i7exg0` FOREIGN KEY (`properties_id`) REFERENCES `ix_core_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_procrec_seq` --- - -DROP TABLE IF EXISTS `ix_core_procrec_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_procrec_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_pubauthor` --- - -DROP TABLE IF EXISTS `ix_core_pubauthor`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_pubauthor` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `position` int(11) DEFAULT NULL, - `is_last` tinyint(1) DEFAULT 0, - `correspondence` tinyint(1) DEFAULT 0, - `author_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_962a3366` (`author_id`), - CONSTRAINT `c_6fb86703` FOREIGN KEY (`author_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_publication` --- - -DROP TABLE IF EXISTS `ix_core_publication`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_publication` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `pmid` bigint(20) DEFAULT NULL, - `pmcid` varchar(255) DEFAULT NULL, - `title` longtext DEFAULT NULL, - `pages` varchar(255) DEFAULT NULL, - `doi` varchar(255) DEFAULT NULL, - `abstract_text` longtext DEFAULT NULL, - `journal_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_d2188a90` (`pmid`), - UNIQUE KEY `c_388c2569` (`pmcid`), - KEY `i_773c6776` (`journal_id`), - CONSTRAINT `c_35349138` FOREIGN KEY (`journal_id`) REFERENCES `ix_core_journal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_publication_author` --- - -DROP TABLE IF EXISTS `ix_core_publication_author`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_publication_author` ( - `ix_core_publication_id` bigint(20) NOT NULL, - `ix_core_pubauthor_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_publication_id`,`ix_core_pubauthor_id`), - KEY `c_9f462072` (`ix_core_pubauthor_id`), - CONSTRAINT `c_6954fa07` FOREIGN KEY (`ix_core_publication_id`) REFERENCES `ix_core_publication` (`id`), - CONSTRAINT `c_9f462072` FOREIGN KEY (`ix_core_pubauthor_id`) REFERENCES `ix_core_pubauthor` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_publication_figure` --- - -DROP TABLE IF EXISTS `ix_core_publication_figure`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_publication_figure` ( - `ix_core_publication_id` bigint(20) NOT NULL, - `ix_core_figure_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_publication_id`,`ix_core_figure_id`), - KEY `c_229b7533` (`ix_core_figure_id`), - CONSTRAINT `c_01454ae4` FOREIGN KEY (`ix_core_publication_id`) REFERENCES `ix_core_publication` (`id`), - CONSTRAINT `c_229b7533` FOREIGN KEY (`ix_core_figure_id`) REFERENCES `ix_core_figure` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_publication_keyword` --- - -DROP TABLE IF EXISTS `ix_core_publication_keyword`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_publication_keyword` ( - `ix_core_publication_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_publication_id`,`ix_core_value_id`), - KEY `c_aebecf49` (`ix_core_value_id`), - CONSTRAINT `c_aebecf49` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_c0cadd3d` FOREIGN KEY (`ix_core_publication_id`) REFERENCES `ix_core_publication` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_publication_mesh` --- - -DROP TABLE IF EXISTS `ix_core_publication_mesh`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_publication_mesh` ( - `ix_core_publication_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_publication_id`,`ix_core_value_id`), - KEY `c_00f5160e` (`ix_core_value_id`), - CONSTRAINT `c_00f5160e` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_5c0daa3c` FOREIGN KEY (`ix_core_publication_id`) REFERENCES `ix_core_publication` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_session` --- - -DROP TABLE IF EXISTS `ix_core_session`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_session` ( - `id` varchar(40) NOT NULL, - `profile_id` bigint(20) DEFAULT NULL, - `created` bigint(20) DEFAULT NULL, - `accessed` bigint(20) DEFAULT NULL, - `location` varchar(255) DEFAULT NULL, - `expired` tinyint(1) DEFAULT 0, - PRIMARY KEY (`id`), - KEY `i_3e903ae6` (`profile_id`), - CONSTRAINT `c_1a9538dc` FOREIGN KEY (`profile_id`) REFERENCES `ix_core_userprof` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_stitch` --- - -DROP TABLE IF EXISTS `ix_core_stitch`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_stitch` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - `impl` varchar(1024) DEFAULT NULL, - `description` longtext DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_stitch_attribute` --- - -DROP TABLE IF EXISTS `ix_core_stitch_attribute`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_stitch_attribute` ( - `ix_core_stitch_id` bigint(20) NOT NULL, - `ix_core_attribute_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_stitch_id`,`ix_core_attribute_id`), - KEY `c_01938a37` (`ix_core_attribute_id`), - CONSTRAINT `c_01938a37` FOREIGN KEY (`ix_core_attribute_id`) REFERENCES `ix_core_attribute` (`id`), - CONSTRAINT `c_c9d83c50` FOREIGN KEY (`ix_core_stitch_id`) REFERENCES `ix_core_stitch` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_structure` --- - -DROP TABLE IF EXISTS `ix_core_structure`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_structure` ( - `dtype` varchar(10) NOT NULL, - `id` varchar(40) NOT NULL, - `created` datetime DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `digest` varchar(128) DEFAULT NULL, - `molfile` longtext DEFAULT NULL, - `smiles` longtext DEFAULT NULL, - `formula` varchar(255) DEFAULT NULL, - `stereo` varchar(255) DEFAULT NULL, - `optical` int(11) DEFAULT NULL, - `atropi` int(11) DEFAULT NULL, - `stereo_comments` longtext DEFAULT NULL, - `stereo_centers` int(11) DEFAULT NULL, - `defined_stereo` int(11) DEFAULT NULL, - `ez_centers` int(11) DEFAULT NULL, - `charge` int(11) DEFAULT NULL, - `mwt` double DEFAULT NULL, - `count` int(11) DEFAULT NULL, - `version` bigint(20) NOT NULL, - `internal_references` longtext DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `record_access` varbinary(255) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_97f0d7b1` (`created_by_id`), - KEY `i_86d0302b` (`last_edited_by_id`), - CONSTRAINT `c_d4a49424` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_f0993eb0` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_structure_link` --- - -DROP TABLE IF EXISTS `ix_core_structure_link`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_structure_link` ( - `ix_core_structure_id` varchar(40) NOT NULL, - `ix_core_xref_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_structure_id`,`ix_core_xref_id`), - KEY `c_40d92d08` (`ix_core_xref_id`), - CONSTRAINT `c_40d92d08` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`), - CONSTRAINT `c_55f5450b` FOREIGN KEY (`ix_core_structure_id`) REFERENCES `ix_core_structure` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_structure_property` --- - -DROP TABLE IF EXISTS `ix_core_structure_property`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_structure_property` ( - `ix_core_structure_id` varchar(40) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_structure_id`,`ix_core_value_id`), - KEY `c_72b2a857` (`ix_core_value_id`), - KEY `property_structure_id_index` (`ix_core_structure_id`), - KEY `property_value_id_index` (`ix_core_value_id`), - CONSTRAINT `c_634d3d46` FOREIGN KEY (`ix_core_structure_id`) REFERENCES `ix_core_structure` (`id`), - CONSTRAINT `c_72b2a857` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_timeline` --- - -DROP TABLE IF EXISTS `ix_core_timeline`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_timeline` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_timeline_event` --- - -DROP TABLE IF EXISTS `ix_core_timeline_event`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_timeline_event` ( - `ix_core_timeline_id` bigint(20) NOT NULL, - `ix_core_event_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_timeline_id`,`ix_core_event_id`), - KEY `c_f4784b80` (`ix_core_event_id`), - CONSTRAINT `c_2c85a4b0` FOREIGN KEY (`ix_core_timeline_id`) REFERENCES `ix_core_timeline` (`id`), - CONSTRAINT `c_f4784b80` FOREIGN KEY (`ix_core_event_id`) REFERENCES `ix_core_event` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_user_saved_list` --- - -DROP TABLE IF EXISTS `ix_core_user_saved_list`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_user_saved_list` ( - `id` bigint(20) NOT NULL, - `list` longtext DEFAULT NULL, - `name` varchar(255) NOT NULL, - `user_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `uknftwibs7mebodwpavq6ub0lqh` (`name`,`user_id`), - KEY `fkhd1bc5m9wxca27lxoexqjfwei` (`user_id`), - CONSTRAINT `fkhd1bc5m9wxca27lxoexqjfwei` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_userprof` --- - -DROP TABLE IF EXISTS `ix_core_userprof`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_userprof` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `user_id` bigint(20) DEFAULT NULL, - `active` tinyint(1) DEFAULT 0, - `hashp` varchar(255) DEFAULT NULL, - `salt` varchar(255) DEFAULT NULL, - `system_auth` tinyint(1) DEFAULT 0, - `roles_json` longtext DEFAULT NULL, - `apikey` varchar(255) DEFAULT NULL, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - KEY `i_278ce9be` (`namespace_id`), - KEY `i_b7398fef` (`user_id`), - CONSTRAINT `c_3fac3cac` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`), - CONSTRAINT `c_91de8ced` FOREIGN KEY (`user_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=10014 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = latin1 */ ; -/*!50003 SET character_set_results = latin1 */ ; -/*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; -DELIMITER ;; -/*!50003 CREATE*/ /*!50003 TRIGGER ix_core_userprof_update_roles BEFORE UPDATE ON ix_core_userprof -FOR EACH ROW -BEGIN - IF NEW.roles_json IS NULL THEN - SET NEW.roles_json = '["Query","Updater","SuperUpdate","DataEntry","SuperDataEntry"]'; - END IF; -END */;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; - --- --- Table structure for table `ix_core_userprof_prop` --- - -DROP TABLE IF EXISTS `ix_core_userprof_prop`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_userprof_prop` ( - `ix_core_userprof_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_userprof_id`,`ix_core_value_id`), - KEY `c_cc1c20b1` (`ix_core_value_id`), - CONSTRAINT `c_74285f69` FOREIGN KEY (`ix_core_userprof_id`) REFERENCES `ix_core_userprof` (`id`), - CONSTRAINT `c_cc1c20b1` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_userprof_seq` --- - -DROP TABLE IF EXISTS `ix_core_userprof_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_userprof_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_value` --- - -DROP TABLE IF EXISTS `ix_core_value`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_value` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `label` varchar(255) DEFAULT NULL, - `term` varchar(255) DEFAULT NULL, - `href` longtext DEFAULT NULL, - `major_topic` tinyint(1) DEFAULT 0, - `heading` varchar(1024) DEFAULT NULL, - `text` longtext DEFAULT NULL, - `data` longblob DEFAULT NULL, - `data_size` int(11) DEFAULT NULL, - `sha1` varchar(40) DEFAULT NULL, - `mime_type` varchar(32) DEFAULT NULL, - `intval` bigint(20) DEFAULT NULL, - `numval` double DEFAULT NULL, - `unit` varchar(255) DEFAULT NULL, - `lval` double DEFAULT NULL, - `rval` double DEFAULT NULL, - `average` double DEFAULT NULL, - `strval` varchar(1024) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `value_label_index` (`label`), - KEY `value_term_index` (`term`) -) ENGINE=InnoDB AUTO_INCREMENT=54371927 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_value_seq` --- - -DROP TABLE IF EXISTS `ix_core_value_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_value_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_xref` --- - -DROP TABLE IF EXISTS `ix_core_xref`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_xref` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `refid` varchar(40) NOT NULL, - `kind` varchar(255) NOT NULL, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - KEY `i_8bbd04dc` (`namespace_id`), - KEY `xref_refid_index` (`refid`), - KEY `xref_kind_index` (`kind`), - CONSTRAINT `c_76da580e` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=5153780 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_xref_property` --- - -DROP TABLE IF EXISTS `ix_core_xref_property`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_xref_property` ( - `ix_core_xref_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_core_xref_id`,`ix_core_value_id`), - KEY `c_07052a0b` (`ix_core_value_id`), - CONSTRAINT `c_07052a0b` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_c56225d5` FOREIGN KEY (`ix_core_xref_id`) REFERENCES `ix_core_xref` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_core_xref_seq` --- - -DROP TABLE IF EXISTS `ix_core_xref_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_core_xref_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_agentmod` --- - -DROP TABLE IF EXISTS `ix_ginas_agentmod`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_agentmod` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `agent_modification_process` varchar(255) DEFAULT NULL, - `agent_modification_role` varchar(255) DEFAULT NULL, - `agent_modification_type` varchar(255) DEFAULT NULL, - `agent_substance_uuid` varchar(40) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - `modification_group` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_e8fec8b0` (`created_by_id`), - KEY `i_797c3291` (`last_edited_by_id`), - KEY `i_90654d9b` (`owner_uuid`), - KEY `i_916a29a3` (`agent_substance_uuid`), - KEY `i_8048764d` (`amount_uuid`), - CONSTRAINT `c_09a65704` FOREIGN KEY (`agent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_60a9acb3` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), - CONSTRAINT `c_d284f5d7` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_d5922695` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_fbcb8c5e` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_amount` --- - -DROP TABLE IF EXISTS `ix_ginas_amount`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_amount` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `average` double DEFAULT NULL, - `high_limit` double DEFAULT NULL, - `high` double DEFAULT NULL, - `low_limit` double DEFAULT NULL, - `low` double DEFAULT NULL, - `units` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `non_numeric_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `approval_id` varchar(10) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_9044f8e6` (`created_by_id`), - KEY `i_1396ad0a` (`last_edited_by_id`), - CONSTRAINT `c_172b3d49` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_48c42eee` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_code` --- - -DROP TABLE IF EXISTS `ix_ginas_code`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_code` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `code_system` varchar(255) DEFAULT NULL, - `code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `comments` longtext DEFAULT NULL, - `code_text` longtext DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `url` longtext DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_edc5bb41` (`created_by_id`), - KEY `i_aa0faf44` (`last_edited_by_id`), - KEY `i_1e97fd27` (`owner_uuid`), - KEY `code_index` (`code`), - KEY `code_system_index` (`code_system`), - KEY `code_code_system_index` (`code`,`code_system`), - KEY `ix_ix_ginas_code_code` (`code`), - KEY `ix_ix_ginas_code_code_system` (`code_system`), - KEY `ix_ix_ginas_code_type` (`type`), - KEY `ix_ix_ginas_code_owner` (`owner_uuid`), - CONSTRAINT `c_1d85e0b8` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_31873b2b` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_7c279009` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_component` --- - -DROP TABLE IF EXISTS `ix_ginas_component`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_component` ( - `dtype` varchar(10) NOT NULL, - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `substance_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - `role` varchar(255) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - PRIMARY KEY (`uuid`), - KEY `i_1204b09e` (`created_by_id`), - KEY `i_992c5a03` (`last_edited_by_id`), - KEY `i_c5a4340b` (`substance_uuid`), - KEY `i_ec7c7e9a` (`amount_uuid`), - CONSTRAINT `c_175162da` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_358de474` FOREIGN KEY (`substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_966c1285` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_c2cfb61d` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_controlled_vocab` --- - -DROP TABLE IF EXISTS `ix_ginas_controlled_vocab`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_controlled_vocab` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `domain` varchar(255) DEFAULT NULL, - `vocabulary_term_type` varchar(255) DEFAULT NULL, - `editable` tinyint(1) DEFAULT 0, - `filterable` tinyint(1) DEFAULT 0, - `version` bigint(20) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `c_5afb2826` (`domain`), - KEY `i_f95f237a` (`namespace_id`), - CONSTRAINT `c_b23afb26` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=4397 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_controlled_vocab_core_value` --- - -DROP TABLE IF EXISTS `ix_ginas_controlled_vocab_core_value`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_controlled_vocab_core_value` ( - `ix_ginas_controlled_vocab_id` bigint(20) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_ginas_controlled_vocab_id`,`ix_core_value_id`), - KEY `c_ac65921f` (`ix_core_value_id`), - CONSTRAINT `c_ac65921f` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_d583143a` FOREIGN KEY (`ix_ginas_controlled_vocab_id`) REFERENCES `ix_ginas_controlled_vocab` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_controlled_vocab_seq` --- - -DROP TABLE IF EXISTS `ix_ginas_controlled_vocab_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_controlled_vocab_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_definition` --- - -DROP TABLE IF EXISTS `ix_ginas_definition`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_definition` ( - `uuid` varchar(40) NOT NULL, - `created` datetime(6) DEFAULT NULL, - `current_version` int(11) NOT NULL, - `deprecated` bit(1) NOT NULL, - `internal_version` bigint(20) DEFAULT NULL, - `last_edited` datetime(6) DEFAULT NULL, - `record_access` mediumblob DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `definition` longtext DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - PRIMARY KEY (`uuid`), - KEY `fk4kcslc98jcqx137enxl5fgs5t` (`created_by_id`), - KEY `fk9wxg9p9i1bi7qoxfcu9gkg9og` (`last_edited_by_id`), - CONSTRAINT `fk4kcslc98jcqx137enxl5fgs5t` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `fk9wxg9p9i1bi7qoxfcu9gkg9og` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_glycosylation` --- - -DROP TABLE IF EXISTS `ix_ginas_glycosylation`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_glycosylation` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `c_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, - `n_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, - `o_glycosylation_sites_uuid` varchar(40) DEFAULT NULL, - `glycosylation_type` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_f243b84a` (`created_by_id`), - KEY `i_e6735e70` (`last_edited_by_id`), - KEY `i_a41ea995` (`c_glycosylation_sites_uuid`), - KEY `i_e167ac5a` (`n_glycosylation_sites_uuid`), - KEY `i_6caedade` (`o_glycosylation_sites_uuid`), - CONSTRAINT `c_22d42e85` FOREIGN KEY (`c_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_8ddb40b1` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_b1b38f93` FOREIGN KEY (`n_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_b501c304` FOREIGN KEY (`o_glycosylation_sites_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_d9f835a6` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_linkage` --- - -DROP TABLE IF EXISTS `ix_ginas_linkage`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_linkage` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `linkage` varchar(255) DEFAULT NULL, - `site_container_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_69e7b2a7` (`created_by_id`), - KEY `i_5c50e6ba` (`last_edited_by_id`), - KEY `i_31291300` (`owner_uuid`), - KEY `i_3eff1028` (`site_container_uuid`), - CONSTRAINT `c_a8c5dc9e` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_ae6b03c1` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_ca67400b` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_de82d9a4` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_material` --- - -DROP TABLE IF EXISTS `ix_ginas_material`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_material` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - `monomer_substance_uuid` varchar(40) DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `defining` tinyint(1) DEFAULT 0, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_57660fad` (`created_by_id`), - KEY `i_6b6bb6e1` (`last_edited_by_id`), - KEY `i_6dc373fb` (`owner_uuid`), - KEY `i_2cb0b2dd` (`amount_uuid`), - KEY `i_7c19cf3c` (`monomer_substance_uuid`), - CONSTRAINT `c_228619ce` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_8be1479b` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`), - CONSTRAINT `c_e02e47e1` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_e72e3a1f` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_eede4a4e` FOREIGN KEY (`monomer_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_mixture` --- - -DROP TABLE IF EXISTS `ix_ginas_mixture`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_mixture` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `parent_substance_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_873527b2` (`created_by_id`), - KEY `i_046c8793` (`last_edited_by_id`), - KEY `i_8589cf27` (`parent_substance_uuid`), - CONSTRAINT `c_4b599f1d` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_c531797e` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_e140e14f` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_modifications` --- - -DROP TABLE IF EXISTS `ix_ginas_modifications`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_modifications` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_cd4ce51a` (`created_by_id`), - KEY `i_9f57a27d` (`last_edited_by_id`), - CONSTRAINT `c_d0121858` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_db44363c` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_moiety` --- - -DROP TABLE IF EXISTS `ix_ginas_moiety`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_moiety` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `structure_id` varchar(40) DEFAULT NULL, - `count_uuid` varchar(40) DEFAULT NULL, - `inner_uuid` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - UNIQUE KEY `c_ce8c5912` (`inner_uuid`), - KEY `i_59b3b423` (`created_by_id`), - KEY `i_521b68cd` (`last_edited_by_id`), - KEY `i_9b5117f0` (`owner_uuid`), - KEY `i_9448f241` (`structure_id`), - KEY `i_c7272b24` (`count_uuid`), - KEY `moiety_owner_index` (`owner_uuid`), - CONSTRAINT `c_1e35889c` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_4a0fd12e` FOREIGN KEY (`count_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_6c4e84d5` FOREIGN KEY (`structure_id`) REFERENCES `ix_core_structure` (`id`), - CONSTRAINT `c_79e8cf95` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_b45ca216` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_name` --- - -DROP TABLE IF EXISTS `ix_ginas_name`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_name` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `full_name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `std_name` longtext DEFAULT NULL, - `type` varchar(32) DEFAULT NULL, - `domains` longtext DEFAULT NULL, - `languages` longtext DEFAULT NULL, - `name_jurisdiction` longtext DEFAULT NULL, - `preferred` tinyint(1) DEFAULT 0, - `display_name` tinyint(1) DEFAULT 0, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_d0a3e858` (`created_by_id`), - KEY `i_e6a2fb51` (`last_edited_by_id`), - KEY `i_25e68980` (`owner_uuid`), - KEY `name_index` (`name`), - KEY `name_owner_index` (`owner_uuid`), - CONSTRAINT `c_3cdaab27` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_52348b70` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_d3d75121` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_nameorg` --- - -DROP TABLE IF EXISTS `ix_ginas_nameorg`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_nameorg` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `name_org` varchar(255) NOT NULL, - `deprecated_date` datetime DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_0af6ec35` (`created_by_id`), - KEY `i_9a2588f9` (`last_edited_by_id`), - KEY `i_14ebb953` (`owner_uuid`), - KEY `nameorg_owner_index` (`owner_uuid`), - CONSTRAINT `c_17af48a9` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_name` (`uuid`), - CONSTRAINT `c_4d1f3b68` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_7104c31d` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_note` --- - -DROP TABLE IF EXISTS `ix_ginas_note`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_note` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `note` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_9cf176b5` (`created_by_id`), - KEY `i_53803677` (`last_edited_by_id`), - KEY `i_236d20c3` (`owner_uuid`), - KEY `note_owner_index` (`owner_uuid`), - CONSTRAINT `c_520232f3` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_81b64cae` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_e6509aec` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_nucleicacid` --- - -DROP TABLE IF EXISTS `ix_ginas_nucleicacid`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_nucleicacid` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `modifications_uuid` varchar(40) DEFAULT NULL, - `nucleic_acid_type` varchar(255) DEFAULT NULL, - `nucleic_acid_sub_type` varchar(255) DEFAULT NULL, - `sequence_origin` varchar(255) DEFAULT NULL, - `sequence_type` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_c8ea3507` (`created_by_id`), - KEY `i_b8ebab65` (`last_edited_by_id`), - KEY `i_a1392a03` (`modifications_uuid`), - CONSTRAINT `c_959b9999` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_bb280648` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_eeb5efc7` FOREIGN KEY (`modifications_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_nucleicacid_subunits` --- - -DROP TABLE IF EXISTS `ix_ginas_nucleicacid_subunits`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_nucleicacid_subunits` ( - `ix_ginas_nucleicacid_uuid` varchar(40) NOT NULL, - `ix_ginas_subunit_uuid` varchar(40) NOT NULL, - PRIMARY KEY (`ix_ginas_nucleicacid_uuid`,`ix_ginas_subunit_uuid`), - KEY `c_2d109af2` (`ix_ginas_subunit_uuid`), - CONSTRAINT `c_2d109af2` FOREIGN KEY (`ix_ginas_subunit_uuid`) REFERENCES `ix_ginas_subunit` (`uuid`), - CONSTRAINT `c_5de01eee` FOREIGN KEY (`ix_ginas_nucleicacid_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_otherlinks` --- - -DROP TABLE IF EXISTS `ix_ginas_otherlinks`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_otherlinks` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `linkage_type` varchar(255) DEFAULT NULL, - `site_container_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_fd4e4062` (`created_by_id`), - KEY `i_a755aebd` (`last_edited_by_id`), - KEY `i_a90e8053` (`owner_uuid`), - KEY `i_995b649a` (`site_container_uuid`), - CONSTRAINT `c_11058b93` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_protein` (`uuid`), - CONSTRAINT `c_5e78f982` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_a0829419` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_ff3037e8` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_parameter` --- - -DROP TABLE IF EXISTS `ix_ginas_parameter`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_parameter` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `referenced_substance_uuid` varchar(40) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `type` varchar(255) DEFAULT NULL, - `value_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_a0c76346` (`created_by_id`), - KEY `i_bc65cddb` (`last_edited_by_id`), - KEY `i_97bca746` (`owner_uuid`), - KEY `i_75718d16` (`referenced_substance_uuid`), - KEY `i_b9a77f65` (`value_uuid`), - CONSTRAINT `c_a24936da` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_bc99c270` FOREIGN KEY (`value_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_bd1f6900` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_e991be08` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_property` (`uuid`), - CONSTRAINT `c_f176d1eb` FOREIGN KEY (`referenced_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_physicalmod` --- - -DROP TABLE IF EXISTS `ix_ginas_physicalmod`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_physicalmod` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `physical_modification_role` varchar(255) DEFAULT NULL, - `modification_group` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_0b062bce` (`created_by_id`), - KEY `i_7c71774f` (`last_edited_by_id`), - KEY `i_023e1ac8` (`owner_uuid`), - CONSTRAINT `c_6d989fc6` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_744c488c` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_c141927f` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_physicalpar` --- - -DROP TABLE IF EXISTS `ix_ginas_physicalpar`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_physicalpar` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `parameter_name` varchar(255) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_212447c4` (`created_by_id`), - KEY `i_75c04a35` (`last_edited_by_id`), - KEY `i_082ca133` (`owner_uuid`), - KEY `i_1eb217f4` (`amount_uuid`), - CONSTRAINT `c_034e2f7c` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_b595e4ba` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_dc5bce39` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_e0845807` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_physicalmod` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_polymer` --- - -DROP TABLE IF EXISTS `ix_ginas_polymer`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_polymer` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `classification_uuid` varchar(40) DEFAULT NULL, - `display_structure_id` varchar(40) DEFAULT NULL, - `idealized_structure_id` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_508683b0` (`created_by_id`), - KEY `i_8356da61` (`last_edited_by_id`), - KEY `i_3e38b877` (`classification_uuid`), - KEY `i_3c66be92` (`display_structure_id`), - KEY `i_48e4a01f` (`idealized_structure_id`), - CONSTRAINT `c_2cda8114` FOREIGN KEY (`display_structure_id`) REFERENCES `ix_core_structure` (`id`), - CONSTRAINT `c_5f9c7f23` FOREIGN KEY (`classification_uuid`) REFERENCES `polymer_classification` (`uuid`), - CONSTRAINT `c_a83467a2` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_d21ee884` FOREIGN KEY (`idealized_structure_id`) REFERENCES `ix_core_structure` (`id`), - CONSTRAINT `c_d85112ff` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_property` --- - -DROP TABLE IF EXISTS `ix_ginas_property`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_property` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `type` varchar(255) DEFAULT NULL, - `property_type` varchar(255) DEFAULT NULL, - `value_uuid` varchar(40) DEFAULT NULL, - `referenced_substance_uuid` varchar(40) DEFAULT NULL, - `defining` tinyint(1) DEFAULT 0, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_6f12c2a9` (`created_by_id`), - KEY `i_7a9b0f71` (`last_edited_by_id`), - KEY `i_434f1898` (`owner_uuid`), - KEY `i_dc5306ee` (`value_uuid`), - KEY `i_18c70ecb` (`referenced_substance_uuid`), - KEY `property_owner_index` (`owner_uuid`), - CONSTRAINT `c_1824202b` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_1f9e699f` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_3a23d2a9` FOREIGN KEY (`referenced_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_5330547a` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_ef8b2c10` FOREIGN KEY (`value_uuid`) REFERENCES `ix_ginas_amount` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_protein` --- - -DROP TABLE IF EXISTS `ix_ginas_protein`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_protein` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `protein_type` varchar(255) DEFAULT NULL, - `protein_sub_type` varchar(255) DEFAULT NULL, - `sequence_origin` varchar(255) DEFAULT NULL, - `sequence_type` varchar(255) DEFAULT NULL, - `disulf_json` longtext DEFAULT NULL, - `glycosylation_uuid` varchar(40) DEFAULT NULL, - `modifications_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_c07043ef` (`created_by_id`), - KEY `i_32cafedb` (`last_edited_by_id`), - KEY `i_75436589` (`glycosylation_uuid`), - KEY `i_fcca9817` (`modifications_uuid`), - CONSTRAINT `c_3e88fd93` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_4f44d62a` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_a6fb4ff8` FOREIGN KEY (`modifications_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), - CONSTRAINT `c_bcc47a8d` FOREIGN KEY (`glycosylation_uuid`) REFERENCES `ix_ginas_glycosylation` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_protein_subunit` --- - -DROP TABLE IF EXISTS `ix_ginas_protein_subunit`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_protein_subunit` ( - `ix_ginas_protein_uuid` varchar(40) NOT NULL, - `ix_ginas_subunit_uuid` varchar(40) NOT NULL, - PRIMARY KEY (`ix_ginas_protein_uuid`,`ix_ginas_subunit_uuid`), - KEY `c_0f1fc6ff` (`ix_ginas_subunit_uuid`), - CONSTRAINT `c_0f1fc6ff` FOREIGN KEY (`ix_ginas_subunit_uuid`) REFERENCES `ix_ginas_subunit` (`uuid`), - CONSTRAINT `c_819d6150` FOREIGN KEY (`ix_ginas_protein_uuid`) REFERENCES `ix_ginas_protein` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_reference` --- - -DROP TABLE IF EXISTS `ix_ginas_reference`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_reference` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `citation` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `doc_type` varchar(255) DEFAULT NULL, - `document_date` datetime DEFAULT NULL, - `public_domain` tinyint(1) DEFAULT 0, - `tags` longtext DEFAULT NULL, - `uploaded_file` varchar(1024) DEFAULT NULL, - `id` varchar(255) DEFAULT NULL, - `url` longtext DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_2ba5b3d5` (`created_by_id`), - KEY `i_80ef682b` (`last_edited_by_id`), - KEY `i_3ccbbc1c` (`owner_uuid`), - KEY `ref_id_index` (`id`), - KEY `ref_owner_index` (`owner_uuid`), - CONSTRAINT `c_071569ce` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_cbd3863e` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_df17ffc0` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_relationship` --- - -DROP TABLE IF EXISTS `ix_ginas_relationship`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_relationship` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - `comments` longtext DEFAULT NULL, - `interaction_type` varchar(255) DEFAULT NULL, - `qualification` varchar(255) DEFAULT NULL, - `related_substance_uuid` varchar(40) DEFAULT NULL, - `mediator_substance_uuid` varchar(40) DEFAULT NULL, - `originator_uuid` varchar(255) DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_1e1d5825` (`created_by_id`), - KEY `i_61241701` (`last_edited_by_id`), - KEY `i_47b6e4f0` (`owner_uuid`), - KEY `i_b5235fc5` (`amount_uuid`), - KEY `i_39d89a99` (`related_substance_uuid`), - KEY `i_4195462c` (`mediator_substance_uuid`), - KEY `interaction_index` (`interaction_type`), - KEY `qualification_index` (`qualification`), - KEY `type_index` (`type`), - KEY `relate_originate_index` (`originator_uuid`), - KEY `rel_owner_index` (`owner_uuid`), - CONSTRAINT `c_337c9ac9` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_62502be5` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_936c0c00` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_a3fdf047` FOREIGN KEY (`related_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_d433b684` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_e4bb9034` FOREIGN KEY (`mediator_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_site_lob` --- - -DROP TABLE IF EXISTS `ix_ginas_site_lob`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_site_lob` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `sites_short_hand` longtext DEFAULT NULL, - `sites_json` longtext DEFAULT NULL, - `site_count` bigint(20) DEFAULT NULL, - `site_type` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_3215d1f7` (`created_by_id`), - KEY `i_2d4558ef` (`last_edited_by_id`), - CONSTRAINT `c_0fd266c8` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_70f007e0` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_ssg1` --- - -DROP TABLE IF EXISTS `ix_ginas_ssg1`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_ssg1` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_c7f61a0d` (`created_by_id`), - KEY `i_043f1e31` (`last_edited_by_id`), - CONSTRAINT `c_13cf7618` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_1763863d` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_strucdiv` --- - -DROP TABLE IF EXISTS `ix_ginas_strucdiv`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_strucdiv` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `source_material_class` varchar(255) DEFAULT NULL, - `source_material_type` varchar(255) DEFAULT NULL, - `source_material_state` varchar(255) DEFAULT NULL, - `organism_family` varchar(255) DEFAULT NULL, - `organism_genus` varchar(255) DEFAULT NULL, - `organism_species` varchar(255) DEFAULT NULL, - `organism_author` varchar(255) DEFAULT NULL, - `part_location` varchar(255) DEFAULT NULL, - `part` longtext DEFAULT NULL, - `infra_specific_type` varchar(255) DEFAULT NULL, - `infra_specific_name` varchar(255) DEFAULT NULL, - `developmental_stage` varchar(255) DEFAULT NULL, - `fraction_name` varchar(255) DEFAULT NULL, - `fraction_material_type` varchar(255) DEFAULT NULL, - `paternal_uuid` varchar(40) DEFAULT NULL, - `maternal_uuid` varchar(40) DEFAULT NULL, - `parent_substance_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_2d8cf3af` (`created_by_id`), - KEY `i_9f0fd61b` (`last_edited_by_id`), - KEY `i_b8220566` (`paternal_uuid`), - KEY `i_ce3e8a36` (`maternal_uuid`), - KEY `i_feb57d17` (`parent_substance_uuid`), - CONSTRAINT `c_59e96282` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_7bf1c14b` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_d4abc04c` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_efc8abcb` FOREIGN KEY (`maternal_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`), - CONSTRAINT `c_f9c74f43` FOREIGN KEY (`paternal_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_structuralmod` --- - -DROP TABLE IF EXISTS `ix_ginas_structuralmod`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_structuralmod` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `structural_modification_type` varchar(255) DEFAULT NULL, - `location_type` varchar(255) DEFAULT NULL, - `residue_modified` varchar(255) DEFAULT NULL, - `site_container_uuid` varchar(40) DEFAULT NULL, - `extent` varchar(255) DEFAULT NULL, - `extent_amount_uuid` varchar(40) DEFAULT NULL, - `molecular_fragment_uuid` varchar(40) DEFAULT NULL, - `moleculare_fragment_role` varchar(255) DEFAULT NULL, - `modification_group` varchar(255) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_7d778ca2` (`created_by_id`), - KEY `i_f48ed7eb` (`last_edited_by_id`), - KEY `i_cb2f3eab` (`owner_uuid`), - KEY `i_54af7999` (`site_container_uuid`), - KEY `i_91129afe` (`extent_amount_uuid`), - KEY `i_488d4d1a` (`molecular_fragment_uuid`), - CONSTRAINT `c_2144c64c` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_633ba313` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_d6fed8e4` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), - CONSTRAINT `c_d9a4a985` FOREIGN KEY (`extent_amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_f6bac92e` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_fbb8858e` FOREIGN KEY (`molecular_fragment_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_substance` --- - -DROP TABLE IF EXISTS `ix_ginas_substance`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_substance` ( - `dtype` varchar(10) NOT NULL, - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `definition_type` int(11) DEFAULT NULL, - `definition_level` int(11) DEFAULT NULL, - `class` int(11) DEFAULT NULL, - `status` varchar(255) DEFAULT NULL, - `version` varchar(255) DEFAULT NULL, - `approved_by_id` bigint(20) DEFAULT NULL, - `approved` datetime DEFAULT NULL, - `change_reason` varchar(255) DEFAULT NULL, - `modifications_uuid` varchar(40) DEFAULT NULL, - `approval_id` varchar(10) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - `structure_id` varchar(40) DEFAULT NULL, - `mixture_uuid` varchar(40) DEFAULT NULL, - `nucleic_acid_uuid` varchar(40) DEFAULT NULL, - `polymer_uuid` varchar(40) DEFAULT NULL, - `protein_uuid` varchar(40) DEFAULT NULL, - `specified_substance_uuid` varchar(40) DEFAULT NULL, - `structurally_diverse_uuid` varchar(40) DEFAULT NULL, - PRIMARY KEY (`uuid`), - KEY `i_017dd520` (`created_by_id`), - KEY `i_fa710fd0` (`last_edited_by_id`), - KEY `i_501769c0` (`approved_by_id`), - KEY `i_3062c782` (`modifications_uuid`), - KEY `i_5f8e95e3` (`structure_id`), - KEY `i_bd94d543` (`mixture_uuid`), - KEY `i_57ae22d0` (`nucleic_acid_uuid`), - KEY `i_ce536a5e` (`polymer_uuid`), - KEY `i_23563b9c` (`protein_uuid`), - KEY `i_47e7be29` (`specified_substance_uuid`), - KEY `i_7b7cc8b8` (`structurally_diverse_uuid`), - KEY `sub_approval_index` (`approval_id`), - KEY `sub_dtype_index` (`dtype`), - CONSTRAINT `c_032cfcd1` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_1ca5b4ff` FOREIGN KEY (`modifications_uuid`) REFERENCES `ix_ginas_modifications` (`uuid`), - CONSTRAINT `c_254367aa` FOREIGN KEY (`polymer_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`), - CONSTRAINT `c_2a618519` FOREIGN KEY (`nucleic_acid_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`), - CONSTRAINT `c_58b246cd` FOREIGN KEY (`approved_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_6a75f028` FOREIGN KEY (`structure_id`) REFERENCES `ix_core_structure` (`id`), - CONSTRAINT `c_8c408528` FOREIGN KEY (`structurally_diverse_uuid`) REFERENCES `ix_ginas_strucdiv` (`uuid`), - CONSTRAINT `c_a38cec20` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_abe2e656` FOREIGN KEY (`specified_substance_uuid`) REFERENCES `ix_ginas_ssg1` (`uuid`), - CONSTRAINT `c_c9363aed` FOREIGN KEY (`protein_uuid`) REFERENCES `ix_ginas_protein` (`uuid`), - CONSTRAINT `c_e3fbf5c3` FOREIGN KEY (`mixture_uuid`) REFERENCES `ix_ginas_mixture` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_substance_mix_comp` --- - -DROP TABLE IF EXISTS `ix_ginas_substance_mix_comp`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_substance_mix_comp` ( - `ix_ginas_mixture_uuid` varchar(40) NOT NULL, - `ix_ginas_component_uuid` varchar(40) NOT NULL, - PRIMARY KEY (`ix_ginas_mixture_uuid`,`ix_ginas_component_uuid`), - KEY `c_0b03e134` (`ix_ginas_component_uuid`), - CONSTRAINT `c_0b03e134` FOREIGN KEY (`ix_ginas_component_uuid`) REFERENCES `ix_ginas_component` (`uuid`), - CONSTRAINT `c_0cedb7b8` FOREIGN KEY (`ix_ginas_mixture_uuid`) REFERENCES `ix_ginas_mixture` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_substance_ss_comp` --- - -DROP TABLE IF EXISTS `ix_ginas_substance_ss_comp`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_substance_ss_comp` ( - `ix_ginas_ssg1_uuid` varchar(40) NOT NULL, - `ix_ginas_component_uuid` varchar(40) NOT NULL, - PRIMARY KEY (`ix_ginas_ssg1_uuid`,`ix_ginas_component_uuid`), - KEY `c_fdd7602a` (`ix_ginas_component_uuid`), - CONSTRAINT `c_a5b1f22a` FOREIGN KEY (`ix_ginas_ssg1_uuid`) REFERENCES `ix_ginas_ssg1` (`uuid`), - CONSTRAINT `c_fdd7602a` FOREIGN KEY (`ix_ginas_component_uuid`) REFERENCES `ix_ginas_component` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_substance_tags` --- - -DROP TABLE IF EXISTS `ix_ginas_substance_tags`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_substance_tags` ( - `ix_ginas_substance_uuid` varchar(40) NOT NULL, - `ix_core_value_id` bigint(20) NOT NULL, - PRIMARY KEY (`ix_ginas_substance_uuid`,`ix_core_value_id`), - KEY `c_995ed877` (`ix_core_value_id`), - CONSTRAINT `c_52663f1e` FOREIGN KEY (`ix_ginas_substance_uuid`) REFERENCES `ix_ginas_substance` (`uuid`), - CONSTRAINT `c_995ed877` FOREIGN KEY (`ix_core_value_id`) REFERENCES `ix_core_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_substanceref` --- - -DROP TABLE IF EXISTS `ix_ginas_substanceref`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_substanceref` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `ref_pname` varchar(1024) DEFAULT NULL, - `refuuid` varchar(128) DEFAULT NULL, - `substance_class` varchar(255) DEFAULT NULL, - `approval_id` varchar(32) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_72eceab6` (`created_by_id`), - KEY `i_e935f847` (`last_edited_by_id`), - KEY `ref_uuid_index` (`refuuid`), - KEY `sub_ref_index` (`refuuid`), - CONSTRAINT `c_9b338593` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_bc0dcaaa` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_subunit` --- - -DROP TABLE IF EXISTS `ix_ginas_subunit`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_subunit` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `sequence` longtext DEFAULT NULL, - `subunit_index` int(11) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_848760c5` (`created_by_id`), - KEY `i_3f6a6aa5` (`last_edited_by_id`), - CONSTRAINT `c_77fe4be4` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_f5925ba9` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_sugar` --- - -DROP TABLE IF EXISTS `ix_ginas_sugar`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_sugar` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `sugar` varchar(255) DEFAULT NULL, - `site_container_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_a4bffe4a` (`created_by_id`), - KEY `i_68c29fda` (`last_edited_by_id`), - KEY `i_9359fa3c` (`owner_uuid`), - KEY `i_a7509a91` (`site_container_uuid`), - CONSTRAINT `c_1b8dcc24` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_1bdc9737` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_40a4802c` FOREIGN KEY (`site_container_uuid`) REFERENCES `ix_ginas_site_lob` (`uuid`), - CONSTRAINT `c_9e3fbfd1` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_nucleicacid` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_unit` --- - -DROP TABLE IF EXISTS `ix_ginas_unit`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_unit` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `owner_uuid` varchar(40) DEFAULT NULL, - `amap_id` bigint(20) DEFAULT NULL, - `amount_uuid` varchar(40) DEFAULT NULL, - `attachment_count` int(11) DEFAULT NULL, - `label` varchar(255) DEFAULT NULL, - `structure` longtext DEFAULT NULL, - `type` varchar(255) DEFAULT NULL, - `attachmentMap` longtext DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_e1fe74d1` (`created_by_id`), - KEY `i_083bb113` (`last_edited_by_id`), - KEY `i_e89dda2c` (`owner_uuid`), - KEY `i_bece0bd4` (`amap_id`), - KEY `i_3d103a81` (`amount_uuid`), - CONSTRAINT `c_47464e5a` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_4f784205` FOREIGN KEY (`amount_uuid`) REFERENCES `ix_ginas_amount` (`uuid`), - CONSTRAINT `c_9bc432b1` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_dc716ff8` FOREIGN KEY (`amap_id`) REFERENCES `ix_core_value` (`id`), - CONSTRAINT `c_f269116f` FOREIGN KEY (`owner_uuid`) REFERENCES `ix_ginas_polymer` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_vocabulary_term` --- - -DROP TABLE IF EXISTS `ix_ginas_vocabulary_term`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_vocabulary_term` ( - `dtype` varchar(10) NOT NULL, - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `namespace_id` bigint(20) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `modified` datetime DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `owner_id` bigint(20) DEFAULT NULL, - `value` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `display` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `description` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, - `origin` varchar(255) DEFAULT NULL, - `filters` longtext DEFAULT NULL, - `hidden` tinyint(1) DEFAULT 0, - `selected` tinyint(1) DEFAULT 0, - `version` bigint(20) NOT NULL, - `system_category` varchar(255) DEFAULT NULL, - `regex` varchar(255) DEFAULT NULL, - `fragment_structure` varchar(255) DEFAULT NULL, - `simplified_structure` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `i_c9edf351` (`namespace_id`), - KEY `i_e7c81616` (`owner_id`), - KEY `vocabulary_term_owner_index` (`owner_id`), - CONSTRAINT `c_26a25a8c` FOREIGN KEY (`owner_id`) REFERENCES `ix_ginas_controlled_vocab` (`id`), - CONSTRAINT `c_a94727e8` FOREIGN KEY (`namespace_id`) REFERENCES `ix_core_namespace` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=106722 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_ginas_vocabulary_term_seq` --- - -DROP TABLE IF EXISTS `ix_ginas_vocabulary_term_seq`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_ginas_vocabulary_term_seq` ( - `next_not_cached_value` bigint(21) NOT NULL, - `minimum_value` bigint(21) NOT NULL, - `maximum_value` bigint(21) NOT NULL, - `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', - `increment` bigint(21) NOT NULL COMMENT 'increment value', - `cache_size` bigint(21) unsigned NOT NULL, - `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', - `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' -) ENGINE=InnoDB SEQUENCE=1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_import_data` --- - -DROP TABLE IF EXISTS `ix_import_data`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_import_data` ( - `instance_id` varchar(40) NOT NULL, - `data` longtext DEFAULT NULL, - `entity_class_name` varchar(255) DEFAULT NULL, - `record_id` varchar(40) DEFAULT NULL, - `save_date` datetime(6) DEFAULT NULL, - `version` int(11) NOT NULL, - PRIMARY KEY (`instance_id`), - KEY `idx_ix_import_data_entity_class_name` (`entity_class_name`), - KEY `idx_ix_import_data_version` (`version`), - KEY `idx_ix_import_data_record_id` (`record_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_import_mapping` --- - -DROP TABLE IF EXISTS `ix_import_mapping`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_import_mapping` ( - `mapping_id` varchar(40) NOT NULL, - `data_location` varchar(255) DEFAULT NULL, - `entity_class` varchar(255) DEFAULT NULL, - `instance_id` varchar(40) DEFAULT NULL, - `mapping_key` varchar(255) DEFAULT NULL, - `qualifier` varchar(255) DEFAULT NULL, - `record_id` varchar(40) DEFAULT NULL, - `mapping_value` varchar(512) DEFAULT NULL, - `instanceId` varchar(40) DEFAULT NULL, - PRIMARY KEY (`mapping_id`), - KEY `idx_ix_import_mapping_key` (`mapping_key`), - KEY `idx_ix_import_mapping_value` (`mapping_value`), - KEY `idx_ix_import_mapping_instance_id` (`instance_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_import_metadata` --- - -DROP TABLE IF EXISTS `ix_import_metadata`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_import_metadata` ( - `record_id` varchar(40) NOT NULL, - `data_format` varchar(255) DEFAULT NULL, - `entity_class_name` varchar(255) DEFAULT NULL, - `import_adapter` varchar(255) DEFAULT NULL, - `import_status` int(11) DEFAULT NULL, - `import_type` int(11) DEFAULT NULL, - `instance_id` varchar(40) DEFAULT NULL, - `process_status` int(11) DEFAULT NULL, - `reason` varchar(255) DEFAULT NULL, - `record_access` mediumblob DEFAULT NULL, - `source_name` varchar(255) DEFAULT NULL, - `validation_status` int(11) DEFAULT NULL, - `version` int(11) NOT NULL, - `version_creation_date` datetime(6) DEFAULT NULL, - `version_status` int(11) DEFAULT NULL, - PRIMARY KEY (`record_id`), - UNIQUE KEY `UK_b3wth3q98eiauf3rngwjybxve` (`instance_id`), - KEY `idx_ix_import_metadata_entity_class_name` (`entity_class_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_import_raw` --- - -DROP TABLE IF EXISTS `ix_import_raw`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_import_raw` ( - `record_id` varchar(40) NOT NULL, - `raw_data` longblob DEFAULT NULL, - `record_format` varchar(255) DEFAULT NULL, - PRIMARY KEY (`record_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `ix_import_validation` --- - -DROP TABLE IF EXISTS `ix_import_validation`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `ix_import_validation` ( - `validation_id` varchar(40) NOT NULL, - `validation_date` datetime(6) DEFAULT NULL, - `validation_json` longtext DEFAULT NULL, - `validation_message` varchar(2048) DEFAULT NULL, - `validation_type` int(11) DEFAULT NULL, - `entity_class_name` varchar(255) DEFAULT NULL, - `instance_id` varchar(40) DEFAULT NULL, - `version` int(11) NOT NULL, - `instanceId` varchar(40) DEFAULT NULL, - PRIMARY KEY (`validation_id`), - KEY `idx_ix_import_validation_entity_class_name` (`entity_class_name`), - KEY `idx_ix_import_validation_version` (`version`), - KEY `idx_ix_import_validation_instance_id` (`instance_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `play_evolutions` --- - -DROP TABLE IF EXISTS `play_evolutions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `play_evolutions` ( - `id` int(11) NOT NULL, - `hash` varchar(255) NOT NULL, - `applied_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `apply_script` longtext DEFAULT NULL, - `revert_script` longtext DEFAULT NULL, - `state` varchar(255) DEFAULT NULL, - `last_problem` text DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `polymer_classification` --- - -DROP TABLE IF EXISTS `polymer_classification`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `polymer_classification` ( - `uuid` varchar(40) NOT NULL, - `current_version` int(11) DEFAULT NULL, - `created` datetime DEFAULT NULL, - `created_by_id` bigint(20) DEFAULT NULL, - `last_edited` datetime DEFAULT NULL, - `last_edited_by_id` bigint(20) DEFAULT NULL, - `deprecated` tinyint(1) DEFAULT 0, - `record_access` varbinary(255) DEFAULT NULL, - `internal_references` longtext DEFAULT NULL, - `polymer_class` varchar(255) DEFAULT NULL, - `polymer_geometry` varchar(255) DEFAULT NULL, - `polymer_subclass` longtext DEFAULT NULL, - `source_type` varchar(255) DEFAULT NULL, - `parent_substance_uuid` varchar(40) DEFAULT NULL, - `internal_version` bigint(20) NOT NULL, - PRIMARY KEY (`uuid`), - KEY `i_ed48cb35` (`created_by_id`), - KEY `i_7009c842` (`last_edited_by_id`), - KEY `i_a11b724a` (`parent_substance_uuid`), - CONSTRAINT `c_37c0d602` FOREIGN KEY (`last_edited_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_86d29a3e` FOREIGN KEY (`created_by_id`) REFERENCES `ix_core_principal` (`id`), - CONSTRAINT `c_99019ebe` FOREIGN KEY (`parent_substance_uuid`) REFERENCES `ix_ginas_substanceref` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2023-10-24 2:53:09 - - --- Migration to GSRS 3.1, January 2024 -ALTER TABLE ix_core_db_gsrs_version MODIFY COLUMN `id` bigint not null auto_increment; - -ALTER TABLE ix_core_key_user_list MODIFY COLUMN `id` bigint not null auto_increment; -ALTER TABLE ix_core_key_user_list ADD COLUMN `kind` varchar(255); -ALTER TABLE ix_core_key_user_list DROP INDEX ukbomijjxdp2cmjttgrnqtoucvo; -alter table ix_core_key_user_list add constraint ukbomijjxdp2cmjttgrnqtoucvo unique (entity_key, list_name, user_id, kind); - -ALTER TABLE ix_core_user_saved_list MODIFY COLUMN `id` bigint not null auto_increment; -ALTER TABLE ix_core_user_saved_list ADD COLUMN `kind` varchar(255); -ALTER TABLE ix_core_user_saved_list DROP INDEX uknftwibs7mebodwpavq6ub0lqh; -alter table ix_core_user_saved_list add constraint uknftwibs7mebodwpavq6ub0lqh unique (name, user_id, kind); - - -ALTER TABLE ix_import_metadata ADD COLUMN `imported_by_id` bigint; -alter table ix_import_metadata add constraint fkn75dm5x09m6wvk7uq5q74do9c foreign key (imported_by_id) references ix_core_principal (id); -alter table ix_ginas_vocabulary_term change column value term_value varchar(3000); \ No newline at end of file diff --git a/packages/rails/docker/misc/gsrs/config/frontend_application.conf b/packages/rails/docker/misc/gsrs/config/frontend_application.conf deleted file mode 100644 index 2b9d2b855..000000000 --- a/packages/rails/docker/misc/gsrs/config/frontend_application.conf +++ /dev/null @@ -1,1230 +0,0 @@ -{ - "apiBaseUrl": "https://localhost:3000/ginas/app/", - "version": "3.0.2", - "contactEmail": "admin@admin.com", - "isPfdaVersion": true, - "displayMatchApplication": "false", - "adverseEventShinyHomepageDisplay": "true", - "adverseEventShinySubstanceNameDisplay": "true", - "adverseEventShinyAdverseEventDisplay": "true", - "bannerMessage": null, - "showNameStandardizeButton": true, - "advancedSearchFacetDisplay": false, - "approvalCodeName": "UNII", - "primaryCode": "BDNUM", - "filteredDuplicationCodes": [ - "BDNUM", - "FDA UNII" - ], - "typeaheadFields": [ - "Standardized_Name", - "Display_Name", - "CAS", - "Name", - "Approval_ID" - ], - "loadedComponents": { - "applications": false, - "products": false, - "clinicaltrials": false, - "adverseevents": false, - "impurities": false - }, - "substanceDetailsCards": [ - { - "card": "substance-overview", - "title": "overview" - }, - { - "card": "substance-primary-definition", - "title": "Primary Definition", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "definitionType", - "value": "ALTERNATIVE" - } - ] - }, - { - "card": "substance-alternative-definition", - "type": "SUBSTANCE->SUB_ALTERNATE", - "title": "Alternative Definitions", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "SUBSTANCE->SUB_ALTERNATE" - } - ] - }, - { - "card": "substance-relationships", - "type": "SUB_CONCEPT->SUBSTANCE", - "title": "Subconcepts Variants", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "SUB_CONCEPT->SUBSTANCE" - } - ] - }, - { - "card": "substance-concept-definition", - "title": "Concept Definition", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "concept" - } - ] - }, - { - "card": "substance-mixture-parent", - "title": "Found in Mixtures", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "$$mixtureParents" - } - ] - }, - { - "card": "substance-ssg1-parent", - "title": "Found in G1SS", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "$$constituentParents" - } - ] - }, - { - "card": "substance-hierarchy", - "title": "Substance Hierarchy" - }, - { - "card": "structure-details", - "title": "Chemical Structure", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "chemical|polymer" - }, - { - "filterName": "exists", - "propertyToCheck": "structure" - } - ] - }, - { - "card": "substance-moieties", - "title": "Chemical Moieties", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "chemical" - }, - { - "filterName": "exists", - "propertyToCheck": "moieties" - } - ] - }, - { - "card": "substance-subunits", - "title": "Protein Subunits", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "protein" - }, - { - "filterName": "exists", - "propertyToCheck": "protein.subunits" - } - ] - }, - { - "card": "substance-glycosylation", - "title": "Protein Glycosylation", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "protein" - }, - { - "filterName": "anyExists", - "propertyToCheck": "protein.glycosylation.glycosylationType|protein.glycosylation.CGlycosylationSites|protein.glycosylation.NGlycosylationSites|protein.glycosylation.OGlycosylationSites" - } - ] - }, - { - "card": "substance-disulfide-links", - "title": "Protein Disulfide Links", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "protein" - }, - { - "filterName": "exists", - "propertyToCheck": "protein.disulfideLinks" - } - ] - }, - { - "card": "substance-other-links", - "title": "Protein Other Links", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "protein" - }, - { - "filterName": "exists", - "propertyToCheck": "protein.otherLinks" - } - ] - }, - { - "card": "substance-subunits", - "title": "Nuceic Acid Subunits", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "nucleicAcid" - }, - { - "filterName": "exists", - "propertyToCheck": "nucleicAcid.subunits" - } - ] - }, - { - "card": "substance-na-sugars", - "title": "Nucleic Acid Sugars", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "nucleicAcid" - }, - { - "filterName": "exists", - "propertyToCheck": "nucleicAcid.sugars" - } - ] - }, - { - "card": "substance-na-linkages", - "title": "Nucleic Acid Linkages", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "nucleicAcid" - }, - { - "filterName": "exists", - "propertyToCheck": "nucleicAcid.linkages" - } - ] - }, - { - "card": "substance-polymer-structure", - "title": "Polymer Display Structure", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "polymer" - } - ] - }, - { - "card": "substance-monomers", - "title": "Polymer Monomers and Starting Materials", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "polymer" - }, - { - "filterName": "exists", - "propertyToCheck": "polymer.monomers" - } - ] - }, - { - "card": "substance-structural-units", - "title": "Polymer Structural Units", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "polymer" - }, - { - "filterName": "exists", - "propertyToCheck": "polymer.structuralUnits" - } - ] - }, - { - "card": "substance-mixture-source", - "title": "Mixture Source", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "mixture" - }, - { - "filterName": "exists", - "propertyToCheck": "mixture.parentSubstance" - } - ] - }, - { - "card": "substance-mixture-components", - "title": "Mixture Components", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "mixture" - }, - { - "filterName": "exists", - "propertyToCheck": "mixture.components" - } - ] - }, - { - "card": "substance-constituents", - "title": "G1 Specified Substance Constituents", - "filters": [ - { - "filterName": "equals", - "propertyToCheck": "substanceClass", - "value": "specifiedSubstanceG1" - }, - { - "filterName": "exists", - "propertyToCheck": "specifiedSubstance.constituents" - } - ] - }, - { - "card": "substance-modifications", - "title": "Substance Modifications", - "filters": [ - { - "filterName": "anyExists", - "propertyToCheck": "modifications.structuralModifications|modifications.physicalModifications|modifications.agentModifications" - } - ] - }, - { - "card": "substance-ssg-parent-substance", - "title": "G3 Specified Substance Parent", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "specifiedSubstanceG3.parentSubstance" - } - ] - }, - { - "card": "substance-ssg-definition", - "title": "G3 Specified Substance Definition", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "specifiedSubstanceG3.definition" - } - ] - }, - { - "card": "substance-ssg-grade", - "title": "G3 Specified Substance Grade", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "specifiedSubstanceG3.grade" - } - ] - }, - { - "card": "substance-names", - "title": "Names and Synonyms", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "names" - } - ] - }, - { - "card": "substance-codes", - "type": "Codes - Classifications", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "codes" - }, - { - "filterName": "substanceCodes", - "value": "classification" - } - ] - }, - { - "card": "substance-codes", - "type": "Codes - Identifiers", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "codes" - }, - { - "filterName": "substanceCodes", - "value": "identifiers" - } - ] - }, - { - "card": "substance-properties", - "title": "Characteristic Attributes", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "properties" - } - ] - }, - { - "card": "substance-relationships-visualization", - "title": "Relationships Visualization", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - } - ] - }, - { - "card": "substance-relationships", - "type": "ACTIVE MOIETY", - "title": "Relationships: Active Moiety", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "ACTIVE MOIETY" - } - ] - }, - { - "card": "substance-relationships", - "type": "METABOLITE", - "title": "Relationships: Metabolites", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "METABOLITE" - } - ] - }, - { - "card": "substance-relationships", - "type": "IMPURITY", - "title": "Relationships: Impurities", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "IMPURITY" - } - ] - }, - { - "card": "substance-relationships", - "type": "CONSTITUENT", - "title": "Relationships: Constitents", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": "CONSTITUENT" - } - ] - }, - { - "card": "substance-relationships", - "type": "RELATIONSHIPS", - "title": "Relationships", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "relationships" - }, - { - "filterName": "substanceRelationships", - "value": [ - "METABOLITE", - "IMPURITY", - "ACTIVE MOIETY", - "CONSTITUENT", - "SUB_CONCEPT->SUBSTANCE" - ] - } - ] - }, - { - "card": "substance-notes", - "title": "Notes", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "notes" - } - ] - }, - { - "card": "substance-references", - "title": "References", - "filters": [ - { - "filterName": "exists", - "propertyToCheck": "references" - } - ] - }, - { - "card": "substance-audit-info", - "title": "Audit Information" - }, - { - "card": "substance-history", - "title": "Record History", - "filters": [ - { - "filterName": "hasCredentials", - "propertyToCheck": "admin" - } - ] - } - ], - "facets": { - "substances": { - "default": [ - "Deprecated", - "Record Status", - "Substance Class", - "GInAS Tag", - "Relationships", - "Code System", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4", - "WHO-SDG Level 1", - "WHO-SDG Level 2", - "Application Status", - "Application Type", - "DME Reactions", - "Moiety Type", - "Molecular Weight", - "SubstanceStereochemistry", - "Record Level Access", - "Display Name Level Access", - "Definition Level Access", - "Protein Type", - "modified", - "Product Ingredient Type", - "Product Type", - "Product Dosage Form", - "Definition Level", - "Clinical Trial Count" - ], - "admin": [ - "Record Created By", - "root_lastEdited", - "root_created", - "root_lastEditedBy", - "root_approved", - "Approved By", - "Material Type", - "Family", - "Parts" - ], - "facetView": [ - { - "category": "Default", - "facets": [ - "Deprecated", - "Record Status", - "Substance Class", - "GInAS Tag", - "GInAS Domain", - "Code System", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4", - "WHO-SDG Level 1", - "WHO-SDG Level 2", - "DME Reactions", - "Application Center", - "Application Type", - "Application Status", - "Material Type", - "Family", - "Parts", - "Moiety Type", - "Molecular Weight", - "SubstanceStereochemistry", - "root_approved", - "Approved By", - "root_created", - "Record Created By", - "root_lastEdited", - "root_lastEditedBy", - "Record Level Access", - "Display Name Level Access", - "Definition Level Access", - "Protein Type", - "Product Ingredient Type", - "Product Type", - "Product Dosage Form", - "Definition Level", - "Clinical Trial Count", - "Relationships" - ] - }, - { - "category": "Record Data", - "facets": [ - "Deprecated", - "Record Status", - "Substance Class", - "Definition Type", - "Definition Level", - "GInAS Tag", - "GInAS Domain", - "GInAS Language", - "GInAS Name Jurisdiction", - "Code System", - "root_approved", - "Approved By", - "root_created", - "Record Created By", - "root_lastEdited", - "root_lastEditedBy", - "Record Level Access", - "Display Name Level Access", - "Definition Level Access", - "Validation", - "Reference Type", - "GInAS Document Tag", - "Relationships" - ] - }, - { - "category": "User Data", - "facets": [ - "Record Created By", - "Approved By", - "root_lastEditedBy" - ] - }, - { - "category": "CMC Data", - "facets": [ - "Record Status", - "Substance Class", - "Code System", - "GInAS Tag", - "Moiety Type", - "Application Center", - "Application Type", - "Application Status", - "Product Ingredient Type", - "Product Type", - "Product Dosage Form", - "Clinical Trial Count", - "CFR", - "Qualification", - "Interaction Type" - ] - }, - { - "category": "Medical Data", - "facets": [ - "Record Status", - "Substance Class", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4", - "WHO-SDG Level 1", - "WHO-SDG Level 2", - "DME Reactions", - "Code System", - "GInAS Tag", - "Product Ingredient Type", - "Product Type", - "Product Dosage Form", - "Clinical Trial Count", - "CFR" - ] - }, - { - "category": "Chemistry", - "facets": [ - "Record Status", - "Substance Class", - "Code System", - "GInAS Tag", - "Moiety Type", - "Molecular Weight", - "SubstanceStereochemistry", - "Molecular Formula", - "Polymer Class", - "GInAS Subclass", - "Polymer Geometry" - ] - }, - { - "category": "Proteins, DNA and RNA", - "facets": [ - "Record Status", - "Substance Class", - "Code System", - "GInAS Tag", - "Protein Type", - "Modifications", - "Glycosylation Type", - "Protein Subtype", - "Linkage Type", - "Nucleic Acid Subtype", - "Sequence Origin", - "Sequence Type", - "Molecular Weight" - ] - }, - { - "category": "Organisms", - "facets": [ - "Record Status", - "Substance Class", - "Code System", - "GInAS Tag", - "Material Class", - "Material Type", - "Modifications", - "Parts", - "Family", - "Genus", - "Species", - "Author" - ] - }, - { - "category": "Codes", - "facets": [ - "ATCC", - "BDNUM", - "BIOLOGIC SUBSTANCE CLASSIFICATION CODE", - "CAS", - "CAYMAN", - "CERES", - "CFR", - "CFSAN PSEUDO CAS", - "ChEMBL", - "CLINICAL_TRIALS.GOV", - "Code System", - "CODEX ALIMENTARIUS (GSFA)", - "COSMETIC INGREDIENT REVIEW (CIR)", - "DASH INDICATION", - "DEA NO.", - "DME Reactions", - "DRUG BANK", - "DRUG CENTRAL", - "DSLD", - "EC (ENZYME CLASS)", - "EC SCIENTIFIC COMMITTEE ON CONSUMER SAFETY OPINION", - "ECHA (EC/EINECS)", - "EMA ASSESSMENT REPORTS", - "EMA VETERINARY ASSESSMENT REPORTS", - "EPA CompTox", - "EPA PESTICIDE CODE", - "EU CLINICAL TRIALS REGISTER", - "EU FOOD ADDITIVES", - "EU-Orphan Drug", - "EVMPD", - "FARM SUBSTANCE ID", - "FDA ORPHAN DRUG", - "FDA UNII", - "Food Contact Sustance Notif, (FCN No.)", - "GENE", - "GRIN", - "HEALTH -CANADA NHP INGREDIENT MONOGRAPH", - "HEALTH-CANADA NHP INGREDIENT RECORD", - "HSDB", - "IARC", - "INCB IDS CODE", - "INN", - "INS", - "ITIS", - "IUPHAR", - "JAPANESE REVIEW", - "JECFA EVALUATION", - "JECFA MONOGRAPH", - "JMPR-PESTICIDE RESIDUE", - "KEGG", - "LactMed", - "LIVERTOX", - "LOINC", - "MANUFACTURER PRODUCT INFORMATION", - "MERCK INDEX", - "MESH", - "MIRBASE", - "MPNS", - "NCBI TAXONOMY", - "NCI_THESAURUS", - "NDF-RT", - "NSC", - "Other", - "PFAF", - "PHAROS", - "PROTEIN ID", - "PUBCHEM", - "RXCUI", - "STARI", - "SUPERSEDED_BD_NUM", - "SWGDRUG", - "UCSF-FDA TRANSPORTAL", - "UNII", - "UNIPROT", - "USDA PLANTS", - "USP_CATALOG", - "USP-HMC", - "WEB RESOURCE", - "WHO INTERNATIONAL PHARMACOPEIA", - "WHO INTERNATIONAL PHARMACPOEIA", - "WHO-ATC", - "WHO-ESSENTIAL MEDICINES LIST", - "WHO-SDG", - "WHO-SDG Level 1", - "WHO-SDG Level 2", - "WHO-VATC", - "WIKIPEDIA", - "YELLOW LIST" - ] - } - ] - }, - "applications": { - "default": [ - "Application Type", - "Center", - "Title", - "Has Indications", - "Has Ingredients", - "Has Products", - "Status Date Year", - "Submit Date", - "Submit Date Year", - "Application Number", - "Ingredient Name", - "Provenance (GSRS)", - "Public Domain", - "Product Name", - "Sponsor Name", - "Application Status", - "Ingredient Type", - "Substance Key", - "Application Sub Type", - "Indication", - "Dosage Form", - "Division Class Description", - "Source", - "Product Name Deprecated" - ], - "admin": [ - "Record Created By", - "Record Last Edited By", - "Record Create Date", - "Record Last Edited", - "Ingredient Created By", - "Ingredient Last Edited By", - "Ingredient Create Date", - "Ingredient Last Edited" - ] - }, - "products": { - "default": [ - "Product Name", - "Nonproprietary Name", - "Product NDC", - "Dosage Form Name", - "Ingredient Name", - "Ingredient Type", - "Product Type", - "Product Code Type", - "Application Number", - "Status", - "Marketing Category Name", - "Route of Admin", - "Is Listed", - "Labeler Name", - "Labeler DUNS Number", - "Registrant Name", - "Registrant DUNS", - "City", - "State", - "Company Country", - "Country Code", - "Provenance" - ], - "admin": [ - "Record Created By", - "Record Last Edited By", - "Record Create Date", - "Record Last Edited" - ] - }, - "ctclinicaltrial": { - "default": [ - "Has Substances", - "CT Matching Complete", - "Last Updated Year", - "Primary Completion Year", - "First Posted Year", - "Study Types", - "Gender", - "Age Groups", - "Intervention Type", - "Study Results", - "Conditions" - ] - }, - "clinicaltrialsus": { - "default": [ - "Has Substances", - "CT Matching Complete", - "Last Updated Year", - "Primary Completion Year", - "First Posted Year", - "Study Types", - "Gender", - "Age Groups", - "Intervention Type", - "Study Results", - "Conditions" - ] - }, - "adverseeventpt": { - "default": [ - "Adverse Event", - "Prim SOC", - "Ingredient Name", - "Substance Key", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4" - ] - }, - "adverseeventdme": { - "default": [ - "DME Reactions", - "PTTerm Meddra", - "Ingredient Name", - "Substance Key", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4" - ] - }, - "adverseeventcvm": { - "default": [ - "Adverse Event", - "Species", - "Route of Administration", - "Ingredient Name", - "Substance Key", - "ATC Level 1", - "ATC Level 2", - "ATC Level 3", - "ATC Level 4" - ] - } - }, - "codeSystemOrder": [ - "BDNUM", - "CAS", - "WHO-ATC", - "EVMPD", - "NCI" - ], - "homeContents": "The main goal of ginas is the production of software, called GSRS, to assist agencies in registering and documenting information about substances found in medicines. The Global Ingredient Archival System provides a common identifier for all of the substances used in medicinal products, utilizing a consistent definition of substances globally, including active substances under clinical investigation, consistent with the ISO 11238 standard.", - "relationshipsVisualizationUri": "/ginas/app/beta/substanceRelationshipVisualizer/index.html?uuid=", - "navItems": [ - { - "display": "Help", - "order": 60, - "children": [ - { - "display": "User Manual", - "href": "https://gsrs.ncats.nih.gov/downloads/Substance%20Registration%20-%20October%202019.docx", - "order": 10 - }, - { - "display": "Email GSRS Support", - "path": "", - "order": 30 - } - ] - } - ], - "substanceSelectorProperties": [ - "root_names_name", - "root_approvalID", - "root_codes_BDNUM", - "root_codes_CAS", - "root_codes_ECHA\\ \\(EC\\/EINECS\\)" - ], - "homeDynamicLinks": [ - { - "display": "Chemicals", - "facetName": "Substance Class", - "facetValue": "chemical" - }, - { - "display": "Polymers", - "facetName": "Substance Class", - "facetValue": "polymer" - }, - { - "display": "Structurally Diverse", - "facetName": "Substance Class", - "facetValue": "structurallyDiverse" - }, - { - "display": "Proteins", - "facetName": "Substance Class", - "facetValue": "protein" - }, - { - "display": "Nucleic Acids", - "facetName": "Substance Class", - "facetValue": "nucleicAcid" - }, - { - "display": "Concepts", - "facetName": "Substance Class", - "facetValue": "concept" - } - ], - "registrarDynamicLinks": [ - { - "display": "Chemicals", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "chemical" - } - ] - }, - { - "display": "Polymers", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "polymer" - } - ] - }, - { - "display": "Structurally Diverse", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "structurallyDiverse" - } - ] - }, - { - "display": "Proteins", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "protein" - } - ] - }, - { - "display": "Nucleic Acids", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "nucleicAcid" - } - ] - }, - { - "display": "Concepts", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "concept" - } - ] - }, - { - "display": "SSG1", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "specifiedSubstanceG1" - } - ] - } - ], - "registrarDynamicLinks2": [ - { - "display": "Pending Chemicals", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "chemical" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending Polymers", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "polymer" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending Structurally Diverse", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "structurallyDiverse" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending Proteins", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "protein" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending Nucleic Acids", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "nucleicAcid" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending Concepts", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "concept" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - }, - { - "display": "Pending SSG1", - "facets": [ - { - "facetName": "Substance Class", - "facetValue": "specifiedSubstanceG1" - }, - { - "facetName": "Record Status", - "facetValue": "pending" - } - ] - } - ], - "substance": { - "linking": { - "keyType": { - "default": "BDNUM", - "orgDisplayKeyType": "BDNUM", - "clinicalTrialKeyType": "UUID" - } - } - } -} diff --git a/packages/rails/docker/misc/gsrs/config/gateway_application.yml b/packages/rails/docker/misc/gsrs/config/gateway_application.yml deleted file mode 100644 index b45f4384f..000000000 --- a/packages/rails/docker/misc/gsrs/config/gateway_application.yml +++ /dev/null @@ -1,165 +0,0 @@ -gsrs: - gateway: - server: - addHeaders: - # these are for the FDA GSRS server to be able to respond to the KASA SSG4M GSRS instance - - "Access-Control-Allow-Origin: *" - - "Access-Control-Allow-Methods: POST, GET, PUT, PATCH, DELETE, OPTIONS" - - "Access-Control-Allow-Headers: auth-key, auth-username, auth-password, auth-token, Content-Type, Content-Range, Content-Disposition, Content-Description" - redirectPatterns: - # fixes for improper redirects on single tomcat instance - - "[/][a-z|A-Z]*/api/v1/: /ginas/app/api/v1/" -eureka: - client: - registerWithEureka: false - fetch-registry: true - serviceUrl: - defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka} - -spring: - application: - name: gateway - -debug: true - -zuul: - #this sets sensitiveHeaders to empty list so cookies and auth headers are passed through both ways - sensitiveHeaders: - routes: - beta-ui: - path: /ginas/app/beta/** - url: http://localhost:8080/frontend/ginas/app/ui - serviceId: frontend - ui: - path: /ginas/app/ui/** - url: http://localhost:8080/frontend/ginas/app/ui - serviceId: frontend - ginas_app: - path: /ginas/app/** - url: http://localhost:8080 - serviceId: ginas_app_route - applications_core: - path: /api/v1/applications/** - url: http://localhost:8080/applications/api/v1/applications - serviceId: applications_core - applications_core_alt: - path: /api/v1/applications(**)/** - url: http://localhost:8080/applications/api/v1/applications - serviceId: applications_core_alt - applications_all: - path: /api/v1/applicationsall/** - url: http://localhost:8080/applications/api/v1/applicationsall - serviceId: applications_all - applications_all_alt: - path: /api/v1/applicationsall(**)/** - url: http://localhost:8080/applications/api/v1/applicationsall - serviceId: applications_all_alt - applications_darrts: - path: /api/v1/applicationsdarrts/** - url: http://localhost:8080/applications/api/v1/applicationsdarrts - serviceId: applications_darrts - applications_darrts_alt: - path: /api/v1/applicationsdarrts(**)/** - url: http://localhost:8080/applications/api/v1/applicationsdarrts - serviceId: applications_darrts_alt - applications_searchcount: - path: /api/v1/searchcounts/** - url: http://localhost:8080/applications/api/v1/searchcounts - serviceId: applications_searchcount - applications_searchcount_alt: - path: /api/v1/searchcounts(**)/** - url: http://localhost:8080/applications/api/v1/searchcounts - serviceId: applications_searchcount - products_core: - path: /api/v1/products/** - url: http://localhost:8080/products/api/v1/products - serviceId: products_core - products_core_alt: - path: /api/v1/products(**)/** - url: http://localhost:8080/products/api/v1/products - serviceId: products_core - products_all: - path: /api/v1/productsall/** - url: http://localhost:8080/products/api/v1/productsall - serviceId: products_all - products_all_alt: - path: /api/v1/productsall(**)/** - url: http://localhost:8080/products/api/v1/productsall - serviceId: products_all - products_elist: - path: /api/v1/productselist/** - url: http://localhost:8080/products/api/v1/productselist - serviceId: products_elist - products_elist_alt: - path: /api/v1/productselist(**)/** - url: http://localhost:8080/products/api/v1/productselist - serviceId: products_elist - impurities: - path: /api/v1/impurities/** - url: http://localhost:8080/impurities/api/v1/impurities - serviceId: impurities - impurities_alt: - path: /api/v1/impurities(**)/** - url: http://localhost:8080/impurities/api/v1/impurities - serviceId: impurities - adverseeventpt: - path: /api/v1/adverseeventpt/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventpt - serviceId: adverseeventpt - adverseeventpt_alt: - path: /api/v1/adverseeventpt(**)/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventpt - serviceId: adverseeventpt - adverseeventdme: - path: /api/v1/adverseeventdme/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventdme - serviceId: adverseeventdme - adverseeventdme_alt: - path: /api/v1/adverseeventdme(**)/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventdme - serviceId: adverseeventdme - adverseeventcvm: - path: /api/v1/adverseeventcvm/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventcvm - serviceId: adverseeventcvm - adverseeventcvm_alt: - path: /api/v1/adverseeventcvm(**)/** - url: http://localhost:8080/adverse-events/api/v1/adverseeventcvm - serviceId: adverseeventcvm - clinical_trials_us: - path: /api/v1/clinicaltrialsus/** - url: http://localhost:8080/clinical-trials/api/v1/clinicaltrialsus - serviceId: clinical_trials_us - clinical_trials_us_alt: - path: /api/v1/clinicaltrialsus(**)/** - url: http://localhost:8080/clinical-trials/api/v1/clinicaltrialsus - serviceId: clinical_trials_us - clinical_trials_europe: - path: /api/v1/clinicaltrialseurope/** - url: http://localhost:8080/clinical-trials/api/v1/clinicaltrialseurope - serviceId: clinical_trials_europe - clinical_trials_europe_alt: - path: /api/v1/clinicaltrialseurope(**)/** - url: http://localhost:8080/clinical-trials/api/v1/clinicaltrialseurope - serviceId: clinical_trials_europe - legacy: - path: /** - url: http://localhost:8080/substances - serviceId: substances - ignored-patterns: - - "/actuator/health" - -ribbon: - eureka: - enabled: false - -management.endpoints.web.exposure.include: 'routes,filters' - -logging: - level: - org.springframework.cloud.gateway: DEBUG - reactor.netty.http.client: DEBUG - -eureka.client.enabled: false - -zuul.host.socket-timeout-millis: 300000 diff --git a/packages/rails/docker/misc/gsrs/config/substances_application.conf b/packages/rails/docker/misc/gsrs/config/substances_application.conf deleted file mode 100644 index 40ba8f843..000000000 --- a/packages/rails/docker/misc/gsrs/config/substances_application.conf +++ /dev/null @@ -1,445 +0,0 @@ -include "substances-core.conf" - -server.tomcat.max-threads=2000 -ix.home= "/ginas.ix" -application.host="https://localhost:3000/ginas/app" -spring.application.name="substances" -logging.file.path="/usr/local/tomcat/logs/substances" -################################################################## -# SPRING BOOT ACTUATOR SETTINGS FOR MICROSERVICE HEALTH CHECKS ## -################################################################## -# turn off rabbit mq check for now since we don't use it otherwise it will say we are down -management.health.rabbit.enabled: false - -ix.ginas.approvalIdGenerator.generatorClass="ix.ginas.utils.UNIIGenerator" - -# PUT YOUR PERSONAL EXTENSIONS AND ADDITIONS HERE -#debug=true -spring.main.allow-bean-definition-overriding=true - -#this is how HOCON does default values -#eureka.client.serviceUrl.defaultZone= "http://localhost:8761/eureka" -eureka.client.enabled=false -ix.ginas.export.path="/gsrs_exports" - -## START AUTHENTICATION -# SSO HTTP proxy authentication settings -ix.authentication.trustheader=true -ix.authentication.usernameheader="AUTHENTICATION_USERNAME" -ix.authentication.useremailheader="AUTHENTICATION_EMAIL" -# set this "false" to only allow authenticated users to see the application -ix.authentication.allownonauthenticated=true -# set this "true" to allow any user that authenticates to be registered -# as a user automatically -ix.authentication.autoregister=true -#Set this to "true" to allow autoregistered users to be active as well -ix.authentication.autoregisteractive=true -## END AUTHENTICATION - -# Oracle Connection -#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -spring.jpa.hibernate.use-new-id-generator-mappings=true -spring.datasource.driverClassName="org.mariadb.jdbc.Driver" -spring.datasource.url="jdbc:mariadb://host.docker.internal:32900/ixginas" -spring.datasource.username="root" -spring.datasource.password="password" -spring.datasource.maximum-pool-size=50 - -# Spring Boot Config -spring.jpa.hibernate.ddl-auto=none #### THIS IS VERY IMPORTANT, OTHERWISE Hibernate will WIPE OUT our database -spring.jpa.show-sql=false -spring.jpa.properties.hibernate.format_sql=false -eureka.client.enabled=false - -# NEED THIS for Applications-api, Products-api and ClinicalTrialsUS/Europe-Api -# gsrs.microservice.applications.api.baseURL="http://localhost:8081/" -# gsrs.microservice.products.api.baseURL="http://localhost:8081/" -# gsrs.microservice.clinicaltrialsus.api.baseURL="http://localhost:8081/" -# gsrs.microservice.clinicaltrialseurope.api.baseURL="http://localhost:8081/" - - -# Secure session off for dev, but if using HTTPS it's better to have it on -gsrs.sessions.sessionSecure=false - -# This is configured in substance-core.conf; modify if needed here. -# Standardize Names in accordance with FDA rules -# Uncomment to add name standardization functionality -# gsrs.validators.substances += { -# "validatorClass" = "ix.ginas.utils.validation.validators.StandardNameValidator", -# "newObjClass" = "ix.ginas.models.v1.Substance", -# "configClass" = "SubstanceValidatorConfig", -# "parameters"= { -# "inPlaceNameStandardizerClass":"gsrs.module.substance.standardizer.FDAMinimumNameStandardizer", -# "fullNameStandardizerClass":"gsrs.module.substance.standardizer.FDAFullNameStandardizer", -# "behaviorOnInvalidStdName": "error" -# } -# } - -ix.ginas.export.settingsPresets.substances= { - "PUBLIC_DATA_ONLY": { - "owner":"admin", - "scrubberSettings": { - "removeAllLocked":true - } - }, - "ALL_DATA": { - "owner":"admin", - "scrubberSettings":null - } -} - -gsrs.importAdapterFactories.substances = - [ - { - - "adapterName": "SDF Adapter", - "importAdapterFactoryClass": "gsrs.module.substance.importers.SDFImportAdapterFactory", - "stagingAreaServiceClass": "gsrs.stagingarea.service.DefaultStagingAreaService", - "entityServiceClass" :"gsrs.dataexchange.SubstanceStagingAreaEntityService", - "description" : "SD file importer for general users", - "supportedFileExtensions": [ - "sdf", - "sd", - "sdfile" - ], - - "parameters": { - #the things used to instantiate a thing used to do the import - - "fileImportActions": [ - ##list of available actions for user to select from - #each action takes in a file record + a substance record to update substance record with data from file - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.NameExtractorActionFactory", - "fields": [ - { - "fieldName": "Name", - "fieldLabel": "Substance Name", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - }, - { - "fieldName": "nameType", - "fieldLabel": "Name Type", - "defaultValue": "cn", - "cv": "name_type", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - }, - { - "fieldName": "displayName", - "fieldLabel": "Display Name?", - "defaultValue": false, - "fieldType": "java.lang.Boolean", - "expectedToChange": true, - "required": false, - "lookupKey": null - } - ], - "parameters": { - "lang": "en" - }, - "actionName": "common_name", - "label":"Create Name" - }, - { - "actionName": "code_import", - "label":"Create Code", - "actionClass": "gsrs.module.substance.importers.importActionFactories.CodeExtractorActionFactory", - "fields": [ - { - "fieldName": "code", - "fieldLabel": "Code/Identifier", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - }, - { - "fieldName": "codeType", - "fieldLabel": "Primary or Alternative", - "defaultValue": "PRIMARY", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - }, - { - "fieldName": "codeSystem", - "fieldLabel": "Code System", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - } - ], - "parameters": { - } - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.NSRSCustomCodeExtractorActionFactory", - "fields": [ - { - "fieldName": "code", - "fieldLabel": "NSC Number", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - }, - { - "fieldName": "codeType", - "fieldLabel": "Primary or Alternative", - "defaultValue": "PRIMARY", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - } - ], - "parameters": { - "codeSystem": "NSC" - }, - "actionName": "nci_import", - "label":"Create NSC Code" - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.StructureExtractorActionFactory", - "fields": [ - { - "fieldName": "molfile", - "fieldLabel": "Structure", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - } - ], - "parameters": { - - }, - "actionName": "structure_and_moieties", - "label":"Create Structure" - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.PropertyExtractorActionFactory", - "fields": [ - { - "fieldName": "name", - "fieldLabel": "Name", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - }, - { - "fieldName": "propertyType", - "fieldLabel": "Property Type", - "defaultValue": "chemical", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - }, - { - "fieldName": "valueAverage", - "fieldLabel": "Average Value", - "defaultValue": null, - "fieldType": "java.lang.Double", - "expectedToChange": true, - "required": false, - "lookupKey": null - }, - { - "fieldName": "valueNonNumeric", - "fieldLabel": "Non-numeric Value", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - }, - { - "fieldName": "valueUnits", - "fieldLabel": "Units", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - } - ], - "parameters": { - }, - "actionName": "property_import", - "label":"Create Chemical Property" - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.ReferenceExtractorActionFactory", - "fields": [ - { - "fieldName": "docType", - "fieldLabel": "Type", - "defaultValue": "OTHER", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - }, - { - "fieldName": "citation", - "fieldLabel": "Reference", - "defaultValue": "{INSERT REFERENCE CITATION HERE}", - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": false, - "lookupKey": null - } - ], - "parameters": { - - }, - "actionName": "public_reference", - "label":"Create Reference" - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.NotesExtractorActionFactory", - "fields": [ - { - "fieldName": "note", - "fieldLabel": "Note", - "defaultValue": null, - "fieldType": "java.lang.String", - "expectedToChange": true, - "required": true, - "lookupKey": null - } - ], - "parameters": { - }, - "actionName": "note_import", - "label":"Create Note" - }, - { - "actionClass": "gsrs.module.substance.importers.importActionFactories.NoOpActionFactory", - "fields": [ - { - "fieldName": "fieldName", - "fieldLabel": "Field to ignore", - "fieldType": "java.lang.String", - "expectedToChange": true, - "lookupKey": null - } - ], - "parameters": { - }, - "actionName": "no-op", - "label":"Omit this field" - } - ] - } - }, - { - "adapterName": "GSRS JSON Adapter", - "importAdapterFactoryClass": "gsrs.module.substance.importers.GSRSJSONImportAdapterFactory", - "stagingAreaServiceClass": "gsrs.stagingarea.service.DefaultStagingAreaService", - "entityServiceClass" :"gsrs.dataexchange.SubstanceStagingAreaEntityService", - "description" : "GSRS legacy JSON file importer", - #extensions belong here because they can override the default set within the class - "supportedFileExtensions": [ - "gsrs", - "gz" - ], - "parameters": { - } - } - ] - -## Add after StandardNameValidator -# gsrs.validators.substances += { -# "validatorClass" = "ix.ginas.utils.validation.validators.StandardNameDuplicateValidator", -# "newObjClass" = "ix.ginas.models.v1.Substance", -# "parameters"= { -# "checkDuplicateInOtherRecord" = true, -# "checkDuplicateInSameRecord" = true, -# "onDuplicateInOtherRecordShowError" = true, -# "onDuplicateInSameRecordShowError" = false -# } -# } - -# Manage tags/bracketed terms in names per FDA configuration. -# In FDA's case: -# No automatic addition in tags found in names to explicit tag list. -# No automatic deletion of explicit tags missing from bracketed terms. -# Warnings off for bracket name missing from tags; warning on for explicit tag missing from names. -# gsrs.validators.substances += { -# "validatorClass" = "ix.ginas.utils.validation.validators.tags.TagsValidator", -# "newObjClass" = "ix.ginas.models.v1.Substance", -# "parameters" = { -# "checkExplicitTagsExtractedFromNames": false, -# "checkExplicitTagsMissingFromNames": true, -# "addExplicitTagsExtractedFromNamesOnCreate": false, -# "addExplicitTagsExtractedFromNamesOnUpdate": false, -# "removeExplicitTagsMissingFromNamesOnCreate": false, -# "removeExplicitTagsMissingFromNamesOnUpdate": false -# } -# } - -gsrs.defaultStagingAreaServiceClass.substances = gsrs.stagingarea.service.DefaultStagingAreaService -gsrs.defaultStagingAreaEntityService.substances = gsrs.dataexchange.SubstanceStagingAreaEntityService -gsrs.availableProcessActions.substances = ["gsrs.dataexchange.processingactions.CreateProcessingAction", - "gsrs.dataexchange.processingactions.MergeProcessingAction", - "gsrs.dataexchange.processingactions.RejectProcessingAction", - "gsrs.dataexchange.processingactions.CreateBatchProcessingAction", - "gsrs.dataexchange.processingactions.ScrubProcessingAction"] - -gsrs.matchableCalculators.substances = -[ - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.CASNumberMatchableExtractor", - "config" :{ - "casCodeSystems": ["CAS", "CASNo", "CASNumber"] - } - }, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.AllNamesMatchableExtractor","config" :{}}, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.ApprovalIdMatchableExtractor","config" :{}}, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.DefinitionalHashMatchableExtractor","config" :{}}, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.SelectedCodesMatchableExtractor", - "config" : - { - "codeSystems" :["CAS", "ChemBL", "NCI", "NSC", "EINECS"] - } - }, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.UUIDMatchableExtractor","config" :{}}, - {"matchableCalculationClass" : "gsrs.dataexchange.extractors.CodeMatchableExtractor", - "config" :{ - "reqCodeSystems": ["FDA UNII"], - "codeType": "PRIMARY", - "codeKey": "CODE" - } - } -] - -gsrs.uuidCodeSystem.substances="UUID Code" -gsrs.approvalIdCodeSystem.substances="FDA UNII" - -gsrs.application.ivm.search.max.fetch = "20000" -gsrs.product.ivm.search.max.fetch = "20000" -gsrs.clinicaltrial.ivm.search.max.fetch = "20000" - -gsrs.entityProcessors+={ - "entityClassName": ix.ginas.models.v1.Substance, - "processor": "gsrs.dataexchange.processors.CalculateMatchablesProcessor", - "with":{ - } - } diff --git a/packages/rails/docker/misc/gsrs/context.xml b/packages/rails/docker/misc/gsrs/context.xml deleted file mode 100644 index 678bdf220..000000000 --- a/packages/rails/docker/misc/gsrs/context.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/rails/docker/misc/gsrs/libjnainchi.so b/packages/rails/docker/misc/gsrs/libjnainchi.so deleted file mode 100644 index 8839c5c14..000000000 Binary files a/packages/rails/docker/misc/gsrs/libjnainchi.so and /dev/null differ diff --git a/packages/rails/docker/misc/gsrs/run-version.sh b/packages/rails/docker/misc/gsrs/run-version.sh deleted file mode 100644 index 9134cf7c8..000000000 --- a/packages/rails/docker/misc/gsrs/run-version.sh +++ /dev/null @@ -1,22 +0,0 @@ -rm -rf /gsrs-to-deploy -mkdir /gsrs-to-deploy -cd /gsrs-to-deploy - -echo "Paste the name of branch from gsrs-play-dist repo you wish to run:" -read branch_name - -git clone -b $branch_name https://github.com/dnanexus/gsrs-play-dist.git - -cd gsrs-play-dist -cp -rf /gsrs-conf/substances_application.conf substances/WEB-INF/classes/application.conf -cp -rf /gsrs-conf/gateway_application.yml ROOT/WEB-INF/classes/application.yml -cp -rf /gsrs-conf/frontend_application.conf frontend/WEB-INF/classes/static/assets/data/config.json - -/usr/local/tomcat/bin/catalina.sh stop && rm -rf /usr/local/tomcat/work - -rm -rf /usr/local/tomcat/webapps/* -cp -rf /gsrs-to-deploy/gsrs-play-dist/* /usr/local/tomcat/webapps/ - -/usr/local/tomcat/bin/catalina.sh start - -echo -e "\nGSRS version updated, tomcat restarted\n" diff --git a/packages/rails/docker/misc/gsrs/switch-frontend.sh b/packages/rails/docker/misc/gsrs/switch-frontend.sh deleted file mode 100755 index 59a15fc20..000000000 --- a/packages/rails/docker/misc/gsrs/switch-frontend.sh +++ /dev/null @@ -1,26 +0,0 @@ -echo "Enter [1] to use frontend from your local source code (instant rebuilt on code change)" -echo "Enter [2] to use pre-built frontend" - -read choice - -if [[ $choice -eq 1 ]] -then - oldPwd=$(pwd) - cd /usr/local/GSRSFrontend - bash /usr/local/GSRSFrontend/build.sh - npm install webpack - sed -i 's$http://localhost:8080/frontend/ginas/app/ui$http://localhost:4200/ginas/app/ui$g' /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/application.yml - /usr/local/tomcat/bin/catalina.sh stop && rm -rf /usr/local/tomcat/work - /usr/local/tomcat/bin/catalina.sh start - npm run start:fda:local & - cd $oldPwd -elif [[ $choice -eq 2 ]] -then - sed -i 's$http://localhost:4200/ginas/app/ui$http://localhost:8080/frontend/ginas/app/ui$g' /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/application.yml - /usr/local/tomcat/bin/catalina.sh stop && rm -rf /usr/local/tomcat/work - /usr/local/tomcat/bin/catalina.sh start -else - echo "Invalid option. Not doing anything." -fi - - diff --git a/packages/rails/spec/controllers/api_controller_spec.rb b/packages/rails/spec/controllers/api_controller_spec.rb index ef48f9a6c..d9aa1cc1b 100644 --- a/packages/rails/spec/controllers/api_controller_spec.rb +++ b/packages/rails/spec/controllers/api_controller_spec.rb @@ -591,81 +591,6 @@ end end - describe "POST create_file" do - before do - authenticate!(user) - - allow(Users::ChargesFetcher).to receive(:exceeded_charges_limit?).and_return(false) - allow_any_instance_of(DNAnexusAPI).to( - receive(:call).with("file", "new", anything).and_return( - "id" => "file-Bx46ZqQ04Pz5Bq3x20pkBXP4", - ) - ) - end - - context "when sends a file with incorrect params" do - context "with empty name" do - it "doesn't create a file" do - post :create_file, params: { description: "some_desc" } - - expect(response).not_to have_http_status(200) - end - end - end - - context "when sends a file with correct params" do - it "creates a file" do - post :create_file, params: { name: "some_name", description: "some_desc" } - - expect(response).to have_http_status(200) - - expect(UserFile.last.attributes).to include( - "name" => "some_name", - "description" => "some_desc", - "dxid" => "file-Bx46ZqQ04Pz5Bq3x20pkBXP4", - "parent_folder_id" => nil, - ) - end - - it "creates a private file" do - post :create_file, params: { name: anything, public_scope: false } - - expect(UserFile.last.project).to eq(user.private_files_project) - expect(UserFile.last.scope).to eq("private") - end - - it "creates a public file" do - post :create_file, params: { name: anything, public_scope: true } - - expect(UserFile.last.project).to eq(user.public_files_project) - expect(UserFile.last.scope).to eq("public") - end - - context "when public_scope param doesn't exist" do - it "creates a private file" do - post :create_file, params: { name: anything } - - expect(UserFile.last.project).to eq(user.private_files_project) - expect(UserFile.last.scope).to eq("private") - end - end - end - - context "when user exceeded charges limit" do - before do - allow(Users::ChargesFetcher).to receive(:exceeded_charges_limit?).and_return(true) - end - - it "responds with an error" do - post :create_file, format: :json - - expect(response.status).to eq(422) - expect(parsed_response["error"]["message"]).to \ - include(I18n.t("api.errors.exceeded_charges_limit")) - end - end - end - describe "POST #set_tags" do context "when logged in" do let(:host_lead) { create(:user, dxuser: "user_1") } diff --git a/packages/rails/spec/serializers/asset_serializer_spec.rb b/packages/rails/spec/serializers/asset_serializer_spec.rb index ed3c2ab1c..2f66c73b9 100644 --- a/packages/rails/spec/serializers/asset_serializer_spec.rb +++ b/packages/rails/spec/serializers/asset_serializer_spec.rb @@ -36,8 +36,7 @@ expect(asset_serialized["links"]["update"]).to eq(api_files_path(asset)) end - it "links[add_file, add_folder] exist" do - expect(asset_serialized["links"]["add_file"]).to eq(api_create_file_path) + it "links[add_folder] exist" do expect(asset_serialized["links"]["add_folder"]).to eq(create_folder_api_files_path) end diff --git a/packages/rails/spec/serializers/user_file_serializer_spec.rb b/packages/rails/spec/serializers/user_file_serializer_spec.rb index c41761641..633b4892d 100644 --- a/packages/rails/spec/serializers/user_file_serializer_spec.rb +++ b/packages/rails/spec/serializers/user_file_serializer_spec.rb @@ -37,8 +37,7 @@ expect(user_file_serialized["links"]["download_list"]).to eq(download_list_api_files_path) end - it "links[add_file, add_folder, update] exist" do - expect(user_file_serialized["links"]["add_file"]).to eq(api_create_file_path) + it "links[add_folder, update] exist" do expect(user_file_serialized["links"]["add_folder"]).to eq(create_folder_api_files_path) expect(user_file_serialized["links"]["update"]).to eq(api_files_path) end diff --git a/packages/server/apps/api/src/admin/admin-memberships.controller.ts b/packages/server/apps/api/src/admin/admin-memberships.controller.ts index 89fefb442..7df7c854a 100644 --- a/packages/server/apps/api/src/admin/admin-memberships.controller.ts +++ b/packages/server/apps/api/src/admin/admin-memberships.controller.ts @@ -4,7 +4,7 @@ import { CreateAdminMembershipDTO } from '@shared/domain/admin-membership/dto/cr import { UserWithAdminRolesDTO } from '@shared/domain/admin-membership/dto/user-with-admin-roles.dto' import { PaginatedResult } from '@shared/domain/entity/domain/paginated.result' import { CreateAdminMembershipFacade } from '@shared/facade/admin-membership/create-admin-membership.facade' -import { ListAdminMembershipFacade } from '@shared/facade/admin-membership/list-admin-membership.facade' +import { AdminMembershipsListFacade } from '@shared/facade/admin-membership/admin-memberships-list.facade' import { RemoveAdminMembershipFacade } from '@shared/facade/admin-membership/remove-admin-membership.facade' import { UserContextGuard } from '../user-context/guard/user-context.guard' import { SiteAdminGuard } from './guards/site-admin.guard' @@ -13,7 +13,7 @@ import { SiteAdminGuard } from './guards/site-admin.guard' @Controller('/admin/memberships') export class AdminMembershipsController { constructor( - private readonly listAdminMembershipFacade: ListAdminMembershipFacade, + private readonly adminMembershipsListFacade: AdminMembershipsListFacade, private readonly createAdminMembershipFacade: CreateAdminMembershipFacade, private readonly removeAdminMembershipFacade: RemoveAdminMembershipFacade, ) {} @@ -22,7 +22,7 @@ export class AdminMembershipsController { async getUsersWithRoles( @Query() query: AdminMembershipPaginationDTO, ): Promise> { - return this.listAdminMembershipFacade.listUsersWithRoles(query) + return this.adminMembershipsListFacade.listUsersWithRoles(query) } @HttpCode(201) diff --git a/packages/server/apps/api/src/apps/app.api.module.ts b/packages/server/apps/api/src/apps/app.api.module.ts index 7eb2babf1..97743817f 100644 --- a/packages/server/apps/api/src/apps/app.api.module.ts +++ b/packages/server/apps/api/src/apps/app.api.module.ts @@ -2,10 +2,10 @@ import { Module } from '@nestjs/common' import { AppModule } from '@shared/domain/app/app.module' import { AppFacadeModule } from '@shared/facade/app/app-facade.module' import { LicenseApiFacadeModule } from '../facade/license/license-api-facade.module' -import { AppController } from './app.controller' +import { AppsController } from './apps.controller' @Module({ imports: [AppModule, LicenseApiFacadeModule, AppFacadeModule], - controllers: [AppController], + controllers: [AppsController], }) export class AppApiModule {} diff --git a/packages/server/apps/api/src/apps/app.controller.ts b/packages/server/apps/api/src/apps/apps.controller.ts similarity index 98% rename from packages/server/apps/api/src/apps/app.controller.ts rename to packages/server/apps/api/src/apps/apps.controller.ts index f279b957e..a09b5d481 100644 --- a/packages/server/apps/api/src/apps/app.controller.ts +++ b/packages/server/apps/api/src/apps/apps.controller.ts @@ -11,7 +11,7 @@ import { AppUidParamDto } from './model/app-uid-param.dto' @UseGuards(UserContextGuard) @Controller('/apps') -export class AppController { +export class AppsController { constructor( private readonly licensesForAppFacade: LicensesForAppFacade, private readonly appRunFacade: AppRunFacade, diff --git a/packages/server/apps/api/src/challenges/challenge.api.module.ts b/packages/server/apps/api/src/challenges/challenge.api.module.ts index 1d9d8ab3c..2233c0e92 100644 --- a/packages/server/apps/api/src/challenges/challenge.api.module.ts +++ b/packages/server/apps/api/src/challenges/challenge.api.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common' import { ChallengeModule } from '@shared/domain/challenge/challenge.module' import { ChallengeApiFacadeModule } from '../facade/challenge/challenge-api-facade.module' -import { ChallengeController } from './challenge.controller' +import { ChallengesController } from './challenges.controller' @Module({ imports: [ChallengeModule, ChallengeApiFacadeModule], - controllers: [ChallengeController], + controllers: [ChallengesController], }) export class ChallengeApiModule {} diff --git a/packages/server/apps/api/src/challenges/challenge.controller.ts b/packages/server/apps/api/src/challenges/challenges.controller.ts similarity index 99% rename from packages/server/apps/api/src/challenges/challenge.controller.ts rename to packages/server/apps/api/src/challenges/challenges.controller.ts index 332c43454..62da7aeae 100644 --- a/packages/server/apps/api/src/challenges/challenge.controller.ts +++ b/packages/server/apps/api/src/challenges/challenges.controller.ts @@ -15,7 +15,7 @@ import { ChallengeFacade } from '../facade/challenge/challenge.facade' import { UserContextGuard } from '../user-context/guard/user-context.guard' @Controller('/challenges') -export class ChallengeController { +export class ChallengesController { constructor( private readonly challengeService: ChallengeService, private readonly challengeFacade: ChallengeFacade, diff --git a/packages/server/apps/api/src/cli/cli-assets.controller.ts b/packages/server/apps/api/src/cli/cli-assets.controller.ts index 4988e94d7..ee3eb803a 100644 --- a/packages/server/apps/api/src/cli/cli-assets.controller.ts +++ b/packages/server/apps/api/src/cli/cli-assets.controller.ts @@ -1,16 +1,16 @@ import { Controller, Get, Query, UseGuards } from '@nestjs/common' -import { CliListAssetDTO } from '@shared/domain/cli/dto/cli-list-assets.dto' +import { CliAssetListDTO } from '@shared/domain/cli/dto/cli-assets-list.dto' import { CliScopeQueryDTO } from '@shared/domain/cli/dto/cli-scope-query.dto' -import { CliListAssetsFacade } from '../facade/cli/cli-list-assets.facade' +import { CliAssetsListFacade } from '../facade/cli/cli-assets-list.facade' import { UserContextGuard } from '../user-context/guard/user-context.guard' @Controller('/cli/assets') export class CliAssetsController { - constructor(private readonly cliListAssetsFacade: CliListAssetsFacade) {} + constructor(private readonly cliAssetsListFacade: CliAssetsListFacade) {} @UseGuards(UserContextGuard) @Get() - async listAssets(@Query() query: CliScopeQueryDTO): Promise { - return this.cliListAssetsFacade.listAssets(query.scope) + async listAssets(@Query() query: CliScopeQueryDTO): Promise { + return this.cliAssetsListFacade.listAssets(query.scope) } } diff --git a/packages/server/apps/api/src/cli/cli-dbclusters.controller.ts b/packages/server/apps/api/src/cli/cli-db-clusters.controller.ts similarity index 100% rename from packages/server/apps/api/src/cli/cli-dbclusters.controller.ts rename to packages/server/apps/api/src/cli/cli-db-clusters.controller.ts diff --git a/packages/server/apps/api/src/cli/cli-jobs.controller.ts b/packages/server/apps/api/src/cli/cli-jobs.controller.ts index 925ab50e2..9cba3da3b 100644 --- a/packages/server/apps/api/src/cli/cli-jobs.controller.ts +++ b/packages/server/apps/api/src/cli/cli-jobs.controller.ts @@ -1,11 +1,11 @@ import { Controller, Get, Param, Patch, Query, UseGuards } from '@nestjs/common' -import { CliListJobDTO } from '@shared/domain/cli/dto/cli-list-jobs.dto' +import { CliJobListDTO } from '@shared/domain/cli/dto/cli-jobs-list.dto' import { CliScopeQueryDTO } from '@shared/domain/cli/dto/cli-scope-query.dto' import { DxId } from '@shared/domain/entity/domain/dxid' import { Uid } from '@shared/domain/entity/domain/uid' import { EntityScope } from '@shared/types/common' import { CliJobScopeFacade } from '../facade/cli/cli-job-scope.facade' -import { CliListJobsFacade } from '../facade/cli/cli-list-jobs.facade' +import { CliJobsListFacade } from '../facade/cli/cli-jobs-list.facade' import { CliTerminateJobFacade } from '../facade/cli/cli-terminate-job.facade' import { UserContextGuard } from '../user-context/guard/user-context.guard' import { UidValidationPipe } from '../validation/pipes/uid.pipe' @@ -16,7 +16,7 @@ export class CliJobsController { constructor( private readonly cliJobScopeFacade: CliJobScopeFacade, private readonly cliTerminateJobFacade: CliTerminateJobFacade, - private readonly cliListJobsFacade: CliListJobsFacade, + private readonly cliJobsListFacade: CliJobsListFacade, ) {} @UseGuards(UserContextGuard) @@ -29,8 +29,8 @@ export class CliJobsController { @UseGuards(UserContextGuard) @Get() - async listJobs(@Query() query: CliScopeQueryDTO): Promise { - return this.cliListJobsFacade.listJobs(query.scope) + async listJobs(@Query() query: CliScopeQueryDTO): Promise { + return this.cliJobsListFacade.listJobs(query.scope) } @UseGuards(UserContextGuard) diff --git a/packages/server/apps/api/src/cli/cli-spaces.controller.ts b/packages/server/apps/api/src/cli/cli-spaces.controller.ts index 129b3916d..2e3a0f043 100644 --- a/packages/server/apps/api/src/cli/cli-spaces.controller.ts +++ b/packages/server/apps/api/src/cli/cli-spaces.controller.ts @@ -1,40 +1,40 @@ import { Body, Controller, Get, HttpCode, Param, ParseIntPipe, Post, Query, UseGuards } from '@nestjs/common' import { CliCreateDiscussionDTO } from '@shared/domain/cli/dto/cli-create-discussion.dto' import { CliDiscussionDTO } from '@shared/domain/cli/dto/cli-discussion.dto' -import { CliListSpaceDTO } from '@shared/domain/cli/dto/cli-list-spaces.dto' -import { CliListSpacesQueryDTO } from '@shared/domain/cli/dto/cli-list-spaces-query.dto' +import { CliSpaceListDTO } from '@shared/domain/cli/dto/cli-spaces-list.dto' +import { CliSpacesListQueryDTO } from '@shared/domain/cli/dto/cli-spaces-list-query.dto' import { CliSpaceMemberDTO } from '@shared/domain/cli/dto/cli-space-member.dto' import { CliCreateDiscussionFacade } from '../facade/cli/cli-create-discussion.facade' -import { CliListDiscussionsFacade } from '../facade/cli/cli-list-discussions.facade' -import { CliListMembersFacade } from '../facade/cli/cli-list-members.facade' -import { CliListSpacesFacade } from '../facade/cli/cli-list-spaces.facade' +import { CliDiscussionsListFacade } from '../facade/cli/cli-discussions-list.facade' +import { CliMembersListFacade } from '../facade/cli/cli-members-list.facade' +import { CliSpacesListFacade } from '../facade/cli/cli-spaces-list.facade' import { UserContextGuard } from '../user-context/guard/user-context.guard' @Controller('/cli/spaces') export class CliSpacesController { constructor( - private readonly cliListSpacesFacade: CliListSpacesFacade, - private readonly cliListMembersFacade: CliListMembersFacade, - private readonly cliListDiscussionsFacade: CliListDiscussionsFacade, + private readonly cliSpacesListFacade: CliSpacesListFacade, + private readonly cliMembersListFacade: CliMembersListFacade, + private readonly cliDiscussionsListFacade: CliDiscussionsListFacade, private readonly cliCreateDiscussionFacade: CliCreateDiscussionFacade, ) {} @UseGuards(UserContextGuard) @Get() - async listSpaces(@Query() query: CliListSpacesQueryDTO): Promise { - return this.cliListSpacesFacade.listSpaces(query) + async listSpaces(@Query() query: CliSpacesListQueryDTO): Promise { + return this.cliSpacesListFacade.listSpaces(query) } @UseGuards(UserContextGuard) @Get('/:id/members') async listMembers(@Param('id', ParseIntPipe) spaceId: number): Promise { - return this.cliListMembersFacade.listSpaceMembers(spaceId) + return this.cliMembersListFacade.listSpaceMembers(spaceId) } @UseGuards(UserContextGuard) @Get('/:id/discussions') async listDiscussions(@Param('id', ParseIntPipe) spaceId: number): Promise { - return this.cliListDiscussionsFacade.listDiscussions(spaceId) + return this.cliDiscussionsListFacade.listDiscussions(spaceId) } @UseGuards(UserContextGuard) diff --git a/packages/server/apps/api/src/cli/cli.api.module.ts b/packages/server/apps/api/src/cli/cli.api.module.ts index dcb746f74..7f64363cd 100644 --- a/packages/server/apps/api/src/cli/cli.api.module.ts +++ b/packages/server/apps/api/src/cli/cli.api.module.ts @@ -7,7 +7,7 @@ import { DiscussionApiFacadeModule } from '../facade/discussion/discussion-api-f import { UserFileApiFacadeModule } from '../facade/user-file/user-file-api-facade.module' import { CliController } from './cli.controller' import { CliAssetsController } from './cli-assets.controller' -import { CliDbClustersController } from './cli-dbclusters.controller' +import { CliDbClustersController } from './cli-db-clusters.controller' import { CliDescribeController } from './cli-describe.controller' import { CliDiscussionsController } from './cli-discussions.controller' import { CliFilesController } from './cli-files.controller' diff --git a/packages/server/apps/api/src/dbclusters/dbcluster.controller.ts b/packages/server/apps/api/src/dbclusters/db-clusters.controller.ts similarity index 94% rename from packages/server/apps/api/src/dbclusters/dbcluster.controller.ts rename to packages/server/apps/api/src/dbclusters/db-clusters.controller.ts index 0d966b849..e702e878a 100644 --- a/packages/server/apps/api/src/dbclusters/dbcluster.controller.ts +++ b/packages/server/apps/api/src/dbclusters/db-clusters.controller.ts @@ -12,7 +12,7 @@ import { Uid } from '@shared/domain/entity/domain/uid' import { DbClusterActionFacade } from '../facade/db-cluster/action-facade/db-cluster-action.facade' import { DbClusterCreateFacade } from '../facade/db-cluster/create-facade/db-cluster-create.facade' import { DbClusterGetFacade } from '../facade/db-cluster/get-facade/db-cluster-get.facade' -import { DbClusterListFacade } from '../facade/db-cluster/list-facade/db-cluster-list.facade' +import { DbClustersListFacade } from '../facade/db-cluster/list-facade/db-clusters-list.facade' import { DbClusterSynchronizeFacade } from '../facade/db-cluster/synchronize-facade/db-cluster-synchronize.facade' import { DbClusterUpdateFacade } from '../facade/db-cluster/update-facade/db-cluster-update.facade' import { InternalRouteGuard } from '../internal/guard/internal.guard' @@ -22,21 +22,21 @@ import { DbClusterUidParamDto } from './model/dbcluster-uid-param.dto' @ApiTags('dbclusters') @UseGuards(UserContextGuard) @Controller('/dbclusters') -export class DbClusterController { +export class DbClustersController { constructor( private readonly dbClusterSynchronizeFacade: DbClusterSynchronizeFacade, private readonly dbClusterCreateFacade: DbClusterCreateFacade, private readonly dbClusterUpdateFacade: DbClusterUpdateFacade, private readonly dbClusterActionFacade: DbClusterActionFacade, private readonly dbClusterGetFacade: DbClusterGetFacade, - private readonly dbClusterListFacade: DbClusterListFacade, + private readonly dbClustersListFacade: DbClustersListFacade, ) {} @ApiOperation({ summary: 'List db clusters' }) @ApiOkResponse({ description: 'Paginated list of db clusters' }) @Get() async list(@Query() query: DbClusterPaginationDTO): Promise> { - return await this.dbClusterListFacade.listDbClusters(query) + return await this.dbClustersListFacade.listDbClusters(query) } @ApiOperation({ summary: 'Get db cluster by uid' }) diff --git a/packages/server/apps/api/src/dbclusters/dbcluster.api.module.ts b/packages/server/apps/api/src/dbclusters/dbcluster.api.module.ts index 314e784f6..0ea45d72d 100644 --- a/packages/server/apps/api/src/dbclusters/dbcluster.api.module.ts +++ b/packages/server/apps/api/src/dbclusters/dbcluster.api.module.ts @@ -2,10 +2,10 @@ import { Module } from '@nestjs/common' import { DbClusterActionFacadeModule } from '../facade/db-cluster/action-facade/db-cluster-action-facade.module' import { DbClusterCreateFacadeModule } from '../facade/db-cluster/create-facade/db-cluster-create-facade.module' import { DbClusterGetFacadeModule } from '../facade/db-cluster/get-facade/db-cluster-get-facade.module' -import { DbClusterListFacadeModule } from '../facade/db-cluster/list-facade/db-cluster-list-facade.module' +import { DbClustersListFacadeModule } from '../facade/db-cluster/list-facade/db-clusters-list-facade.module' import { DbClusterSynchronizeFacadeModule } from '../facade/db-cluster/synchronize-facade/db-cluster-synchronize-facade.module' import { DbClusterUpdateFacadeModule } from '../facade/db-cluster/update-facade/db-cluster-update-facade.module' -import { DbClusterController } from './dbcluster.controller' +import { DbClustersController } from './db-clusters.controller' @Module({ imports: [ @@ -14,8 +14,8 @@ import { DbClusterController } from './dbcluster.controller' DbClusterUpdateFacadeModule, DbClusterActionFacadeModule, DbClusterGetFacadeModule, - DbClusterListFacadeModule, + DbClustersListFacadeModule, ], - controllers: [DbClusterController], + controllers: [DbClustersController], }) export class DbClusterApiModule {} diff --git a/packages/server/apps/api/src/emails/email.api.module.ts b/packages/server/apps/api/src/emails/email.api.module.ts index 478124b34..806b1576d 100644 --- a/packages/server/apps/api/src/emails/email.api.module.ts +++ b/packages/server/apps/api/src/emails/email.api.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common' import { EmailModule } from '@shared/domain/email/email.module' -import { EmailController } from './email.controller' +import { EmailsController } from './emails.controller' @Module({ imports: [EmailModule], - controllers: [EmailController], + controllers: [EmailsController], }) export class EmailApiModule {} diff --git a/packages/server/apps/api/src/emails/email.controller.ts b/packages/server/apps/api/src/emails/emails.controller.ts similarity index 95% rename from packages/server/apps/api/src/emails/email.controller.ts rename to packages/server/apps/api/src/emails/emails.controller.ts index 18a3cc6fc..b22e5d0d6 100644 --- a/packages/server/apps/api/src/emails/email.controller.ts +++ b/packages/server/apps/api/src/emails/emails.controller.ts @@ -6,7 +6,7 @@ import { InternalRouteGuard } from '../internal/guard/internal.guard' @UseGuards(InternalRouteGuard) @Controller('/emails') -export class EmailController { +export class EmailsController { constructor(private readonly emailService: EmailService) {} @HttpCode(200) diff --git a/packages/server/apps/api/src/facade/cli/cli-api-facade.module.ts b/packages/server/apps/api/src/facade/cli/cli-api-facade.module.ts index 41ea36ebc..999cdd756 100644 --- a/packages/server/apps/api/src/facade/cli/cli-api-facade.module.ts +++ b/packages/server/apps/api/src/facade/cli/cli-api-facade.module.ts @@ -16,11 +16,11 @@ import { UserFileApiFacadeModule } from '../user-file/user-file-api-facade.modul import { CliDescribeEntityFacade } from './cli-describe-entity.facade' import { CliFindNodesFacade } from './cli-find-nodes.facade' import { CliJobScopeFacade } from './cli-job-scope.facade' -import { CliListAssetsFacade } from './cli-list-assets.facade' -import { CliListDiscussionsFacade } from './cli-list-discussions.facade' -import { CliListJobsFacade } from './cli-list-jobs.facade' -import { CliListMembersFacade } from './cli-list-members.facade' -import { CliListSpacesFacade } from './cli-list-spaces.facade' +import { CliAssetsListFacade } from './cli-assets-list.facade' +import { CliDiscussionsListFacade } from './cli-discussions-list.facade' +import { CliJobsListFacade } from './cli-jobs-list.facade' +import { CliMembersListFacade } from './cli-members-list.facade' +import { CliSpacesListFacade } from './cli-spaces-list.facade' import { CliNodeRemoveFacade } from './cli-node-remove.facade' import { CliRunAppFacade } from './cli-run-app.facade' import { CliTerminateJobFacade } from './cli-terminate-job.facade' @@ -46,27 +46,27 @@ import { CliTerminateJobFacade } from './cli-terminate-job.facade' CliDescribeEntityFacade, CliJobScopeFacade, CliNodeRemoveFacade, - CliListMembersFacade, - CliListDiscussionsFacade, + CliMembersListFacade, + CliDiscussionsListFacade, CliFindNodesFacade, CliRunAppFacade, CliTerminateJobFacade, - CliListSpacesFacade, - CliListAssetsFacade, - CliListJobsFacade, + CliSpacesListFacade, + CliAssetsListFacade, + CliJobsListFacade, ], exports: [ CliDescribeEntityFacade, CliJobScopeFacade, CliNodeRemoveFacade, - CliListMembersFacade, - CliListDiscussionsFacade, + CliMembersListFacade, + CliDiscussionsListFacade, CliFindNodesFacade, CliRunAppFacade, CliTerminateJobFacade, - CliListSpacesFacade, - CliListAssetsFacade, - CliListJobsFacade, + CliSpacesListFacade, + CliAssetsListFacade, + CliJobsListFacade, ], }) export class CliApiFacadeModule {} diff --git a/packages/server/apps/api/src/facade/cli/cli-list-assets.facade.ts b/packages/server/apps/api/src/facade/cli/cli-assets-list.facade.ts similarity index 86% rename from packages/server/apps/api/src/facade/cli/cli-list-assets.facade.ts rename to packages/server/apps/api/src/facade/cli/cli-assets-list.facade.ts index 439af5b86..b314cce50 100644 --- a/packages/server/apps/api/src/facade/cli/cli-list-assets.facade.ts +++ b/packages/server/apps/api/src/facade/cli/cli-assets-list.facade.ts @@ -1,6 +1,6 @@ import { FilterQuery } from '@mikro-orm/mysql' import { Injectable } from '@nestjs/common' -import { CliListAssetDTO } from '@shared/domain/cli/dto/cli-list-assets.dto' +import { CliAssetListDTO } from '@shared/domain/cli/dto/cli-assets-list.dto' import { SpaceService } from '@shared/domain/space/service/space.service' import { UserContext } from '@shared/domain/user-context/model/user-context' import { Asset } from '@shared/domain/user-file/asset.entity' @@ -11,14 +11,14 @@ import { EntityScope } from '@shared/types/common' import { EntityScopeUtils } from '@shared/utils/entity-scope.utils' @Injectable() -export class CliListAssetsFacade { +export class CliAssetsListFacade { constructor( private readonly nodeService: NodeService, private readonly user: UserContext, private readonly spaceService: SpaceService, ) {} - async listAssets(scope: EntityScope): Promise { + async listAssets(scope: EntityScope): Promise { let where: FilterQuery if (EntityScopeUtils.isSpaceScope(scope)) { @@ -40,6 +40,6 @@ export class CliListAssetsFacade { orderBy: { createdAt: 'DESC' } as const, }) - return assets.map(asset => CliListAssetDTO.fromEntity(asset)) + return assets.map(asset => CliAssetListDTO.fromEntity(asset)) } } diff --git a/packages/server/apps/api/src/facade/cli/cli-list-discussions.facade.ts b/packages/server/apps/api/src/facade/cli/cli-discussions-list.facade.ts similarity index 95% rename from packages/server/apps/api/src/facade/cli/cli-list-discussions.facade.ts rename to packages/server/apps/api/src/facade/cli/cli-discussions-list.facade.ts index 105bf43de..1223817e1 100644 --- a/packages/server/apps/api/src/facade/cli/cli-list-discussions.facade.ts +++ b/packages/server/apps/api/src/facade/cli/cli-discussions-list.facade.ts @@ -5,7 +5,7 @@ import { DiscussionService } from '@shared/domain/discussion/services/discussion import { EntityScopeUtils } from '@shared/utils/entity-scope.utils' @Injectable() -export class CliListDiscussionsFacade { +export class CliDiscussionsListFacade { constructor(private readonly discussionService: DiscussionService) {} async listDiscussions(spaceId: number): Promise { diff --git a/packages/server/apps/api/src/facade/cli/cli-list-jobs.facade.ts b/packages/server/apps/api/src/facade/cli/cli-jobs-list.facade.ts similarity index 86% rename from packages/server/apps/api/src/facade/cli/cli-list-jobs.facade.ts rename to packages/server/apps/api/src/facade/cli/cli-jobs-list.facade.ts index 06b1d15f3..4d7d24436 100644 --- a/packages/server/apps/api/src/facade/cli/cli-list-jobs.facade.ts +++ b/packages/server/apps/api/src/facade/cli/cli-jobs-list.facade.ts @@ -1,6 +1,6 @@ import { FilterQuery } from '@mikro-orm/mysql' import { Injectable } from '@nestjs/common' -import { CliListJobDTO } from '@shared/domain/cli/dto/cli-list-jobs.dto' +import { CliJobListDTO } from '@shared/domain/cli/dto/cli-jobs-list.dto' import { Job } from '@shared/domain/job/job.entity' import { JobService } from '@shared/domain/job/job.service' import { SpaceService } from '@shared/domain/space/service/space.service' @@ -11,14 +11,14 @@ import { EntityScope } from '@shared/types/common' import { EntityScopeUtils } from '@shared/utils/entity-scope.utils' @Injectable() -export class CliListJobsFacade { +export class CliJobsListFacade { constructor( private readonly user: UserContext, private readonly jobService: JobService, private readonly spaceService: SpaceService, ) {} - async listJobs(scope: EntityScope): Promise { + async listJobs(scope: EntityScope): Promise { let where: FilterQuery if (EntityScopeUtils.isSpaceScope(scope)) { @@ -43,6 +43,6 @@ export class CliListJobsFacade { orderBy: { createdAt: 'DESC' }, }) - return jobs.map(job => CliListJobDTO.fromEntity(job)) + return jobs.map(job => CliJobListDTO.fromEntity(job)) } } diff --git a/packages/server/apps/api/src/facade/cli/cli-list-members.facade.ts b/packages/server/apps/api/src/facade/cli/cli-members-list.facade.ts similarity index 93% rename from packages/server/apps/api/src/facade/cli/cli-list-members.facade.ts rename to packages/server/apps/api/src/facade/cli/cli-members-list.facade.ts index 18d083728..cdd45e67b 100644 --- a/packages/server/apps/api/src/facade/cli/cli-list-members.facade.ts +++ b/packages/server/apps/api/src/facade/cli/cli-members-list.facade.ts @@ -3,7 +3,7 @@ import { CliSpaceMemberDTO } from '@shared/domain/cli/dto/cli-space-member.dto' import { SpaceService } from '@shared/domain/space/service/space.service' @Injectable() -export class CliListMembersFacade { +export class CliMembersListFacade { constructor(private readonly spaceService: SpaceService) {} async listSpaceMembers(spaceId: number): Promise { diff --git a/packages/server/apps/api/src/facade/cli/cli-list-spaces.facade.ts b/packages/server/apps/api/src/facade/cli/cli-spaces-list.facade.ts similarity index 75% rename from packages/server/apps/api/src/facade/cli/cli-list-spaces.facade.ts rename to packages/server/apps/api/src/facade/cli/cli-spaces-list.facade.ts index f6db6417f..eb312fa59 100644 --- a/packages/server/apps/api/src/facade/cli/cli-list-spaces.facade.ts +++ b/packages/server/apps/api/src/facade/cli/cli-spaces-list.facade.ts @@ -1,20 +1,20 @@ import { FilterQuery } from '@mikro-orm/mysql' import { Injectable } from '@nestjs/common' -import { CliListSpaceDTO } from '@shared/domain/cli/dto/cli-list-spaces.dto' -import { CliListSpacesQueryDTO } from '@shared/domain/cli/dto/cli-list-spaces-query.dto' +import { CliSpaceListDTO } from '@shared/domain/cli/dto/cli-spaces-list.dto' +import { CliSpacesListQueryDTO } from '@shared/domain/cli/dto/cli-spaces-list-query.dto' import { SpaceService } from '@shared/domain/space/service/space.service' import { Space } from '@shared/domain/space/space.entity' import { SPACE_STATE } from '@shared/domain/space/space.enum' import { UserContext } from '@shared/domain/user-context/model/user-context' @Injectable() -export class CliListSpacesFacade { +export class CliSpacesListFacade { constructor( private readonly user: UserContext, private readonly spaceService: SpaceService, ) {} - async listSpaces(query: CliListSpacesQueryDTO): Promise { + async listSpaces(query: CliSpacesListQueryDTO): Promise { const state = query.state ?? SPACE_STATE.ACTIVE const where: FilterQuery = { state } @@ -33,7 +33,7 @@ export class CliListSpacesFacade { return spaces.map(space => { const membership = space.spaceMemberships.getItems().find(m => m.user.id === this.user.id && m.active) - return CliListSpaceDTO.fromEntity(space, membership) + return CliSpaceListDTO.fromEntity(space, membership) }) } } diff --git a/packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list-facade.module.ts b/packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list-facade.module.ts similarity index 71% rename from packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list-facade.module.ts rename to packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list-facade.module.ts index fe88d828d..90017deab 100644 --- a/packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list-facade.module.ts +++ b/packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list-facade.module.ts @@ -3,11 +3,11 @@ import { DbClusterModule } from '@shared/domain/db-cluster/db-cluster.module' import { LicenseModule } from '@shared/domain/license/license.module' import { SpaceModule } from '@shared/domain/space/space.module' import { SpaceMembershipModule } from '@shared/domain/space-membership/space-membership.module' -import { DbClusterListFacade } from './db-cluster-list.facade' +import { DbClustersListFacade } from './db-clusters-list.facade' @Module({ imports: [DbClusterModule, SpaceModule, SpaceMembershipModule, LicenseModule], - providers: [DbClusterListFacade], - exports: [DbClusterListFacade], + providers: [DbClustersListFacade], + exports: [DbClustersListFacade], }) -export class DbClusterListFacadeModule {} +export class DbClustersListFacadeModule {} diff --git a/packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list.facade.ts b/packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list.facade.ts similarity index 99% rename from packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list.facade.ts rename to packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list.facade.ts index b21cf63e2..042404089 100644 --- a/packages/server/apps/api/src/facade/db-cluster/list-facade/db-cluster-list.facade.ts +++ b/packages/server/apps/api/src/facade/db-cluster/list-facade/db-clusters-list.facade.ts @@ -15,7 +15,7 @@ import { PermissionError } from '@shared/errors' import { ServiceLogger } from '@shared/logger/decorator/service-logger' @Injectable() -export class DbClusterListFacade { +export class DbClustersListFacade { @ServiceLogger() private readonly logger: Logger diff --git a/packages/server/apps/api/src/facade/space-membership/space-membership-api-facade.module.ts b/packages/server/apps/api/src/facade/space-membership/space-membership-api-facade.module.ts index 4e3329a14..402fb7eb0 100644 --- a/packages/server/apps/api/src/facade/space-membership/space-membership-api-facade.module.ts +++ b/packages/server/apps/api/src/facade/space-membership/space-membership-api-facade.module.ts @@ -1,13 +1,13 @@ import { Module } from '@nestjs/common' import { DbClusterSynchronizeFacadeModule } from 'apps/api/src/facade/db-cluster/synchronize-facade/db-cluster-synchronize-facade.module' -import { SpaceMembershipListApiFacade } from 'apps/api/src/facade/space-membership/space-membership-list-api.facade' +import { SpaceMembershipsListApiFacade } from 'apps/api/src/facade/space-membership/space-memberships-list-api.facade' import { SpaceMembershipUpdateApiFacade } from 'apps/api/src/facade/space-membership/space-membership-update-api.facade' import { SpaceModule } from '@shared/domain/space/space.module' import { SpaceMembershipFacadeModule } from '@shared/facade/space-membership/space-membership-facade.module' @Module({ imports: [SpaceMembershipFacadeModule, DbClusterSynchronizeFacadeModule, SpaceModule], - providers: [SpaceMembershipUpdateApiFacade, SpaceMembershipListApiFacade], - exports: [SpaceMembershipUpdateApiFacade, SpaceMembershipListApiFacade], + providers: [SpaceMembershipUpdateApiFacade, SpaceMembershipsListApiFacade], + exports: [SpaceMembershipUpdateApiFacade, SpaceMembershipsListApiFacade], }) export class SpaceMembershipApiFacadeModule {} diff --git a/packages/server/apps/api/src/facade/space-membership/space-membership-list-api.facade.ts b/packages/server/apps/api/src/facade/space-membership/space-memberships-list-api.facade.ts similarity index 93% rename from packages/server/apps/api/src/facade/space-membership/space-membership-list-api.facade.ts rename to packages/server/apps/api/src/facade/space-membership/space-memberships-list-api.facade.ts index 8733fdd54..b7c6983f9 100644 --- a/packages/server/apps/api/src/facade/space-membership/space-membership-list-api.facade.ts +++ b/packages/server/apps/api/src/facade/space-membership/space-memberships-list-api.facade.ts @@ -4,7 +4,7 @@ import { SpaceService } from '@shared/domain/space/service/space.service' import { SpaceMemberDTO } from '@shared/domain/space-membership/dto/space-member.dto' @Injectable() -export class SpaceMembershipListApiFacade { +export class SpaceMembershipsListApiFacade { constructor( private readonly em: SqlEntityManager, private readonly spaceService: SpaceService, diff --git a/packages/server/apps/api/src/files/files.api.module.ts b/packages/server/apps/api/src/files/files.api.module.ts index 1227d9b1d..5b628bfab 100644 --- a/packages/server/apps/api/src/files/files.api.module.ts +++ b/packages/server/apps/api/src/files/files.api.module.ts @@ -1,10 +1,11 @@ import { Module } from '@nestjs/common' import { UserFileModule } from '@shared/domain/user-file/user-file.module' +import { UserFileCreateFacadeModule } from '@shared/facade/file-create/user-file-create-facade.module' import { UserFileApiFacadeModule } from '../facade/user-file/user-file-api-facade.module' import { FilesController } from './files.controller' @Module({ - imports: [UserFileModule, UserFileApiFacadeModule], + imports: [UserFileModule, UserFileApiFacadeModule, UserFileCreateFacadeModule], controllers: [FilesController], }) export class FilesApiModule {} diff --git a/packages/server/apps/api/src/files/files.controller.ts b/packages/server/apps/api/src/files/files.controller.ts index 4e4766ab8..0933196c6 100644 --- a/packages/server/apps/api/src/files/files.controller.ts +++ b/packages/server/apps/api/src/files/files.controller.ts @@ -16,6 +16,7 @@ import { Query, Res, UseGuards, + UsePipes, } from '@nestjs/common' import { ApiOperation, ApiQuery, ApiResponse } from '@nestjs/swagger' import archiver from 'archiver' @@ -24,20 +25,24 @@ import { compareVersions } from 'compare-versions' import { Response } from 'express' import { DownloadLinkOptionsDTO } from '@shared/domain/entity/domain/download-link-options.dto' import { Uid } from '@shared/domain/entity/domain/uid' +import { EntityUidResponseDTO } from '@shared/domain/entity/dto/entity-uid-response.dto' import { UserContext } from '@shared/domain/user-context/model/user-context' -import { ResolvePathDTO } from '@shared/domain/user-file/dto/user-file.dto' import { FileGetDTO } from '@shared/domain/user-file/dto/file-get.dto' +import { ResolvePathDTO } from '@shared/domain/user-file/dto/user-file.dto' +import { UserFileCreateDTO } from '@shared/domain/user-file/dto/user-file-create.dto' import { NodeService } from '@shared/domain/user-file/node.service' import { UrlFetchService } from '@shared/domain/user-file/service/url-fetch.service' import { ExistingFileSet, ResolvePath, SelectedNode } from '@shared/domain/user-file/user-file.types' +import { UserFileCreateFacade } from '@shared/facade/file-create/user-file-create.facade' import { GetUploadURLResponse } from '@shared/platform-client/platform-client.responses' import { createCloseFileJobTask } from '@shared/queue' import { TimeUtils } from '@shared/utils/time.utils' +import { SnakeToCamelPipe } from '@shared/validation/pipes/snake-to-camel.pipe' import { CustomValidationPipe } from '@shared/validation/pipes/validation.pipe' import { UserFileBulkDownloadFacade } from '../facade/user-file/user-file-bulk-download.facade' import { UserFileDownloadFacade } from '../facade/user-file/user-file-download.facade' -import { UserFileResolverFacade } from '../facade/user-file/user-file-resolver.facade' import { UserFileGetFacade } from '../facade/user-file/user-file-get.facade' +import { UserFileResolverFacade } from '../facade/user-file/user-file-resolver.facade' import { InternalRouteGuard } from '../internal/guard/internal.guard' import { UserContextGuard } from '../user-context/guard/user-context.guard' import { FileUidParamDTO } from './model/file-uid-param.dto' @@ -56,8 +61,24 @@ export class FilesController { private readonly userFileGetFacade: UserFileGetFacade, private readonly userFileDownloadFacade: UserFileDownloadFacade, private readonly userFileBulkDownloadFacade: UserFileBulkDownloadFacade, + private readonly userFileCreateFacade: UserFileCreateFacade, ) {} + @Post() + @UsePipes(new SnakeToCamelPipe()) + async createFile( + @Body() input: UserFileCreateDTO, + @Res({ passthrough: true }) res: Response, + @Headers('user-agent') userAgent?: string, + ): Promise { + const result = await this.userFileCreateFacade.createFile(input) + + // Keep returning 200 for JupyterLab client + if (userAgent?.includes('python-requests')) res.status(200) + + return result + } + @Get('/:uid/upload-url') async getUploadUrl( @Param() params: FileUidParamDTO, diff --git a/packages/server/apps/api/src/folders/folder.api.module.ts b/packages/server/apps/api/src/folders/folder.api.module.ts index 55fdb4a23..71cd79ad5 100644 --- a/packages/server/apps/api/src/folders/folder.api.module.ts +++ b/packages/server/apps/api/src/folders/folder.api.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common' import { UserFileModule } from '@shared/domain/user-file/user-file.module' -import { FolderController } from './folder.controller' +import { FoldersController } from './folders.controller' @Module({ imports: [UserFileModule], - controllers: [FolderController], + controllers: [FoldersController], }) export class FolderApiModule {} diff --git a/packages/server/apps/api/src/folders/folder.controller.ts b/packages/server/apps/api/src/folders/folders.controller.ts similarity index 94% rename from packages/server/apps/api/src/folders/folder.controller.ts rename to packages/server/apps/api/src/folders/folders.controller.ts index 044af7e53..be061a7ed 100644 --- a/packages/server/apps/api/src/folders/folder.controller.ts +++ b/packages/server/apps/api/src/folders/folders.controller.ts @@ -6,7 +6,7 @@ import { FetchChildrenDTO } from './model/fetch-children.dto' @UseGuards(UserContextGuard) @Controller('/folders') -export class FolderController { +export class FoldersController { constructor(private readonly nodeService: NodeService) {} @Get('/children') diff --git a/packages/server/apps/api/src/jobs/job.api.module.ts b/packages/server/apps/api/src/jobs/job.api.module.ts index c0c8b729d..97678a4ef 100644 --- a/packages/server/apps/api/src/jobs/job.api.module.ts +++ b/packages/server/apps/api/src/jobs/job.api.module.ts @@ -2,10 +2,10 @@ import { Module } from '@nestjs/common' import { JobModule } from '@shared/domain/job/job.module' import { JobFacadeModule } from '@shared/facade/job/job-facade.module' import { JobGetFacadeModule } from '../facade/job/get-facade/job-get-facade.module' -import { JobController } from './job.controller' +import { JobsController } from './jobs.controller' @Module({ imports: [JobModule, JobFacadeModule, JobGetFacadeModule], - controllers: [JobController], + controllers: [JobsController], }) export class JobApiModule {} diff --git a/packages/server/apps/api/src/jobs/job.controller.ts b/packages/server/apps/api/src/jobs/jobs.controller.ts similarity index 99% rename from packages/server/apps/api/src/jobs/job.controller.ts rename to packages/server/apps/api/src/jobs/jobs.controller.ts index 23f87372a..c30041c8d 100644 --- a/packages/server/apps/api/src/jobs/job.controller.ts +++ b/packages/server/apps/api/src/jobs/jobs.controller.ts @@ -18,7 +18,7 @@ import { DxidValidationPipe } from '../validation/pipes/dxid.pipe' @UseGuards(UserContextGuard) @Controller('/jobs') -export class JobController { +export class JobsController { constructor( private readonly jobSynchronizationService: JobSynchronizationService, private readonly jobService: JobService, diff --git a/packages/server/apps/api/src/licenses/license.api.module.ts b/packages/server/apps/api/src/licenses/license.api.module.ts index 5389c9e1e..cddf7dfe5 100644 --- a/packages/server/apps/api/src/licenses/license.api.module.ts +++ b/packages/server/apps/api/src/licenses/license.api.module.ts @@ -2,10 +2,10 @@ import { Module } from '@nestjs/common' import { AcceptedLicenseModule } from '@shared/domain/accepted-license/accepted-license.module' import { LicenseModule } from '@shared/domain/license/license.module' import { LicenseApiFacadeModule } from '../facade/license/license-api-facade.module' -import { LicenseController } from './license.controller' +import { LicensesController } from './licenses.controller' @Module({ imports: [LicenseModule, AcceptedLicenseModule, LicenseApiFacadeModule], - controllers: [LicenseController], + controllers: [LicensesController], }) export class LicenseApiModule {} diff --git a/packages/server/apps/api/src/licenses/license.controller.ts b/packages/server/apps/api/src/licenses/licenses.controller.ts similarity index 99% rename from packages/server/apps/api/src/licenses/license.controller.ts rename to packages/server/apps/api/src/licenses/licenses.controller.ts index 0b0b67bad..32d48b274 100644 --- a/packages/server/apps/api/src/licenses/license.controller.ts +++ b/packages/server/apps/api/src/licenses/licenses.controller.ts @@ -14,7 +14,7 @@ import { UpdateLicenseDto } from './model/update-license.dto' @ApiCookieAuth() @UseGuards(UserContextGuard) @Controller('/licenses') -export class LicenseController { +export class LicensesController { constructor( private readonly licenseService: LicenseService, private readonly acceptedLicenseService: AcceptedLicenseService, diff --git a/packages/server/apps/api/src/news/news.api.module.ts b/packages/server/apps/api/src/news/news.api.module.ts index 195cc61f6..c896fe935 100644 --- a/packages/server/apps/api/src/news/news.api.module.ts +++ b/packages/server/apps/api/src/news/news.api.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common' -import { NewsModule } from '@shared/domain/news-item/news-item.module' +import { NewsItemModule } from '@shared/domain/news-item/news-item.module' import { NewsController } from './news.controller' @Module({ - imports: [NewsModule], + imports: [NewsItemModule], controllers: [NewsController], }) export class NewsApiModule {} diff --git a/packages/server/apps/api/src/news/news.controller.ts b/packages/server/apps/api/src/news/news.controller.ts index 0f6b3dd04..d457b4d46 100644 --- a/packages/server/apps/api/src/news/news.controller.ts +++ b/packages/server/apps/api/src/news/news.controller.ts @@ -15,52 +15,52 @@ import { PaginatedResult } from '@shared/domain/entity/domain/paginated.result' import { NewsItemDTO } from '@shared/domain/news-item/dto/news-item.dto' import { NewsListDTO } from '@shared/domain/news-item/dto/news-list.dto' import { NewsItem } from '@shared/domain/news-item/news-item.entity' -import { NewsService } from '@shared/domain/news-item/service/new-item.service' +import { NewsItemService } from '@shared/domain/news-item/service/news-item.service' import { SiteAdminGuard } from '../admin/guards/site-admin.guard' @Controller('/news') export class NewsController { - constructor(private readonly newsService: NewsService) {} + constructor(private readonly newsItemService: NewsItemService) {} @Get() async listNews(@Query() query: NewsListDTO): Promise> { - return await this.newsService.listNews(query) + return await this.newsItemService.listNews(query) } @UseGuards(SiteAdminGuard) @Get('/all') async getAllNews(@Query() query: NewsListDTO): Promise { - return await this.newsService.getAllNews(query) + return await this.newsItemService.getAllNews(query) } @Get('/years') async listYears(): Promise { - return await this.newsService.listYears() + return await this.newsItemService.listYears() } @Get('/:id') async getNews(@Param('id', ParseIntPipe) id: number): Promise { - return await this.newsService.getNews(id) + return await this.newsItemService.getNews(id) } @UseGuards(SiteAdminGuard) @HttpCode(204) @Delete('/:id') async deleteNews(@Param('id', ParseIntPipe) id: number): Promise { - await this.newsService.deleteNews(id) + await this.newsItemService.deleteNews(id) } @UseGuards(SiteAdminGuard) @HttpCode(201) @Post() async createNews(@Body() body: NewsItemDTO): Promise> { - return await this.newsService.createNews(body) + return await this.newsItemService.createNews(body) } @UseGuards(SiteAdminGuard) @HttpCode(204) @Put('/:id') async updateNews(@Param('id', ParseIntPipe) id: number, @Body() body: NewsItemDTO): Promise { - await this.newsService.updateNews(id, body) + await this.newsItemService.updateNews(id, body) } } diff --git a/packages/server/apps/api/src/session/csrf-token.controller.ts b/packages/server/apps/api/src/session/csrf-token.controller.ts new file mode 100644 index 000000000..3ef7b26c1 --- /dev/null +++ b/packages/server/apps/api/src/session/csrf-token.controller.ts @@ -0,0 +1,43 @@ +import crypto from 'node:crypto' +import { Controller, Get, Req, Res } from '@nestjs/common' +import { Request, Response } from 'express' +import { COOKIE_SESSION_KEY } from '@shared/config/consts' +import { CookieUtils } from '@shared/utils/cookie.utils' +import { CSRFUtils } from '@shared/utils/csrf.utils' +import { Encryptor } from '@shared/utils/encryptors/encryptor' + +@Controller('/csrf-token') +export class CsrfTokenController { + @Get() + getCsrfToken(@Req() req: Request, @Res() res: Response): void { + const cookie = CookieUtils.getCookie(COOKIE_SESSION_KEY, req.headers.cookie) + if (!cookie) { + res.json({ token: null }) + return + } + try { + const session = Encryptor.decrypt(cookie) + if (!session) { + res.json({ token: null }) + return + } + + if (!session._csrf_token) { + // Generate a _csrf_token if Rails hasn't set one yet. + // This matches Rails' behavior: a 32-byte random value, base64-encoded. + session._csrf_token = crypto.randomBytes(32).toString('base64') + const encryptedSession = Encryptor.encrypt(session) + res.cookie(COOKIE_SESSION_KEY, encryptedSession, { + httpOnly: true, + secure: true, + sameSite: 'lax', + path: '/', + }) + } + + res.json({ token: CSRFUtils.generateToken(session._csrf_token) }) + } catch { + res.json({ token: null }) + } + } +} diff --git a/packages/server/apps/api/src/session/session.api.module.ts b/packages/server/apps/api/src/session/session.api.module.ts index 5bd10d77f..fa9a8d920 100644 --- a/packages/server/apps/api/src/session/session.api.module.ts +++ b/packages/server/apps/api/src/session/session.api.module.ts @@ -1,7 +1,8 @@ import { Module } from '@nestjs/common' +import { CsrfTokenController } from './csrf-token.controller' import { SessionController } from './session.controller' @Module({ - controllers: [SessionController], + controllers: [SessionController, CsrfTokenController], }) export class SessionApiModule {} diff --git a/packages/server/apps/api/src/space-memberships/space-memberships.controller.ts b/packages/server/apps/api/src/space-memberships/space-memberships.controller.ts index 504f987b1..2dc06b28c 100644 --- a/packages/server/apps/api/src/space-memberships/space-memberships.controller.ts +++ b/packages/server/apps/api/src/space-memberships/space-memberships.controller.ts @@ -1,6 +1,6 @@ import { Body, Controller, Get, HttpCode, Param, ParseIntPipe, Patch, Post, UseGuards } from '@nestjs/common' import { ApiOperation } from '@nestjs/swagger' -import { SpaceMembershipListApiFacade } from 'apps/api/src/facade/space-membership/space-membership-list-api.facade' +import { SpaceMembershipsListApiFacade } from 'apps/api/src/facade/space-membership/space-memberships-list-api.facade' import { SpaceLeadRecoverDTO } from '@shared/domain/space-membership/dto/space-lead-recover.dto' import { SpaceMemberDTO } from '@shared/domain/space-membership/dto/space-member.dto' import { UpdateSpaceMembershipDTO } from '@shared/domain/space-membership/dto/update-space-membership.dto' @@ -13,12 +13,12 @@ import { UserContextGuard } from '../user-context/guard/user-context.guard' export class SpaceMembershipsController { constructor( private readonly spaceMembershipUpdateApiFacade: SpaceMembershipUpdateApiFacade, - private readonly spaceMembershipListApiFacade: SpaceMembershipListApiFacade, + private readonly spaceMembershipsListApiFacade: SpaceMembershipsListApiFacade, ) {} @Get('/') async listMembers(@Param('spaceId', ParseIntPipe) spaceId: number): Promise { - return this.spaceMembershipListApiFacade.listSpaceMembers(spaceId) + return this.spaceMembershipsListApiFacade.listSpaceMembers(spaceId) } @ApiOperation({ summary: 'Recover space lead for orphaned spaces' }) diff --git a/packages/server/apps/api/src/validation/pipes/uid.pipe.ts b/packages/server/apps/api/src/validation/pipes/uid.pipe.ts index 31d840db2..4d3e06956 100644 --- a/packages/server/apps/api/src/validation/pipes/uid.pipe.ts +++ b/packages/server/apps/api/src/validation/pipes/uid.pipe.ts @@ -16,7 +16,7 @@ type UidValidationPipeOptions = { * is thrown and the request is rejected. * * @example usage can be found in - * DbClusterController#updateDbCluster + * DbClustersController#updateDbCluster * * @example with entity type * @Param('uid', new UidValidationPipe({ entityType: 'job' })) uid: Uid<'job'> diff --git a/packages/server/apps/api/src/workflows/workflow.api.module.ts b/packages/server/apps/api/src/workflows/workflow.api.module.ts index ae75269a5..2e8dde9d7 100644 --- a/packages/server/apps/api/src/workflows/workflow.api.module.ts +++ b/packages/server/apps/api/src/workflows/workflow.api.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common' import { LicenseApiFacadeModule } from '../facade/license/license-api-facade.module' -import { WorkflowController } from './workflow.controller' +import { WorkflowsController } from './workflows.controller' @Module({ imports: [LicenseApiFacadeModule], - controllers: [WorkflowController], + controllers: [WorkflowsController], }) export class WorkflowApiModule {} diff --git a/packages/server/apps/api/src/workflows/workflow.controller.ts b/packages/server/apps/api/src/workflows/workflows.controller.ts similarity index 95% rename from packages/server/apps/api/src/workflows/workflow.controller.ts rename to packages/server/apps/api/src/workflows/workflows.controller.ts index 08ca31bfa..9b487921f 100644 --- a/packages/server/apps/api/src/workflows/workflow.controller.ts +++ b/packages/server/apps/api/src/workflows/workflows.controller.ts @@ -6,7 +6,7 @@ import { WorkflowUidParamDto } from './model/workflow-uid-param.dto' @UseGuards(UserContextGuard) @Controller('/workflows') -export class WorkflowController { +export class WorkflowsController { constructor(private readonly licensesForWorkflowFacade: LicensesForWorkflowFacade) {} @Get('/:workflowUid/licenses-to-accept') diff --git a/packages/server/apps/api/test/integration/files/file-create.spec.ts b/packages/server/apps/api/test/integration/files/file-create.spec.ts new file mode 100644 index 000000000..b296dfd76 --- /dev/null +++ b/packages/server/apps/api/test/integration/files/file-create.spec.ts @@ -0,0 +1,460 @@ +import { SqlEntityManager } from '@mikro-orm/mysql' +import { expect } from 'chai' +import supertest from 'supertest' +import { database } from '@shared/database' +import { Space } from '@shared/domain/space/space.entity' +import { SPACE_TYPE } from '@shared/domain/space/space.enum' +import { SPACE_MEMBERSHIP_ROLE, SPACE_MEMBERSHIP_SIDE } from '@shared/domain/space-membership/space-membership.enum' +import { User } from '@shared/domain/user/user.entity' +import { UserFile } from '@shared/domain/user-file/user-file.entity' +import { UserFileRepository } from '@shared/domain/user-file/user-file.repository' +import { PARENT_TYPE } from '@shared/domain/user-file/user-file.types' +import { create, db } from '@shared/test' +import { mocksReset } from '@shared/test/mocks' +import { testedApp } from '../..' +import { getDefaultHeaderData } from '../../utils/expect-helper' + +describe('POST /files', () => { + let em: SqlEntityManager + let user: User + let fileRepo: UserFileRepository + let space: Space + + beforeEach(async () => { + await db.dropData(database.connection()) + // create DB mocks + em = database.orm().em.fork() + em.clear() + fileRepo = em.getRepository(UserFile) + user = create.userHelper.create(em) + space = create.spacesHelper.create(em, { + type: SPACE_TYPE.GROUPS, + hostProject: 'project-host', + guestProject: 'project-guest', + }) + create.spacesHelper.addMember( + em, + { space, user }, + { role: SPACE_MEMBERSHIP_ROLE.CONTRIBUTOR, side: SPACE_MEMBERSHIP_SIDE.HOST }, + ) + create.sessionHelper.create(em, { user }) + await em.flush() + // handle the stubs + mocksReset() + }) + + it('should throw error if name is empty', async () => { + await supertest(testedApp.getHttpServer()).post(`/files`).set(getDefaultHeaderData(user)).send({}).expect(400) + + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: '', + }) + .expect(400) + }) + + it('should create file with default description and user as parent', async () => { + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.name).to.equal('test_file.txt') + expect(file.description).to.equal('') + expect(file.parentType).to.equal(PARENT_TYPE.USER) + expect(file.parentId).to.equal(user.id) + }) + + context('should create file with correct scope or private scope by default', () => { + it('should create file in correct scope', async () => { + const result1 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: 'private', + }) + .expect(201) + + const file1 = await fileRepo.findOne({ uid: result1.body.uid }) + expect(file1.scope).to.equal('private') + expect(file1.project).to.equal(user.privateFilesProject) + + const result2 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: `space-${space.id}`, + }) + .expect(201) + + const file2 = await fileRepo.findOne({ uid: result2.body.uid }) + expect(file2.scope).to.equal(`space-${space.id}`) + expect(file2.project).to.equal(space.hostProject) + }) + + it('should create file in private scope by default', async () => { + const result1 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: null, + }) + .expect(201) + + const file1 = await fileRepo.findOne({ uid: result1.body.uid }) + expect(file1.scope).to.equal('private') + + const result2 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: '', + }) + .expect(201) + + const file2 = await fileRepo.findOne({ uid: result2.body.uid }) + expect(file2.scope).to.equal('private') + + const result3 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: undefined, + }) + .expect(201) + + const file3 = await fileRepo.findOne({ uid: result3.body.uid }) + expect(file3.scope).to.equal('private') + }) + + it('should throw error if scope is invalid', async () => { + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: 'invalid_scope', + }) + .expect(400) + }) + + it('should throw error if creating public file by non site admin', async () => { + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + scope: 'public', + }) + .expect(403) + }) + + it('should create public file if user is site admin', async () => { + const siteAdmin = create.userHelper.createSiteAdmin(em) + create.sessionHelper.create(em, { user: siteAdmin }) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(siteAdmin)) + .send({ + name: 'test_file.txt', + scope: 'public', + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.scope).to.equal('public') + expect(file.project).to.equal(siteAdmin.publicFilesProject) + }) + + it('should throw error if user does not have write access to the space', async () => { + const anotherUser = create.userHelper.create(em) + create.sessionHelper.create(em, { user: anotherUser }) + create.spacesHelper.addMember( + em, + { space, user: anotherUser }, + { role: SPACE_MEMBERSHIP_ROLE.VIEWER, side: SPACE_MEMBERSHIP_SIDE.HOST }, + ) + await em.flush() + + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(anotherUser)) + .send({ + name: 'test_file.txt', + scope: `space-${space.id}`, + }) + .expect(422) + }) + }) + + context('should create file with correct parent folder', () => { + it('should create file in root if folderId is not provided', async () => { + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentFolderId).to.be.null() + expect(file.scopedParentFolderId).to.be.null() + }) + + it('should create file in root if folderId is null or empty', async () => { + const result1 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + folderId: null, + }) + .expect(201) + + const file1 = await fileRepo.findOne({ uid: result1.body.uid }) + expect(file1.parentFolderId).to.be.null() + expect(file1.scopedParentFolderId).to.be.null() + + const result2 = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + folderId: '', + }) + .expect(201) + + const file2 = await fileRepo.findOne({ uid: result2.body.uid }) + expect(file2.parentFolderId).to.be.null() + expect(file2.scopedParentFolderId).to.be.null() + }) + + it('should create file in the folder if folderId is provided', async () => { + const folder = create.filesHelper.createFolder(em, { + user, + parentFolder: null, + }) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + folderId: folder.id, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentFolderId).to.equal(folder.id) + expect(file.scopedParentFolderId).to.be.null() + }) + + it('should create file in scope folder if folderId is provided and scope is space', async () => { + const newSpace = create.spacesHelper.create(em, { + type: SPACE_TYPE.GROUPS, + hostProject: 'project-host2', + guestProject: 'project-guest2', + }) + create.spacesHelper.addMember( + em, + { space: newSpace, user }, + { role: SPACE_MEMBERSHIP_ROLE.CONTRIBUTOR, side: SPACE_MEMBERSHIP_SIDE.GUEST }, + ) + await em.flush() + const folder = create.filesHelper.createFolder( + em, + { + user, + parentFolder: null, + }, + { + scope: newSpace.scope, + }, + ) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + folderId: folder.id, + scope: newSpace.scope, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentFolderId).to.be.null() + expect(file.scopedParentFolderId).to.equal(folder.id) + expect(file.scope).to.equal(newSpace.scope) + expect(file.project).to.equal(newSpace.guestProject) + }) + }) + + it('should create file with correct parent job', async () => { + const app = create.appHelper.createHTTPS(em, { user }) + const job = create.jobHelper.create(em, { user, app }) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentType: PARENT_TYPE.JOB, + parentId: job.dxid, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentType).to.equal(PARENT_TYPE.JOB) + expect(file.parentId).to.equal(job.id) + }) + + it('should inherit the scope of the folder if the file is being created inside a folder', async () => { + const folder = create.filesHelper.createFolder( + em, + { + user, + parentFolder: null, + }, + { + scope: 'private', + }, + ) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + folderId: folder.id, + scope: space.scope, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.scope).to.equal(folder.scope) + }) + + it('should fall back to current user if parent job does not exist', async () => { + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentType: PARENT_TYPE.JOB, + parentId: 'job-12345', + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentType).to.equal(PARENT_TYPE.USER) + expect(file.parentId).to.equal(user.id) + }) + + it('should throw error if parentType or parentId is invalid', async () => { + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentType: 'invalid_parent_type', + parentId: 'job-12345', + }) + .expect(400) + + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentType: PARENT_TYPE.JOB, + parentId: 'invalid_parent_id', + }) + .expect(400) + + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentType: PARENT_TYPE.JOB, + }) + .expect(400) + + await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parentId: 'job-12345', + }) + .expect(400) + }) + + it('should create file with content in description', async () => { + const description = 'This is a test file' + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + description, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.description).to.equal(description) + }) + + it('should return 200 for JupyterLab client', async () => { + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .set('user-agent', 'python-requests/2.25.1') + .send({ + name: 'test_file.txt', + }) + .expect(200) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.name).to.equal('test_file.txt') + }) + + it('should parse snake case parameters', async () => { + const app = create.appHelper.createHTTPS(em, { user }) + const job = create.jobHelper.create(em, { user, app }) + await em.flush() + + const result = await supertest(testedApp.getHttpServer()) + .post(`/files`) + .set(getDefaultHeaderData(user)) + .send({ + name: 'test_file.txt', + parent_type: PARENT_TYPE.JOB, + parent_id: job.dxid, + }) + .expect(201) + + const file = await fileRepo.findOne({ uid: result.body.uid }) + expect(file.parentType).to.equal(PARENT_TYPE.JOB) + expect(file.parentId).to.equal(job.id) + }) +}) diff --git a/packages/server/apps/api/test/integration/news/news.spec.ts b/packages/server/apps/api/test/integration/news/news.spec.ts index abf9dd4da..b93063dc1 100644 --- a/packages/server/apps/api/test/integration/news/news.spec.ts +++ b/packages/server/apps/api/test/integration/news/news.spec.ts @@ -181,8 +181,8 @@ describe('/news', () => { .expect(201) expect(body).to.deep.eq({ id: body.id }) - const newsRepo = em.getRepository(NewsItem) - const newsItemFromDb = await newsRepo.findOne({ id: body.id }) + const newsItemRepo = em.getRepository(NewsItem) + const newsItemFromDb = await newsItemRepo.findOne({ id: body.id }) expect(newsItemFromDb.title).to.be.eq(data.title) expect(newsItemFromDb.content).to.be.eq(data.content) expect(newsItemFromDb.link).to.be.eq(data.link) diff --git a/packages/server/apps/api/test/unit/facade/cli-list-assets.facade.spec.ts b/packages/server/apps/api/test/unit/facade/cli-assets-list.facade.spec.ts similarity index 92% rename from packages/server/apps/api/test/unit/facade/cli-list-assets.facade.spec.ts rename to packages/server/apps/api/test/unit/facade/cli-assets-list.facade.spec.ts index 0e4c439f5..b7b369005 100644 --- a/packages/server/apps/api/test/unit/facade/cli-list-assets.facade.spec.ts +++ b/packages/server/apps/api/test/unit/facade/cli-assets-list.facade.spec.ts @@ -5,7 +5,7 @@ import { UserContext } from '@shared/domain/user-context/model/user-context' import { NodeService } from '@shared/domain/user-file/node.service' import { STATIC_SCOPE } from '@shared/enums' import { NotFoundError } from '@shared/errors' -import { CliListAssetsFacade } from '../../../src/facade/cli/cli-list-assets.facade' +import { CliAssetsListFacade } from '../../../src/facade/cli/cli-assets-list.facade' const USER_ID = 42 const DXUSER = 'user-test' @@ -19,7 +19,7 @@ function createUserContext(overrides?: Partial): UserContext { } as unknown as UserContext } -describe('CliListAssetsFacade', () => { +describe('CliAssetsListFacade', () => { let listAccessibleAssetsStub: SinonStub let loadEntityStub: SinonStub let spaceGetAccessibleByIdStub: SinonStub @@ -30,7 +30,7 @@ describe('CliListAssetsFacade', () => { spaceGetAccessibleByIdStub = stub().resolves(null) }) - function getInstance(): CliListAssetsFacade { + function getInstance(): CliAssetsListFacade { const nodeService = { listAccessibleAssets: listAccessibleAssetsStub, } as unknown as NodeService @@ -38,7 +38,7 @@ describe('CliListAssetsFacade', () => { const spaceService = { getAccessibleById: spaceGetAccessibleByIdStub, } as unknown as SpaceService - return new CliListAssetsFacade(nodeService, user, spaceService) + return new CliAssetsListFacade(nodeService, user, spaceService) } it('queries with scope: PUBLIC when scope is STATIC_SCOPE.PUBLIC', async () => { diff --git a/packages/server/apps/api/test/unit/facade/cli-dto-validation.spec.ts b/packages/server/apps/api/test/unit/facade/cli-dto-validation.spec.ts index eb9022d1c..06438ecb1 100644 --- a/packages/server/apps/api/test/unit/facade/cli-dto-validation.spec.ts +++ b/packages/server/apps/api/test/unit/facade/cli-dto-validation.spec.ts @@ -1,13 +1,13 @@ import { expect } from 'chai' import { plainToInstance } from 'class-transformer' import { validate } from 'class-validator' -import { CliListSpacesQueryDTO } from '@shared/domain/cli/dto/cli-list-spaces-query.dto' +import { CliSpacesListQueryDTO } from '@shared/domain/cli/dto/cli-spaces-list-query.dto' import { CliScopeQueryDTO } from '@shared/domain/cli/dto/cli-scope-query.dto' import { SPACE_STATE, SPACE_TYPE } from '@shared/domain/space/space.enum' -describe('CliListSpacesQueryDTO', () => { - const toInstance = (plain: Record): CliListSpacesQueryDTO => - plainToInstance(CliListSpacesQueryDTO, plain, { enableImplicitConversion: false }) +describe('CliSpacesListQueryDTO', () => { + const toInstance = (plain: Record): CliSpacesListQueryDTO => + plainToInstance(CliSpacesListQueryDTO, plain, { enableImplicitConversion: false }) describe('state', () => { it('transforms "active" to SPACE_STATE.ACTIVE', async () => { diff --git a/packages/server/apps/api/test/unit/facade/cli-list-jobs.facade.spec.ts b/packages/server/apps/api/test/unit/facade/cli-jobs-list.facade.spec.ts similarity index 92% rename from packages/server/apps/api/test/unit/facade/cli-list-jobs.facade.spec.ts rename to packages/server/apps/api/test/unit/facade/cli-jobs-list.facade.spec.ts index 23aef4d58..5fa0f313d 100644 --- a/packages/server/apps/api/test/unit/facade/cli-list-jobs.facade.spec.ts +++ b/packages/server/apps/api/test/unit/facade/cli-jobs-list.facade.spec.ts @@ -5,7 +5,7 @@ import { SpaceService } from '@shared/domain/space/service/space.service' import { UserContext } from '@shared/domain/user-context/model/user-context' import { STATIC_SCOPE } from '@shared/enums' import { NotFoundError } from '@shared/errors' -import { CliListJobsFacade } from '../../../src/facade/cli/cli-list-jobs.facade' +import { CliJobsListFacade } from '../../../src/facade/cli/cli-jobs-list.facade' const USER_ID = 42 const DXUSER = 'user-test' @@ -19,7 +19,7 @@ function createUserContext(overrides?: Partial): UserContext { } as unknown as UserContext } -describe('CliListJobsFacade', () => { +describe('CliJobsListFacade', () => { let jobListAccessibleStub: SinonStub let spaceGetAccessibleByIdStub: SinonStub let loadEntityStub: SinonStub @@ -30,7 +30,7 @@ describe('CliListJobsFacade', () => { loadEntityStub = stub().resolves({ id: USER_ID }) }) - function getInstance(): CliListJobsFacade { + function getInstance(): CliJobsListFacade { const user = createUserContext({ loadEntity: loadEntityStub }) const jobService = { listAccessible: jobListAccessibleStub, @@ -38,7 +38,7 @@ describe('CliListJobsFacade', () => { const spaceService = { getAccessibleById: spaceGetAccessibleByIdStub, } as unknown as SpaceService - return new CliListJobsFacade(user, jobService, spaceService) + return new CliJobsListFacade(user, jobService, spaceService) } it('queries with scope: space-123 when scope is a space scope and space exists', async () => { diff --git a/packages/server/apps/api/test/unit/facade/cli-list-spaces.facade.spec.ts b/packages/server/apps/api/test/unit/facade/cli-spaces-list.facade.spec.ts similarity index 92% rename from packages/server/apps/api/test/unit/facade/cli-list-spaces.facade.spec.ts rename to packages/server/apps/api/test/unit/facade/cli-spaces-list.facade.spec.ts index c31685d1f..77c95acee 100644 --- a/packages/server/apps/api/test/unit/facade/cli-list-spaces.facade.spec.ts +++ b/packages/server/apps/api/test/unit/facade/cli-spaces-list.facade.spec.ts @@ -4,7 +4,7 @@ import { SpaceService } from '@shared/domain/space/service/space.service' import { SPACE_STATE, SPACE_TYPE } from '@shared/domain/space/space.enum' import { SPACE_MEMBERSHIP_ROLE, SPACE_MEMBERSHIP_SIDE } from '@shared/domain/space-membership/space-membership.enum' import { UserContext } from '@shared/domain/user-context/model/user-context' -import { CliListSpacesFacade } from '../../../src/facade/cli/cli-list-spaces.facade' +import { CliSpacesListFacade } from '../../../src/facade/cli/cli-spaces-list.facade' const USER_ID = 42 const DXUSER = 'user-test' @@ -18,19 +18,19 @@ function createUserContext(overrides?: Partial): UserContext { } as unknown as UserContext } -describe('CliListSpacesFacade', () => { +describe('CliSpacesListFacade', () => { let listAccessibleStub: SinonStub beforeEach(() => { listAccessibleStub = stub().resolves([]) }) - function getInstance(): CliListSpacesFacade { + function getInstance(): CliSpacesListFacade { const user = createUserContext() const spaceService = { listAccessible: listAccessibleStub, } as unknown as SpaceService - return new CliListSpacesFacade(user, spaceService) + return new CliSpacesListFacade(user, spaceService) } it('calls spaceService.listAccessible with SPACE_STATE.ACTIVE when state is not provided in query', async () => { @@ -85,7 +85,7 @@ describe('CliListSpacesFacade', () => { expect(where).to.not.have.property('type') }) - it('maps results using CliListSpaceDTO.fromEntity', async () => { + it('maps results using CliSpaceListDTO.fromEntity', async () => { const mockMembership = { user: { id: USER_ID }, active: true, diff --git a/packages/server/apps/worker/src/queues/processor/main-queue.processor.ts b/packages/server/apps/worker/src/queues/processor/main-queue.processor.ts index e4333a9d2..2ace9f181 100644 --- a/packages/server/apps/worker/src/queues/processor/main-queue.processor.ts +++ b/packages/server/apps/worker/src/queues/processor/main-queue.processor.ts @@ -15,6 +15,7 @@ import { FOLLOW_UP_ACTION } from '@shared/domain/user-file/user-file.input' import { SpaceMemberNotificationFacade } from '@shared/facade/space-member-notification/space-member-notification.facade' import { SyncFilesStateFacade } from '@shared/facade/sync-file-state/sync-files-state.facade' import { UserProvisionFacade } from '@shared/facade/user/user-provision.facade' +import { ServiceLogger } from '@shared/logger/decorator/service-logger' import { createRunFollowUpActionJobTask } from '@shared/queue' import { NotifyNewDiscussionJob, @@ -27,8 +28,10 @@ import { ProcessWithContext } from '../decorator/process-with-context' @Processor(config.workerJobs.queues.default.name) export class MainQueueProcessor { + @ServiceLogger() + private readonly logger: Logger + constructor( - private readonly logger: Logger, private readonly user: UserContext, private readonly nodeService: NodeService, private readonly challengeService: ChallengeService, @@ -71,7 +74,12 @@ export class MainQueueProcessor { this.logger.log(`synchronizeFile result: ${result}`) if (!result) { - throw new Error(`File ${input.fileUid} not ready for synchronizing, trigger repeat of the job by throwing error`) + this.logger.log( + `File ${input.fileUid} is not ready yet. Deferring via Bull retry/backoff (${job.attemptsMade + 1}/${job.opts.attempts ?? 'n/a'}).`, + ) + + await job.moveToFailed(new Error(`File ${input.fileUid} is not ready on platform to be synchronized`), true) + return } else { const followUpAction = await this.followUpDecider.decideNextAction(input.fileUid) if (followUpAction) { diff --git a/packages/server/libs/shared/src/config/envs/dev.ts b/packages/server/libs/shared/src/config/envs/dev.ts index b386577da..2fcbcc241 100644 --- a/packages/server/libs/shared/src/config/envs/dev.ts +++ b/packages/server/libs/shared/src/config/envs/dev.ts @@ -3,7 +3,6 @@ import { ConfigOverride, parseBooleanFromProcess, parseIntFromProcess } from '.. export const config: ConfigOverride = () => ({ // NOTE(samuel) copied from "staging.ts" configuration, so to avoid breaking changes, left unchanged - appName: 'https-apps-worker-stg', api: { railsHost: process.env.HOST, fdaSubnet: { diff --git a/packages/server/libs/shared/src/config/envs/development.ts b/packages/server/libs/shared/src/config/envs/development.ts index 6b36345a3..1bc4f5d4b 100644 --- a/packages/server/libs/shared/src/config/envs/development.ts +++ b/packages/server/libs/shared/src/config/envs/development.ts @@ -1,7 +1,6 @@ import { ConfigOverride, parseBooleanFromProcess, parseIntFromProcess } from '..' export const config: ConfigOverride = () => ({ - appName: 'https-apps-worker-dev', api: { certPath: process.env.NODE_PATH_CERT ?? '../cert.pem', keyCertPath: process.env.NODE_PATH_KEY_CERT ?? '../key.pem', diff --git a/packages/server/libs/shared/src/config/envs/production.ts b/packages/server/libs/shared/src/config/envs/production.ts index 0f58724b5..005e74dd9 100644 --- a/packages/server/libs/shared/src/config/envs/production.ts +++ b/packages/server/libs/shared/src/config/envs/production.ts @@ -3,7 +3,6 @@ import { ConfigOverride, defaultConfig, parseBooleanFromProcess, parseIntFromPro import { MAX_JOB_DURATION_SECONDS } from '../constants' export const config: ConfigOverride = () => ({ - appName: 'https-apps-worker-prod', api: { railsHost: process.env.HOST, allowErrorTestingRoutes: false, diff --git a/packages/server/libs/shared/src/config/envs/staging.ts b/packages/server/libs/shared/src/config/envs/staging.ts index 12eacb714..090bb40be 100644 --- a/packages/server/libs/shared/src/config/envs/staging.ts +++ b/packages/server/libs/shared/src/config/envs/staging.ts @@ -2,7 +2,6 @@ import { parseIpv4Cidr } from '../../validation/parsers' import { ConfigOverride, defaultConfig, parseBooleanFromProcess, parseIntFromProcess } from '..' export const config: ConfigOverride = () => ({ - appName: 'https-apps-worker-stg', api: { railsHost: process.env.HOST, fdaSubnet: { diff --git a/packages/server/libs/shared/src/config/envs/test.ts b/packages/server/libs/shared/src/config/envs/test.ts index 9e5f03e87..cb5fe82a8 100644 --- a/packages/server/libs/shared/src/config/envs/test.ts +++ b/packages/server/libs/shared/src/config/envs/test.ts @@ -2,7 +2,6 @@ import { parseIpv4Cidr } from '@shared/validation/parsers' import { ConfigOverride, parseBooleanFromProcess, parseIntFromProcess } from '..' export const config: ConfigOverride = () => ({ - appName: 'https-apps-worker-test', api: { railsHost: process.env.HOST, fdaSubnet: { diff --git a/packages/server/libs/shared/src/config/index.ts b/packages/server/libs/shared/src/config/index.ts index 610328cb8..3b38f0fc9 100644 --- a/packages/server/libs/shared/src/config/index.ts +++ b/packages/server/libs/shared/src/config/index.ts @@ -49,7 +49,6 @@ const getEnv = (): ENVS => { const env: ENVS = getEnv() const defaultConfig = { - appName: 'https-apps-worker', env, api: { port: parseIntFromProcess(process.env.NODE_PORT) ?? 3001, @@ -57,7 +56,6 @@ const defaultConfig = { enableSsl: parseBooleanFromProcess(process.env.NODE_ENABLE_SSL, true), certPath: process.env.NODE_PATH_CERT ?? path.join(__dirname, '../../../../cert.pem'), keyCertPath: process.env.NODE_PATH_KEY_CERT ?? path.join(__dirname, '../../../../key.pem'), - url: process.env.NODE_URL ?? 'https://nodejs-api', railsHost: process.env.HOST ?? 'https://localhost:3000', // TODO - refactor to boolean allowErrorTestingRoutes: parseBooleanFromProcess(process.env.NODE_ALLOW_ERROR_TESTING_ROUTES, true), diff --git a/packages/server/libs/shared/src/domain/app-series/service/app-series.service.ts b/packages/server/libs/shared/src/domain/app-series/service/app-series.service.ts index b6bf31cb9..03f3a9285 100644 --- a/packages/server/libs/shared/src/domain/app-series/service/app-series.service.ts +++ b/packages/server/libs/shared/src/domain/app-series/service/app-series.service.ts @@ -1,19 +1,13 @@ -import { Injectable, Logger } from '@nestjs/common' -import { constructDxid } from '@shared/domain/app/app.helper' +import { Injectable } from '@nestjs/common' import { AppSeries } from '@shared/domain/app-series/app-series.entity' import { AppSeriesRepository } from '@shared/domain/app-series/app-series.repository' import { AppSeriesCountService } from '@shared/domain/app-series/app-series-count.service' import { ScopeFilterContext } from '@shared/domain/counters/counters.types' -import { User } from '@shared/domain/user/user.entity' import { UserContext } from '@shared/domain/user-context/model/user-context' -import { ServiceLogger } from '@shared/logger/decorator/service-logger' import { EntityScope } from '@shared/types/common' @Injectable() export class AppSeriesService { - @ServiceLogger() - private readonly logger: Logger - constructor( private readonly user: UserContext, private readonly appSeriesRepository: AppSeriesRepository, @@ -34,15 +28,4 @@ export class AppSeriesService { user: this.user.id, }) } - - async createAppSeries(appName: string, user: User, scope?: EntityScope): Promise { - const appSeriesDxid = constructDxid(this.user.dxuser, appName, scope) - const appSeries = new AppSeries(user) - appSeries.name = appName - appSeries.dxid = appSeriesDxid - appSeries.scope = scope - this.logger.log(`Creating app series ${appSeries.dxid}`) - await this.appSeriesRepository.persistAndFlush(appSeries) - return appSeries - } } diff --git a/packages/server/libs/shared/src/domain/cli/dto/cli-list-assets.dto.ts b/packages/server/libs/shared/src/domain/cli/dto/cli-assets-list.dto.ts similarity index 91% rename from packages/server/libs/shared/src/domain/cli/dto/cli-list-assets.dto.ts rename to packages/server/libs/shared/src/domain/cli/dto/cli-assets-list.dto.ts index 18bc7c2ee..0c2e32db6 100644 --- a/packages/server/libs/shared/src/domain/cli/dto/cli-list-assets.dto.ts +++ b/packages/server/libs/shared/src/domain/cli/dto/cli-assets-list.dto.ts @@ -1,7 +1,7 @@ import { Uid } from '@shared/domain/entity/domain/uid' import { Asset } from '@shared/domain/user-file/asset.entity' -export class CliListAssetDTO { +export class CliAssetListDTO { id: number uid: Uid<'file'> name: string @@ -15,7 +15,7 @@ export class CliListAssetDTO { archiveContent: string[] properties: Record - static fromEntity(asset: Asset): CliListAssetDTO { + static fromEntity(asset: Asset): CliAssetListDTO { const props: Record = {} asset.properties.getItems().forEach(p => { props[p.propertyName] = p.propertyValue diff --git a/packages/server/libs/shared/src/domain/cli/dto/cli-list-jobs.dto.ts b/packages/server/libs/shared/src/domain/cli/dto/cli-jobs-list.dto.ts similarity index 91% rename from packages/server/libs/shared/src/domain/cli/dto/cli-list-jobs.dto.ts rename to packages/server/libs/shared/src/domain/cli/dto/cli-jobs-list.dto.ts index a81f6f02a..e60cdc9c3 100644 --- a/packages/server/libs/shared/src/domain/cli/dto/cli-list-jobs.dto.ts +++ b/packages/server/libs/shared/src/domain/cli/dto/cli-jobs-list.dto.ts @@ -2,7 +2,7 @@ import { DxId } from '@shared/domain/entity/domain/dxid' import { Uid } from '@shared/domain/entity/domain/uid' import { Job } from '@shared/domain/job/job.entity' -export class CliListJobDTO { +export class CliJobListDTO { id: number uid: Uid<'job'> dxid: DxId<'job'> @@ -30,7 +30,7 @@ export class CliListJobDTO { runInputData: RunDataItem[] runOutputData: RunDataItem[] - static fromEntity(job: Job): CliListJobDTO { + static fromEntity(job: Job): CliJobListDTO { let appTitle: string | null = null let appUid: Uid<'app'> | null = null let appRevision: number | null = null @@ -56,11 +56,11 @@ export class CliListJobDTO { .map(t => t.tag?.name) .filter(Boolean) as string[] - const runtime = CliListJobDTO.getRuntime(job) - const energy = CliListJobDTO.getEnergy(job) + const runtime = CliJobListDTO.getRuntime(job) + const energy = CliJobListDTO.getEnergy(job) - const runInputData = CliListJobDTO.buildRunData(job.runData?.run_inputs) - const runOutputData = CliListJobDTO.buildRunData(job.runData?.run_outputs) + const runInputData = CliJobListDTO.buildRunData(job.runData?.run_inputs) + const runOutputData = CliJobListDTO.buildRunData(job.runData?.run_outputs) return { id: job.id, uid: job.uid, diff --git a/packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces-query.dto.ts b/packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list-query.dto.ts similarity index 94% rename from packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces-query.dto.ts rename to packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list-query.dto.ts index ba4612208..6ca2b7bca 100644 --- a/packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces-query.dto.ts +++ b/packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list-query.dto.ts @@ -4,7 +4,7 @@ import { SPACE_STATE, SPACE_TYPE } from '@shared/domain/space/space.enum' import { TransformAndValidateBoolean } from '@shared/utils/transformers/is-valid-boolean' import { TransformEnumKey } from '@shared/utils/transformers/transform-enum-key.decorator' -export class CliListSpacesQueryDTO { +export class CliSpacesListQueryDTO { @IsOptional() @TransformEnumKey(SPACE_STATE) @IsEnum(SPACE_STATE) diff --git a/packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces.dto.ts b/packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list.dto.ts similarity index 95% rename from packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces.dto.ts rename to packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list.dto.ts index 8cdc4f967..1beaa0c97 100644 --- a/packages/server/libs/shared/src/domain/cli/dto/cli-list-spaces.dto.ts +++ b/packages/server/libs/shared/src/domain/cli/dto/cli-spaces-list.dto.ts @@ -3,7 +3,7 @@ import { SPACE_STATE, SPACE_TYPE } from '@shared/domain/space/space.enum' import { SpaceMembership } from '@shared/domain/space-membership/space-membership.entity' import { SPACE_MEMBERSHIP_ROLE, SPACE_MEMBERSHIP_SIDE } from '@shared/domain/space-membership/space-membership.enum' -export class CliListSpaceDTO { +export class CliSpaceListDTO { id: number title: string type: string @@ -14,7 +14,7 @@ export class CliListSpaceDTO { // membership may be undefined for site admins: SpaceRepository.getAccessibleWhere() // grants visibility to all spaces including ones they have no membership in. - static fromEntity(space: Space, membership?: SpaceMembership): CliListSpaceDTO { + static fromEntity(space: Space, membership?: SpaceMembership): CliSpaceListDTO { return { id: space.id, title: space.name, diff --git a/packages/server/libs/shared/src/domain/entity/dto/entity-uid-response.dto.ts b/packages/server/libs/shared/src/domain/entity/dto/entity-uid-response.dto.ts new file mode 100644 index 000000000..07fcfc897 --- /dev/null +++ b/packages/server/libs/shared/src/domain/entity/dto/entity-uid-response.dto.ts @@ -0,0 +1,6 @@ +import { Uid } from '../domain/uid' + +export class EntityUidResponseDTO { + uid: Uid + id?: Uid // for backward compatibility to old clients +} diff --git a/packages/server/libs/shared/src/domain/event/event.entity.ts b/packages/server/libs/shared/src/domain/event/event.entity.ts index e57e96885..cca7ab308 100644 --- a/packages/server/libs/shared/src/domain/event/event.entity.ts +++ b/packages/server/libs/shared/src/domain/event/event.entity.ts @@ -25,6 +25,7 @@ export enum EVENT_TYPES { JOB_RUN = 'Event::JobRun', SUBMISSION_CREATED = 'Event::SubmissionCreated', SIGNED_UP_FOR_CHALLENGE = 'Event::SignedUpForChallenge', + USER_DEACTIVATED = 'Event::UserDeactivated', } @Entity({ tableName: 'events' }) diff --git a/packages/server/libs/shared/src/domain/event/event.helper.ts b/packages/server/libs/shared/src/domain/event/event.helper.ts index caac3d8ea..8a2013d45 100644 --- a/packages/server/libs/shared/src/domain/event/event.helper.ts +++ b/packages/server/libs/shared/src/domain/event/event.helper.ts @@ -166,4 +166,18 @@ const createJobClosed = async (user: User, job: Job, platformJobData: JobDescrib return event } -export { createAppCreated, createAppPublished, createDbClusterPasswordRotated, createJobClosed } +const createUserDeactivated = async (actor: User, targetUser: User): Promise => { + const event = new Event() + const organization = await actor.organization.load() + wrap(event).assign({ + type: EVENT_TYPES.USER_DEACTIVATED, + orgHandle: organization.handle, + dxuser: actor.dxuser, + param1: targetUser.dxuser, + param2: targetUser.id.toString(), + data: JSON.stringify({}), + }) + return event +} + +export { createAppCreated, createAppPublished, createDbClusterPasswordRotated, createJobClosed, createUserDeactivated } diff --git a/packages/server/libs/shared/src/domain/job/job.service.ts b/packages/server/libs/shared/src/domain/job/job.service.ts index e7af328ca..2e67fff7e 100644 --- a/packages/server/libs/shared/src/domain/job/job.service.ts +++ b/packages/server/libs/shared/src/domain/job/job.service.ts @@ -90,6 +90,10 @@ export class JobService implements SearchableByUid<'job'> { return this.jobRepo.findEditableOne({ uid }) } + getEditableOne(where: FilterQuery): Promise { + return this.jobRepo.findEditableOne(where) + } + async synchronizeJob(jobDxid: DxId<'job'>, bullJob: BullJob): Promise> { return await this.jobSyncService.synchronizeJob(jobDxid, bullJob) } diff --git a/packages/server/libs/shared/src/domain/news-item/news-item.entity.ts b/packages/server/libs/shared/src/domain/news-item/news-item.entity.ts index ad8461940..e51845177 100644 --- a/packages/server/libs/shared/src/domain/news-item/news-item.entity.ts +++ b/packages/server/libs/shared/src/domain/news-item/news-item.entity.ts @@ -1,9 +1,9 @@ import { Entity, ManyToOne, Property, Ref, Reference } from '@mikro-orm/core' import { User } from '@shared/domain/user/user.entity' import { BaseEntity } from '../../database/base.entity' -import { NewsRepository } from './news-item.repository' +import { NewsItemRepository } from './news-item.repository' -@Entity({ tableName: 'news_items', repository: () => NewsRepository }) +@Entity({ tableName: 'news_items', repository: () => NewsItemRepository }) class NewsItem extends BaseEntity { @Property() title?: string diff --git a/packages/server/libs/shared/src/domain/news-item/news-item.module.ts b/packages/server/libs/shared/src/domain/news-item/news-item.module.ts index 31732fe96..128773d65 100644 --- a/packages/server/libs/shared/src/domain/news-item/news-item.module.ts +++ b/packages/server/libs/shared/src/domain/news-item/news-item.module.ts @@ -1,11 +1,11 @@ import { MikroOrmModule } from '@mikro-orm/nestjs' import { Module } from '@nestjs/common' import { NewsItem } from './news-item.entity' -import { NewsService } from './service/new-item.service' +import { NewsItemService } from './service/news-item.service' @Module({ imports: [MikroOrmModule.forFeature([NewsItem])], - providers: [NewsService], - exports: [NewsService], + providers: [NewsItemService], + exports: [NewsItemService], }) -export class NewsModule {} +export class NewsItemModule {} diff --git a/packages/server/libs/shared/src/domain/news-item/news-item.repository.ts b/packages/server/libs/shared/src/domain/news-item/news-item.repository.ts index 1a6febb61..84d5258b2 100644 --- a/packages/server/libs/shared/src/domain/news-item/news-item.repository.ts +++ b/packages/server/libs/shared/src/domain/news-item/news-item.repository.ts @@ -1,7 +1,7 @@ import { PaginatedRepository } from '@shared/database/repository/paginated.repository' import { NewsItem } from './news-item.entity' -export class NewsRepository extends PaginatedRepository { +export class NewsItemRepository extends PaginatedRepository { async getDistinctYears(): Promise { const allYears: { year: number }[] = await this.em.execute( 'SELECT DISTINCT YEAR(created_at) as year FROM news_items ORDER BY year DESC', diff --git a/packages/server/libs/shared/src/domain/news-item/service/new-item.service.ts b/packages/server/libs/shared/src/domain/news-item/service/news-item.service.ts similarity index 85% rename from packages/server/libs/shared/src/domain/news-item/service/new-item.service.ts rename to packages/server/libs/shared/src/domain/news-item/service/news-item.service.ts index 307b265cf..99d8be73b 100644 --- a/packages/server/libs/shared/src/domain/news-item/service/new-item.service.ts +++ b/packages/server/libs/shared/src/domain/news-item/service/news-item.service.ts @@ -7,16 +7,16 @@ import { ServiceLogger } from '@shared/logger/decorator/service-logger' import { NewsItemDTO } from '../dto/news-item.dto' import { NewsListDTO, PUBLICATION_TYPE } from '../dto/news-list.dto' import { NewsItem } from '../news-item.entity' -import { NewsRepository } from '../news-item.repository' +import { NewsItemRepository } from '../news-item.repository' @Injectable() -export class NewsService { +export class NewsItemService { @ServiceLogger() private readonly logger: Logger constructor( private readonly em: SqlEntityManager, private readonly user: UserContext, - private readonly newsRepo: NewsRepository, + private readonly newsItemRepo: NewsItemRepository, ) {} async listNews(query: NewsListDTO): Promise> { @@ -34,7 +34,7 @@ export class NewsService { typeWhere = { isPublication: query.type !== PUBLICATION_TYPE.ARTICLE } } - return await this.newsRepo.paginate(query, { + return await this.newsItemRepo.paginate(query, { ...whereYear, ...typeWhere, published: true, @@ -46,15 +46,15 @@ export class NewsService { if (query.type === PUBLICATION_TYPE.ARTICLE) whereType = { isPublication: false } if (query.type === PUBLICATION_TYPE.PUBLICATION) whereType = { isPublication: true } - return this.newsRepo.find(whereType, { orderBy: { createdAt: -1 } }) + return this.newsItemRepo.find(whereType, { orderBy: { createdAt: -1 } }) } async listYears(): Promise { - return await this.newsRepo.getDistinctYears() + return await this.newsItemRepo.getDistinctYears() } async getNews(id: number): Promise { - return await this.newsRepo.findOne({ id }) + return await this.newsItemRepo.findOne({ id }) } async deleteNews(id: number): Promise { @@ -79,7 +79,7 @@ export class NewsService { } async updateNews(id: number, body: NewsItemDTO): Promise { - const existing = await this.newsRepo.findOneOrFail({ id }) + const existing = await this.newsItemRepo.findOneOrFail({ id }) const toSave = wrap(existing).assign(body, { mergeObjectProperties: true }) await this.em.persistAndFlush(toSave) } diff --git a/packages/server/libs/shared/src/domain/tagging/tagging.service.ts b/packages/server/libs/shared/src/domain/tagging/tagging.service.ts index ac9d18147..99680ed8e 100644 --- a/packages/server/libs/shared/src/domain/tagging/tagging.service.ts +++ b/packages/server/libs/shared/src/domain/tagging/tagging.service.ts @@ -1,6 +1,5 @@ import { SqlEntityManager } from '@mikro-orm/mysql' import { Injectable, Logger } from '@nestjs/common' -import { Tag } from '@shared/domain/tag/tag.entity' import { TagRepository } from '@shared/domain/tag/tag.repository' import { Tagging } from '@shared/domain/tagging/tagging.entity' import { TaggingRepository } from '@shared/domain/tagging/tagging.repository' @@ -28,28 +27,24 @@ export class TaggingService { this.logger.log( `Adding tag ${name} for entity with id: ${taggableId}, type ${taggableType}, taggerId: ${taggerId}, taggerType: ${taggerType}`, ) - let tag = await this.tagRepo.findOne({ name }) + let activeTag = await this.tagRepo.findOne({ name }) + if (!activeTag) { + activeTag = this.tagRepo.create({ name }) + await this.em.persist(activeTag).flush() + } - return this.em.transactional(async em => { - if (!tag) { - tag = new Tag() - tag.name = name - await em.persistAndFlush(tag) - } - - const existingTagging = await this.taggingRepo.findOne({ tag, taggableType, taggableId }) - if (existingTagging) return + const existingTagging = await this.taggingRepo.findOne({ tag: activeTag, taggableType, taggableId }) + if (existingTagging) return - const tagging = new Tagging() - tagging.tagId = tag.id - tagging.taggableType = taggableType - tagging.taggableId = taggableId - tagging.taggerType = taggerType - tagging.taggerId = taggerId - tagging.context = 'tags' + const tagging = new Tagging() + tagging.tagId = activeTag.id + tagging.taggableType = taggableType + tagging.taggableId = taggableId + tagging.taggerType = taggerType + tagging.taggerId = taggerId + tagging.context = 'tags' - em.persist(tagging) - }) + await this.em.persist(tagging).flush() } /** @@ -73,4 +68,8 @@ export class TaggingService { } }) } + + async getTaggingsForEntity(id: number, type: TAGGABLE_TYPE): Promise { + return this.taggingRepo.findForTaggable(id, type) + } } diff --git a/packages/server/libs/shared/src/domain/user-file/dto/user-file-create.dto.ts b/packages/server/libs/shared/src/domain/user-file/dto/user-file-create.dto.ts new file mode 100644 index 000000000..ddaa8ce8e --- /dev/null +++ b/packages/server/libs/shared/src/domain/user-file/dto/user-file-create.dto.ts @@ -0,0 +1,37 @@ +import { Transform } from 'class-transformer' +import { IsIn, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateIf } from 'class-validator' +import { IsValidDxid } from '@shared/domain/entity/constraint/is-dxid-valid.constraint' +import { IsValidScope } from '@shared/domain/entity/constraint/is-valid-scope.constraint' +import { DxId } from '@shared/domain/entity/domain/dxid' +import { STATIC_SCOPE } from '@shared/enums' +import { EntityScope } from '@shared/types/common' +import { PARENT_TYPE } from '../user-file.types' + +export class UserFileCreateDTO { + @IsString() + @IsNotEmpty() + name: string + + @Transform(({ value }) => (value === null || value === undefined || value === '' ? 'private' : value)) + @IsValidScope() + scope: EntityScope = STATIC_SCOPE.PRIVATE + + @Transform(({ value }) => (value === '' ? null : value)) + @IsOptional() + @IsNumber() + folderId?: number + + @IsOptional() + @IsString() + description?: string + + @ValidateIf(o => o.parentId != null && o.parentId !== '') + @IsNotEmpty() + @IsIn([PARENT_TYPE.JOB]) + parentType: PARENT_TYPE.JOB + + @ValidateIf(o => o.parentType != null && o.parentType !== '') + @IsNotEmpty() + @IsValidDxid({ entityType: 'job' }) + parentId: DxId<'job'> +} diff --git a/packages/server/libs/shared/src/domain/user-file/node.service.ts b/packages/server/libs/shared/src/domain/user-file/node.service.ts index 39394c493..04c683ca2 100644 --- a/packages/server/libs/shared/src/domain/user-file/node.service.ts +++ b/packages/server/libs/shared/src/domain/user-file/node.service.ts @@ -203,6 +203,10 @@ export class NodeService { })) as FileOrAsset | null } + async getEditableFolder(id: number): Promise { + return this.nodeRepository.findEditableOne({ id, stiType: FILE_STI_TYPE.FOLDER }) as Promise + } + /** * Loads the whole tree that is filtered by parameters and returns * it sorted with leaves first diff --git a/packages/server/libs/shared/src/domain/user-file/service/user-file.service.ts b/packages/server/libs/shared/src/domain/user-file/service/user-file.service.ts index 1571ae0f4..b3b7df449 100644 --- a/packages/server/libs/shared/src/domain/user-file/service/user-file.service.ts +++ b/packages/server/libs/shared/src/domain/user-file/service/user-file.service.ts @@ -303,7 +303,7 @@ export class UserFileService { file.uid = `${fileCreate.dxid}-1` this.logger.log(`Creating file ${JSON.stringify(fileCreate)}`) - await this.em.persistAndFlush(file) + await this.fileRepo.persistAndFlush(file) return file } diff --git a/packages/server/libs/shared/src/domain/user/service/user-management.service.ts b/packages/server/libs/shared/src/domain/user/service/user-management.service.ts index c6d0bbea4..224e42a04 100644 --- a/packages/server/libs/shared/src/domain/user/service/user-management.service.ts +++ b/packages/server/libs/shared/src/domain/user/service/user-management.service.ts @@ -1,7 +1,9 @@ import { Inject, Logger } from '@nestjs/common' +import { EntityManager } from '@mikro-orm/mysql' import { DNANEXUS_INVALID_EMAIL, ORG_EVERYONE } from '@shared/config/consts' import { ObjectFilterQuery } from '@shared/database/domain/object-filter-query' import { PaginatedResult } from '@shared/domain/entity/domain/paginated.result' +import { createUserDeactivated } from '@shared/domain/event/event.helper' import { PendingUserDTO } from '@shared/domain/user/dto/pending-user.dto' import { UserPaginationDto } from '@shared/domain/user/dto/user-pagination.dto' import { Resource, USER_STATE, User } from '@shared/domain/user/user.entity' @@ -17,6 +19,7 @@ export class UserManagementService { private readonly logger: Logger constructor( + private readonly em: EntityManager, private readonly user: UserContext, private readonly userRepo: UserRepository, @Inject(ADMIN_PLATFORM_CLIENT) @@ -144,8 +147,10 @@ export class UserManagementService { const encodeEmail = (email: string): string => Buffer.from(email, 'utf8').toString('base64').replace('\n', '') + DNANEXUS_INVALID_EMAIL + const actor = await this.user.loadEntity() + await this.userRepo.transactional(async () => { - users.forEach(user => { + for (const user of users) { user.disableMessage = `Deactivated by admin: ${this.user.dxuser}` user.userState = USER_STATE.DEACTIVATED @@ -155,7 +160,10 @@ export class UserManagementService { if (user.normalizedEmail) { user.normalizedEmail = encodeEmail(user.normalizedEmail) } - }) + + const event = await createUserDeactivated(actor, user) + this.em.persist(event) + } }) } diff --git a/packages/server/libs/shared/src/domain/user/service/user.service.ts b/packages/server/libs/shared/src/domain/user/service/user.service.ts index f92ddb429..98c84a461 100644 --- a/packages/server/libs/shared/src/domain/user/service/user.service.ts +++ b/packages/server/libs/shared/src/domain/user/service/user.service.ts @@ -201,7 +201,7 @@ export class UserService { if (user.extras.sso_enabled === null || user.extras.sso_enabled === undefined) { try { const response = await this.platformClient.getSSOId({ id: user.dxid }) - user.extras.sso_enabled = Boolean(response.SSoId) + user.extras.sso_enabled = Boolean(response.SSOId) await this.em.flush() } catch (error) { this.logger.warn(`Failed to fetch SSO id for user ${user.dxuser}: ${error}`) diff --git a/packages/server/libs/shared/src/domain/user/user.entity.ts b/packages/server/libs/shared/src/domain/user/user.entity.ts index 0c92e0733..c80d2a6ff 100644 --- a/packages/server/libs/shared/src/domain/user/user.entity.ts +++ b/packages/server/libs/shared/src/domain/user/user.entity.ts @@ -13,6 +13,8 @@ import { SPACE_STATE } from '@shared/domain/space/space.enum' import { SpaceMembership } from '@shared/domain/space-membership/space-membership.entity' import { ADMIN_LEAD_ROLES, CAN_EDIT_ROLES } from '@shared/domain/space-membership/space-membership.helper' import { UserExtras } from '@shared/domain/user/user-extras' +import { EntityScope } from '@shared/types/common' +import { EntityScopeUtils } from '@shared/utils/entity-scope.utils' import { config } from '../../config' import { BaseEntity } from '../../database/base.entity' import { AdminMembership } from '../admin-membership/admin-membership.entity' @@ -142,6 +144,8 @@ export const DEFAULT_USER_EXTRAS: UserExtras = { sso_enabled: null, } +export type SpaceMembershipMode = 'leadable' | 'manageable' | 'editable' | 'accessible' + @Entity({ tableName: 'users', repository: () => UserRepository }) export class User extends BaseEntity { @Property() @@ -277,15 +281,30 @@ export class User extends BaseEntity { return this.dxuser } + private spaceMembershipWhere(mode?: SpaceMembershipMode, spaceId?: number): Record { + let roleFilter = {} + if (mode === 'leadable') { + roleFilter = { role: SPACE_MEMBERSHIP_ROLE.LEAD } + } else if (mode === 'manageable') { + roleFilter = { role: { $in: ADMIN_LEAD_ROLES } } + } else if (mode === 'editable') { + roleFilter = { role: { $in: CAN_EDIT_ROLES } } + } + + return { + active: true, + ...roleFilter, + spaces: { + ...(spaceId !== undefined ? { id: spaceId } : {}), + state: { $ne: SPACE_STATE.DELETED }, + }, + } + } + async accessibleSpaces(): Promise { await this.spaceMemberships.load({ populate: ['spaces'], - where: { - active: true, - spaces: { - state: { $ne: SPACE_STATE.DELETED }, - }, - }, + where: this.spaceMembershipWhere('accessible'), }) return Array.from(this.spaceMemberships).flatMap(spaceMembership => Array.from(spaceMembership.spaces)) @@ -299,13 +318,7 @@ export class User extends BaseEntity { async editableSpaces(): Promise { await this.spaceMemberships.load({ populate: ['spaces'], - where: { - active: true, - role: { $in: CAN_EDIT_ROLES }, - spaces: { - state: { $ne: SPACE_STATE.DELETED }, - }, - }, + where: this.spaceMembershipWhere('editable'), }) return Array.from(this.spaceMemberships).flatMap(membership => Array.from(membership.spaces)) @@ -317,13 +330,7 @@ export class User extends BaseEntity { async manageableSpaces(): Promise { await this.spaceMemberships.load({ populate: ['spaces'], - where: { - active: true, - role: { $in: ADMIN_LEAD_ROLES }, - spaces: { - state: { $ne: SPACE_STATE.DELETED }, - }, - }, + where: this.spaceMembershipWhere('manageable'), }) return Array.from(this.spaceMemberships).flatMap(membership => Array.from(membership.spaces)) @@ -332,13 +339,7 @@ export class User extends BaseEntity { async leadableSpaces(): Promise { await this.spaceMemberships.load({ populate: ['spaces'], - where: { - active: true, - role: SPACE_MEMBERSHIP_ROLE.LEAD, - spaces: { - state: { $ne: SPACE_STATE.DELETED }, - }, - }, + where: this.spaceMembershipWhere('leadable'), }) return Array.from(this.spaceMemberships).flatMap(membership => Array.from(membership.spaces)) } @@ -388,4 +389,29 @@ export class User extends BaseEntity { isJobExecutionEnabled(): boolean { return this.cloudResourceSettings.job_limit > 0 } + + async getDestinationProjectId(scope: EntityScope, mode?: SpaceMembershipMode): Promise | null> { + if (EntityScopeUtils.isPublic(scope)) { + return this.publicFilesProject + } else if (EntityScopeUtils.isPrivate(scope)) { + return this.privateFilesProject + } else if (EntityScopeUtils.isSpaceScope(scope)) { + const spaceId = EntityScopeUtils.getSpaceIdFromScope(scope) + + const spaceMemberships = await this.spaceMemberships.loadItems({ + where: this.spaceMembershipWhere(mode, spaceId), + refresh: true, + }) + if (spaceMemberships.length > 1) { + throw new Error(`Data integrity error: user ${this.dxuser} has multiple memberships for space ${spaceId}`) + } + const spaceMembership = spaceMemberships[0] + if (!spaceMembership) { + return null + } + await spaceMembership.spaces.load() + const space = spaceMembership.spaces.find(space => space.id === spaceId) + return spaceMembership.isHost() ? space.hostProject : space.guestProject + } + } } diff --git a/packages/server/libs/shared/src/facade/admin-membership/admin-membership-facade.module.ts b/packages/server/libs/shared/src/facade/admin-membership/admin-membership-facade.module.ts index d0be2fc3a..6c178615f 100644 --- a/packages/server/libs/shared/src/facade/admin-membership/admin-membership-facade.module.ts +++ b/packages/server/libs/shared/src/facade/admin-membership/admin-membership-facade.module.ts @@ -5,12 +5,12 @@ import { SpaceMembershipModule } from '@shared/domain/space-membership/space-mem import { UserModule } from '@shared/domain/user/user.module' import { PlatformClientModule } from '@shared/platform-client/platform-client.module' import { CreateAdminMembershipFacade } from './create-admin-membership.facade' -import { ListAdminMembershipFacade } from './list-admin-membership.facade' +import { AdminMembershipsListFacade } from './admin-memberships-list.facade' import { RemoveAdminMembershipFacade } from './remove-admin-membership.facade' @Module({ imports: [AdminMembershipModule, SpaceMembershipModule, SpaceModule, UserModule, PlatformClientModule], - providers: [ListAdminMembershipFacade, CreateAdminMembershipFacade, RemoveAdminMembershipFacade], - exports: [ListAdminMembershipFacade, CreateAdminMembershipFacade, RemoveAdminMembershipFacade], + providers: [AdminMembershipsListFacade, CreateAdminMembershipFacade, RemoveAdminMembershipFacade], + exports: [AdminMembershipsListFacade, CreateAdminMembershipFacade, RemoveAdminMembershipFacade], }) export class AdminMembershipFacadeModule {} diff --git a/packages/server/libs/shared/src/facade/admin-membership/list-admin-membership.facade.ts b/packages/server/libs/shared/src/facade/admin-membership/admin-memberships-list.facade.ts similarity index 94% rename from packages/server/libs/shared/src/facade/admin-membership/list-admin-membership.facade.ts rename to packages/server/libs/shared/src/facade/admin-membership/admin-memberships-list.facade.ts index 24ae15a65..ff84e714a 100644 --- a/packages/server/libs/shared/src/facade/admin-membership/list-admin-membership.facade.ts +++ b/packages/server/libs/shared/src/facade/admin-membership/admin-memberships-list.facade.ts @@ -5,7 +5,7 @@ import { PaginatedResult } from '@shared/domain/entity/domain/paginated.result' import { UserService } from '@shared/domain/user/service/user.service' @Injectable() -export class ListAdminMembershipFacade { +export class AdminMembershipsListFacade { constructor(private readonly userService: UserService) {} async listUsersWithRoles(query: AdminMembershipPaginationDTO): Promise> { diff --git a/packages/server/libs/shared/src/facade/app/app-create.facade.ts b/packages/server/libs/shared/src/facade/app/app-create.facade.ts index d1922e7dd..feed89a04 100644 --- a/packages/server/libs/shared/src/facade/app/app-create.facade.ts +++ b/packages/server/libs/shared/src/facade/app/app-create.facade.ts @@ -7,6 +7,7 @@ import { App, AppSpec, Internal } from '@shared/domain/app/app.entity' import { ENTITY_TYPE } from '@shared/domain/app/app.enum' import { APPKIT_LATEST_VERSION, + constructDxid, constructDxName, getCLIKeyInputSpec, getEntityType, @@ -22,6 +23,10 @@ import { DxId } from '@shared/domain/entity/domain/dxid' import { Uid } from '@shared/domain/entity/domain/uid' import { createAppCreated } from '@shared/domain/event/event.helper' import { allowedInstanceTypes } from '@shared/domain/job/job.enum' +import { Tag } from '@shared/domain/tag/tag.entity' +import { Tagging } from '@shared/domain/tagging/tagging.entity' +import { TaggingService } from '@shared/domain/tagging/tagging.service' +import { TAGGABLE_TYPE } from '@shared/domain/tagging/tagging.types' import { User } from '@shared/domain/user/user.entity' import { UserContext } from '@shared/domain/user-context/model/user-context' import { Asset } from '@shared/domain/user-file/asset.entity' @@ -48,6 +53,7 @@ export class AppCreateFacade { private readonly nodeService: NodeService, private readonly appService: AppService, private readonly appSeriesService: AppSeriesService, + private readonly taggingService: TaggingService, ) {} /** @@ -65,23 +71,20 @@ export class AppCreateFacade { await this.validateAppInput(appInput, assets) await this.validateScopeAndUser(user, appInput.scope) - await this.validateForkedApp(appInput.forked_from as Uid<'app'>) + const forkedApp = await this.validateForkedApp(appInput.forked_from as Uid<'app'>) // - create app series let appSeries = await this.appSeriesService.getAppSeriesByName(appInput.name, appInput.scope) + const appSeriesCreated = !appSeries this.validateAppSeriesCreation(appSeries, appInput.createAppSeries) this.validateAppRevisionCreation(appSeries, appInput.createAppRevision) const previousVersionAppDxid = appSeries ? (await this.getLatestRevisionApp(appSeries)).dxid : null - if (!appSeries && appInput.createAppSeries) { - appSeries = await this.appSeriesService.createAppSeries(appInput.name, user, appInput.scope) - this.logger.log(`App series for dxid ${appSeries.dxid} did not exist and user requested its creation`) - } // - get release const release = appInput.release ? appInput.release : UBUNTU_20 // - find the latest revision and increase it by one - const revision = await this.getAppRevision(appSeries.latestRevisionAppId) + const revision = appSeries ? await this.getAppRevision(appSeries.latestRevisionAppId) : 1 // - create new applet in platform const appletId = await this.createApplet(user, appInput, release) @@ -105,28 +108,43 @@ export class AppCreateFacade { await this.publishAppInSpace(user, EntityScopeUtils.getSpaceIdFromScope(appInput.scope), platformAppId) } - await this.em.begin() - try { + return this.em.transactional(async () => { + if (!appSeries && appInput.createAppSeries) { + const appSeriesDxid = constructDxid(this.user.dxuser, appInput.name, appInput.scope) + appSeries = new AppSeries(user) + appSeries.name = appInput.name + appSeries.dxid = appSeriesDxid + appSeries.scope = appInput.scope + await this.em.persist(appSeries).flush() + this.logger.log(`App series for dxid ${appSeries.dxid} did not exist and user requested its creation`) + } + + if (!appSeries) { + throw new ValidationError('App series is missing and cannot proceed with app creation.', { + code: ErrorCodes.APP_SERIES_CREATION_NOT_REQUESTED, + }) + } + // - store app in a database - const app = await this.saveAppInDB(user, platformAppId, revision, release, assets, appInput, appSeries.id) + const app = this.buildApp(user, platformAppId, revision, release, assets, appInput, appSeries.id) + await this.em.persist(app).flush() // - update app series (version, revision, deleted - why?) - await this.updateAppSeries(appSeries, appInput, app) + this.updateAppSeries(appSeries, appInput, app) + + // - copy tags from forked app + if (appSeriesCreated && forkedApp) { + await this.copyForkedAppTags(forkedApp, appSeries) + } // - store app event await this.createAppEvent(user, app) - await this.em.commit() - return app.uid - } catch (error) { - this.logger.error('Error creating an app', error) - await this.em.rollback() - throw error - } + }) } - private async publishAppInSpace(user: User, spaceId: number, appDxid): Promise { + private async publishAppInSpace(user: User, spaceId: number, appDxid: DxId<'app'>): Promise { const space = (await user.editableSpaces()).find(space => space.id === spaceId) if (!space) { @@ -147,11 +165,11 @@ export class AppCreateFacade { private async createAppEvent(user: User, app: App): Promise { this.logger.log(`Creating app event for app ${app.uid} and user ${user.id}`) - const createAppEvent = await createAppCreated(user, app) - await this.em.persist(createAppEvent).flush() + const event = await createAppCreated(user, app) + await this.em.persist(event).flush() } - private async updateAppSeries(appSeries: AppSeries, appInput: SaveAppDTO, app: App): Promise { + private updateAppSeries(appSeries: AppSeries, appInput: SaveAppDTO, app: App): void { this.logger.log(`Updating app series ${appSeries.dxid}`) appSeries.latestRevisionAppId = app.id if (appInput.scope && appInput.scope !== STATIC_SCOPE.PRIVATE) { @@ -165,7 +183,7 @@ export class AppCreateFacade { } } - private async saveAppInDB( + private buildApp( user: User, platformAppId: DxId<'app'>, revision: number, @@ -173,7 +191,7 @@ export class AppCreateFacade { assets: Asset[], appInput: SaveAppDTO, appSeriesId: number, - ): Promise { + ): App { this.logger.log(`Saving app in DB with platformAppId: ${platformAppId}`) const app = new App(user) app.dxid = platformAppId @@ -200,7 +218,6 @@ export class AppCreateFacade { assets.forEach(asset => app.assets.add(asset)) app.release = release - await this.em.persist(app).flush() return app } @@ -313,18 +330,67 @@ export class AppCreateFacade { } } - private async validateForkedApp(forkFrom?: Uid<'app'>): Promise { - if (forkFrom) { - const forkedApp = await this.appService.getAccessibleEntityByUid(forkFrom) + private async validateForkedApp(forkFrom?: Uid<'app'>): Promise { + if (!forkFrom) { + return null + } + + const forkedApp = await this.appService.getAccessibleEntityByUid(forkFrom) + + if (!forkedApp) { + throw new NotFoundError('Forked app does not exist or is not accessible.') + } + + if (forkedApp.entityType === ENTITY_TYPE.HTTPS) { + throw new InvalidRequestError('Forking from this app is not allowed.') + } + + return forkedApp + } + + private async copyForkedAppTags(forkedApp: App, targetAppSeries: AppSeries): Promise { + if (!forkedApp.appSeriesId) { + return + } - if (!forkedApp) { - throw new NotFoundError('Forked app does not exist or is not accessible.') + const sourceTaggings = await this.taggingService.getTaggingsForEntity( + forkedApp.appSeriesId, + TAGGABLE_TYPE.APP_SERIES, + ) + if (!sourceTaggings.length) { + return + } + + for (const sourceTagging of sourceTaggings) { + if (!sourceTagging.tag?.name) { + continue } - if (forkedApp.entityType === ENTITY_TYPE.HTTPS) { - throw new InvalidRequestError('Forking from this app is not allowed.') + let activeTag = await this.em.findOne(Tag, { name: sourceTagging.tag.name }) + if (!activeTag) { + activeTag = new Tag() + activeTag.name = sourceTagging.tag.name + await this.em.persist(activeTag).flush() } + + const existingTagging = await this.em.findOne(Tagging, { + tag: activeTag, + taggableType: TAGGABLE_TYPE.APP_SERIES, + taggableId: targetAppSeries.id, + }) + if (existingTagging) continue + + const tagging = new Tagging() + tagging.tagId = activeTag.id + tagging.taggableType = TAGGABLE_TYPE.APP_SERIES + tagging.taggableId = targetAppSeries.id + tagging.taggerType = sourceTagging.taggerType + tagging.taggerId = sourceTagging.taggerId + tagging.context = 'tags' + this.em.persist(tagging) } + + await this.em.flush() } private async validateScopeAndUser(user: User, scope: EntityScope): Promise { diff --git a/packages/server/libs/shared/src/facade/app/app-facade.module.ts b/packages/server/libs/shared/src/facade/app/app-facade.module.ts index 9f6ead00e..789a2b4e3 100644 --- a/packages/server/libs/shared/src/facade/app/app-facade.module.ts +++ b/packages/server/libs/shared/src/facade/app/app-facade.module.ts @@ -6,6 +6,7 @@ import { CliExchangeTokenModule } from '@shared/domain/cli-exchange-token/cli-ex import { JobModule } from '@shared/domain/job/job.module' import { LicenseModule } from '@shared/domain/license/license.module' import { SpaceMembershipModule } from '@shared/domain/space-membership/space-membership.module' +import { TaggingModule } from '@shared/domain/tagging/tagging.module' import { UserModule } from '@shared/domain/user/user.module' import { UserFileModule } from '@shared/domain/user-file/user-file.module' import { PlatformClientModule } from '@shared/platform-client/platform-client.module' @@ -16,6 +17,7 @@ import { AppRunFacade } from './app-run.facade' imports: [ AppModule, AppSeriesModule, + TaggingModule, JobModule, AuthModule, LicenseModule, diff --git a/packages/server/libs/shared/src/facade/file-create/model/file-create.ts b/packages/server/libs/shared/src/facade/file-create/model/file-create.ts index d8ac65f13..6122b03b0 100644 --- a/packages/server/libs/shared/src/facade/file-create/model/file-create.ts +++ b/packages/server/libs/shared/src/facade/file-create/model/file-create.ts @@ -1,4 +1,5 @@ import { DxId } from '@shared/domain/entity/domain/dxid' +import { PARENT_TYPE } from '@shared/domain/user-file/user-file.types' import { EntityScope } from '@shared/types/common' export interface FileCreate { @@ -6,4 +7,8 @@ export interface FileCreate { name: string scope: EntityScope description: string + parentType?: PARENT_TYPE + parentId?: number + parentFolderId?: number + scopedParentFolderId?: number } diff --git a/packages/server/libs/shared/src/facade/file-create/user-file-create-facade.module.ts b/packages/server/libs/shared/src/facade/file-create/user-file-create-facade.module.ts index 0bb0c8086..bf2c2d2d0 100644 --- a/packages/server/libs/shared/src/facade/file-create/user-file-create-facade.module.ts +++ b/packages/server/libs/shared/src/facade/file-create/user-file-create-facade.module.ts @@ -1,10 +1,12 @@ import { Module } from '@nestjs/common' +import { JobModule } from '@shared/domain/job/job.module' import { PlatformModule } from '@shared/domain/platform/platform.module' +import { UserModule } from '@shared/domain/user/user.module' import { UserFileModule } from '@shared/domain/user-file/user-file.module' import { UserFileCreateFacade } from '@shared/facade/file-create/user-file-create.facade' @Module({ - imports: [PlatformModule, UserFileModule], + imports: [PlatformModule, UserFileModule, JobModule, UserModule], providers: [UserFileCreateFacade], exports: [UserFileCreateFacade], }) diff --git a/packages/server/libs/shared/src/facade/file-create/user-file-create.facade.ts b/packages/server/libs/shared/src/facade/file-create/user-file-create.facade.ts index d6a9c0b37..1af015908 100644 --- a/packages/server/libs/shared/src/facade/file-create/user-file-create.facade.ts +++ b/packages/server/libs/shared/src/facade/file-create/user-file-create.facade.ts @@ -1,11 +1,17 @@ import { Injectable } from '@nestjs/common' import { DxId } from '@shared/domain/entity/domain/dxid' +import { EntityUidResponseDTO } from '@shared/domain/entity/dto/entity-uid-response.dto' +import { JobService } from '@shared/domain/job/job.service' import { PlatformFileService } from '@shared/domain/platform/service/platform-file.service' +import { UserService } from '@shared/domain/user/service/user.service' import { UserContext } from '@shared/domain/user-context/model/user-context' +import { UserFileCreateDTO } from '@shared/domain/user-file/dto/user-file-create.dto' +import { Folder } from '@shared/domain/user-file/folder.entity' import { NodeService } from '@shared/domain/user-file/node.service' import { UserFile } from '@shared/domain/user-file/user-file.entity' -import { InternalError } from '@shared/errors' -import { FILE_STATE_DX, PARENT_TYPE } from '../../domain/user-file/user-file.types' +import { InternalError, InvalidStateError, PermissionError } from '@shared/errors' +import { EntityScopeUtils } from '@shared/utils/entity-scope.utils' +import { FILE_STATE_DX, FILE_STATE_PFDA, PARENT_TYPE } from '../../domain/user-file/user-file.types' import { FileCreate } from './model/file-create' import { FileCreateWithContent } from './model/file-create-with-content' @@ -15,10 +21,12 @@ export class UserFileCreateFacade { private readonly user: UserContext, private readonly platformFileService: PlatformFileService, private readonly nodeService: NodeService, + private readonly jobService: JobService, + private readonly userService: UserService, ) {} async createFileWithContent(props: FileCreateWithContent, initCloseFile = true): Promise { - const file = await this.createFile(props) + const file = await this.saveFileToDB(props) await this.platformFileService.uploadFileContent(file, props.content) if (initCloseFile) { @@ -28,7 +36,62 @@ export class UserFileCreateFacade { return file } - async createFile({ name, project, scope, description }: FileCreate): Promise { + async createFile(input: UserFileCreateDTO): Promise { + const user = await this.user.loadEntity() + + if (input.scope === 'public' && !(await user?.isSiteAdmin())) { + throw new PermissionError('Only site admin can create public files') + } + + let folder: Folder = null + if (input.folderId) { + folder = await this.nodeService.getEditableFolder(input.folderId) + if (!folder) { + throw new InvalidStateError('Parent folder not found') + } + if (folder && folder.state === FILE_STATE_PFDA.REMOVING) { + throw new InvalidStateError('Cannot add file to a folder that is being removed') + } + + // Inherit the scope of the folder if the file is being created inside a folder + input.scope = folder.scope + } + + await this.userService.checkTotalChargesLimit() + + let parentType = PARENT_TYPE.USER + let parentId = user.id + if (input.parentType === PARENT_TYPE.JOB) { + const job = await this.jobService.getEditableOne({ dxid: input.parentId }) + // file could be uploaded by CLI inside job; fall back to current_user if job is not found + if (job) { + parentType = PARENT_TYPE.JOB + parentId = job.id + } + } + + const project = await user.getDestinationProjectId(input.scope, 'editable') + if (!project) { + throw new InvalidStateError('Scope does not exist or user does not have write access to the scope') + } + + const isSpaceScope = EntityScopeUtils.isSpaceScope(input.scope) + + const file = await this.saveFileToDB({ + name: input.name, + project, + scope: input.scope, + description: input.description ?? '', + parentType, + parentId, + parentFolderId: !isSpaceScope ? folder?.id : null, + scopedParentFolderId: isSpaceScope ? folder?.id : null, + }) + return { uid: file.uid, id: file.uid } + } + + async saveFileToDB(input: FileCreate): Promise { + const { name, project, description, scope, parentType, parentId } = input const dxid = (await this.platformFileService.createFile({ name, project, description }))?.id as DxId<'file'> if (dxid == null) { @@ -36,8 +99,8 @@ export class UserFileCreateFacade { } return await this.nodeService.createFile({ - parentId: this.user.id, - parentType: PARENT_TYPE.USER, + parentId: parentId ?? this.user.id, + parentType: parentType ?? PARENT_TYPE.USER, userId: this.user.id, name, state: FILE_STATE_DX.OPEN, @@ -45,6 +108,8 @@ export class UserFileCreateFacade { project, dxid, description, + parentFolderId: input.parentFolderId, + scopedParentFolderId: input.scopedParentFolderId, }) } } diff --git a/packages/server/libs/shared/src/facade/node-copy/copy-nodes.facade.ts b/packages/server/libs/shared/src/facade/node-copy/copy-nodes.facade.ts index 6ff7e6678..ba2f0f4fe 100644 --- a/packages/server/libs/shared/src/facade/node-copy/copy-nodes.facade.ts +++ b/packages/server/libs/shared/src/facade/node-copy/copy-nodes.facade.ts @@ -431,7 +431,7 @@ export class CopyNodesFacade { const spaceId = EntityScopeUtils.getSpaceIdFromScope(scope) const membership = await this.spaceMembershipRepo.getMembership(spaceId, user.id) await membership.spaces.load() - return membership.isHost ? membership.spaces[0].hostProject : membership.spaces[0].guestProject + return membership.isHost() ? membership.spaces[0].hostProject : membership.spaces[0].guestProject } } } diff --git a/packages/server/libs/shared/src/facade/profile/org-member-action.facade.ts b/packages/server/libs/shared/src/facade/profile/org-member-action.facade.ts index be8d4293c..0abbe1e2a 100644 --- a/packages/server/libs/shared/src/facade/profile/org-member-action.facade.ts +++ b/packages/server/libs/shared/src/facade/profile/org-member-action.facade.ts @@ -1,5 +1,6 @@ import { EntityManager } from '@mikro-orm/mysql' import { Injectable, Logger } from '@nestjs/common' +import { createUserDeactivated } from '@shared/domain/event/event.helper' import { OrgActionRequestService } from '@shared/domain/org-action-request/org-action-request.service' import { Organization } from '@shared/domain/org/organization.entity' import { UserContext } from '@shared/domain/user-context/model/user-context' @@ -40,8 +41,12 @@ export class OrgMemberActionFacade { throw new InvalidStateError('User is already deactivated') } - targetUser.userState = USER_STATE.DEACTIVATED - await this.em.flush() + await this.em.transactional(async () => { + targetUser.userState = USER_STATE.DEACTIVATED + + const event = await createUserDeactivated(currentUser, targetUser) + this.em.persist(event) + }) this.logger.log( `User ${targetUserId} deactivated by org admin ${currentUser.id} in org ${org.id}`, diff --git a/packages/server/libs/shared/src/platform-client/index.ts b/packages/server/libs/shared/src/platform-client/index.ts index a1c01d744..c821ebfe5 100644 --- a/packages/server/libs/shared/src/platform-client/index.ts +++ b/packages/server/libs/shared/src/platform-client/index.ts @@ -764,7 +764,7 @@ export class PlatformClient { * Outputs: * - {SSOId: string} Identity provider ID from Okta, or empty string for non-SSO users */ - async getSSOId(data: GetSsoIdData): Promise<{ SSoId: string }> { + async getSSOId(data: GetSsoIdData): Promise<{ SSOId: string }> { const url = `${config.platform.apiUrl}/user/getSSOId` const options: AxiosRequestConfig = { diff --git a/packages/server/libs/shared/src/queue/index.ts b/packages/server/libs/shared/src/queue/index.ts index ae4b52eee..9787239ae 100644 --- a/packages/server/libs/shared/src/queue/index.ts +++ b/packages/server/libs/shared/src/queue/index.ts @@ -164,11 +164,8 @@ const createRunFollowUpActionJobTask = async (payload: UidAndFollowUpInput, user /** * @deprecated Use the job producer directly within the DI */ -const createFileSynchronizeJobTask = async ( - payload: SyncFileJobInput, - user?: UserCtx, - delayInMs?: number, -): Promise => mainJobProducer.createFileSynchronizeJobTask(payload, user, delayInMs) +const createFileSynchronizeJobTask = async (payload: SyncFileJobInput, user?: UserCtx): Promise => + mainJobProducer.createFileSynchronizeJobTask(payload, user) /** * @deprecated Use the job producer directly within the DI diff --git a/packages/server/libs/shared/src/queue/producer/main-queue-job.producer.ts b/packages/server/libs/shared/src/queue/producer/main-queue-job.producer.ts index 325fdb93e..4658666f1 100644 --- a/packages/server/libs/shared/src/queue/producer/main-queue-job.producer.ts +++ b/packages/server/libs/shared/src/queue/producer/main-queue-job.producer.ts @@ -82,7 +82,7 @@ export class MainQueueJobProducer extends QueueJobProducer { await this.addToQueue(wrapped, options) } - async createFileSynchronizeJobTask(payload: SyncFileJobInput, user?: UserCtx, delayInMs?: number): Promise { + async createFileSynchronizeJobTask(payload: SyncFileJobInput, user?: UserCtx): Promise { const wrapped = { type: TASK_TYPE.SYNC_FILE_STATE as const, payload, @@ -91,7 +91,6 @@ export class MainQueueJobProducer extends QueueJobProducer { const options: JobOptions = { jobId: `${wrapped.type}.${payload.fileUid}`, - delay: delayInMs ?? 0, } await this.addToQueue(wrapped, options) diff --git a/packages/server/libs/shared/src/queue/queue.event.listener.ts b/packages/server/libs/shared/src/queue/queue.event.listener.ts index f9120c477..090ef4632 100644 --- a/packages/server/libs/shared/src/queue/queue.event.listener.ts +++ b/packages/server/libs/shared/src/queue/queue.event.listener.ts @@ -21,29 +21,47 @@ export class QueueEventListener { this.init() } - private init() { + private init(): void { this.queues.forEach(queue => { queue.on('failed', (job: Job, error: Error) => { try { - this.logger.error({ job: this.getJobInfo(job), error }, 'Job failed') - } catch (error) { - console.error('error during queue failed handling', { error }) + const attempts = job.opts.attempts ?? 1 + const isTerminalFailure = job.attemptsMade >= attempts + const context = { + job: this.getJobInfo(job), + error, + attemptsMade: job.attemptsMade, + attempts, + } + + if (isTerminalFailure) { + this.logger.error(context, 'Job failed') + } else { + this.logger.warn(context, 'Job attempt failed, retry scheduled by Bull') + } + } catch (eventHandlerError) { + console.error('error during queue failed handling', { error: eventHandlerError }) } }) - queue.on('waiting', async (jobId: number) => { + queue.on('waiting', async (jobId: number | string) => { try { const job = await queue.getJob(jobId) this.logger.debug(this.getJobInfo(job), 'Job waiting in queue') - } catch (error) { - console.error('error during queue waiting handling', { error }) + } catch (eventHandlerError) { + console.error('error during queue waiting handling', { error: eventHandlerError }) } }) }) } - private getJobInfo(job: Job) { + private getJobInfo(job: Job | null): { + type: TaskWithAuth['type'] | undefined + payload: TaskWithAuth['payload'] | undefined + userId: number | undefined + jobId: string | number | undefined + } { return { type: job?.data?.type, payload: job?.data?.payload, diff --git a/packages/server/libs/shared/src/test/generate.ts b/packages/server/libs/shared/src/test/generate.ts index 557d6d3d5..19de86783 100644 --- a/packages/server/libs/shared/src/test/generate.ts +++ b/packages/server/libs/shared/src/test/generate.ts @@ -546,6 +546,7 @@ const userFile = { stiType: FILE_STI_TYPE.USERFILE, } }, + fileId: (): string => `file-${random.dxstr()}`, } const asset = { diff --git a/packages/server/libs/shared/src/test/mocks.ts b/packages/server/libs/shared/src/test/mocks.ts index dd534a601..0df09a9c8 100644 --- a/packages/server/libs/shared/src/test/mocks.ts +++ b/packages/server/libs/shared/src/test/mocks.ts @@ -33,6 +33,7 @@ const fakes = { fileStatesFake: sinon.stub(), filesListFake: sinon.stub(), filesDescFake: sinon.stub(), + fileCreateFake: sinon.stub(), foldersListFake: sinon.stub(), folderRenameFake: sinon.stub(), folderRemoveFake: sinon.stub(), @@ -123,6 +124,7 @@ const mocksSetDefaultBehaviour = (): void => { fakes.client.filesMoveFake.callsFake(() => ({ id: generate.job.jobId() })) fakes.client.filesListFake.callsFake(() => FILES_LIST_RES_ROOT) fakes.client.filesDescFake.callsFake(() => FILES_DESC_RES) + fakes.client.fileCreateFake.callsFake(() => ({ id: generate.userFile.fileId() })) fakes.client.foldersListFake.callsFake(() => FOLDERS_LIST_RES) fakes.client.orgFindMembersFake.callsFake(() => FIND_MEMBERS_RES) @@ -203,6 +205,12 @@ const mocksSetDefaultBehaviour = (): void => { const data = stub ? stub(...(body.params ?? [])) : undefined return of({ data }) }) + fakes.client.userCloudResourcesFake.callsFake(() => ({ + computeCharges: 0, + storageCharges: 0, + dataEgressCharges: 0, + })) + ;(fakes.bull.isReadyFake as sinon.SinonStub).callsFake(() => Promise.resolve(true)) mockServiceFactory.reset() } @@ -217,6 +225,7 @@ const mocksSetup = (): void => { sandbox.replace(PlatformClient.prototype, 'fileDescribe', fakes.client.fileDescribeFake) sandbox.replace(PlatformClient.prototype, 'fileStates', fakes.client.fileStatesFake) sandbox.replace(PlatformClient.prototype, 'filesList', fakes.client.filesListFake) + sandbox.replace(PlatformClient.prototype, 'fileCreate', fakes.client.fileCreateFake) sandbox.replace(PlatformClient.prototype, 'folderCreate', fakes.client.folderCreateFake) sandbox.replace(PlatformClient.prototype, 'filesMoveToFolder', fakes.client.filesMoveFake) // sandbox.replace(PlatformClient.prototype, 'filesDescribe', fakes.client.filesDescFake) @@ -280,6 +289,7 @@ const mocksReset = (): void => { fakes.client.fileStatesFake.reset() fakes.client.filesListFake.reset() fakes.client.filesDescFake.reset() + fakes.client.fileCreateFake.reset() fakes.client.foldersListFake.reset() fakes.client.folderRenameFake.reset() fakes.client.folderRemoveFake.reset() @@ -299,6 +309,7 @@ const mocksReset = (): void => { fakes.client.userDescribeFake.reset() fakes.client.userResetMfaFake.reset() fakes.client.userUpdateEmailFake.reset() + fakes.client.userCloudResourcesFake.reset() fakes.client.fileDownloadLinkFake.reset() fakes.client.userCloudResourcesFake.reset() diff --git a/packages/server/libs/shared/src/validation/pipes/snake-to-camel.pipe.ts b/packages/server/libs/shared/src/validation/pipes/snake-to-camel.pipe.ts new file mode 100644 index 000000000..63f9ece21 --- /dev/null +++ b/packages/server/libs/shared/src/validation/pipes/snake-to-camel.pipe.ts @@ -0,0 +1,23 @@ +import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common' + +function snakeToCamel(str: string): string { + return str.replace(/_([a-z])/g, (_, char: string) => char.toUpperCase()) +} + +function transformKeys(value: unknown): unknown { + if (Array.isArray(value)) return value.map(transformKeys) + if (value !== null && typeof value === 'object') { + return Object.fromEntries( + Object.entries(value as Record).map(([k, v]) => [snakeToCamel(k), transformKeys(v)]), + ) + } + return value +} + +@Injectable() +export class SnakeToCamelPipe implements PipeTransform { + transform(value: unknown, metadata: ArgumentMetadata): unknown { + if (metadata.type === 'body') return transformKeys(value) + return value + } +} diff --git a/packages/server/libs/shared/src/validation/pipes/validation.pipe.ts b/packages/server/libs/shared/src/validation/pipes/validation.pipe.ts index 6b61dba32..4c62677c6 100644 --- a/packages/server/libs/shared/src/validation/pipes/validation.pipe.ts +++ b/packages/server/libs/shared/src/validation/pipes/validation.pipe.ts @@ -16,7 +16,7 @@ import { ValidationError } from '@shared/errors' **/ @Injectable() export class CustomValidationPipe extends ValidationPipe { - async transform(value: unknown, metadata: ArgumentMetadata) { + async transform(value: unknown, metadata: ArgumentMetadata): Promise { try { return await super.transform(value, metadata) } catch (error) { diff --git a/packages/server/libs/shared/test/unit/domain/app-series.service.spec.ts b/packages/server/libs/shared/test/unit/domain/app-series.service.spec.ts index 32eccd1cd..b62643117 100644 --- a/packages/server/libs/shared/test/unit/domain/app-series.service.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/app-series.service.spec.ts @@ -49,24 +49,6 @@ describe('AppSeriesService', () => { }) }) - context('createAppSeries', () => { - it('should create a new app series', async () => { - const appSeriesService = getInstance() - const appName = 'Test App Series' - const scope = 'private' - const appSeries = await appSeriesService.createAppSeries(appName, user, scope) - - expect(appSeries).to.be.instanceOf(AppSeries) - expect(appSeries.name).to.equal(appName) - expect(appSeries.scope).to.equal(scope) - expect(appSeries.user?.id).to.equal(user.id) - - const foundAppSeries = await em.findOne(AppSeries, { id: appSeries.id }) - expect(foundAppSeries).to.not.be.null - expect(foundAppSeries?.name).to.equal(appName) - }) - }) - function getInstance(): AppSeriesService { return new AppSeriesService(userCtx, appSeriesRepository, appSeriesCountService) } diff --git a/packages/server/libs/shared/test/unit/domain/copy-nodes.facade.spec.ts b/packages/server/libs/shared/test/unit/domain/copy-nodes.facade.spec.ts index 7d0746409..96e3cd1d4 100644 --- a/packages/server/libs/shared/test/unit/domain/copy-nodes.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/copy-nodes.facade.spec.ts @@ -357,7 +357,7 @@ describe('CopyNodesFacade', () => { spacesCollection.load = stub().resolves() const spaceMembership = { - isHost: true, + isHost: () => true, spaces: spacesCollection, } as unknown as SpaceMembership @@ -366,7 +366,7 @@ describe('CopyNodesFacade', () => { spaceMemberships: [ { spaces: [{ id: spaceId, hostProject: 'project-host' }], - isHost: true, + isHost: () => true, }, ], }) diff --git a/packages/server/libs/shared/test/unit/domain/db-cluster-list.facade.spec.ts b/packages/server/libs/shared/test/unit/domain/db-clusters-list.facade.spec.ts similarity index 96% rename from packages/server/libs/shared/test/unit/domain/db-cluster-list.facade.spec.ts rename to packages/server/libs/shared/test/unit/domain/db-clusters-list.facade.spec.ts index 20acd9fce..c5cf283e6 100644 --- a/packages/server/libs/shared/test/unit/domain/db-cluster-list.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/db-clusters-list.facade.spec.ts @@ -1,5 +1,5 @@ import { EntityManager } from '@mikro-orm/mysql' -import { DbClusterListFacade } from 'apps/api/src/facade/db-cluster/list-facade/db-cluster-list.facade' +import { DbClustersListFacade } from 'apps/api/src/facade/db-cluster/list-facade/db-clusters-list.facade' import { expect } from 'chai' import { match, stub } from 'sinon' import { STATUS } from '@shared/domain/db-cluster/db-cluster.enum' @@ -16,7 +16,7 @@ import { UserContext } from '@shared/domain/user-context/model/user-context' import { STATIC_SCOPE } from '@shared/enums' import { PermissionError } from '@shared/errors' -describe('DbClusterListFacade', () => { +describe('DbClustersListFacade', () => { const USER_ID = 0 const accessibleSpaces = stub() const USER = { @@ -267,7 +267,7 @@ describe('DbClusterListFacade', () => { expect(result.data).to.have.length(0) }) - function getInstance(): DbClusterListFacade { + function getInstance(): DbClustersListFacade { const em = {} as unknown as EntityManager const dbClusterRepo = { paginate: paginateStub, @@ -291,6 +291,6 @@ describe('DbClusterListFacade', () => { findLicenseRefsByLicenseableIds: findLicenseRefsByLicenseableIdsStub, } as unknown as LicenseService - return new DbClusterListFacade(dbClusterService, userContext, spaceService, spaceMembershipService, licenseService) + return new DbClustersListFacade(dbClusterService, userContext, spaceService, spaceMembershipService, licenseService) } }) diff --git a/packages/server/libs/shared/test/unit/domain/node.helper.spec.ts b/packages/server/libs/shared/test/unit/domain/node.helper.spec.ts index dfb6a9f7c..f2108601d 100644 --- a/packages/server/libs/shared/test/unit/domain/node.helper.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/node.helper.spec.ts @@ -117,6 +117,62 @@ describe('NodeHelper', () => { }) }) + it('renders node origin link when parent node exists', async () => { + let findOneWhere: { id: number } | null = null + const nodeRepo = { + findOne: async (where: { id: number }) => { + findOneWhere = where + return { uid: 'file-G222-1', name: 'Source File' } + }, + } + + const helper = new NodeHelper( + {} as never, + {} as never, + {} as never, + nodeRepo as never, + { findOne: async () => null } as never, + { findOne: async () => null } as never, + ) + + const result = await helper.resolveOrigin({ parentType: PARENT_TYPE.NODE, parentId: 42 } as UserFile) + + expect(findOneWhere).to.deep.equal({ id: 42 }) + expect(result).to.deep.equal({ + origin: { text: 'Source File' }, + parentType: 'Node', + parentUid: 'file-G222-1', + }) + }) + + it('returns Copied origin for node parent type when parentId does not resolve', async () => { + let findOneWhere: { id: number } | null = null + const nodeRepo = { + findOne: async (where: { id: number }) => { + findOneWhere = where + return null + }, + } + + const helper = new NodeHelper( + {} as never, + {} as never, + {} as never, + nodeRepo as never, + { findOne: async () => null } as never, + { findOne: async () => null } as never, + ) + + const result = await helper.resolveOrigin({ parentType: PARENT_TYPE.NODE, parentId: 99 } as UserFile) + + expect(findOneWhere).to.deep.equal({ id: 99 }) + expect(result).to.deep.equal({ + origin: 'Copied', + parentType: 'Node', + parentUid: null, + }) + }) + it('renders job origin link when parent job exists', async () => { let findOneWhere: { id: number } | null = null const jobRepo = { diff --git a/packages/server/libs/shared/test/unit/domain/tagging.service.spec.ts b/packages/server/libs/shared/test/unit/domain/tagging.service.spec.ts index f35cf1a02..9d1b63036 100644 --- a/packages/server/libs/shared/test/unit/domain/tagging.service.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/tagging.service.spec.ts @@ -1,4 +1,4 @@ -import { SqlEntityManager } from '@mikro-orm/mysql' +import { EntityManager } from '@mikro-orm/mysql' import { expect } from 'chai' import sinon from 'sinon' import { TagRepository } from '@shared/domain/tag/tag.repository' @@ -7,40 +7,61 @@ import { TaggingService } from '@shared/domain/tagging/tagging.service' import { TAGGABLE_TYPE } from '@shared/domain/tagging/tagging.types' describe('TaggingService', () => { + const emTransactionalStub = sinon.stub() + const emPersistStub = sinon.stub() + const emPersistFlushStub = sinon.stub() + const emRemoveStub = sinon.stub() + const tagRepoFindOneStub = sinon.stub() + const tagRepoCreateStub = sinon.stub() + const taggingRepoFindForTaggableStub = sinon.stub() const taggingRepoFindOneStub = sinon.stub() const taggingRepoCountStub = sinon.stub() - const emTransactionalStub = sinon.stub() - const emRemoveStub = sinon.stub() - const emPersistAndFlushStub = sinon.stub() - const emPersistStub = sinon.stub() - const em = { - transactional: emTransactionalStub, - remove: emRemoveStub, - persistAndFlush: emPersistAndFlushStub, - persist: emPersistStub, - } as unknown as SqlEntityManager - - emTransactionalStub.callsFake(async callback => { - return callback(em) - }) + emPersistStub.callsFake(() => ({ flush: emPersistFlushStub })) - const getTaggingService = () => { + const getTaggingService = (): TaggingService => { const taggingRepository = { findForTaggable: taggingRepoFindForTaggableStub, findOne: taggingRepoFindOneStub, count: taggingRepoCountStub, } as unknown as TaggingRepository + const tagRepository = { findOne: tagRepoFindOneStub, + create: tagRepoCreateStub, } as unknown as TagRepository + const em = { + transactional: emTransactionalStub, + persist: emPersistStub, + remove: emRemoveStub, + getRepository: sinon.stub().callsFake((entity: unknown) => { + const entityName = (entity as { name?: string })?.name + if (entityName === 'Tag') return tagRepository + if (entityName === 'Tagging') return taggingRepository + return undefined + }), + } as unknown as EntityManager + + emTransactionalStub.callsFake(async callback => callback(em)) + return new TaggingService(em, taggingRepository, tagRepository) } beforeEach(() => { + emTransactionalStub.reset() + + emPersistStub.reset() + emPersistStub.callsFake(() => ({ flush: emPersistFlushStub })) + + emPersistFlushStub.reset() + emPersistFlushStub.resolves() + + emRemoveStub.reset() + emRemoveStub.returns(undefined) + taggingRepoFindForTaggableStub.reset() taggingRepoFindForTaggableStub.throws() @@ -50,20 +71,11 @@ describe('TaggingService', () => { taggingRepoCountStub.reset() taggingRepoCountStub.throws() - emRemoveStub.reset() - emRemoveStub.throws() - tagRepoFindOneStub.reset() tagRepoFindOneStub.throws() - emPersistAndFlushStub.reset() - emPersistAndFlushStub.throws() - - emPersistStub.reset() - emPersistStub.throws() - - emTransactionalStub.reset() - emTransactionalStub.callsFake(cb => cb(em)) + tagRepoCreateStub.reset() + tagRepoCreateStub.callsFake((data: { name: string }) => ({ name: data.name })) }) describe('#addTaggingForEntity', () => { @@ -74,38 +86,43 @@ describe('TaggingService', () => { it('non existing tag and existing taggings', async () => { tagRepoFindOneStub.resolves(null) taggingRepoFindOneStub.resolves(null) - emPersistAndFlushStub.reset() - emPersistAndFlushStub.callsFake(entity => { - entity.id = TAG_ID - }) emPersistStub.reset() + emPersistStub.callsFake((entity: { id?: number }) => { + if (!entity.id) { + entity.id = TAG_ID + } + return { flush: emPersistFlushStub } + }) const service = getTaggingService() await service.addTaggingForEntity('tag', 'taggerType', USER_ID, TAGGABLE_ID, TAGGABLE_TYPE.NODE) - expect(emTransactionalStub.calledOnce).to.be.true() + expect(emTransactionalStub.notCalled).to.be.true() expect(tagRepoFindOneStub.calledOnce).to.be.true() - expect(emPersistAndFlushStub.calledOnce).to.be.true() - expect(emPersistAndFlushStub.firstCall.args[0].name).to.eq('tag') - expect(emPersistStub.calledOnce).to.be.true() - expect(emPersistStub.firstCall.args[0].tagId).to.eq(TAG_ID) - expect(emPersistStub.firstCall.args[0].taggableType).to.eq(TAGGABLE_TYPE.NODE) - expect(emPersistStub.firstCall.args[0].taggableId).to.eq(TAGGABLE_ID) - expect(emPersistStub.firstCall.args[0].taggerType).to.eq('taggerType') - expect(emPersistStub.firstCall.args[0].taggerId).to.eq(USER_ID) - expect(emPersistStub.firstCall.args[0].context).to.eq('tags') + expect(tagRepoCreateStub.calledOnceWithExactly({ name: 'tag' })).to.be.true() + expect(emPersistStub.calledTwice).to.be.true() + expect(emPersistStub.firstCall.args[0].name).to.eq('tag') + expect(emPersistStub.secondCall.args[0].tagId).to.eq(TAG_ID) + expect(emPersistStub.secondCall.args[0].taggableType).to.eq(TAGGABLE_TYPE.NODE) + expect(emPersistStub.secondCall.args[0].taggableId).to.eq(TAGGABLE_ID) + expect(emPersistStub.secondCall.args[0].taggerType).to.eq('taggerType') + expect(emPersistStub.secondCall.args[0].taggerId).to.eq(USER_ID) + expect(emPersistStub.secondCall.args[0].context).to.eq('tags') + expect(emPersistFlushStub.callCount).to.eq(2) }) it('existing tag and non existing taggings', async () => { tagRepoFindOneStub.resolves({ id: TAG_ID }) taggingRepoFindOneStub.resolves(null) emPersistStub.reset() + emPersistStub.callsFake(() => ({ flush: emPersistFlushStub })) const service = getTaggingService() await service.addTaggingForEntity('tag', 'taggerType', USER_ID, TAGGABLE_ID, TAGGABLE_TYPE.NODE) - expect(emTransactionalStub.calledOnce).to.be.true() + expect(emTransactionalStub.notCalled).to.be.true() expect(tagRepoFindOneStub.calledOnce).to.be.true() + expect(tagRepoCreateStub.notCalled).to.be.true() expect(emPersistStub.calledOnce).to.be.true() expect(emPersistStub.firstCall.args[0].tagId).to.eq(TAG_ID) expect(emPersistStub.firstCall.args[0].taggableType).to.eq(TAGGABLE_TYPE.NODE) @@ -113,6 +130,7 @@ describe('TaggingService', () => { expect(emPersistStub.firstCall.args[0].taggerType).to.eq('taggerType') expect(emPersistStub.firstCall.args[0].taggerId).to.eq(USER_ID) expect(emPersistStub.firstCall.args[0].context).to.eq('tags') + expect(emPersistFlushStub.calledOnce).to.be.true() }) it('existing tag and existing taggings', async () => { @@ -122,20 +140,21 @@ describe('TaggingService', () => { const service = getTaggingService() await service.addTaggingForEntity('tag', 'taggerType', USER_ID, TAGGABLE_ID, TAGGABLE_TYPE.NODE) - expect(emTransactionalStub.calledOnce).to.be.true() + expect(emTransactionalStub.notCalled).to.be.true() expect(tagRepoFindOneStub.calledOnce).to.be.true() + expect(tagRepoCreateStub.notCalled).to.be.true() expect(emPersistStub.notCalled).to.be.true() - expect(emPersistAndFlushStub.notCalled).to.be.true() + expect(emPersistFlushStub.notCalled).to.be.true() }) }) describe('#removeTaggings', () => { it('should remove taggings for entity with id and type', async () => { const tag = { id: 5 } - const tagging = { tag } + const tagging = { tag, tagId: tag.id } taggingRepoFindForTaggableStub.withArgs(1, TAGGABLE_TYPE.NODE).resolves([tagging]) taggingRepoCountStub.reset() - taggingRepoCountStub.withArgs({ tagId: 1 }).resolves(2) + taggingRepoCountStub.withArgs({ tagId: tag.id }).resolves(2) emRemoveStub.reset() const service = getTaggingService() @@ -168,9 +187,9 @@ describe('TaggingService', () => { expect(emTransactionalStub.calledOnce).to.be.true() expect(taggingRepoFindForTaggableStub.calledOnce).to.be.true() expect(taggingRepoFindForTaggableStub.calledWith(id, type)).to.be.true() - expect(emRemoveStub.calledTwice).to.be.true() - expect(emRemoveStub.calledWith(tag)).to.be.true() - expect(emRemoveStub.calledWith(tagging)).to.be.true() + expect(emRemoveStub.callCount).to.eq(2) + expect(emRemoveStub.firstCall.calledWith(tag)).to.be.true() + expect(emRemoveStub.secondCall.calledWith(tagging)).to.be.true() }) }) }) diff --git a/packages/server/libs/shared/test/unit/domain/user-file-create.facade.spec.ts b/packages/server/libs/shared/test/unit/domain/user-file-create.facade.spec.ts index 8998607bd..7e1abc83a 100644 --- a/packages/server/libs/shared/test/unit/domain/user-file-create.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/user-file-create.facade.spec.ts @@ -1,7 +1,10 @@ import { expect } from 'chai' import { stub } from 'sinon' +import { JobService } from '@shared/domain/job/job.service' import { PlatformFileService } from '@shared/domain/platform/service/platform-file.service' -import { UserFileService } from '@shared/domain/user-file/service/user-file.service' +import { UserService } from '@shared/domain/user/service/user.service' +import { UserContext } from '@shared/domain/user-context/model/user-context' +import { NodeService } from '@shared/domain/user-file/node.service' import { UserFile } from '@shared/domain/user-file/user-file.entity' import { FILE_STATE_DX, PARENT_TYPE } from '@shared/domain/user-file/user-file.types' import { STATIC_SCOPE } from '@shared/enums' @@ -9,11 +12,10 @@ import { InternalError } from '@shared/errors' import { FileCreate } from '@shared/facade/file-create/model/file-create' import { FileCreateWithContent } from '@shared/facade/file-create/model/file-create-with-content' import { UserFileCreateFacade } from '@shared/facade/file-create/user-file-create.facade' -import { UserCtx } from '@shared/types' describe('UserFileCreateFacade', () => { const USER_ID = 0 - const USER_CTX = { id: USER_ID } as UserCtx + const USER_CTX = { id: USER_ID } as UserContext const FILE_PARENT_TYPE = PARENT_TYPE.USER const FILE_SCOPE = STATIC_SCOPE.PRIVATE @@ -58,6 +60,8 @@ describe('UserFileCreateFacade', () => { project: PROJECT, dxid: DXID, description: DESCRIPTION, + parentFolderId: undefined, + scopedParentFolderId: undefined, }) .resolves(SERVICE_RESULT) @@ -69,13 +73,13 @@ describe('UserFileCreateFacade', () => { uploadFileContentStub.throws() }) - describe('#createFile', () => { + describe('#saveFileToDB', () => { it('should not catch error from platformCreateFile', async () => { const error = new Error('my error') platformCreateFileStub.reset() platformCreateFileStub.throws(error) - await expect(getInstance().createFile(FILE_CREATE)).to.be.rejectedWith(error) + await expect(getInstance().saveFileToDB(FILE_CREATE)).to.be.rejectedWith(error) }) it('should not catch error from serviceCreateFile', async () => { @@ -83,13 +87,13 @@ describe('UserFileCreateFacade', () => { serviceCreateFileStub.reset() serviceCreateFileStub.throws(error) - await expect(getInstance().createFile(FILE_CREATE)).to.be.rejectedWith(error) + await expect(getInstance().saveFileToDB(FILE_CREATE)).to.be.rejectedWith(error) }) it('should reject if platform returns a null dxid', async () => { platformCreateFileStub.withArgs({ name: NAME, project: PROJECT, description: DESCRIPTION }).returns({ id: null }) - await expect(getInstance().createFile(FILE_CREATE)).to.be.rejectedWith( + await expect(getInstance().saveFileToDB(FILE_CREATE)).to.be.rejectedWith( InternalError, 'Failed to create the file on the platform', ) @@ -98,14 +102,14 @@ describe('UserFileCreateFacade', () => { it('should reject if platform returns an empty response', async () => { platformCreateFileStub.withArgs({ name: NAME, project: PROJECT, description: DESCRIPTION }).returns(undefined) - await expect(getInstance().createFile(FILE_CREATE)).to.be.rejectedWith( + await expect(getInstance().saveFileToDB(FILE_CREATE)).to.be.rejectedWith( InternalError, 'Failed to create the file on the platform', ) }) it('should return correctly created file', async () => { - const res = await getInstance().createFile(FILE_CREATE) + const res = await getInstance().saveFileToDB(FILE_CREATE) expect(res).to.eq(SERVICE_RESULT) }) @@ -150,11 +154,13 @@ describe('UserFileCreateFacade', () => { createFile: platformCreateFileStub, uploadFileContent: uploadFileContentStub, } as unknown as PlatformFileService - const userFileService = { + const nodeService = { createFile: serviceCreateFileStub, closeFile: serviceCloseFileStub, - } as unknown as UserFileService + } as unknown as NodeService + const jobService = {} as unknown as JobService + const userService = {} as unknown as UserService - return new UserFileCreateFacade(USER_CTX, platformFileService, userFileService) + return new UserFileCreateFacade(USER_CTX, platformFileService, nodeService, jobService, userService) } }) diff --git a/packages/server/libs/shared/test/unit/domain/user-file.service.spec.ts b/packages/server/libs/shared/test/unit/domain/user-file.service.spec.ts index f5e6e6e61..0810f5998 100644 --- a/packages/server/libs/shared/test/unit/domain/user-file.service.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/user-file.service.spec.ts @@ -70,6 +70,7 @@ describe('UserFileService', () => { const fileRepoFindAccessibleOneStub = stub() const fileRepoFindStub = stub() const fileRepoCountStub = stub() + const fileRepoPersistAndFlushStub = stub() const fileLoadIfAccessibleByUserStub = stub() const folderRepoFindOneStub = stub() const nodeRepoFindOneOrFailStub = stub() @@ -174,6 +175,7 @@ describe('UserFileService', () => { find: fileRepoFindStub, count: fileRepoCountStub, findEditable: findEditableStub, + persistAndFlush: fileRepoPersistAndFlushStub, } as unknown as UserFileRepository const licensedItemRepo = { getLicenseItemsForNode: getLicenseItemsForNodeStub, @@ -244,6 +246,9 @@ describe('UserFileService', () => { fileRepoFindStub.reset() fileRepoFindStub.throws() + fileRepoPersistAndFlushStub.reset() + fileRepoPersistAndFlushStub.throws() + folderRepoFindOneStub.reset() folderRepoFindOneStub.throws() @@ -377,6 +382,8 @@ describe('UserFileService', () => { }) it('should create the correct UserFile', async () => { + fileRepoPersistAndFlushStub.resolves() + const res = await getInstance().createFile(FILE_CREATE) expect(res.dxid).to.eq(DXID) diff --git a/packages/server/libs/shared/test/unit/domain/user-management.service.spec.ts b/packages/server/libs/shared/test/unit/domain/user-management.service.spec.ts index c8dec96ed..71c97cfff 100644 --- a/packages/server/libs/shared/test/unit/domain/user-management.service.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/user-management.service.spec.ts @@ -1,6 +1,8 @@ import { expect } from 'chai' import { stub } from 'sinon' +import { EntityManager } from '@mikro-orm/mysql' import { ORG_EVERYONE } from '@shared/config/consts' +import { EVENT_TYPES } from '@shared/domain/event/event.entity' import { UserManagementService } from '@shared/domain/user/service/user-management.service' import { USER_STATE, User } from '@shared/domain/user/user.entity' import { UserRepository } from '@shared/domain/user/user.repository' @@ -11,9 +13,17 @@ import { createRepositoryStub } from '../../factory/repository' describe('user-management service tests', () => { const userUnlockStub = stub() const userResetMfaStub = stub() + const emPersistStub = stub() + const emPopulateStub = stub() + const loadEntityStub = stub() const userRepo = createRepositoryStub() + const em = { + persist: emPersistStub, + populate: emPopulateStub, + } as unknown as EntityManager + const getInstance = (): UserManagementService => { const platformClient = { userUnlock: userUnlockStub, @@ -21,11 +31,12 @@ describe('user-management service tests', () => { } as unknown as PlatformClient return new UserManagementService( + em, { id: 666, dxuser: 'user1', accessToken: 'access_token', - loadEntity: () => null, + loadEntity: loadEntityStub, }, userRepo as unknown as UserRepository, platformClient, @@ -36,8 +47,17 @@ describe('user-management service tests', () => { userRepo.stubs.reset() userUnlockStub.reset() userResetMfaStub.reset() + emPersistStub.reset() + emPopulateStub.reset() + loadEntityStub.reset() userUnlockStub.throws() userResetMfaStub.throws() + emPopulateStub.resolves() + loadEntityStub.resolves({ + id: 666, + dxuser: 'user1', + organization: { load: stub().resolves({ handle: 'test-org' }) }, + }) }) describe('#deactivateUsers', () => { @@ -53,6 +73,27 @@ describe('user-management service tests', () => { expect(userRepo.stubs.find.calledOnceWithExactly({ id: { $in: [1, 2] } })).to.be.true() }) + it('persists a UserDeactivated event per user', async () => { + const instance = getInstance() + + userRepo.stubs.find.resolves([ + { id: 1, userState: USER_STATE.ENABLED, dxuser: 'userA' }, + { id: 2, userState: USER_STATE.ENABLED, dxuser: 'userB' }, + ]) + + await instance.deactivateUsers([1, 2]) + + expect(emPersistStub.callCount).to.equal(2) + const event1 = emPersistStub.firstCall.firstArg + expect(event1.type).to.equal(EVENT_TYPES.USER_DEACTIVATED) + expect(event1.param1).to.equal('userA') + expect(event1.dxuser).to.equal('user1') + + const event2 = emPersistStub.secondCall.firstArg + expect(event2.type).to.equal(EVENT_TYPES.USER_DEACTIVATED) + expect(event2.param1).to.equal('userB') + }) + it('fails for themself', async () => { const instance = getInstance() diff --git a/packages/server/libs/shared/test/unit/domain/user.service.spec.ts b/packages/server/libs/shared/test/unit/domain/user.service.spec.ts index 1ecd99fcf..aa9e420b2 100644 --- a/packages/server/libs/shared/test/unit/domain/user.service.spec.ts +++ b/packages/server/libs/shared/test/unit/domain/user.service.spec.ts @@ -442,7 +442,7 @@ describe('user service tests', () => { it('lazy-backfills sso_enabled when null and persists', async () => { const user = buildUser({ sso_enabled: null }) userRepoFindOneOrFailStub.resolves(user) - platformClientGetSSOIdStub.resolves({ SSoId: 'idp-okta-123' }) + platformClientGetSSOIdStub.resolves({ SSOId: 'idp-okta-123' }) const userService = createUserService() const dto = await userService.getAdminUserDetails(99) @@ -453,10 +453,10 @@ describe('user service tests', () => { expect(dto.isSSO).to.equal(true) }) - it('records non-SSO users when platform returns empty SSoId', async () => { + it('records non-SSO users when platform returns empty SSOId', async () => { const user = buildUser({ sso_enabled: null }) userRepoFindOneOrFailStub.resolves(user) - platformClientGetSSOIdStub.resolves({ SSoId: '' }) + platformClientGetSSOIdStub.resolves({ SSOId: '' }) const userService = createUserService() const dto = await userService.getAdminUserDetails(99) diff --git a/packages/server/libs/shared/test/unit/facade/list-admin-membership.facade.spec.ts b/packages/server/libs/shared/test/unit/facade/admin-memberships-list.facade.spec.ts similarity index 90% rename from packages/server/libs/shared/test/unit/facade/list-admin-membership.facade.spec.ts rename to packages/server/libs/shared/test/unit/facade/admin-memberships-list.facade.spec.ts index b525f2aa8..8c95fa78d 100644 --- a/packages/server/libs/shared/test/unit/facade/list-admin-membership.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/facade/admin-memberships-list.facade.spec.ts @@ -4,9 +4,9 @@ import { AdminMembershipPaginationDTO } from '@shared/domain/admin-membership/dt import { UserWithAdminRolesDTO } from '@shared/domain/admin-membership/dto/user-with-admin-roles.dto' import { UserService } from '@shared/domain/user/service/user.service' import { User } from '@shared/domain/user/user.entity' -import { ListAdminMembershipFacade } from '@shared/facade/admin-membership/list-admin-membership.facade' +import { AdminMembershipsListFacade } from '@shared/facade/admin-membership/admin-memberships-list.facade' -describe('ListAdminMembershipFacade', () => { +describe('AdminMembershipsListFacade', () => { const paginateUsersWithAdminRolesStub = stub() let fromEntityStub: SinonStub @@ -26,8 +26,8 @@ describe('ListAdminMembershipFacade', () => { fromEntityStub.restore() }) - function getInstance(): ListAdminMembershipFacade { - return new ListAdminMembershipFacade(userService) + function getInstance(): AdminMembershipsListFacade { + return new AdminMembershipsListFacade(userService) } describe('#listUsersWithRoles', () => { diff --git a/packages/server/libs/shared/test/unit/facade/app-create.facade.spec.ts b/packages/server/libs/shared/test/unit/facade/app-create.facade.spec.ts index af931c5d5..376443db9 100644 --- a/packages/server/libs/shared/test/unit/facade/app-create.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/facade/app-create.facade.spec.ts @@ -14,13 +14,22 @@ import { AppSeries } from '@shared/domain/app-series/app-series.entity' import { AppSeriesRepository } from '@shared/domain/app-series/app-series.repository' import { AppSeriesCountService } from '@shared/domain/app-series/app-series-count.service' import { AppSeriesService } from '@shared/domain/app-series/service/app-series.service' +import { ComparisonRepository } from '@shared/domain/comparison/comparison.repository' import { EVENT_TYPES, Event } from '@shared/domain/event/event.entity' import { allowedInstanceTypes } from '@shared/domain/job/job.enum' +import { JobRepository } from '@shared/domain/job/job.repository' import { Organization } from '@shared/domain/org/organization.entity' import { Space } from '@shared/domain/space/space.entity' import { SPACE_TYPE } from '@shared/domain/space/space.enum' import { SpaceRepository } from '@shared/domain/space/space.repository' import { SPACE_MEMBERSHIP_ROLE, SPACE_MEMBERSHIP_SIDE } from '@shared/domain/space-membership/space-membership.enum' +import { Tag } from '@shared/domain/tag/tag.entity' +import { TagRepository } from '@shared/domain/tag/tag.repository' +import { AppSeriesTagging } from '@shared/domain/tagging/app-series-tagging.entity' +import { Tagging } from '@shared/domain/tagging/tagging.entity' +import { TaggingRepository } from '@shared/domain/tagging/tagging.repository' +import { TaggingService } from '@shared/domain/tagging/tagging.service' +import { TAGGABLE_TYPE } from '@shared/domain/tagging/tagging.types' import { User } from '@shared/domain/user/user.entity' import { UserRepository } from '@shared/domain/user/user.repository' import { UserContext } from '@shared/domain/user-context/model/user-context' @@ -69,8 +78,11 @@ describe('AppCreateFacade', () => { let nodeService: NodeService let appService: AppService let appSeriesService: AppSeriesService + let taggingService: TaggingService let appRepository: AppRepository let appSeriesRepository: AppSeriesRepository + let taggingRepository: TaggingRepository + let tagRepository: TagRepository let folderRepository: FolderRepository let nodeRepository: NodeRepository let spaceRepository: SpaceRepository @@ -91,6 +103,8 @@ describe('AppCreateFacade', () => { appRepository = em.getRepository(App) appSeriesRepository = em.getRepository(AppSeries) + taggingRepository = em.getRepository(Tagging) + tagRepository = em.getRepository(Tag) folderRepository = em.getRepository(Folder) nodeRepository = em.getRepository(Node) spaceRepository = em.getRepository(Space) @@ -112,7 +126,14 @@ describe('AppCreateFacade', () => { ;(nodeRepository as unknown as { user: UserContext }).user = userCtx ;(appRepository as unknown as { user: UserContext }).user = userCtx - nodeHelper = new NodeHelper(em, userCtx, folderRepository, nodeRepository) + nodeHelper = new NodeHelper( + em, + userCtx, + folderRepository, + nodeRepository, + {} as unknown as JobRepository, + {} as unknown as ComparisonRepository, + ) nodeService = new NodeService( em, @@ -131,6 +152,20 @@ describe('AppCreateFacade', () => { appService = new AppService(appRepository) appSeriesService = new AppSeriesService(userCtx, appSeriesRepository, {} as unknown as AppSeriesCountService) + taggingService = new TaggingService(em, taggingRepository, tagRepository) + + // Mock transactional to execute the callback directly using the same em (no forking) + stub(em, 'transactional').callsFake(async (cb) => { + await em.begin() + try { + const result = await (cb as (...args: unknown[]) => Promise)(em) + await em.commit() + return result + } catch (e) { + await em.rollback() + throw e + } + }) appletCreateStub.reset() appletCreateStub.throws() @@ -161,6 +196,22 @@ describe('AppCreateFacade', () => { appPublishStub.resolves() }) + afterEach(async () => { + // Ensure any pending transactions are rolled back so locks are released + try { + const connection = em.getConnection() + await connection.execute('ROLLBACK') + } catch { + // ignore if no transaction is active + } + // Restore transactional stub + const transactionalStub = em.transactional as ReturnType + if (transactionalStub.restore) { + transactionalStub.restore() + } + em.clear() + }) + const getDefaultApp = (): SaveAppDTO => { return { createAppSeries: true, @@ -350,6 +401,102 @@ describe('AppCreateFacade', () => { expect(loadedApp.internal.ordered_assets).to.contain.members([asset1.uid, asset2.uid]) }) + it('copies app series tags when creating a forked app', async () => { + const sourceAppSeries = create.appSeriesHelper.create(em, { user }, { name: 'source-app-series', scope: 'private' }) + await em.flush() + + const sourceApp = create.appHelper.createRegular( + em, + { user }, + { title: 'source app', scope: 'private', appSeriesId: sourceAppSeries.id }, + ) + await em.flush() + + const sourceTag = new Tag() + sourceTag.name = 'genomics' + em.persist(sourceTag) + await em.flush() + + const sourceTagging = new AppSeriesTagging() + sourceTagging.tagId = sourceTag.id + sourceTagging.taggableType = TAGGABLE_TYPE.APP_SERIES + sourceTagging.taggableId = sourceAppSeries.id + sourceTagging.taggerId = user.id + sourceTagging.taggerType = 'User' + sourceTagging.context = 'tags' + em.persist(sourceTagging) + await em.flush() + + const appCreateFacade = getInstance() + const appInput = getDefaultApp() + appInput.name = 'forked-app-with-tags' + appInput.forked_from = sourceApp.uid + + await appCreateFacade.create(appInput) + em.clear() + + const forkedAppSeries = await em.findOneOrFail( + AppSeries, + { name: appInput.name, scope: appInput.scope }, + { populate: ['taggings.tag'] }, + ) + + expect(forkedAppSeries.taggings.length).to.equal(1) + expect(forkedAppSeries.taggings[0].tag.name).to.equal(sourceTag.name) + }) + + it('rolls back copied tags when app creation fails after tag copying', async () => { + const sourceAppSeries = create.appSeriesHelper.create(em, { user }, { name: 'rollback-source', scope: 'private' }) + await em.flush() + + const sourceApp = create.appHelper.createRegular( + em, + { user }, + { title: 'rollback source app', scope: 'private', appSeriesId: sourceAppSeries.id }, + ) + await em.flush() + + const sourceTag = new Tag() + sourceTag.name = 'rollback-tag' + em.persist(sourceTag) + await em.flush() + + const sourceTagging = new AppSeriesTagging() + sourceTagging.tagId = sourceTag.id + sourceTagging.taggableType = TAGGABLE_TYPE.APP_SERIES + sourceTagging.taggableId = sourceAppSeries.id + sourceTagging.taggerId = user.id + sourceTagging.taggerType = 'User' + sourceTagging.context = 'tags' + em.persist(sourceTagging) + await em.flush() + + const appCreateFacade = getInstance() + // Sabotage: fail after tag copying to verify tx rollback semantics. + const createAppEventStub = stub(appCreateFacade as unknown as { createAppEvent: () => Promise }, 'createAppEvent') + createAppEventStub.rejects(new Error('Simulated event creation failure')) + + const appInput = getDefaultApp() + appInput.name = 'forked-app-rollback-test' + appInput.forked_from = sourceApp.uid + + await expect(appCreateFacade.create(appInput)).to.be.rejectedWith(Error) + + createAppEventStub.restore() + em.clear() + + // AppSeries and transactional app/tagging writes must all be rolled back. + const forkedAppSeries = await em.findOne(AppSeries, { name: appInput.name }) + expect(forkedAppSeries).to.be.null() + + // Verify no orphaned taggings were left behind + const allTaggings = await em.find(Tagging, { taggerId: user.id }) + const orphanedTaggings = allTaggings.filter( + t => t.taggableType === TAGGABLE_TYPE.APP_SERIES && t.taggableId !== sourceAppSeries.id, + ) + expect(orphanedTaggings).to.have.length(0) + }) + it('new revision of an app', async () => { const appCreateFacade = getInstance() @@ -687,11 +834,11 @@ describe('AppCreateFacade', () => { label, optional, default: defaultValue, - choices, + choices: choices as AppInputSpecItem['choices'], } } function getInstance(userContext: UserContext = userCtx): AppCreateFacade { - return new AppCreateFacade(em, userContext, platformClient, nodeService, appService, appSeriesService) + return new AppCreateFacade(em, userContext, platformClient, nodeService, appService, appSeriesService, taggingService) } }) diff --git a/packages/server/libs/shared/test/unit/facade/org-member-action.facade.spec.ts b/packages/server/libs/shared/test/unit/facade/org-member-action.facade.spec.ts index bbde32114..0927e7a97 100644 --- a/packages/server/libs/shared/test/unit/facade/org-member-action.facade.spec.ts +++ b/packages/server/libs/shared/test/unit/facade/org-member-action.facade.spec.ts @@ -1,19 +1,19 @@ -import { EntityManager } from '@mikro-orm/mysql'; -import { expect } from 'chai'; -import { stub } from 'sinon'; -import { OrgActionRequestService } from '@shared/domain/org-action-request/org-action-request.service'; -import { Organization } from '@shared/domain/org/organization.entity'; -import { UserContext } from '@shared/domain/user-context/model/user-context' -import { User, USER_STATE } from '@shared/domain/user/user.entity'; -import { UserService } from '@shared/domain/user/service/user.service'; -import { InvalidStateError, NotFoundError, PermissionError } from '@shared/errors'; -import { OrgMemberActionFacade } from '@shared/facade/profile/org-member-action.facade'; import { Ref } from '@mikro-orm/core' - +import { EntityManager } from '@mikro-orm/mysql' +import { expect } from 'chai' +import { stub } from 'sinon' +import { Organization } from '@shared/domain/org/organization.entity' +import { OrgActionRequestService } from '@shared/domain/org-action-request/org-action-request.service' +import { UserService } from '@shared/domain/user/service/user.service' +import { USER_STATE, User } from '@shared/domain/user/user.entity' +import { UserContext } from '@shared/domain/user-context/model/user-context' +import { InvalidStateError, NotFoundError, PermissionError } from '@shared/errors' +import { OrgMemberActionFacade } from '@shared/facade/profile/org-member-action.facade' describe('OrgMemberActionFacade', () => { const populateStub = stub() const flushStub = stub() + const persistStub = stub().returnsThis() const loadEntityStub = stub() const getUserInOrganizationStub = stub() const findPendingRemoveMemberRequestStub = stub() @@ -22,6 +22,12 @@ describe('OrgMemberActionFacade', () => { const em = { populate: populateStub, flush: flushStub, + persist: persistStub, + transactional: async (cb: (...args: unknown[]) => Promise) => { + const result = await cb(em) + await flushStub() + return result + }, } as unknown as EntityManager const userCtx = { @@ -41,11 +47,16 @@ describe('OrgMemberActionFacade', () => { id: 10, singular: false, admin: { id: 1 }, + handle: 'test-org', } as Organization const ADMIN_USER = { id: 1, - organization: { getEntity: (): Organization => ORG }, + dxuser: 'admin-user', + organization: { + getEntity: (): Organization => ORG, + load: async () => ORG, + }, } beforeEach(() => { @@ -53,6 +64,8 @@ describe('OrgMemberActionFacade', () => { populateStub.resolves() flushStub.reset() flushStub.resolves() + persistStub.reset() + persistStub.returnsThis() loadEntityStub.reset() loadEntityStub.resolves(ADMIN_USER) getUserInOrganizationStub.reset() @@ -68,7 +81,7 @@ describe('OrgMemberActionFacade', () => { describe('#deactivateOrgUser', () => { it('deactivates an enabled member', async () => { - const targetUser = { id: 5, userState: USER_STATE.ENABLED } + const targetUser = { id: 5, dxuser: 'target-user', userState: USER_STATE.ENABLED } getUserInOrganizationStub.resolves(targetUser) const facade = getInstance() @@ -123,7 +136,7 @@ describe('OrgMemberActionFacade', () => { const nonAdminUser = { id: 2, organization: { - getEntity: (): Organization => ({ id: 10, singular: false, admin: { id: 1 } as Ref } as Organization), + getEntity: (): Organization => ({ id: 10, singular: false, admin: { id: 1 } as Ref }) as Organization, }, } loadEntityStub.resolves(nonAdminUser) @@ -144,7 +157,7 @@ describe('OrgMemberActionFacade', () => { const singularUser = { id: 1, organization: { - getEntity: (): Organization => ({ id: 20, singular: true, admin: { id: 1 } as Ref } as Organization), + getEntity: (): Organization => ({ id: 20, singular: true, admin: { id: 1 } as Ref }) as Organization, }, } loadEntityStub.resolves(singularUser) @@ -220,7 +233,7 @@ describe('OrgMemberActionFacade', () => { const nonAdminUser = { id: 2, organization: { - getEntity: (): Organization => ({ id: 10, singular: false, admin: { id: 1 } as Ref } as Organization), + getEntity: (): Organization => ({ id: 10, singular: false, admin: { id: 1 } as Ref }) as Organization, }, } loadEntityStub.resolves(nonAdminUser)