Skip to content

Commit

Permalink
Editable git
Browse files Browse the repository at this point in the history
  • Loading branch information
PMazarovich committed Dec 6, 2021
1 parent 1ea23e3 commit 3bd8d16
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 21 deletions.
65 changes: 48 additions & 17 deletions cvat-ui/src/components/task-page/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,21 @@ import notification from 'antd/lib/notification';
import Text from 'antd/lib/typography/Text';
import Title from 'antd/lib/typography/Title';
import moment from 'moment';

import Descriptions from 'antd/lib/descriptions';
import Paragraph from 'antd/lib/typography/Paragraph';
import Select from 'antd/lib/select';
import Checkbox from 'antd/lib/checkbox';
import getCore from 'cvat-core-wrapper';
import { getReposData, syncRepos } from 'utils/git-utils';
import { getReposData, syncRepos, changeRepo } from 'utils/git-utils';
import { ActiveInference } from 'reducers/interfaces';
import AutomaticAnnotationProgress from 'components/tasks-page/automatic-annotation-progress';
import Descriptions from 'antd/lib/descriptions';
import UserSelector, { User } from './user-selector';
import BugTrackerEditor from './bug-tracker-editor';
import LabelsEditorComponent from '../labels-editor/labels-editor';
import ProjectSubsetField from '../create-task-page/project-subset-field';

const { Option } = Select;

const core = getCore();

interface Props {
Expand All @@ -32,6 +36,8 @@ interface Props {
projectSubsets: string[];
cancelAutoAnnotation(): void;
onTaskUpdate: (taskInstance: any) => void;
dumpers: any[];
user: any;
}

interface State {
Expand All @@ -40,6 +46,7 @@ interface State {
repository: string;
repositoryStatus: string;
format: string;
lfs: boolean;
}

export default class DetailsComponent extends React.PureComponent<Props, State> {
Expand All @@ -63,6 +70,8 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
repository: '',
format: '',
repositoryStatus: '',
changedRepo: '',
lfs: '',
};
}

Expand Down Expand Up @@ -102,7 +111,9 @@ export default class DetailsComponent extends React.PureComponent<Props, State>

this.setState({
repository: data.url,
changedRepo: data.url,
format: data.format,
lfs: !!data.lfs,
});
}
})
Expand Down Expand Up @@ -130,6 +141,26 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
this.mounted = false;
}

private onChangeRepoValue = (value: string): void => {
const { taskInstance } = this.props;
this.setState({ changedRepo: value });
changeRepo(taskInstance.id, 'url', value).then(() => {
setTimeout(() => window.location.reload());
});
};

private onChangeLFSValue = (value): void => {
const { taskInstance } = this.props;
this.setState({ lfs: value.target.checked });
changeRepo(taskInstance.id, 'lfs', value.target.checked);
};

private onChangeFormatValue = (value: string): void => {
const { taskInstance } = this.props;
this.setState({ format: value });
changeRepo(taskInstance.id, 'format', value);
};

private renderTaskName(): JSX.Element {
const { name } = this.state;
const { taskInstance, onTaskUpdate } = this.props;
Expand Down Expand Up @@ -205,28 +236,28 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
}

