Skip to content

Commit 798729b

Browse files
committed
SOFIE-261 | add UI for configuring t-timers (WIP)
1 parent d0c77c8 commit 798729b

File tree

5 files changed

+734
-0
lines changed

5 files changed

+734
-0
lines changed

packages/shared-lib/src/core/model/StudioSettings.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,30 @@ export interface IStudioSettings {
104104
* How long before their start time a rundown owned piece be added to the timeline
105105
*/
106106
rundownGlobalPiecesPrepareTime?: number
107+
108+
/** Configuration for T-Timers in this studio */
109+
tTimerSettings?: [TTimerSettingsConfig, TTimerSettingsConfig, TTimerSettingsConfig]
110+
}
111+
112+
export type TTimerMode = 'freeRun' | 'countdown' | 'timeOfDay'
113+
114+
export interface TTimerSettingsConfig {
115+
/** User label for this timer (matches RundownTTimer.label) */
116+
label: string
117+
/** Whether this timer is enabled */
118+
enabled: boolean
119+
/** The mode for this timer */
120+
mode: TTimerMode
121+
/** Countdown duration in milliseconds (for 'countdown' mode) */
122+
countdownDuration: number
123+
/** Target time string for 'timeOfDay' mode (e.g. "14:30") */
124+
timeOfDayTarget: string
125+
/** Whether the timer should stop at zero, or continue into negative values */
126+
stopAtZero: boolean
127+
/** Show on the Top Bar */
128+
showOnTopBar: boolean
129+
/** Show on the Director Screen */
130+
showOnDirectorScreen: boolean
131+
/** Show on the Presenter Screen + Prompter */
132+
showOnPresenterScreen: boolean
107133
}

