From 2c6b9a882276b8ef0a613910d1322ec5682b54bb Mon Sep 17 00:00:00 2001 From: Armen Rohalov Date: Sat, 28 Jun 2025 14:46:59 +0300 Subject: [PATCH] redesign --- .../AnnotationControls/AnnotationControls.css | 68 ++++++++----------- .../AnnotationControls/AnnotationControls.js | 32 +++++---- .../AnnotationList/AnnotationList.css | 28 ++++++++ .../{ => AnnotationList}/AnnotationList.js | 10 ++- .../AnnotationMain/AnnotationMain.css | 17 ++--- .../AnnotationMain/AnnotationMain.js | 2 +- .../DetectionClassList/DetectionClassList.css | 66 ++++++++++++------ .../DetectionClassList/DetectionClassList.js | 47 +++++++------ src/components/MediaList/MediaList.css | 68 ++++++++++++++++--- src/components/MediaList/MediaList.js | 18 ++--- src/icons/CleanIcon.js | 7 ++ src/icons/DeleteIcon.js | 8 +++ src/icons/NextIcon.js | 8 +++ src/icons/PauseIcon.js | 8 +++ src/icons/PlayIcon.js | 7 ++ src/icons/PreviousIcon.js | 8 +++ src/icons/SaveIcon.js | 7 ++ src/icons/StopIcon.js | 7 ++ src/index.css | 4 ++ 19 files changed, 293 insertions(+), 127 deletions(-) create mode 100644 src/components/AnnotationList/AnnotationList.css rename src/components/{ => AnnotationList}/AnnotationList.js (61%) create mode 100644 src/icons/CleanIcon.js create mode 100644 src/icons/DeleteIcon.js create mode 100644 src/icons/NextIcon.js create mode 100644 src/icons/PauseIcon.js create mode 100644 src/icons/PlayIcon.js create mode 100644 src/icons/PreviousIcon.js create mode 100644 src/icons/SaveIcon.js create mode 100644 src/icons/StopIcon.js diff --git a/src/components/AnnotationControls/AnnotationControls.css b/src/components/AnnotationControls/AnnotationControls.css index d09d26b..8da947c 100644 --- a/src/components/AnnotationControls/AnnotationControls.css +++ b/src/components/AnnotationControls/AnnotationControls.css @@ -1,61 +1,47 @@ +.controls { + margin-top: 4px; +} + .input-group { display: flex; flex-direction: row; - padding: 0 4px; + background: #222531; + padding: 0 20px; + border-radius: 4px; +} + +.time { + color: #fff; } .video-slider { - width: 100%; - margin: 12px 20px; + margin: 12px 26px; +} + +.MuiSlider-root { + color: #fff !important; } .buttons-group { display: flex; - justify-content: center; - position: relative; - z-index: 1; - padding: 10px; - background: #f5f5f5; - border-radius: 4px; - margin-top: 10px; + flex-direction: row; + gap: 10px; + margin-top: 6px; } .control-btn { + width: 40px; + height: 40px; display: flex; + justify-content: center; align-items: center; - gap: 4px; - padding: 10px 20px; - font-size: 16px; - margin: 0 5px; - border: 1px solid #ccc; + background: #222531; + padding: 4px; + border: 0; border-radius: 4px; cursor: pointer; } -.play-btn { - background: #8aff8a; -} - -.pause-btn { - background: #ff8a8a; -} - -.arrow-btn { - background: #e0e0e0; -} - -.stop-btn { - background: #e8a1a5; -} - -.save-btn { - background: #8ad4ff; -} - -.delete-btn { - background: #ffb38a; -} - -.clean-btn{ - background: #ff8a8a; +.control-btn:hover { + background: #535b77; } \ No newline at end of file diff --git a/src/components/AnnotationControls/AnnotationControls.js b/src/components/AnnotationControls/AnnotationControls.js index 40f5b46..4e5363c 100644 --- a/src/components/AnnotationControls/AnnotationControls.js +++ b/src/components/AnnotationControls/AnnotationControls.js @@ -1,7 +1,13 @@ import { Slider } from '@mui/material'; -import { FaStop } from "react-icons/fa"; -import { MdCleaningServices } from "react-icons/md"; import './AnnotationControls.css'; +import PreviousIcon from '../../icons/PreviousIcon'; +import PlayIcon from '../../icons/PlayIcon'; +import PauseIcon from '../../icons/PauseIcon'; +import NextIcon from '../../icons/NextIcon'; +import StopIcon from '../../icons/StopIcon'; +import SaveIcon from '../../icons/SaveIcon'; +import CleanIcon from '../../icons/CleanIcon'; +import DeleteIcon from '../../icons/DeleteIcon'; function AnnotationControls({ videoRef, @@ -32,7 +38,7 @@ function AnnotationControls({ return (
-

{formatDuration(currentTime)}

+

{formatDuration(currentTime)}

{videoRef.current !== null - ?

{formatDuration(videoRef.current.duration - currentTime)}

- :

{formatDuration(0)}

+ ?

{formatDuration(videoRef.current.duration - currentTime)}

+ :

{formatDuration(0)}

}
@@ -55,46 +61,48 @@ function AnnotationControls({ onClick={onFrameBackward} title="Previous Frame" > - ⏮️ +
diff --git a/src/components/AnnotationList/AnnotationList.css b/src/components/AnnotationList/AnnotationList.css new file mode 100644 index 0000000..c5091be --- /dev/null +++ b/src/components/AnnotationList/AnnotationList.css @@ -0,0 +1,28 @@ +.annotation-section { + background: #222531; + border-radius: 4px; + padding: 8px; + height: 80%; +} + +.annotation-list { + display: flex; + flex-direction: column; + gap: 4px; + list-style-type: none; + padding: 0; +} + +.annotation-list-item { + box-sizing: border-box; + display: flex; + align-items: center; + height: 22px; + background: #858CA2; + padding: 4px; + color: #fff; + font-size: 14px; + line-height: 1; + font-weight: 600; + border-radius: 4px ; +} \ No newline at end of file diff --git a/src/components/AnnotationList.js b/src/components/AnnotationList/AnnotationList.js similarity index 61% rename from src/components/AnnotationList.js rename to src/components/AnnotationList/AnnotationList.js index 241964f..0430627 100644 --- a/src/components/AnnotationList.js +++ b/src/components/AnnotationList/AnnotationList.js @@ -1,14 +1,12 @@ -// src/components/AnnotationList.js -// No changes -import React from 'react'; +import './AnnotationList.css' function AnnotationList({ annotations, onAnnotationClick }) { return ( -
+

Annotations

-
    +
      {annotations.map((annotation, index) => ( -
    • onAnnotationClick(annotation.time)}> +
    • onAnnotationClick(annotation.time)}> Frame {index + 1} - {annotation.annotations.length} objects
    • ))} diff --git a/src/components/AnnotationMain/AnnotationMain.css b/src/components/AnnotationMain/AnnotationMain.css index 8c28be9..87005d5 100644 --- a/src/components/AnnotationMain/AnnotationMain.css +++ b/src/components/AnnotationMain/AnnotationMain.css @@ -1,33 +1,32 @@ .content-wrapper { display: flex; + gap: 4px; height: 100vh; overflow: hidden; + background: #0D1421; + padding: 4px; } .side-menu { display: flex; flex-direction: column; - width: 15%; - height: 100%; -} - -.left-menu{ - border-right: 1px solid #ccc; + width: 228px; + height: 100vh; } .right-menu{ overflow-y: auto; - border-left: 1px solid #ccc; } .player-wrapper { - width: 70%; + width: calc(100% - 464px); height: 100%; display: flex; flex-direction: column; } .error-message { + position: absolute; background: #ffdddd; color: #d8000c; padding: 6px; @@ -51,4 +50,6 @@ justify-content: center; align-items: center; overflow: hidden; + border-radius: 8px; + border: 1px solid #222531; } \ No newline at end of file diff --git a/src/components/AnnotationMain/AnnotationMain.js b/src/components/AnnotationMain/AnnotationMain.js index fa310e4..df9b849 100644 --- a/src/components/AnnotationMain/AnnotationMain.js +++ b/src/components/AnnotationMain/AnnotationMain.js @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import VideoPlayer from '../VideoPlayer/VideoPlayer'; -import AnnotationList from '../AnnotationList'; +import AnnotationList from '../AnnotationList/AnnotationList'; import MediaList from '../MediaList/MediaList'; import DetectionClassList from '../DetectionClassList/DetectionClassList'; import CanvasEditor from '../CanvasEditor/CanvasEditor'; diff --git a/src/components/DetectionClassList/DetectionClassList.css b/src/components/DetectionClassList/DetectionClassList.css index 6d0320c..0b642bb 100644 --- a/src/components/DetectionClassList/DetectionClassList.css +++ b/src/components/DetectionClassList/DetectionClassList.css @@ -1,56 +1,80 @@ +.detection { + margin-top: 4px; +} + .class-list { - flex-grow: 1; + display: flex; + flex-direction: column; + background: #858CA2; + border-radius: 4px; + padding: 4px; + height: 48vh; +} + +.menu-title { + margin-bottom: 6px; } .class-list-group { - list-style-type: none; + display: flex; + flex-direction: column; + gap: 3px; padding: 0; margin: 0; - height: 40vh; - min-height: 300px; overflow: auto; + scrollbar-width: none; + list-style-type: none; +} + +.class-list-group::-webkit-scrollbar { + display: none; } .class-list-item { display: flex; align-items: center; - height: 12px; + height: 30px; cursor: pointer; padding: 8px; font-size: 14px; font-weight: 500; - margin-bottom: 2px; border-radius: 4px; } .detection-type-group { + background: #222531; display: flex; flex-direction: row; - justify-content: center; - gap: 5%; - padding: 10px 12px; -} - -.detection-type-btn { - width: 25%; - display: flex; - justify-content: center; - align-items: center; - font-size: 18px; - padding: 4px 10px; + justify-content: space-between; + padding: 16px 9px; + margin-top: 4px; border-radius: 4px; } +.detection-type-btn { + width: 66px; + height: 40px; + display: flex; + justify-content: center; + align-items: center; + background: #3862fb41; + color: #3861FB; + font-size: 30px; + padding: 5px 17px; + border-radius: 4px; + border: 0; +} + .detection-type-btn:hover { - background: #d6eed5; + background: #0e2060; } .active-type { color: white; - background: black; + background: #3861FB; } .active-type:hover { cursor: default; - background: black; + background: #3861FB; } \ No newline at end of file diff --git a/src/components/DetectionClassList/DetectionClassList.js b/src/components/DetectionClassList/DetectionClassList.js index c45cabd..a8d68a0 100644 --- a/src/components/DetectionClassList/DetectionClassList.js +++ b/src/components/DetectionClassList/DetectionClassList.js @@ -91,29 +91,32 @@ function DetectionClassList({ onClassSelect, detectionType, setDetectionType }) } return ( -
      -

      Classes

      -
        - {detectionClasses.map((cls) => { - const backgroundColor = calculateColor(cls.Id); - const darkBg = calculateColor(cls.Id, '0.8'); - const isSelected = selectedClass && selectedClass.Id === cls.Id; +
        - return ( -
      • handleClassClick(cls)} - > - {cls.Name} -
      • - ); - })} -
      +
      +

      Classes

      +
        + {detectionClasses.map((cls) => { + const backgroundColor = calculateColor(cls.Id); + const darkBg = calculateColor(cls.Id, '0.8'); + const isSelected = selectedClass && selectedClass.Id === cls.Id; + + return ( +
      • handleClassClick(cls)} + > + {cls.Name} +
      • + ); + })} +
      +
      - +
      +

      Files

      + + +
        {filteredFiles.map((file) => ( @@ -42,7 +44,7 @@ function MediaList({ files, selectedFile, onFileSelect, onDropNewFiles }) { className='file-list-item' key={file.name} style={{ - backgroundColor: selectedFile === file ? '#f0f0f0' : 'transparent' + backgroundColor: selectedFile === file ? '#474A52' : '#858CA2' }} onClick={() => onFileSelect(file)} > diff --git a/src/icons/CleanIcon.js b/src/icons/CleanIcon.js new file mode 100644 index 0000000..05e34ec --- /dev/null +++ b/src/icons/CleanIcon.js @@ -0,0 +1,7 @@ +const CleanIcon = ({ width = 32, height = 32 }) => ( + + + +); + +export default CleanIcon; \ No newline at end of file diff --git a/src/icons/DeleteIcon.js b/src/icons/DeleteIcon.js new file mode 100644 index 0000000..a78d67a --- /dev/null +++ b/src/icons/DeleteIcon.js @@ -0,0 +1,8 @@ +const DeleteIcon = ({ width = 32, height = 32 }) => ( + + + + +); + +export default DeleteIcon; \ No newline at end of file diff --git a/src/icons/NextIcon.js b/src/icons/NextIcon.js new file mode 100644 index 0000000..4c1aa02 --- /dev/null +++ b/src/icons/NextIcon.js @@ -0,0 +1,8 @@ +const NextIcon = ({ width = 32, height = 32 }) => ( + + + + +); + +export default NextIcon; \ No newline at end of file diff --git a/src/icons/PauseIcon.js b/src/icons/PauseIcon.js new file mode 100644 index 0000000..7d8bd7d --- /dev/null +++ b/src/icons/PauseIcon.js @@ -0,0 +1,8 @@ +const PauseIcon = ({ width = 32, height = 32 }) => ( + + + + +); + +export default PauseIcon; \ No newline at end of file diff --git a/src/icons/PlayIcon.js b/src/icons/PlayIcon.js new file mode 100644 index 0000000..cf9e9b5 --- /dev/null +++ b/src/icons/PlayIcon.js @@ -0,0 +1,7 @@ +const PlayIcon = ({ width = 32, height = 32 }) => ( + + + +); + +export default PlayIcon; \ No newline at end of file diff --git a/src/icons/PreviousIcon.js b/src/icons/PreviousIcon.js new file mode 100644 index 0000000..b1a1a29 --- /dev/null +++ b/src/icons/PreviousIcon.js @@ -0,0 +1,8 @@ +const PreviousIcon = ({ width = 32, height = 32 }) => ( + + + + +); + +export default PreviousIcon; \ No newline at end of file diff --git a/src/icons/SaveIcon.js b/src/icons/SaveIcon.js new file mode 100644 index 0000000..7726492 --- /dev/null +++ b/src/icons/SaveIcon.js @@ -0,0 +1,7 @@ +const SaveIcon = ({ width = 32, height = 32 }) => ( + + + +); + +export default SaveIcon; \ No newline at end of file diff --git a/src/icons/StopIcon.js b/src/icons/StopIcon.js new file mode 100644 index 0000000..ab4884c --- /dev/null +++ b/src/icons/StopIcon.js @@ -0,0 +1,7 @@ +const StopIcon = ({ width = 32, height = 32 }) => ( + + + +); + +export default StopIcon; \ No newline at end of file diff --git a/src/index.css b/src/index.css index ec2585e..4551eb2 100644 --- a/src/index.css +++ b/src/index.css @@ -7,6 +7,10 @@ body { -moz-osx-font-smoothing: grayscale; } +* { + box-sizing: border-box; +} + code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;