YACWC
This commit is contained in:
@@ -26,12 +26,15 @@
|
|||||||
|
|
||||||
/* Main app container */
|
/* Main app container */
|
||||||
.app-container {
|
.app-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 95vw;
|
width: 95vw;
|
||||||
max-width: 95vw;
|
max-width: 95vw;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Controls section */
|
/* Controls section */
|
||||||
@@ -62,8 +65,7 @@
|
|||||||
/* Timeline container */
|
/* Timeline container */
|
||||||
.timeline-section {
|
.timeline-section {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 30vh;
|
min-height: 60px;
|
||||||
min-height: 200px;
|
|
||||||
background: #20232a;
|
background: #20232a;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -72,14 +74,15 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: flex 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Video player section */
|
/* Video player section */
|
||||||
.video-section {
|
.video-section {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-height: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60vw;
|
|
||||||
margin-top: 12px;
|
|
||||||
min-height: 40vw;
|
|
||||||
background: #23272f;
|
background: #23272f;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -88,6 +91,8 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: flex 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Date range picker styles */
|
/* Date range picker styles */
|
||||||
|
|||||||
@@ -37,8 +37,19 @@ function App() {
|
|||||||
);
|
);
|
||||||
const [endRange, setEndRange] = useState(new Date());
|
const [endRange, setEndRange] = useState(new Date());
|
||||||
// const [endRange, setEndRange] = useState(new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000));
|
// const [endRange, setEndRange] = useState(new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000));
|
||||||
const [queryText, setQueryText] = useState("Two clouded leopards being aggressive");
|
const [queryText, setQueryText] = useState(
|
||||||
|
"Two clouded leopards being aggressive",
|
||||||
|
);
|
||||||
const [sliderValue, setSliderValue] = useState(0);
|
const [sliderValue, setSliderValue] = useState(0);
|
||||||
|
const [videoFlex, setVideoFlex] = useState(5.8); // ratio: video vs timeline
|
||||||
|
|
||||||
|
const handleVideoWheel = useCallback((e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setVideoFlex((prev) => {
|
||||||
|
const delta = e.deltaY > 0 ? 0.3 : -0.3;
|
||||||
|
return Math.max(3, Math.min(10, Math.max(1, prev + 0.5*delta)))
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
// State to track last submitted values
|
// State to track last submitted values
|
||||||
const [lastSubmitted, setLastSubmitted] = useState({
|
const [lastSubmitted, setLastSubmitted] = useState({
|
||||||
@@ -157,22 +168,24 @@ function App() {
|
|||||||
queryText,
|
queryText,
|
||||||
selectedCamera,
|
selectedCamera,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function selectHighResFunc(
|
||||||
function selectHighResFunc(selectedHighRes, setSelectedHighRes, toggleCheckbox = true) {
|
selectedHighRes,
|
||||||
|
setSelectedHighRes,
|
||||||
|
sendState = false,
|
||||||
|
) {
|
||||||
console.log(selectedHighRes);
|
console.log(selectedHighRes);
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.append("do_high_res", !selectedHighRes);
|
if (sendState) {
|
||||||
|
params.append("do_high_res", selectedHighRes);
|
||||||
|
} else {
|
||||||
|
params.append("do_high_res", !selectedHighRes);
|
||||||
|
}
|
||||||
authenticatedFetch("api/set_parameter?" + params.toString())
|
authenticatedFetch("api/set_parameter?" + params.toString())
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (toggleCheckbox) {
|
if (!sendState) {
|
||||||
setSelectedHighRes(!selectedHighRes);
|
setSelectedHighRes(!selectedHighRes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -267,8 +280,8 @@ function App() {
|
|||||||
tech.el_.addEventListener("loadstart", () => {
|
tech.el_.addEventListener("loadstart", () => {
|
||||||
// Force range request capability
|
// Force range request capability
|
||||||
if (
|
if (
|
||||||
tech.el_.seekable &&
|
tech.el_.seekable
|
||||||
tech.el_.seekable.length === 0
|
&& tech.el_.seekable.length === 0
|
||||||
) {
|
) {
|
||||||
console.log(
|
console.log(
|
||||||
"Video doesn't support seeking - range headers may be needed",
|
"Video doesn't support seeking - range headers may be needed",
|
||||||
@@ -339,11 +352,7 @@ function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
selectHighResFunc(
|
selectHighResFunc(selectedHighRes, setSelectedHighRes, true);
|
||||||
selectedHighRes,
|
|
||||||
setSelectedHighRes,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
handleResubmit(params.get("test_mode") === "true");
|
handleResubmit(params.get("test_mode") === "true");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -367,10 +376,9 @@ function App() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
setSliderMax(max_value);
|
setSliderMax(max_value);
|
||||||
|
|
||||||
original_data.current = data;
|
original_data.current = data;
|
||||||
setDataResults(data);
|
setDataResults(data);
|
||||||
updateDataAndValue(sliderValue)
|
updateDataAndValue(sliderValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -601,20 +609,32 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="controls-section" style={{
|
<div
|
||||||
display: "flex",
|
className="controls-section"
|
||||||
alignItems: "center",
|
style={{
|
||||||
justifyContent: "center",
|
display: "flex",
|
||||||
gap: "12px",
|
alignItems: "center",
|
||||||
flexWrap: "nowrap",
|
justifyContent: "center",
|
||||||
padding: "12px 16px",
|
gap: "12px",
|
||||||
background: "linear-gradient(135deg, #2a2d3a 0%, #1f2129 100%)",
|
flexWrap: "nowrap",
|
||||||
borderRadius: "12px",
|
padding: videoFlex >= 6 ? "0" : "12px 16px",
|
||||||
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
background:
|
||||||
border: "1px solid #3a3f4f",
|
"linear-gradient(135deg, #2a2d3a 0%, #1f2129 100%)",
|
||||||
overflowX: "auto"
|
borderRadius: "12px",
|
||||||
}}>
|
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
||||||
<div className="control-group" style={{ margin: 0, flexShrink: 0 }}>
|
border: videoFlex >= 6 ? "none" : "1px solid #3a3f4f",
|
||||||
|
overflowX: "auto",
|
||||||
|
maxHeight: videoFlex >= 6 ? "0px" : "200px",
|
||||||
|
overflow: "hidden",
|
||||||
|
opacity: videoFlex >= 6 ? 0 : 1,
|
||||||
|
marginBottom: videoFlex >= 6 ? 0 : 12,
|
||||||
|
transition: "max-height 0.3s ease, opacity 0.3s ease, padding 0.3s ease, margin-bottom 0.3s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="control-group"
|
||||||
|
style={{ margin: 0, flexShrink: 0 }}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
className="drawer-toggle"
|
className="drawer-toggle"
|
||||||
onClick={() => setDrawerOpen(!drawerOpen)}
|
onClick={() => setDrawerOpen(!drawerOpen)}
|
||||||
@@ -622,35 +642,41 @@ function App() {
|
|||||||
padding: "8px 12px",
|
padding: "8px 12px",
|
||||||
fontSize: "0.85em",
|
fontSize: "0.85em",
|
||||||
minWidth: "70px",
|
minWidth: "70px",
|
||||||
background: "linear-gradient(135deg, #4a90e2 0%, #357abd 100%)",
|
background:
|
||||||
|
"linear-gradient(135deg, #4a90e2 0%, #357abd 100%)",
|
||||||
color: "white",
|
color: "white",
|
||||||
border: "none",
|
border: "none",
|
||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
fontWeight: "500",
|
fontWeight: "500",
|
||||||
boxShadow: "0 2px 4px rgba(74, 144, 226, 0.3)",
|
boxShadow: "0 2px 4px rgba(74, 144, 226, 0.3)",
|
||||||
transition: "all 0.2s ease"
|
transition: "all 0.2s ease",
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
e.target.style.transform = "translateY(-1px)";
|
e.target.style.transform = "translateY(-1px)";
|
||||||
e.target.style.boxShadow = "0 4px 8px rgba(74, 144, 226, 0.4)";
|
e.target.style.boxShadow =
|
||||||
|
"0 4px 8px rgba(74, 144, 226, 0.4)";
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
e.target.style.transform = "translateY(0)";
|
e.target.style.transform = "translateY(0)";
|
||||||
e.target.style.boxShadow = "0 2px 4px rgba(74, 144, 226, 0.3)";
|
e.target.style.boxShadow =
|
||||||
|
"0 2px 4px rgba(74, 144, 226, 0.3)";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{drawerOpen ? "✕" : "Options"}
|
{drawerOpen ? "✕" : "Options"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-group" style={{
|
<div
|
||||||
margin: 0,
|
className="control-group"
|
||||||
flexShrink: 0,
|
style={{
|
||||||
background: "rgba(255, 255, 255, 0.05)",
|
margin: 0,
|
||||||
borderRadius: "6px",
|
flexShrink: 0,
|
||||||
border: "1px solid rgba(255, 255, 255, 0.1)"
|
background: "rgba(255, 255, 255, 0.05)",
|
||||||
}}>
|
borderRadius: "6px",
|
||||||
|
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<CustomDateRangePicker
|
<CustomDateRangePicker
|
||||||
startDate={startRange}
|
startDate={startRange}
|
||||||
endDate={endRange}
|
endDate={endRange}
|
||||||
@@ -659,7 +685,15 @@ function App() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-group" style={{ margin: 0, flex: "1 1 180px", minWidth: "180px", maxWidth: "300px" }}>
|
<div
|
||||||
|
className="control-group"
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
flex: "1 1 180px",
|
||||||
|
minWidth: "180px",
|
||||||
|
maxWidth: "300px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter search query..."
|
placeholder="Enter search query..."
|
||||||
@@ -680,33 +714,38 @@ function App() {
|
|||||||
fontWeight: "400",
|
fontWeight: "400",
|
||||||
outline: "none",
|
outline: "none",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
boxShadow: "inset 0 2px 4px rgba(0, 0, 0, 0.1)"
|
boxShadow: "inset 0 2px 4px rgba(0, 0, 0, 0.1)",
|
||||||
}}
|
}}
|
||||||
onFocus={(e) => {
|
onFocus={(e) => {
|
||||||
e.target.style.borderColor = "#4a90e2";
|
e.target.style.borderColor = "#4a90e2";
|
||||||
e.target.style.boxShadow = "inset 0 2px 4px rgba(0, 0, 0, 0.1), 0 0 0 3px rgba(74, 144, 226, 0.15)";
|
e.target.style.boxShadow =
|
||||||
|
"inset 0 2px 4px rgba(0, 0, 0, 0.1), 0 0 0 3px rgba(74, 144, 226, 0.15)";
|
||||||
}}
|
}}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
e.target.style.borderColor = "#3a3f4f";
|
e.target.style.borderColor = "#3a3f4f";
|
||||||
e.target.style.boxShadow = "inset 0 2px 4px rgba(0, 0, 0, 0.1)";
|
e.target.style.boxShadow =
|
||||||
|
"inset 0 2px 4px rgba(0, 0, 0, 0.1)";
|
||||||
}}
|
}}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-group" style={{
|
<div
|
||||||
margin: 0,
|
className="control-group"
|
||||||
display: "flex",
|
style={{
|
||||||
alignItems: "center",
|
margin: 0,
|
||||||
gap: "6px",
|
display: "flex",
|
||||||
color: "#e1e5e9",
|
alignItems: "center",
|
||||||
fontSize: "0.85em",
|
gap: "6px",
|
||||||
background: "rgba(255, 255, 255, 0.05)",
|
color: "#e1e5e9",
|
||||||
padding: "6px 10px",
|
fontSize: "0.85em",
|
||||||
borderRadius: "6px",
|
background: "rgba(255, 255, 255, 0.05)",
|
||||||
border: "1px solid rgba(255, 255, 255, 0.1)",
|
padding: "6px 10px",
|
||||||
flexShrink: 0
|
borderRadius: "6px",
|
||||||
}}>
|
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="do_high_res"
|
name="do_high_res"
|
||||||
@@ -720,29 +759,35 @@ function App() {
|
|||||||
style={{
|
style={{
|
||||||
width: "14px",
|
width: "14px",
|
||||||
height: "14px",
|
height: "14px",
|
||||||
accentColor: "#4a90e2"
|
accentColor: "#4a90e2",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span style={{ fontWeight: "500", whiteSpace: "nowrap" }}>HD</span>
|
<span style={{ fontWeight: "500", whiteSpace: "nowrap" }}>
|
||||||
|
HD
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{
|
<div
|
||||||
display: "flex",
|
style={{
|
||||||
alignItems: "center",
|
display: "flex",
|
||||||
gap: "8px",
|
alignItems: "center",
|
||||||
visibility: queryChanged ? "hidden" : "visible",
|
gap: "8px",
|
||||||
background: "rgba(255, 255, 255, 0.05)",
|
visibility: queryChanged ? "hidden" : "visible",
|
||||||
padding: "6px 12px",
|
background: "rgba(255, 255, 255, 0.05)",
|
||||||
borderRadius: "6px",
|
padding: "6px 12px",
|
||||||
border: "1px solid rgba(255, 255, 255, 0.1)",
|
borderRadius: "6px",
|
||||||
flexShrink: 0
|
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||||
}}>
|
flexShrink: 0,
|
||||||
<label style={{
|
}}
|
||||||
color: "#e1e5e9",
|
>
|
||||||
fontSize: "0.85em",
|
<label
|
||||||
whiteSpace: "nowrap",
|
style={{
|
||||||
fontWeight: "500"
|
color: "#e1e5e9",
|
||||||
}}>
|
fontSize: "0.85em",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
fontWeight: "500",
|
||||||
|
}}
|
||||||
|
>
|
||||||
Threshold:
|
Threshold:
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -755,35 +800,42 @@ function App() {
|
|||||||
style={{
|
style={{
|
||||||
width: "80px",
|
width: "80px",
|
||||||
height: "6px",
|
height: "6px",
|
||||||
background: "linear-gradient(to right, #3a3f4f 0%, #4a90e2 100%)",
|
background:
|
||||||
|
"linear-gradient(to right, #3a3f4f 0%, #4a90e2 100%)",
|
||||||
borderRadius: "3px",
|
borderRadius: "3px",
|
||||||
outline: "none",
|
outline: "none",
|
||||||
appearance: "none"
|
appearance: "none",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span style={{
|
<span
|
||||||
color: "#4a90e2",
|
style={{
|
||||||
fontSize: "0.8em",
|
color: "#4a90e2",
|
||||||
minWidth: "35px",
|
fontSize: "0.8em",
|
||||||
textAlign: "right",
|
minWidth: "35px",
|
||||||
fontWeight: "600",
|
textAlign: "right",
|
||||||
fontFamily: "monospace"
|
fontWeight: "600",
|
||||||
}}>
|
fontFamily: "monospace",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{sliderValue.toFixed(2)}
|
{sliderValue.toFixed(2)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-group" style={{
|
<div
|
||||||
margin: 0,
|
className="control-group"
|
||||||
visibility: queryChanged ? "visible" : "hidden",
|
style={{
|
||||||
flexShrink: 0
|
margin: 0,
|
||||||
}}>
|
visibility: queryChanged ? "visible" : "hidden",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
onClick={handleResubmit}
|
onClick={handleResubmit}
|
||||||
style={{
|
style={{
|
||||||
padding: "8px 14px",
|
padding: "8px 14px",
|
||||||
fontSize: "0.85em",
|
fontSize: "0.85em",
|
||||||
background: "linear-gradient(135deg, #28a745 0%, #20a73a 100%)",
|
background:
|
||||||
|
"linear-gradient(135deg, #28a745 0%, #20a73a 100%)",
|
||||||
color: "white",
|
color: "white",
|
||||||
border: "none",
|
border: "none",
|
||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
@@ -791,24 +843,33 @@ function App() {
|
|||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
boxShadow: "0 2px 4px rgba(40, 167, 69, 0.3)",
|
boxShadow: "0 2px 4px rgba(40, 167, 69, 0.3)",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
whiteSpace: "nowrap"
|
whiteSpace: "nowrap",
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
e.target.style.transform = "translateY(-1px)";
|
e.target.style.transform = "translateY(-1px)";
|
||||||
e.target.style.boxShadow = "0 4px 8px rgba(40, 167, 69, 0.4)";
|
e.target.style.boxShadow =
|
||||||
|
"0 4px 8px rgba(40, 167, 69, 0.4)";
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
e.target.style.transform = "translateY(0)";
|
e.target.style.transform = "translateY(0)";
|
||||||
e.target.style.boxShadow = "0 2px 4px rgba(40, 167, 69, 0.3)";
|
e.target.style.boxShadow =
|
||||||
|
"0 2px 4px rgba(40, 167, 69, 0.3)";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
🔄 Resubmit
|
Resubmit
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-group" style={{ margin: 0, flexShrink: 0 }}>
|
<div
|
||||||
|
className="control-group"
|
||||||
|
style={{ margin: 0, flexShrink: 0 }}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
onClick={videoPlaying ? () => window.open("api/media_download/low") : undefined}
|
onClick={
|
||||||
|
videoPlaying
|
||||||
|
? () => window.open("api/media_download/low")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
disabled={!videoPlaying}
|
disabled={!videoPlaying}
|
||||||
style={{
|
style={{
|
||||||
padding: "6px 10px",
|
padding: "6px 10px",
|
||||||
@@ -826,27 +887,36 @@ function App() {
|
|||||||
? "0 2px 4px rgba(23, 198, 113, 0.3)"
|
? "0 2px 4px rgba(23, 198, 113, 0.3)"
|
||||||
: "0 1px 2px rgba(108, 117, 125, 0.2)",
|
: "0 1px 2px rgba(108, 117, 125, 0.2)",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
whiteSpace: "nowrap"
|
whiteSpace: "nowrap",
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
if (videoPlaying) {
|
if (videoPlaying) {
|
||||||
e.target.style.transform = "translateY(-1px)";
|
e.target.style.transform = "translateY(-1px)";
|
||||||
e.target.style.boxShadow = "0 4px 8px rgba(23, 198, 113, 0.4)";
|
e.target.style.boxShadow =
|
||||||
|
"0 4px 8px rgba(23, 198, 113, 0.4)";
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
if (videoPlaying) {
|
if (videoPlaying) {
|
||||||
e.target.style.transform = "translateY(0)";
|
e.target.style.transform = "translateY(0)";
|
||||||
e.target.style.boxShadow = "0 2px 4px rgba(23, 198, 113, 0.3)";
|
e.target.style.boxShadow =
|
||||||
|
"0 2px 4px rgba(23, 198, 113, 0.3)";
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
DL Low-Res Video
|
DL Low-Res Video
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="control-group" style={{ margin: 0, flexShrink: 0 }}>
|
<div
|
||||||
|
className="control-group"
|
||||||
|
style={{ margin: 0, flexShrink: 0 }}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
onClick={videoPlaying ? () => window.open("api/media_download/high") : undefined}
|
onClick={
|
||||||
|
videoPlaying
|
||||||
|
? () => window.open("api/media_download/high")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
disabled={!videoPlaying}
|
disabled={!videoPlaying}
|
||||||
style={{
|
style={{
|
||||||
padding: "6px 10px",
|
padding: "6px 10px",
|
||||||
@@ -864,22 +934,24 @@ function App() {
|
|||||||
? "0 2px 4px rgba(0, 123, 255, 0.3)"
|
? "0 2px 4px rgba(0, 123, 255, 0.3)"
|
||||||
: "0 1px 2px rgba(108, 117, 125, 0.2)",
|
: "0 1px 2px rgba(108, 117, 125, 0.2)",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
whiteSpace: "nowrap"
|
whiteSpace: "nowrap",
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
if (videoPlaying) {
|
if (videoPlaying) {
|
||||||
e.target.style.transform = "translateY(-1px)";
|
e.target.style.transform = "translateY(-1px)";
|
||||||
e.target.style.boxShadow = "0 4px 8px rgba(0, 123, 255, 0.4)";
|
e.target.style.boxShadow =
|
||||||
|
"0 4px 8px rgba(0, 123, 255, 0.4)";
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
if (videoPlaying) {
|
if (videoPlaying) {
|
||||||
e.target.style.transform = "translateY(0)";
|
e.target.style.transform = "translateY(0)";
|
||||||
e.target.style.boxShadow = "0 2px 4px rgba(0, 123, 255, 0.3)";
|
e.target.style.boxShadow =
|
||||||
|
"0 2px 4px rgba(0, 123, 255, 0.3)";
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
DL High-Res Video
|
DL High-Res Video
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -888,16 +960,17 @@ function App() {
|
|||||||
<StatusesDisplayHUD statusMessages={statusMessages} />
|
<StatusesDisplayHUD statusMessages={statusMessages} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="timeline-section">
|
<div className="timeline-section" style={{ flex: `${Math.max(1, 5 - videoFlex * 0.5)} 1 0`, minHeight: 60 }}>
|
||||||
<EmbedTimeline
|
<EmbedTimeline
|
||||||
chartRef={chartRef}
|
chartRef={chartRef}
|
||||||
data_in={dataResults}
|
data_in={dataResults}
|
||||||
onTimelineClick={handleTimelineClick}
|
onTimelineClick={handleTimelineClick}
|
||||||
authenticatedFetch={authenticatedFetch}
|
authenticatedFetch={authenticatedFetch}
|
||||||
|
hideDataZoom={videoFlex >= 6}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="video-section vjs-16-9 vjs-fluid">
|
<div className="video-section" style={{ flex: `${videoFlex} 1 0` }} onWheel={handleVideoWheel}>
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
videoRef={playerRef}
|
videoRef={playerRef}
|
||||||
playerInstanceRef={playerInstanceRef}
|
playerInstanceRef={playerInstanceRef}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export default function CustomDateRangePicker({ startDate, endDate, setStartRang
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{showCalendar && (
|
{showCalendar && (
|
||||||
<div style={{ position: "absolute", zIndex: 10 }}>
|
<div style={{ position: "fixed", zIndex: 9999 }}>
|
||||||
<DateRange
|
<DateRange
|
||||||
minDate={minDate}
|
minDate={minDate}
|
||||||
maxDate={maxDate}
|
maxDate={maxDate}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const EmbedTimeline = React.memo(function EmbedTimeline({
|
|||||||
onTimelineClick,
|
onTimelineClick,
|
||||||
authenticatedFetch,
|
authenticatedFetch,
|
||||||
markerTime,
|
markerTime,
|
||||||
|
hideDataZoom,
|
||||||
}) {
|
}) {
|
||||||
// Use useRef instead of props/state to avoid re-renders
|
// Use useRef instead of props/state to avoid re-renders
|
||||||
const zoomed_range = useRef([null, null]);
|
const zoomed_range = useRef([null, null]);
|
||||||
@@ -475,16 +476,18 @@ const EmbedTimeline = React.memo(function EmbedTimeline({
|
|||||||
},
|
},
|
||||||
response: true,
|
response: true,
|
||||||
grid: {
|
grid: {
|
||||||
top: 30, // Remove top padding
|
top: 30,
|
||||||
left: 10,
|
left: 10,
|
||||||
right: 20,
|
right: 20,
|
||||||
bottom: 60,
|
bottom: hideDataZoom ? 10 : 10,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
dataZoom: [
|
dataZoom: [
|
||||||
{
|
{
|
||||||
type: "slider",
|
type: "slider",
|
||||||
show: true,
|
// show: !hideDataZoom,
|
||||||
|
show: false,
|
||||||
|
height: hideDataZoom ? 0 : undefined,
|
||||||
xAxisIndex: [0],
|
xAxisIndex: [0],
|
||||||
startValue: virtual_x_min,
|
startValue: virtual_x_min,
|
||||||
endValue: virtual_x_max,
|
endValue: virtual_x_max,
|
||||||
|
|||||||
@@ -22,14 +22,13 @@ const VideoPlayer = function VideoPlayer({
|
|||||||
controls: true,
|
controls: true,
|
||||||
preload: "auto",
|
preload: "auto",
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
fluid: true,
|
fill: true,
|
||||||
html5: {
|
html5: {
|
||||||
vhs: {
|
vhs: {
|
||||||
overrideNative: true, // use Video.js native range handling
|
overrideNative: true, // use Video.js native range handling
|
||||||
},
|
},
|
||||||
nativeVideoTracks: false,
|
nativeVideoTracks: false,
|
||||||
},
|
},
|
||||||
responsive: true,
|
|
||||||
techOrder: ['html5'],
|
techOrder: ['html5'],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user