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

Fixed export formats for empty project #5899

Merged
merged 9 commits into from
Mar 22, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Cloud storage content listing when the manifest name contains special characters
(<https://github.com/opencv/cvat/pull/5873>)
- Width and height in CVAT dataset format mask annotations (<https://github.com/opencv/cvat/pull/5905>)
- Empty list of export formats for a project without tasks (<https://github.com/opencv/cvat/pull/5899>)

### Security
- TDB
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.50.1",
"version": "1.50.2",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
47 changes: 28 additions & 19 deletions cvat-ui/src/components/export-dataset/export-dataset-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -18,7 +18,10 @@ import Space from 'antd/lib/space';
import TargetStorageField from 'components/storage/target-storage-field';
import { CombinedState, StorageLocation } from 'reducers';
import { exportActions, exportDatasetAsync } from 'actions/export-actions';
import { getCore, Storage, StorageData } from 'cvat-core-wrapper';
import {
Dumper,
getCore, Job, Project, Storage, StorageData, Task,
} from 'cvat-core-wrapper';

const core = getCore();

Expand Down Expand Up @@ -56,15 +59,15 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
location: StorageLocation.LOCAL,
});
const [defaultStorageLocation, setDefaultStorageLocation] = useState(StorageLocation.LOCAL);
const [defaultStorageCloudId, setDefaultStorageCloudId] = useState<number | null>(null);
const [defaultStorageCloudId, setDefaultStorageCloudId] = useState<number>();
bsekachev marked this conversation as resolved.
Show resolved Hide resolved
const [helpMessage, setHelpMessage] = useState('');
const dispatch = useDispatch();

useEffect(() => {
if (instance instanceof core.classes.Project) {
if (instance instanceof Project) {
setInstanceType(`project #${instance.id}`);
} else if (instance instanceof core.classes.Task || instance instanceof core.classes.Job) {
if (instance instanceof core.classes.Task) {
} else if (instance instanceof Task || instance instanceof Job) {
if (instance instanceof Task) {
setInstanceType(`task #${instance.id}`);
} else {
setInstanceType(`job #${instance.id}`);
Expand All @@ -79,16 +82,16 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {

useEffect(() => {
if (instance) {
if (instance instanceof core.classes.Project || instance instanceof core.classes.Task) {
if (instance instanceof Project || instance instanceof Task) {
setDefaultStorageLocation(instance.targetStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(instance.targetStorage?.cloudStorageId || null);
setDefaultStorageCloudId(instance.targetStorage?.cloudStorageId);
} else {
core.tasks.get({ id: instance.taskId })
.then((response: any) => {
if (response.length) {
const [taskInstance] = response;
setDefaultStorageLocation(taskInstance.targetStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(taskInstance.targetStorage?.cloudStorageId || null);
setDefaultStorageCloudId(taskInstance.targetStorage?.cloudStorageId);
}
})
.catch((error: Error) => {
Expand All @@ -104,7 +107,6 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
}, [instance]);

useEffect(() => {
// eslint-disable-next-line prefer-template
setHelpMessage(`Export to ${(defaultStorageLocation) ? defaultStorageLocation.split('_')[0] : 'local'} ` +
`storage ${(defaultStorageCloudId) ? `№${defaultStorageCloudId}` : ''}`);
}, [defaultStorageLocation, defaultStorageCloudId]);
Expand All @@ -129,7 +131,7 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
location: defaultStorageLocation,
cloudStorageId: defaultStorageCloudId,
}) : new Storage(targetStorage),
values.customName ? `${values.customName}.zip` : null,
values.customName ? `${values.customName}.zip` : undefined,
),
);
closeModal();
Expand Down Expand Up @@ -168,10 +170,13 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
>
<Select virtual={false} placeholder='Select dataset format' className='cvat-modal-export-select'>
{dumpers
.sort((a: any, b: any) => a.name.localeCompare(b.name))
.filter((dumper: any): boolean => dumper.dimension === instance?.dimension)
.sort((a: Dumper, b: Dumper) => a.name.localeCompare(b.name))
.filter(
(dumper: Dumper): boolean => dumper.dimension === instance?.dimension ||
(instance instanceof Project && instance.dimension === null),
)
.map(
(dumper: any): JSX.Element => {
(dumper: Dumper): JSX.Element => {
const pending = (instance && current ? current : [])
.includes(dumper.name);
const disabled = !dumper.enabled || pending;
Expand All @@ -192,7 +197,11 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
</Select>
</Form.Item>
<Space>
<Form.Item name='saveImages' className='cvat-modal-export-switch-use-default-storage'>
<Form.Item
className='cvat-modal-export-switch-use-default-storage'
name='saveImages'
valuePropName='checked'
>
<Switch className='cvat-modal-export-save-images' />
</Form.Item>
<Text strong>Save images</Text>
Expand All @@ -206,7 +215,7 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
/>
</Form.Item>
<TargetStorageField
instanceId={instance?.id}
instanceId={instance ? instance.id : null}
switchDescription='Use default settings'
switchHelpMessage={helpMessage}
useDefaultStorage={useDefaultTargetStorage}
Expand All @@ -224,9 +233,9 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {
}

interface StateToProps {
dumpers: any;
instance: any;
current: any;
dumpers: Dumper[];
instance: Project | Task | Job | null;
current: string[];
}

function mapStateToProps(state: CombinedState): StateToProps {
Expand Down
1 change: 1 addition & 0 deletions cvat-ui/src/components/import-dataset/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
}
}

.cvat-switch-use-default-storage,
.cvat-modal-import-switch-use-default-storage,
.cvat-modal-import-switch-conv-mask-to-poly {
display: table-cell;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function StorageWithSwitchField(props: Props): JSX.Element {
<Form.Item
name={switchName}
valuePropName='checked'
className='cvat-settings-switch'
className='cvat-settings-switch cvat-switch-use-default-storage'
>
<Switch
onChange={(value: boolean) => {
Expand Down
2 changes: 2 additions & 0 deletions cvat-ui/src/cvat-core-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Issue from 'cvat-core/src/issue';
import Comment from 'cvat-core/src/comment';
import User from 'cvat-core/src/user';
import Organization from 'cvat-core/src/organization';
import { Dumper } from 'cvat-core/src/annotation-formats';

const cvat: any = _cvat;

Expand Down Expand Up @@ -55,6 +56,7 @@ export {
ModelProviders,
ModelReturnType,
DimensionType,
Dumper,
};

export type {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

/// <reference types="cypress" />

const issueId = '5381';
const project = {
name: `Issue ${issueId}`,
label: 'Tree',
attrName: 'Kind',
attrVaue: 'Oak',
};

context('List of export formats for a project without tasks is not empty', () => {
before(() => {
cy.visit('auth/login');
cy.login();
cy.goToProjectsList();
cy.createProjects(project.name, project.label, project.attrName, project.attrVaue);
cy.goToProjectsList();
});

describe(`Testing issue "${issueId}"`, () => {
it('Export formats list is not empty for empty project', () => {
cy.projectActions(project.name);
cy.get('.cvat-project-actions-menu').contains('Export dataset').click();
cy.get('.cvat-modal-export-project').should('be.visible').find('.cvat-modal-export-select').click();
cy.get('.cvat-modal-export-option-item').should('have.length.above', 0);
});
});
});