mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-03 21:39:08 +00:00
style: recompose layout
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
export function debounce(callback: () => void, wait: number) {
|
||||||
|
let timeout: NodeJS.Timeout | null;
|
||||||
|
return () => {
|
||||||
|
if (timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
timeout = null;
|
||||||
|
callback();
|
||||||
|
}, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
.operatorEvents {
|
.operatorEvents {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.spacer {
|
.spacer {
|
||||||
min-height: 80vh;
|
min-height: 95vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin block() {
|
@mixin block() {
|
||||||
|
|||||||
@@ -65,8 +65,10 @@ export default function Operator() {
|
|||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
if (selectedRef && scrollRef) {
|
if (selectedRef && scrollRef) {
|
||||||
const selectedRect = selectedRef.current?.getBoundingClientRect();
|
const selectedRect = selectedRef.current?.getBoundingClientRect();
|
||||||
if (selectedRect) {
|
const scrollerRect = scrollRef.current?.getBoundingClientRect();
|
||||||
const hasScrolledOutOfThreshold = selectedRect.top < 0 || selectedRect.top > selectedOffset;
|
if (selectedRect && scrollerRect) {
|
||||||
|
const distanceFromTop = selectedRect.top - scrollerRect.top;
|
||||||
|
const hasScrolledOutOfThreshold = distanceFromTop < -8 || distanceFromTop > selectedOffset;
|
||||||
setLockAutoScroll(hasScrolledOutOfThreshold);
|
setLockAutoScroll(hasScrolledOutOfThreshold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,16 @@ export default function Operator() {
|
|||||||
<NavigationMenu />
|
<NavigationMenu />
|
||||||
<ViewParamsEditor paramFields={operatorOptions} />
|
<ViewParamsEditor paramFields={operatorOptions} />
|
||||||
|
|
||||||
|
<StatusBar
|
||||||
|
projectTitle={projectData.title}
|
||||||
|
playback={featureData.playback}
|
||||||
|
selectedEventId={featureData.selectedEventId}
|
||||||
|
firstStart={firstEvent?.timeStart}
|
||||||
|
firstId={firstEvent?.id}
|
||||||
|
lastEnd={lastEvent?.timeEnd}
|
||||||
|
lastId={lastEvent?.id}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className={style.operatorEvents} onScroll={handleScroll} ref={scrollRef}>
|
<div className={style.operatorEvents} onScroll={handleScroll} ref={scrollRef}>
|
||||||
{data.map((entry) => {
|
{data.map((entry) => {
|
||||||
if (entry.type === SupportedEvent.Event) {
|
if (entry.type === SupportedEvent.Event) {
|
||||||
@@ -136,15 +148,6 @@ export default function Operator() {
|
|||||||
<div className={style.spacer} />
|
<div className={style.spacer} />
|
||||||
</div>
|
</div>
|
||||||
<FollowButton isVisible={lockAutoScroll} onClickHandler={handleOffset} />
|
<FollowButton isVisible={lockAutoScroll} onClickHandler={handleOffset} />
|
||||||
<StatusBar
|
|
||||||
projectTitle={projectData.title}
|
|
||||||
playback={featureData.playback}
|
|
||||||
selectedEventId={featureData.selectedEventId}
|
|
||||||
firstStart={firstEvent?.timeStart}
|
|
||||||
firstId={firstEvent?.id}
|
|
||||||
lastEnd={lastEvent?.timeEnd}
|
|
||||||
lastId={lastEvent?.id}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
.followButton {
|
.followButton {
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: 100px;
|
bottom: 10rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
@@ -25,12 +25,5 @@
|
|||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
transition: bottom 1s;
|
transition: bottom 1s;
|
||||||
bottom: -0;
|
bottom: -50px;
|
||||||
}
|
|
||||||
|
|
||||||
// tablet
|
|
||||||
@media (min-width: $min-tablet) {
|
|
||||||
.followButton {
|
|
||||||
bottom: 150px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.statusBar {
|
.statusBar {
|
||||||
position: absolute;
|
position: sticky;
|
||||||
bottom: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: $gray-1350;
|
background-color: $gray-1350;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
border-top: 1px solid $white-10;
|
border-bottom: 1px solid $white-10;
|
||||||
box-shadow: $large-bottom-drawer-shadow;
|
box-shadow: $large-top-drawer-shadow;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
@@ -50,9 +50,10 @@
|
|||||||
|
|
||||||
.title {
|
.title {
|
||||||
grid-area: title;
|
grid-area: title;
|
||||||
font-size: 1.5rem;
|
font-size: 1rem;
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.25rem;
|
||||||
display: none;
|
display: none;
|
||||||
|
line-height: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.startTime {
|
.startTime {
|
||||||
@@ -80,8 +81,8 @@
|
|||||||
@media (min-width: $min-tablet) {
|
@media (min-width: $min-tablet) {
|
||||||
.statusBar {
|
.statusBar {
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"playback timer1B timer2B timer3B"
|
"playback timer1B timer2A timer3A"
|
||||||
"title timer1A timer2A timer3A";
|
"title title timer2B timer3B";
|
||||||
row-gap: 0.25rem;
|
row-gap: 0.25rem;
|
||||||
column-gap: 2rem;
|
column-gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,16 +63,6 @@ export default function StatusBar(props: StatusBarProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.statusBar}>
|
<div className={styles.statusBar}>
|
||||||
<span className={styles.title}>{projectTitle}</span>
|
|
||||||
<div className={styles.startTime}>
|
|
||||||
<span className={styles.label}>Scheduled start</span>
|
|
||||||
<span className={styles.timer}>{getTimeStart()}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.endTime}>
|
|
||||||
<span className={styles.label}>Scheduled end</span>
|
|
||||||
<span className={styles.timer}>{getTimeEnd()}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{PlaybackIconComponent}
|
{PlaybackIconComponent}
|
||||||
<div className={styles.timeNow}>
|
<div className={styles.timeNow}>
|
||||||
<span className={styles.label}>Time now</span>
|
<span className={styles.label}>Time now</span>
|
||||||
@@ -86,6 +76,16 @@ export default function StatusBar(props: StatusBarProps) {
|
|||||||
<span className={styles.label}>Running timer</span>
|
<span className={styles.label}>Running timer</span>
|
||||||
<span className={styles.timer}>{runningTime}</span>
|
<span className={styles.timer}>{runningTime}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<span className={styles.title}>{projectTitle}</span>
|
||||||
|
<div className={styles.startTime}>
|
||||||
|
<span className={styles.label}>Scheduled start</span>
|
||||||
|
<span className={styles.timer}>{getTimeStart()}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.endTime}>
|
||||||
|
<span className={styles.label}>Scheduled end</span>
|
||||||
|
<span className={styles.timer}>{getTimeEnd()}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ $bg-container-onlight: $gray-100;
|
|||||||
$box-shadow-l1: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
$box-shadow-l1: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
||||||
$box-shadow-l2: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
$box-shadow-l2: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
||||||
$large-bottom-drawer-shadow: rgba(0, 0, 0, 0.35) 0 3px 6px 6px;
|
$large-bottom-drawer-shadow: rgba(0, 0, 0, 0.35) 0 3px 6px 6px;
|
||||||
|
$large-top-drawer-shadow: rgba(0, 0, 0, 0.35) 0 1px 6px 3px;
|
||||||
|
|
||||||
$modal-note-color: $gray-700;
|
$modal-note-color: $gray-700;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user