diff --git a/api/controllers/console/app/app.py b/api/controllers/console/app/app.py index 898fd4f7c4..98636fa95f 100644 --- a/api/controllers/console/app/app.py +++ b/api/controllers/console/app/app.py @@ -1,5 +1,5 @@ from flask_login import current_user -from flask_restful import Resource, abort, inputs, marshal_with, reqparse +from flask_restful import Resource, inputs, marshal_with, reqparse from werkzeug.exceptions import Forbidden, BadRequest from controllers.console import api @@ -53,6 +53,7 @@ class AppListApi(Resource): """Create app""" parser = reqparse.RequestParser() parser.add_argument('name', type=str, required=True, location='json') + parser.add_argument('description', type=str, location='json') parser.add_argument('mode', type=str, choices=ALLOW_CREATE_APP_MODES, location='json') parser.add_argument('icon', type=str, location='json') parser.add_argument('icon_background', type=str, location='json') @@ -86,6 +87,7 @@ class AppImportApi(Resource): parser = reqparse.RequestParser() parser.add_argument('data', type=str, required=True, nullable=False, location='json') parser.add_argument('name', type=str, location='json') + parser.add_argument('description', type=str, location='json') parser.add_argument('icon', type=str, location='json') parser.add_argument('icon_background', type=str, location='json') args = parser.parse_args() @@ -144,6 +146,25 @@ class AppApi(Resource): return app_model + @setup_required + @login_required + @account_initialization_required + @get_app_model + @marshal_with(app_detail_fields_with_site) + def put(self, app_model): + """Update app""" + parser = reqparse.RequestParser() + parser.add_argument('name', type=str, required=True, nullable=False, location='json') + parser.add_argument('description', type=str, location='json') + parser.add_argument('icon', type=str, location='json') + parser.add_argument('icon_background', type=str, location='json') + args = parser.parse_args() + + app_service = AppService() + app_model = app_service.update_app(app_model, args) + + return app_model + @setup_required @login_required @account_initialization_required diff --git a/api/fields/app_fields.py b/api/fields/app_fields.py index 75b68d24fc..69ab1d3e3e 100644 --- a/api/fields/app_fields.py +++ b/api/fields/app_fields.py @@ -5,6 +5,7 @@ from libs.helper import TimestampField app_detail_kernel_fields = { 'id': fields.String, 'name': fields.String, + 'description': fields.String, 'mode': fields.String, 'icon': fields.String, 'icon_background': fields.String, @@ -41,6 +42,7 @@ model_config_fields = { app_detail_fields = { 'id': fields.String, 'name': fields.String, + 'description': fields.String, 'mode': fields.String, 'icon': fields.String, 'icon_background': fields.String, @@ -62,6 +64,7 @@ model_config_partial_fields = { app_partial_fields = { 'id': fields.String, 'name': fields.String, + 'description': fields.String, 'mode': fields.String, 'icon': fields.String, 'icon_background': fields.String, @@ -109,6 +112,7 @@ site_fields = { app_detail_fields_with_site = { 'id': fields.String, 'name': fields.String, + 'description': fields.String, 'mode': fields.String, 'icon': fields.String, 'icon_background': fields.String, diff --git a/api/migrations/versions/f9107f83abab_add_desc_for_apps.py b/api/migrations/versions/f9107f83abab_add_desc_for_apps.py new file mode 100644 index 0000000000..88d77bb320 --- /dev/null +++ b/api/migrations/versions/f9107f83abab_add_desc_for_apps.py @@ -0,0 +1,32 @@ +"""add desc for apps + +Revision ID: f9107f83abab +Revises: cc04d0998d4d +Create Date: 2024-02-28 08:16:14.090481 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'f9107f83abab' +down_revision = 'cc04d0998d4d' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('apps', schema=None) as batch_op: + batch_op.add_column(sa.Column('description', sa.Text(), server_default=sa.text("''::character varying"), nullable=False)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('apps', schema=None) as batch_op: + batch_op.drop_column('description') + + # ### end Alembic commands ### diff --git a/api/models/model.py b/api/models/model.py index 713d8da577..8d286d3482 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -14,7 +14,6 @@ from extensions.ext_database import db from libs.helper import generate_string from .account import Account, Tenant -from .workflow import Workflow, WorkflowRun class DifySetup(db.Model): @@ -59,6 +58,7 @@ class App(db.Model): id = db.Column(UUID, server_default=db.text('uuid_generate_v4()')) tenant_id = db.Column(UUID, nullable=False) name = db.Column(db.String(255), nullable=False) + description = db.Column(db.Text, nullable=False, server_default=db.text("''::character varying")) mode = db.Column(db.String(255), nullable=False) icon = db.Column(db.String(255)) icon_background = db.Column(db.String(255)) @@ -279,6 +279,7 @@ class AppModelConfig(db.Model): @property def workflow(self): if self.workflow_id: + from api.models.workflow import Workflow return db.session.query(Workflow).filter(Workflow.id == self.workflow_id).first() return None @@ -692,6 +693,7 @@ class Message(db.Model): @property def workflow_run(self): if self.workflow_run_id: + from api.models.workflow import WorkflowRun return db.session.query(WorkflowRun).filter(WorkflowRun.id == self.workflow_run_id).first() return None diff --git a/api/models/workflow.py b/api/models/workflow.py index 7ea342cda7..316d3e623e 100644 --- a/api/models/workflow.py +++ b/api/models/workflow.py @@ -5,7 +5,6 @@ from sqlalchemy.dialects.postgresql import UUID from extensions.ext_database import db from models.account import Account -from models.model import EndUser class CreatedByRole(Enum): @@ -242,6 +241,7 @@ class WorkflowRun(db.Model): @property def created_by_end_user(self): + from models.model import EndUser created_by_role = CreatedByRole.value_of(self.created_by_role) return EndUser.query.get(self.created_by) \ if created_by_role == CreatedByRole.END_USER else None @@ -356,6 +356,7 @@ class WorkflowNodeExecution(db.Model): @property def created_by_end_user(self): + from models.model import EndUser created_by_role = CreatedByRole.value_of(self.created_by_role) return EndUser.query.get(self.created_by) \ if created_by_role == CreatedByRole.END_USER else None @@ -418,6 +419,7 @@ class WorkflowAppLog(db.Model): @property def created_by_end_user(self): + from models.model import EndUser created_by_role = CreatedByRole.value_of(self.created_by_role) return EndUser.query.get(self.created_by) \ if created_by_role == CreatedByRole.END_USER else None diff --git a/api/services/app_service.py b/api/services/app_service.py index 5de87dbad5..2e534eae15 100644 --- a/api/services/app_service.py +++ b/api/services/app_service.py @@ -97,10 +97,11 @@ class AppService: app = App(**app_template['app']) app.name = args['name'] + app.description = args.get('description', '') app.mode = args['mode'] app.icon = args['icon'] app.icon_background = args['icon_background'] - app.tenant_id = account.current_tenant_id + app.tenant_id = tenant_id db.session.add(app) db.session.flush() @@ -145,6 +146,7 @@ class AppService: tenant_id=tenant_id, mode=app_data.get('mode'), name=args.get("name") if args.get("name") else app_data.get('name'), + description=args.get("description") if args.get("description") else app_data.get('description', ''), icon=args.get("icon") if args.get("icon") else app_data.get('icon'), icon_background=args.get("icon_background") if args.get("icon_background") \ else app_data.get('icon_background'), @@ -205,6 +207,22 @@ class AppService: return yaml.dump(export_data) + def update_app(self, app: App, args: dict) -> App: + """ + Update app + :param app: App instance + :param args: request args + :return: App instance + """ + app.name = args.get('name') + app.description = args.get('description', '') + app.icon = args.get('icon') + app.icon_background = args.get('icon_background') + app.updated_at = datetime.utcnow() + db.session.commit() + + return app + def update_app_name(self, app: App, name: str) -> App: """ Update app name