Add about CVAT (#1024)

main
Lisa 6 years ago committed by Boris Sekachev
parent 25164fe8b6
commit 3f22922818

@ -0,0 +1,55 @@
import { AnyAction, Dispatch, ActionCreator } from 'redux';
import { ThunkAction } from 'redux-thunk';
import getCore from 'cvat-core';
const core = getCore();
export enum AboutActionTypes {
GET_ABOUT = 'GET_ABOUT',
GET_ABOUT_SUCCESS = 'GET_ABOUT_SUCCESS',
GET_ABOUT_FAILED = 'GET_ABOUT_FAILED',
}
function getAbout(): AnyAction {
const action = {
type: AboutActionTypes.GET_ABOUT,
payload: {},
};
return action;
}
function getAboutSuccess(about: any): AnyAction {
const action = {
type: AboutActionTypes.GET_ABOUT_SUCCESS,
payload: { about },
};
return action;
}
function getAboutFailed(error: any): AnyAction {
const action = {
type: AboutActionTypes.GET_ABOUT_FAILED,
payload: { error },
};
return action;
}
export function getAboutAsync():
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch(getAbout());
try {
const about = await core.server.about();
dispatch(
getAboutSuccess(about),
);
} catch (error) {
dispatch(getAboutFailed(error));
}
};
}

