Skip to content

Commit

Permalink
feat: allow users to use the app icon as the answer icon (langgenius#…
Browse files Browse the repository at this point in the history
…7888)

Co-authored-by: crazywoola <[email protected]>
  • Loading branch information
2 people authored and mehrajagdish committed Sep 6, 2024
1 parent 12623f4 commit d42bfae
Show file tree
Hide file tree
Showing 24 changed files with 208 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/controllers/console/app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def put(self, app_model):
parser.add_argument("icon", type=str, location="json")
parser.add_argument("icon_background", type=str, location="json")
parser.add_argument("max_active_requests", type=int, location="json")
parser.add_argument("use_icon_as_answer_icon", type=bool, location="json")
args = parser.parse_args()

app_service = AppService()
Expand Down
2 changes: 2 additions & 0 deletions api/controllers/console/app/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def parse_app_site_args():
)
parser.add_argument("prompt_public", type=bool, required=False, location="json")
parser.add_argument("show_workflow_steps", type=bool, required=False, location="json")
parser.add_argument("use_icon_as_answer_icon", type=bool, required=False, location="json")
return parser.parse_args()


Expand Down Expand Up @@ -68,6 +69,7 @@ def post(self, app_model):
"customize_token_strategy",
"prompt_public",
"show_workflow_steps",
"use_icon_as_answer_icon",
]:
value = args.get(attr_name)
if value is not None:
Expand Down
1 change: 1 addition & 0 deletions api/controllers/web/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AppSiteApi(WebApiResource):
"default_language": fields.String,
"prompt_public": fields.Boolean,
"show_workflow_steps": fields.Boolean,
"use_icon_as_answer_icon": fields.Boolean,
}

app_fields = {
Expand Down
5 changes: 5 additions & 0 deletions api/fields/app_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"tracing": fields.Raw,
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
Expand Down Expand Up @@ -91,6 +92,7 @@
"icon_url": AppIconUrlField,
"model_config": fields.Nested(model_config_partial_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
Expand Down Expand Up @@ -140,6 +142,7 @@
"prompt_public": fields.Boolean,
"app_base_url": fields.String,
"show_workflow_steps": fields.Boolean,
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
Expand All @@ -161,6 +164,7 @@
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"site": fields.Nested(site_fields),
"api_base_url": fields.String,
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
Expand All @@ -184,4 +188,5 @@
"customize_token_strategy": fields.String,
"prompt_public": fields.Boolean,
"show_workflow_steps": fields.Boolean,
"use_icon_as_answer_icon": fields.Boolean,
}
1 change: 1 addition & 0 deletions api/fields/installed_app_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
"use_icon_as_answer_icon": fields.Boolean,
}