private renderDatasetRepository(): JSX.Element | boolean {
const { taskInstance } = this.props;
const { repository, repositoryStatus, format } = this.state;

const { taskInstance, dumpers } = this.props;
const {
repository, repositoryStatus, format, changedRepo, lfs
} = this.state;
return (
!!repository && (
<Row>
<Col className='cvat-dataset-repository-url'>
<Text strong className='cvat-text-color'>
Dataset Repository
</Text>
<Paragraph editable={{ onChange: this.onChangeRepoValue }}>{changedRepo}</Paragraph>
<Text strong className='cvat-text-color'>Using format</Text>
<Select onChange={this.onChangeFormatValue} className='cvat-repository-format-select' initialValue={format} defaultValue={format}>
{
dumpers.map((dumper: any) => <Option value={dumper.name}>{dumper.name}</Option>)
}
</Select>
<Checkbox onChange={this.onChangeLFSValue} checked={lfs}>
Large file support
</Checkbox>
<br />
<a href={repository} rel='noopener noreferrer' target='_blank'>
{repository}
</a>
<br />
<p>
Using format
{' '}
<Text strong>
{format}
</Text>
</p>
{repositoryStatus === 'sync' && (
<Tag color='blue'>
<CheckCircleOutlined />
Expand Down
4 changes: 4 additions & 0 deletions cvat-ui/src/components/task-page/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
}
}

.cvat-repository-format-select {
width: 100%;
}

.cvat-task-job-list {
width: 100%;
height: auto;
Expand Down
8 changes: 7 additions & 1 deletion cvat-ui/src/containers/task-page/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ interface StateToProps {
activeInference: ActiveInference | null;
installedGit: boolean;
projectSubsets: string[];
dumpers: [];
user: any;
}

interface DispatchToProps {
Expand All @@ -30,6 +32,8 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const [taskProject] = state.projects.current.filter((project) => project.id === own.task.instance.projectId);

return {
dumpers: state.formats.annotationFormats.dumpers,
user: state.auth.user,
installedGit: list.GIT_INTEGRATION,
activeInference: state.models.inferences[own.task.instance.id] || null,
projectSubsets: taskProject ?
Expand All @@ -53,11 +57,13 @@ function mapDispatchToProps(dispatch: any, own: OwnProps): DispatchToProps {

function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps): JSX.Element {
const {
task, installedGit, activeInference, projectSubsets, cancelAutoAnnotation, onTaskUpdate,
task, installedGit, activeInference, projectSubsets, cancelAutoAnnotation, onTaskUpdate, dumpers, user,
} = props;

return (
<DetailsComponent
dumpers={dumpers}
user={user}
previewImage={task.preview}
taskInstance={task.instance}
installedGit={installedGit}
Expand Down
18 changes: 18 additions & 0 deletions cvat-ui/src/utils/git-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ interface ReposData {
error: string | null;
};
format: string
lfs: boolean
}

function waitForClone(cloneResponse: any): Promise<void> {
Expand Down Expand Up @@ -157,6 +158,7 @@ export async function getReposData(tid: number): Promise<ReposData | null> {
error: response.status.error,
},
format: response.format,
lfs: response.lfs,
};
}

Expand Down Expand Up @@ -193,3 +195,19 @@ export function syncRepos(tid: number): Promise<void> {
});
});
}

export async function changeRepo(taskId: number, type: string, value: any): Promise<void> {
return new Promise((resolve, reject): void => {
core.server
.request(`${baseURL}/git/repository/${taskId}`, {
method: 'PATCH',
data: JSON.stringify({
type,
value,
}),
})
.catch((error: any): void => {
reject(error);
});
});
}
9 changes: 7 additions & 2 deletions cvat/apps/dataset_repo/dataset_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,12 @@ def init_repos(self, wo_remote = False):
if self._ssh_url() != self._rep.git.remote('get-url', '--all', 'origin'):
slogger.task[self._tid].info("Local repository URL is obsolete.")
# We need reinitialize repository if it's false
raise git.exc.GitError("Actual and saved repository URLs aren't match")
slogger.task[self._tid].info("Local repository initialization..")
shutil.rmtree(self._cwd, True)
self._clone()
except git.exc.GitError:
if wo_remote:
raise Exception('Local repository is failed')
slogger.task[self._tid].info("Local repository is failed")
slogger.task[self._tid].info("Local repository initialization..")
shutil.rmtree(self._cwd, True)
self._clone()
Expand Down Expand Up @@ -418,6 +420,7 @@ def get(tid, user):
response["url"] = {"value": None}
response["status"] = {"value": None, "error": None}
response["format"] = {"format": None}
response["lfs"] = {"lfs": None}
db_task = Task.objects.get(pk = tid)
if GitData.objects.filter(pk = db_task).exists():
db_git = GitData.objects.select_for_update().get(pk = db_task)
Expand All @@ -430,13 +433,15 @@ def get(tid, user):
db_git.status = GitStatusChoice.SYNCING
response['status']['value'] = str(db_git.status)
response['format'] = str(db_git.format)
response["lfs"] = db_git.lfs
else:
try:
_git = Git(db_git, db_task, user)
_git.init_repos(True)
db_git.status = _git.remote_status(db_task.updated_date)
response['status']['value'] = str(db_git.status)
response['format'] = str(db_git.format)
response["lfs"] = db_git.lfs
except git.exc.GitCommandError as ex:
_have_no_access_exception(ex)
db_git.save()
Expand Down
1 change: 1 addition & 0 deletions cvat/apps/dataset_repo/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
path('push/<int:tid>', views.push_repository),
path('check/<str:rq_id>', views.check_process),
path('meta/get', views.get_meta_info),
path('<int:tid>', views.update_git_repo)
]
32 changes: 31 additions & 1 deletion cvat/apps/dataset_repo/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Copyright (C) 2018-2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
import http.client

from django.http import HttpResponseBadRequest, JsonResponse
from django.http import HttpResponseBadRequest, JsonResponse, HttpResponse
from rules.contrib.views import permission_required, objectgetter

from cvat.apps.authentication.decorators import login_required
Expand Down Expand Up @@ -88,6 +89,35 @@ def get_repository(request, tid):
pass
return HttpResponseBadRequest(str(ex))

@login_required
@permission_required(perm=['engine.task.access'],
fn=objectgetter(models.Task, 'tid'), raise_exception=True)
def update_git_repo(request, tid):
try:
body = json.loads(request.body.decode('utf-8'))
req_type = body["type"]
value = body["value"]
git_data_obj = GitData.objects.filter(task_id=tid)[0]
if req_type == "url":
git_data_obj.url = value
git_data_obj.save(update_fields=["url"])
elif req_type == "lfs":
git_data_obj.lfs = bool(value)
git_data_obj.save(update_fields=["lfs"])
elif req_type == "format":
git_data_obj.format = value
git_data_obj.save(update_fields=["format"])
slogger.task[tid].info("get repository request")
return HttpResponse(
status=http.HTTPStatus.OK,
)
except Exception as ex:
try:
slogger.task[tid].error("error occurred during changing repository request", exc_info=True)
except Exception:
pass
return HttpResponseBadRequest(str(ex))


@login_required
def get_meta_info(request):
Expand Down

0 comments on commit 3bd8d16

Please sign in to comment.