Skip to content

Commit

Permalink
Configurable REST for UI, minor improvements (cvat-ai#880)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsekachev authored and Chris Lee-Messer committed Mar 5, 2020
1 parent e5a9e4c commit 59993a2
Show file tree
Hide file tree
Showing 26 changed files with 210 additions and 50 deletions.
5 changes: 4 additions & 1 deletion Dockerfile.ui
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ ARG http_proxy
ARG https_proxy
ARG no_proxy
ARG socks_proxy
ARG REACT_APP_API_PORT
ARG REACT_APP_API_PROTOCOL
ARG REACT_APP_API_HOST

ENV TERM=xterm \
http_proxy=${http_proxy} \
Expand Down Expand Up @@ -36,7 +39,7 @@ RUN npm install
# Build source code
COPY cvat-core/ /tmp/cvat-core/
COPY cvat-ui/ /tmp/cvat-ui/
RUN mv .env.production .env && npm run build
RUN npm run build

FROM nginx
# Replace default.conf configuration to remove unnecessary rules
Expand Down
9 changes: 0 additions & 9 deletions cvat-ui/.env

This file was deleted.

9 changes: 0 additions & 9 deletions cvat-ui/.env.production

This file was deleted.

18 changes: 18 additions & 0 deletions cvat-ui/src/actions/auth-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ const cvat = getCore();
export enum AuthActionTypes {
AUTHORIZED_SUCCESS = 'AUTHORIZED_SUCCESS',
AUTHORIZED_FAILED = 'AUTHORIZED_FAILED',
LOGIN = 'LOGIN',
LOGIN_SUCCESS = 'LOGIN_SUCCESS',
LOGIN_FAILED = 'LOGIN_FAILED',
REGISTER = 'REGISTER',
REGISTER_SUCCESS = 'REGISTER_SUCCESS',
REGISTER_FAILED = 'REGISTER_FAILED',
LOGOUT = 'LOGOUT',
LOGOUT_SUCCESS = 'LOGOUT_SUCCESS',
LOGOUT_FAILED = 'LOGOUT_FAILED',
}
Expand Down Expand Up @@ -95,6 +98,11 @@ export function registerAsync(
password2: string,
): ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch({
type: AuthActionTypes.REGISTER,
payload: {},
});

let users = null;
try {
await cvat.server.register(username, firstName, lastName,
Expand All @@ -112,6 +120,11 @@ export function registerAsync(
export function loginAsync(username: string, password: string):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch({
type: AuthActionTypes.LOGIN,
payload: {},
});

let users = null;
try {
await cvat.server.login(username, password);
Expand All @@ -127,6 +140,11 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {

export function logoutAsync(): ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch({
type: AuthActionTypes.LOGOUT,
payload: {},
});

try {
await cvat.server.logout();
} catch (error) {
Expand Down
19 changes: 15 additions & 4 deletions cvat-ui/src/actions/models-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export enum ModelsActionTypes {
INFER_MODEL = 'INFER_MODEL',
INFER_MODEL_SUCCESS = 'INFER_MODEL_SUCCESS',
INFER_MODEL_FAILED = 'INFER_MODEL_FAILED',
FETCH_META_FAILED = 'FETCH_META_FAILED',
GET_INFERENCE_STATUS = 'GET_INFERENCE_STATUS',
GET_INFERENCE_STATUS_SUCCESS = 'GET_INFERENCE_STATUS_SUCCESS',
GET_INFERENCE_STATUS_FAILED = 'GET_INFERENCE_STATUS_FAILED',
Expand Down Expand Up @@ -329,6 +330,16 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
};
}

function fetchMetaFailed(error: any): AnyAction {
const action = {
type: ModelsActionTypes.FETCH_META_FAILED,
payload: {
error,
},
};

return action;
}

function getInferenceStatusSuccess(
taskID: number,
Expand Down Expand Up @@ -419,7 +430,9 @@ async function timeoutCallback(

dispatch(getInferenceStatusSuccess(taskID, activeInference));
} catch (error) {
dispatch(getInferenceStatusFailed(taskID, error));
dispatch(getInferenceStatusFailed(taskID, new Error(
`Server request for the task ${taskID} was failed`
)));
}
}

Expand Down Expand Up @@ -514,9 +527,7 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
});
}
} catch (error) {
tasks.forEach((task: number): void => {
dispatch(getInferenceStatusFailed(task, error));
});
dispatch(fetchMetaFailed(error));
}
};
}
Expand Down
6 changes: 5 additions & 1 deletion cvat-ui/src/components/cvat-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
|| !!tasks.fetching || !!tasks.updating || !!tasks.dumping || !!tasks.loading
|| !!tasks.exporting || !!tasks.deleting || !!tasks.creating || !!formats.fetching
|| !!users.fetching || !!share.fetching || !!models.creating || !!models.starting
|| !!models.fetching || !!models.deleting || !!models.inferenceStatusFetching;
|| !!models.fetching || !!models.deleting || !!models.inferenceStatusFetching
|| !!models.metaFetching;