installed_app_fields = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""add use_icon_as_answer_icon fields for app and site
Revision ID: 030f4915f36a
Revises: d0187d6a88dd
Create Date: 2024-09-01 12:55:45.129687
"""

import sqlalchemy as sa
from alembic import op

import models as models

# revision identifiers, used by Alembic.
revision = "030f4915f36a"
down_revision = "d0187d6a88dd"
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("use_icon_as_answer_icon", sa.Boolean(), server_default=sa.text("false"), nullable=False)
)

with op.batch_alter_table("sites", schema=None) as batch_op:
batch_op.add_column(
sa.Column("use_icon_as_answer_icon", sa.Boolean(), server_default=sa.text("false"), nullable=False)
)

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###

with op.batch_alter_table("sites", schema=None) as batch_op:
batch_op.drop_column("use_icon_as_answer_icon")

with op.batch_alter_table("apps", schema=None) as batch_op:
batch_op.drop_column("use_icon_as_answer_icon")

# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions api/models/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class App(db.Model):
created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
updated_by = db.Column(StringUUID, nullable=True)
updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
use_icon_as_answer_icon = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))

@property
def desc_or_prompt(self):
Expand Down Expand Up @@ -1114,6 +1115,7 @@ class Site(db.Model):
copyright = db.Column(db.String(255))
privacy_policy = db.Column(db.String(255))
show_workflow_steps = db.Column(db.Boolean, nullable=False, server_default=db.text('true'))
use_icon_as_answer_icon = db.Column(db.Boolean, nullable=False, server_default=db.text("false"))
custom_disclaimer = db.Column(db.String(255), nullable=True)
customize_domain = db.Column(db.String(255))
customize_token_strategy = db.Column(db.String(255), nullable=False)
Expand Down
12 changes: 12 additions & 0 deletions api/services/app_dsl_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def import_and_create_new_app(cls, tenant_id: str, data: str, args: dict, accoun
icon_background = (
args.get("icon_background") if args.get("icon_background") else app_data.get("icon_background")
)
use_icon_as_answer_icon = app_data.get("use_icon_as_answer_icon", False)

# import dsl and create app
app_mode = AppMode.value_of(app_data.get("mode"))
Expand All @@ -101,6 +102,7 @@ def import_and_create_new_app(cls, tenant_id: str, data: str, args: dict, accoun
icon_type=icon_type,
icon=icon,
icon_background=icon_background,
use_icon_as_answer_icon=use_icon_as_answer_icon,
)
elif app_mode in [AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.COMPLETION]:
app = cls._import_and_create_new_model_config_based_app(
Expand All @@ -113,6 +115,7 @@ def import_and_create_new_app(cls, tenant_id: str, data: str, args: dict, accoun
icon_type=icon_type,
icon=icon,
icon_background=icon_background,
use_icon_as_answer_icon=use_icon_as_answer_icon,
)
else:
raise ValueError("Invalid app mode")
Expand Down Expand Up @@ -171,6 +174,7 @@ def export_dsl(cls, app_model: App, include_secret: bool = False) -> str:
"icon": "🤖" if app_model.icon_type == "image" else app_model.icon,
"icon_background": "#FFEAD5" if app_model.icon_type == "image" else app_model.icon_background,
"description": app_model.description,
"use_icon_as_answer_icon": app_model.use_icon_as_answer_icon,
},
}

Expand Down Expand Up @@ -218,6 +222,7 @@ def _import_and_create_new_workflow_based_app(
icon_type: str,
icon: str,
icon_background: str,
use_icon_as_answer_icon: bool,
) -> App:
"""
Import app dsl and create new workflow based app
Expand All @@ -231,6 +236,7 @@ def _import_and_create_new_workflow_based_app(
:param icon_type: app icon type, "emoji" or "image"
:param icon: app icon
:param icon_background: app icon background
:param use_icon_as_answer_icon: use app icon as answer icon
"""
if not workflow_data:
raise ValueError("Missing workflow in data argument " "when app mode is advanced-chat or workflow")
Expand All @@ -244,6 +250,7 @@ def _import_and_create_new_workflow_based_app(
icon_type=icon_type,
icon=icon,
icon_background=icon_background,
use_icon_as_answer_icon=use_icon_as_answer_icon,
)

# init draft workflow
Expand Down Expand Up @@ -316,6 +323,7 @@ def _import_and_create_new_model_config_based_app(
icon_type: str,
icon: str,
icon_background: str,
use_icon_as_answer_icon: bool,
) -> App:
"""
Import app dsl and create new model config based app
Expand All @@ -341,6 +349,7 @@ def _import_and_create_new_model_config_based_app(
icon_type=icon_type,
icon=icon,
icon_background=icon_background,
use_icon_as_answer_icon=use_icon_as_answer_icon,
)

app_model_config = AppModelConfig()
Expand Down Expand Up @@ -369,6 +378,7 @@ def _create_app(
icon_type: str,
icon: str,
icon_background: str,
use_icon_as_answer_icon: bool,
) -> App:
"""
Create new app
Expand All @@ -381,6 +391,7 @@ def _create_app(
:param icon_type: app icon type, "emoji" or "image"
:param icon: app icon
:param icon_background: app icon background
:param use_icon_as_answer_icon: use app icon as answer icon
"""
app = App(
tenant_id=tenant_id,
Expand All @@ -392,6 +403,7 @@ def _create_app(
icon_background=icon_background,
enable_site=True,
enable_api=True,
use_icon_as_answer_icon=use_icon_as_answer_icon,
created_by=account.id,
updated_by=account.id,
)
Expand Down
1 change: 1 addition & 0 deletions api/services/app_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ def update_app(self, app: App, args: dict) -> App:
app.icon_type = args.get("icon_type", "emoji")
app.icon = args.get("icon")
app.icon_background = args.get("icon_background")
app.use_icon_as_answer_icon = args.get("use_icon_as_answer_icon", False)
app.updated_by = current_user.id
app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
db.session.commit()
Expand Down
4 changes: 4 additions & 0 deletions web/app/(commonLayout)/apps/AppCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
icon,
icon_background,
description,
use_icon_as_answer_icon,
}) => {
try {
await updateAppInfo({
Expand All @@ -88,6 +89,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
icon,
icon_background,
description,
use_icon_as_answer_icon,
})
setShowEditModal(false)
notify({
Expand Down Expand Up @@ -370,6 +372,8 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
appIconBackground={app.icon_background}
appIconUrl={app.icon_url}
appDescription={app.description}
appMode={app.mode}
appUseIconAsAnswerIcon={app.use_icon_as_answer_icon}
show={showEditModal}
onConfirm={onEdit}
onHide={() => setShowEditModal(false)}
Expand Down
4 changes: 4 additions & 0 deletions web/app/components/app-sidebar/app-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
icon,
icon_background,
description,
use_icon_as_answer_icon,
}) => {
if (!appDetail)
return
Expand All @@ -74,6 +75,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
icon,
icon_background,
description,
use_icon_as_answer_icon,
})
setShowEditModal(false)
notify({
Expand Down Expand Up @@ -423,6 +425,8 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
appIconBackground={appDetail.icon_background}
appIconUrl={appDetail.icon_url}
appDescription={appDetail.description}
appMode={appDetail.mode}
appUseIconAsAnswerIcon={appDetail.use_icon_as_answer_icon}
show={showEditModal}
onConfirm={onEdit}
onHide={() => setShowEditModal(false)}
Expand Down
18 changes: 18 additions & 0 deletions web/app/components/app/overview/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export type ConfigParams = {
icon: string
icon_background?: string
show_workflow_steps: boolean
use_icon_as_answer_icon: boolean
enable_sso?: boolean
}

Expand Down Expand Up @@ -72,6 +73,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
custom_disclaimer,
default_language,
show_workflow_steps,
use_icon_as_answer_icon,
} = appInfo.site
const [inputInfo, setInputInfo] = useState({
title,
Expand All @@ -82,6 +84,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
privacyPolicy: privacy_policy,
customDisclaimer: custom_disclaimer,
show_workflow_steps,
use_icon_as_answer_icon,
enable_sso: appInfo.enable_sso,
})
const [language, setLanguage] = useState(default_language)
Expand All @@ -94,6 +97,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
? { type: 'image', url: icon_url!, fileId: icon }
: { type: 'emoji', icon, background: icon_background! },
)
const isChatBot = appInfo.mode === 'chat' || appInfo.mode === 'advanced-chat' || appInfo.mode === 'agent-chat'

useEffect(() => {
setInputInfo({
Expand All @@ -105,6 +109,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
privacyPolicy: privacy_policy,
customDisclaimer: custom_disclaimer,
show_workflow_steps,
use_icon_as_answer_icon,
enable_sso: appInfo.enable_sso,
})
setLanguage(default_language)
Expand Down Expand Up @@ -157,6 +162,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
icon: appIcon.type === 'emoji' ? appIcon.icon : appIcon.fileId,
icon_background: appIcon.type === 'emoji' ? appIcon.background : undefined,
show_workflow_steps: inputInfo.show_workflow_steps,
use_icon_as_answer_icon: inputInfo.use_icon_as_answer_icon,
enable_sso: inputInfo.enable_sso,
}
await onSave?.(params)
Expand Down Expand Up @@ -209,6 +215,18 @@ const SettingsModal: FC<ISettingsModalProps> = ({
onChange={onChange('desc')}
placeholder={t(`${prefixSettings}.webDescPlaceholder`) as string}
/>
{isChatBot && (
<div className='w-full mt-4'>
<div className='flex justify-between items-center'>
<div className={`font-medium ${s.settingTitle} text-gray-900 `}>{t('app.answerIcon.title')}</div>
<Switch
defaultValue={inputInfo.use_icon_as_answer_icon}
onChange={v => setInputInfo({ ...inputInfo, use_icon_as_answer_icon: v })}
/>
</div>
<p className='body-xs-regular text-gray-500'>{t('app.answerIcon.description')}</p>
</div>
)}
<div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.language`)}</div>
<SimpleSelect
items={languages.filter(item => item.supported)}
Expand Down
Loading

0 comments on commit d42bfae

Please sign in to comment.