Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[web] 250 bugsfixed07 for zentao #1742

Merged
merged 10 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions ymir/web/src/components/common/LeftMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { FC, ReactNode, useEffect, useState } from 'react'
import { Menu, Layout, MenuProps, MenuItemProps, Modal, message } from 'antd'
import { useHistory, useLocation, withRouter, useSelector, useParams } from 'umi'
import { Menu, Layout, MenuProps, Modal, message } from 'antd'
import { useHistory, useLocation, withRouter, useSelector } from 'umi'
import t from '@/utils/t'
import { getDeployUrl, getPublicImageUrl } from '@/constants/common'
import { getDeployUrl, getPublicImageUrl, readyState } from '@/constants/common'
import { isAdmin, isSuperAdmin } from '@/constants/user'
import {
BarchartIcon,
FlagIcon,
GithubIcon,
FileHistoryIcon,
Expand All @@ -20,7 +19,6 @@ import {
DeviceSupportedIcon,
MyAlgoIcon,
StoreIcon,
BarChart2LineIcon,
ProjectIcon,
VectorIcon,
BookIcon,
Expand All @@ -33,7 +31,6 @@ import useRequest from '@/hooks/useRequest'
import SampleProjectTip from './SampleProjectTip'
import { Image, Project } from '@/constants'
import { isMultiModal } from '@/constants/objectType'
import LLMM from '@/constants/llmm'
type MenuItem = Required<MenuProps>['items'][number]
type Handler = Required<MenuProps>['onClick']

Expand Down Expand Up @@ -63,11 +60,11 @@ function LeftMenu() {
const [project, setProject] = useState<Project>()
const { trainingDatasetCount, tasks } = useSelector(({ dataset, socket }) => ({ trainingDatasetCount: dataset.trainingDatasetCount, tasks: socket.tasks }))
const { run: getTrainingDatasetCount } = useRequest<null, [number]>('dataset/getTrainingDatasetCount', {
cacheKey: 'getTrainingDatasetCount',
loading: false,
})
const { data: gsImage } = useRequest<Image>('image/getGroundedSAMImage', {
const { runAsync: getGroundedSAMImage } = useRequest<Image>('image/getGroundedSAMImage', {
loading: false,
manual: false,
})
const { runAsync: createGroundedSAMImage } = useRequest('image/createGroundedSAMImage')

Expand Down Expand Up @@ -136,28 +133,42 @@ function LeftMenu() {
])
}, [id, project, role, trainingDatasetCount])

const clickHandle: Handler = ({ key }) => {
const clickHandle: Handler = async ({ key }) => {
const outer = /^outer\//.test(key)
if (!outer) {
if (key.includes('/llmm/infer')) {
llmmInferHandle(key)
return
}
setDefaultKeys([key])
if (key.includes('/llmm/infer') && gsImage?.url !== LLMM.GroundedSAMImageUrl) {
if (!isAdmin(role)) {
return Modal.info({
title: 'Grounded-SAM Image',
content: t('llmm.groundedsam.image.add.user.invalid'),
})
}
return Modal.confirm({
history.push(key)
}
}

const llmmInferHandle = async (key: string) => {
const gsImage = await getGroundedSAMImage()
if (!gsImage) {
if (!isAdmin(role)) {
return Modal.info({
title: 'Grounded-SAM Image',
content: <>{t('llmm.groundedsam.image.add.tip')}</>,
onOk: async () => {
const result = await createGroundedSAMImage()
if (result) {
message.success('llmm.groundedsam.image.add.success')
}
},
content: t('llmm.groundedsam.image.add.user.invalid'),
})
}
return Modal.confirm({
title: 'Grounded-SAM Image',
content: <>{t('llmm.groundedsam.image.add.tip')}</>,
onOk: async () => {
const result = await createGroundedSAMImage()
if (result) {
message.success(t('llmm.groundedsam.image.add.success'))
}
},
})
} else {
if (readyState(gsImage.state)) {
return Modal.info({ content: t('llmm.groundedsam.image.add.success') })
}
setDefaultKeys([key])
history.push(key)
}
}
Expand Down
2 changes: 1 addition & 1 deletion ymir/web/src/components/image/StateTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const StateTag: React.FC<Props> = ({ state = states.READY, label, code }) => {
{label ? t(`image.state.${tag.key}`) : null}
</span>
)
return tag.key === 'error' ? (
return tag.key === 'error' && code ? (
<a href={getErrorCodeDocLink(code)} target="_blank" title={t(`error${code}`)}>
{text}
</a>
Expand Down
2 changes: 1 addition & 1 deletion ymir/web/src/constants/typings/task.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ type ProgressTask = {
result_dataset?: { id: number }
result_model?: { id: number }
result_prediction?: { id: number }
result_image?: { id: number }
result_docker_image?: { id: number }
}

export { Task, ProgressTask, ParamsByType }
1 change: 1 addition & 0 deletions ymir/web/src/locales/modules/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const model = {
'model.stage.metrics.primary.label.det': { en: 'mAP', cn: '精度均值(mAP)' },
'model.stage.metrics.primary.label.seg': { en: 'mIoU', cn: '精度均值(mIoU)' },
'model.stage.metrics.primary.label.ins': { en: 'maskAP', cn: '精度均值(maskAP)' },
'model.stage.metrics.primary.label.mul': { en: 'mAP', cn: '精度均值(mAP)' },
}

export default model
1 change: 1 addition & 0 deletions ymir/web/src/models/__test__/image.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe('models: image', () => {
code: 0,
result,
})
generator.next()
const end = generator.next()

expect(end.value).toEqual(expected)
Expand Down
20 changes: 13 additions & 7 deletions ymir/web/src/models/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { ObjectType } from '@/constants/objectType'
import LLMM from '@/constants/llmm'
import { ImageState, ImageStore } from '.'
import { Image } from '@/constants'
import { List } from './typings/common'

const state: ImageState = {
images: { items: [], total: 0 },
image: {},
total: 0,
official: undefined,
Expand All @@ -23,6 +25,11 @@ const ImageModel: ImageStore = {
if (code === 0) {
const { items, total } = result
const images: Image[] = items.map(transferImage)
const list = { items: images, total }
yield put({
type: 'UpdateImages',
payload: list,
})
yield put({
type: 'UpdateImage',
payload: images.reduce(
Expand All @@ -33,7 +40,7 @@ const ImageModel: ImageStore = {
{},
),
})
return { items: images, total }
return list
}
}),
getImage: createEffect<{ id: number; force?: boolean }>(function* ({ payload }, { call, put, select }) {
Expand Down Expand Up @@ -125,11 +132,11 @@ const ImageModel: ImageStore = {
return list
}),
getOfficialImage: createEffect<boolean>(function* ({ payload: force }, { put, select }) {
const { official } = select(({ image }) => image)
const { official } = yield select(({ image }) => image)
if (!force && official) {
return official
}
const images = yield put.resolve({
const images: List<Image> = yield put.resolve({
type: 'getImages',
payload: {
official: true,
Expand All @@ -145,15 +152,14 @@ const ImageModel: ImageStore = {
}
}),
getGroundedSAMImage: createEffect(function* ({}, { put, select }) {
const { groundedSAM } = select(({ image }) => image)
const { groundedSAM } = yield select(({ image }) => image)
if (groundedSAM) {
return groundedSAM
}
const images = yield put.resolve({
type: 'getImages',
payload: {
url: LLMM.GroundedSAMImageUrl,
state: STATES.VALID,
},
})
if (images?.items?.length) {
Expand All @@ -166,14 +172,14 @@ const ImageModel: ImageStore = {
}
}),
haveGroundedSAMImage: createEffect(function* ({}, { put, select }) {
const { groundedSAM } = select(({ image }) => image)
const { groundedSAM } = yield select(({ image }) => image)
return LLMM.GroundedSAMImageUrl === groundedSAM?.url
}),
createGroundedSAMImage: createEffect(function* ({}, { put }) {
return yield put.resolve({
type: 'createImage',
payload: {
name: 'Grounded SAM',
name: 'Grounded-SAM',
url: LLMM.GroundedSAMImageUrl,
},
})
Expand Down
1 change: 1 addition & 0 deletions ymir/web/src/models/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ interface IterationState {
}

interface ImageState {
images: List<Image>
image: IdMap<Image>
total: number
official?: Image
Expand Down
44 changes: 42 additions & 2 deletions ymir/web/src/models/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { createEffect } from './_utils'
import { history } from 'umi'
import { Socket as SocketType } from 'socket.io-client'
import { SocketStore } from '.'
import { IdMap } from './typings/common.d'
import { Backend, ProgressTask, User } from '@/constants'
import { IdMap, List } from './typings/common.d'
import { Backend, Image, ProgressTask, User } from '@/constants'

history
const pageMaps = [
{ path: '/home/project/\\d+/dataset', method: 'dataset/updateDatasets' },
Expand Down Expand Up @@ -56,6 +57,36 @@ const Socket: SocketStore = {
payload,
})
}),
updateGroundedSamImage: createEffect<ProgressTask[]>(function* ({ payload: tasks }, { put, select }) {
const gsImage: Image | undefined = yield select(({ image }) => image.groundedSAM)
const imageTask = tasks.find(({ result_docker_image }) => result_docker_image?.id)
if (gsImage && imageTask && gsImage?.id === imageTask?.result_docker_image?.id) {
const image = { ...gsImage, state: imageTask.result_state }
yield put({
type: 'image/UpdateGroundedSAM',
payload: image,
})
}
}),
updateImageList: createEffect<ProgressTask[]>(function* ({ payload: tasks }, { put, select }) {
const { items, total }: List<Image> = yield select(({ image }) => image.images)
const imageTasks = tasks.filter(({ result_docker_image }) => result_docker_image?.id)
if (imageTasks.length) {
const images = items.map((image) => {
const imageTask = imageTasks.find((task) => task.result_docker_image?.id === image.id)
return imageTask
? {
...image,
state: imageTask.result_state,
}
: image
})
yield put({
type: 'image/UpdateImages',
payload: { items: images, total },
})
}
}),
},
reducers: {
updateSocket(state, { payload }) {
Expand All @@ -75,8 +106,17 @@ const Socket: SocketStore = {
.off()
.on('update_taskstate', (data) => {
pageMaps.forEach((page) => dispatch({ type: page.method, payload: data }))

const tasks: ProgressTask[] = Object.keys(data).map((hash) => ({
...data[hash],
hash,
reload: !readyState(data[hash].result_state),
}))
// cache socket valid data
dispatch({ type: 'saveUpdatedTasks', payload: data })
// update data in socket model by dispatch effects
dispatch({ type: 'updateGroundedSamImage', payload: tasks })
dispatch({ type: 'updateImageList', payload: tasks })
})
.on('update_message', (data) => {
dispatch({ type: 'asyncMessages', payload: data })
Expand Down
7 changes: 4 additions & 3 deletions ymir/web/src/pages/image/components/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const ImageList: FC<{ filter: () => void }> = ({ filter }) => {
const linkModalRef = useRef<RefProps>(null)
const delRef = useRef<DelRefProps>(null)
const role = useSelector(({ user }) => user.user.role)
const { data: remoteImages, run: getImages } = useRequest<ListType<Image>, [QueryParams]>('image/getImages')
const { images: remoteImages } = useSelector(({ image }) => image)
const { run: getImages } = useRequest<ListType<Image>, [QueryParams]>('image/getImages')

/** use effect must put on the top */
useEffect(() => {
Expand Down Expand Up @@ -144,7 +145,7 @@ const ImageList: FC<{ filter: () => void }> = ({ filter }) => {
const cls = getProjectTypeLabel(type)
const label = getProjectTypeLabel(type, true)
return type && cls ? (
<span key={type} className={`extraTag ${cls}`}>
<span key={`ot${type}`} className={`extraTag ${cls}`}>
{t(label)}
</span>
) : null
Expand Down Expand Up @@ -207,7 +208,7 @@ const ImageList: FC<{ filter: () => void }> = ({ filter }) => {
)

return (
<List.Item className={item.state ? 'success' : 'failure'} onClick={() => history.push(`/home/image/detail/${item.id}`)}>
<List.Item key={item.id} className={item.state ? 'success' : 'failure'} onClick={() => history.push(`/home/image/detail/${item.id}`)}>
<List.Item.Meta title={title} description={desc}></List.Item.Meta>
</List.Item>
)
Expand Down
4 changes: 2 additions & 2 deletions ymir/web/src/pages/project/diagnose/components/Metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Button, Form, Row, Col, Radio, Slider, Select, InputNumber, Space, Tag,
import { useLocation, useSelector } from 'umi'

import t from '@/utils/t'
import { ObjectType, isDetection, isSemantic } from '@/constants/objectType'
import { ObjectType, isDetection, isSemantic, isSegmentation } from '@/constants/objectType'

import Panel from '@/components/form/panel'
import SingleMetircView from './SingleMetircView'
Expand Down Expand Up @@ -155,7 +155,7 @@ const Matrics: FC<Props> = ({ prediction }) => {
fetchDiagnosis({
pid: prediction.projectId,
predictionId: prediction.id,
curve: isDetection(prediction?.type),
curve: !isSegmentation(prediction?.type),
averageIou: true,
confidence,
})
Expand Down