if (auth.authorized) {
showError('Could not check authorization on the server', auth.authorized);
Expand Down Expand Up @@ -156,6 +157,9 @@ export default class CVATApplication extends React.PureComponent<CVATAppProps> {
if (models.deleting) {
showError('Could not delete model from the server', models.deleting);
}
if (models.metaFetching) {
showError('Could not fetch models meta information from the server', models.metaFetching);
}
if (models.inferenceStatusFetching) {
showError('Could not fetch inference status from the server', models.inferenceStatusFetching);
}
Expand Down
9 changes: 8 additions & 1 deletion cvat-ui/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const core = getCore();

interface HeaderContainerProps {
onLogout: () => void;
logoutFetching: boolean;
installedAnalytics: boolean;
installedAutoAnnotation: boolean;
installedTFAnnotation: boolean;
Expand Down Expand Up @@ -81,7 +82,13 @@ function HeaderContainer(props: Props) {
</span>
</span>
}>
<Menu.Item onClick={props.onLogout}>Logout</Menu.Item>
<Menu.Item
onClick={props.onLogout}
disabled={props.logoutFetching}
className='cvat-header-button'
>
{props.logoutFetching && <Icon type='loading'/>} Logout
</Menu.Item>
</Menu.SubMenu>
</Menu>
</div>
Expand Down
9 changes: 8 additions & 1 deletion cvat-ui/src/components/login-page/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface LoginData {
}

type LoginFormProps = {
fetching: boolean;
onSubmit(loginData: LoginData): void;
} & FormComponentProps;

Expand Down Expand Up @@ -80,7 +81,13 @@ class LoginFormComponent extends React.PureComponent<LoginFormProps> {
{this.renderPasswordField()}

<Form.Item>
<Button type='primary' htmlType='submit' className='login-form-button'>
<Button
type='primary'
loading={this.props.fetching}
disabled={this.props.fetching}
htmlType='submit'
className='login-form-button'
>
Sign in
</Button>
</Form.Item>
Expand Down
3 changes: 2 additions & 1 deletion cvat-ui/src/components/login-page/login-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import LoginForm, { LoginData } from './login-form';

interface LoginPageComponentProps {
fetching: boolean;
onLogin: (username: string, password: string) => void;
}

Expand All @@ -29,7 +30,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
<Row type='flex' justify='center' align='middle'>
<Col {...sizes}>
<Title level={2}> Login </Title>
<LoginForm onSubmit={(loginData: LoginData) => {
<LoginForm fetching={props.fetching} onSubmit={(loginData: LoginData) => {
props.onLogin(loginData.username, loginData.password);
}}/>
<Row type='flex' justify='start' align='top'>
Expand Down
9 changes: 8 additions & 1 deletion cvat-ui/src/components/register-page/register-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface RegisterData {
import patterns from '../../utils/validation-patterns';

type RegisterFormProps = {
fetching: boolean;
onSubmit(registerData: RegisterData): void;
} & FormComponentProps;

Expand Down Expand Up @@ -212,7 +213,13 @@ class RegisterFormComponent extends React.PureComponent<RegisterFormProps> {
{this.renderPasswordConfirmationField()}

<Form.Item>
<Button type='primary' htmlType='submit' className='register-form-button'>
<Button
type='primary'
htmlType='submit'
className='register-form-button'
loading={this.props.fetching}
disabled={this.props.fetching}
>
Submit
</Button>
</Form.Item>
Expand Down
4 changes: 2 additions & 2 deletions cvat-ui/src/components/register-page/register-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import Text from 'antd/lib/typography/Text';
import {
Col,
Row,
Modal,
} from 'antd';

import RegisterForm, { RegisterData } from '../../components/register-page/register-form';

interface RegisterPageComponentProps {
fetching: boolean;
onRegister: (username: string, firstName: string,
lastName: string, email: string,
password1: string, password2: string) => void;
Expand All @@ -32,7 +32,7 @@ function RegisterPageComponent(props: RegisterPageComponentProps & RouteComponen
<Row type='flex' justify='center' align='middle'>
<Col {...sizes}>
<Title level={2}> Create an account </Title>
<RegisterForm onSubmit={(registerData: RegisterData) => {
<RegisterForm fetching={props.fetching} onSubmit={(registerData: RegisterData) => {
props.onRegister(
registerData.username,
registerData.firstName,
Expand Down
3 changes: 3 additions & 0 deletions cvat-ui/src/containers/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import HeaderComponent from '../../components/header/header';

interface StateToProps {
logoutFetching: boolean;
installedAnalytics: boolean;
installedAutoAnnotation: boolean;
installedTFSegmentation: boolean;
Expand All @@ -25,6 +26,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
const { auth } = state;
const { plugins } = state.plugins;
return {
logoutFetching: state.auth.fetching,
installedAnalytics: plugins[SupportedPlugins.ANALYTICS],
installedAutoAnnotation: plugins[SupportedPlugins.AUTO_ANNOTATION],
installedTFSegmentation: plugins[SupportedPlugins.TF_SEGMENTATION],
Expand All @@ -42,6 +44,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
function HeaderContainer(props: StateToProps & DispatchToProps) {
return (
<HeaderComponent
logoutFetching={props.logoutFetching}
installedAnalytics={props.installedAnalytics}
installedTFAnnotation={props.installedTFAnnotation}
installedTFSegmentation={props.installedTFSegmentation}
Expand Down
14 changes: 10 additions & 4 deletions cvat-ui/src/containers/login-page/login-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import React from 'react';
import { connect } from 'react-redux';
import { loginAsync } from '../../actions/auth-actions';
import LoginPageComponent from '../../components/login-page/login-page';
import { CombinedState } from '../../reducers/interfaces';

interface StateToProps {}
interface StateToProps {
fetching: boolean;
}

interface DispatchToProps {
login(username: string, password: string): void;
}

function mapStateToProps(): StateToProps {
return {};
function mapStateToProps(state: CombinedState): StateToProps {
return {
fetching: state.auth.fetching,
};
}

function mapDispatchToProps(dispatch: any): DispatchToProps {
Expand All @@ -19,9 +24,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
};
}

function LoginPageContainer(props: DispatchToProps) {
function LoginPageContainer(props: DispatchToProps & StateToProps) {
return (
<LoginPageComponent
fetching={props.fetching}
onLogin={props.login}
/>
);
Expand Down
12 changes: 9 additions & 3 deletions cvat-ui/src/containers/register-page/register-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ import React from 'react';
import { connect } from 'react-redux';
import { registerAsync } from '../../actions/auth-actions';
import RegisterPageComponent from '../../components/register-page/register-page';
import { CombinedState } from '../../reducers/interfaces';

interface StateToProps {}
interface StateToProps {
fetching: boolean;
}

interface DispatchToProps {
register: (username: string, firstName: string,
lastName: string, email: string,
password1: string, password2: string) => void;
}

function mapStateToProps(): StateToProps {
return {};
function mapStateToProps(state: CombinedState): StateToProps {
return {
fetching: state.auth.fetching,
};
}

function mapDispatchToProps(dispatch: any): DispatchToProps {
Expand All @@ -24,6 +29,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
function RegisterPageContainer(props: StateToProps & DispatchToProps) {
return (
<RegisterPageComponent
fetching={props.fetching}
onRegister={props.register}
/>
);
Expand Down
9 changes: 6 additions & 3 deletions cvat-ui/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import _cvat from '../../cvat-core/src/api';

const cvat: any = _cvat;

const protocol = process.env.REACT_APP_API_PROTOCOL;
const host = process.env.REACT_APP_API_HOST;
const port = process.env.REACT_APP_API_PORT;
const protocol = typeof (process.env.REACT_APP_API_PROTOCOL) === 'undefined'
? 'http' : process.env.REACT_APP_API_PROTOCOL;
const host = typeof (process.env.REACT_APP_API_HOST) === 'undefined'
? 'localhost' : process.env.REACT_APP_API_HOST;
const port = typeof (process.env.REACT_APP_API_PORT) === 'undefined'
? '7000' : process.env.REACT_APP_API_PORT;

cvat.config.backendAPI = `${protocol}://${host}:${port}/api/v1`;

Expand Down
Loading

0 comments on commit 59993a2

Please sign in to comment.