mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 14:14:17 +00:00
V3 (#657)
* refactor: cleanup routes * style: smaller base font * chore: upgrade dependencies * chore: lock node version to electron * refactor: pass HTTP to integration controller (#652) * refactor: deprecate onair control * refactor: remove playback router * Several project files user folder (#617) * chore: automated screenshots (#667) * feat: app settings (#658) * refactor: remove deprecated event data (#674) * Studio clock (#663) --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Feat: reorder events with alt+ctrl + arrow up/down (#645) * Warning and danger per event (#677) --------- Co-authored-by: Fabian Posenau <fabian@fphome.de> * refactor: stabilise actionHandler (#683) Co-authored-by: Fabian Posenau <fabian@fphome.de> * improvement: hide seconds (#675) * wip: overview (#688) * fix: focus cursor (#695) * refactor: update lower third (#665) * Refactor/time formatting (#696) --------- Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * feat: multiple selection (#703) --------- Co-authored-by: asharonbaltazar <asharonbaltazar@outlook.com> Co-authored-by: Alex <ac@omnivox.dk> * fix: test - go to `Edit mode` befor tying to click `Event options` button (#708) * refactor: runtime service (#715) * fix: issue with loosing cursor position on message (#719) * remove info panel (#721) * Event editor continue (#722) * update API - part (#709) --------- Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * refactor: update timers (#729) * feat: many timers (#706) --------- Co-authored-by: arc-alex <ac@omnivox.dk> * refactor: excel cleanup (#734) * refactor: allow import of blocks and skip import (#735) * Project manager (#697) * refactor: UI for linking events (#763) * upgraded pipeline actions (#777) * Over under (#771) * custom fields (#744) --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Sheets settings (#774) --------- Co-authored-by: arc-alex <ac@omnivox.dk> * style: tweaks to lower thirds (#785) * refactor: delays account for gaps (#784) * refactor: partial state updates (#780) * feat: generate crash report (#787) * Sheet use limited input device auth flow (#782) --------- Co-authored-by: cv <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Custom fields views (#789) * refactor: deprecate presenter and subtitle (#795) * refactor: organise API around resources (#798) --------- Co-authored-by: Bianca Procopio <biancahprocopio@gmail.com> * Time to end (#804) * Skip fixes (#805) * fix: onair derives from playback * Param nav (#822) --------- Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk> * refactor: download files from interface (#831) * Quick options (#814) * End pause (#832) * chore: bump node version in docker (#834) * refactor: follow in run mode (#840) * fix: uncaught error in http integration (#837) * Apply project (#843) Co-authored-by: Matteo Gheza <matteo.gheza07@gmail.com> Co-authored-by: Ary <arylmoraesn@gmail.com> Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk> Co-authored-by: Fabian Posenau <19673098+kellhogs@users.noreply.github.com> Co-authored-by: Fabian Posenau <fabian@fphome.de> Co-authored-by: Alex Rohleder <alexrohleder96@gmail.com> Co-authored-by: asharonbaltazar <asharonbaltazar@outlook.com> Co-authored-by: Bianca Procopio <biancahprocopio@gmail.com> Co-authored-by: Fabian Posenau <fabianpos99+github@gmail.com>
This commit is contained in:
@@ -1,20 +1,21 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { isOntimeEvent, OntimeEvent, SupportedEvent, UserFields } from 'ontime-types';
|
||||
import { getFirstEvent, getLastEvent } from 'ontime-utils';
|
||||
import { CustomField, CustomFields, isOntimeEvent, OntimeEvent, SupportedEvent } from 'ontime-types';
|
||||
import { getFirstEventNormal, getLastEventNormal } from 'ontime-utils';
|
||||
|
||||
import NavigationMenu from '../../common/components/navigation-menu/NavigationMenu';
|
||||
import Empty from '../../common/components/state/Empty';
|
||||
import { getOperatorOptions } from '../../common/components/view-params-editor/constants';
|
||||
import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor';
|
||||
import useFollowComponent from '../../common/hooks/useFollowComponent';
|
||||
import { useOperator } from '../../common/hooks/useSocket';
|
||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||
import useCustomFields from '../../common/hooks-query/useCustomFields';
|
||||
import useProjectData from '../../common/hooks-query/useProjectData';
|
||||
import useRundown from '../../common/hooks-query/useRundown';
|
||||
import useSettings from '../../common/hooks-query/useSettings';
|
||||
import useUserFields from '../../common/hooks-query/useUserFields';
|
||||
import { debounce } from '../../common/utils/debounce';
|
||||
import { isStringBoolean } from '../../common/utils/viewUtils';
|
||||
import { getDefaultFormat } from '../../common/utils/time';
|
||||
import { getPropertyValue, isStringBoolean } from '../viewers/common/viewUtils';
|
||||
|
||||
import EditModal from './edit-modal/EditModal';
|
||||
import FollowButton from './follow-button/FollowButton';
|
||||
@@ -26,15 +27,15 @@ import style from './Operator.module.scss';
|
||||
|
||||
const selectedOffset = 50;
|
||||
|
||||
type TitleFields = Pick<OntimeEvent, 'title' | 'subtitle' | 'presenter'>;
|
||||
type TitleFields = Pick<OntimeEvent, 'title'>;
|
||||
export type EditEvent = Pick<OntimeEvent, 'id' | 'cue'> & { fieldLabel?: string; fieldValue: string };
|
||||
export type PartialEdit = EditEvent & {
|
||||
field: keyof UserFields;
|
||||
field: keyof CustomFields;
|
||||
};
|
||||
|
||||
export default function Operator() {
|
||||
const { data, status } = useRundown();
|
||||
const { data: userFields, status: userFieldsStatus } = useUserFields();
|
||||
const { data: customFields, status: customFieldStatus } = useCustomFields();
|
||||
const { data: projectData, status: projectDataStatus } = useProjectData();
|
||||
|
||||
const timeoutId = useRef<NodeJS.Timeout | null>(null);
|
||||
@@ -51,15 +52,12 @@ export default function Operator() {
|
||||
const scrollRef = useRef<HTMLDivElement | null>(null);
|
||||
const scrollToComponent = useFollowComponent({
|
||||
followRef: selectedRef,
|
||||
scrollRef: scrollRef,
|
||||
scrollRef,
|
||||
doFollow: !lockAutoScroll,
|
||||
topOffset: selectedOffset,
|
||||
});
|
||||
|
||||
// Set window title
|
||||
useEffect(() => {
|
||||
document.title = 'ontime - Operator';
|
||||
}, []);
|
||||
useWindowTitle('Operator');
|
||||
|
||||
// reset scroll if nothing is selected
|
||||
useEffect(() => {
|
||||
@@ -106,7 +104,7 @@ export default function Operator() {
|
||||
|
||||
const handleEdit = useCallback(
|
||||
(event: EditEvent) => {
|
||||
const field = searchParams.get('subscribe') as keyof UserFields | null;
|
||||
const field = searchParams.get('subscribe') as keyof CustomField | null;
|
||||
|
||||
if (field) {
|
||||
setEditEvent({ ...event, field });
|
||||
@@ -115,8 +113,8 @@ export default function Operator() {
|
||||
[searchParams],
|
||||
);
|
||||
|
||||
const missingData = !data || !userFields || !projectData;
|
||||
const isLoading = status === 'pending' || userFieldsStatus === 'pending' || projectDataStatus === 'pending';
|
||||
const missingData = !data || !customFields || !projectData;
|
||||
const isLoading = status === 'pending' || customFieldStatus === 'pending' || projectDataStatus === 'pending';
|
||||
|
||||
if (missingData || isLoading) {
|
||||
return <Empty text='Loading...' />;
|
||||
@@ -124,24 +122,22 @@ export default function Operator() {
|
||||
|
||||
// get fields which the user subscribed to
|
||||
const shouldEdit = searchParams.get('shouldEdit');
|
||||
const subscribe = searchParams.get('subscribe') as keyof UserFields | null;
|
||||
const subscribe = searchParams.get('subscribe') as keyof CustomFields;
|
||||
const canEdit = shouldEdit && subscribe;
|
||||
|
||||
const main = searchParams.get('main') as keyof TitleFields | null;
|
||||
const secondary = searchParams.get('secondary') as keyof TitleFields | null;
|
||||
const subscribedAlias = subscribe ? userFields[subscribe] : '';
|
||||
const showSeconds = isStringBoolean(searchParams.get('showseconds'));
|
||||
const secondary = searchParams.get('secondary');
|
||||
|
||||
const operatorOptions = getOperatorOptions(userFields, settings?.timeFormat ?? '24');
|
||||
const defaultFormat = getDefaultFormat(settings?.timeFormat);
|
||||
const operatorOptions = getOperatorOptions(customFields, defaultFormat);
|
||||
let isPast = Boolean(featureData.selectedEventId);
|
||||
const hidePast = isStringBoolean(searchParams.get('hidepast'));
|
||||
|
||||
const firstEvent = getFirstEvent(data);
|
||||
const lastEvent = getLastEvent(data);
|
||||
const { firstEvent } = getFirstEventNormal(data.rundown, data.order);
|
||||
const { lastEvent } = getLastEventNormal(data.rundown, data.order);
|
||||
|
||||
return (
|
||||
<div className={style.operatorContainer}>
|
||||
<NavigationMenu />
|
||||
<ViewParamsEditor paramFields={operatorOptions} />
|
||||
{editEvent && <EditModal event={editEvent} onClose={() => setEditEvent(null)} />}
|
||||
|
||||
@@ -162,7 +158,8 @@ export default function Operator() {
|
||||
)}
|
||||
|
||||
<div className={style.operatorEvents} onWheel={handleScroll} onTouchMove={handleScroll} ref={scrollRef}>
|
||||
{data.map((entry) => {
|
||||
{data.order.map((eventId) => {
|
||||
const entry = data.rundown[eventId];
|
||||
if (isOntimeEvent(entry)) {
|
||||
const isSelected = featureData.selectedEventId === entry.id;
|
||||
if (isSelected) {
|
||||
@@ -175,8 +172,8 @@ export default function Operator() {
|
||||
}
|
||||
|
||||
const mainField = main ? entry?.[main] || entry.title : entry.title;
|
||||
const secondaryField = secondary ? entry?.[secondary] || entry.subtitle : entry.subtitle;
|
||||
const subscribedData = (subscribe ? entry?.[subscribe] : undefined) || '';
|
||||
const secondaryField = getPropertyValue(entry, secondary) ?? '';
|
||||
const subscribedData = entry.custom[subscribe]?.value;
|
||||
|
||||
return (
|
||||
<OperatorEvent
|
||||
@@ -192,8 +189,7 @@ export default function Operator() {
|
||||
delay={entry.delay}
|
||||
isSelected={isSelected}
|
||||
subscribed={subscribedData}
|
||||
subscribedAlias={subscribedAlias}
|
||||
showSeconds={showSeconds}
|
||||
subscribeLabel={subscribe}
|
||||
isPast={isPast}
|
||||
selectedRef={isSelected ? selectedRef : undefined}
|
||||
onLongPress={canEdit ? handleEdit : () => undefined}
|
||||
|
||||
Reference in New Issue
Block a user