mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 11:31:11 +00:00
redesign
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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 (
|
||||
<div className='controls'>
|
||||
<div className='input-group'>
|
||||
<p>{formatDuration(currentTime)}</p>
|
||||
<p className='time'>{formatDuration(currentTime)}</p>
|
||||
<Slider
|
||||
aria-label='time-indicator'
|
||||
value={currentTime}
|
||||
@@ -43,8 +49,8 @@ function AnnotationControls({
|
||||
className='video-slider'
|
||||
/>
|
||||
{videoRef.current !== null
|
||||
? <p>{formatDuration(videoRef.current.duration - currentTime)}</p>
|
||||
: <p>{formatDuration(0)}</p>
|
||||
? <p className='time'>{formatDuration(videoRef.current.duration - currentTime)}</p>
|
||||
: <p className='time'>{formatDuration(0)}</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -55,46 +61,48 @@ function AnnotationControls({
|
||||
onClick={onFrameBackward}
|
||||
title="Previous Frame"
|
||||
>
|
||||
⏮️
|
||||
<PreviousIcon />
|
||||
</button>
|
||||
<button
|
||||
className={isPlaying ? 'control-btn pause-btn' : 'control-btn play-btn'}
|
||||
onClick={onPlayPause}
|
||||
>
|
||||
{isPlaying ? '⏸️ Pause' : '▶️ Play'}
|
||||
{isPlaying ? <PauseIcon /> : <PlayIcon />}
|
||||
</button>
|
||||
<button
|
||||
className='control-btn arrow-btn'
|
||||
onClick={onFrameForward}
|
||||
title="Next Frame"
|
||||
>
|
||||
⏭️
|
||||
<NextIcon />
|
||||
</button>
|
||||
<button
|
||||
className='control-btn stop-btn'
|
||||
onClick={onStop}
|
||||
title='Stop'
|
||||
>
|
||||
<FaStop /> Stop
|
||||
<StopIcon />
|
||||
</button>
|
||||
<button
|
||||
className='control-btn save-btn'
|
||||
onClick={onSaveAnnotation}
|
||||
title='Save'
|
||||
>
|
||||
💾 Save
|
||||
<SaveIcon />
|
||||
</button>
|
||||
<button
|
||||
className='control-btn delete-btn'
|
||||
onClick={onDelete}
|
||||
title='Delete'
|
||||
>
|
||||
🗑️ Delete
|
||||
<DeleteIcon />
|
||||
</button>
|
||||
<button
|
||||
className='control-btn clean-btn'
|
||||
onClick={onDeleteAll}
|
||||
title='DeleteAll'
|
||||
>
|
||||
<MdCleaningServices /> Delete All
|
||||
<CleanIcon />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
// src/components/AnnotationList.js
|
||||
// No changes
|
||||
import React from 'react';
|
||||
import './AnnotationList.css'
|
||||
|
||||
function AnnotationList({ annotations, onAnnotationClick }) {
|
||||
return (
|
||||
<div>
|
||||
<div className='annotation-section'>
|
||||
<h3 className='menu-title'>Annotations</h3>
|
||||
<ul>
|
||||
<ul className='annotation-list'>
|
||||
{annotations.map((annotation, index) => (
|
||||
<li key={index} onClick={() => onAnnotationClick(annotation.time)}>
|
||||
<li className='annotation-list-item' key={index} onClick={() => onAnnotationClick(annotation.time)}>
|
||||
Frame {index + 1} - {annotation.annotations.length} objects
|
||||
</li>
|
||||
))}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -91,29 +91,32 @@ function DetectionClassList({ onClassSelect, detectionType, setDetectionType })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='class-list'>
|
||||
<h3 className='menu-title'>Classes</h3>
|
||||
<ul className='class-list-group' >
|
||||
{detectionClasses.map((cls) => {
|
||||
const backgroundColor = calculateColor(cls.Id);
|
||||
const darkBg = calculateColor(cls.Id, '0.8');
|
||||
const isSelected = selectedClass && selectedClass.Id === cls.Id;
|
||||
<div className='detection'>
|
||||
|
||||
return (
|
||||
<li
|
||||
key={cls.Id}
|
||||
className='class-list-item'
|
||||
style={{
|
||||
border: `1px solid ${isSelected ? '#000' : '#eee'}`,
|
||||
backgroundColor: isSelected ? darkBg : backgroundColor,
|
||||
}}
|
||||
onClick={() => handleClassClick(cls)}
|
||||
>
|
||||
{cls.Name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className='class-list'>
|
||||
<h3 className='menu-title'>Classes</h3>
|
||||
<ul className='class-list-group' >
|
||||
{detectionClasses.map((cls) => {
|
||||
const backgroundColor = calculateColor(cls.Id);
|
||||
const darkBg = calculateColor(cls.Id, '0.8');
|
||||
const isSelected = selectedClass && selectedClass.Id === cls.Id;
|
||||
|
||||
return (
|
||||
<li
|
||||
key={cls.Id}
|
||||
className='class-list-item'
|
||||
style={{
|
||||
border: `1px solid ${isSelected ? '#000' : '#eee0'}`,
|
||||
backgroundColor: isSelected ? darkBg : backgroundColor,
|
||||
}}
|
||||
onClick={() => handleClassClick(cls)}
|
||||
>
|
||||
{cls.Name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className='detection-type-group'>
|
||||
<button className={detectionType == detectionTypes.day
|
||||
|
||||
@@ -1,26 +1,73 @@
|
||||
.explorer{
|
||||
height: 40vh ;
|
||||
background: #222531;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.explorer-head{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
font-size: 14px;
|
||||
margin: 15px 0;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
color: white;
|
||||
margin: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.open-btn{
|
||||
width: 80px;
|
||||
height: 20px;
|
||||
background: #6188FF;
|
||||
color: white;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.open-btn:hover{
|
||||
background: #295cf7;
|
||||
}
|
||||
|
||||
.file-filter{
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
height: 26px;
|
||||
background: white;
|
||||
padding: 6px 12px;
|
||||
border: 0;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.file-list-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
margin: 12px 0;
|
||||
list-style-type: none;
|
||||
max-height: 20vh;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
max-height: 36%;
|
||||
}
|
||||
|
||||
.file-list-group::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-list-item {
|
||||
cursor: pointer;
|
||||
padding: 6px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 7px 6px;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.label {
|
||||
@@ -28,9 +75,14 @@
|
||||
}
|
||||
|
||||
.file-input-block {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 12%;
|
||||
color: white;
|
||||
border: 2px dashed #ccc;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -28,13 +28,15 @@ function MediaList({ files, selectedFile, onFileSelect, onDropNewFiles }) {
|
||||
|
||||
return (
|
||||
<div className='explorer'>
|
||||
<h3 className='menu-title' >Files</h3>
|
||||
<button type="button" onClick={openFileDialog}>
|
||||
Open File
|
||||
</button>
|
||||
<button type="button" onClick={openFolderDialog}>
|
||||
Open Folder
|
||||
</button>
|
||||
<div className='explorer-head'>
|
||||
<h3 className='menu-title' >Files</h3>
|
||||
<button className='open-btn' type="button" onClick={openFileDialog}>
|
||||
Open File
|
||||
</button>
|
||||
<button className='open-btn' type="button" onClick={openFolderDialog}>
|
||||
Open Folder
|
||||
</button>
|
||||
</div>
|
||||
<input className='file-filter' type='text' placeholder='Filename' onChange={handleInputChange} />
|
||||
<ul className='file-list-group' >
|
||||
{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)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user