Skip to content

Commit

Permalink
feature/164_respect_directory_structure_or_at_least_provide_warning (#…
Browse files Browse the repository at this point in the history
…195)

* initial refactor

* empty labels validation

* non unique labels validation
  • Loading branch information
SkalskiP authored Sep 5, 2021
1 parent 6c19192 commit 2852857
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 92 deletions.
4 changes: 4 additions & 0 deletions src/data/enums/Notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Notification {
EMPTY_LABEL_NAME_ERROR = 0,
NON_UNIQUE_LABEL_NAMES_ERROR = 1
}
3 changes: 2 additions & 1 deletion src/data/enums/NotificationType.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum NotificationType {
ERROR = 'ERROR',
SUCCESS = 'SUCCESS',
MESSAGE = 'MESSAGE'
MESSAGE = 'MESSAGE',
WARNING = 'WARNING'
}
34 changes: 17 additions & 17 deletions src/data/info/EditorFeatureData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@ export interface IEditorFeature {

export const EditorFeatureData: IEditorFeature[] = [
{
displayText: "Open source and free to use under GPLv3 license",
imageSrc: "ico/open-source.png",
imageAlt: "open-source",
displayText: 'Open source and free to use under GPLv3 license',
imageSrc: 'ico/open-source.png',
imageAlt: 'open-source',
},
{
displayText: "No advanced installation required, just open up your browser",
imageSrc: "ico/online.png",
imageAlt: "online",
displayText: 'No advanced installation required, just open up your browser',
imageSrc: 'ico/online.png',
imageAlt: 'online',
},
{
displayText: "We don't store your images, because we don't send them anywhere",
imageSrc: "ico/private.png",
imageAlt: "private",
imageSrc: 'ico/private.png',
imageAlt: 'private',
},
{
displayText: "Support multiple label types - rects, lines, points and polygons",
imageSrc: "ico/labels.png",
imageAlt: "labels",
displayText: 'Support multiple label types - rects, lines, points and polygons',
imageSrc: 'ico/labels.png',
imageAlt: 'labels',
},
{
displayText: "Support output file formats like YOLO, VOC XML, VGG JSON, CSV",
imageSrc: "ico/file.png",
imageAlt: "file",
displayText: 'Support output file formats like YOLO, VOC XML, VGG JSON, CSV',
imageSrc: 'ico/file.png',
imageAlt: 'file',
},
{
displayText: "Use AI to make your work more productive",
imageSrc: "ico/robot.png",
imageAlt: "robot",
displayText: 'Use AI to make your work more productive',
imageSrc: 'ico/robot.png',
imageAlt: 'robot',
},
];
21 changes: 21 additions & 0 deletions src/data/info/NotificationsData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {Notification} from '../enums/Notification';

export type NotificationContent = {
header: string;
description: string;
}

export type ExportFormatDataMap = Record<Notification, NotificationContent>;

export const NotificationsDataMap = {
[Notification.EMPTY_LABEL_NAME_ERROR]: {
header: 'Empty label name',
description: "Looks like you didn't assign name to one of your labels. Unfortunately it is mandatory for " +
'every label to have unique name value. Insert correct name or delete empty label and try again.'
},
[Notification.NON_UNIQUE_LABEL_NAMES_ERROR]: {
header: 'Non unique label names',
description: 'Looks like not all your label names are unique. Unique names are necessary to guarantee correct' +
' data export when you complete your work. Make your names unique and try again.'
}
}
4 changes: 2 additions & 2 deletions src/utils/ImageDataUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export class ImageDataUtil {
const missingImages = images.filter((i: ImageData) => !i.loadStatus);
const missingImagesFiles = missingImages.map((i: ImageData) => i.fileData);
FileUtil.loadImages(missingImagesFiles)
.then((images:HTMLImageElement[]) => {
ImageRepository.storeImages(missingImages.map((i: ImageData) => i.id), images);
.then((htmlImageElements:HTMLImageElement[]) => {
ImageRepository.storeImages(missingImages.map((i: ImageData) => i.id), htmlImageElements);
resolve()
})
.catch((error: Error) => reject(error));
Expand Down
22 changes: 16 additions & 6 deletions src/utils/NotificationUtil.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import {INotification} from '../store/notifications/types';
import {v4 as uuidv4} from 'uuid';
import {NotificationType} from '../data/enums/NotificationType';
import {NotificationContent} from "../data/info/NotificationsData";

export class NotificationUtil {
public static createErrorNotification(header: string, description: string): INotification {
public static createErrorNotification(content: NotificationContent): INotification {
return {
id: uuidv4(),
type: NotificationType.ERROR,
header,
description
header: content.header,
description: content.description
}
}

public static createMessageNotification(header: string, description: string): INotification {
public static createMessageNotification(content: NotificationContent): INotification {
return {
id: uuidv4(),
type: NotificationType.MESSAGE,
header,
description
header: content.header,
description: content.description
}
}

public static createWarningNotification(content: NotificationContent): INotification {
return {
id: uuidv4(),
type: NotificationType.WARNING,
header: content.header,
description: content.description
}
}
}
13 changes: 4 additions & 9 deletions src/views/Common/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import './TextInput.scss';

interface IProps {
key: string;
label?: string;
isPassword: boolean;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => any;
Expand All @@ -17,7 +16,6 @@ interface IProps {
const TextInput = (props: IProps) => {

const {
key,
label,
isPassword,
onChange,
Expand All @@ -30,33 +28,30 @@ const TextInput = (props: IProps) => {
} = props;

const getInputType = () => {
return isPassword ? "password" : "text";
return isPassword ? 'password' : 'text';
};

return (
<div className="TextInput">
<div className='TextInput'>
<input
value={!!value ? value : undefined}
type={getInputType()}
id={key}
style={inputStyle}
onChange={onChange ? onChange : undefined}
onFocus={onFocus ? onFocus : undefined}
autoFocus
onKeyUp={onKeyUp}
/>
{!!label && <label
htmlFor={key}
style={labelStyle}
>
{label}
</label>}
<div
className="Bar"
className='Bar'
style={barStyle}
/>
</div>
);
};

export default TextInput;
export default TextInput;
67 changes: 34 additions & 33 deletions src/views/EditorView/TopNavigationBar/TopNavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React from 'react';
import './TopNavigationBar.scss';
import StateBar from "../StateBar/StateBar";
import {PopupWindowType} from "../../../data/enums/PopupWindowType";
import {AppState} from "../../../store";
import {connect} from "react-redux";
import {updateActivePopupType, updateProjectData} from "../../../store/general/actionCreators";
import TextInput from "../../Common/TextInput/TextInput";
import {ImageButton} from "../../Common/ImageButton/ImageButton";
import {Settings} from "../../../settings/Settings";
import {ProjectData} from "../../../store/general/types";
import DropDownMenu from "./DropDownMenu/DropDownMenu";
import StateBar from '../StateBar/StateBar';
import {PopupWindowType} from '../../../data/enums/PopupWindowType';
import {AppState} from '../../../store';
import {connect} from 'react-redux';
import {updateActivePopupType, updateProjectData} from '../../../store/general/actionCreators';
import TextInput from '../../Common/TextInput/TextInput';
import {ImageButton} from '../../Common/ImageButton/ImageButton';
import {Settings} from '../../../settings/Settings';
import {ProjectData} from '../../../store/general/types';
import DropDownMenu from './DropDownMenu/DropDownMenu';

interface IProps {
updateActivePopupType: (activePopupType: PopupWindowType) => any;
updateProjectData: (projectData: ProjectData) => any;
updateActivePopupTypeAction: (activePopupType: PopupWindowType) => any;
updateProjectDataAction: (projectData: ProjectData) => any;
projectData: ProjectData;
}

const TopNavigationBar: React.FC<IProps> = ({updateActivePopupType, updateProjectData, projectData}) => {
const TopNavigationBar: React.FC<IProps> = (props) => {
const onFocus = (event: React.FocusEvent<HTMLInputElement>) => {
event.target.setSelectionRange(0, event.target.value.length);
};
Expand All @@ -27,46 +27,47 @@ const TopNavigationBar: React.FC<IProps> = ({updateActivePopupType, updateProjec
.toLowerCase()
.replace(' ', '-');

updateProjectData({
...projectData,
props.updateProjectDataAction({
...props.projectData,
name: value
})
};

const closePopup = () => props.updateActivePopupTypeAction(PopupWindowType.EXIT_PROJECT)

return (
<div className="TopNavigationBar">
<div className='TopNavigationBar'>
<StateBar/>
<div className="TopNavigationBarWrapper">
<div className="NavigationBarGroupWrapper">
<div className='TopNavigationBarWrapper'>
<div className='NavigationBarGroupWrapper'>
<div
className="Header"
onClick={() => updateActivePopupType(PopupWindowType.EXIT_PROJECT)}
className='Header'
onClick={closePopup}
>
<img
draggable={false}
alt={"make-sense"}
src={"/make-sense-ico-transparent.png"}
alt={'make-sense'}
src={'/make-sense-ico-transparent.png'}
/>
Make Sense
</div>
</div>
<div className="NavigationBarGroupWrapper">
<div className='NavigationBarGroupWrapper'>
<DropDownMenu/>
</div>
<div className="NavigationBarGroupWrapper middle">
<div className="ProjectName">Project Name:</div>
<div className='NavigationBarGroupWrapper middle'>
<div className='ProjectName'>Project Name:</div>
<TextInput
key={"ProjectName"}
isPassword={false}
value={projectData.name}
value={props.projectData.name}
onChange={onChange}
onFocus={onFocus}
/>
</div>
<div className="NavigationBarGroupWrapper">
<div className='NavigationBarGroupWrapper'>
<ImageButton
image={"ico/github-logo.png"}
imageAlt={"github-logo.png"}
image={'ico/github-logo.png'}
imageAlt={'github-logo.png'}
buttonSize={{width: 30, height: 30}}
href={Settings.GITHUB_URL}
/>
Expand All @@ -77,8 +78,8 @@ const TopNavigationBar: React.FC<IProps> = ({updateActivePopupType, updateProjec
};

const mapDispatchToProps = {
updateActivePopupType,
updateProjectData
updateActivePopupTypeAction: updateActivePopupType,
updateProjectDataAction: updateProjectData
};

const mapStateToProps = (state: AppState) => ({
Expand All @@ -88,4 +89,4 @@ const mapStateToProps = (state: AppState) => ({
export default connect(
mapStateToProps,
mapDispatchToProps
)(TopNavigationBar);
)(TopNavigationBar);
6 changes: 4 additions & 2 deletions src/views/MainView/ImagesDropZone/ImagesDropZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {updateActivePopupType, updateProjectData} from '../../../store/general/a
import {AcceptedFileType} from '../../../data/enums/AcceptedFileType';
import {ProjectData} from '../../../store/general/types';
import {ImageDataUtil} from '../../../utils/ImageDataUtil';
import { sortBy } from 'lodash';

interface IProps {
updateActiveImageIndexAction: (activeImageIndex: number) => any;
Expand All @@ -28,13 +29,14 @@ const ImagesDropZone: React.FC<IProps> = (props: PropsWithChildren<IProps>) => {

const startEditor = (projectType: ProjectType) => {
if (acceptedFiles.length > 0) {
const files = sortBy(acceptedFiles, (item: File) => item.name)
props.updateProjectDataAction({
...props.projectData,
type: projectType
});
props.updateActiveImageIndexAction(0);
props.addImageDataAction(acceptedFiles.map((fileData:File) => ImageDataUtil
.createImageDataFromFileData(fileData)));
props.addImageDataAction(files.map((file:File) => ImageDataUtil
.createImageDataFromFileData(file)));
props.updateActivePopupTypeAction(PopupWindowType.INSERT_LABEL_NAMES);
}
};
Expand Down
11 changes: 11 additions & 0 deletions src/views/NotificationsView/NotificationsView.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ $baseZIndex: 2000;
//$errorColor: #ff0033;
$errorColor: #d42245;
$successColor: #009944;
$warningColor: #eed202;

.notification-wrapper {
position: fixed;
Expand Down Expand Up @@ -93,6 +94,16 @@ $successColor: #009944;
background-color: #{$secondaryColor};
}
}

&.warning {
.header {
background-color: #{$warningColor};
color: white;
}
.loader {
background-color: #{$warningColor};
}
}
}

&.in {
Expand Down
1 change: 1 addition & 0 deletions src/views/NotificationsView/NotificationsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const NotificationsView: React.FC<IProps> = (props) => {
'error': notification.type === NotificationType.ERROR,
'success': notification.type === NotificationType.SUCCESS,
'message': notification.type === NotificationType.MESSAGE,
'warning': notification.type === NotificationType.WARNING
})
}

Expand Down
Loading

0 comments on commit 2852857

Please # to comment.