mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-07-31 00:12:03 +08:00
Feat: time period filter for workflow logs (#14271)
Signed-off-by: -LAN- <laipz8200@outlook.com> Co-authored-by: -LAN- <laipz8200@outlook.com>
This commit is contained in:
parent
3254018ddb
commit
78d460a6d1
@ -1,13 +1,18 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask_restful import Resource, marshal_with, reqparse # type: ignore
|
from flask_restful import Resource, marshal_with, reqparse # type: ignore
|
||||||
from flask_restful.inputs import int_range # type: ignore
|
from flask_restful.inputs import int_range # type: ignore
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from controllers.console import api
|
from controllers.console import api
|
||||||
from controllers.console.app.wraps import get_app_model
|
from controllers.console.app.wraps import get_app_model
|
||||||
from controllers.console.wraps import account_initialization_required, setup_required
|
from controllers.console.wraps import account_initialization_required, setup_required
|
||||||
|
from extensions.ext_database import db
|
||||||
from fields.workflow_app_log_fields import workflow_app_log_pagination_fields
|
from fields.workflow_app_log_fields import workflow_app_log_pagination_fields
|
||||||
from libs.login import login_required
|
from libs.login import login_required
|
||||||
from models import App
|
from models import App
|
||||||
from models.model import AppMode
|
from models.model import AppMode
|
||||||
|
from models.workflow import WorkflowRunStatus
|
||||||
from services.workflow_app_service import WorkflowAppService
|
from services.workflow_app_service import WorkflowAppService
|
||||||
|
|
||||||
|
|
||||||
@ -24,17 +29,38 @@ class WorkflowAppLogApi(Resource):
|
|||||||
parser = reqparse.RequestParser()
|
parser = reqparse.RequestParser()
|
||||||
parser.add_argument("keyword", type=str, location="args")
|
parser.add_argument("keyword", type=str, location="args")
|
||||||
parser.add_argument("status", type=str, choices=["succeeded", "failed", "stopped"], location="args")
|
parser.add_argument("status", type=str, choices=["succeeded", "failed", "stopped"], location="args")
|
||||||
|
parser.add_argument(
|
||||||
|
"created_at__before", type=str, location="args", help="Filter logs created before this timestamp"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"created_at__after", type=str, location="args", help="Filter logs created after this timestamp"
|
||||||
|
)
|
||||||
parser.add_argument("page", type=int_range(1, 99999), default=1, location="args")
|
parser.add_argument("page", type=int_range(1, 99999), default=1, location="args")
|
||||||
parser.add_argument("limit", type=int_range(1, 100), default=20, location="args")
|
parser.add_argument("limit", type=int_range(1, 100), default=20, location="args")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
args.status = WorkflowRunStatus(args.status) if args.status else None
|
||||||
|
if args.created_at__before:
|
||||||
|
args.created_at__before = datetime.fromisoformat(args.created_at__before.replace("Z", "+00:00"))
|
||||||
|
|
||||||
|
if args.created_at__after:
|
||||||
|
args.created_at__after = datetime.fromisoformat(args.created_at__after.replace("Z", "+00:00"))
|
||||||
|
|
||||||
# get paginate workflow app logs
|
# get paginate workflow app logs
|
||||||
workflow_app_service = WorkflowAppService()
|
workflow_app_service = WorkflowAppService()
|
||||||
workflow_app_log_pagination = workflow_app_service.get_paginate_workflow_app_logs(
|
with Session(db.engine) as session:
|
||||||
app_model=app_model, args=args
|
workflow_app_log_pagination = workflow_app_service.get_paginate_workflow_app_logs(
|
||||||
)
|
session=session,
|
||||||
|
app_model=app_model,
|
||||||
|
keyword=args.keyword,
|
||||||
|
status=args.status,
|
||||||
|
created_at_before=args.created_at__before,
|
||||||
|
created_at_after=args.created_at__after,
|
||||||
|
page=args.page,
|
||||||
|
limit=args.limit,
|
||||||
|
)
|
||||||
|
|
||||||
return workflow_app_log_pagination
|
return workflow_app_log_pagination
|
||||||
|
|
||||||
|
|
||||||
api.add_resource(WorkflowAppLogApi, "/apps/<uuid:app_id>/workflow-app-logs")
|
api.add_resource(WorkflowAppLogApi, "/apps/<uuid:app_id>/workflow-app-logs")
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask_restful import Resource, fields, marshal_with, reqparse # type: ignore
|
from flask_restful import Resource, fields, marshal_with, reqparse # type: ignore
|
||||||
from flask_restful.inputs import int_range # type: ignore
|
from flask_restful.inputs import int_range # type: ignore
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
from werkzeug.exceptions import InternalServerError
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
from controllers.service_api import api
|
from controllers.service_api import api
|
||||||
@ -25,7 +27,7 @@ from extensions.ext_database import db
|
|||||||
from fields.workflow_app_log_fields import workflow_app_log_pagination_fields
|
from fields.workflow_app_log_fields import workflow_app_log_pagination_fields
|
||||||
from libs import helper
|
from libs import helper
|
||||||
from models.model import App, AppMode, EndUser
|
from models.model import App, AppMode, EndUser
|
||||||
from models.workflow import WorkflowRun
|
from models.workflow import WorkflowRun, WorkflowRunStatus
|
||||||
from services.app_generate_service import AppGenerateService
|
from services.app_generate_service import AppGenerateService
|
||||||
from services.workflow_app_service import WorkflowAppService
|
from services.workflow_app_service import WorkflowAppService
|
||||||
|
|
||||||
@ -125,17 +127,34 @@ class WorkflowAppLogApi(Resource):
|
|||||||
parser = reqparse.RequestParser()
|
parser = reqparse.RequestParser()
|
||||||
parser.add_argument("keyword", type=str, location="args")
|
parser.add_argument("keyword", type=str, location="args")
|
||||||
parser.add_argument("status", type=str, choices=["succeeded", "failed", "stopped"], location="args")
|
parser.add_argument("status", type=str, choices=["succeeded", "failed", "stopped"], location="args")
|
||||||
|
parser.add_argument("created_at__before", type=str, location="args")
|
||||||
|
parser.add_argument("created_at__after", type=str, location="args")
|
||||||
parser.add_argument("page", type=int_range(1, 99999), default=1, location="args")
|
parser.add_argument("page", type=int_range(1, 99999), default=1, location="args")
|
||||||
parser.add_argument("limit", type=int_range(1, 100), default=20, location="args")
|
parser.add_argument("limit", type=int_range(1, 100), default=20, location="args")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
args.status = WorkflowRunStatus(args.status) if args.status else None
|
||||||
|
if args.created_at__before:
|
||||||
|
args.created_at__before = datetime.fromisoformat(args.created_at__before.replace("Z", "+00:00"))
|
||||||
|
|
||||||
|
if args.created_at__after:
|
||||||
|
args.created_at__after = datetime.fromisoformat(args.created_at__after.replace("Z", "+00:00"))
|
||||||
|
|
||||||
# get paginate workflow app logs
|
# get paginate workflow app logs
|
||||||
workflow_app_service = WorkflowAppService()
|
workflow_app_service = WorkflowAppService()
|
||||||
workflow_app_log_pagination = workflow_app_service.get_paginate_workflow_app_logs(
|
with Session(db.engine) as session:
|
||||||
app_model=app_model, args=args
|
workflow_app_log_pagination = workflow_app_service.get_paginate_workflow_app_logs(
|
||||||
)
|
session=session,
|
||||||
|
app_model=app_model,
|
||||||
|
keyword=args.keyword,
|
||||||
|
status=args.status,
|
||||||
|
created_at_before=args.created_at__before,
|
||||||
|
created_at_after=args.created_at__after,
|
||||||
|
page=args.page,
|
||||||
|
limit=args.limit,
|
||||||
|
)
|
||||||
|
|
||||||
return workflow_app_log_pagination
|
return workflow_app_log_pagination
|
||||||
|
|
||||||
|
|
||||||
api.add_resource(WorkflowRunApi, "/workflows/run")
|
api.add_resource(WorkflowRunApi, "/workflows/run")
|
||||||
|
@ -17,8 +17,8 @@ workflow_app_log_partial_fields = {
|
|||||||
|
|
||||||
workflow_app_log_pagination_fields = {
|
workflow_app_log_pagination_fields = {
|
||||||
"page": fields.Integer,
|
"page": fields.Integer,
|
||||||
"limit": fields.Integer(attribute="per_page"),
|
"limit": fields.Integer,
|
||||||
"total": fields.Integer,
|
"total": fields.Integer,
|
||||||
"has_more": fields.Boolean(attribute="has_next"),
|
"has_more": fields.Boolean,
|
||||||
"data": fields.List(fields.Nested(workflow_app_log_partial_fields), attribute="items"),
|
"data": fields.List(fields.Nested(workflow_app_log_partial_fields)),
|
||||||
}
|
}
|
||||||
|
@ -354,19 +354,6 @@ class WorkflowRunStatus(StrEnum):
|
|||||||
STOPPED = "stopped"
|
STOPPED = "stopped"
|
||||||
PARTIAL_SUCCESSED = "partial-succeeded"
|
PARTIAL_SUCCESSED = "partial-succeeded"
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def value_of(cls, value: str) -> "WorkflowRunStatus":
|
|
||||||
"""
|
|
||||||
Get value of given mode.
|
|
||||||
|
|
||||||
:param value: mode value
|
|
||||||
:return: mode
|
|
||||||
"""
|
|
||||||
for mode in cls:
|
|
||||||
if mode.value == value:
|
|
||||||
return mode
|
|
||||||
raise ValueError(f"invalid workflow run status value {value}")
|
|
||||||
|
|
||||||
|
|
||||||
class WorkflowRun(Base):
|
class WorkflowRun(Base):
|
||||||
"""
|
"""
|
||||||
|
@ -1,30 +1,46 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask_sqlalchemy.pagination import Pagination
|
from sqlalchemy import and_, func, or_, select
|
||||||
from sqlalchemy import and_, or_
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from extensions.ext_database import db
|
|
||||||
from models import App, EndUser, WorkflowAppLog, WorkflowRun
|
from models import App, EndUser, WorkflowAppLog, WorkflowRun
|
||||||
from models.enums import CreatedByRole
|
from models.enums import CreatedByRole
|
||||||
from models.workflow import WorkflowRunStatus
|
from models.workflow import WorkflowRunStatus
|
||||||
|
|
||||||
|
|
||||||
class WorkflowAppService:
|
class WorkflowAppService:
|
||||||
def get_paginate_workflow_app_logs(self, app_model: App, args: dict) -> Pagination:
|
def get_paginate_workflow_app_logs(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
session: Session,
|
||||||
|
app_model: App,
|
||||||
|
keyword: str | None = None,
|
||||||
|
status: WorkflowRunStatus | None = None,
|
||||||
|
created_at_before: datetime | None = None,
|
||||||
|
created_at_after: datetime | None = None,
|
||||||
|
page: int = 1,
|
||||||
|
limit: int = 20,
|
||||||
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Get paginate workflow app logs
|
Get paginate workflow app logs using SQLAlchemy 2.0 style
|
||||||
:param app: app model
|
:param session: SQLAlchemy session
|
||||||
:param args: request args
|
:param app_model: app model
|
||||||
:return:
|
:param keyword: search keyword
|
||||||
|
:param status: filter by status
|
||||||
|
:param created_at_before: filter logs created before this timestamp
|
||||||
|
:param created_at_after: filter logs created after this timestamp
|
||||||
|
:param page: page number
|
||||||
|
:param limit: items per page
|
||||||
|
:return: Pagination object
|
||||||
"""
|
"""
|
||||||
query = db.select(WorkflowAppLog).where(
|
# Build base statement using SQLAlchemy 2.0 style
|
||||||
|
stmt = select(WorkflowAppLog).where(
|
||||||
WorkflowAppLog.tenant_id == app_model.tenant_id, WorkflowAppLog.app_id == app_model.id
|
WorkflowAppLog.tenant_id == app_model.tenant_id, WorkflowAppLog.app_id == app_model.id
|
||||||
)
|
)
|
||||||
|
|
||||||
status = WorkflowRunStatus.value_of(args.get("status", "")) if args.get("status") else None
|
|
||||||
keyword = args["keyword"]
|
|
||||||
if keyword or status:
|
if keyword or status:
|
||||||
query = query.join(WorkflowRun, WorkflowRun.id == WorkflowAppLog.workflow_run_id)
|
stmt = stmt.join(WorkflowRun, WorkflowRun.id == WorkflowAppLog.workflow_run_id)
|
||||||
|
|
||||||
if keyword:
|
if keyword:
|
||||||
keyword_like_val = f"%{keyword[:30].encode('unicode_escape').decode('utf-8')}%".replace(r"\u", r"\\u")
|
keyword_like_val = f"%{keyword[:30].encode('unicode_escape').decode('utf-8')}%".replace(r"\u", r"\\u")
|
||||||
@ -40,20 +56,40 @@ class WorkflowAppService:
|
|||||||
if keyword_uuid:
|
if keyword_uuid:
|
||||||
keyword_conditions.append(WorkflowRun.id == keyword_uuid)
|
keyword_conditions.append(WorkflowRun.id == keyword_uuid)
|
||||||
|
|
||||||
query = query.outerjoin(
|
stmt = stmt.outerjoin(
|
||||||
EndUser,
|
EndUser,
|
||||||
and_(WorkflowRun.created_by == EndUser.id, WorkflowRun.created_by_role == CreatedByRole.END_USER),
|
and_(WorkflowRun.created_by == EndUser.id, WorkflowRun.created_by_role == CreatedByRole.END_USER),
|
||||||
).filter(or_(*keyword_conditions))
|
).where(or_(*keyword_conditions))
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
# join with workflow_run and filter by status
|
stmt = stmt.where(WorkflowRun.status == status)
|
||||||
query = query.filter(WorkflowRun.status == status.value)
|
|
||||||
|
|
||||||
query = query.order_by(WorkflowAppLog.created_at.desc())
|
# Add time-based filtering
|
||||||
|
if created_at_before:
|
||||||
|
stmt = stmt.where(WorkflowAppLog.created_at <= created_at_before)
|
||||||
|
|
||||||
pagination = db.paginate(query, page=args["page"], per_page=args["limit"], error_out=False)
|
if created_at_after:
|
||||||
|
stmt = stmt.where(WorkflowAppLog.created_at >= created_at_after)
|
||||||
|
|
||||||
return pagination
|
stmt = stmt.order_by(WorkflowAppLog.created_at.desc())
|
||||||
|
|
||||||
|
# Get total count using the same filters
|
||||||
|
count_stmt = select(func.count()).select_from(stmt.subquery())
|
||||||
|
total = session.scalar(count_stmt) or 0
|
||||||
|
|
||||||
|
# Apply pagination limits
|
||||||
|
offset_stmt = stmt.offset((page - 1) * limit).limit(limit)
|
||||||
|
|
||||||
|
# Execute query and get items
|
||||||
|
items = list(session.scalars(offset_stmt).all())
|
||||||
|
|
||||||
|
return {
|
||||||
|
"page": page,
|
||||||
|
"limit": limit,
|
||||||
|
"total": total,
|
||||||
|
"has_more": total > page * limit,
|
||||||
|
"data": items,
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _safe_parse_uuid(value: str):
|
def _safe_parse_uuid(value: str):
|
||||||
|
@ -2,11 +2,29 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { RiCalendarLine } from '@remixicon/react'
|
||||||
|
import quarterOfYear from 'dayjs/plugin/quarterOfYear'
|
||||||
import type { QueryParam } from './index'
|
import type { QueryParam } from './index'
|
||||||
import Chip from '@/app/components/base/chip'
|
import Chip from '@/app/components/base/chip'
|
||||||
import Input from '@/app/components/base/input'
|
import Input from '@/app/components/base/input'
|
||||||
|
dayjs.extend(quarterOfYear)
|
||||||
|
|
||||||
interface IFilterProps {
|
const today = dayjs()
|
||||||
|
|
||||||
|
export const TIME_PERIOD_MAPPING: { [key: string]: { value: number; name: string } } = {
|
||||||
|
1: { value: 0, name: 'today' },
|
||||||
|
2: { value: 7, name: 'last7days' },
|
||||||
|
3: { value: 28, name: 'last4weeks' },
|
||||||
|
4: { value: today.diff(today.subtract(3, 'month'), 'day'), name: 'last3months' },
|
||||||
|
5: { value: today.diff(today.subtract(12, 'month'), 'day'), name: 'last12months' },
|
||||||
|
6: { value: today.diff(today.startOf('month'), 'day'), name: 'monthToDate' },
|
||||||
|
7: { value: today.diff(today.startOf('quarter'), 'day'), name: 'quarterToDate' },
|
||||||
|
8: { value: today.diff(today.startOf('year'), 'day'), name: 'yearToDate' },
|
||||||
|
9: { value: -1, name: 'allTime' },
|
||||||
|
}
|
||||||
|
|
||||||
|
type IFilterProps = {
|
||||||
queryParams: QueryParam
|
queryParams: QueryParam
|
||||||
setQueryParams: (v: QueryParam) => void
|
setQueryParams: (v: QueryParam) => void
|
||||||
}
|
}
|
||||||
@ -27,6 +45,17 @@ const Filter: FC<IFilterProps> = ({ queryParams, setQueryParams }: IFilterProps)
|
|||||||
{ value: 'stopped', name: 'Stop' },
|
{ value: 'stopped', name: 'Stop' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<Chip
|
||||||
|
className='min-w-[150px]'
|
||||||
|
panelClassName='w-[270px]'
|
||||||
|
leftIcon={<RiCalendarLine className='h-4 w-4 text-text-secondary' />}
|
||||||
|
value={queryParams.period}
|
||||||
|
onSelect={(item) => {
|
||||||
|
setQueryParams({ ...queryParams, period: item.value })
|
||||||
|
}}
|
||||||
|
onClear={() => setQueryParams({ ...queryParams, period: '9' })}
|
||||||
|
items={Object.entries(TIME_PERIOD_MAPPING).map(([k, v]) => ({ value: k, name: t(`appLog.filter.period.${v.name}`) }))}
|
||||||
|
/>
|
||||||
<Input
|
<Input
|
||||||
wrapperClassName='w-[200px]'
|
wrapperClassName='w-[200px]'
|
||||||
showLeftIcon
|
showLeftIcon
|
||||||
|
@ -4,21 +4,30 @@ import React, { useState } from 'react'
|
|||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
import { useDebounce } from 'ahooks'
|
import { useDebounce } from 'ahooks'
|
||||||
|
import { omit } from 'lodash-es'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import utc from 'dayjs/plugin/utc'
|
||||||
|
import timezone from 'dayjs/plugin/timezone'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import List from './list'
|
import List from './list'
|
||||||
import Filter from './filter'
|
import Filter, { TIME_PERIOD_MAPPING } from './filter'
|
||||||
import Pagination from '@/app/components/base/pagination'
|
import Pagination from '@/app/components/base/pagination'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import { fetchWorkflowLogs } from '@/service/log'
|
import { fetchWorkflowLogs } from '@/service/log'
|
||||||
import { APP_PAGE_LIMIT } from '@/config'
|
import { APP_PAGE_LIMIT } from '@/config'
|
||||||
import type { App, AppMode } from '@/types/app'
|
import type { App, AppMode } from '@/types/app'
|
||||||
|
import { useAppContext } from '@/context/app-context'
|
||||||
|
|
||||||
|
dayjs.extend(utc)
|
||||||
|
dayjs.extend(timezone)
|
||||||
|
|
||||||
export type ILogsProps = {
|
export type ILogsProps = {
|
||||||
appDetail: App
|
appDetail: App
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueryParam = {
|
export type QueryParam = {
|
||||||
|
period: string
|
||||||
status?: string
|
status?: string
|
||||||
keyword?: string
|
keyword?: string
|
||||||
}
|
}
|
||||||
@ -48,7 +57,8 @@ const EmptyElement: FC<{ appUrl: string }> = ({ appUrl }) => {
|
|||||||
|
|
||||||
const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [queryParams, setQueryParams] = useState<QueryParam>({ status: 'all' })
|
const { userProfile: { timezone } } = useAppContext()
|
||||||
|
const [queryParams, setQueryParams] = useState<QueryParam>({ status: 'all', period: '2' })
|
||||||
const [currPage, setCurrPage] = React.useState<number>(0)
|
const [currPage, setCurrPage] = React.useState<number>(0)
|
||||||
const debouncedQueryParams = useDebounce(queryParams, { wait: 500 })
|
const debouncedQueryParams = useDebounce(queryParams, { wait: 500 })
|
||||||
const [limit, setLimit] = React.useState<number>(APP_PAGE_LIMIT)
|
const [limit, setLimit] = React.useState<number>(APP_PAGE_LIMIT)
|
||||||
@ -58,6 +68,13 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
|
|||||||
limit,
|
limit,
|
||||||
...(debouncedQueryParams.status !== 'all' ? { status: debouncedQueryParams.status } : {}),
|
...(debouncedQueryParams.status !== 'all' ? { status: debouncedQueryParams.status } : {}),
|
||||||
...(debouncedQueryParams.keyword ? { keyword: debouncedQueryParams.keyword } : {}),
|
...(debouncedQueryParams.keyword ? { keyword: debouncedQueryParams.keyword } : {}),
|
||||||
|
...((debouncedQueryParams.period !== '9')
|
||||||
|
? {
|
||||||
|
created_at__after: dayjs().subtract(TIME_PERIOD_MAPPING[debouncedQueryParams.period].value, 'day').startOf('day').tz(timezone).format('YYYY-MM-DDTHH:mm:ssZ'),
|
||||||
|
created_at__before: dayjs().endOf('day').tz(timezone).format('YYYY-MM-DDTHH:mm:ssZ'),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...omit(debouncedQueryParams, ['period', 'status']),
|
||||||
}
|
}
|
||||||
|
|
||||||
const getWebAppType = (appType: AppMode) => {
|
const getWebAppType = (appType: AppMode) => {
|
||||||
|
@ -42,7 +42,7 @@ export const VarItem: FC<VarItemProps> = ({
|
|||||||
<div className='py-1'>
|
<div className='py-1'>
|
||||||
<div className='flex leading-[18px] items-center'>
|
<div className='flex leading-[18px] items-center'>
|
||||||
<div className='code-sm-semibold text-text-secondary'>{name}</div>
|
<div className='code-sm-semibold text-text-secondary'>{name}</div>
|
||||||
<div className='ml-2 system-xs-regular text-text-tertiary'>{type}</div>
|
<div className='ml-2 system-xs-regular text-text-tertiary capitalize'>{type}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-0.5 system-xs-regular text-text-tertiary'>
|
<div className='mt-0.5 system-xs-regular text-text-tertiary'>
|
||||||
{description}
|
{description}
|
||||||
|
@ -17,7 +17,6 @@ import type {
|
|||||||
LogMessageAnnotationsResponse,
|
LogMessageAnnotationsResponse,
|
||||||
LogMessageFeedbacksRequest,
|
LogMessageFeedbacksRequest,
|
||||||
LogMessageFeedbacksResponse,
|
LogMessageFeedbacksResponse,
|
||||||
WorkflowLogsRequest,
|
|
||||||
WorkflowLogsResponse,
|
WorkflowLogsResponse,
|
||||||
WorkflowRunDetailResponse,
|
WorkflowRunDetailResponse,
|
||||||
} from '@/models/log'
|
} from '@/models/log'
|
||||||
@ -64,7 +63,7 @@ export const fetchAnnotationsCount: Fetcher<AnnotationsCountResponse, { url: str
|
|||||||
return get<AnnotationsCountResponse>(url)
|
return get<AnnotationsCountResponse>(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchWorkflowLogs: Fetcher<WorkflowLogsResponse, { url: string; params?: WorkflowLogsRequest }> = ({ url, params }) => {
|
export const fetchWorkflowLogs: Fetcher<WorkflowLogsResponse, { url: string; params: Record<string, any> }> = ({ url, params }) => {
|
||||||
return get<WorkflowLogsResponse>(url, { params })
|
return get<WorkflowLogsResponse>(url, { params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user