feat: add share page settings dialog + add org id to deployment as well
This commit is contained in:
		
							parent
							
								
									b2690ab2c5
								
							
						
					
					
						commit
						30ec7d3105
					
				
							
								
								
									
										
											BIN
										
									
								
								web/bun.lockb
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/bun.lockb
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								web/drizzle/0029_large_frightful_four.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								web/drizzle/0029_large_frightful_four.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
ALTER TABLE "comfyui_deploy"."deployments" ADD COLUMN "description" text;--> statement-breakpoint
 | 
			
		||||
ALTER TABLE "comfyui_deploy"."deployments" ADD COLUMN "showcase_media" jsonb;
 | 
			
		||||
							
								
								
									
										1
									
								
								web/drizzle/0030_kind_doorman.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								web/drizzle/0030_kind_doorman.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
ALTER TABLE "comfyui_deploy"."deployments" ADD COLUMN "org_id" text;
 | 
			
		||||
							
								
								
									
										750
									
								
								web/drizzle/meta/0029_snapshot.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										750
									
								
								web/drizzle/meta/0029_snapshot.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,750 @@
 | 
			
		||||
{
 | 
			
		||||
  "id": "a7d6a8dd-0e15-4165-98a2-de2a334455dc",
 | 
			
		||||
  "prevId": "7bdeb193-ee27-40cc-8252-59ddaf505ab8",
 | 
			
		||||
  "version": "5",
 | 
			
		||||
  "dialect": "pg",
 | 
			
		||||
  "tables": {
 | 
			
		||||
    "api_keys": {
 | 
			
		||||
      "name": "api_keys",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "key": {
 | 
			
		||||
          "name": "key",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "revoked": {
 | 
			
		||||
          "name": "revoked",
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "api_keys_user_id_users_id_fk": {
 | 
			
		||||
          "name": "api_keys_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "api_keys",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {
 | 
			
		||||
        "api_keys_key_unique": {
 | 
			
		||||
          "name": "api_keys_key_unique",
 | 
			
		||||
          "nullsNotDistinct": false,
 | 
			
		||||
          "columns": [
 | 
			
		||||
            "key"
 | 
			
		||||
          ]
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "deployments": {
 | 
			
		||||
      "name": "deployments",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_version_id": {
 | 
			
		||||
          "name": "workflow_version_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "machine_id": {
 | 
			
		||||
          "name": "machine_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "description": {
 | 
			
		||||
          "name": "description",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "showcase_media": {
 | 
			
		||||
          "name": "showcase_media",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "environment": {
 | 
			
		||||
          "name": "environment",
 | 
			
		||||
          "type": "deployment_environment",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "deployments_user_id_users_id_fk": {
 | 
			
		||||
          "name": "deployments_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_workflow_version_id_workflow_versions_id_fk": {
 | 
			
		||||
          "name": "deployments_workflow_version_id_workflow_versions_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "workflow_versions",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_version_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "no action",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "deployments_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_machine_id_machines_id_fk": {
 | 
			
		||||
          "name": "deployments_machine_id_machines_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "machines",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "machine_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "no action",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "machines": {
 | 
			
		||||
      "name": "machines",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "endpoint": {
 | 
			
		||||
          "name": "endpoint",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "disabled": {
 | 
			
		||||
          "name": "disabled",
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": false
 | 
			
		||||
        },
 | 
			
		||||
        "auth_token": {
 | 
			
		||||
          "name": "auth_token",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "type": {
 | 
			
		||||
          "name": "type",
 | 
			
		||||
          "type": "machine_type",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'classic'"
 | 
			
		||||
        },
 | 
			
		||||
        "status": {
 | 
			
		||||
          "name": "status",
 | 
			
		||||
          "type": "machine_status",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'ready'"
 | 
			
		||||
        },
 | 
			
		||||
        "snapshot": {
 | 
			
		||||
          "name": "snapshot",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "models": {
 | 
			
		||||
          "name": "models",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "gpu": {
 | 
			
		||||
          "name": "gpu",
 | 
			
		||||
          "type": "machine_gpu",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "build_machine_instance_id": {
 | 
			
		||||
          "name": "build_machine_instance_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "build_log": {
 | 
			
		||||
          "name": "build_log",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "machines_user_id_users_id_fk": {
 | 
			
		||||
          "name": "machines_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "machines",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "users": {
 | 
			
		||||
      "name": "users",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "username": {
 | 
			
		||||
          "name": "username",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {},
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_outputs": {
 | 
			
		||||
      "name": "workflow_run_outputs",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "run_id": {
 | 
			
		||||
          "name": "run_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "data": {
 | 
			
		||||
          "name": "data",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_run_outputs_run_id_workflow_runs_id_fk": {
 | 
			
		||||
          "name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_run_outputs",
 | 
			
		||||
          "tableTo": "workflow_runs",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "run_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_runs": {
 | 
			
		||||
      "name": "workflow_runs",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_version_id": {
 | 
			
		||||
          "name": "workflow_version_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_inputs": {
 | 
			
		||||
          "name": "workflow_inputs",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "machine_id": {
 | 
			
		||||
          "name": "machine_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "origin": {
 | 
			
		||||
          "name": "origin",
 | 
			
		||||
          "type": "workflow_run_origin",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'api'"
 | 
			
		||||
        },
 | 
			
		||||
        "status": {
 | 
			
		||||
          "name": "status",
 | 
			
		||||
          "type": "workflow_run_status",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'not-started'"
 | 
			
		||||
        },
 | 
			
		||||
        "ended_at": {
 | 
			
		||||
          "name": "ended_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_runs_workflow_version_id_workflow_versions_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "workflow_versions",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_version_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "set null",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_runs_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_runs_machine_id_machines_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_machine_id_machines_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "machines",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "machine_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "set null",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflows": {
 | 
			
		||||
      "name": "workflows",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflows_user_id_users_id_fk": {
 | 
			
		||||
          "name": "workflows_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "workflows",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_versions": {
 | 
			
		||||
      "name": "workflow_versions",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow": {
 | 
			
		||||
          "name": "workflow",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_api": {
 | 
			
		||||
          "name": "workflow_api",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "version": {
 | 
			
		||||
          "name": "version",
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "snapshot": {
 | 
			
		||||
          "name": "snapshot",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_versions_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "workflow_versions_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_versions",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "enums": {
 | 
			
		||||
    "deployment_environment": {
 | 
			
		||||
      "name": "deployment_environment",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "staging": "staging",
 | 
			
		||||
        "production": "production",
 | 
			
		||||
        "public-share": "public-share"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_gpu": {
 | 
			
		||||
      "name": "machine_gpu",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "T4": "T4",
 | 
			
		||||
        "A10G": "A10G",
 | 
			
		||||
        "A100": "A100"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_status": {
 | 
			
		||||
      "name": "machine_status",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "ready": "ready",
 | 
			
		||||
        "building": "building",
 | 
			
		||||
        "error": "error"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_type": {
 | 
			
		||||
      "name": "machine_type",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "classic": "classic",
 | 
			
		||||
        "runpod-serverless": "runpod-serverless",
 | 
			
		||||
        "modal-serverless": "modal-serverless",
 | 
			
		||||
        "comfy-deploy-serverless": "comfy-deploy-serverless"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_origin": {
 | 
			
		||||
      "name": "workflow_run_origin",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "manual": "manual",
 | 
			
		||||
        "api": "api",
 | 
			
		||||
        "public-share": "public-share"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_status": {
 | 
			
		||||
      "name": "workflow_run_status",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "not-started": "not-started",
 | 
			
		||||
        "running": "running",
 | 
			
		||||
        "uploading": "uploading",
 | 
			
		||||
        "success": "success",
 | 
			
		||||
        "failed": "failed"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "schemas": {
 | 
			
		||||
    "comfyui_deploy": "comfyui_deploy"
 | 
			
		||||
  },
 | 
			
		||||
  "_meta": {
 | 
			
		||||
    "schemas": {},
 | 
			
		||||
    "tables": {},
 | 
			
		||||
    "columns": {}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										756
									
								
								web/drizzle/meta/0030_snapshot.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										756
									
								
								web/drizzle/meta/0030_snapshot.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,756 @@
 | 
			
		||||
{
 | 
			
		||||
  "id": "db06ea66-92c2-4ebe-93c1-6cb8a90ccd8b",
 | 
			
		||||
  "prevId": "a7d6a8dd-0e15-4165-98a2-de2a334455dc",
 | 
			
		||||
  "version": "5",
 | 
			
		||||
  "dialect": "pg",
 | 
			
		||||
  "tables": {
 | 
			
		||||
    "api_keys": {
 | 
			
		||||
      "name": "api_keys",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "key": {
 | 
			
		||||
          "name": "key",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "revoked": {
 | 
			
		||||
          "name": "revoked",
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "api_keys_user_id_users_id_fk": {
 | 
			
		||||
          "name": "api_keys_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "api_keys",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {
 | 
			
		||||
        "api_keys_key_unique": {
 | 
			
		||||
          "name": "api_keys_key_unique",
 | 
			
		||||
          "nullsNotDistinct": false,
 | 
			
		||||
          "columns": [
 | 
			
		||||
            "key"
 | 
			
		||||
          ]
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "deployments": {
 | 
			
		||||
      "name": "deployments",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_version_id": {
 | 
			
		||||
          "name": "workflow_version_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "machine_id": {
 | 
			
		||||
          "name": "machine_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "description": {
 | 
			
		||||
          "name": "description",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "showcase_media": {
 | 
			
		||||
          "name": "showcase_media",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "environment": {
 | 
			
		||||
          "name": "environment",
 | 
			
		||||
          "type": "deployment_environment",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "deployments_user_id_users_id_fk": {
 | 
			
		||||
          "name": "deployments_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_workflow_version_id_workflow_versions_id_fk": {
 | 
			
		||||
          "name": "deployments_workflow_version_id_workflow_versions_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "workflow_versions",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_version_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "no action",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "deployments_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "deployments_machine_id_machines_id_fk": {
 | 
			
		||||
          "name": "deployments_machine_id_machines_id_fk",
 | 
			
		||||
          "tableFrom": "deployments",
 | 
			
		||||
          "tableTo": "machines",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "machine_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "no action",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "machines": {
 | 
			
		||||
      "name": "machines",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "endpoint": {
 | 
			
		||||
          "name": "endpoint",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "disabled": {
 | 
			
		||||
          "name": "disabled",
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": false
 | 
			
		||||
        },
 | 
			
		||||
        "auth_token": {
 | 
			
		||||
          "name": "auth_token",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "type": {
 | 
			
		||||
          "name": "type",
 | 
			
		||||
          "type": "machine_type",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'classic'"
 | 
			
		||||
        },
 | 
			
		||||
        "status": {
 | 
			
		||||
          "name": "status",
 | 
			
		||||
          "type": "machine_status",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'ready'"
 | 
			
		||||
        },
 | 
			
		||||
        "snapshot": {
 | 
			
		||||
          "name": "snapshot",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "models": {
 | 
			
		||||
          "name": "models",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "gpu": {
 | 
			
		||||
          "name": "gpu",
 | 
			
		||||
          "type": "machine_gpu",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "build_machine_instance_id": {
 | 
			
		||||
          "name": "build_machine_instance_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "build_log": {
 | 
			
		||||
          "name": "build_log",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "machines_user_id_users_id_fk": {
 | 
			
		||||
          "name": "machines_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "machines",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "users": {
 | 
			
		||||
      "name": "users",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "username": {
 | 
			
		||||
          "name": "username",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {},
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_outputs": {
 | 
			
		||||
      "name": "workflow_run_outputs",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "run_id": {
 | 
			
		||||
          "name": "run_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "data": {
 | 
			
		||||
          "name": "data",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_run_outputs_run_id_workflow_runs_id_fk": {
 | 
			
		||||
          "name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_run_outputs",
 | 
			
		||||
          "tableTo": "workflow_runs",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "run_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_runs": {
 | 
			
		||||
      "name": "workflow_runs",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_version_id": {
 | 
			
		||||
          "name": "workflow_version_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_inputs": {
 | 
			
		||||
          "name": "workflow_inputs",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "machine_id": {
 | 
			
		||||
          "name": "machine_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "origin": {
 | 
			
		||||
          "name": "origin",
 | 
			
		||||
          "type": "workflow_run_origin",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'api'"
 | 
			
		||||
        },
 | 
			
		||||
        "status": {
 | 
			
		||||
          "name": "status",
 | 
			
		||||
          "type": "workflow_run_status",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "'not-started'"
 | 
			
		||||
        },
 | 
			
		||||
        "ended_at": {
 | 
			
		||||
          "name": "ended_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_runs_workflow_version_id_workflow_versions_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "workflow_versions",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_version_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "set null",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_runs_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_runs_machine_id_machines_id_fk": {
 | 
			
		||||
          "name": "workflow_runs_machine_id_machines_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_runs",
 | 
			
		||||
          "tableTo": "machines",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "machine_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "set null",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflows": {
 | 
			
		||||
      "name": "workflows",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "user_id": {
 | 
			
		||||
          "name": "user_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "org_id": {
 | 
			
		||||
          "name": "org_id",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "name": {
 | 
			
		||||
          "name": "name",
 | 
			
		||||
          "type": "text",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflows_user_id_users_id_fk": {
 | 
			
		||||
          "name": "workflows_user_id_users_id_fk",
 | 
			
		||||
          "tableFrom": "workflows",
 | 
			
		||||
          "tableTo": "users",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "user_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_versions": {
 | 
			
		||||
      "name": "workflow_versions",
 | 
			
		||||
      "schema": "comfyui_deploy",
 | 
			
		||||
      "columns": {
 | 
			
		||||
        "workflow_id": {
 | 
			
		||||
          "name": "workflow_id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "id": {
 | 
			
		||||
          "name": "id",
 | 
			
		||||
          "type": "uuid",
 | 
			
		||||
          "primaryKey": true,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "gen_random_uuid()"
 | 
			
		||||
        },
 | 
			
		||||
        "workflow": {
 | 
			
		||||
          "name": "workflow",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "workflow_api": {
 | 
			
		||||
          "name": "workflow_api",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "version": {
 | 
			
		||||
          "name": "version",
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true
 | 
			
		||||
        },
 | 
			
		||||
        "snapshot": {
 | 
			
		||||
          "name": "snapshot",
 | 
			
		||||
          "type": "jsonb",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": false
 | 
			
		||||
        },
 | 
			
		||||
        "created_at": {
 | 
			
		||||
          "name": "created_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        },
 | 
			
		||||
        "updated_at": {
 | 
			
		||||
          "name": "updated_at",
 | 
			
		||||
          "type": "timestamp",
 | 
			
		||||
          "primaryKey": false,
 | 
			
		||||
          "notNull": true,
 | 
			
		||||
          "default": "now()"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "indexes": {},
 | 
			
		||||
      "foreignKeys": {
 | 
			
		||||
        "workflow_versions_workflow_id_workflows_id_fk": {
 | 
			
		||||
          "name": "workflow_versions_workflow_id_workflows_id_fk",
 | 
			
		||||
          "tableFrom": "workflow_versions",
 | 
			
		||||
          "tableTo": "workflows",
 | 
			
		||||
          "columnsFrom": [
 | 
			
		||||
            "workflow_id"
 | 
			
		||||
          ],
 | 
			
		||||
          "columnsTo": [
 | 
			
		||||
            "id"
 | 
			
		||||
          ],
 | 
			
		||||
          "onDelete": "cascade",
 | 
			
		||||
          "onUpdate": "no action"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "compositePrimaryKeys": {},
 | 
			
		||||
      "uniqueConstraints": {}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "enums": {
 | 
			
		||||
    "deployment_environment": {
 | 
			
		||||
      "name": "deployment_environment",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "staging": "staging",
 | 
			
		||||
        "production": "production",
 | 
			
		||||
        "public-share": "public-share"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_gpu": {
 | 
			
		||||
      "name": "machine_gpu",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "T4": "T4",
 | 
			
		||||
        "A10G": "A10G",
 | 
			
		||||
        "A100": "A100"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_status": {
 | 
			
		||||
      "name": "machine_status",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "ready": "ready",
 | 
			
		||||
        "building": "building",
 | 
			
		||||
        "error": "error"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "machine_type": {
 | 
			
		||||
      "name": "machine_type",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "classic": "classic",
 | 
			
		||||
        "runpod-serverless": "runpod-serverless",
 | 
			
		||||
        "modal-serverless": "modal-serverless",
 | 
			
		||||
        "comfy-deploy-serverless": "comfy-deploy-serverless"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_origin": {
 | 
			
		||||
      "name": "workflow_run_origin",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "manual": "manual",
 | 
			
		||||
        "api": "api",
 | 
			
		||||
        "public-share": "public-share"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "workflow_run_status": {
 | 
			
		||||
      "name": "workflow_run_status",
 | 
			
		||||
      "values": {
 | 
			
		||||
        "not-started": "not-started",
 | 
			
		||||
        "running": "running",
 | 
			
		||||
        "uploading": "uploading",
 | 
			
		||||
        "success": "success",
 | 
			
		||||
        "failed": "failed"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "schemas": {
 | 
			
		||||
    "comfyui_deploy": "comfyui_deploy"
 | 
			
		||||
  },
 | 
			
		||||
  "_meta": {
 | 
			
		||||
    "schemas": {},
 | 
			
		||||
    "tables": {},
 | 
			
		||||
    "columns": {}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -204,6 +204,20 @@
 | 
			
		||||
      "when": 1705642345817,
 | 
			
		||||
      "tag": "0028_futuristic_lady_deathstrike",
 | 
			
		||||
      "breakpoints": true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "idx": 29,
 | 
			
		||||
      "version": "5",
 | 
			
		||||
      "when": 1705662714161,
 | 
			
		||||
      "tag": "0029_large_frightful_four",
 | 
			
		||||
      "breakpoints": true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "idx": 30,
 | 
			
		||||
      "version": "5",
 | 
			
		||||
      "when": 1705716303820,
 | 
			
		||||
      "tag": "0030_kind_doorman",
 | 
			
		||||
      "breakpoints": true
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -60,6 +60,7 @@
 | 
			
		||||
    "dayjs": "^1.11.10",
 | 
			
		||||
    "drizzle-orm": "^0.29.1",
 | 
			
		||||
    "drizzle-zod": "^0.5.1",
 | 
			
		||||
    "embla-carousel-react": "^8.0.0-rc19",
 | 
			
		||||
    "fast-glob": "^3.3.2",
 | 
			
		||||
    "flexsearch": "^0.7.31",
 | 
			
		||||
    "framer-motion": "^10.16.16",
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,9 @@
 | 
			
		||||
import { SharePageSettings } from "@/components/SharePageSettings";
 | 
			
		||||
 | 
			
		||||
export default async function Page({
 | 
			
		||||
  params,
 | 
			
		||||
}: {
 | 
			
		||||
  params: { share_id: string };
 | 
			
		||||
}) {
 | 
			
		||||
  return <SharePageSettings deployment_id={params.share_id} />;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								web/src/app/(app)/@modal/default.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								web/src/app/(app)/@modal/default.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
import type { FC } from "react";
 | 
			
		||||
 | 
			
		||||
const Default: FC = () => {
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Default;
 | 
			
		||||
@ -27,8 +27,10 @@ export const metadata: Metadata = {
 | 
			
		||||
 | 
			
		||||
export default function RootLayout({
 | 
			
		||||
  children,
 | 
			
		||||
  modal,
 | 
			
		||||
}: {
 | 
			
		||||
  children: React.ReactNode;
 | 
			
		||||
  modal: React.ReactNode;
 | 
			
		||||
}) {
 | 
			
		||||
  return (
 | 
			
		||||
    <html lang="en">
 | 
			
		||||
@ -51,6 +53,7 @@ export default function RootLayout({
 | 
			
		||||
                {children}
 | 
			
		||||
              </div>
 | 
			
		||||
              <Toaster richColors />
 | 
			
		||||
              {modal}
 | 
			
		||||
            </main>
 | 
			
		||||
          </body>
 | 
			
		||||
        </TooltipProvider>
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
import { ButtonActionMenu } from "@/components/ButtonActionLoader";
 | 
			
		||||
import {
 | 
			
		||||
  PublicRunOutputs,
 | 
			
		||||
} from "@/components/VersionSelect";
 | 
			
		||||
import { RunWorkflowInline } from "@/components/RunWorkflowInline";
 | 
			
		||||
import { PublicRunOutputs } from "@/components/VersionSelect";
 | 
			
		||||
import {
 | 
			
		||||
  Card,
 | 
			
		||||
  CardContent,
 | 
			
		||||
@ -89,6 +87,11 @@ export default async function Page({
 | 
			
		||||
        </CardHeader>
 | 
			
		||||
 | 
			
		||||
        <CardContent>
 | 
			
		||||
          <div>
 | 
			
		||||
            {sharedDeployment?.description && (
 | 
			
		||||
              <>{sharedDeployment?.description}</>
 | 
			
		||||
            )}
 | 
			
		||||
          </div>
 | 
			
		||||
          <RunWorkflowInline
 | 
			
		||||
            inputs={inputs}
 | 
			
		||||
            machine_id={sharedDeployment.machine_id}
 | 
			
		||||
@ -102,7 +105,7 @@ export default async function Page({
 | 
			
		||||
        </CardHeader>
 | 
			
		||||
 | 
			
		||||
        <CardContent>
 | 
			
		||||
          <PublicRunOutputs />
 | 
			
		||||
          <PublicRunOutputs preview={sharedDeployment.showcase_media} />
 | 
			
		||||
        </CardContent>
 | 
			
		||||
      </Card>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								web/src/app/(app)/share/[share_id]/settings/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								web/src/app/(app)/share/[share_id]/settings/page.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
import { SharePageSettings } from "@/components/SharePageSettings";
 | 
			
		||||
 | 
			
		||||
export default async function Page({
 | 
			
		||||
  params,
 | 
			
		||||
}: {
 | 
			
		||||
  params: { share_id: string };
 | 
			
		||||
}) {
 | 
			
		||||
  return <SharePageSettings deployment_id={params.share_id} />;
 | 
			
		||||
}
 | 
			
		||||
@ -17,7 +17,7 @@ export default async function Page({
 | 
			
		||||
      <CardHeader className="relative">
 | 
			
		||||
        <CardTitle>Run</CardTitle>
 | 
			
		||||
        <div className="absolute right-6 top-6">
 | 
			
		||||
          <RouteRefresher interval={5000} />
 | 
			
		||||
          <RouteRefresher interval={5000} autoRefresh={false} />
 | 
			
		||||
        </div>
 | 
			
		||||
      </CardHeader>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@ import {
 | 
			
		||||
  DropdownMenuItem,
 | 
			
		||||
  DropdownMenuTrigger,
 | 
			
		||||
} from "@/components/ui/dropdown-menu";
 | 
			
		||||
import { useAuth, useClerk } from "@clerk/nextjs";
 | 
			
		||||
import { MoreVertical } from "lucide-react";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
@ -49,7 +50,9 @@ export function ButtonActionMenu(props: {
 | 
			
		||||
    action: () => Promise<any>;
 | 
			
		||||
  }[];
 | 
			
		||||
}) {
 | 
			
		||||
  const user = useAuth();
 | 
			
		||||
  const [isLoading, setIsLoading] = useState(false);
 | 
			
		||||
  const clerk = useClerk();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <DropdownMenu>
 | 
			
		||||
@ -64,6 +67,13 @@ export function ButtonActionMenu(props: {
 | 
			
		||||
          <DropdownMenuItem
 | 
			
		||||
            key={action.title}
 | 
			
		||||
            onClick={async () => {
 | 
			
		||||
              if (!user.isSignedIn) {
 | 
			
		||||
                clerk.openSignIn({
 | 
			
		||||
                  redirectUrl: window.location.href,
 | 
			
		||||
                });
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              setIsLoading(true);
 | 
			
		||||
              await callServerPromise(action.action());
 | 
			
		||||
              setIsLoading(false);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
import { ButtonAction } from "@/components/ButtonActionLoader";
 | 
			
		||||
import { DeploymentRow } from "./DeploymentRow";
 | 
			
		||||
import { CodeBlock } from "@/components/CodeBlock";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import {
 | 
			
		||||
  Dialog,
 | 
			
		||||
  DialogContent,
 | 
			
		||||
@ -10,15 +9,9 @@ import {
 | 
			
		||||
  DialogTrigger,
 | 
			
		||||
} from "@/components/ui/dialog";
 | 
			
		||||
import { ScrollArea } from "@/components/ui/scroll-area";
 | 
			
		||||
import { TableCell, TableRow } from "@/components/ui/table";
 | 
			
		||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
 | 
			
		||||
import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow";
 | 
			
		||||
import { getRelativeTime } from "@/lib/getRelativeTime";
 | 
			
		||||
import { removePublicShareDeployment } from "@/server/curdDeploments";
 | 
			
		||||
import type { findAllDeployments } from "@/server/findAllRuns";
 | 
			
		||||
import { ExternalLink } from "lucide-react";
 | 
			
		||||
import { headers } from "next/headers";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
 | 
			
		||||
const curlTemplate = `
 | 
			
		||||
curl --request POST \
 | 
			
		||||
@ -90,33 +83,21 @@ const run = await client.getRun(run_id);
 | 
			
		||||
 | 
			
		||||
export function DeploymentDisplay({
 | 
			
		||||
  deployment,
 | 
			
		||||
  domain,
 | 
			
		||||
}: {
 | 
			
		||||
  deployment: Awaited<ReturnType<typeof findAllDeployments>>[0];
 | 
			
		||||
  domain: string;
 | 
			
		||||
}) {
 | 
			
		||||
  const headersList = headers();
 | 
			
		||||
  const host = headersList.get("host") || "";
 | 
			
		||||
  const protocol = headersList.get("x-forwarded-proto") || "";
 | 
			
		||||
  const domain = `${protocol}://${host}`;
 | 
			
		||||
 | 
			
		||||
  const workflowInput = getInputsFromWorkflow(deployment.version);
 | 
			
		||||
 | 
			
		||||
  if (deployment.environment == "public-share") {
 | 
			
		||||
    return <DeploymentRow deployment={deployment} />;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog>
 | 
			
		||||
      <DialogTrigger asChild className="appearance-none hover:cursor-pointer">
 | 
			
		||||
        <TableRow>
 | 
			
		||||
          <TableCell className="capitalize truncate">
 | 
			
		||||
            {deployment.environment}
 | 
			
		||||
          </TableCell>
 | 
			
		||||
          <TableCell className="font-medium truncate">
 | 
			
		||||
            {deployment.version?.version}
 | 
			
		||||
          </TableCell>
 | 
			
		||||
          <TableCell className="font-medium truncate">
 | 
			
		||||
            {deployment.machine?.name}
 | 
			
		||||
          </TableCell>
 | 
			
		||||
          <TableCell className="text-right truncate">
 | 
			
		||||
            {getRelativeTime(deployment.updated_at)}
 | 
			
		||||
          </TableCell>
 | 
			
		||||
        </TableRow>
 | 
			
		||||
        <DeploymentRow deployment={deployment} />
 | 
			
		||||
      </DialogTrigger>
 | 
			
		||||
      <DialogContent className="max-w-3xl">
 | 
			
		||||
        <DialogHeader>
 | 
			
		||||
@ -126,7 +107,6 @@ export function DeploymentDisplay({
 | 
			
		||||
          <DialogDescription>Code for your deployment client</DialogDescription>
 | 
			
		||||
        </DialogHeader>
 | 
			
		||||
        <ScrollArea className="max-h-[600px] pr-4">
 | 
			
		||||
          {deployment.environment !== "public-share" ? (
 | 
			
		||||
          <Tabs defaultValue="client" className="w-full gap-2 text-sm">
 | 
			
		||||
            <TabsList className="grid w-fit grid-cols-3 mb-2">
 | 
			
		||||
              <TabsTrigger value="client">Server Client</TabsTrigger>
 | 
			
		||||
@ -181,12 +161,7 @@ export function DeploymentDisplay({
 | 
			
		||||
              Trigger the workflow
 | 
			
		||||
              <CodeBlock
 | 
			
		||||
                lang="js"
 | 
			
		||||
                  code={formatCode(
 | 
			
		||||
                    jsTemplate,
 | 
			
		||||
                    deployment,
 | 
			
		||||
                    domain,
 | 
			
		||||
                    workflowInput
 | 
			
		||||
                  )}
 | 
			
		||||
                code={formatCode(jsTemplate, deployment, domain, workflowInput)}
 | 
			
		||||
              />
 | 
			
		||||
              Check the status of the run, and retrieve the outputs
 | 
			
		||||
              <CodeBlock
 | 
			
		||||
@ -201,30 +176,10 @@ export function DeploymentDisplay({
 | 
			
		||||
              />
 | 
			
		||||
              <CodeBlock
 | 
			
		||||
                lang="bash"
 | 
			
		||||
                  code={formatCode(
 | 
			
		||||
                    curlTemplate_checkStatus,
 | 
			
		||||
                    deployment,
 | 
			
		||||
                    domain
 | 
			
		||||
                  )}
 | 
			
		||||
                code={formatCode(curlTemplate_checkStatus, deployment, domain)}
 | 
			
		||||
              />
 | 
			
		||||
            </TabsContent>
 | 
			
		||||
          </Tabs>
 | 
			
		||||
          ) : (
 | 
			
		||||
            <div className="w-full justify-end flex gap-2 py-1">
 | 
			
		||||
              <Button asChild className="gap-2" variant="outline" type="submit">
 | 
			
		||||
                <ButtonAction
 | 
			
		||||
                  action={removePublicShareDeployment.bind(null, deployment.id)}
 | 
			
		||||
                >
 | 
			
		||||
                  Remove
 | 
			
		||||
                </ButtonAction>
 | 
			
		||||
              </Button>
 | 
			
		||||
              <Button asChild className="gap-2">
 | 
			
		||||
                <Link href={`/share/${deployment.id}`} target="_blank">
 | 
			
		||||
                  View Share Page <ExternalLink size={14} />
 | 
			
		||||
                </Link>
 | 
			
		||||
              </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
        </ScrollArea>
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
    </Dialog>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								web/src/components/DeploymentRow.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								web/src/components/DeploymentRow.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { TableCell, TableRow } from "@/components/ui/table";
 | 
			
		||||
import { getRelativeTime } from "@/lib/getRelativeTime";
 | 
			
		||||
import type { findAllDeployments } from "@/server/findAllRuns";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
 | 
			
		||||
export function DeploymentRow({
 | 
			
		||||
  deployment,
 | 
			
		||||
}: {
 | 
			
		||||
  deployment: Awaited<ReturnType<typeof findAllDeployments>>[0];
 | 
			
		||||
}) {
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  return (
 | 
			
		||||
    <TableRow
 | 
			
		||||
      className="appearance-none hover:cursor-pointer"
 | 
			
		||||
      onClick={() => {
 | 
			
		||||
        if (deployment.environment == "public-share") {
 | 
			
		||||
          router.push(`/share/${deployment.id}/settings`);
 | 
			
		||||
        }
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <TableCell className="capitalize truncate">
 | 
			
		||||
        {deployment.environment}
 | 
			
		||||
      </TableCell>
 | 
			
		||||
      <TableCell className="font-medium truncate">
 | 
			
		||||
        {deployment.version?.version}
 | 
			
		||||
      </TableCell>
 | 
			
		||||
      <TableCell className="font-medium truncate">
 | 
			
		||||
        {deployment.machine?.name}
 | 
			
		||||
      </TableCell>
 | 
			
		||||
      <TableCell className="text-right truncate">
 | 
			
		||||
        {getRelativeTime(deployment.updated_at)}
 | 
			
		||||
      </TableCell>
 | 
			
		||||
    </TableRow>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -11,6 +11,7 @@ import {
 | 
			
		||||
  DialogDescription,
 | 
			
		||||
  DialogHeader,
 | 
			
		||||
  DialogTitle,
 | 
			
		||||
  DialogTrigger,
 | 
			
		||||
} from "@/components/ui/dialog";
 | 
			
		||||
import {
 | 
			
		||||
  Tooltip,
 | 
			
		||||
@ -106,12 +107,14 @@ export function UpdateModal<
 | 
			
		||||
  Y extends UnknownKeysParam,
 | 
			
		||||
  Z extends ZodObject<K, Y>
 | 
			
		||||
>(props: {
 | 
			
		||||
  open: boolean;
 | 
			
		||||
  setOpen: (open: boolean) => void;
 | 
			
		||||
  open?: boolean;
 | 
			
		||||
  setOpen?: (open: boolean) => void;
 | 
			
		||||
  title: string;
 | 
			
		||||
  description: string;
 | 
			
		||||
  dialogClassName?: string;
 | 
			
		||||
  data: z.infer<Z>;
 | 
			
		||||
  data: z.infer<Z> & {
 | 
			
		||||
    id: string;
 | 
			
		||||
  };
 | 
			
		||||
  serverAction: (
 | 
			
		||||
    data: z.infer<Z> & {
 | 
			
		||||
      id: string;
 | 
			
		||||
@ -119,8 +122,13 @@ export function UpdateModal<
 | 
			
		||||
  ) => Promise<unknown>;
 | 
			
		||||
  formSchema: Z;
 | 
			
		||||
  fieldConfig?: FieldConfig<z.infer<Z>>;
 | 
			
		||||
  trigger?: React.ReactNode;
 | 
			
		||||
  extraButtons?: React.ReactNode;
 | 
			
		||||
}) {
 | 
			
		||||
  // const [open, setOpen] = React.useState(false);
 | 
			
		||||
  const [_open, _setOpen] = React.useState(false);
 | 
			
		||||
  const open = props.open ?? _open;
 | 
			
		||||
  const setOpen = props.setOpen ?? _setOpen;
 | 
			
		||||
 | 
			
		||||
  const [values, setValues] = useState<Partial<z.infer<Z>>>({});
 | 
			
		||||
  const [isLoading, setIsLoading] = React.useState(false);
 | 
			
		||||
 | 
			
		||||
@ -129,10 +137,18 @@ export function UpdateModal<
 | 
			
		||||
  }, [props.data]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog open={props.open} onOpenChange={props.setOpen}>
 | 
			
		||||
      {/* <DialogTrigger asChild>
 | 
			
		||||
        <DropdownMenuItem>{props.title}</DropdownMenuItem>
 | 
			
		||||
      </DialogTrigger> */}
 | 
			
		||||
    <Dialog open={open} onOpenChange={setOpen}>
 | 
			
		||||
      {props.trigger ?? (
 | 
			
		||||
        <DialogTrigger
 | 
			
		||||
          className="appearance-none hover:cursor-pointer"
 | 
			
		||||
          asChild
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            setOpen(true);
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          {props.trigger}
 | 
			
		||||
        </DialogTrigger>
 | 
			
		||||
      )}
 | 
			
		||||
      <DialogContent className={cn("sm:max-w-[425px]", props.dialogClassName)}>
 | 
			
		||||
        <DialogHeader>
 | 
			
		||||
          <DialogTitle>{props.title}</DialogTitle>
 | 
			
		||||
@ -152,13 +168,14 @@ export function UpdateModal<
 | 
			
		||||
              })
 | 
			
		||||
            );
 | 
			
		||||
            setIsLoading(false);
 | 
			
		||||
            props.setOpen(false);
 | 
			
		||||
            setOpen(false);
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <div className="flex justify-end">
 | 
			
		||||
          <div className="flex justify-end flex-wrap gap-2">
 | 
			
		||||
            {props.extraButtons}
 | 
			
		||||
            <AutoFormSubmit>
 | 
			
		||||
              Save Changes
 | 
			
		||||
              <span className="ml-2">{isLoading && <LoadingIcon />}</span>
 | 
			
		||||
              {isLoading && <LoadingIcon />}
 | 
			
		||||
            </AutoFormSubmit>
 | 
			
		||||
          </div>
 | 
			
		||||
        </AutoForm>
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,7 @@ export default async function Main() {
 | 
			
		||||
            </Section.Announcement>
 | 
			
		||||
 | 
			
		||||
            <Section.Title className="text-left">
 | 
			
		||||
              <span className="text-6xl md:text-7xl pb-2 inline-flex animate-background-shine bg-[linear-gradient(110deg,#1e293b,45%,#939393,55%,#1e293b)] bg-[length:250%_100%] bg-clip-text text-transparent">
 | 
			
		||||
              <span className="text-5xl sm:text-6xl md:text-7xl pb-2 inline-flex animate-background-shine bg-[linear-gradient(110deg,#1e293b,45%,#939393,55%,#1e293b)] bg-[length:250%_100%] bg-clip-text text-transparent">
 | 
			
		||||
                {meta.tagline}
 | 
			
		||||
              </span>
 | 
			
		||||
            </Section.Title>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								web/src/components/OutputPreviews.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								web/src/components/OutputPreviews.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
import { Card, CardContent } from "@/components/ui/card";
 | 
			
		||||
import {
 | 
			
		||||
  Carousel,
 | 
			
		||||
  CarouselContent,
 | 
			
		||||
  CarouselItem,
 | 
			
		||||
  CarouselNext,
 | 
			
		||||
  CarouselPrevious,
 | 
			
		||||
  type CarouselApi,
 | 
			
		||||
} from "@/components/ui/carousel";
 | 
			
		||||
import * as React from "react";
 | 
			
		||||
 | 
			
		||||
export function OutputPreview() {
 | 
			
		||||
  const [api, setApi] = React.useState<CarouselApi>();
 | 
			
		||||
  const [current, setCurrent] = React.useState(0);
 | 
			
		||||
  const [count, setCount] = React.useState(0);
 | 
			
		||||
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    if (!api) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setCount(api.scrollSnapList().length);
 | 
			
		||||
    setCurrent(api.selectedScrollSnap() + 1);
 | 
			
		||||
 | 
			
		||||
    api.on("select", () => {
 | 
			
		||||
      setCurrent(api.selectedScrollSnap() + 1);
 | 
			
		||||
    });
 | 
			
		||||
  }, [api]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <Carousel setApi={setApi} className="w-full max-w-xs">
 | 
			
		||||
        <CarouselContent>
 | 
			
		||||
          {Array.from({ length: 5 }).map((_, index) => (
 | 
			
		||||
            <CarouselItem key={index}>
 | 
			
		||||
              <Card>
 | 
			
		||||
                <CardContent className="flex aspect-square items-center justify-center p-6">
 | 
			
		||||
                  <span className="text-4xl font-semibold">{index + 1}</span>
 | 
			
		||||
                </CardContent>
 | 
			
		||||
              </Card>
 | 
			
		||||
            </CarouselItem>
 | 
			
		||||
          ))}
 | 
			
		||||
        </CarouselContent>
 | 
			
		||||
        <CarouselPrevious />
 | 
			
		||||
        <CarouselNext />
 | 
			
		||||
      </Carousel>
 | 
			
		||||
      <div className="py-2 text-center text-sm text-muted-foreground">
 | 
			
		||||
        Slide {current} of {count}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +1,21 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { LoadingIcon } from "@/components/LoadingIcon";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { RefreshCcw } from "lucide-react";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { useEffect, useTransition } from "react";
 | 
			
		||||
 | 
			
		||||
export function RouteRefresher(props: { interval: number }) {
 | 
			
		||||
export function RouteRefresher(props: {
 | 
			
		||||
  interval: number;
 | 
			
		||||
  autoRefresh: boolean;
 | 
			
		||||
}) {
 | 
			
		||||
  const [isPending, startTransition] = useTransition();
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (!props.autoRefresh) return;
 | 
			
		||||
 | 
			
		||||
    let timeout: NodeJS.Timeout;
 | 
			
		||||
 | 
			
		||||
    const refresh = () => {
 | 
			
		||||
@ -35,7 +42,24 @@ export function RouteRefresher(props: { interval: number }) {
 | 
			
		||||
      clearTimeout(timeout);
 | 
			
		||||
      window.removeEventListener("visibilitychange", handleVisibilityChange);
 | 
			
		||||
    };
 | 
			
		||||
  }, [props.interval, router]);
 | 
			
		||||
  }, [props.interval, router, props.autoRefresh]);
 | 
			
		||||
 | 
			
		||||
  return <div>{isPending && <LoadingIcon />}</div>;
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      {isPending && <LoadingIcon />}
 | 
			
		||||
      {!isPending && !props.autoRefresh && (
 | 
			
		||||
        <Button
 | 
			
		||||
          className="p-0 h-min"
 | 
			
		||||
          variant="ghost"
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            startTransition(() => {
 | 
			
		||||
              router.refresh();
 | 
			
		||||
            });
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <RefreshCcw size={14} />
 | 
			
		||||
        </Button>
 | 
			
		||||
      )}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,9 @@ export async function RunDisplay({
 | 
			
		||||
          </TableCell>
 | 
			
		||||
          <TableCell>{run.version?.version}</TableCell>
 | 
			
		||||
          <TableCell>
 | 
			
		||||
            <Badge variant="outline">{run.origin}</Badge>
 | 
			
		||||
            <Badge variant="outline" className="truncate">
 | 
			
		||||
              {run.origin}
 | 
			
		||||
            </Badge>
 | 
			
		||||
          </TableCell>
 | 
			
		||||
          <LiveStatus run={run} />
 | 
			
		||||
        </TableRow>
 | 
			
		||||
 | 
			
		||||
@ -40,13 +40,10 @@ export function RunWorkflowInline({
 | 
			
		||||
  } = publicRunStore();
 | 
			
		||||
 | 
			
		||||
  const runWorkflow = async () => {
 | 
			
		||||
    console.log();
 | 
			
		||||
 | 
			
		||||
    if (!user.isSignedIn) {
 | 
			
		||||
      clerk.openSignIn({
 | 
			
		||||
        redirectUrl: window.location.href,
 | 
			
		||||
      });
 | 
			
		||||
      console.log("hi");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    console.log(values);
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ import {
 | 
			
		||||
  TableRow,
 | 
			
		||||
} from "@/components/ui/table";
 | 
			
		||||
import { parseAsInteger } from "next-usequerystate";
 | 
			
		||||
import { headers } from "next/headers";
 | 
			
		||||
 | 
			
		||||
const itemPerPage = 6;
 | 
			
		||||
const pageParser = parseAsInteger.withDefault(1);
 | 
			
		||||
@ -69,6 +70,12 @@ export async function RunsTable(props: {
 | 
			
		||||
 | 
			
		||||
export async function DeploymentsTable(props: { workflow_id: string }) {
 | 
			
		||||
  const allRuns = await findAllDeployments(props.workflow_id);
 | 
			
		||||
 | 
			
		||||
  const headersList = headers();
 | 
			
		||||
  const host = headersList.get("host") || "";
 | 
			
		||||
  const protocol = headersList.get("x-forwarded-proto") || "";
 | 
			
		||||
  const domain = `${protocol}://${host}`;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="overflow-auto h-fit w-full">
 | 
			
		||||
      <Table className="">
 | 
			
		||||
@ -83,7 +90,7 @@ export async function DeploymentsTable(props: { workflow_id: string }) {
 | 
			
		||||
        </TableHeader>
 | 
			
		||||
        <TableBody>
 | 
			
		||||
          {allRuns.map((run) => (
 | 
			
		||||
            <DeploymentDisplay deployment={run} key={run.id} />
 | 
			
		||||
            <DeploymentDisplay deployment={run} key={run.id} domain={domain} />
 | 
			
		||||
          ))}
 | 
			
		||||
        </TableBody>
 | 
			
		||||
      </Table>
 | 
			
		||||
 | 
			
		||||
@ -1,33 +1,37 @@
 | 
			
		||||
import { Button, buttonVariants } from '@/components/ui/button';
 | 
			
		||||
type ButtonProps = React.ComponentProps<typeof Button>;
 | 
			
		||||
type LinkProps = React.ComponentProps<typeof Link>;
 | 
			
		||||
import { Card as BaseCard } from '@/components/ui/card';
 | 
			
		||||
type CardProps = React.ComponentProps<typeof BaseCard>;
 | 
			
		||||
import { Tabs, TabsTrigger as Tab, TabsList } from '@/components/ui/tabs';
 | 
			
		||||
type TabsProps = React.ComponentProps<typeof Tabs>;
 | 
			
		||||
import {
 | 
			
		||||
  Accordion,
 | 
			
		||||
  AccordionItem,
 | 
			
		||||
  AccordionContent,
 | 
			
		||||
  AccordionTrigger,
 | 
			
		||||
} from '@/components/ui/accordion';
 | 
			
		||||
type AccordionProps = React.ComponentProps<typeof Accordion>;
 | 
			
		||||
import { Badge as Chip } from '@/components/ui/badge';
 | 
			
		||||
type ChipProps = React.ComponentProps<typeof Chip>;
 | 
			
		||||
 | 
			
		||||
import Link from 'next/link';
 | 
			
		||||
} from "@/components/ui/accordion";
 | 
			
		||||
import { Badge as Chip } from "@/components/ui/badge";
 | 
			
		||||
import { Button, buttonVariants } from "@/components/ui/button";
 | 
			
		||||
import { Card as BaseCard } from "@/components/ui/card";
 | 
			
		||||
import { Tabs, TabsTrigger as Tab, TabsList } from "@/components/ui/tabs";
 | 
			
		||||
// import { PiCheckCircleDuotone } from 'react-icons/pi';
 | 
			
		||||
import { cn } from "@/lib/utils";
 | 
			
		||||
import { ChevronRight as MdChevronRight } from "lucide-react";
 | 
			
		||||
import { CheckCircle as PiCheckCircleDuotone } from "lucide-react";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import type {
 | 
			
		||||
  HTMLAttributeAnchorTarget,
 | 
			
		||||
  HTMLAttributes,
 | 
			
		||||
  ReactNode,
 | 
			
		||||
} from 'react';
 | 
			
		||||
import { twMerge } from 'tailwind-merge';
 | 
			
		||||
import { ChevronRight as MdChevronRight} from 'lucide-react'
 | 
			
		||||
} from "react";
 | 
			
		||||
// import { MdChevronRight } from 'react-icons/md';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { CheckCircle as PiCheckCircleDuotone } from 'lucide-react'
 | 
			
		||||
// import { PiCheckCircleDuotone } from 'react-icons/pi';
 | 
			
		||||
import { cn } from '@/lib/utils';
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { twMerge } from "tailwind-merge";
 | 
			
		||||
 | 
			
		||||
type ButtonProps = React.ComponentProps<typeof Button>;
 | 
			
		||||
type LinkProps = React.ComponentProps<typeof Link>;
 | 
			
		||||
 | 
			
		||||
type CardProps = React.ComponentProps<typeof BaseCard>;
 | 
			
		||||
 | 
			
		||||
type TabsProps = React.ComponentProps<typeof Tabs>;
 | 
			
		||||
 | 
			
		||||
type AccordionProps = React.ComponentProps<typeof Accordion>;
 | 
			
		||||
 | 
			
		||||
type ChipProps = React.ComponentProps<typeof Chip>;
 | 
			
		||||
 | 
			
		||||
function Section({
 | 
			
		||||
  className,
 | 
			
		||||
@ -41,8 +45,8 @@ function Section({
 | 
			
		||||
  return (
 | 
			
		||||
    <section
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'flex min-h-[400px] w-full max-w-6xl flex-col justify-center gap-2 rounded-lg px-10 py-10 md:px-20',
 | 
			
		||||
        className,
 | 
			
		||||
        "flex min-h-[400px] w-full max-w-6xl flex-col justify-center gap-2 rounded-lg px-2 sm:px-10 py-10 md:px-20",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
@ -64,12 +68,12 @@ function Title({
 | 
			
		||||
    <h1
 | 
			
		||||
      {...props}
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'text-center text-4xl font-bold md:text-6xl',
 | 
			
		||||
        className,
 | 
			
		||||
        "text-center text-4xl font-bold md:text-6xl",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      style={{
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        textWrap: 'balance',
 | 
			
		||||
        textWrap: "balance",
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {children}
 | 
			
		||||
@ -86,12 +90,12 @@ function Subtitle({
 | 
			
		||||
    <h2
 | 
			
		||||
      {...props}
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'text text-center overflow-hidden text-ellipsis text-xl',
 | 
			
		||||
        className,
 | 
			
		||||
        "text text-center overflow-hidden text-ellipsis text-xl",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      style={{
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        textWrap: 'balance',
 | 
			
		||||
        textWrap: "balance",
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {children}
 | 
			
		||||
@ -103,7 +107,7 @@ function Announcement({
 | 
			
		||||
  className,
 | 
			
		||||
  children,
 | 
			
		||||
  href,
 | 
			
		||||
  target = '_blank',
 | 
			
		||||
  target = "_blank",
 | 
			
		||||
  ...props
 | 
			
		||||
}: ChipProps & {
 | 
			
		||||
  href?: string; //string | UrlObject;
 | 
			
		||||
@ -112,8 +116,8 @@ function Announcement({
 | 
			
		||||
  return (
 | 
			
		||||
    <Chip
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'w-fit group bg-foreground-50 text-center transition-colors hover:bg-gray-200',
 | 
			
		||||
        className,
 | 
			
		||||
        "w-fit group bg-foreground-50 text-center transition-colors hover:bg-gray-200",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      variant="outline"
 | 
			
		||||
      // href={href}
 | 
			
		||||
@ -127,13 +131,13 @@ function Announcement({
 | 
			
		||||
      // }
 | 
			
		||||
      style={{
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        textWrap: 'balance',
 | 
			
		||||
        textWrap: "balance",
 | 
			
		||||
      }}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
      <a href={href} target={target}>
 | 
			
		||||
        {children}
 | 
			
		||||
      </a>{' '}
 | 
			
		||||
      </a>{" "}
 | 
			
		||||
      <MdChevronRight
 | 
			
		||||
        size={20}
 | 
			
		||||
        className="pr-1 transition-transform group-hover:translate-x-[2px]"
 | 
			
		||||
@ -143,14 +147,14 @@ function Announcement({
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ActionProps = ButtonProps & {
 | 
			
		||||
  be: 'button';
 | 
			
		||||
  be: "button";
 | 
			
		||||
  hideArrow?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type ActionLinkProps = LinkProps & {
 | 
			
		||||
  be?: 'a';
 | 
			
		||||
  be?: "a";
 | 
			
		||||
  hideArrow?: boolean;
 | 
			
		||||
  variant?: ButtonProps['variant'];
 | 
			
		||||
  variant?: ButtonProps["variant"];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function PrimaryAction({
 | 
			
		||||
@ -160,15 +164,15 @@ function PrimaryAction({
 | 
			
		||||
  hideArrow,
 | 
			
		||||
  ...props
 | 
			
		||||
}: ActionLinkProps | ActionProps) {
 | 
			
		||||
  if (props.be === 'button') {
 | 
			
		||||
  if (props.be === "button") {
 | 
			
		||||
    return (
 | 
			
		||||
      <Button
 | 
			
		||||
        className={cn(
 | 
			
		||||
          buttonVariants({
 | 
			
		||||
            variant: variant,
 | 
			
		||||
          }),
 | 
			
		||||
          'group',
 | 
			
		||||
          className,
 | 
			
		||||
          "group",
 | 
			
		||||
          className
 | 
			
		||||
        )}
 | 
			
		||||
        {...props}
 | 
			
		||||
      >
 | 
			
		||||
@ -186,8 +190,8 @@ function PrimaryAction({
 | 
			
		||||
        buttonVariants({
 | 
			
		||||
          variant: variant,
 | 
			
		||||
        }),
 | 
			
		||||
        'group',
 | 
			
		||||
        className,
 | 
			
		||||
        "group",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
@ -206,17 +210,17 @@ function SecondaryAction({
 | 
			
		||||
  hideArrow,
 | 
			
		||||
  ...props
 | 
			
		||||
}: ActionLinkProps | ActionProps) {
 | 
			
		||||
  if (props.be === 'button') {
 | 
			
		||||
  if (props.be === "button") {
 | 
			
		||||
    return (
 | 
			
		||||
      <Button
 | 
			
		||||
        className={cn(
 | 
			
		||||
          buttonVariants({
 | 
			
		||||
            variant: variant,
 | 
			
		||||
          }),
 | 
			
		||||
          'group',
 | 
			
		||||
          className,
 | 
			
		||||
          "group",
 | 
			
		||||
          className
 | 
			
		||||
        )}
 | 
			
		||||
        variant={'ghost'}
 | 
			
		||||
        variant="ghost"
 | 
			
		||||
        {...props}
 | 
			
		||||
      >
 | 
			
		||||
        {children}
 | 
			
		||||
@ -231,10 +235,10 @@ function SecondaryAction({
 | 
			
		||||
    <Link
 | 
			
		||||
      className={cn(
 | 
			
		||||
        buttonVariants({
 | 
			
		||||
          variant: 'ghost',
 | 
			
		||||
          variant: "ghost",
 | 
			
		||||
        }),
 | 
			
		||||
        'group',
 | 
			
		||||
        className,
 | 
			
		||||
        "group",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
@ -249,31 +253,31 @@ function PricingCard({
 | 
			
		||||
  className,
 | 
			
		||||
  children,
 | 
			
		||||
  ...props
 | 
			
		||||
}: Omit<CardProps, 'children'> & {
 | 
			
		||||
}: Omit<CardProps, "children"> & {
 | 
			
		||||
  children:
 | 
			
		||||
    | ReactNode
 | 
			
		||||
    | ReactNode[]
 | 
			
		||||
    | ((pricingType: PricingType) => ReactNode | ReactNode[]);
 | 
			
		||||
}) {
 | 
			
		||||
  // const { pricingType } = usePricingContext();
 | 
			
		||||
  if (typeof children === 'function')
 | 
			
		||||
    children = (children('month') as React.ReactElement).props.children as
 | 
			
		||||
  if (typeof children === "function")
 | 
			
		||||
    children = (children("month") as React.ReactElement).props.children as
 | 
			
		||||
      | ReactNode
 | 
			
		||||
      | ReactNode[];
 | 
			
		||||
 | 
			
		||||
  // extract the title and subtitle from the children
 | 
			
		||||
  // const cardTitleStyles =
 | 
			
		||||
  const title = getChildComponent(children, Title, {
 | 
			
		||||
    className: 'text-2xl md:text-2xl text-start font-bold',
 | 
			
		||||
    className: "text-2xl md:text-2xl text-start font-bold",
 | 
			
		||||
  });
 | 
			
		||||
  const subTitle = getChildComponent(children, Subtitle, {
 | 
			
		||||
    className: 'text-md text-start text-foreground-500 mt-4',
 | 
			
		||||
    className: "text-md text-start text-foreground-500 mt-4",
 | 
			
		||||
  });
 | 
			
		||||
  const priceTags = getChildComponents(children, PriceTag, {
 | 
			
		||||
    className: 'text-4xl font-bold',
 | 
			
		||||
    className: "text-4xl font-bold",
 | 
			
		||||
  });
 | 
			
		||||
  const primaryAction = getChildComponent(children, PrimaryAction, {
 | 
			
		||||
    className: 'w-full',
 | 
			
		||||
    className: "w-full",
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@ -281,8 +285,8 @@ function PricingCard({
 | 
			
		||||
      // shadow="sm"
 | 
			
		||||
      {...props}
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'flex flex-col min-h-[400px] w-full max-w-full items-start justify-between gap-2 p-8 text-sm',
 | 
			
		||||
        className,
 | 
			
		||||
        "flex flex-col min-h-[400px] w-full max-w-full items-start justify-between gap-2 p-8 text-sm",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
    >
 | 
			
		||||
      <div>
 | 
			
		||||
@ -320,7 +324,7 @@ function PricingCard({
 | 
			
		||||
//   setPricingType: (pricingType: PricingType) => {},
 | 
			
		||||
// });
 | 
			
		||||
 | 
			
		||||
const PricingTypeValue = ['month', 'year'] as const;
 | 
			
		||||
const PricingTypeValue = ["month", "year"] as const;
 | 
			
		||||
export type PricingType = (typeof PricingTypeValue)[number];
 | 
			
		||||
 | 
			
		||||
// // an helper function to useContext
 | 
			
		||||
@ -350,7 +354,7 @@ function PricingOption({ className, ...props }: TabsProps) {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Tabs
 | 
			
		||||
      className={twMerge('w-fit', className)}
 | 
			
		||||
      className={twMerge("w-fit", className)}
 | 
			
		||||
      defaultValue="month"
 | 
			
		||||
      aria-label="Pricing Options"
 | 
			
		||||
      {...props}
 | 
			
		||||
@ -384,10 +388,10 @@ function PriceTag({
 | 
			
		||||
  pricingType,
 | 
			
		||||
  ...props
 | 
			
		||||
}: HTMLAttributes<HTMLHeadingElement> & {
 | 
			
		||||
  pricingType?: 'month' | 'year' | string;
 | 
			
		||||
  pricingType?: "month" | "year" | string;
 | 
			
		||||
}) {
 | 
			
		||||
  // const { pricingType: currentPricingType } = usePricingContext();
 | 
			
		||||
  let currentPricingType = 'month';
 | 
			
		||||
  const currentPricingType = "month";
 | 
			
		||||
 | 
			
		||||
  if (pricingType != undefined && currentPricingType !== pricingType)
 | 
			
		||||
    return <></>;
 | 
			
		||||
@ -399,10 +403,10 @@ function Card({ className, children, ...props }: CardProps) {
 | 
			
		||||
  // extract the title and subtitle from the children
 | 
			
		||||
  // const cardTitleStyles =
 | 
			
		||||
  const title = getChildComponent(children, Title, {
 | 
			
		||||
    className: 'text-2xl md:text-2xl font-normal text-center',
 | 
			
		||||
    className: "text-2xl md:text-2xl font-normal text-center",
 | 
			
		||||
  });
 | 
			
		||||
  const subTitle = getChildComponent(children, Subtitle, {
 | 
			
		||||
    className: 'text-md text-center',
 | 
			
		||||
    className: "text-md text-center",
 | 
			
		||||
  });
 | 
			
		||||
  const image = getChildComponent(children, ImageArea);
 | 
			
		||||
 | 
			
		||||
@ -411,8 +415,8 @@ function Card({ className, children, ...props }: CardProps) {
 | 
			
		||||
      // shadow="sm"
 | 
			
		||||
      {...props}
 | 
			
		||||
      className={twMerge(
 | 
			
		||||
        'flex min-h-[280px] w-full max-w-full items-center justify-center gap-2 p-4 text-sm flex-col',
 | 
			
		||||
        className,
 | 
			
		||||
        "flex min-h-[280px] w-full max-w-full items-center justify-center gap-2 p-4 text-sm flex-col",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
    >
 | 
			
		||||
      {image}
 | 
			
		||||
@ -431,7 +435,7 @@ function ImageArea({
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      {...props}
 | 
			
		||||
      className={twMerge('aspect-square w-14 bg-foreground-300', className)}
 | 
			
		||||
      className={twMerge("aspect-square w-14 bg-foreground-300", className)}
 | 
			
		||||
    >
 | 
			
		||||
      {children}
 | 
			
		||||
    </div>
 | 
			
		||||
@ -442,11 +446,11 @@ function ImageArea({
 | 
			
		||||
function getChildComponent<T extends (...args: any[]) => React.JSX.Element>(
 | 
			
		||||
  children: React.ReactNode | React.ReactNode[],
 | 
			
		||||
  type: T,
 | 
			
		||||
  propsOverride?: Partial<Parameters<T>[0]>,
 | 
			
		||||
  propsOverride?: Partial<Parameters<T>[0]>
 | 
			
		||||
) {
 | 
			
		||||
  const childrenArr = React.Children.toArray(children);
 | 
			
		||||
  let child = childrenArr.find(
 | 
			
		||||
    (child) => React.isValidElement(child) && child.type === type,
 | 
			
		||||
    (child) => React.isValidElement(child) && child.type === type
 | 
			
		||||
  ) as React.ReactElement<
 | 
			
		||||
    Parameters<T>[0],
 | 
			
		||||
    string | React.JSXElementConstructor<any>
 | 
			
		||||
@ -466,12 +470,12 @@ function getChildComponent<T extends (...args: any[]) => React.JSX.Element>(
 | 
			
		||||
function getChildComponents<T extends (...args: any[]) => React.JSX.Element>(
 | 
			
		||||
  children: React.ReactNode | React.ReactNode[],
 | 
			
		||||
  type: T,
 | 
			
		||||
  propsOverride?: Partial<Parameters<T>[0]>,
 | 
			
		||||
  propsOverride?: Partial<Parameters<T>[0]>
 | 
			
		||||
) {
 | 
			
		||||
  const childrenArr = React.Children.toArray(children);
 | 
			
		||||
  let child = (
 | 
			
		||||
  const child = (
 | 
			
		||||
    childrenArr.filter(
 | 
			
		||||
      (child) => React.isValidElement(child) && child.type === type,
 | 
			
		||||
      (child) => React.isValidElement(child) && child.type === type
 | 
			
		||||
    ) as React.ReactElement<
 | 
			
		||||
      Parameters<T>[0],
 | 
			
		||||
      string | React.JSXElementConstructor<any>
 | 
			
		||||
@ -492,10 +496,10 @@ function getChildComponents<T extends (...args: any[]) => React.JSX.Element>(
 | 
			
		||||
 | 
			
		||||
function removeFromChildren(
 | 
			
		||||
  children: React.ReactNode | React.ReactNode[],
 | 
			
		||||
  types: any[],
 | 
			
		||||
  types: any[]
 | 
			
		||||
): React.ReactNode[] {
 | 
			
		||||
  return React.Children.toArray(children).filter(
 | 
			
		||||
    (child) => React.isValidElement(child) && !types.includes(child.type),
 | 
			
		||||
    (child) => React.isValidElement(child) && !types.includes(child.type)
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -508,11 +512,11 @@ function FAQItem({
 | 
			
		||||
  ...props
 | 
			
		||||
}: {
 | 
			
		||||
  children: React.ReactNode | React.ReactNode[];
 | 
			
		||||
  'aria-label': string;
 | 
			
		||||
  "aria-label": string;
 | 
			
		||||
  title: string;
 | 
			
		||||
}): JSX.Element {
 | 
			
		||||
  return (
 | 
			
		||||
    <AccordionItem value={props['aria-label']}>
 | 
			
		||||
    <AccordionItem value={props["aria-label"]}>
 | 
			
		||||
      <AccordionTrigger>{props.title}</AccordionTrigger>
 | 
			
		||||
      <AccordionContent>{children}</AccordionContent>
 | 
			
		||||
    </AccordionItem>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								web/src/components/SharePageSettings.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								web/src/components/SharePageSettings.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { useServerActionData } from "./useServerActionData";
 | 
			
		||||
import { ButtonAction } from "@/components/ButtonActionLoader";
 | 
			
		||||
import { UpdateModal } from "@/components/InsertModal";
 | 
			
		||||
import { LoadingPageWrapper } from "@/components/LoadingWrapper";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { publicShareDeployment } from "@/db/schema";
 | 
			
		||||
import {
 | 
			
		||||
  findUserShareDeployment,
 | 
			
		||||
  removePublicShareDeployment,
 | 
			
		||||
  updateSharePageInfo,
 | 
			
		||||
} from "@/server/curdDeploments";
 | 
			
		||||
import { ExternalLink } from "lucide-react";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
 | 
			
		||||
export function SharePageSettings({
 | 
			
		||||
  deployment_id,
 | 
			
		||||
}: {
 | 
			
		||||
  deployment_id: string;
 | 
			
		||||
}) {
 | 
			
		||||
  const {
 | 
			
		||||
    data: deployment,
 | 
			
		||||
    pending,
 | 
			
		||||
    started,
 | 
			
		||||
  } = useServerActionData(findUserShareDeployment, deployment_id);
 | 
			
		||||
 | 
			
		||||
  const [_open, _setOpen] = useState(false);
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  if (pending) return <LoadingPageWrapper className="h-full" tag="settings" />;
 | 
			
		||||
 | 
			
		||||
  if (!deployment && started && !pending)
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="h-full w-full flex items-center justify-center">
 | 
			
		||||
        <p>Settings page not found.</p>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  if (!deployment) return null;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <UpdateModal
 | 
			
		||||
        dialogClassName="sm:max-w-[600px]"
 | 
			
		||||
        open={true}
 | 
			
		||||
        setOpen={() => {
 | 
			
		||||
          router.back();
 | 
			
		||||
        }}
 | 
			
		||||
        extraButtons={
 | 
			
		||||
          <>
 | 
			
		||||
            <Button
 | 
			
		||||
              asChild
 | 
			
		||||
              className="gap-2 truncate"
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              type="button"
 | 
			
		||||
            >
 | 
			
		||||
              <ButtonAction
 | 
			
		||||
                action={removePublicShareDeployment.bind(null, deployment.id)}
 | 
			
		||||
              >
 | 
			
		||||
                Remove
 | 
			
		||||
              </ButtonAction>
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button asChild className="gap-2 truncate" type="button">
 | 
			
		||||
              <Link href={`/share/${deployment.id}`} target="_blank">
 | 
			
		||||
                View Share Page <ExternalLink size={14} />
 | 
			
		||||
              </Link>
 | 
			
		||||
            </Button>
 | 
			
		||||
          </>
 | 
			
		||||
        }
 | 
			
		||||
        data={{
 | 
			
		||||
          id: deployment.id,
 | 
			
		||||
          description: deployment.description,
 | 
			
		||||
          showcase_media: deployment.showcase_media ?? [],
 | 
			
		||||
        }}
 | 
			
		||||
        title="Share Page"
 | 
			
		||||
        description="Edit share page details."
 | 
			
		||||
        serverAction={updateSharePageInfo}
 | 
			
		||||
        formSchema={publicShareDeployment}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -39,7 +39,7 @@ import {
 | 
			
		||||
  TableHeader,
 | 
			
		||||
  TableRow,
 | 
			
		||||
} from "@/components/ui/table";
 | 
			
		||||
import type { workflowAPINodeType } from "@/db/schema";
 | 
			
		||||
import type { showcaseMediaNullable, workflowAPINodeType } from "@/db/schema";
 | 
			
		||||
import { checkStatus, createRun } from "@/server/createRun";
 | 
			
		||||
import { createDeployments } from "@/server/curdDeploments";
 | 
			
		||||
import type { getMachines } from "@/server/curdMachine";
 | 
			
		||||
@ -154,7 +154,9 @@ export const publicRunStore = create<PublicRunStore>((set) => ({
 | 
			
		||||
  setStatus: (status) => set({ status }),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export function PublicRunOutputs() {
 | 
			
		||||
export function PublicRunOutputs(props: {
 | 
			
		||||
  preview: z.infer<typeof showcaseMediaNullable>;
 | 
			
		||||
}) {
 | 
			
		||||
  const { image, loading, runId, status, setStatus, setImage, setLoading } =
 | 
			
		||||
    publicRunStore();
 | 
			
		||||
 | 
			
		||||
@ -176,6 +178,15 @@ export function PublicRunOutputs() {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="border border-gray-200 w-full square h-[400px] rounded-lg relative">
 | 
			
		||||
      {!loading && !image && props.preview && props.preview.length > 0 && (
 | 
			
		||||
        <>
 | 
			
		||||
          <img
 | 
			
		||||
            className="w-full h-full object-contain"
 | 
			
		||||
            src={props.preview[0]?.url}
 | 
			
		||||
            alt="Generated image"
 | 
			
		||||
          />
 | 
			
		||||
        </>
 | 
			
		||||
      )}
 | 
			
		||||
      {!loading && image && (
 | 
			
		||||
        <img
 | 
			
		||||
          className="w-full h-full object-contain"
 | 
			
		||||
 | 
			
		||||
@ -10,12 +10,11 @@ export default function ErrorPage({
 | 
			
		||||
  error,
 | 
			
		||||
  reset,
 | 
			
		||||
}: {
 | 
			
		||||
  error?: Error & { digest?: string };
 | 
			
		||||
  reset?: () => void;
 | 
			
		||||
  error: Error & { digest?: string };
 | 
			
		||||
  reset: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    // Log the error to an error reporting service
 | 
			
		||||
    console.log(error?.message);
 | 
			
		||||
    console.log(error.message);
 | 
			
		||||
  }, [error]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@ -26,9 +25,14 @@ export default function ErrorPage({
 | 
			
		||||
            <div className="text-xl">Unexpected error.</div>
 | 
			
		||||
          </CardTitle>
 | 
			
		||||
          <CardDescription className="flex flex-col gap-4">
 | 
			
		||||
            <div className="text-sm">Error: {error?.message}</div>
 | 
			
		||||
            <div className="text-sm">Error: {error.message}</div>
 | 
			
		||||
            <div className="flex w-full justify-end">
 | 
			
		||||
              <Button className="w-fit" onClick={() => reset?.()}>
 | 
			
		||||
              <Button
 | 
			
		||||
                className="w-fit"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                  window.location.reload();
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                Refresh Page
 | 
			
		||||
              </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -39,14 +43,20 @@ export default function ErrorPage({
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ErrorFullPage() {
 | 
			
		||||
export function ErrorFullPage({
 | 
			
		||||
  error,
 | 
			
		||||
  reset,
 | 
			
		||||
}: {
 | 
			
		||||
  error: Error & { digest?: string };
 | 
			
		||||
  reset: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={cn(
 | 
			
		||||
        "w-full py-4 flex justify-center items-center gap-2 text-sm h-full"
 | 
			
		||||
      )}
 | 
			
		||||
    >
 | 
			
		||||
      <ErrorPage />
 | 
			
		||||
      <ErrorPage error={error} reset={reset} />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { DefaultValues } from "react-hook-form";
 | 
			
		||||
import { z } from "zod";
 | 
			
		||||
import type { DefaultValues } from "react-hook-form";
 | 
			
		||||
import type { z } from "zod";
 | 
			
		||||
 | 
			
		||||
// TODO: This should support recursive ZodEffects but TypeScript doesn't allow circular type definitions.
 | 
			
		||||
export type ZodObjectOrWrapped =
 | 
			
		||||
@ -21,7 +21,7 @@ export function beautifyObjectName(string: string) {
 | 
			
		||||
 * This will unpack optionals, refinements, etc.
 | 
			
		||||
 */
 | 
			
		||||
export function getBaseSchema<
 | 
			
		||||
  ChildType extends z.ZodAny | z.AnyZodObject = z.ZodAny,
 | 
			
		||||
  ChildType extends z.ZodAny | z.AnyZodObject = z.ZodAny
 | 
			
		||||
>(schema: ChildType | z.ZodEffects<ChildType>): ChildType {
 | 
			
		||||
  if ("innerType" in schema._def) {
 | 
			
		||||
    return getBaseSchema(schema._def.innerType as ChildType);
 | 
			
		||||
@ -54,12 +54,12 @@ export function getDefaultValueInZodStack(schema: z.ZodAny): any {
 | 
			
		||||
 | 
			
		||||
  if ("innerType" in typedSchema._def) {
 | 
			
		||||
    return getDefaultValueInZodStack(
 | 
			
		||||
      typedSchema._def.innerType as unknown as z.ZodAny,
 | 
			
		||||
      typedSchema._def.innerType as unknown as z.ZodAny
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  if ("schema" in typedSchema._def) {
 | 
			
		||||
    return getDefaultValueInZodStack(
 | 
			
		||||
      (typedSchema._def as any).schema as z.ZodAny,
 | 
			
		||||
      (typedSchema._def as any).schema as z.ZodAny
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  return undefined;
 | 
			
		||||
@ -69,7 +69,7 @@ export function getDefaultValueInZodStack(schema: z.ZodAny): any {
 | 
			
		||||
 * Get all default values from a Zod schema.
 | 
			
		||||
 */
 | 
			
		||||
export function getDefaultValues<Schema extends z.ZodObject<any, any>>(
 | 
			
		||||
  schema: Schema,
 | 
			
		||||
  schema: Schema
 | 
			
		||||
) {
 | 
			
		||||
  const { shape } = schema;
 | 
			
		||||
  type DefaultValuesType = DefaultValues<Partial<z.infer<Schema>>>;
 | 
			
		||||
@ -80,7 +80,7 @@ export function getDefaultValues<Schema extends z.ZodObject<any, any>>(
 | 
			
		||||
 | 
			
		||||
    if (getBaseType(item) === "ZodObject") {
 | 
			
		||||
      const defaultItems = getDefaultValues(
 | 
			
		||||
        getBaseSchema(item) as unknown as z.ZodObject<any, any>,
 | 
			
		||||
        getBaseSchema(item) as unknown as z.ZodObject<any, any>
 | 
			
		||||
      );
 | 
			
		||||
      for (const defaultItemKey of Object.keys(defaultItems)) {
 | 
			
		||||
        const pathKey = `${key}.${defaultItemKey}` as keyof DefaultValuesType;
 | 
			
		||||
@ -98,7 +98,7 @@ export function getDefaultValues<Schema extends z.ZodObject<any, any>>(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getObjectFormSchema(
 | 
			
		||||
  schema: ZodObjectOrWrapped,
 | 
			
		||||
  schema: ZodObjectOrWrapped
 | 
			
		||||
): z.ZodObject<any, any> {
 | 
			
		||||
  if (schema._def.typeName === "ZodEffects") {
 | 
			
		||||
    const typedSchema = schema as z.ZodEffects<z.ZodObject<any, any>>;
 | 
			
		||||
@ -116,7 +116,7 @@ export function zodToHtmlInputProps(
 | 
			
		||||
    | z.ZodNumber
 | 
			
		||||
    | z.ZodString
 | 
			
		||||
    | z.ZodOptional<z.ZodNumber | z.ZodString>
 | 
			
		||||
    | any,
 | 
			
		||||
    | any
 | 
			
		||||
): React.InputHTMLAttributes<HTMLInputElement> {
 | 
			
		||||
  if (["ZodOptional", "ZodNullable"].includes(schema._def.typeName)) {
 | 
			
		||||
    const typedSchema = schema as z.ZodOptional<z.ZodNumber | z.ZodString>;
 | 
			
		||||
@ -128,8 +128,9 @@ export function zodToHtmlInputProps(
 | 
			
		||||
 | 
			
		||||
  const typedSchema = schema as z.ZodNumber | z.ZodString;
 | 
			
		||||
 | 
			
		||||
  if (!("checks" in typedSchema._def)) return {
 | 
			
		||||
    required: true
 | 
			
		||||
  if (!("checks" in typedSchema._def))
 | 
			
		||||
    return {
 | 
			
		||||
      required: true,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  const { checks } = typedSchema._def;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										262
									
								
								web/src/components/ui/carousel.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								web/src/components/ui/carousel.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,262 @@
 | 
			
		||||
"use client"
 | 
			
		||||
 | 
			
		||||
import * as React from "react"
 | 
			
		||||
import useEmblaCarousel, {
 | 
			
		||||
  type UseEmblaCarouselType,
 | 
			
		||||
} from "embla-carousel-react"
 | 
			
		||||
import { ArrowLeft, ArrowRight } from "lucide-react"
 | 
			
		||||
 | 
			
		||||
import { cn } from "@/lib/utils"
 | 
			
		||||
import { Button } from "@/components/ui/button"
 | 
			
		||||
 | 
			
		||||
type CarouselApi = UseEmblaCarouselType[1]
 | 
			
		||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
 | 
			
		||||
type CarouselOptions = UseCarouselParameters[0]
 | 
			
		||||
type CarouselPlugin = UseCarouselParameters[1]
 | 
			
		||||
 | 
			
		||||
type CarouselProps = {
 | 
			
		||||
  opts?: CarouselOptions
 | 
			
		||||
  plugins?: CarouselPlugin
 | 
			
		||||
  orientation?: "horizontal" | "vertical"
 | 
			
		||||
  setApi?: (api: CarouselApi) => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CarouselContextProps = {
 | 
			
		||||
  carouselRef: ReturnType<typeof useEmblaCarousel>[0]
 | 
			
		||||
  api: ReturnType<typeof useEmblaCarousel>[1]
 | 
			
		||||
  scrollPrev: () => void
 | 
			
		||||
  scrollNext: () => void
 | 
			
		||||
  canScrollPrev: boolean
 | 
			
		||||
  canScrollNext: boolean
 | 
			
		||||
} & CarouselProps
 | 
			
		||||
 | 
			
		||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
 | 
			
		||||
 | 
			
		||||
function useCarousel() {
 | 
			
		||||
  const context = React.useContext(CarouselContext)
 | 
			
		||||
 | 
			
		||||
  if (!context) {
 | 
			
		||||
    throw new Error("useCarousel must be used within a <Carousel />")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Carousel = React.forwardRef<
 | 
			
		||||
  HTMLDivElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLDivElement> & CarouselProps
 | 
			
		||||
>(
 | 
			
		||||
  (
 | 
			
		||||
    {
 | 
			
		||||
      orientation = "horizontal",
 | 
			
		||||
      opts,
 | 
			
		||||
      setApi,
 | 
			
		||||
      plugins,
 | 
			
		||||
      className,
 | 
			
		||||
      children,
 | 
			
		||||
      ...props
 | 
			
		||||
    },
 | 
			
		||||
    ref
 | 
			
		||||
  ) => {
 | 
			
		||||
    const [carouselRef, api] = useEmblaCarousel(
 | 
			
		||||
      {
 | 
			
		||||
        ...opts,
 | 
			
		||||
        axis: orientation === "horizontal" ? "x" : "y",
 | 
			
		||||
      },
 | 
			
		||||
      plugins
 | 
			
		||||
    )
 | 
			
		||||
    const [canScrollPrev, setCanScrollPrev] = React.useState(false)
 | 
			
		||||
    const [canScrollNext, setCanScrollNext] = React.useState(false)
 | 
			
		||||
 | 
			
		||||
    const onSelect = React.useCallback((api: CarouselApi) => {
 | 
			
		||||
      if (!api) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      setCanScrollPrev(api.canScrollPrev())
 | 
			
		||||
      setCanScrollNext(api.canScrollNext())
 | 
			
		||||
    }, [])
 | 
			
		||||
 | 
			
		||||
    const scrollPrev = React.useCallback(() => {
 | 
			
		||||
      api?.scrollPrev()
 | 
			
		||||
    }, [api])
 | 
			
		||||
 | 
			
		||||
    const scrollNext = React.useCallback(() => {
 | 
			
		||||
      api?.scrollNext()
 | 
			
		||||
    }, [api])
 | 
			
		||||
 | 
			
		||||
    const handleKeyDown = React.useCallback(
 | 
			
		||||
      (event: React.KeyboardEvent<HTMLDivElement>) => {
 | 
			
		||||
        if (event.key === "ArrowLeft") {
 | 
			
		||||
          event.preventDefault()
 | 
			
		||||
          scrollPrev()
 | 
			
		||||
        } else if (event.key === "ArrowRight") {
 | 
			
		||||
          event.preventDefault()
 | 
			
		||||
          scrollNext()
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      [scrollPrev, scrollNext]
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    React.useEffect(() => {
 | 
			
		||||
      if (!api || !setApi) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      setApi(api)
 | 
			
		||||
    }, [api, setApi])
 | 
			
		||||
 | 
			
		||||
    React.useEffect(() => {
 | 
			
		||||
      if (!api) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      onSelect(api)
 | 
			
		||||
      api.on("reInit", onSelect)
 | 
			
		||||
      api.on("select", onSelect)
 | 
			
		||||
 | 
			
		||||
      return () => {
 | 
			
		||||
        api?.off("select", onSelect)
 | 
			
		||||
      }
 | 
			
		||||
    }, [api, onSelect])
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <CarouselContext.Provider
 | 
			
		||||
        value={{
 | 
			
		||||
          carouselRef,
 | 
			
		||||
          api: api,
 | 
			
		||||
          opts,
 | 
			
		||||
          orientation:
 | 
			
		||||
            orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
 | 
			
		||||
          scrollPrev,
 | 
			
		||||
          scrollNext,
 | 
			
		||||
          canScrollPrev,
 | 
			
		||||
          canScrollNext,
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          ref={ref}
 | 
			
		||||
          onKeyDownCapture={handleKeyDown}
 | 
			
		||||
          className={cn("relative", className)}
 | 
			
		||||
          role="region"
 | 
			
		||||
          aria-roledescription="carousel"
 | 
			
		||||
          {...props}
 | 
			
		||||
        >
 | 
			
		||||
          {children}
 | 
			
		||||
        </div>
 | 
			
		||||
      </CarouselContext.Provider>
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
Carousel.displayName = "Carousel"
 | 
			
		||||
 | 
			
		||||
const CarouselContent = React.forwardRef<
 | 
			
		||||
  HTMLDivElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLDivElement>
 | 
			
		||||
>(({ className, ...props }, ref) => {
 | 
			
		||||
  const { carouselRef, orientation } = useCarousel()
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div ref={carouselRef} className="overflow-hidden">
 | 
			
		||||
      <div
 | 
			
		||||
        ref={ref}
 | 
			
		||||
        className={cn(
 | 
			
		||||
          "flex",
 | 
			
		||||
          orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
 | 
			
		||||
          className
 | 
			
		||||
        )}
 | 
			
		||||
        {...props}
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
CarouselContent.displayName = "CarouselContent"
 | 
			
		||||
 | 
			
		||||
const CarouselItem = React.forwardRef<
 | 
			
		||||
  HTMLDivElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLDivElement>
 | 
			
		||||
>(({ className, ...props }, ref) => {
 | 
			
		||||
  const { orientation } = useCarousel()
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      ref={ref}
 | 
			
		||||
      role="group"
 | 
			
		||||
      aria-roledescription="slide"
 | 
			
		||||
      className={cn(
 | 
			
		||||
        "min-w-0 shrink-0 grow-0 basis-full",
 | 
			
		||||
        orientation === "horizontal" ? "pl-4" : "pt-4",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      {...props}
 | 
			
		||||
    />
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
CarouselItem.displayName = "CarouselItem"
 | 
			
		||||
 | 
			
		||||
const CarouselPrevious = React.forwardRef<
 | 
			
		||||
  HTMLButtonElement,
 | 
			
		||||
  React.ComponentProps<typeof Button>
 | 
			
		||||
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
 | 
			
		||||
  const { orientation, scrollPrev, canScrollPrev } = useCarousel()
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Button
 | 
			
		||||
      ref={ref}
 | 
			
		||||
      variant={variant}
 | 
			
		||||
      size={size}
 | 
			
		||||
      className={cn(
 | 
			
		||||
        "absolute  h-8 w-8 rounded-full",
 | 
			
		||||
        orientation === "horizontal"
 | 
			
		||||
          ? "-left-12 top-1/2 -translate-y-1/2"
 | 
			
		||||
          : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      disabled={!canScrollPrev}
 | 
			
		||||
      onClick={scrollPrev}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
      <ArrowLeft className="h-4 w-4" />
 | 
			
		||||
      <span className="sr-only">Previous slide</span>
 | 
			
		||||
    </Button>
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
CarouselPrevious.displayName = "CarouselPrevious"
 | 
			
		||||
 | 
			
		||||
const CarouselNext = React.forwardRef<
 | 
			
		||||
  HTMLButtonElement,
 | 
			
		||||
  React.ComponentProps<typeof Button>
 | 
			
		||||
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
 | 
			
		||||
  const { orientation, scrollNext, canScrollNext } = useCarousel()
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Button
 | 
			
		||||
      ref={ref}
 | 
			
		||||
      variant={variant}
 | 
			
		||||
      size={size}
 | 
			
		||||
      className={cn(
 | 
			
		||||
        "absolute h-8 w-8 rounded-full",
 | 
			
		||||
        orientation === "horizontal"
 | 
			
		||||
          ? "-right-12 top-1/2 -translate-y-1/2"
 | 
			
		||||
          : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
 | 
			
		||||
        className
 | 
			
		||||
      )}
 | 
			
		||||
      disabled={!canScrollNext}
 | 
			
		||||
      onClick={scrollNext}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
      <ArrowRight className="h-4 w-4" />
 | 
			
		||||
      <span className="sr-only">Next slide</span>
 | 
			
		||||
    </Button>
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
CarouselNext.displayName = "CarouselNext"
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  type CarouselApi,
 | 
			
		||||
  Carousel,
 | 
			
		||||
  CarouselContent,
 | 
			
		||||
  CarouselItem,
 | 
			
		||||
  CarouselPrevious,
 | 
			
		||||
  CarouselNext,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								web/src/components/useServerActionData.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								web/src/components/useServerActionData.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { callServerPromise } from "@/components/callServerPromise";
 | 
			
		||||
import { useEffect, useState, useTransition } from "react";
 | 
			
		||||
 | 
			
		||||
export function useServerActionData<I, O>(
 | 
			
		||||
  action: (data: I) => Promise<O>,
 | 
			
		||||
  input: I
 | 
			
		||||
) {
 | 
			
		||||
  const [data, setData] = useState<O | null>(null);
 | 
			
		||||
  const [pending, startTransition] = useTransition();
 | 
			
		||||
  const [started, setStarted] = useState(false);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    startTransition(() => {
 | 
			
		||||
      setStarted(true);
 | 
			
		||||
      callServerPromise(action(input)).then(setData);
 | 
			
		||||
    });
 | 
			
		||||
  }, [action, input]);
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    started,
 | 
			
		||||
    data,
 | 
			
		||||
    pending,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@ -239,6 +239,22 @@ export const insertMachineSchema = createInsertSchema(machinesTable, {
 | 
			
		||||
  type: (schema) => schema.type.default("classic"),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const showcaseMedia = z.array(
 | 
			
		||||
  z.object({
 | 
			
		||||
    url: z.string(),
 | 
			
		||||
    isCover: z.boolean().default(false),
 | 
			
		||||
  })
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const showcaseMediaNullable = z
 | 
			
		||||
  .array(
 | 
			
		||||
    z.object({
 | 
			
		||||
      url: z.string(),
 | 
			
		||||
      isCover: z.boolean().default(false),
 | 
			
		||||
    })
 | 
			
		||||
  )
 | 
			
		||||
  .nullable();
 | 
			
		||||
 | 
			
		||||
export const deploymentsTable = dbSchema.table("deployments", {
 | 
			
		||||
  id: uuid("id").primaryKey().defaultRandom().notNull(),
 | 
			
		||||
  user_id: text("user_id")
 | 
			
		||||
@ -246,6 +262,7 @@ export const deploymentsTable = dbSchema.table("deployments", {
 | 
			
		||||
      onDelete: "cascade",
 | 
			
		||||
    })
 | 
			
		||||
    .notNull(),
 | 
			
		||||
  org_id: text("org_id"),
 | 
			
		||||
  workflow_version_id: uuid("workflow_version_id")
 | 
			
		||||
    .notNull()
 | 
			
		||||
    .references(() => workflowVersionTable.id),
 | 
			
		||||
@ -257,11 +274,27 @@ export const deploymentsTable = dbSchema.table("deployments", {
 | 
			
		||||
  machine_id: uuid("machine_id")
 | 
			
		||||
    .notNull()
 | 
			
		||||
    .references(() => machinesTable.id),
 | 
			
		||||
  description: text("description"),
 | 
			
		||||
  showcase_media:
 | 
			
		||||
    jsonb("showcase_media").$type<z.infer<typeof showcaseMedia>>(),
 | 
			
		||||
  environment: deploymentEnvironment("environment").notNull(),
 | 
			
		||||
  created_at: timestamp("created_at").defaultNow().notNull(),
 | 
			
		||||
  updated_at: timestamp("updated_at").defaultNow().notNull(),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const publicShareDeployment = z.object({
 | 
			
		||||
  description: z.string().nullable(),
 | 
			
		||||
  showcase_media: showcaseMedia,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// createInsertSchema(deploymentsTable, {
 | 
			
		||||
//   description: (schema) => schema.description.default(""),
 | 
			
		||||
//   showcase_media: () => showcaseMedia.default([]),
 | 
			
		||||
// }).pick({
 | 
			
		||||
//   description: true,
 | 
			
		||||
//   showcase_media: true,
 | 
			
		||||
// });
 | 
			
		||||
 | 
			
		||||
export const deploymentsRelations = relations(deploymentsTable, ({ one }) => ({
 | 
			
		||||
  machine: one(machinesTable, {
 | 
			
		||||
    fields: [deploymentsTable.machine_id],
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
"use server";
 | 
			
		||||
 | 
			
		||||
import { db } from "@/db/db";
 | 
			
		||||
import type { DeploymentType } from "@/db/schema";
 | 
			
		||||
import type { DeploymentType, publicShareDeployment } from "@/db/schema";
 | 
			
		||||
import { deploymentsTable, workflowTable } from "@/db/schema";
 | 
			
		||||
import { createNewWorkflow } from "@/server/createNewWorkflow";
 | 
			
		||||
import { addCustomMachine } from "@/server/curdMachine";
 | 
			
		||||
@ -11,6 +11,7 @@ import { and, eq, isNull } from "drizzle-orm";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
import { redirect } from "next/navigation";
 | 
			
		||||
import "server-only";
 | 
			
		||||
import type { z } from "zod";
 | 
			
		||||
 | 
			
		||||
export async function createDeployments(
 | 
			
		||||
  workflow_id: string,
 | 
			
		||||
@ -18,7 +19,7 @@ export async function createDeployments(
 | 
			
		||||
  machine_id: string,
 | 
			
		||||
  environment: DeploymentType["environment"]
 | 
			
		||||
) {
 | 
			
		||||
  const { userId } = auth();
 | 
			
		||||
  const { userId, orgId } = auth();
 | 
			
		||||
  if (!userId) throw new Error("No user id");
 | 
			
		||||
 | 
			
		||||
  if (!machine_id) {
 | 
			
		||||
@ -40,6 +41,7 @@ export async function createDeployments(
 | 
			
		||||
        workflow_id,
 | 
			
		||||
        workflow_version_id: version_id,
 | 
			
		||||
        machine_id,
 | 
			
		||||
        org_id: orgId,
 | 
			
		||||
      })
 | 
			
		||||
      .where(eq(deploymentsTable.id, existingDeployment.id));
 | 
			
		||||
  } else {
 | 
			
		||||
@ -49,6 +51,7 @@ export async function createDeployments(
 | 
			
		||||
      workflow_version_id: version_id,
 | 
			
		||||
      machine_id,
 | 
			
		||||
      environment,
 | 
			
		||||
      org_id: orgId,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  revalidatePath(`/${workflow_id}`);
 | 
			
		||||
@ -195,3 +198,56 @@ export const cloneMachine = withServerPromise(async (deployment_id: string) => {
 | 
			
		||||
    message: "Successfully cloned workflow",
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export async function findUserShareDeployment(share_id: string) {
 | 
			
		||||
  const { userId, orgId } = auth();
 | 
			
		||||
 | 
			
		||||
  if (!userId) throw new Error("No user id");
 | 
			
		||||
 | 
			
		||||
  const [deployment] = await db
 | 
			
		||||
    .select()
 | 
			
		||||
    .from(deploymentsTable)
 | 
			
		||||
    .where(
 | 
			
		||||
      and(
 | 
			
		||||
        eq(deploymentsTable.id, share_id),
 | 
			
		||||
        eq(deploymentsTable.environment, "public-share"),
 | 
			
		||||
        orgId
 | 
			
		||||
          ? eq(deploymentsTable.org_id, orgId)
 | 
			
		||||
          : and(
 | 
			
		||||
              eq(deploymentsTable.user_id, userId),
 | 
			
		||||
              isNull(deploymentsTable.org_id)
 | 
			
		||||
            )
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  if (!deployment) throw new Error("No deployment found");
 | 
			
		||||
 | 
			
		||||
  return deployment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const updateSharePageInfo = withServerPromise(
 | 
			
		||||
  async ({
 | 
			
		||||
    id,
 | 
			
		||||
    ...data
 | 
			
		||||
  }: z.infer<typeof publicShareDeployment> & {
 | 
			
		||||
    id: string;
 | 
			
		||||
  }) => {
 | 
			
		||||
    const { userId } = auth();
 | 
			
		||||
    if (!userId) return { error: "No user id" };
 | 
			
		||||
 | 
			
		||||
    console.log(data);
 | 
			
		||||
 | 
			
		||||
    const [deployment] = await db
 | 
			
		||||
      .update(deploymentsTable)
 | 
			
		||||
      .set(data)
 | 
			
		||||
      .where(
 | 
			
		||||
        and(
 | 
			
		||||
          eq(deploymentsTable.environment, "public-share"),
 | 
			
		||||
          eq(deploymentsTable.id, id)
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
      .returning();
 | 
			
		||||
 | 
			
		||||
    return { message: "Info Updated" };
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user