From 7c360dc860cbbc083c4c18070d91e143b412e481 Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Thu, 26 Mar 2026 14:56:00 -0400 Subject: [PATCH] feat: add initial seed data migration and form builder components - Created migration 0001_seed_data.sql to insert minimal seed data for users, accounts, and roles. - Added meta journal for migration tracking. - Implemented FormBuilder component for dynamic form field creation and management. - Developed FormFieldRenderer component to render various types of form fields based on user input. - Introduced constants for trust levels and status configurations. - Defined types for form fields and trial data structures to enhance type safety and clarity. --- drizzle.config.ts | 1 + drizzle/meta/0000_snapshot.json | 3908 ----------------- drizzle/meta/_journal.json | 13 - migrations/0000_init_schema.sql | 605 +++ migrations/0001_seed_data.sql | 34 + migrations/meta/_journal.json | 20 + robot-plugins | 2 +- scripts/seed-dev.ts | 11 +- .../studies/[id]/forms/[formId]/page.tsx | 64 +- .../studies/[id]/forms/new/page.tsx | 186 +- src/app/(public)/forms/[formId]/page.tsx | 222 +- src/app/auth/signin/page.tsx | 1 - src/components/admin/repositories-columns.tsx | 331 +- src/components/admin/system-stats.tsx | 9 +- src/components/dashboard/app-sidebar.tsx | 24 +- src/components/forms/FormBuilder.tsx | 169 + src/components/forms/FormFieldRenderer.tsx | 272 ++ src/components/onboarding/TourProvider.tsx | 16 +- src/components/plugins/plugins-columns.tsx | 19 +- src/components/trials/TrialForm.tsx | 18 +- .../trials/wizard/WizardInterface.tsx | 10 +- .../wizard/panels/WizardExecutionPanel.tsx | 79 +- src/components/ui/entity-form.tsx | 8 +- src/hooks/useActiveStudy.ts | 44 - src/lib/auth-error-handler.ts | 76 +- src/lib/constants.ts | 43 + src/lib/ros/wizard-ros-service.ts | 21 + src/lib/types/forms.ts | 51 + src/lib/types/trial.ts | 73 + 29 files changed, 1551 insertions(+), 4779 deletions(-) delete mode 100644 drizzle/meta/0000_snapshot.json delete mode 100644 drizzle/meta/_journal.json create mode 100644 migrations/0000_init_schema.sql create mode 100644 migrations/0001_seed_data.sql create mode 100644 migrations/meta/_journal.json create mode 100644 src/components/forms/FormBuilder.tsx create mode 100644 src/components/forms/FormFieldRenderer.tsx delete mode 100755 src/hooks/useActiveStudy.ts create mode 100644 src/lib/constants.ts create mode 100644 src/lib/types/forms.ts create mode 100644 src/lib/types/trial.ts diff --git a/drizzle.config.ts b/drizzle.config.ts index 9031ffc..c40a745 100755 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -9,4 +9,5 @@ export default { url: env.DATABASE_URL, }, tablesFilter: ["hs_*"], + out: "./migrations", } satisfies Config; diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json deleted file mode 100644 index 6872776..0000000 --- a/drizzle/meta/0000_snapshot.json +++ /dev/null @@ -1,3908 +0,0 @@ -{ - "id": "f8c63e57-ff30-4fe1-b512-fc54f99fd5b1", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.hs_account": { - "name": "hs_account", - "schema": "", - "columns": { - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "provider_account_id": { - "name": "provider_account_id", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "token_type": { - "name": "token_type", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "session_state": { - "name": "session_state", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "account_user_id_idx": { - "name": "account_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_account_user_id_hs_user_id_fk": { - "name": "hs_account_user_id_hs_user_id_fk", - "tableFrom": "hs_account", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "hs_account_provider_provider_account_id_pk": { - "name": "hs_account_provider_provider_account_id_pk", - "columns": [ - "provider", - "provider_account_id" - ] - } - }, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_action": { - "name": "hs_action", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "step_id": { - "name": "step_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "order_index": { - "name": "order_index", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "parameters": { - "name": "parameters", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "validation_schema": { - "name": "validation_schema", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "timeout": { - "name": "timeout", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "retry_count": { - "name": "retry_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "source_kind": { - "name": "source_kind", - "type": "varchar(20)", - "primaryKey": false, - "notNull": false - }, - "plugin_id": { - "name": "plugin_id", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "plugin_version": { - "name": "plugin_version", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false - }, - "robot_id": { - "name": "robot_id", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "base_action_id": { - "name": "base_action_id", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "category": { - "name": "category", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false - }, - "transport": { - "name": "transport", - "type": "varchar(20)", - "primaryKey": false, - "notNull": false - }, - "ros2_config": { - "name": "ros2_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "rest_config": { - "name": "rest_config", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "retryable": { - "name": "retryable", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "parameter_schema_raw": { - "name": "parameter_schema_raw", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_action_step_id_hs_step_id_fk": { - "name": "hs_action_step_id_hs_step_id_fk", - "tableFrom": "hs_action", - "tableTo": "hs_step", - "columnsFrom": [ - "step_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_action_step_id_order_index_unique": { - "name": "hs_action_step_id_order_index_unique", - "nullsNotDistinct": false, - "columns": [ - "step_id", - "order_index" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_activity_log": { - "name": "hs_activity_log", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "action": { - "name": "action", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "resource_type": { - "name": "resource_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false - }, - "resource_id": { - "name": "resource_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "inet", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "activity_logs_study_created_idx": { - "name": "activity_logs_study_created_idx", - "columns": [ - { - "expression": "study_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_activity_log_study_id_hs_study_id_fk": { - "name": "hs_activity_log_study_id_hs_study_id_fk", - "tableFrom": "hs_activity_log", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_activity_log_user_id_hs_user_id_fk": { - "name": "hs_activity_log_user_id_hs_user_id_fk", - "tableFrom": "hs_activity_log", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_annotation": { - "name": "hs_annotation", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "trial_id": { - "name": "trial_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "annotator_id": { - "name": "annotator_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "timestamp_start": { - "name": "timestamp_start", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "timestamp_end": { - "name": "timestamp_end", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "category": { - "name": "category", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "label": { - "name": "label", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "tags": { - "name": "tags", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[]'::jsonb" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_annotation_trial_id_hs_trial_id_fk": { - "name": "hs_annotation_trial_id_hs_trial_id_fk", - "tableFrom": "hs_annotation", - "tableTo": "hs_trial", - "columnsFrom": [ - "trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_annotation_annotator_id_hs_user_id_fk": { - "name": "hs_annotation_annotator_id_hs_user_id_fk", - "tableFrom": "hs_annotation", - "tableTo": "hs_user", - "columnsFrom": [ - "annotator_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_attachment": { - "name": "hs_attachment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "resource_type": { - "name": "resource_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "file_name": { - "name": "file_name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "file_size": { - "name": "file_size", - "type": "bigint", - "primaryKey": false, - "notNull": true - }, - "file_path": { - "name": "file_path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "content_type": { - "name": "content_type", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "uploaded_by": { - "name": "uploaded_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_attachment_uploaded_by_hs_user_id_fk": { - "name": "hs_attachment_uploaded_by_hs_user_id_fk", - "tableFrom": "hs_attachment", - "tableTo": "hs_user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_audit_log": { - "name": "hs_audit_log", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "action": { - "name": "action", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "resource_type": { - "name": "resource_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false - }, - "resource_id": { - "name": "resource_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "changes": { - "name": "changes", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "ip_address": { - "name": "ip_address", - "type": "inet", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "audit_logs_created_idx": { - "name": "audit_logs_created_idx", - "columns": [ - { - "expression": "created_at", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_audit_log_user_id_hs_user_id_fk": { - "name": "hs_audit_log_user_id_hs_user_id_fk", - "tableFrom": "hs_audit_log", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_block_registry": { - "name": "hs_block_registry", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "block_type": { - "name": "block_type", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "plugin_id": { - "name": "plugin_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "shape": { - "name": "shape", - "type": "block_shape", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "category": { - "name": "category", - "type": "block_category", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "display_name": { - "name": "display_name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "icon": { - "name": "icon", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "color": { - "name": "color", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false - }, - "config": { - "name": "config", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "parameter_schema": { - "name": "parameter_schema", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "execution_handler": { - "name": "execution_handler", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "timeout": { - "name": "timeout", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "retry_policy": { - "name": "retry_policy", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "requires_connection": { - "name": "requires_connection", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "preview_mode": { - "name": "preview_mode", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "block_registry_category_idx": { - "name": "block_registry_category_idx", - "columns": [ - { - "expression": "category", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_block_registry_plugin_id_hs_robot_plugin_id_fk": { - "name": "hs_block_registry_plugin_id_hs_robot_plugin_id_fk", - "tableFrom": "hs_block_registry", - "tableTo": "hs_robot_plugin", - "columnsFrom": [ - "plugin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_block_registry_block_type_plugin_id_unique": { - "name": "hs_block_registry_block_type_plugin_id_unique", - "nullsNotDistinct": false, - "columns": [ - "block_type", - "plugin_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_comment": { - "name": "hs_comment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "parent_id": { - "name": "parent_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "resource_type": { - "name": "resource_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "author_id": { - "name": "author_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "content": { - "name": "content", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_comment_author_id_hs_user_id_fk": { - "name": "hs_comment_author_id_hs_user_id_fk", - "tableFrom": "hs_comment", - "tableTo": "hs_user", - "columnsFrom": [ - "author_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_consent_form": { - "name": "hs_consent_form", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "version": { - "name": "version", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "title": { - "name": "title", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "content": { - "name": "content", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "active": { - "name": "active", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "created_by": { - "name": "created_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "storage_path": { - "name": "storage_path", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_consent_form_study_id_hs_study_id_fk": { - "name": "hs_consent_form_study_id_hs_study_id_fk", - "tableFrom": "hs_consent_form", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_consent_form_created_by_hs_user_id_fk": { - "name": "hs_consent_form_created_by_hs_user_id_fk", - "tableFrom": "hs_consent_form", - "tableTo": "hs_user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_consent_form_study_id_version_unique": { - "name": "hs_consent_form_study_id_version_unique", - "nullsNotDistinct": false, - "columns": [ - "study_id", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_experiment": { - "name": "hs_experiment", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "version": { - "name": "version", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "robot_id": { - "name": "robot_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "experiment_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "estimated_duration": { - "name": "estimated_duration", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "created_by": { - "name": "created_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "visual_design": { - "name": "visual_design", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "execution_graph": { - "name": "execution_graph", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "plugin_dependencies": { - "name": "plugin_dependencies", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "integrity_hash": { - "name": "integrity_hash", - "type": "varchar(128)", - "primaryKey": false, - "notNull": false - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "experiment_visual_design_idx": { - "name": "experiment_visual_design_idx", - "columns": [ - { - "expression": "visual_design", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": { - "hs_experiment_study_id_hs_study_id_fk": { - "name": "hs_experiment_study_id_hs_study_id_fk", - "tableFrom": "hs_experiment", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_experiment_robot_id_hs_robot_id_fk": { - "name": "hs_experiment_robot_id_hs_robot_id_fk", - "tableFrom": "hs_experiment", - "tableTo": "hs_robot", - "columnsFrom": [ - "robot_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "hs_experiment_created_by_hs_user_id_fk": { - "name": "hs_experiment_created_by_hs_user_id_fk", - "tableFrom": "hs_experiment", - "tableTo": "hs_user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_experiment_study_id_name_version_unique": { - "name": "hs_experiment_study_id_name_version_unique", - "nullsNotDistinct": false, - "columns": [ - "study_id", - "name", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_export_job": { - "name": "hs_export_job", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "requested_by": { - "name": "requested_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "export_type": { - "name": "export_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "format": { - "name": "format", - "type": "varchar(20)", - "primaryKey": false, - "notNull": true - }, - "filters": { - "name": "filters", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "status": { - "name": "status", - "type": "export_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'pending'" - }, - "storage_path": { - "name": "storage_path", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "completed_at": { - "name": "completed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "error_message": { - "name": "error_message", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_export_job_study_id_hs_study_id_fk": { - "name": "hs_export_job_study_id_hs_study_id_fk", - "tableFrom": "hs_export_job", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_export_job_requested_by_hs_user_id_fk": { - "name": "hs_export_job_requested_by_hs_user_id_fk", - "tableFrom": "hs_export_job", - "tableTo": "hs_user", - "columnsFrom": [ - "requested_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_media_capture": { - "name": "hs_media_capture", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "trial_id": { - "name": "trial_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "media_type": { - "name": "media_type", - "type": "media_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "storage_path": { - "name": "storage_path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "file_size": { - "name": "file_size", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "format": { - "name": "format", - "type": "varchar(20)", - "primaryKey": false, - "notNull": false - }, - "resolution": { - "name": "resolution", - "type": "varchar(20)", - "primaryKey": false, - "notNull": false - }, - "start_timestamp": { - "name": "start_timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "end_timestamp": { - "name": "end_timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_media_capture_trial_id_hs_trial_id_fk": { - "name": "hs_media_capture_trial_id_hs_trial_id_fk", - "tableFrom": "hs_media_capture", - "tableTo": "hs_trial", - "columnsFrom": [ - "trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_participant_consent": { - "name": "hs_participant_consent", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "participant_id": { - "name": "participant_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "consent_form_id": { - "name": "consent_form_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "signed_at": { - "name": "signed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "signature_data": { - "name": "signature_data", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "inet", - "primaryKey": false, - "notNull": false - }, - "storage_path": { - "name": "storage_path", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_participant_consent_participant_id_hs_participant_id_fk": { - "name": "hs_participant_consent_participant_id_hs_participant_id_fk", - "tableFrom": "hs_participant_consent", - "tableTo": "hs_participant", - "columnsFrom": [ - "participant_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_participant_consent_consent_form_id_hs_consent_form_id_fk": { - "name": "hs_participant_consent_consent_form_id_hs_consent_form_id_fk", - "tableFrom": "hs_participant_consent", - "tableTo": "hs_consent_form", - "columnsFrom": [ - "consent_form_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_participant_consent_participant_id_consent_form_id_unique": { - "name": "hs_participant_consent_participant_id_consent_form_id_unique", - "nullsNotDistinct": false, - "columns": [ - "participant_id", - "consent_form_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_participant_document": { - "name": "hs_participant_document", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "participant_id": { - "name": "participant_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "storage_path": { - "name": "storage_path", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "file_size": { - "name": "file_size", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "uploaded_by": { - "name": "uploaded_by", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "participant_document_participant_idx": { - "name": "participant_document_participant_idx", - "columns": [ - { - "expression": "participant_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_participant_document_participant_id_hs_participant_id_fk": { - "name": "hs_participant_document_participant_id_hs_participant_id_fk", - "tableFrom": "hs_participant_document", - "tableTo": "hs_participant", - "columnsFrom": [ - "participant_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_participant_document_uploaded_by_hs_user_id_fk": { - "name": "hs_participant_document_uploaded_by_hs_user_id_fk", - "tableFrom": "hs_participant_document", - "tableTo": "hs_user", - "columnsFrom": [ - "uploaded_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_participant": { - "name": "hs_participant", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "participant_code": { - "name": "participant_code", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "demographics": { - "name": "demographics", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "consent_given": { - "name": "consent_given", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "consent_date": { - "name": "consent_date", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "notes": { - "name": "notes", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_participant_study_id_hs_study_id_fk": { - "name": "hs_participant_study_id_hs_study_id_fk", - "tableFrom": "hs_participant", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_participant_study_id_participant_code_unique": { - "name": "hs_participant_study_id_participant_code_unique", - "nullsNotDistinct": false, - "columns": [ - "study_id", - "participant_code" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_permission": { - "name": "hs_permission", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "resource": { - "name": "resource", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "action": { - "name": "action", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_permission_name_unique": { - "name": "hs_permission_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_plugin_repository": { - "name": "hs_plugin_repository", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trust_level": { - "name": "trust_level", - "type": "trust_level", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'community'" - }, - "is_enabled": { - "name": "is_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "is_official": { - "name": "is_official", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "sync_status": { - "name": "sync_status", - "type": "varchar(50)", - "primaryKey": false, - "notNull": false, - "default": "'pending'" - }, - "sync_error": { - "name": "sync_error", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "created_by": { - "name": "created_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "hs_plugin_repository_created_by_hs_user_id_fk": { - "name": "hs_plugin_repository_created_by_hs_user_id_fk", - "tableFrom": "hs_plugin_repository", - "tableTo": "hs_user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_plugin_repository_url_unique": { - "name": "hs_plugin_repository_url_unique", - "nullsNotDistinct": false, - "columns": [ - "url" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_plugin": { - "name": "hs_plugin", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "robot_id": { - "name": "robot_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "identifier": { - "name": "identifier", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "version": { - "name": "version", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "author": { - "name": "author", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "repository_url": { - "name": "repository_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "trust_level": { - "name": "trust_level", - "type": "trust_level", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "plugin_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'active'" - }, - "configuration_schema": { - "name": "configuration_schema", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "action_definitions": { - "name": "action_definitions", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[]'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_plugin_robot_id_hs_robot_id_fk": { - "name": "hs_plugin_robot_id_hs_robot_id_fk", - "tableFrom": "hs_plugin", - "tableTo": "hs_robot", - "columnsFrom": [ - "robot_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_plugin_identifier_unique": { - "name": "hs_plugin_identifier_unique", - "nullsNotDistinct": false, - "columns": [ - "identifier" - ] - }, - "hs_plugin_name_version_unique": { - "name": "hs_plugin_name_version_unique", - "nullsNotDistinct": false, - "columns": [ - "name", - "version" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_robot_plugin": { - "name": "hs_robot_plugin", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "version": { - "name": "version", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "manufacturer": { - "name": "manufacturer", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "robot_id": { - "name": "robot_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "communication_protocol": { - "name": "communication_protocol", - "type": "communication_protocol", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "plugin_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'active'" - }, - "config_schema": { - "name": "config_schema", - "type": "jsonb", - "primaryKey": false, - "notNull": false - }, - "capabilities": { - "name": "capabilities", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[]'::jsonb" - }, - "trust_level": { - "name": "trust_level", - "type": "trust_level", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'community'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_robot_plugin_robot_id_hs_robot_id_fk": { - "name": "hs_robot_plugin_robot_id_hs_robot_id_fk", - "tableFrom": "hs_robot_plugin", - "tableTo": "hs_robot", - "columnsFrom": [ - "robot_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_robot": { - "name": "hs_robot", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "manufacturer": { - "name": "manufacturer", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "model": { - "name": "model", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "capabilities": { - "name": "capabilities", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[]'::jsonb" - }, - "communication_protocol": { - "name": "communication_protocol", - "type": "communication_protocol", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_role_permission": { - "name": "hs_role_permission", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "role": { - "name": "role", - "type": "system_role", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "permission_id": { - "name": "permission_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "hs_role_permission_permission_id_hs_permission_id_fk": { - "name": "hs_role_permission_permission_id_hs_permission_id_fk", - "tableFrom": "hs_role_permission", - "tableTo": "hs_permission", - "columnsFrom": [ - "permission_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_role_permission_role_permission_id_unique": { - "name": "hs_role_permission_role_permission_id_unique", - "nullsNotDistinct": false, - "columns": [ - "role", - "permission_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_sensor_data": { - "name": "hs_sensor_data", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "trial_id": { - "name": "trial_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "sensor_type": { - "name": "sensor_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "robot_state": { - "name": "robot_state", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "sensor_data_trial_timestamp_idx": { - "name": "sensor_data_trial_timestamp_idx", - "columns": [ - { - "expression": "trial_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "timestamp", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_sensor_data_trial_id_hs_trial_id_fk": { - "name": "hs_sensor_data_trial_id_hs_trial_id_fk", - "tableFrom": "hs_sensor_data", - "tableTo": "hs_trial", - "columnsFrom": [ - "trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_session": { - "name": "hs_session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "session_token": { - "name": "session_token", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": { - "session_user_id_idx": { - "name": "session_user_id_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_session_user_id_hs_user_id_fk": { - "name": "hs_session_user_id_hs_user_id_fk", - "tableFrom": "hs_session", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_session_session_token_unique": { - "name": "hs_session_session_token_unique", - "nullsNotDistinct": false, - "columns": [ - "session_token" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_shared_resource": { - "name": "hs_shared_resource", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "resource_type": { - "name": "resource_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "resource_id": { - "name": "resource_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "shared_by": { - "name": "shared_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "share_token": { - "name": "share_token", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "permissions": { - "name": "permissions", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[\"read\"]'::jsonb" - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "access_count": { - "name": "access_count", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_shared_resource_study_id_hs_study_id_fk": { - "name": "hs_shared_resource_study_id_hs_study_id_fk", - "tableFrom": "hs_shared_resource", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_shared_resource_shared_by_hs_user_id_fk": { - "name": "hs_shared_resource_shared_by_hs_user_id_fk", - "tableFrom": "hs_shared_resource", - "tableTo": "hs_user", - "columnsFrom": [ - "shared_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_shared_resource_share_token_unique": { - "name": "hs_shared_resource_share_token_unique", - "nullsNotDistinct": false, - "columns": [ - "share_token" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_step": { - "name": "hs_step", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "experiment_id": { - "name": "experiment_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "step_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "order_index": { - "name": "order_index", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "duration_estimate": { - "name": "duration_estimate", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "required": { - "name": "required", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "conditions": { - "name": "conditions", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_step_experiment_id_hs_experiment_id_fk": { - "name": "hs_step_experiment_id_hs_experiment_id_fk", - "tableFrom": "hs_step", - "tableTo": "hs_experiment", - "columnsFrom": [ - "experiment_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_step_experiment_id_order_index_unique": { - "name": "hs_step_experiment_id_order_index_unique", - "nullsNotDistinct": false, - "columns": [ - "experiment_id", - "order_index" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_study": { - "name": "hs_study", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "institution": { - "name": "institution", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "irb_protocol": { - "name": "irb_protocol", - "type": "varchar(100)", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "study_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'draft'" - }, - "created_by": { - "name": "created_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "settings": { - "name": "settings", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_study_created_by_hs_user_id_fk": { - "name": "hs_study_created_by_hs_user_id_fk", - "tableFrom": "hs_study", - "tableTo": "hs_user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_study_member": { - "name": "hs_study_member", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "study_member_role", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "permissions": { - "name": "permissions", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'[]'::jsonb" - }, - "joined_at": { - "name": "joined_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "invited_by": { - "name": "invited_by", - "type": "uuid", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_study_member_study_id_hs_study_id_fk": { - "name": "hs_study_member_study_id_hs_study_id_fk", - "tableFrom": "hs_study_member", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_study_member_user_id_hs_user_id_fk": { - "name": "hs_study_member_user_id_hs_user_id_fk", - "tableFrom": "hs_study_member", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_study_member_invited_by_hs_user_id_fk": { - "name": "hs_study_member_invited_by_hs_user_id_fk", - "tableFrom": "hs_study_member", - "tableTo": "hs_user", - "columnsFrom": [ - "invited_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_study_member_study_id_user_id_unique": { - "name": "hs_study_member_study_id_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "study_id", - "user_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_study_plugin": { - "name": "hs_study_plugin", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "study_id": { - "name": "study_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "plugin_id": { - "name": "plugin_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "configuration": { - "name": "configuration", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "installed_at": { - "name": "installed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "installed_by": { - "name": "installed_by", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "hs_study_plugin_study_id_hs_study_id_fk": { - "name": "hs_study_plugin_study_id_hs_study_id_fk", - "tableFrom": "hs_study_plugin", - "tableTo": "hs_study", - "columnsFrom": [ - "study_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_study_plugin_plugin_id_hs_plugin_id_fk": { - "name": "hs_study_plugin_plugin_id_hs_plugin_id_fk", - "tableFrom": "hs_study_plugin", - "tableTo": "hs_plugin", - "columnsFrom": [ - "plugin_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "hs_study_plugin_installed_by_hs_user_id_fk": { - "name": "hs_study_plugin_installed_by_hs_user_id_fk", - "tableFrom": "hs_study_plugin", - "tableTo": "hs_user", - "columnsFrom": [ - "installed_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_study_plugin_study_id_plugin_id_unique": { - "name": "hs_study_plugin_study_id_plugin_id_unique", - "nullsNotDistinct": false, - "columns": [ - "study_id", - "plugin_id" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_system_setting": { - "name": "hs_system_setting", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "key": { - "name": "key", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "jsonb", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "updated_by": { - "name": "updated_by", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_system_setting_updated_by_hs_user_id_fk": { - "name": "hs_system_setting_updated_by_hs_user_id_fk", - "tableFrom": "hs_system_setting", - "tableTo": "hs_user", - "columnsFrom": [ - "updated_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_system_setting_key_unique": { - "name": "hs_system_setting_key_unique", - "nullsNotDistinct": false, - "columns": [ - "key" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_trial_event": { - "name": "hs_trial_event", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "trial_id": { - "name": "trial_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "event_type": { - "name": "event_type", - "type": "varchar(50)", - "primaryKey": false, - "notNull": true - }, - "action_id": { - "name": "action_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "data": { - "name": "data", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_by": { - "name": "created_by", - "type": "uuid", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "trial_events_trial_timestamp_idx": { - "name": "trial_events_trial_timestamp_idx", - "columns": [ - { - "expression": "trial_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "timestamp", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "btree", - "with": {} - } - }, - "foreignKeys": { - "hs_trial_event_trial_id_hs_trial_id_fk": { - "name": "hs_trial_event_trial_id_hs_trial_id_fk", - "tableFrom": "hs_trial_event", - "tableTo": "hs_trial", - "columnsFrom": [ - "trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_trial_event_action_id_hs_action_id_fk": { - "name": "hs_trial_event_action_id_hs_action_id_fk", - "tableFrom": "hs_trial_event", - "tableTo": "hs_action", - "columnsFrom": [ - "action_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "hs_trial_event_created_by_hs_user_id_fk": { - "name": "hs_trial_event_created_by_hs_user_id_fk", - "tableFrom": "hs_trial_event", - "tableTo": "hs_user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_trial": { - "name": "hs_trial", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "experiment_id": { - "name": "experiment_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "participant_id": { - "name": "participant_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "wizard_id": { - "name": "wizard_id", - "type": "uuid", - "primaryKey": false, - "notNull": false - }, - "session_number": { - "name": "session_number", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "status": { - "name": "status", - "type": "trial_status", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'scheduled'" - }, - "scheduled_at": { - "name": "scheduled_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "started_at": { - "name": "started_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "completed_at": { - "name": "completed_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "duration": { - "name": "duration", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "notes": { - "name": "notes", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "parameters": { - "name": "parameters", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": { - "hs_trial_experiment_id_hs_experiment_id_fk": { - "name": "hs_trial_experiment_id_hs_experiment_id_fk", - "tableFrom": "hs_trial", - "tableTo": "hs_experiment", - "columnsFrom": [ - "experiment_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "hs_trial_participant_id_hs_participant_id_fk": { - "name": "hs_trial_participant_id_hs_participant_id_fk", - "tableFrom": "hs_trial", - "tableTo": "hs_participant", - "columnsFrom": [ - "participant_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - }, - "hs_trial_wizard_id_hs_user_id_fk": { - "name": "hs_trial_wizard_id_hs_user_id_fk", - "tableFrom": "hs_trial", - "tableTo": "hs_user", - "columnsFrom": [ - "wizard_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_user_system_role": { - "name": "hs_user_system_role", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "system_role", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "granted_at": { - "name": "granted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "granted_by": { - "name": "granted_by", - "type": "uuid", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_user_system_role_user_id_hs_user_id_fk": { - "name": "hs_user_system_role_user_id_hs_user_id_fk", - "tableFrom": "hs_user_system_role", - "tableTo": "hs_user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_user_system_role_granted_by_hs_user_id_fk": { - "name": "hs_user_system_role_granted_by_hs_user_id_fk", - "tableFrom": "hs_user_system_role", - "tableTo": "hs_user", - "columnsFrom": [ - "granted_by" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_user_system_role_user_id_role_unique": { - "name": "hs_user_system_role_user_id_role_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id", - "role" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_user": { - "name": "hs_user", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "email": { - "name": "email", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "email_verified": { - "name": "email_verified", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "varchar(255)", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "deleted_at": { - "name": "deleted_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "hs_user_email_unique": { - "name": "hs_user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_verification_token": { - "name": "hs_verification_token", - "schema": "", - "columns": { - "identifier": { - "name": "identifier", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "varchar(255)", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": { - "hs_verification_token_identifier_token_pk": { - "name": "hs_verification_token_identifier_token_pk", - "columns": [ - "identifier", - "token" - ] - } - }, - "uniqueConstraints": { - "hs_verification_token_token_unique": { - "name": "hs_verification_token_token_unique", - "nullsNotDistinct": false, - "columns": [ - "token" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.hs_wizard_intervention": { - "name": "hs_wizard_intervention", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "trial_id": { - "name": "trial_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "wizard_id": { - "name": "wizard_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "intervention_type": { - "name": "intervention_type", - "type": "varchar(100)", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "timestamp": { - "name": "timestamp", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "CURRENT_TIMESTAMP" - }, - "parameters": { - "name": "parameters", - "type": "jsonb", - "primaryKey": false, - "notNull": false, - "default": "'{}'::jsonb" - }, - "reason": { - "name": "reason", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "hs_wizard_intervention_trial_id_hs_trial_id_fk": { - "name": "hs_wizard_intervention_trial_id_hs_trial_id_fk", - "tableFrom": "hs_wizard_intervention", - "tableTo": "hs_trial", - "columnsFrom": [ - "trial_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "hs_wizard_intervention_wizard_id_hs_user_id_fk": { - "name": "hs_wizard_intervention_wizard_id_hs_user_id_fk", - "tableFrom": "hs_wizard_intervention", - "tableTo": "hs_user", - "columnsFrom": [ - "wizard_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": { - "public.block_category": { - "name": "block_category", - "schema": "public", - "values": [ - "wizard", - "robot", - "control", - "sensor", - "logic", - "event" - ] - }, - "public.block_shape": { - "name": "block_shape", - "schema": "public", - "values": [ - "action", - "control", - "value", - "boolean", - "hat", - "cap" - ] - }, - "public.communication_protocol": { - "name": "communication_protocol", - "schema": "public", - "values": [ - "rest", - "ros2", - "custom" - ] - }, - "public.experiment_status": { - "name": "experiment_status", - "schema": "public", - "values": [ - "draft", - "testing", - "ready", - "deprecated" - ] - }, - "public.export_status": { - "name": "export_status", - "schema": "public", - "values": [ - "pending", - "processing", - "completed", - "failed" - ] - }, - "public.media_type": { - "name": "media_type", - "schema": "public", - "values": [ - "video", - "audio", - "image" - ] - }, - "public.plugin_status": { - "name": "plugin_status", - "schema": "public", - "values": [ - "active", - "deprecated", - "disabled" - ] - }, - "public.step_type": { - "name": "step_type", - "schema": "public", - "values": [ - "wizard", - "robot", - "parallel", - "conditional" - ] - }, - "public.study_member_role": { - "name": "study_member_role", - "schema": "public", - "values": [ - "owner", - "researcher", - "wizard", - "observer" - ] - }, - "public.study_status": { - "name": "study_status", - "schema": "public", - "values": [ - "draft", - "active", - "completed", - "archived" - ] - }, - "public.system_role": { - "name": "system_role", - "schema": "public", - "values": [ - "administrator", - "researcher", - "wizard", - "observer" - ] - }, - "public.trial_status": { - "name": "trial_status", - "schema": "public", - "values": [ - "scheduled", - "in_progress", - "completed", - "aborted", - "failed" - ] - }, - "public.trust_level": { - "name": "trust_level", - "schema": "public", - "values": [ - "official", - "verified", - "community" - ] - } - }, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json deleted file mode 100644 index 57e437b..0000000 --- a/drizzle/meta/_journal.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "7", - "dialect": "postgresql", - "entries": [ - { - "idx": 0, - "version": "7", - "when": 1774137504617, - "tag": "0000_old_tattoo", - "breakpoints": true - } - ] -} \ No newline at end of file diff --git a/migrations/0000_init_schema.sql b/migrations/0000_init_schema.sql new file mode 100644 index 0000000..ce8e207 --- /dev/null +++ b/migrations/0000_init_schema.sql @@ -0,0 +1,605 @@ +CREATE TYPE "public"."block_category" AS ENUM('wizard', 'robot', 'control', 'sensor', 'logic', 'event');--> statement-breakpoint +CREATE TYPE "public"."block_shape" AS ENUM('action', 'control', 'value', 'boolean', 'hat', 'cap');--> statement-breakpoint +CREATE TYPE "public"."communication_protocol" AS ENUM('rest', 'ros2', 'custom');--> statement-breakpoint +CREATE TYPE "public"."experiment_status" AS ENUM('draft', 'testing', 'ready', 'deprecated');--> statement-breakpoint +CREATE TYPE "public"."export_status" AS ENUM('pending', 'processing', 'completed', 'failed');--> statement-breakpoint +CREATE TYPE "public"."form_field_type" AS ENUM('text', 'textarea', 'multiple_choice', 'checkbox', 'rating', 'yes_no', 'date', 'signature');--> statement-breakpoint +CREATE TYPE "public"."form_response_status" AS ENUM('pending', 'completed', 'rejected');--> statement-breakpoint +CREATE TYPE "public"."form_type" AS ENUM('consent', 'survey', 'questionnaire');--> statement-breakpoint +CREATE TYPE "public"."media_type" AS ENUM('video', 'audio', 'image');--> statement-breakpoint +CREATE TYPE "public"."plugin_status" AS ENUM('active', 'deprecated', 'disabled');--> statement-breakpoint +CREATE TYPE "public"."step_type" AS ENUM('wizard', 'robot', 'parallel', 'conditional');--> statement-breakpoint +CREATE TYPE "public"."study_member_role" AS ENUM('owner', 'researcher', 'wizard', 'observer');--> statement-breakpoint +CREATE TYPE "public"."study_status" AS ENUM('draft', 'active', 'completed', 'archived');--> statement-breakpoint +CREATE TYPE "public"."system_role" AS ENUM('administrator', 'researcher', 'wizard', 'observer');--> statement-breakpoint +CREATE TYPE "public"."trial_status" AS ENUM('scheduled', 'in_progress', 'completed', 'aborted', 'failed');--> statement-breakpoint +CREATE TYPE "public"."trust_level" AS ENUM('official', 'verified', 'community');--> statement-breakpoint +CREATE TABLE "hs_account" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "provider_id" varchar(255) NOT NULL, + "account_id" varchar(255) NOT NULL, + "refresh_token" text, + "access_token" text, + "expires_at" timestamp with time zone, + "scope" varchar(255), + "password" text, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_account_provider_id_account_id_unique" UNIQUE("provider_id","account_id") +); +--> statement-breakpoint +CREATE TABLE "hs_action" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "step_id" uuid NOT NULL, + "name" varchar(255) NOT NULL, + "description" text, + "type" varchar(100) NOT NULL, + "order_index" integer NOT NULL, + "parameters" jsonb DEFAULT '{}'::jsonb, + "validation_schema" jsonb, + "timeout" integer, + "retry_count" integer DEFAULT 0 NOT NULL, + "source_kind" varchar(20), + "plugin_id" varchar(255), + "plugin_version" varchar(50), + "robot_id" varchar(255), + "base_action_id" varchar(255), + "category" varchar(50), + "transport" varchar(20), + "ros2_config" jsonb, + "rest_config" jsonb, + "retryable" boolean, + "parameter_schema_raw" jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_action_step_id_order_index_unique" UNIQUE("step_id","order_index") +); +--> statement-breakpoint +CREATE TABLE "hs_activity_log" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid, + "user_id" text, + "action" varchar(100) NOT NULL, + "resource_type" varchar(50), + "resource_id" uuid, + "description" text, + "ip_address" "inet", + "user_agent" text, + "metadata" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_annotation" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "annotator_id" text NOT NULL, + "timestamp_start" timestamp with time zone NOT NULL, + "timestamp_end" timestamp with time zone, + "category" varchar(100), + "label" varchar(100), + "description" text, + "tags" jsonb DEFAULT '[]'::jsonb, + "metadata" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_attachment" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "resource_type" varchar(50) NOT NULL, + "resource_id" uuid NOT NULL, + "file_name" varchar(255) NOT NULL, + "file_size" bigint NOT NULL, + "file_path" text NOT NULL, + "content_type" varchar(100), + "description" text, + "uploaded_by" text NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_audit_log" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" text, + "action" varchar(100) NOT NULL, + "resource_type" varchar(50), + "resource_id" uuid, + "changes" jsonb DEFAULT '{}'::jsonb, + "ip_address" "inet", + "user_agent" text, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_block_registry" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "block_type" varchar(100) NOT NULL, + "plugin_id" uuid, + "shape" "block_shape" NOT NULL, + "category" "block_category" NOT NULL, + "display_name" varchar(255) NOT NULL, + "description" text, + "icon" varchar(100), + "color" varchar(50), + "config" jsonb NOT NULL, + "parameter_schema" jsonb NOT NULL, + "execution_handler" varchar(100), + "timeout" integer, + "retry_policy" jsonb, + "requires_connection" boolean DEFAULT false, + "preview_mode" boolean DEFAULT true, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_block_registry_block_type_plugin_id_unique" UNIQUE("block_type","plugin_id") +); +--> statement-breakpoint +CREATE TABLE "hs_comment" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "parent_id" uuid, + "resource_type" varchar(50) NOT NULL, + "resource_id" uuid NOT NULL, + "author_id" text NOT NULL, + "content" text NOT NULL, + "metadata" jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_consent_form" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "version" integer DEFAULT 1 NOT NULL, + "title" varchar(255) NOT NULL, + "content" text NOT NULL, + "active" boolean DEFAULT true NOT NULL, + "created_by" text NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "storage_path" text, + CONSTRAINT "hs_consent_form_study_id_version_unique" UNIQUE("study_id","version") +); +--> statement-breakpoint +CREATE TABLE "hs_experiment" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "name" varchar(255) NOT NULL, + "description" text, + "version" integer DEFAULT 1 NOT NULL, + "robot_id" uuid, + "status" "experiment_status" DEFAULT 'draft' NOT NULL, + "estimated_duration" integer, + "created_by" text NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "metadata" jsonb DEFAULT '{}'::jsonb, + "visual_design" jsonb, + "execution_graph" jsonb, + "plugin_dependencies" text[], + "integrity_hash" varchar(128), + "deleted_at" timestamp with time zone, + CONSTRAINT "hs_experiment_study_id_name_version_unique" UNIQUE("study_id","name","version") +); +--> statement-breakpoint +CREATE TABLE "hs_export_job" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "requested_by" text NOT NULL, + "export_type" varchar(50) NOT NULL, + "format" varchar(20) NOT NULL, + "filters" jsonb DEFAULT '{}'::jsonb, + "status" "export_status" DEFAULT 'pending' NOT NULL, + "storage_path" text, + "expires_at" timestamp with time zone, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "completed_at" timestamp with time zone, + "error_message" text +); +--> statement-breakpoint +CREATE TABLE "hs_form_response" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "form_id" uuid NOT NULL, + "participant_id" uuid NOT NULL, + "responses" jsonb DEFAULT '{}'::jsonb NOT NULL, + "status" "form_response_status" DEFAULT 'pending', + "signature_data" text, + "signed_at" timestamp with time zone, + "ip_address" "inet", + "submitted_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_form_response_form_id_participant_id_unique" UNIQUE("form_id","participant_id") +); +--> statement-breakpoint +CREATE TABLE "hs_form" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "type" "form_type" NOT NULL, + "title" varchar(255) NOT NULL, + "description" text, + "version" integer DEFAULT 1 NOT NULL, + "active" boolean DEFAULT true NOT NULL, + "is_template" boolean DEFAULT false NOT NULL, + "template_name" varchar(100), + "fields" jsonb DEFAULT '[]'::jsonb NOT NULL, + "settings" jsonb DEFAULT '{}'::jsonb, + "created_by" text NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_form_study_id_version_unique" UNIQUE("study_id","version") +); +--> statement-breakpoint +CREATE TABLE "hs_media_capture" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "media_type" "media_type", + "storage_path" text NOT NULL, + "file_size" bigint, + "duration" integer, + "format" varchar(20), + "resolution" varchar(20), + "start_timestamp" timestamp with time zone, + "end_timestamp" timestamp with time zone, + "metadata" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_participant_consent" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "participant_id" uuid NOT NULL, + "consent_form_id" uuid NOT NULL, + "signed_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "signature_data" text, + "ip_address" "inet", + "storage_path" text, + CONSTRAINT "hs_participant_consent_participant_id_consent_form_id_unique" UNIQUE("participant_id","consent_form_id") +); +--> statement-breakpoint +CREATE TABLE "hs_participant_document" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "participant_id" uuid NOT NULL, + "name" varchar(255) NOT NULL, + "type" varchar(100), + "storage_path" text NOT NULL, + "file_size" integer, + "uploaded_by" text, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_participant" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "participant_code" varchar(50) NOT NULL, + "email" varchar(255), + "name" varchar(255), + "demographics" jsonb DEFAULT '{}'::jsonb, + "consent_given" boolean DEFAULT false NOT NULL, + "consent_date" timestamp with time zone, + "notes" text, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_participant_study_id_participant_code_unique" UNIQUE("study_id","participant_code") +); +--> statement-breakpoint +CREATE TABLE "hs_permission" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar(100) NOT NULL, + "description" text, + "resource" varchar(50) NOT NULL, + "action" varchar(50) NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_permission_name_unique" UNIQUE("name") +); +--> statement-breakpoint +CREATE TABLE "hs_plugin_repository" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar(255) NOT NULL, + "url" text NOT NULL, + "description" text, + "trust_level" "trust_level" DEFAULT 'community' NOT NULL, + "is_enabled" boolean DEFAULT true NOT NULL, + "is_official" boolean DEFAULT false NOT NULL, + "last_sync_at" timestamp with time zone, + "sync_status" varchar(50) DEFAULT 'pending', + "sync_error" text, + "metadata" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "created_by" text NOT NULL, + CONSTRAINT "hs_plugin_repository_url_unique" UNIQUE("url") +); +--> statement-breakpoint +CREATE TABLE "hs_plugin" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "robot_id" uuid, + "identifier" varchar(100) NOT NULL, + "name" varchar(255) NOT NULL, + "version" varchar(50) NOT NULL, + "description" text, + "author" varchar(255), + "repository_url" text, + "trust_level" "trust_level", + "status" "plugin_status" DEFAULT 'active' NOT NULL, + "configuration_schema" jsonb, + "action_definitions" jsonb DEFAULT '[]'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "metadata" jsonb DEFAULT '{}'::jsonb, + CONSTRAINT "hs_plugin_identifier_unique" UNIQUE("identifier"), + CONSTRAINT "hs_plugin_name_version_unique" UNIQUE("name","version") +); +--> statement-breakpoint +CREATE TABLE "hs_robot_plugin" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar(255) NOT NULL, + "version" varchar(50) NOT NULL, + "manufacturer" varchar(255), + "description" text, + "robot_id" uuid, + "communication_protocol" "communication_protocol", + "status" "plugin_status" DEFAULT 'active' NOT NULL, + "config_schema" jsonb, + "capabilities" jsonb DEFAULT '[]'::jsonb, + "trust_level" "trust_level" DEFAULT 'community' NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_robot" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar(255) NOT NULL, + "manufacturer" varchar(255), + "model" varchar(255), + "description" text, + "capabilities" jsonb DEFAULT '[]'::jsonb, + "communication_protocol" "communication_protocol", + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_role_permission" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "role" "system_role" NOT NULL, + "permission_id" uuid NOT NULL, + CONSTRAINT "hs_role_permission_role_permission_id_unique" UNIQUE("role","permission_id") +); +--> statement-breakpoint +CREATE TABLE "hs_sensor_data" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "sensor_type" varchar(50) NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + "data" jsonb NOT NULL, + "robot_state" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "hs_session" ( + "id" text PRIMARY KEY NOT NULL, + "token" varchar(255) NOT NULL, + "user_id" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "ip_address" text, + "user_agent" text, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_session_token_unique" UNIQUE("token") +); +--> statement-breakpoint +CREATE TABLE "hs_shared_resource" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "resource_type" varchar(50) NOT NULL, + "resource_id" uuid NOT NULL, + "shared_by" text NOT NULL, + "share_token" varchar(255), + "permissions" jsonb DEFAULT '["read"]'::jsonb, + "expires_at" timestamp with time zone, + "access_count" integer DEFAULT 0 NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_shared_resource_share_token_unique" UNIQUE("share_token") +); +--> statement-breakpoint +CREATE TABLE "hs_step" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "experiment_id" uuid NOT NULL, + "name" varchar(255) NOT NULL, + "description" text, + "type" "step_type" NOT NULL, + "order_index" integer NOT NULL, + "duration_estimate" integer, + "required" boolean DEFAULT true NOT NULL, + "conditions" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_step_experiment_id_order_index_unique" UNIQUE("experiment_id","order_index") +); +--> statement-breakpoint +CREATE TABLE "hs_study" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "name" varchar(255) NOT NULL, + "description" text, + "institution" varchar(255), + "irb_protocol" varchar(100), + "status" "study_status" DEFAULT 'draft' NOT NULL, + "created_by" text NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "metadata" jsonb DEFAULT '{}'::jsonb, + "settings" jsonb DEFAULT '{}'::jsonb, + "deleted_at" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "hs_study_member" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "user_id" text NOT NULL, + "role" "study_member_role" NOT NULL, + "permissions" jsonb DEFAULT '[]'::jsonb, + "joined_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "invited_by" text, + CONSTRAINT "hs_study_member_study_id_user_id_unique" UNIQUE("study_id","user_id") +); +--> statement-breakpoint +CREATE TABLE "hs_study_plugin" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "study_id" uuid NOT NULL, + "plugin_id" uuid NOT NULL, + "configuration" jsonb DEFAULT '{}'::jsonb, + "installed_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "installed_by" text NOT NULL, + CONSTRAINT "hs_study_plugin_study_id_plugin_id_unique" UNIQUE("study_id","plugin_id") +); +--> statement-breakpoint +CREATE TABLE "hs_system_setting" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "key" varchar(100) NOT NULL, + "value" jsonb NOT NULL, + "description" text, + "updated_by" text, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_system_setting_key_unique" UNIQUE("key") +); +--> statement-breakpoint +CREATE TABLE "hs_trial_event" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "event_type" varchar(50) NOT NULL, + "action_id" uuid, + "timestamp" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "data" jsonb DEFAULT '{}'::jsonb, + "created_by" text +); +--> statement-breakpoint +CREATE TABLE "hs_trial" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "experiment_id" uuid NOT NULL, + "participant_id" uuid, + "wizard_id" text, + "session_number" integer DEFAULT 1 NOT NULL, + "status" "trial_status" DEFAULT 'scheduled' NOT NULL, + "scheduled_at" timestamp with time zone, + "started_at" timestamp with time zone, + "completed_at" timestamp with time zone, + "duration" integer, + "notes" text, + "parameters" jsonb DEFAULT '{}'::jsonb, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "metadata" jsonb DEFAULT '{}'::jsonb +); +--> statement-breakpoint +CREATE TABLE "hs_user_system_role" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" text NOT NULL, + "role" "system_role" NOT NULL, + "granted_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "granted_by" text, + CONSTRAINT "hs_user_system_role_user_id_role_unique" UNIQUE("user_id","role") +); +--> statement-breakpoint +CREATE TABLE "hs_user" ( + "id" text PRIMARY KEY NOT NULL, + "name" varchar(255), + "email" varchar(255) NOT NULL, + "email_verified" boolean DEFAULT false NOT NULL, + "image" text, + "password" varchar(255), + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "deleted_at" timestamp with time zone, + CONSTRAINT "hs_user_email_unique" UNIQUE("email") +); +--> statement-breakpoint +CREATE TABLE "hs_verification_token" ( + "id" text PRIMARY KEY NOT NULL, + "identifier" varchar(255) NOT NULL, + "value" varchar(255) NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_verification_token_value_unique" UNIQUE("value") +); +--> statement-breakpoint +CREATE TABLE "hs_wizard_intervention" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "wizard_id" text NOT NULL, + "intervention_type" varchar(100) NOT NULL, + "description" text, + "timestamp" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "parameters" jsonb DEFAULT '{}'::jsonb, + "reason" text +); +--> statement-breakpoint +CREATE TABLE "hs_ws_connection" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "trial_id" uuid NOT NULL, + "client_id" text NOT NULL, + "user_id" text, + "connected_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "hs_ws_connection_client_id_unique" UNIQUE("client_id") +); +--> statement-breakpoint +ALTER TABLE "hs_account" ADD CONSTRAINT "hs_account_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_action" ADD CONSTRAINT "hs_action_step_id_hs_step_id_fk" FOREIGN KEY ("step_id") REFERENCES "public"."hs_step"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_activity_log" ADD CONSTRAINT "hs_activity_log_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_activity_log" ADD CONSTRAINT "hs_activity_log_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_annotation" ADD CONSTRAINT "hs_annotation_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_annotation" ADD CONSTRAINT "hs_annotation_annotator_id_hs_user_id_fk" FOREIGN KEY ("annotator_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_attachment" ADD CONSTRAINT "hs_attachment_uploaded_by_hs_user_id_fk" FOREIGN KEY ("uploaded_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_audit_log" ADD CONSTRAINT "hs_audit_log_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_block_registry" ADD CONSTRAINT "hs_block_registry_plugin_id_hs_robot_plugin_id_fk" FOREIGN KEY ("plugin_id") REFERENCES "public"."hs_robot_plugin"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_comment" ADD CONSTRAINT "hs_comment_author_id_hs_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_consent_form" ADD CONSTRAINT "hs_consent_form_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_consent_form" ADD CONSTRAINT "hs_consent_form_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_experiment" ADD CONSTRAINT "hs_experiment_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_experiment" ADD CONSTRAINT "hs_experiment_robot_id_hs_robot_id_fk" FOREIGN KEY ("robot_id") REFERENCES "public"."hs_robot"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_experiment" ADD CONSTRAINT "hs_experiment_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_export_job" ADD CONSTRAINT "hs_export_job_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_export_job" ADD CONSTRAINT "hs_export_job_requested_by_hs_user_id_fk" FOREIGN KEY ("requested_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_form_response" ADD CONSTRAINT "hs_form_response_form_id_hs_form_id_fk" FOREIGN KEY ("form_id") REFERENCES "public"."hs_form"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_form_response" ADD CONSTRAINT "hs_form_response_participant_id_hs_participant_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."hs_participant"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_form" ADD CONSTRAINT "hs_form_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_form" ADD CONSTRAINT "hs_form_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_media_capture" ADD CONSTRAINT "hs_media_capture_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_participant_consent" ADD CONSTRAINT "hs_participant_consent_participant_id_hs_participant_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."hs_participant"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_participant_consent" ADD CONSTRAINT "hs_participant_consent_consent_form_id_hs_consent_form_id_fk" FOREIGN KEY ("consent_form_id") REFERENCES "public"."hs_consent_form"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_participant_document" ADD CONSTRAINT "hs_participant_document_participant_id_hs_participant_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."hs_participant"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_participant_document" ADD CONSTRAINT "hs_participant_document_uploaded_by_hs_user_id_fk" FOREIGN KEY ("uploaded_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_participant" ADD CONSTRAINT "hs_participant_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_plugin_repository" ADD CONSTRAINT "hs_plugin_repository_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_plugin" ADD CONSTRAINT "hs_plugin_robot_id_hs_robot_id_fk" FOREIGN KEY ("robot_id") REFERENCES "public"."hs_robot"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_robot_plugin" ADD CONSTRAINT "hs_robot_plugin_robot_id_hs_robot_id_fk" FOREIGN KEY ("robot_id") REFERENCES "public"."hs_robot"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_role_permission" ADD CONSTRAINT "hs_role_permission_permission_id_hs_permission_id_fk" FOREIGN KEY ("permission_id") REFERENCES "public"."hs_permission"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_sensor_data" ADD CONSTRAINT "hs_sensor_data_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_session" ADD CONSTRAINT "hs_session_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_shared_resource" ADD CONSTRAINT "hs_shared_resource_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_shared_resource" ADD CONSTRAINT "hs_shared_resource_shared_by_hs_user_id_fk" FOREIGN KEY ("shared_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_step" ADD CONSTRAINT "hs_step_experiment_id_hs_experiment_id_fk" FOREIGN KEY ("experiment_id") REFERENCES "public"."hs_experiment"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study" ADD CONSTRAINT "hs_study_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_member" ADD CONSTRAINT "hs_study_member_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_member" ADD CONSTRAINT "hs_study_member_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_member" ADD CONSTRAINT "hs_study_member_invited_by_hs_user_id_fk" FOREIGN KEY ("invited_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_plugin" ADD CONSTRAINT "hs_study_plugin_study_id_hs_study_id_fk" FOREIGN KEY ("study_id") REFERENCES "public"."hs_study"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_plugin" ADD CONSTRAINT "hs_study_plugin_plugin_id_hs_plugin_id_fk" FOREIGN KEY ("plugin_id") REFERENCES "public"."hs_plugin"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_study_plugin" ADD CONSTRAINT "hs_study_plugin_installed_by_hs_user_id_fk" FOREIGN KEY ("installed_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_system_setting" ADD CONSTRAINT "hs_system_setting_updated_by_hs_user_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial_event" ADD CONSTRAINT "hs_trial_event_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial_event" ADD CONSTRAINT "hs_trial_event_action_id_hs_action_id_fk" FOREIGN KEY ("action_id") REFERENCES "public"."hs_action"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial_event" ADD CONSTRAINT "hs_trial_event_created_by_hs_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial" ADD CONSTRAINT "hs_trial_experiment_id_hs_experiment_id_fk" FOREIGN KEY ("experiment_id") REFERENCES "public"."hs_experiment"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial" ADD CONSTRAINT "hs_trial_participant_id_hs_participant_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."hs_participant"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_trial" ADD CONSTRAINT "hs_trial_wizard_id_hs_user_id_fk" FOREIGN KEY ("wizard_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_user_system_role" ADD CONSTRAINT "hs_user_system_role_user_id_hs_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."hs_user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_user_system_role" ADD CONSTRAINT "hs_user_system_role_granted_by_hs_user_id_fk" FOREIGN KEY ("granted_by") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_wizard_intervention" ADD CONSTRAINT "hs_wizard_intervention_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_wizard_intervention" ADD CONSTRAINT "hs_wizard_intervention_wizard_id_hs_user_id_fk" FOREIGN KEY ("wizard_id") REFERENCES "public"."hs_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "hs_ws_connection" ADD CONSTRAINT "hs_ws_connection_trial_id_hs_trial_id_fk" FOREIGN KEY ("trial_id") REFERENCES "public"."hs_trial"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "account_user_id_idx" ON "hs_account" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "activity_logs_study_created_idx" ON "hs_activity_log" USING btree ("study_id","created_at");--> statement-breakpoint +CREATE INDEX "audit_logs_created_idx" ON "hs_audit_log" USING btree ("created_at");--> statement-breakpoint +CREATE INDEX "block_registry_category_idx" ON "hs_block_registry" USING btree ("category");--> statement-breakpoint +CREATE INDEX "experiment_visual_design_idx" ON "hs_experiment" USING gin ("visual_design");--> statement-breakpoint +CREATE INDEX "participant_document_participant_idx" ON "hs_participant_document" USING btree ("participant_id");--> statement-breakpoint +CREATE INDEX "sensor_data_trial_timestamp_idx" ON "hs_sensor_data" USING btree ("trial_id","timestamp");--> statement-breakpoint +CREATE INDEX "session_user_id_idx" ON "hs_session" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "trial_events_trial_timestamp_idx" ON "hs_trial_event" USING btree ("trial_id","timestamp");--> statement-breakpoint +CREATE INDEX "verification_token_identifier_idx" ON "hs_verification_token" USING btree ("identifier");--> statement-breakpoint +CREATE INDEX "verification_token_value_idx" ON "hs_verification_token" USING btree ("value"); \ No newline at end of file diff --git a/migrations/0001_seed_data.sql b/migrations/0001_seed_data.sql new file mode 100644 index 0000000..4700083 --- /dev/null +++ b/migrations/0001_seed_data.sql @@ -0,0 +1,34 @@ +-- Migration 0001: Minimal Seed Data +-- HRIStudio - Only essential data needed for auth + +-- ====================== +-- USERS & AUTH +-- ====================== + +-- Users (using valid UUID v4 format) +INSERT INTO "hs_user" ("id", "name", "email", "email_verified", "image", "created_at", "updated_at") +VALUES + ('11111111-1111-4111-8111-111111111111', 'Sean O''Connor', 'sean@soconnor.dev', true, 'https://www.gravatar.com/avatar/4b20f4a15f9a0e0f5e5e5a0f5e5e5a0f?d=identicon', NOW(), NOW()), + ('22222222-2222-4222-8222-222222222222', 'Dr. Felipe Perrone', 'felipe.perrone@bucknell.edu', true, 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felipe', NOW(), NOW()) +ON CONFLICT DO NOTHING; + +-- Accounts +INSERT INTO "hs_account" ("id", "user_id", "provider_id", "account_id", "password", "created_at", "updated_at") +VALUES + ('aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa', '11111111-1111-4111-8111-111111111111', 'credential', '11111111-1111-4111-8111-111111111111', '$2b$12$50kgpkp.qZrZXCWjHuVSHOZBjAQUrX50VdtWc6WBj27HnzUYFwwPm', NOW(), NOW()), + ('bbbbbbbb-bbbb-4bbb-bbbb-bbbbbbbbbbbb', '22222222-2222-4222-8222-222222222222', 'credential', '22222222-2222-4222-8222-222222222222', '$2b$12$50kgpkp.qZrZXCWjHuVSHOZBjAQUrX50VdtWc6WBj27HnzUYFwwPm', NOW(), NOW()) +ON CONFLICT DO NOTHING; + +-- System Roles +INSERT INTO "hs_user_system_role" ("id", "user_id", "role", "granted_at", "granted_by") +VALUES + (gen_random_uuid(), '11111111-1111-4111-8111-111111111111', 'administrator', NOW(), '11111111-1111-4111-8111-111111111111'), + (gen_random_uuid(), '22222222-2222-4222-8222-222222222222', 'researcher', NOW(), '11111111-1111-4111-8111-111111111111') +ON CONFLICT DO NOTHING; + +DO $$ +BEGIN + RAISE NOTICE 'Minimal seed migration complete'; + RAISE NOTICE 'Admin: sean@soconnor.dev / password123'; + RAISE NOTICE 'Use bun db:seed for full demo data'; +END $$; \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json new file mode 100644 index 0000000..3021601 --- /dev/null +++ b/migrations/meta/_journal.json @@ -0,0 +1,20 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 0, + "tag": "0000_init_schema", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1, + "tag": "0001_seed_data", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/robot-plugins b/robot-plugins index f83a207..d772aec 160000 --- a/robot-plugins +++ b/robot-plugins @@ -1 +1 @@ -Subproject commit f83a207b16d5ceabfb6a25be35b99bfe4fe53ad1 +Subproject commit d772aecc54306b211cd97ff6f720936d38a6b8a9 diff --git a/scripts/seed-dev.ts b/scripts/seed-dev.ts index 18f23b3..2530294 100755 --- a/scripts/seed-dev.ts +++ b/scripts/seed-dev.ts @@ -88,7 +88,8 @@ async function main() { await db.delete(schema.participants).where(sql`1=1`); await db.delete(schema.studyPlugins).where(sql`1=1`); await db.delete(schema.studyMembers).where(sql`1=1`); - await db.delete(schema.studies).where(sql`1=1`); + await db.delete(schema.formResponses).where(sql`1=1`); + await db.delete(schema.forms).where(sql`1=1`); await db.delete(schema.studies).where(sql`1=1`); await db.delete(schema.plugins).where(sql`1=1`); await db.delete(schema.pluginRepositories).where(sql`1=1`); @@ -236,7 +237,7 @@ async function main() { description: "A comprehensive informed consent document template for HRI research studies.", isTemplate: true, templateName: "Informed Consent", - version: 1, + version: 100, fields: [ { id: "1", type: "text", label: "Study Title", required: true }, { id: "2", type: "text", label: "Principal Investigator Name", required: true }, @@ -262,7 +263,7 @@ async function main() { description: "Standard questionnaire to collect participant feedback after HRI sessions.", isTemplate: true, templateName: "Post-Session Survey", - version: 2, + version: 101, fields: [ { id: "1", type: "rating", label: "How engaging was the robot?", required: true, settings: { scale: 5 } }, { id: "2", type: "rating", label: "How understandable was the robot's speech?", required: true, settings: { scale: 5 } }, @@ -285,7 +286,7 @@ async function main() { description: "Basic demographic information collection form.", isTemplate: true, templateName: "Demographics", - version: 3, + version: 102, fields: [ { id: "1", type: "text", label: "Age", required: true }, { id: "2", type: "multiple_choice", label: "Gender", required: true, options: ["Male", "Female", "Non-binary", "Prefer not to say"] }, @@ -305,8 +306,8 @@ async function main() { type: "consent", title: "Interactive Storyteller Consent", description: "Consent form for the Comparative WoZ Study - Interactive Storyteller scenario.", + version: 1, active: true, - version: 4, fields: [ { id: "1", type: "text", label: "Participant Name", required: true }, { id: "2", type: "date", label: "Date", required: true }, diff --git a/src/app/(dashboard)/studies/[id]/forms/[formId]/page.tsx b/src/app/(dashboard)/studies/[id]/forms/[formId]/page.tsx index 4317d8a..713cd77 100644 --- a/src/app/(dashboard)/studies/[id]/forms/[formId]/page.tsx +++ b/src/app/(dashboard)/studies/[id]/forms/[formId]/page.tsx @@ -20,17 +20,16 @@ import { Users, CheckCircle, Printer, - Download, Pencil, X, FileDown, } from "lucide-react"; +import { Textarea } from "~/components/ui/textarea"; import { useBreadcrumbsEffect } from "~/components/ui/breadcrumb-provider"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; -import { Textarea } from "~/components/ui/textarea"; import { Select, SelectContent, @@ -42,26 +41,11 @@ import { Badge } from "~/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import { api } from "~/trpc/react"; import { toast } from "sonner"; - -interface Field { - id: string; - type: string; - label: string; - required: boolean; - options?: string[]; - settings?: Record; -} - -const fieldTypes = [ - { value: "text", label: "Text (short)", icon: "📝" }, - { value: "textarea", label: "Text (long)", icon: "📄" }, - { value: "multiple_choice", label: "Multiple Choice", icon: "☑️" }, - { value: "checkbox", label: "Checkbox", icon: "✅" }, - { value: "rating", label: "Rating Scale", icon: "⭐" }, - { value: "yes_no", label: "Yes/No", icon: "✔️" }, - { value: "date", label: "Date", icon: "📅" }, - { value: "signature", label: "Signature", icon: "✍️" }, -]; +import type { FormField, FormFieldType } from "~/lib/types/forms"; +import { FORM_FIELD_TYPES } from "~/lib/types/forms"; +import { formStatusColors } from "~/lib/constants"; +import { FormBuilder } from "~/components/forms/FormBuilder"; +import { FormFieldRenderer } from "~/components/forms/FormFieldRenderer"; const formTypeIcons = { consent: FileSignature, @@ -69,12 +53,6 @@ const formTypeIcons = { questionnaire: FileQuestion, }; -const statusColors = { - pending: "bg-yellow-100 text-yellow-700", - completed: "bg-green-100 text-green-700", - rejected: "bg-red-100 text-red-700", -}; - interface FormViewPageProps { params: Promise<{ id: string; @@ -99,7 +77,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); - const [fields, setFields] = useState([]); + const [fields, setFields] = useState([]); useEffect(() => { const resolveParams = async () => { @@ -213,7 +191,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { '
Yes   No
'; break; case "rating": - const scale = field.settings?.scale || 5; + const scale = (field.settings?.scale as number) || 5; inputField = `
${Array.from( { length: scale }, (_, i) => ` ${i + 1} `, @@ -284,7 +262,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { if (form) { setTitle(form.title); setDescription(form.description || ""); - setFields((form.fields as Field[]) || []); + setFields((form.fields as FormField[]) || []); } }, [form]); @@ -307,10 +285,10 @@ export default function FormViewPage({ params }: FormViewPageProps) { const responses = responsesData?.responses ?? []; const addField = (type: string) => { - const newField: Field = { + const newField: FormField = { id: crypto.randomUUID(), - type, - label: `New ${fieldTypes.find((f) => f.value === type)?.label || "Field"}`, + type: type as FormFieldType, + label: `New ${FORM_FIELD_TYPES.find((f) => f.value === type)?.label || "Field"}`, required: false, options: type === "multiple_choice" ? ["Option 1", "Option 2"] : undefined, @@ -322,7 +300,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { setFields(fields.filter((f) => f.id !== id)); }; - const updateField = (id: string, updates: Partial) => { + const updateField = (id: string, updates: Partial) => { setFields(fields.map((f) => (f.id === id ? { ...f, ...updates } : f))); }; @@ -332,7 +310,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { title, description, fields, - settings: form.settings as Record, + settings: form.settings as Record, }); }; @@ -415,7 +393,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { - {fieldTypes.map((type) => ( + {FORM_FIELD_TYPES.map((type) => ( {type.icon} {type.label} @@ -444,11 +422,11 @@ export default function FormViewPage({ params }: FormViewPageProps) {
{ - fieldTypes.find((f) => f.value === field.type) + FORM_FIELD_TYPES.find((f) => f.value === field.type) ?.icon }{" "} { - fieldTypes.find((f) => f.value === field.type) + FORM_FIELD_TYPES.find((f) => f.value === field.type) ?.label } @@ -569,7 +547,7 @@ export default function FormViewPage({ params }: FormViewPageProps) {

{field.label}

{ - fieldTypes.find((f) => f.value === field.type) + FORM_FIELD_TYPES.find((f) => f.value === field.type) ?.label } {field.required && " • Required"} @@ -646,7 +624,7 @@ export default function FormViewPage({ params }: FormViewPageProps) { {field.type === "rating" && (

{Array.from( - { length: field.settings?.scale || 5 }, + { length: (field.settings?.scale as number) || 5 }, (_, i) => (
{response.status} diff --git a/src/app/(dashboard)/studies/[id]/forms/new/page.tsx b/src/app/(dashboard)/studies/[id]/forms/new/page.tsx index 13c5fd5..c54c1cf 100644 --- a/src/app/(dashboard)/studies/[id]/forms/new/page.tsx +++ b/src/app/(dashboard)/studies/[id]/forms/new/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useParams, useRouter } from "next/navigation"; import { useSession } from "~/lib/auth-client"; import { notFound } from "next/navigation"; @@ -8,22 +8,17 @@ import Link from "next/link"; import { FileText, ArrowLeft, - Plus, - Trash2, - GripVertical, + Save, + LayoutTemplate, FileSignature, ClipboardList, FileQuestion, - Save, - Copy, - LayoutTemplate, } from "lucide-react"; import { useBreadcrumbsEffect } from "~/components/ui/breadcrumb-provider"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; -import { Textarea } from "~/components/ui/textarea"; import { Select, SelectContent, @@ -31,29 +26,11 @@ import { SelectTrigger, SelectValue, } from "~/components/ui/select"; -import { Badge } from "~/components/ui/badge"; import { api } from "~/trpc/react"; import { toast } from "sonner"; - -interface Field { - id: string; - type: string; - label: string; - required: boolean; - options?: string[]; - settings?: Record; -} - -const fieldTypes = [ - { value: "text", label: "Text (short)", icon: "📝" }, - { value: "textarea", label: "Text (long)", icon: "📄" }, - { value: "multiple_choice", label: "Multiple Choice", icon: "☑️" }, - { value: "checkbox", label: "Checkbox", icon: "✅" }, - { value: "rating", label: "Rating Scale", icon: "⭐" }, - { value: "yes_no", label: "Yes/No", icon: "✔️" }, - { value: "date", label: "Date", icon: "📅" }, - { value: "signature", label: "Signature", icon: "✍️" }, -]; +import type { FormField, FormType } from "~/lib/types/forms"; +import { FORM_FIELD_TYPES } from "~/lib/types/forms"; +import { FormBuilder } from "~/components/forms/FormBuilder"; const formTypes = [ { value: "consent", label: "Consent Form", icon: FileSignature, description: "Legal/IRB consent documents" }, @@ -65,14 +42,13 @@ export default function NewFormPage() { const params = useParams(); const router = useRouter(); const { data: session } = useSession(); - const utils = api.useUtils(); const studyId = typeof params.id === "string" ? params.id : ""; const [formType, setFormType] = useState(""); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); - const [fields, setFields] = useState([]); + const [fields, setFields] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const { data: study } = api.studies.get.useQuery( @@ -115,25 +91,6 @@ export default function NewFormPage() { return notFound(); } - const addField = (type: string) => { - const newField: Field = { - id: crypto.randomUUID(), - type, - label: `New ${fieldTypes.find(f => f.value === type)?.label || "Field"}`, - required: false, - options: type === "multiple_choice" ? ["Option 1", "Option 2"] : undefined, - }; - setFields([...fields, newField]); - }; - - const removeField = (id: string) => { - setFields(fields.filter(f => f.id !== id)); - }; - - const updateField = (id: string, updates: Partial) => { - setFields(fields.map(f => f.id === id ? { ...f, ...updates } : f)); - }; - const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -145,7 +102,7 @@ export default function NewFormPage() { setIsSubmitting(true); createForm.mutate({ studyId, - type: formType as "consent" | "survey" | "questionnaire", + type: formType as FormType, title, description, fields, @@ -266,12 +223,21 @@ export default function NewFormPage() { Form Fields - { + const newField: FormField = { + id: crypto.randomUUID(), + type: type as FormField["type"], + label: `New ${FORM_FIELD_TYPES.find(f => f.value === type)?.label || "Field"}`, + required: false, + options: type === "multiple_choice" ? ["Option 1", "Option 2"] : undefined, + }; + setFields([...fields, newField]); + }}> - {fieldTypes.map((type) => ( + {FORM_FIELD_TYPES.map((type) => ( {type.icon} {type.label} @@ -281,117 +247,7 @@ export default function NewFormPage() { - {fields.length === 0 ? ( -
- -

No fields added yet

-

Use the dropdown above to add fields

-
- ) : ( -
- {fields.map((field, index) => ( -
-
- -
-
-
- - {fieldTypes.find(f => f.value === field.type)?.icon}{" "} - {fieldTypes.find(f => f.value === field.type)?.label} - - updateField(field.id, { label: e.target.value })} - placeholder="Field label" - className="flex-1" - /> - -
- {field.type === "multiple_choice" && ( -
- - {field.options?.map((opt, i) => ( -
- { - const newOptions = [...(field.options || [])]; - newOptions[i] = e.target.value; - updateField(field.id, { options: newOptions }); - }} - placeholder={`Option ${i + 1}`} - className="flex-1" - /> - -
- ))} - -
- )} - {field.type === "rating" && ( -
- Scale: - -
- )} -
- -
- ))} -
- )} +
@@ -407,4 +263,4 @@ export default function NewFormPage() {
); -} \ No newline at end of file +} diff --git a/src/app/(public)/forms/[formId]/page.tsx b/src/app/(public)/forms/[formId]/page.tsx index 486b9e9..1760ccd 100644 --- a/src/app/(public)/forms/[formId]/page.tsx +++ b/src/app/(public)/forms/[formId]/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { useParams, useSearchParams } from "next/navigation"; import Link from "next/link"; import { FileText, @@ -22,18 +22,10 @@ import { } from "~/components/ui/card"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; -import { Textarea } from "~/components/ui/textarea"; import { api } from "~/trpc/react"; import { toast } from "sonner"; - -interface Field { - id: string; - type: string; - label: string; - required: boolean; - options?: string[]; - settings?: Record; -} +import type { FormField } from "~/lib/types/forms"; +import { FormFieldRenderer } from "~/components/forms/FormFieldRenderer"; const formTypeIcons = { consent: FileSignature, @@ -47,7 +39,7 @@ export default function ParticipantFormPage() { const formId = params.formId as string; const [participantCode, setParticipantCode] = useState(""); - const [formResponses, setFormResponses] = useState>({}); + const [formResponses, setFormResponses] = useState>({}); const [hasSubmitted, setHasSubmitted] = useState(false); const [fieldErrors, setFieldErrors] = useState>({}); @@ -113,7 +105,7 @@ export default function ParticipantFormPage() { const TypeIcon = formTypeIcons[form.type as keyof typeof formTypeIcons] || FileText; - const fields = (form.fields as Field[]) || []; + const fields = (form.fields as FormField[]) || []; const validateForm = (): boolean => { const errors: Record = {}; @@ -158,7 +150,7 @@ export default function ParticipantFormPage() { }); }; - const updateResponse = (fieldId: string, value: any) => { + const updateResponse = (fieldId: string, value: unknown) => { setFormResponses({ ...formResponses, [fieldId]: value }); if (fieldErrors[fieldId]) { const newErrors = { ...fieldErrors }; @@ -217,175 +209,21 @@ export default function ParticipantFormPage() {
{fields.map((field, index) => (
- +
- {field.type === "text" && ( - - updateResponse(field.id, e.target.value) - } - placeholder="Enter your response..." - className={ - fieldErrors[field.id] ? "border-destructive" : "" - } - /> - )} - - {field.type === "textarea" && ( -