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

Configurable REST for UI, minor improvements #880

Merged
merged 11 commits into from
Nov 29, 2019
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
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