packages/webui/src/client/styles/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ input {
4141
@import 'rundownList';
4242
@import 'rundownSystemStatus';
4343
@import 'settings';
44+
@import 'tTimerSettings';
4445
@import 'splitDropdown';
4546
@import 'statusbar';
4647
@import 'studioScreenSaver';
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
@import 'colorScheme';
2+
3+
.t-timer-settings {
4+
margin-top: 1rem;
5+
6+
&__header {
7+
display: flex;
8+
align-items: center;
9+
margin-bottom: 0.75rem;
10+
11+
h3 {
12+
margin: 0;
13+
}
14+
}
15+
}
16+
17+
.t-timer-card {
18+
border: 1px solid #ddd;
19+
border-radius: 6px;
20+
background: #fafafa;
21+
padding: 1rem 1.25rem;
22+
margin-bottom: 0.75rem;
23+
transition: box-shadow 0.15s ease;
24+
25+
&:hover {
26+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
27+
}
28+
29+
&--disabled {
30+
opacity: 0.5;
31+
}
32+
33+
&__top-row {
34+
display: flex;
35+
align-items: center;
36+
gap: 0.75rem;
37+
margin-bottom: 1rem;
38+
border-bottom: 1px solid #eee;
39+
padding-bottom: 0.75rem;
40+
}
41+
42+
&__toggle {
43+
flex-shrink: 0;
44+
}
45+
46+
&__name {
47+
display: flex;
48+
align-items: center;
49+
gap: 0.35rem;
50+
font-weight: 600;
51+
text-transform: uppercase;
52+
letter-spacing: 0.05em;
53+
width: 200px;
54+
min-width: 200px;
55+
max-width: 200px;
56+
57+
span {
58+
overflow: hidden;
59+
text-overflow: ellipsis;
60+
white-space: nowrap;
61+
}
62+
63+
input {
64+
font-weight: 600;
65+
text-transform: uppercase;
66+
letter-spacing: 0.05em;
67+
border: none;
68+
border-bottom: 1px dashed #ccc;
69+
background: transparent;
70+
outline: none;
71+
padding: 2px 4px;
72+
width: 100%;
73+
74+
&:focus {
75+
border-bottom-color: #333;
76+
}
77+
}
78+
}
79+
80+
&__edit-btn {
81+
background: none;
82+
border: none;
83+
cursor: pointer;
84+
color: #999;
85+
padding: 0;
86+
}
87+
88+
&__transport {
89+
display: flex;
90+
align-items: center;
91+
gap: 0.25rem;
92+
margin-left: 2rem;
93+
94+
button {
95+
background: none;
96+
border: 1px solid #ccc;
97+
border-radius: 50%;
98+
width: 28px;
99+
height: 28px;
100+
display: flex;
101+
align-items: center;
102+
justify-content: center;
103+
cursor: pointer;
104+
font-size: 0.75rem;
105+
color: #555;
106+
transition: all 0.15s ease;
107+
108+
&:hover {
109+
background: #eee;
110+
border-color: #999;
111+
}
112+
}
113+
}
114+
115+
&__body {
116+
display: flex;
117+
gap: 1rem;
118+
flex-wrap: wrap;
119+
align-items: flex-start;
120+
}
121+
122+
&__section {
123+
display: flex;
124+
flex-direction: column;
125+
gap: 0.35rem;
126+
127+
&--disabled {
128+
opacity: 0.35;
129+
pointer-events: none;
130+
}
131+
132+
&-label {
133+
font-size: 0.7rem;
134+
text-transform: uppercase;
135+
letter-spacing: 0.08em;
136+
color: #888;
137+
font-weight: 600;
138+
margin-bottom: 0.15rem;
139+
}
140+
}
141+
142+
&__radio-group {
143+
display: flex;
144+
flex-direction: column;
145+
gap: 0.25rem;
146+
147+
label {
148+
display: flex;
149+
align-items: center;
150+
gap: 0.35rem;
151+
font-size: 0.85rem;
152+
cursor: pointer;
153+
white-space: nowrap;
154+
155+
input[type='radio'] {
156+
margin: 0;
157+
accent-color: #4caf50;
158+
}
159+
}
160+
}
161+
162+
&__checkbox-group {
163+
display: flex;
164+
flex-direction: column;
165+
gap: 0.3rem;
166+
167+
label {
168+
display: flex;
169+
align-items: center;
170+
gap: 0.35rem;
171+
font-size: 0.85rem;
172+
cursor: pointer;
173+
white-space: nowrap;
174+
175+
input[type='checkbox'] {
176+
margin: 0;
177+
accent-color: #4caf50;
178+
}
179+
}
180+
}
181+
}
182+
183+
.time-segment-group {
184+
display: flex;
185+
align-items: center;
186+
gap: 0;
187+
}
188+
189+
.time-segment {
190+
display: flex;
191+
flex-direction: column;
192+
align-items: center;
193+
194+
&__btn {
195+
background: none;
196+
border: none;
197+
width: 26px;
198+
height: 14px;
199+
display: flex;
200+
align-items: center;
201+
justify-content: center;
202+
cursor: pointer;
203+
font-size: 0.55rem;
204+
color: #ccc;
205+
padding: 0;
206+
transition: color 0.1s ease;
207+
208+
&:hover {
209+
color: #888;
210+
}
211+
}
212+
213+
&__input {
214+
width: 26px;
215+
text-align: center;
216+
border: none;
217+
background: transparent;
218+
padding: 0;
219+
font-size: 1.1rem;
220+
font-weight: 600;
221+
color: #333;
222+
outline: none;
223+
224+
&:focus {
225+
background: rgba(0, 0, 0, 0.03);
226+
border-radius: 3px;
227+
}
228+
}
229+
230+
&__separator {
231+
font-size: 1.1rem;
232+
font-weight: 600;
233+
color: #333;
234+
padding: 0;
235+
align-self: center;
236+
}
237+
238+
&__ampm {
239+
font-size: 0.7rem;
240+
font-weight: 600;
241+
color: #333;
242+
text-transform: uppercase;
243+
background: none;
244+
border: none;
245+
cursor: pointer;
246+
padding: 0 0 0 2px;
247+
align-self: center;
248+
vertical-align: super;
249+
margin-top: -0.5rem;
250+
251+
&:hover {
252+
color: #666;
253+
}
254+
}
255+
}

packages/webui/src/client/ui/Settings/Studio/Generic.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'
55
import { useTranslation } from 'react-i18next'
66
import { EditAttribute } from '../../../lib/EditAttribute.js'
77
import { StudioBaselineStatus } from './Baseline.js'
8+
import { TTimerSettingsPanel } from './TTimerSettings.js'
89
import { ShowStyleBaseId } from '@sofie-automation/corelib/dist/dataModel/Ids'
910
import { ShowStyleBases, Studios } from '../../../collections/index.js'
1011
import { useHistory } from 'react-router-dom'
@@ -105,6 +106,8 @@ export function StudioGenericProperties({ studio }: IStudioGenericPropertiesProp
105106

106107
<StudioSettings studio={studio} />
107108

109+
<TTimerSettingsPanel studio={studio} />
110+
108111
<StudioBaselineStatus studioId={studio._id} />
109112
</div>
110113
)

0 commit comments

Comments
 (0)