Skip to content

Commit

Permalink
feat: [lb-component] Add TagToolInstanceAdaptor to implement toolInst…
Browse files Browse the repository at this point in the history
…ance
  • Loading branch information
lijingchi authored and Glenfiddish committed Jun 8, 2022
1 parent 7ab27c2 commit 85cd646
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 18 deletions.
42 changes: 33 additions & 9 deletions packages/lb-components/src/components/videoAnnotate/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
import React from 'react';
import VideoPlayer from '@/components/VideoPlayer';
import { connect, useDispatch } from 'react-redux';
import { AppState } from '@/store';
import { AnnotationState } from '@/store/annotation/types';
import { PageBackward, PageForward, PageJump } from '@/store/annotation/actionCreators';
import { ANNOTATION_ACTIONS } from '@/store/Actions';
import { TagToolInstanceAdaptor } from '../VideoPlayer/TagToolInstanceAdaptor';

const VideoAnnotate: React.FC<{ annotation: AnnotationState }> = (props) => {
const { imgList, imgIndex } = props.annotation;
const { imgList, imgIndex, stepList, step } = props.annotation;
const dispatch = useDispatch();
const onMounted = (instance: TagToolInstanceAdaptor) => {
dispatch({
type: ANNOTATION_ACTIONS.SET_TOOL,
payload: {
instance,
},
});
};

const onUnmounted = () => {
dispatch({
type: ANNOTATION_ACTIONS.SET_TOOL,
payload: {
instance: undefined,
},
});
};

return (
<VideoPlayer
imgIndex={imgIndex}
imgList={imgList}
pageBackward={() => dispatch(PageBackward())}
pageForward={() => dispatch(PageForward())}
pageJump={(page) => dispatch(PageJump(page))}
/>
<>
<TagToolInstanceAdaptor
imgIndex={imgIndex}
imgList={imgList}
pageBackward={() => dispatch(PageBackward())}
pageForward={() => dispatch(PageForward())}
pageJump={(page) => dispatch(PageJump(page))}
onMounted={onMounted}
onUnmounted={onUnmounted}
stepList={stepList}
step={step}
/>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* @file 视频标签工具实现标签工具的方法
* @author lijingchi <[email protected]>
* @date 2022-05-31
*/

import React from 'react';
import { CommonToolUtils, uuid } from '@labelbee/lb-annotation';
import StepUtils from '@/utils/StepUtils';
import { jsonParser } from '@/utils';
import { VideoPlayer } from './index';
import { VideoTagLayer } from './VideoTagLayer';
import { IStepInfo } from '@/types/step';

export interface IZProp {
imgIndex: number;
imgList: any[];
pageForward: () => void;
pageJump: (page: number) => void;
pageBackward: () => void;
onMounted: (instance: TagToolInstanceAdaptor) => void;
onUnmounted: () => void;
step: number;
stepList: IStepInfo[];
}
export interface IZState {
tagResult: any[];
labelSelectedList: any;
}

export class TagToolInstanceAdaptor extends React.Component<IZProp, IZState> {
constructor(props: IZProp) {
super(props);
this.state = {
tagResult: [],
labelSelectedList: [],
};
}

get config() {
const stepInfo = StepUtils.getCurrentStepInfo(this.props.step, this.props.stepList);
return jsonParser(stepInfo?.config);
}

// TODO 标签记录
get labelSelectedList() {
return [];
}

get history() {
return { initRecord: () => {} };
}

get currentTagResult() {
return this.state.tagResult;
}

set labelSelectedList(labelSelectedList: any) {
this.setState({
labelSelectedList,
});
}

public clearResult = (sendMsg: boolean, value?: string) => {
const newTag = value
? this.state.tagResult.map((v) => {
if (v?.result[value]) {
delete v.result[value];
}
return v;
})
: [];

this.setState({
tagResult: newTag,
});
};

public exportData = () => {
return [this.state.tagResult, { valid: true }];
};

public singleOn() {}

public getTagResultByCode(num1: number, num2?: number) {
try {
const inputList = this.config?.inputList ?? [];
const mulitTags = inputList.length > 1;
const keycode1 = num2 !== undefined ? num1 : 0;
const keycode2 = num2 !== undefined ? num2 : num1;
const primaryTagConfig = mulitTags ? inputList[keycode1] : inputList[0];
const secondaryTagConfig = (primaryTagConfig.subSelected ?? [])[keycode2];

if (primaryTagConfig && secondaryTagConfig) {
return {
value: {
key: primaryTagConfig.value,
value: secondaryTagConfig.value,
},
isMulti: primaryTagConfig.isMulti,
};
}
} catch {
return;
}
}

public setLabelBySelectedList(num1: number, num2?: number) {
const newTagConfig = this.getTagResultByCode(num1, num2);
const currentRes = this.state.tagResult.length > 0 ? this.state.tagResult[0].result : {};

if (newTagConfig) {
const inputValue = { [newTagConfig.value.key]: newTagConfig.value.value };
// todo: 合并输入逻辑
const tagRes = newTagConfig.isMulti ? Object.assign(currentRes, inputValue) : inputValue;

const tagResult = [
{
sourceID: CommonToolUtils.getSourceID(),
id: uuid(8, 62),
result: tagRes,
},
];

this.setState({
tagResult,
});
}
}

public setResult = (tagResult: any[]) => {
this.setState({
tagResult,
});
};

public setLabel = (num1: number, num2: number) => {
this.setLabelBySelectedList(num1, num2);
};

public componentDidMount() {
// document.addEventListener('keydown', this.keydown);
this.props.onMounted(this);
}

public componentWillMount() {
// document.addEventListener('keydown', this.keydown);
this.props.onUnmounted();
}

public shouldComponentUpdate({ imgIndex, imgList, step }: IZProp) {
if (imgIndex !== this.props.imgIndex) {
this.setState({
tagResult: jsonParser(imgList[imgIndex].result)[`step_${step}`]?.result ?? [],
});
}
return true;
}

public render() {
const { imgIndex, imgList, pageForward, pageJump, pageBackward } = this.props;
const { tagResult } = this.state;

return (
<div style={{ height: '100%', width: '100%', position: 'relative' }}>
<VideoPlayer
imgIndex={imgIndex}
imgList={imgList}
pageBackward={pageBackward}
pageForward={pageForward}
pageJump={pageJump}
/>
<VideoTagLayer result={tagResult} inputList={this.config?.inputList} />
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';

/**
* 通过 key和value在inputList找到对应的标签
* @param key
* @param value
* @param inputList
*/
const findTagLabel = (key: string, value: string, inputList: any[]) => {
const primaryTagConfig = inputList.find((i) => i.value === key);
const secondaryTagConfig = primaryTagConfig.subSelected.find((i) => i.value === value);
return { keyLabel: primaryTagConfig.key, valueLabel: secondaryTagConfig.key };
};

const result2LabelKey = (result: any[], inputList: any[]) => {
try {
return (
result?.reduce(
(
exitsTags: Array<{ keyLabel: string; valueLabel: string }>,
res: { result: { [key: string]: string } },
) => {
Object.keys(res.result).forEach((key) => {
const value = res.result[key];
const { keyLabel, valueLabel } = findTagLabel(key, value, inputList);
if (!exitsTags.find((i) => i.keyLabel === keyLabel && i.valueLabel === valueLabel)) {
exitsTags.push({ keyLabel, valueLabel });
}
});
return exitsTags;
},
[],
) ?? []
);
} catch (error) {
return [];
}
};

export const VideoTagLayer = ({
result,
inputList,
}: {
result: Array<{ result: { [key: string]: string } }>;
inputList: any[];
}) => {
const cssProperty: React.CSSProperties = {
position: 'absolute',
zIndex: 20,
padding: '0 20px',
color: 'white',
fontSize: 15,
lineHeight: '32px',
background: 'rgba(0, 255, 255, 0.32)',
top: 0,
right: 0,
maxHeight: 'calc(100% - 80px)',
overflowY: 'scroll',
};

const tags: Array<{ keyLabel: string; valueLabel: string }> = result2LabelKey(result, inputList);

return (
<div style={cssProperty}>
<table>
<tbody>
{tags.map(({ keyLabel, valueLabel }) => (
<tr key={keyLabel}>
<td style={{ paddingRight: 8 }}>{`${keyLabel}:`}</td>
<td>{`${valueLabel}`}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
18 changes: 13 additions & 5 deletions packages/lb-components/src/components/videoPlayer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,19 @@ interface IState {
export const decimalReserved = (num: number, places: number = 2) =>
typeof num === 'number' ? parseFloat(num.toFixed(places)) : num;

class VideoPlayer extends React.Component<IProps, IState> {
const getKeyCodeNumber = (keyCode: number) => {
if (keyCode <= 57 && keyCode >= 49) {
return keyCode - 49;
}

if (keyCode <= 105 && keyCode >= 97) {
return keyCode - 97;
}

return 0;
};

export class VideoPlayer extends React.Component<IProps, IState> {
public videoRef?: React.RefObject<HTMLVideoElement>;
public timeInterval?: number;

Expand Down Expand Up @@ -217,10 +229,6 @@ class VideoPlayer extends React.Component<IProps, IState> {
window.removeEventListener('keyup', this.keyUpEvents);
}

public shouldComponentUpdate() {
return true;
}

public render() {
const { isPlay, playbackRate, currentTime, duration, buffered } = this.state;
const { imgList, imgIndex, pageBackward, pageJump, pageForward } = this.props;
Expand Down
1 change: 1 addition & 0 deletions packages/lb-components/src/store/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const ANNOTATION_ACTIONS = {
SUBMIT_FILE_DATA: '@@SUBMIT_FILE_DATA',
SET_TASK_CONFIG: '@@SET_TASK_CONFIG',
INIT_TOOL: '@@INIT_TOOL',
SET_TOOL: '@@SET_TOOL',
UPDATE_ON_SUBMIT: '@@UPDATE_ON_SUBMIT',
UPDATE_ON_SAVE: '@@UPDATE_ON_SAVE',
UPDATE_ON_PAGE_CHANGE: '@@UPDATE_ON_PAGE_CHANGE',
Expand Down
19 changes: 16 additions & 3 deletions packages/lb-components/src/store/annotation/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,12 @@ export const annotationReducer = (
}

case ANNOTATION_ACTIONS.SUBMIT_RESULT: {
const { imgList, basicIndex, resultList, annotationEngine, basicResultList } = state;
if (!annotationEngine) {
const { imgList, basicIndex, resultList, toolInstance, basicResultList } = state;
if (!toolInstance) {
return state;
}

const [exportResult] = annotationEngine?.toolInstance?.exportData();
const [exportResult] = toolInstance?.exportData();

let previousResultList = exportResult;

Expand Down Expand Up @@ -430,6 +430,19 @@ export const annotationReducer = (
};
}

case ANNOTATION_ACTIONS.SET_TOOL: {
if (action.payload.instance) {
return {
...state,
toolInstance: action.payload.instance,
};
}

return {
...state,
};
}

case ANNOTATION_ACTIONS.UPDATE_ON_SUBMIT: {
return {
...state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ const TagSidebar: React.FC<IProps> = ({ toolInstance, imgIndex }) => {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
flex: 1,
}}
>
<span>
Expand Down
Loading

0 comments on commit 85cd646

Please sign in to comment.