@ -29,6 +29,7 @@ import { NotificationsState } from 'reducers/interfaces';
type CVATAppProps = {
loadFormats: () => void;
loadUsers: () => void;
loadAbout: () => void;
verifyAuthorized: () => void;
initPlugins: () => void;
resetErrors: () => void;
@ -40,6 +41,8 @@ type CVATAppProps = {
formatsFetching: boolean;
usersInitialized: boolean;
usersFetching: boolean;
aboutInitialized: boolean;
aboutFetching: boolean;
installedAutoAnnotation: boolean;
installedTFAnnotation: boolean;
installedTFSegmentation: boolean;
@ -57,12 +60,15 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
const {
loadFormats,
loadUsers,
loadAbout,
initPlugins,
userInitialized,
formatsInitialized,
formatsFetching,
usersInitialized,
usersFetching,
aboutInitialized,
aboutFetching,
pluginsInitialized,
pluginsFetching,
user,
@ -84,6 +90,10 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
loadUsers();
}
if (!aboutInitialized && !aboutFetching) {
loadAbout();
}
if (!pluginsInitialized && !pluginsFetching) {
initPlugins();
}
@ -153,6 +163,7 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
const { tasks } = notifications.errors;
const { formats } = notifications.errors;
const { users } = notifications.errors;
const { about } = notifications.errors;
const { share } = notifications.errors;
const { models } = notifications.errors;
const { annotation } = notifications.errors;
@ -160,7 +171,7 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
const shown = !!auth.authorized || !!auth.login || !!auth.logout || !!auth.register
|| !!tasks.fetching || !!tasks.updating || !!tasks.dumping || !!tasks.loading
|| !!tasks.exporting || !!tasks.deleting || !!tasks.creating || !!formats.fetching
|| !!users.fetching || !!share.fetching || !!models.creating || !!models.starting
|| !!users.fetching || !!about.fetching || !!share.fetching || !!models.creating || !!models.starting
|| !!models.fetching || !!models.deleting || !!models.inferenceStatusFetching
|| !!models.metaFetching || !!annotation.frameFetching || !!annotation.saving
|| !!annotation.jobFetching;
@ -204,6 +215,9 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
if (users.fetching) {
showError(users.fetching.message, users.fetching.reason);
}
if (about.fetching) {
showError(about.fetching.message, about.fetching.reason);
}
if (share.fetching) {
showError(share.fetching.message, share.fetching.reason);
}
@ -248,6 +262,7 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
const {
userInitialized,
usersInitialized,
aboutInitialized,
pluginsInitialized,
formatsInitialized,
installedAutoAnnotation,
@ -258,7 +273,7 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
const readyForRender = (userInitialized && user == null)
|| (userInitialized && formatsInitialized
&& pluginsInitialized && usersInitialized);
&& pluginsInitialized && usersInitialized && aboutInitialized);
const withModels = installedAutoAnnotation
|| installedTFAnnotation || installedTFSegmentation;

@ -3,13 +3,15 @@ import React from 'react';
import { RouteComponentProps } from 'react-router';
import { withRouter } from 'react-router-dom';
import {
Layout,
Icon,
Button,
Menu,
Dropdown,
Modal,
Row,
Col,
} from 'antd';
import Text from 'antd/lib/typography/Text';
@ -31,6 +33,7 @@ interface HeaderContainerProps {
installedTFAnnotation: boolean;
installedTFSegmentation: boolean;
username: string;
about: any;
}
type Props = HeaderContainerProps & RouteComponentProps;
@ -42,6 +45,7 @@ function HeaderContainer(props: Props): JSX.Element {
installedTFAnnotation,
installedAnalytics,
username,
about,
onLogout,
logoutFetching,
} = props;
@ -50,6 +54,47 @@ function HeaderContainer(props: Props): JSX.Element {
|| installedTFAnnotation
|| installedTFSegmentation;
function aboutModal() {
Modal.info({
title: `${about.name}`,
content: (
<div>
<p>
{`${about.description}`}
</p>
<p>
<Text strong>
Server version:
</Text>
<Text type='secondary'>
{` ${about.version}`}
</Text>
</p>
<p>
<Text strong>
Client version:
</Text>
<Text type='secondary'>
{` ${core.client.version}`}
</Text>
</p>
<Row type='flex' justify='space-around'>
<Col><a href='https://github.com/opencv/cvat/blob/develop/CHANGELOG.md' target='_blank' rel='noopener noreferrer' >What's new?</a></Col>
<Col><a href='https://github.com/opencv/cvat/blob/develop/LICENSE' target='_blank' rel='noopener noreferrer' >License</a></Col>
<Col><a href='https://gitter.im/opencv-cvat' target='_blank' rel='noopener noreferrer' >Need help?</a></Col>
<Col><a href='https://software.intel.com/en-us/forums/intel-distribution-of-openvino-toolkit' target='_blank' rel='noopener noreferrer' >Forum on Intel Developer Zone</a></Col>
</Row>
</div>
),
width : 800,
okButtonProps: {
style: {
width: '100px',
},
},
})
}
const menu = (
<Menu className='cvat-header-menu' mode='vertical'>
<Menu.Item
@ -60,7 +105,7 @@ function HeaderContainer(props: Props): JSX.Element {
<Icon type='setting' />
Settings
</Menu.Item>
<Menu.Item>
<Menu.Item onClick={() => aboutModal()}>
<Icon type='info-circle' />
About
</Menu.Item>

@ -16,6 +16,7 @@ interface StateToProps {
installedTFSegmentation: boolean;
installedTFAnnotation: boolean;
username: string;
about: any;
}
interface DispatchToProps {
@ -32,6 +33,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
installedTFSegmentation: plugins[SupportedPlugins.TF_SEGMENTATION],
installedTFAnnotation: plugins[SupportedPlugins.TF_ANNOTATION],
username: auth.user.username,
about: state.about.about,
};
}

@ -11,6 +11,7 @@ import { authorizedAsync } from './actions/auth-actions';
import { getFormatsAsync } from './actions/formats-actions';
import { checkPluginsAsync } from './actions/plugins-actions';
import { getUsersAsync } from './actions/users-actions';
import { getAboutAsync } from './actions/about-actions';
import {
resetErrors,
resetMessages,
@ -30,6 +31,8 @@ interface StateToProps {
userInitialized: boolean;
usersInitialized: boolean;
usersFetching: boolean;
aboutInitialized: boolean;
aboutFetching: boolean;
formatsInitialized: boolean;
formatsFetching: boolean;
installedAutoAnnotation: boolean;
@ -43,6 +46,7 @@ interface DispatchToProps {
loadFormats: () => void;
verifyAuthorized: () => void;
loadUsers: () => void;
loadAbout: () => void;
initPlugins: () => void;
resetErrors: () => void;
resetMessages: () => void;
@ -53,6 +57,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
const { auth } = state;
const { formats } = state;
const { users } = state;
const { about } = state;
return {
userInitialized: auth.initialized,
@ -60,6 +65,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
pluginsFetching: plugins.fetching,
usersInitialized: users.initialized,
usersFetching: users.fetching,
aboutInitialized: about.initialized,
aboutFetching: about.fetching,
formatsInitialized: formats.initialized,
formatsFetching: formats.fetching,
installedAutoAnnotation: plugins.plugins.AUTO_ANNOTATION,
@ -67,6 +74,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
installedTFAnnotation: plugins.plugins.TF_ANNOTATION,
notifications: { ...state.notifications },
user: auth.user,
about: state.about,
};
}
@ -76,6 +84,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
verifyAuthorized: (): void => dispatch(authorizedAsync()),
initPlugins: (): void => dispatch(checkPluginsAsync()),
loadUsers: (): void => dispatch(getUsersAsync()),
loadAbout: (): void => dispatch(getAboutAsync()),
resetErrors: (): void => dispatch(resetErrors()),
resetMessages: (): void => dispatch(resetMessages()),
};

@ -0,0 +1,45 @@
import { AnyAction } from 'redux';
import { AboutState } from './interfaces';
import { AuthActionTypes } from '../actions/auth-actions';
import { AboutActionTypes } from '../actions/about-actions';
const defaultState: AboutState = {
about: {},
fetching: false,
initialized: false,
};
export default function (state: AboutState = defaultState, action: AnyAction): AboutState {
switch (action.type) {
case AboutActionTypes.GET_ABOUT: {
return {
...state,
fetching: true,
initialized: false,
};
}
case AboutActionTypes.GET_ABOUT_SUCCESS:
return {
...state,
fetching: false,
initialized: true,
about: action.payload.about,
};
case AboutActionTypes.GET_ABOUT_FAILED:
return {
...state,
fetching: false,
initialized: true,
};
case AuthActionTypes.LOGOUT_SUCCESS: {
return {
...defaultState,
};
}
default:
return {
...state,
};
}
}

@ -94,6 +94,12 @@ export interface UsersState {
initialized: boolean;
}
export interface AboutState {
about: any;
fetching: boolean;
initialized: boolean;
}
export interface ShareFileInfo { // get this data from cvat-core
name: string;
type: 'DIR' | 'REG';
@ -181,6 +187,9 @@ export interface NotificationsState {
users: {
fetching: null | ErrorState;
};
about: {
fetching: null | ErrorState;
};
share: {
fetching: null | ErrorState;
};
@ -302,6 +311,7 @@ export interface CombinedState {
auth: AuthState;
tasks: TasksState;
users: UsersState;
about: AboutState;
share: ShareState;
formats: FormatsState;
plugins: PluginsState;

@ -6,6 +6,7 @@ import { ModelsActionTypes } from 'actions/models-actions';
import { ShareActionTypes } from 'actions/share-actions';
import { TasksActionTypes } from 'actions/tasks-actions';
import { UsersActionTypes } from 'actions/users-actions';
import { AboutActionTypes } from '../actions/about-actions';
import { AnnotationActionTypes } from 'actions/annotation-actions';
import { NotificationsActionType } from 'actions/notification-actions';
@ -34,6 +35,9 @@ const defaultState: NotificationsState = {
users: {
fetching: null,
},
about: {
fetching: null,
},
share: {
fetching: null,
},
@ -282,6 +286,21 @@ export default function (state = defaultState, action: AnyAction): Notifications
},
};
}
case AboutActionTypes.GET_ABOUT_FAILED: {
return {
...state,
errors: {
...state.errors,
about: {
...state.errors.about,
fetching: {
message: 'Could not get data from the server',
reason: action.payload.error.toString(),
},
},
},
};
}
case ShareActionTypes.LOAD_SHARE_DATA_FAILED: {
return {
...state,

@ -2,6 +2,7 @@ import { combineReducers, Reducer } from 'redux';
import authReducer from './auth-reducer';
import tasksReducer from './tasks-reducer';
import usersReducer from './users-reducer';
import aboutReducer from './about-reducer';
import shareReducer from './share-reducer';
import formatsReducer from './formats-reducer';
import pluginsReducer from './plugins-reducer';
@ -15,6 +16,7 @@ export default function createRootReducer(): Reducer {
auth: authReducer,
tasks: tasksReducer,
users: usersReducer,
about: aboutReducer,
share: shareReducer,
formats: formatsReducer,
plugins: pluginsReducer,

Loading…
Cancel
Save