@getontime/cli 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/assets/{Backstage-CAjkmeJm.js → Backstage-BhtXVpms.js} +2 -2
- package/client/assets/Backstage-BhtXVpms.js.br +0 -0
- package/client/assets/Backstage-BhtXVpms.js.gz +0 -0
- package/client/assets/{Backstage-CAjkmeJm.js.map → Backstage-BhtXVpms.js.map} +1 -1
- package/client/assets/{Countdown-ChuA9az_.js → Countdown-NmGi1KMx.js} +2 -2
- package/client/assets/Countdown-NmGi1KMx.js.br +0 -0
- package/client/assets/Countdown-NmGi1KMx.js.gz +0 -0
- package/client/assets/Countdown-NmGi1KMx.js.map +1 -0
- package/client/assets/{CustomTranslationModal-C3R_2T5s.js → CustomTranslationModal-BBNxpds0.js} +2 -2
- package/client/assets/CustomTranslationModal-BBNxpds0.js.br +0 -0
- package/client/assets/CustomTranslationModal-BBNxpds0.js.gz +0 -0
- package/client/assets/{CustomTranslationModal-C3R_2T5s.js.map → CustomTranslationModal-BBNxpds0.js.map} +1 -1
- package/client/assets/{DelayIndicator-vT7n8ypf.js → DelayIndicator-CFCDQ7FN.js} +2 -2
- package/client/assets/DelayIndicator-CFCDQ7FN.js.br +0 -0
- package/client/assets/DelayIndicator-CFCDQ7FN.js.gz +0 -0
- package/client/assets/{DelayIndicator-vT7n8ypf.js.map → DelayIndicator-CFCDQ7FN.js.map} +1 -1
- package/client/assets/{EditorFeatureWrapper-DHfuO3EA.js → EditorFeatureWrapper-D55c8JBz.js} +2 -2
- package/client/assets/EditorFeatureWrapper-D55c8JBz.js.br +0 -0
- package/client/assets/EditorFeatureWrapper-D55c8JBz.js.gz +0 -0
- package/client/assets/{EditorFeatureWrapper-DHfuO3EA.js.map → EditorFeatureWrapper-D55c8JBz.js.map} +1 -1
- package/client/assets/{EditorUtils-Da5ALK1P.js → EditorUtils-CFE106qQ.js} +2 -2
- package/client/assets/EditorUtils-CFE106qQ.js.br +0 -0
- package/client/assets/EditorUtils-CFE106qQ.js.gz +0 -0
- package/client/assets/{EditorUtils-Da5ALK1P.js.map → EditorUtils-CFE106qQ.js.map} +1 -1
- package/client/assets/{Empty-gWT_HMeu.js → Empty-C-JO_XAr.js} +2 -2
- package/client/assets/Empty-C-JO_XAr.js.br +2 -0
- package/client/assets/Empty-C-JO_XAr.js.gz +0 -0
- package/client/assets/{Empty-gWT_HMeu.js.map → Empty-C-JO_XAr.js.map} +1 -1
- package/client/assets/{EmptyPage-Dcbg6rmF.js → EmptyPage-BSzsxpGg.js} +2 -2
- package/client/assets/EmptyPage-BSzsxpGg.js.br +1 -0
- package/client/assets/EmptyPage-BSzsxpGg.js.gz +0 -0
- package/client/assets/{EmptyPage-Dcbg6rmF.js.map → EmptyPage-BSzsxpGg.js.map} +1 -1
- package/client/assets/{FollowButton-CSqJSvix.js → FollowButton-Mox6N4JW.js} +2 -2
- package/client/assets/FollowButton-Mox6N4JW.js.br +0 -0
- package/client/assets/FollowButton-Mox6N4JW.js.gz +0 -0
- package/client/assets/{FollowButton-CSqJSvix.js.map → FollowButton-Mox6N4JW.js.map} +1 -1
- package/client/assets/MessageControlExport-BL2ip9qN.js +2 -0
- package/client/assets/MessageControlExport-BL2ip9qN.js.br +0 -0
- package/client/assets/MessageControlExport-BL2ip9qN.js.gz +0 -0
- package/client/assets/{MessageControlExport-lXK21piH.js.map → MessageControlExport-BL2ip9qN.js.map} +1 -1
- package/client/assets/{MilestoneEditor-Bge8xLrV.js → MilestoneEditor-DcWPGKNK.js} +2 -2
- package/client/assets/MilestoneEditor-DcWPGKNK.js.br +0 -0
- package/client/assets/MilestoneEditor-DcWPGKNK.js.gz +0 -0
- package/client/assets/{MilestoneEditor-Bge8xLrV.js.map → MilestoneEditor-DcWPGKNK.js.map} +1 -1
- package/client/assets/Modal-D3tAPV2u.css +1 -0
- package/client/assets/Modal-D3tAPV2u.css.br +0 -0
- package/client/assets/Modal-D3tAPV2u.css.gz +0 -0
- package/client/assets/Modal-krcwDRb-.js +2 -0
- package/client/assets/Modal-krcwDRb-.js.br +0 -0
- package/client/assets/Modal-krcwDRb-.js.gz +0 -0
- package/client/assets/Modal-krcwDRb-.js.map +1 -0
- package/client/assets/{MultiPartProgressBar-D3jJZjb5.js → MultiPartProgressBar-BXQbpM-j.js} +2 -2
- package/client/assets/MultiPartProgressBar-BXQbpM-j.js.br +0 -0
- package/client/assets/MultiPartProgressBar-BXQbpM-j.js.gz +0 -0
- package/client/assets/{MultiPartProgressBar-D3jJZjb5.js.map → MultiPartProgressBar-BXQbpM-j.js.map} +1 -1
- package/client/assets/{OperatorExport-BUhxjLUx.js → OperatorExport-C50KHBrD.js} +2 -2
- package/client/assets/OperatorExport-C50KHBrD.js.br +0 -0
- package/client/assets/OperatorExport-C50KHBrD.js.gz +0 -0
- package/client/assets/{OperatorExport-BUhxjLUx.js.map → OperatorExport-C50KHBrD.js.map} +1 -1
- package/client/assets/OverviewWrapper-MGJ1uE5W.js +2 -0
- package/client/assets/OverviewWrapper-MGJ1uE5W.js.br +0 -0
- package/client/assets/OverviewWrapper-MGJ1uE5W.js.gz +0 -0
- package/client/assets/OverviewWrapper-MGJ1uE5W.js.map +1 -0
- package/client/assets/{ProjectInfo-z4k3cipS.js → ProjectInfo-CJ-GLvVG.js} +2 -2
- package/client/assets/ProjectInfo-CJ-GLvVG.js.br +0 -0
- package/client/assets/ProjectInfo-CJ-GLvVG.js.gz +0 -0
- package/client/assets/{ProjectInfo-z4k3cipS.js.map → ProjectInfo-CJ-GLvVG.js.map} +1 -1
- package/client/assets/{ProtectRoute-CrcWfOlG.js → ProtectRoute-DJ9xZnPI.js} +2 -2
- package/client/assets/ProtectRoute-DJ9xZnPI.js.br +0 -0
- package/client/assets/ProtectRoute-DJ9xZnPI.js.gz +0 -0
- package/client/assets/{ProtectRoute-CrcWfOlG.js.map → ProtectRoute-DJ9xZnPI.js.map} +1 -1
- package/client/assets/{ProtectedCuesheet-Deo4Aw6f.js → ProtectedCuesheet-B8tg6Mmo.js} +2 -2
- package/client/assets/ProtectedCuesheet-B8tg6Mmo.js.br +0 -0
- package/client/assets/ProtectedCuesheet-B8tg6Mmo.js.gz +0 -0
- package/client/assets/{ProtectedCuesheet-Deo4Aw6f.js.map → ProtectedCuesheet-B8tg6Mmo.js.map} +1 -1
- package/client/assets/ProtectedEditor-Bl4wV72N.js +3 -0
- package/client/assets/ProtectedEditor-Bl4wV72N.js.br +0 -0
- package/client/assets/ProtectedEditor-Bl4wV72N.js.gz +0 -0
- package/client/assets/ProtectedEditor-Bl4wV72N.js.map +1 -0
- package/client/assets/{RundownEntry-D61IqkXb.js → RundownEntry-D9tXNXPy.js} +2 -2
- package/client/assets/RundownEntry-D9tXNXPy.js.br +0 -0
- package/client/assets/RundownEntry-D9tXNXPy.js.gz +0 -0
- package/client/assets/{RundownEntry-D61IqkXb.js.map → RundownEntry-D9tXNXPy.js.map} +1 -1
- package/client/assets/RundownExport-D6uAmFbb.js +3 -0
- package/client/assets/RundownExport-D6uAmFbb.js.br +0 -0
- package/client/assets/RundownExport-D6uAmFbb.js.gz +0 -0
- package/client/assets/RundownExport-D6uAmFbb.js.map +1 -0
- package/client/assets/{Select-CedN80WS.js → Select-BLA-yQMq.js} +2 -2
- package/client/assets/Select-BLA-yQMq.js.br +0 -0
- package/client/assets/Select-BLA-yQMq.js.gz +0 -0
- package/client/assets/{Select-CedN80WS.js.map → Select-BLA-yQMq.js.map} +1 -1
- package/client/assets/{Studio-DUzPBS6P.js → Studio-DbP92DTf.js} +2 -2
- package/client/assets/Studio-DbP92DTf.js.br +0 -0
- package/client/assets/Studio-DbP92DTf.js.gz +0 -0
- package/client/assets/{Studio-DUzPBS6P.js.map → Studio-DbP92DTf.js.map} +1 -1
- package/client/assets/{StyleEditor-D2z65PB7.js → StyleEditor-DNjZ46Qf.js} +2 -2
- package/client/assets/StyleEditor-DNjZ46Qf.js.br +0 -0
- package/client/assets/StyleEditor-DNjZ46Qf.js.gz +0 -0
- package/client/assets/{StyleEditor-D2z65PB7.js.map → StyleEditor-DNjZ46Qf.js.map} +1 -1
- package/client/assets/{SuperscriptTime-CIrcMcyg.js → SuperscriptTime-C8ypTVpH.js} +2 -2
- package/client/assets/SuperscriptTime-C8ypTVpH.js.br +0 -0
- package/client/assets/SuperscriptTime-C8ypTVpH.js.gz +0 -0
- package/client/assets/{SuperscriptTime-CIrcMcyg.js.map → SuperscriptTime-C8ypTVpH.js.map} +1 -1
- package/client/assets/{TimeElements-CALNfv6u.js → TimeElements-DlEBhXe0.js} +2 -2
- package/client/assets/TimeElements-DlEBhXe0.js.br +0 -0
- package/client/assets/TimeElements-DlEBhXe0.js.gz +0 -0
- package/client/assets/{TimeElements-CALNfv6u.js.map → TimeElements-DlEBhXe0.js.map} +1 -1
- package/client/assets/{TimeInput-Dg1naiy3.js → TimeInput-DU09ewqh.js} +2 -2
- package/client/assets/TimeInput-DU09ewqh.js.br +0 -0
- package/client/assets/TimeInput-DU09ewqh.js.gz +0 -0
- package/client/assets/{TimeInput-Dg1naiy3.js.map → TimeInput-DU09ewqh.js.map} +1 -1
- package/client/assets/{TimelinePage-Cwm0svjN.js → TimelinePage-DTwqRihn.js} +2 -2
- package/client/assets/TimelinePage-DTwqRihn.js.br +0 -0
- package/client/assets/TimelinePage-DTwqRihn.js.gz +0 -0
- package/client/assets/{TimelinePage-Cwm0svjN.js.map → TimelinePage-DTwqRihn.js.map} +1 -1
- package/client/assets/{Timer-BvEmZbmF.css → Timer-B7nk3TMf.css} +1 -1
- package/client/assets/Timer-B7nk3TMf.css.br +0 -0
- package/client/assets/Timer-B7nk3TMf.css.gz +0 -0
- package/client/assets/{Timer-BVXskRjc.js → Timer-jjWAunJc.js} +2 -2
- package/client/assets/Timer-jjWAunJc.js.br +0 -0
- package/client/assets/Timer-jjWAunJc.js.gz +0 -0
- package/client/assets/{Timer-BVXskRjc.js.map → Timer-jjWAunJc.js.map} +1 -1
- package/client/assets/TimerControlExport-i0ZDpUx7.js +2 -0
- package/client/assets/TimerControlExport-i0ZDpUx7.js.br +0 -0
- package/client/assets/TimerControlExport-i0ZDpUx7.js.gz +0 -0
- package/client/assets/{TimerControlExport-C8ECtLBd.js.map → TimerControlExport-i0ZDpUx7.js.map} +1 -1
- package/client/assets/{TitleCard-CZl9wSHS.js → TitleCard-BgOtucv6.js} +2 -2
- package/client/assets/TitleCard-BgOtucv6.js.br +0 -0
- package/client/assets/TitleCard-BgOtucv6.js.gz +0 -0
- package/client/assets/{TitleCard-CZl9wSHS.js.map → TitleCard-BgOtucv6.js.map} +1 -1
- package/client/assets/{Tooltip-D9XRnwOW.js → Tooltip-C0rGHLsB.js} +2 -2
- package/client/assets/Tooltip-C0rGHLsB.js.br +0 -0
- package/client/assets/Tooltip-C0rGHLsB.js.gz +0 -0
- package/client/assets/{Tooltip-D9XRnwOW.js.map → Tooltip-C0rGHLsB.js.map} +1 -1
- package/client/assets/{ViewLogo-_3Z1hIHi.js → ViewLogo--9miplQv.js} +2 -2
- package/client/assets/ViewLogo--9miplQv.js.br +0 -0
- package/client/assets/ViewLogo--9miplQv.js.gz +0 -0
- package/client/assets/{ViewLogo-_3Z1hIHi.js.map → ViewLogo--9miplQv.js.map} +1 -1
- package/client/assets/{ViewParamsEditor-Bca1TIDW.js → ViewParamsEditor-BFu_0oIb.js} +2 -2
- package/client/assets/ViewParamsEditor-BFu_0oIb.js.br +0 -0
- package/client/assets/ViewParamsEditor-BFu_0oIb.js.gz +0 -0
- package/client/assets/{ViewParamsEditor-Bca1TIDW.js.map → ViewParamsEditor-BFu_0oIb.js.map} +1 -1
- package/client/assets/{dateConfig-DRQGMWDF.js → dateConfig-WYqMzV9D.js} +2 -2
- package/client/assets/dateConfig-WYqMzV9D.js.br +0 -0
- package/client/assets/dateConfig-WYqMzV9D.js.gz +0 -0
- package/client/assets/{dateConfig-DRQGMWDF.js.map → dateConfig-WYqMzV9D.js.map} +1 -1
- package/client/assets/{editorSettings-BU0pTMSY.js → editorSettings-CCHx-wCx.js} +2 -2
- package/client/assets/editorSettings-CCHx-wCx.js.br +0 -0
- package/client/assets/editorSettings-CCHx-wCx.js.gz +0 -0
- package/client/assets/{editorSettings-BU0pTMSY.js.map → editorSettings-CCHx-wCx.js.map} +1 -1
- package/client/assets/{getProgress-Cw79NL_O.js → getProgress-B94Ieskb.js} +2 -2
- package/client/assets/getProgress-B94Ieskb.js.br +0 -0
- package/client/assets/getProgress-B94Ieskb.js.gz +0 -0
- package/client/assets/{getProgress-Cw79NL_O.js.map → getProgress-B94Ieskb.js.map} +1 -1
- package/client/assets/{index-BQEUaoAf.js → index-njXwwjfn.js} +3 -3
- package/client/assets/index-njXwwjfn.js.br +0 -0
- package/client/assets/index-njXwwjfn.js.gz +0 -0
- package/client/assets/{index-BQEUaoAf.js.map → index-njXwwjfn.js.map} +1 -1
- package/client/assets/{offset-DJAHqjFW.js → offset-D1q-72D-.js} +2 -2
- package/client/assets/offset-D1q-72D-.js.br +0 -0
- package/client/assets/offset-D1q-72D-.js.gz +0 -0
- package/client/assets/{offset-DJAHqjFW.js.map → offset-D1q-72D-.js.map} +1 -1
- package/client/assets/{parseUserTime-BeTKj08M.js → parseUserTime-Bc1pSJR2.js} +2 -2
- package/client/assets/parseUserTime-Bc1pSJR2.js.br +0 -0
- package/client/assets/parseUserTime-Bc1pSJR2.js.gz +0 -0
- package/client/assets/{parseUserTime-BeTKj08M.js.map → parseUserTime-Bc1pSJR2.js.map} +1 -1
- package/client/assets/{playbackstate-B_khF6xU.js → playbackstate-BpzbtG9F.js} +2 -2
- package/client/assets/playbackstate-BpzbtG9F.js.br +0 -0
- package/client/assets/playbackstate-BpzbtG9F.js.gz +0 -0
- package/client/assets/{playbackstate-B_khF6xU.js.map → playbackstate-BpzbtG9F.js.map} +1 -1
- package/client/assets/{presentation.utils-KwY-ACf7.js → presentation.utils-B2baBe3j.js} +2 -2
- package/client/assets/presentation.utils-B2baBe3j.js.br +0 -0
- package/client/assets/presentation.utils-B2baBe3j.js.gz +0 -0
- package/client/assets/{presentation.utils-KwY-ACf7.js.map → presentation.utils-B2baBe3j.js.map} +1 -1
- package/client/assets/{rundownUtils-BZHazkXR.js → rundownUtils-H6xvQyre.js} +2 -2
- package/client/assets/rundownUtils-H6xvQyre.js.br +0 -0
- package/client/assets/rundownUtils-H6xvQyre.js.gz +0 -0
- package/client/assets/{rundownUtils-BZHazkXR.js.map → rundownUtils-H6xvQyre.js.map} +1 -1
- package/client/assets/{useCustomFields-DqCYz8Kt.js → useCustomFields-Da0Li7nQ.js} +2 -2
- package/client/assets/useCustomFields-Da0Li7nQ.js.br +0 -0
- package/client/assets/useCustomFields-Da0Li7nQ.js.gz +0 -0
- package/client/assets/{useCustomFields-DqCYz8Kt.js.map → useCustomFields-Da0Li7nQ.js.map} +1 -1
- package/client/assets/{useFollowComponent-Ctfhf2or.js → useFollowComponent-Qo3FobyV.js} +2 -2
- package/client/assets/useFollowComponent-Qo3FobyV.js.br +0 -0
- package/client/assets/useFollowComponent-Qo3FobyV.js.gz +0 -0
- package/client/assets/{useFollowComponent-Ctfhf2or.js.map → useFollowComponent-Qo3FobyV.js.map} +1 -1
- package/client/assets/{useProjectData-C1hVamxc.js → useProjectData-DW06zQvF.js} +2 -2
- package/client/assets/useProjectData-DW06zQvF.js.br +0 -0
- package/client/assets/useProjectData-DW06zQvF.js.gz +0 -0
- package/client/assets/{useProjectData-C1hVamxc.js.map → useProjectData-DW06zQvF.js.map} +1 -1
- package/client/assets/{useReport-B4dMYcNL.js → useReport-DhFY2L8v.js} +2 -2
- package/client/assets/useReport-DhFY2L8v.js.br +0 -0
- package/client/assets/useReport-DhFY2L8v.js.gz +0 -0
- package/client/assets/{useReport-B4dMYcNL.js.map → useReport-DhFY2L8v.js.map} +1 -1
- package/client/assets/useRundown-ihoU8qBi.js +2 -0
- package/client/assets/useRundown-ihoU8qBi.js.br +0 -0
- package/client/assets/useRundown-ihoU8qBi.js.gz +0 -0
- package/client/assets/useRundown-ihoU8qBi.js.map +1 -0
- package/client/assets/{useWindowTitle-DqdFTWns.js → useWindowTitle-B2UzPuki.js} +2 -2
- package/client/assets/useWindowTitle-B2UzPuki.js.br +0 -0
- package/client/assets/useWindowTitle-B2UzPuki.js.gz +0 -0
- package/client/assets/{useWindowTitle-DqdFTWns.js.map → useWindowTitle-B2UzPuki.js.map} +1 -1
- package/client/assets/{validateEvent-P9sf7C10.js → validateEvent-BJMwP_mq.js} +2 -2
- package/client/assets/validateEvent-BJMwP_mq.js.br +0 -0
- package/client/assets/validateEvent-BJMwP_mq.js.gz +0 -0
- package/client/assets/{validateEvent-P9sf7C10.js.map → validateEvent-BJMwP_mq.js.map} +1 -1
- package/client/assets/{vendor-CCiSQ9k9.js → vendor-9UkPSc5K.js} +3 -3
- package/client/assets/vendor-9UkPSc5K.js.br +0 -0
- package/client/assets/vendor-9UkPSc5K.js.gz +0 -0
- package/client/assets/{vendor-CCiSQ9k9.js.map → vendor-9UkPSc5K.js.map} +1 -1
- package/client/assets/{viewLoader.utils-CmM-4-pk.js → viewLoader.utils-DQGhrjSp.js} +2 -2
- package/client/assets/viewLoader.utils-DQGhrjSp.js.br +0 -0
- package/client/assets/viewLoader.utils-DQGhrjSp.js.gz +0 -0
- package/client/assets/{viewLoader.utils-CmM-4-pk.js.map → viewLoader.utils-DQGhrjSp.js.map} +1 -1
- package/client/index.html +2 -2
- package/package.json +1 -1
- package/server/index.cjs +82 -82
- package/client/assets/Backstage-CAjkmeJm.js.br +0 -0
- package/client/assets/Backstage-CAjkmeJm.js.gz +0 -0
- package/client/assets/Countdown-ChuA9az_.js.br +0 -0
- package/client/assets/Countdown-ChuA9az_.js.gz +0 -0
- package/client/assets/Countdown-ChuA9az_.js.map +0 -1
- package/client/assets/CustomTranslationModal-C3R_2T5s.js.br +0 -0
- package/client/assets/CustomTranslationModal-C3R_2T5s.js.gz +0 -0
- package/client/assets/DelayIndicator-vT7n8ypf.js.br +0 -0
- package/client/assets/DelayIndicator-vT7n8ypf.js.gz +0 -0
- package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.br +0 -0
- package/client/assets/EditorFeatureWrapper-DHfuO3EA.js.gz +0 -0
- package/client/assets/EditorUtils-Da5ALK1P.js.br +0 -0
- package/client/assets/EditorUtils-Da5ALK1P.js.gz +0 -0
- package/client/assets/Empty-gWT_HMeu.js.br +0 -0
- package/client/assets/Empty-gWT_HMeu.js.gz +0 -0
- package/client/assets/EmptyPage-Dcbg6rmF.js.br +0 -0
- package/client/assets/EmptyPage-Dcbg6rmF.js.gz +0 -0
- package/client/assets/FollowButton-CSqJSvix.js.br +0 -0
- package/client/assets/FollowButton-CSqJSvix.js.gz +0 -0
- package/client/assets/MessageControlExport-lXK21piH.js +0 -2
- package/client/assets/MessageControlExport-lXK21piH.js.br +0 -0
- package/client/assets/MessageControlExport-lXK21piH.js.gz +0 -0
- package/client/assets/MilestoneEditor-Bge8xLrV.js.br +0 -0
- package/client/assets/MilestoneEditor-Bge8xLrV.js.gz +0 -0
- package/client/assets/Modal-BgJx3SNK.css +0 -1
- package/client/assets/Modal-BgJx3SNK.css.br +0 -0
- package/client/assets/Modal-BgJx3SNK.css.gz +0 -0
- package/client/assets/Modal-C2sFA0zf.js +0 -2
- package/client/assets/Modal-C2sFA0zf.js.br +0 -0
- package/client/assets/Modal-C2sFA0zf.js.gz +0 -0
- package/client/assets/Modal-C2sFA0zf.js.map +0 -1
- package/client/assets/MultiPartProgressBar-D3jJZjb5.js.br +0 -0
- package/client/assets/MultiPartProgressBar-D3jJZjb5.js.gz +0 -0
- package/client/assets/OperatorExport-BUhxjLUx.js.br +0 -0
- package/client/assets/OperatorExport-BUhxjLUx.js.gz +0 -0
- package/client/assets/OverviewWrapper-BveJ6GjK.js +0 -2
- package/client/assets/OverviewWrapper-BveJ6GjK.js.br +0 -0
- package/client/assets/OverviewWrapper-BveJ6GjK.js.gz +0 -0
- package/client/assets/OverviewWrapper-BveJ6GjK.js.map +0 -1
- package/client/assets/ProjectInfo-z4k3cipS.js.br +0 -0
- package/client/assets/ProjectInfo-z4k3cipS.js.gz +0 -0
- package/client/assets/ProtectRoute-CrcWfOlG.js.br +0 -0
- package/client/assets/ProtectRoute-CrcWfOlG.js.gz +0 -0
- package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.br +0 -0
- package/client/assets/ProtectedCuesheet-Deo4Aw6f.js.gz +0 -0
- package/client/assets/ProtectedEditor-C_SYWpL2.js +0 -3
- package/client/assets/ProtectedEditor-C_SYWpL2.js.br +0 -0
- package/client/assets/ProtectedEditor-C_SYWpL2.js.gz +0 -0
- package/client/assets/ProtectedEditor-C_SYWpL2.js.map +0 -1
- package/client/assets/RundownEntry-D61IqkXb.js.br +0 -0
- package/client/assets/RundownEntry-D61IqkXb.js.gz +0 -0
- package/client/assets/RundownExport-C6YhMGOC.js +0 -3
- package/client/assets/RundownExport-C6YhMGOC.js.br +0 -0
- package/client/assets/RundownExport-C6YhMGOC.js.gz +0 -0
- package/client/assets/RundownExport-C6YhMGOC.js.map +0 -1
- package/client/assets/Select-CedN80WS.js.br +0 -0
- package/client/assets/Select-CedN80WS.js.gz +0 -0
- package/client/assets/Studio-DUzPBS6P.js.br +0 -0
- package/client/assets/Studio-DUzPBS6P.js.gz +0 -0
- package/client/assets/StyleEditor-D2z65PB7.js.br +0 -0
- package/client/assets/StyleEditor-D2z65PB7.js.gz +0 -0
- package/client/assets/SuperscriptTime-CIrcMcyg.js.br +0 -0
- package/client/assets/SuperscriptTime-CIrcMcyg.js.gz +0 -0
- package/client/assets/TimeElements-CALNfv6u.js.br +0 -0
- package/client/assets/TimeElements-CALNfv6u.js.gz +0 -0
- package/client/assets/TimeInput-Dg1naiy3.js.br +0 -0
- package/client/assets/TimeInput-Dg1naiy3.js.gz +0 -0
- package/client/assets/TimelinePage-Cwm0svjN.js.br +0 -0
- package/client/assets/TimelinePage-Cwm0svjN.js.gz +0 -0
- package/client/assets/Timer-BVXskRjc.js.br +0 -0
- package/client/assets/Timer-BVXskRjc.js.gz +0 -0
- package/client/assets/Timer-BvEmZbmF.css.br +0 -0
- package/client/assets/Timer-BvEmZbmF.css.gz +0 -0
- package/client/assets/TimerControlExport-C8ECtLBd.js +0 -2
- package/client/assets/TimerControlExport-C8ECtLBd.js.br +0 -0
- package/client/assets/TimerControlExport-C8ECtLBd.js.gz +0 -0
- package/client/assets/TitleCard-CZl9wSHS.js.br +0 -0
- package/client/assets/TitleCard-CZl9wSHS.js.gz +0 -0
- package/client/assets/Tooltip-D9XRnwOW.js.br +0 -4
- package/client/assets/Tooltip-D9XRnwOW.js.gz +0 -0
- package/client/assets/ViewLogo-_3Z1hIHi.js.br +0 -0
- package/client/assets/ViewLogo-_3Z1hIHi.js.gz +0 -0
- package/client/assets/ViewParamsEditor-Bca1TIDW.js.br +0 -0
- package/client/assets/ViewParamsEditor-Bca1TIDW.js.gz +0 -0
- package/client/assets/dateConfig-DRQGMWDF.js.br +0 -0
- package/client/assets/dateConfig-DRQGMWDF.js.gz +0 -0
- package/client/assets/editorSettings-BU0pTMSY.js.br +0 -0
- package/client/assets/editorSettings-BU0pTMSY.js.gz +0 -0
- package/client/assets/getProgress-Cw79NL_O.js.br +0 -0
- package/client/assets/getProgress-Cw79NL_O.js.gz +0 -0
- package/client/assets/index-BQEUaoAf.js.br +0 -0
- package/client/assets/index-BQEUaoAf.js.gz +0 -0
- package/client/assets/offset-DJAHqjFW.js.br +0 -0
- package/client/assets/offset-DJAHqjFW.js.gz +0 -0
- package/client/assets/parseUserTime-BeTKj08M.js.br +0 -0
- package/client/assets/parseUserTime-BeTKj08M.js.gz +0 -0
- package/client/assets/playbackstate-B_khF6xU.js.br +0 -0
- package/client/assets/playbackstate-B_khF6xU.js.gz +0 -0
- package/client/assets/presentation.utils-KwY-ACf7.js.br +0 -0
- package/client/assets/presentation.utils-KwY-ACf7.js.gz +0 -0
- package/client/assets/rundownUtils-BZHazkXR.js.br +0 -0
- package/client/assets/rundownUtils-BZHazkXR.js.gz +0 -0
- package/client/assets/useCustomFields-DqCYz8Kt.js.br +0 -0
- package/client/assets/useCustomFields-DqCYz8Kt.js.gz +0 -0
- package/client/assets/useFollowComponent-Ctfhf2or.js.br +0 -0
- package/client/assets/useFollowComponent-Ctfhf2or.js.gz +0 -0
- package/client/assets/useProjectData-C1hVamxc.js.br +0 -0
- package/client/assets/useProjectData-C1hVamxc.js.gz +0 -0
- package/client/assets/useReport-B4dMYcNL.js.br +0 -0
- package/client/assets/useReport-B4dMYcNL.js.gz +0 -0
- package/client/assets/useRundown-BfpjcCEJ.js +0 -2
- package/client/assets/useRundown-BfpjcCEJ.js.br +0 -0
- package/client/assets/useRundown-BfpjcCEJ.js.gz +0 -0
- package/client/assets/useRundown-BfpjcCEJ.js.map +0 -1
- package/client/assets/useWindowTitle-DqdFTWns.js.br +0 -0
- package/client/assets/useWindowTitle-DqdFTWns.js.gz +0 -0
- package/client/assets/validateEvent-P9sf7C10.js.br +0 -3
- package/client/assets/validateEvent-P9sf7C10.js.gz +0 -0
- package/client/assets/vendor-CCiSQ9k9.js.br +0 -0
- package/client/assets/vendor-CCiSQ9k9.js.gz +0 -0
- package/client/assets/viewLoader.utils-CmM-4-pk.js.br +0 -0
- package/client/assets/viewLoader.utils-CmM-4-pk.js.gz +0 -0
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewParamsEditor-Bca1TIDW.js","sources":["../../src/common/components/view-params-editor/viewParams.utils.ts","../../src/common/components/view-params-editor/ViewParamsPresets.tsx","../../src/common/components/view-params-editor/constants.ts","../../src/features/viewers/common/viewUtils.ts","../../src/common/components/view-params-editor/InlineColourPicker.tsx","../../src/common/components/view-params-editor/ParamInput.tsx","../../src/common/components/view-params-editor/ViewParamsSection.tsx","../../src/common/components/view-params-editor/ViewParamsEditor.tsx"],"sourcesContent":["import type { CustomFields, ProjectData } from 'ontime-types';\n\nimport type { SelectOption } from '../select/Select';\n\nimport type { MultiselectOption, ViewOption } from './viewParams.types';\n\n/**\n * Creates a list of custom fields for a select\n * Filters out image type custom fields\n */\nexport function makeOptionsFromCustomFields(\n customFields: CustomFields,\n additionalOptions: SelectOption[] = [],\n filterImageType = true,\n): SelectOption[] {\n const options: SelectOption[] = [...additionalOptions];\n\n // Add custom fields first\n for (const [key, value] of Object.entries(customFields)) {\n if (filterImageType && value.type === 'image') {\n continue;\n }\n\n options.push({\n value: `custom-${key}`,\n label: `Custom: ${value.label}`,\n });\n }\n\n return options;\n}\n\n/**\n * Creates data for a multiselect component from custom fields\n * Filters out image type custom fields\n */\nexport function makeCustomFieldSelectOptions(customFields: CustomFields, filterImageType = true): MultiselectOption[] {\n const options: MultiselectOption[] = [];\n\n // Add custom fields first\n for (const [key, value] of Object.entries(customFields)) {\n if (filterImageType && value.type === 'image') {\n continue;\n }\n\n options.push({\n value: key,\n label: value.label,\n colour: value.colour || 'transparent',\n });\n }\n\n return options;\n}\n\n/**\n * Creates data for a select element that displays project custom data\n */\nexport function makeProjectDataOptions(\n projectData: ProjectData,\n additionalOptions: SelectOption[] = [],\n): SelectOption[] {\n const generatedOptions = projectData.custom.map((entry, index) => {\n return {\n value: `${index}-${entry.title}`,\n label: entry.title,\n };\n });\n\n return [...additionalOptions, ...generatedOptions];\n}\n\ntype ViewParamsObj = { [key: string]: string | FormDataEntryValue };\n\n/**\n * Utility remove the # character from a hex string\n */\nfunction sanitiseColour(colour: string) {\n if (colour.startsWith('#')) {\n return colour.substring(1);\n }\n return colour;\n}\n\ntype FieldMetadata = {\n defaultValues: Record<string, string>;\n colorFields: Set<string>;\n booleanFields: Set<string>;\n isPersistedField: Set<string>;\n persistedValues: Record<string, string[]>;\n};\n\n/**\n * Utility collects metadata about fields from view options\n * - where are the default values\n * - which fields are colours\n * - which fields are persisted\n */\nfunction collectFieldMetadata(paramFields: ViewOption[]): FieldMetadata {\n const metadata: FieldMetadata = {\n defaultValues: {},\n colorFields: new Set(),\n booleanFields: new Set(),\n isPersistedField: new Set(),\n persistedValues: {},\n };\n\n paramFields.forEach((section) => {\n section.options.forEach((option) => {\n if (option.type === 'persist') {\n metadata.isPersistedField.add(option.id);\n if (option.values) {\n metadata.persistedValues[option.id] = option.values;\n }\n } else {\n metadata.defaultValues[option.id] = String(option.defaultValue);\n }\n\n if (option.type === 'colour') {\n metadata.colorFields.add(option.id);\n } else if (option.type === 'boolean') {\n metadata.booleanFields.add(option.id);\n }\n });\n });\n\n return metadata;\n}\n\n/**\n * Makes a new URLSearchParams object from the given params object\n * @param paramsObj - The object containing parameters to be converted\n * @param paramFields - The view options that define the parameters\n * @returns A new URLSearchParams object with the parameters\n */\nexport function getURLSearchParamsFromObj(paramsObj: ViewParamsObj, paramFields: ViewOption[]) {\n const newSearchParams = new URLSearchParams();\n const addedPairs = new Set<string>();\n const metadata = collectFieldMetadata(paramFields);\n\n // Utility function to safely add params without duplicates\n const addUniqueParam = (id: string, value: string) => {\n const pair = `${id}:${value}`;\n if (!addedPairs.has(pair)) {\n addedPairs.add(pair);\n newSearchParams.append(id, value);\n }\n };\n\n // First add all persisted values\n Object.entries(metadata.persistedValues).forEach(([id, values]) => {\n values.forEach((value) => {\n if (value) {\n addUniqueParam(id, value);\n }\n });\n });\n\n // Then process user-provided values\n Object.entries(paramsObj).forEach(([id, value]) => {\n if (typeof value === 'string' && value.length) {\n // For persisted fields, clear existing values before adding new ones\n if (metadata.isPersistedField.has(id)) {\n // Clear tracking of previous values for this field\n Array.from(addedPairs).forEach((pair) => {\n if (pair.startsWith(`${id}:`)) {\n addedPairs.delete(pair);\n }\n });\n newSearchParams.delete(id);\n }\n\n // Process and add new values\n value.split(',').forEach((v) => {\n // some field types need extra processing\n const processedValue = (() => {\n if (metadata.colorFields.has(id)) {\n return sanitiseColour(v);\n }\n if (metadata.booleanFields.has(id)) {\n return v === 'on' ? 'true' : 'false';\n }\n return v;\n })();\n if (metadata.isPersistedField.has(id) || metadata.defaultValues[id] !== processedValue) {\n addUniqueParam(id, processedValue);\n }\n });\n }\n });\n\n return newSearchParams;\n}\n","import { useSearchParams } from 'react-router';\nimport { OntimeView, URLPreset } from 'ontime-types';\n\nimport { useViewUrlPresets } from '../../hooks-query/useUrlPresets';\nimport { cx } from '../../utils/styleUtils';\nimport Button from '../buttons/Button';\n\nimport style from './ViewParamsPresets.module.scss';\n\n/**\n * Shows a list of presets for the current view\n */\nexport function ViewParamsPresets({ target }: { target: OntimeView }) {\n const { viewPresets } = useViewUrlPresets(target);\n const [searchParams, setSearchParams] = useSearchParams();\n\n const handleRecall = (preset: URLPreset) => {\n const newSearch = new URLSearchParams(preset.search);\n newSearch.set('alias', preset.alias);\n setSearchParams(newSearch);\n };\n\n if (viewPresets.length === 0) {\n return null;\n }\n\n return (\n <div className={style.presetSection}>\n {viewPresets.map((preset) => {\n const active = searchParams.get('alias') === preset.alias;\n return (\n <div key={preset.alias} className={cx([style.preset, active && style.active])}>\n <div>{preset.alias}</div>\n <Button\n variant={active ? 'ghosted' : 'subtle-white'}\n onClick={() => handleRecall(preset)}\n disabled={active}\n className={style.presetActions}\n >\n {active ? 'Applied' : 'Apply'}\n </Button>\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * Gathers possible titles for view options\n */\nexport enum OptionTitle {\n ClockOptions = 'Clock Options',\n TimerOptions = 'Timer Options',\n DataSources = 'Data sources',\n ElementVisibility = 'Element visibility',\n BehaviourOptions = 'View behaviour',\n StyleOverride = 'View style override',\n Animation = 'View animation',\n Schedule = 'Schedule options',\n\n /** rendered as hidden inputs */\n Hidden = 'Hidden options',\n}\n","import { MaybeNumber, MaybeString, OntimeEvent, TimerState, TimerType } from 'ontime-types';\nimport { MILLIS_PER_MINUTE, MILLIS_PER_SECOND, millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';\n\nimport { timerPlaceholder, timerPlaceholderMin } from '../../../common/utils/styleUtils';\nimport { formatTime } from '../../../common/utils/time';\n\n/**\n * Gathers all options that affect which timer is displayed and selects the correct data source to display\n * it also handles edge cases such as freezing on end\n */\nexport function getTimerByType(\n freezeEnd: boolean,\n timerTypeNow: TimerType,\n countToEndNow: boolean,\n clock: number,\n timerObject: Pick<TimerState, 'current' | 'elapsed'>,\n timerTypeOverride?: TimerType,\n): number | null {\n if (!timerObject) {\n return null;\n }\n\n const viewTimerType = timerTypeOverride ?? timerTypeNow;\n\n if (countToEndNow) {\n if (timerObject.current === null) {\n return null;\n }\n return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;\n }\n\n switch (viewTimerType) {\n case TimerType.CountDown:\n if (timerObject.current === null) {\n return null;\n }\n return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;\n case TimerType.CountUp:\n return Math.abs(timerObject.elapsed ?? 0);\n case TimerType.Clock:\n return clock;\n case TimerType.None:\n return null;\n default: {\n viewTimerType satisfies never;\n return null;\n }\n }\n}\n\n/**\n * Parses a string to semantically verify if it represents a true value\n * Used in the context of parsing search params and local storage items which can be strings or null\n */\nexport function isStringBoolean(text: string | null) {\n if (text === null) {\n return false;\n }\n return text?.toLowerCase() === 'true' || text === '1';\n}\n\n/**\n * Prepares a colour string for use in views\n * Colours in params do not have the #prefix\n */\nexport function makeColourString(hex: string | null): string | undefined {\n if (!hex) {\n return undefined;\n }\n // ensure the hex starts with a #\n return hex.startsWith('#') ? hex : `#${hex}`;\n}\n\n/**\n * Retrieves a dynamic property from an event\n * Considers custom fields\n */\nexport function getPropertyValue(event: OntimeEvent | null, property: MaybeString): string | undefined {\n if (!event || typeof property !== 'string' || property === 'none') {\n return undefined;\n }\n\n if (property.startsWith('custom-')) {\n const field = property.split('custom-')[1];\n return event.custom?.[field];\n }\n\n return event[property as keyof OntimeEvent] as string;\n}\n\ntype FormattingOptions = {\n removeSeconds: boolean;\n removeLeadingZero: boolean;\n};\n\nexport function getFormattedTimer(\n timer: MaybeNumber,\n timerType: TimerType,\n localisedMinutes: string,\n options: FormattingOptions,\n): string {\n if (timer == null || timerType === TimerType.None) {\n return options.removeSeconds ? timerPlaceholderMin : timerPlaceholder;\n }\n\n if (timerType === TimerType.Clock) {\n return formatTime(timer);\n }\n\n let timeToParse = timer;\n if (options.removeSeconds) {\n const isNegative = timeToParse < -MILLIS_PER_SECOND && timerType !== TimerType.CountUp;\n if (isNegative) {\n // in negative numbers, we need to round down\n timeToParse -= MILLIS_PER_MINUTE;\n }\n }\n\n let display = millisToString(timeToParse, { direction: timerType });\n if (options.removeLeadingZero) {\n display = removeLeadingZero(display);\n }\n\n if (options.removeSeconds) {\n display = formatDisplayWithMinutes(display, localisedMinutes);\n }\n return display;\n}\n\nfunction formatDisplayWithMinutes(display: string, localisedMinutes: string): string {\n display = removeSeconds(display);\n return display.length < 3 ? `${display} ${localisedMinutes}` : display;\n}\n","import { useEffect, useState } from 'react';\n\nimport SwatchPicker from '../input/colour-input/SwatchPicker';\n\nimport style from './InlineColourPicker.module.scss';\n\ninterface InlineColourPickerProps {\n name: string;\n value: string;\n}\n\nconst ensureHex = (value: string) => {\n if (!value.startsWith('#')) {\n return `#${value}`;\n }\n return value;\n};\n\nexport default function InlineColourPicker({ name, value }: InlineColourPickerProps) {\n const [colour, setColour] = useState(() => ensureHex(value));\n\n useEffect(() => {\n setColour(ensureHex(value));\n }, [value]);\n\n return (\n <div className={style.inline}>\n <SwatchPicker color={colour} onChange={setColour} alwaysDisplayColor />\n <span>{colour}</span>\n <input type='hidden' name={name} value={colour} />\n </div>\n );\n}\n","import { ComponentProps, useEffect, useState } from 'react';\nimport { useSearchParams } from 'react-router';\n\nimport { isStringBoolean } from '../../../features/viewers/common/viewUtils';\nimport Checkbox from '../checkbox/Checkbox';\nimport Input from '../input/input/Input';\nimport Select, { SelectOption } from '../select/Select';\nimport Switch from '../switch/Switch';\n\nimport InlineColourPicker from './InlineColourPicker';\nimport { ParamField } from './viewParams.types';\n\nimport style from './ParamInput.module.scss';\n\ninterface ParamInputProps {\n paramField: ParamField;\n}\n\nexport default function ParamInput({ paramField }: ParamInputProps) {\n const [searchParams] = useSearchParams();\n const { id, type, defaultValue } = paramField;\n\n if (type === 'persist') {\n if (!paramField.values || !paramField.values.length) {\n return null;\n }\n return <input hidden name={id} readOnly value={paramField.values.join(',')} />;\n }\n\n if (type === 'option') {\n const optionFromParams = searchParams.get(id);\n const defaultOptionValue = optionFromParams || defaultValue;\n\n if (paramField.values.length === 0) {\n return <span className={style.empty}>No options available</span>;\n }\n\n return <ControlledSelect id={id} initialValue={defaultOptionValue} options={paramField.values} />;\n }\n\n if (type === 'multi-option') {\n const optionFromParams = searchParams.getAll(id);\n\n return (\n <MultiOption\n paramField={paramField}\n options={optionFromParams.length ? optionFromParams : paramField.defaultValue ?? ['']}\n />\n );\n }\n\n if (type === 'boolean') {\n return <ControlledSwitch id={id} initialValue={isStringBoolean(searchParams.get(id)) ?? defaultValue} />;\n }\n\n if (type === 'number') {\n const { placeholder } = paramField;\n const defaultNumberValue = searchParams.get(id) ?? defaultValue;\n\n return (\n <Input\n height='large'\n type='number'\n step='any'\n name={id}\n defaultValue={defaultNumberValue}\n placeholder={placeholder}\n />\n );\n }\n\n if (type === 'colour') {\n return <InlineColourPicker name={id} value={searchParams.get(id) ?? defaultValue} />;\n }\n\n const defaultStringValue = searchParams.get(id) ?? defaultValue ?? '';\n const { placeholder } = paramField;\n\n return <ControlledInput id={id} initialValue={defaultStringValue} placeholder={placeholder} />;\n}\n\ninterface EditFormMultiOptionProps {\n paramField: ParamField & { type: 'multi-option' };\n options: string[];\n}\n\nfunction MultiOption({ paramField, options }: EditFormMultiOptionProps) {\n const { id, values } = paramField;\n const [paramState, setParamState] = useState<string[]>(options);\n\n // synchronise options\n useEffect(() => {\n setParamState(options);\n }, [options]);\n\n const toggleValue = (value: string, checked: boolean) => {\n if (checked) {\n setParamState((prev) => [...prev, value]);\n } else {\n setParamState((prev) => prev.filter((v) => v !== value));\n }\n };\n\n if (values.length === 0) {\n return <span className={style.empty}>No options available</span>;\n }\n\n return (\n <>\n <input name={id} hidden readOnly value={paramState.join(',')} />\n <div className={style.inline}>\n {values.map((option) => {\n return (\n <label\n key={option.value}\n className={style.toggleSelect}\n style={{\n '--user-bg': option.colour,\n }}\n >\n <Checkbox\n checked={paramState.includes(option.value)}\n onCheckedChange={(checked) => toggleValue(option.value, checked as boolean)}\n />\n {option.label}\n </label>\n );\n })}\n </div>\n </>\n );\n}\n\ninterface ControlledSwitchProps {\n id: string;\n initialValue: boolean;\n}\nfunction ControlledSwitch({ id, initialValue }: ControlledSwitchProps) {\n const [checked, setChecked] = useState(initialValue);\n\n // synchronise checked state\n useEffect(() => {\n setChecked(initialValue);\n }, [initialValue]);\n\n return <Switch size='large' name={id} checked={checked} onCheckedChange={setChecked} />;\n}\n\ninterface ControlledSelectProps {\n id: string;\n initialValue?: string;\n options: SelectOption[];\n}\nfunction ControlledSelect({ id, initialValue, options }: ControlledSelectProps) {\n const [selected, setSelected] = useState(initialValue);\n\n // synchronise selected state\n useEffect(() => {\n setSelected(initialValue);\n }, [initialValue]);\n\n return (\n <Select size='large' name={id} options={options} value={selected} onValueChange={(value) => setSelected(value)} />\n );\n}\n\ninterface ControlledInputProps<T extends number | string> extends ComponentProps<typeof Input> {\n id: string;\n initialValue: T;\n}\nfunction ControlledInput<T extends number | string>({ id, initialValue, ...inputProps }: ControlledInputProps<T>) {\n const [value, setValue] = useState(initialValue);\n\n // synchronise selected state\n useEffect(() => {\n setValue(initialValue);\n }, [initialValue]);\n\n return (\n <Input\n height='large'\n name={id}\n value={value}\n onChange={(event) => setValue(event.target.value as T)}\n {...inputProps}\n />\n );\n}\n","import { IoChevronDown } from 'react-icons/io5';\nimport { useLocalStorage } from '@mantine/hooks';\n\nimport { cx } from '../../utils/styleUtils';\n\nimport { OptionTitle } from './constants';\nimport ParamInput from './ParamInput';\nimport { type ParamField } from './viewParams.types';\n\nimport style from './ViewParamsSection.module.scss';\n\ninterface ViewParamsSectionProps {\n title: string;\n collapsible?: boolean;\n options: ParamField[];\n}\n\nexport default function ViewParamsSection({ title, collapsible, options }: ViewParamsSectionProps) {\n const [collapsed, setCollapsed] = useLocalStorage({ key: `params-${title}`, defaultValue: false });\n\n const handleCollapse = () => {\n if (collapsible) {\n setCollapsed((prev) => !prev);\n }\n };\n\n return (\n <section className={style.section}>\n {title === OptionTitle.Hidden ? (\n <HiddenContents options={options} />\n ) : (\n <>\n <div className={cx([style.sectionHeader, collapsible && style.collapsible])} onClick={handleCollapse}>\n {title}\n {collapsible && <IoChevronDown className={cx([collapsed ? style.closed : style.open])} />}\n </div>\n <SectionContents options={options} collapsed={collapsed} />\n </>\n )}\n </section>\n );\n}\n\ninterface SectionContentsProps {\n options: ParamField[];\n collapsed: boolean;\n}\n\nfunction SectionContents({ options, collapsed }: SectionContentsProps) {\n return (\n <>\n {options.map((option) => {\n return (\n <label key={option.title} className={cx([style.label, collapsed && style.hidden])}>\n <span className={style.title}>{option.title}</span>\n <span className={style.description}>{option.description}</span>\n <ParamInput paramField={option} />\n </label>\n );\n })}\n </>\n );\n}\n\nfunction HiddenContents({ options }: { options: ParamField[] }) {\n return (\n <>\n {options.map((option, index) => {\n return <ParamInput key={option.title + index} paramField={option} />;\n })}\n </>\n );\n}\n","import { FormEvent, memo } from 'react';\nimport { IoClose } from 'react-icons/io5';\nimport { useSearchParams } from 'react-router';\nimport { Dialog } from '@base-ui-components/react/dialog';\nimport { OntimeView } from 'ontime-types';\n\nimport useViewSettings from '../../hooks-query/useViewSettings';\nimport Button from '../buttons/Button';\nimport IconButton from '../buttons/IconButton';\nimport Info from '../info/Info';\n\nimport { ViewOption } from './viewParams.types';\nimport { getURLSearchParamsFromObj } from './viewParams.utils';\nimport { useViewParamsEditorStore } from './viewParamsEditor.store';\nimport { ViewParamsPresets } from './ViewParamsPresets';\nimport ViewParamsSection from './ViewParamsSection';\n\nimport style from './ViewParamsEditor.module.scss';\n\ninterface EditFormDrawerProps {\n target: OntimeView;\n viewOptions: ViewOption[];\n}\n\nexport default memo(ViewParamsEditor);\nfunction ViewParamsEditor({ target, viewOptions }: EditFormDrawerProps) {\n const [_, setSearchParams] = useSearchParams();\n const { data: viewSettings } = useViewSettings();\n const { isOpen, close } = useViewParamsEditorStore();\n\n const handleClose = () => {\n close();\n };\n\n const resetParams = () => {\n setSearchParams();\n };\n\n const onParamsFormSubmit = (formEvent: FormEvent<HTMLFormElement>) => {\n formEvent.preventDefault();\n\n const newParamsObject = Object.fromEntries(new FormData(formEvent.currentTarget));\n const newSearchParams = getURLSearchParamsFromObj(newParamsObject, viewOptions);\n setSearchParams(newSearchParams);\n };\n\n return (\n <Dialog.Root\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) {\n handleClose();\n }\n }}\n >\n <Dialog.Portal>\n <Dialog.Backdrop className={style.backdrop} />\n <Dialog.Popup className={style.drawer}>\n <div className={style.header}>\n <Dialog.Title>Customise</Dialog.Title>\n <IconButton variant='subtle-white' size='large' data-testid='close-view-params' onClick={handleClose}>\n <IoClose />\n </IconButton>\n </div>\n <div className={style.body}>\n {viewSettings.overrideStyles && (\n <Info className={style.info}>This view style is being modified by a custom CSS file.</Info>\n )}\n <ViewParamsPresets target={target} />\n <form id='edit-params-form' onSubmit={onParamsFormSubmit} className={style.sectionList}>\n {viewOptions.map((section) => (\n <ViewParamsSection\n key={section.title}\n title={section.title}\n collapsible={section.collapsible}\n options={section.options}\n />\n ))}\n </form>\n </div>\n <div className={style.footer}>\n <Button variant='subtle' size='large' onClick={resetParams} type='reset'>\n Reset to default\n </Button>\n <Button\n variant='primary'\n size='large'\n form='edit-params-form'\n type='submit'\n data-testid='apply-view-params'\n >\n Apply\n </Button>\n </div>\n </Dialog.Popup>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n"],"names":["makeOptionsFromCustomFields","customFields","additionalOptions","filterImageType","options","key","value","makeCustomFieldSelectOptions","makeProjectDataOptions","projectData","generatedOptions","entry","index","sanitiseColour","colour","collectFieldMetadata","paramFields","metadata","section","option","getURLSearchParamsFromObj","paramsObj","newSearchParams","addedPairs","addUniqueParam","id","pair","values","v","processedValue","ViewParamsPresets","target","viewPresets","useViewUrlPresets","searchParams","setSearchParams","useSearchParams","handleRecall","preset","newSearch","jsx","style","active","jsxs","cx","Button","OptionTitle","getTimerByType","freezeEnd","timerTypeNow","countToEndNow","clock","timerObject","timerTypeOverride","viewTimerType","TimerType","isStringBoolean","text","makeColourString","hex","getPropertyValue","event","property","field","_a","getFormattedTimer","timer","timerType","localisedMinutes","timerPlaceholderMin","timerPlaceholder","formatTime","timeToParse","MILLIS_PER_MINUTE","display","millisToString","removeLeadingZero","formatDisplayWithMinutes","removeSeconds","ensureHex","InlineColourPicker","name","setColour","useState","useEffect","SwatchPicker","ParamInput","paramField","type","defaultValue","defaultOptionValue","ControlledSelect","optionFromParams","MultiOption","ControlledSwitch","placeholder","defaultNumberValue","Input","defaultStringValue","ControlledInput","paramState","setParamState","toggleValue","checked","prev","Fragment","Checkbox","initialValue","setChecked","Switch","selected","setSelected","Select","inputProps","setValue","ViewParamsSection","title","collapsible","collapsed","setCollapsed","useLocalStorage","handleCollapse","HiddenContents","IoChevronDown","SectionContents","memo","ViewParamsEditor","viewOptions","_","viewSettings","useViewSettings","isOpen","close","useViewParamsEditorStore","handleClose","resetParams","onParamsFormSubmit","formEvent","newParamsObject","Dialog.Root","open","Dialog.Portal","Dialog.Backdrop","Dialog.Popup","Dialog.Title","IconButton","IoClose","Info"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ViewParamsEditor-BFu_0oIb.js","sources":["../../src/common/components/view-params-editor/viewParams.utils.ts","../../src/common/components/view-params-editor/ViewParamsPresets.tsx","../../src/common/components/view-params-editor/constants.ts","../../src/features/viewers/common/viewUtils.ts","../../src/common/components/view-params-editor/InlineColourPicker.tsx","../../src/common/components/view-params-editor/ParamInput.tsx","../../src/common/components/view-params-editor/ViewParamsSection.tsx","../../src/common/components/view-params-editor/ViewParamsEditor.tsx"],"sourcesContent":["import type { CustomFields, ProjectData } from 'ontime-types';\n\nimport type { SelectOption } from '../select/Select';\n\nimport type { MultiselectOption, ViewOption } from './viewParams.types';\n\n/**\n * Creates a list of custom fields for a select\n * Filters out image type custom fields\n */\nexport function makeOptionsFromCustomFields(\n customFields: CustomFields,\n additionalOptions: SelectOption[] = [],\n filterImageType = true,\n): SelectOption[] {\n const options: SelectOption[] = [...additionalOptions];\n\n // Add custom fields first\n for (const [key, value] of Object.entries(customFields)) {\n if (filterImageType && value.type === 'image') {\n continue;\n }\n\n options.push({\n value: `custom-${key}`,\n label: `Custom: ${value.label}`,\n });\n }\n\n return options;\n}\n\n/**\n * Creates data for a multiselect component from custom fields\n * Filters out image type custom fields\n */\nexport function makeCustomFieldSelectOptions(customFields: CustomFields, filterImageType = true): MultiselectOption[] {\n const options: MultiselectOption[] = [];\n\n // Add custom fields first\n for (const [key, value] of Object.entries(customFields)) {\n if (filterImageType && value.type === 'image') {\n continue;\n }\n\n options.push({\n value: key,\n label: value.label,\n colour: value.colour || 'transparent',\n });\n }\n\n return options;\n}\n\n/**\n * Creates data for a select element that displays project custom data\n */\nexport function makeProjectDataOptions(\n projectData: ProjectData,\n additionalOptions: SelectOption[] = [],\n): SelectOption[] {\n const generatedOptions = projectData.custom.map((entry, index) => {\n return {\n value: `${index}-${entry.title}`,\n label: entry.title,\n };\n });\n\n return [...additionalOptions, ...generatedOptions];\n}\n\ntype ViewParamsObj = { [key: string]: string | FormDataEntryValue };\n\n/**\n * Utility remove the # character from a hex string\n */\nfunction sanitiseColour(colour: string) {\n if (colour.startsWith('#')) {\n return colour.substring(1);\n }\n return colour;\n}\n\ntype FieldMetadata = {\n defaultValues: Record<string, string>;\n colorFields: Set<string>;\n booleanFields: Set<string>;\n isPersistedField: Set<string>;\n persistedValues: Record<string, string[]>;\n};\n\n/**\n * Utility collects metadata about fields from view options\n * - where are the default values\n * - which fields are colours\n * - which fields are persisted\n */\nfunction collectFieldMetadata(paramFields: ViewOption[]): FieldMetadata {\n const metadata: FieldMetadata = {\n defaultValues: {},\n colorFields: new Set(),\n booleanFields: new Set(),\n isPersistedField: new Set(),\n persistedValues: {},\n };\n\n paramFields.forEach((section) => {\n section.options.forEach((option) => {\n if (option.type === 'persist') {\n metadata.isPersistedField.add(option.id);\n if (option.values) {\n metadata.persistedValues[option.id] = option.values;\n }\n } else {\n metadata.defaultValues[option.id] = String(option.defaultValue);\n }\n\n if (option.type === 'colour') {\n metadata.colorFields.add(option.id);\n } else if (option.type === 'boolean') {\n metadata.booleanFields.add(option.id);\n }\n });\n });\n\n return metadata;\n}\n\n/**\n * Makes a new URLSearchParams object from the given params object\n * @param paramsObj - The object containing parameters to be converted\n * @param paramFields - The view options that define the parameters\n * @returns A new URLSearchParams object with the parameters\n */\nexport function getURLSearchParamsFromObj(paramsObj: ViewParamsObj, paramFields: ViewOption[]) {\n const newSearchParams = new URLSearchParams();\n const addedPairs = new Set<string>();\n const metadata = collectFieldMetadata(paramFields);\n\n // Utility function to safely add params without duplicates\n const addUniqueParam = (id: string, value: string) => {\n const pair = `${id}:${value}`;\n if (!addedPairs.has(pair)) {\n addedPairs.add(pair);\n newSearchParams.append(id, value);\n }\n };\n\n // First add all persisted values\n Object.entries(metadata.persistedValues).forEach(([id, values]) => {\n values.forEach((value) => {\n if (value) {\n addUniqueParam(id, value);\n }\n });\n });\n\n // Then process user-provided values\n Object.entries(paramsObj).forEach(([id, value]) => {\n if (typeof value === 'string' && value.length) {\n // For persisted fields, clear existing values before adding new ones\n if (metadata.isPersistedField.has(id)) {\n // Clear tracking of previous values for this field\n Array.from(addedPairs).forEach((pair) => {\n if (pair.startsWith(`${id}:`)) {\n addedPairs.delete(pair);\n }\n });\n newSearchParams.delete(id);\n }\n\n // Process and add new values\n value.split(',').forEach((v) => {\n // some field types need extra processing\n const processedValue = (() => {\n if (metadata.colorFields.has(id)) {\n return sanitiseColour(v);\n }\n if (metadata.booleanFields.has(id)) {\n return v === 'on' ? 'true' : 'false';\n }\n return v;\n })();\n if (metadata.isPersistedField.has(id) || metadata.defaultValues[id] !== processedValue) {\n addUniqueParam(id, processedValue);\n }\n });\n }\n });\n\n return newSearchParams;\n}\n","import { useSearchParams } from 'react-router';\nimport { OntimeView, URLPreset } from 'ontime-types';\n\nimport { useViewUrlPresets } from '../../hooks-query/useUrlPresets';\nimport { cx } from '../../utils/styleUtils';\nimport Button from '../buttons/Button';\n\nimport style from './ViewParamsPresets.module.scss';\n\n/**\n * Shows a list of presets for the current view\n */\nexport function ViewParamsPresets({ target }: { target: OntimeView }) {\n const { viewPresets } = useViewUrlPresets(target);\n const [searchParams, setSearchParams] = useSearchParams();\n\n const handleRecall = (preset: URLPreset) => {\n const newSearch = new URLSearchParams(preset.search);\n newSearch.set('alias', preset.alias);\n setSearchParams(newSearch);\n };\n\n if (viewPresets.length === 0) {\n return null;\n }\n\n return (\n <div className={style.presetSection}>\n {viewPresets.map((preset) => {\n const active = searchParams.get('alias') === preset.alias;\n return (\n <div key={preset.alias} className={cx([style.preset, active && style.active])}>\n <div>{preset.alias}</div>\n <Button\n variant={active ? 'ghosted' : 'subtle-white'}\n onClick={() => handleRecall(preset)}\n disabled={active}\n className={style.presetActions}\n >\n {active ? 'Applied' : 'Apply'}\n </Button>\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * Gathers possible titles for view options\n */\nexport enum OptionTitle {\n ClockOptions = 'Clock Options',\n TimerOptions = 'Timer Options',\n DataSources = 'Data sources',\n ElementVisibility = 'Element visibility',\n BehaviourOptions = 'View behaviour',\n StyleOverride = 'View style override',\n Animation = 'View animation',\n Schedule = 'Schedule options',\n\n /** rendered as hidden inputs */\n Hidden = 'Hidden options',\n}\n","import { MaybeNumber, MaybeString, OntimeEvent, TimerState, TimerType } from 'ontime-types';\nimport { MILLIS_PER_MINUTE, MILLIS_PER_SECOND, millisToString, removeLeadingZero, removeSeconds } from 'ontime-utils';\n\nimport { timerPlaceholder, timerPlaceholderMin } from '../../../common/utils/styleUtils';\nimport { formatTime } from '../../../common/utils/time';\n\n/**\n * Gathers all options that affect which timer is displayed and selects the correct data source to display\n * it also handles edge cases such as freezing on end\n */\nexport function getTimerByType(\n freezeEnd: boolean,\n timerTypeNow: TimerType,\n countToEndNow: boolean,\n clock: number,\n timerObject: Pick<TimerState, 'current' | 'elapsed'>,\n timerTypeOverride?: TimerType,\n): number | null {\n if (!timerObject) {\n return null;\n }\n\n const viewTimerType = timerTypeOverride ?? timerTypeNow;\n\n if (countToEndNow) {\n if (timerObject.current === null) {\n return null;\n }\n return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;\n }\n\n switch (viewTimerType) {\n case TimerType.CountDown:\n if (timerObject.current === null) {\n return null;\n }\n return freezeEnd ? Math.max(timerObject.current, 0) : timerObject.current;\n case TimerType.CountUp:\n return Math.abs(timerObject.elapsed ?? 0);\n case TimerType.Clock:\n return clock;\n case TimerType.None:\n return null;\n default: {\n viewTimerType satisfies never;\n return null;\n }\n }\n}\n\n/**\n * Parses a string to semantically verify if it represents a true value\n * Used in the context of parsing search params and local storage items which can be strings or null\n */\nexport function isStringBoolean(text: string | null) {\n if (text === null) {\n return false;\n }\n return text?.toLowerCase() === 'true' || text === '1';\n}\n\n/**\n * Prepares a colour string for use in views\n * Colours in params do not have the #prefix\n */\nexport function makeColourString(hex: string | null): string | undefined {\n if (!hex) {\n return undefined;\n }\n // ensure the hex starts with a #\n return hex.startsWith('#') ? hex : `#${hex}`;\n}\n\n/**\n * Retrieves a dynamic property from an event\n * Considers custom fields\n */\nexport function getPropertyValue(event: OntimeEvent | null, property: MaybeString): string | undefined {\n if (!event || typeof property !== 'string' || property === 'none') {\n return undefined;\n }\n\n if (property.startsWith('custom-')) {\n const field = property.split('custom-')[1];\n return event.custom?.[field];\n }\n\n return event[property as keyof OntimeEvent] as string;\n}\n\ntype FormattingOptions = {\n removeSeconds: boolean;\n removeLeadingZero: boolean;\n};\n\nexport function getFormattedTimer(\n timer: MaybeNumber,\n timerType: TimerType,\n localisedMinutes: string,\n options: FormattingOptions,\n): string {\n if (timer == null || timerType === TimerType.None) {\n return options.removeSeconds ? timerPlaceholderMin : timerPlaceholder;\n }\n\n if (timerType === TimerType.Clock) {\n return formatTime(timer);\n }\n\n let timeToParse = timer;\n if (options.removeSeconds) {\n const isNegative = timeToParse < -MILLIS_PER_SECOND && timerType !== TimerType.CountUp;\n if (isNegative) {\n // in negative numbers, we need to round down\n timeToParse -= MILLIS_PER_MINUTE;\n }\n }\n\n let display = millisToString(timeToParse, { direction: timerType });\n if (options.removeLeadingZero) {\n display = removeLeadingZero(display);\n }\n\n if (options.removeSeconds) {\n display = formatDisplayWithMinutes(display, localisedMinutes);\n }\n return display;\n}\n\nfunction formatDisplayWithMinutes(display: string, localisedMinutes: string): string {\n display = removeSeconds(display);\n return display.length < 3 ? `${display} ${localisedMinutes}` : display;\n}\n","import { useEffect, useState } from 'react';\n\nimport SwatchPicker from '../input/colour-input/SwatchPicker';\n\nimport style from './InlineColourPicker.module.scss';\n\ninterface InlineColourPickerProps {\n name: string;\n value: string;\n}\n\nconst ensureHex = (value: string) => {\n if (!value.startsWith('#')) {\n return `#${value}`;\n }\n return value;\n};\n\nexport default function InlineColourPicker({ name, value }: InlineColourPickerProps) {\n const [colour, setColour] = useState(() => ensureHex(value));\n\n useEffect(() => {\n setColour(ensureHex(value));\n }, [value]);\n\n return (\n <div className={style.inline}>\n <SwatchPicker color={colour} onChange={setColour} alwaysDisplayColor />\n <span>{colour}</span>\n <input type='hidden' name={name} value={colour} />\n </div>\n );\n}\n","import { ComponentProps, useEffect, useState } from 'react';\nimport { useSearchParams } from 'react-router';\n\nimport { isStringBoolean } from '../../../features/viewers/common/viewUtils';\nimport Checkbox from '../checkbox/Checkbox';\nimport Input from '../input/input/Input';\nimport Select, { SelectOption } from '../select/Select';\nimport Switch from '../switch/Switch';\n\nimport InlineColourPicker from './InlineColourPicker';\nimport { ParamField } from './viewParams.types';\n\nimport style from './ParamInput.module.scss';\n\ninterface ParamInputProps {\n paramField: ParamField;\n}\n\nexport default function ParamInput({ paramField }: ParamInputProps) {\n const [searchParams] = useSearchParams();\n const { id, type, defaultValue } = paramField;\n\n if (type === 'persist') {\n if (!paramField.values || !paramField.values.length) {\n return null;\n }\n return <input hidden name={id} readOnly value={paramField.values.join(',')} />;\n }\n\n if (type === 'option') {\n const optionFromParams = searchParams.get(id);\n const defaultOptionValue = optionFromParams || defaultValue;\n\n if (paramField.values.length === 0) {\n return <span className={style.empty}>No options available</span>;\n }\n\n return <ControlledSelect id={id} initialValue={defaultOptionValue} options={paramField.values} />;\n }\n\n if (type === 'multi-option') {\n const optionFromParams = searchParams.getAll(id);\n\n return (\n <MultiOption\n paramField={paramField}\n options={optionFromParams.length ? optionFromParams : paramField.defaultValue ?? ['']}\n />\n );\n }\n\n if (type === 'boolean') {\n return <ControlledSwitch id={id} initialValue={isStringBoolean(searchParams.get(id)) ?? defaultValue} />;\n }\n\n if (type === 'number') {\n const { placeholder } = paramField;\n const defaultNumberValue = searchParams.get(id) ?? defaultValue;\n\n return (\n <Input\n height='large'\n type='number'\n step='any'\n name={id}\n defaultValue={defaultNumberValue}\n placeholder={placeholder}\n />\n );\n }\n\n if (type === 'colour') {\n return <InlineColourPicker name={id} value={searchParams.get(id) ?? defaultValue} />;\n }\n\n const defaultStringValue = searchParams.get(id) ?? defaultValue ?? '';\n const { placeholder } = paramField;\n\n return <ControlledInput id={id} initialValue={defaultStringValue} placeholder={placeholder} />;\n}\n\ninterface EditFormMultiOptionProps {\n paramField: ParamField & { type: 'multi-option' };\n options: string[];\n}\n\nfunction MultiOption({ paramField, options }: EditFormMultiOptionProps) {\n const { id, values } = paramField;\n const [paramState, setParamState] = useState<string[]>(options);\n\n // synchronise options\n useEffect(() => {\n setParamState(options);\n }, [options]);\n\n const toggleValue = (value: string, checked: boolean) => {\n if (checked) {\n setParamState((prev) => [...prev, value]);\n } else {\n setParamState((prev) => prev.filter((v) => v !== value));\n }\n };\n\n if (values.length === 0) {\n return <span className={style.empty}>No options available</span>;\n }\n\n return (\n <>\n <input name={id} hidden readOnly value={paramState.join(',')} />\n <div className={style.inline}>\n {values.map((option) => {\n return (\n <label\n key={option.value}\n className={style.toggleSelect}\n style={{\n '--user-bg': option.colour,\n }}\n >\n <Checkbox\n checked={paramState.includes(option.value)}\n onCheckedChange={(checked) => toggleValue(option.value, checked as boolean)}\n />\n {option.label}\n </label>\n );\n })}\n </div>\n </>\n );\n}\n\ninterface ControlledSwitchProps {\n id: string;\n initialValue: boolean;\n}\nfunction ControlledSwitch({ id, initialValue }: ControlledSwitchProps) {\n const [checked, setChecked] = useState(initialValue);\n\n // synchronise checked state\n useEffect(() => {\n setChecked(initialValue);\n }, [initialValue]);\n\n return <Switch size='large' name={id} checked={checked} onCheckedChange={setChecked} />;\n}\n\ninterface ControlledSelectProps {\n id: string;\n initialValue?: string;\n options: SelectOption[];\n}\nfunction ControlledSelect({ id, initialValue, options }: ControlledSelectProps) {\n const [selected, setSelected] = useState(initialValue);\n\n // synchronise selected state\n useEffect(() => {\n setSelected(initialValue);\n }, [initialValue]);\n\n return (\n <Select size='large' name={id} options={options} value={selected} onValueChange={(value) => setSelected(value)} />\n );\n}\n\ninterface ControlledInputProps<T extends number | string> extends ComponentProps<typeof Input> {\n id: string;\n initialValue: T;\n}\nfunction ControlledInput<T extends number | string>({ id, initialValue, ...inputProps }: ControlledInputProps<T>) {\n const [value, setValue] = useState(initialValue);\n\n // synchronise selected state\n useEffect(() => {\n setValue(initialValue);\n }, [initialValue]);\n\n return (\n <Input\n height='large'\n name={id}\n value={value}\n onChange={(event) => setValue(event.target.value as T)}\n {...inputProps}\n />\n );\n}\n","import { IoChevronDown } from 'react-icons/io5';\nimport { useLocalStorage } from '@mantine/hooks';\n\nimport { cx } from '../../utils/styleUtils';\n\nimport { OptionTitle } from './constants';\nimport ParamInput from './ParamInput';\nimport { type ParamField } from './viewParams.types';\n\nimport style from './ViewParamsSection.module.scss';\n\ninterface ViewParamsSectionProps {\n title: string;\n collapsible?: boolean;\n options: ParamField[];\n}\n\nexport default function ViewParamsSection({ title, collapsible, options }: ViewParamsSectionProps) {\n const [collapsed, setCollapsed] = useLocalStorage({ key: `params-${title}`, defaultValue: false });\n\n const handleCollapse = () => {\n if (collapsible) {\n setCollapsed((prev) => !prev);\n }\n };\n\n return (\n <section className={style.section}>\n {title === OptionTitle.Hidden ? (\n <HiddenContents options={options} />\n ) : (\n <>\n <div className={cx([style.sectionHeader, collapsible && style.collapsible])} onClick={handleCollapse}>\n {title}\n {collapsible && <IoChevronDown className={cx([collapsed ? style.closed : style.open])} />}\n </div>\n <SectionContents options={options} collapsed={collapsed} />\n </>\n )}\n </section>\n );\n}\n\ninterface SectionContentsProps {\n options: ParamField[];\n collapsed: boolean;\n}\n\nfunction SectionContents({ options, collapsed }: SectionContentsProps) {\n return (\n <>\n {options.map((option) => {\n return (\n <label key={option.title} className={cx([style.label, collapsed && style.hidden])}>\n <span className={style.title}>{option.title}</span>\n <span className={style.description}>{option.description}</span>\n <ParamInput paramField={option} />\n </label>\n );\n })}\n </>\n );\n}\n\nfunction HiddenContents({ options }: { options: ParamField[] }) {\n return (\n <>\n {options.map((option, index) => {\n return <ParamInput key={option.title + index} paramField={option} />;\n })}\n </>\n );\n}\n","import { FormEvent, memo } from 'react';\nimport { IoClose } from 'react-icons/io5';\nimport { useSearchParams } from 'react-router';\nimport { Dialog } from '@base-ui-components/react/dialog';\nimport { OntimeView } from 'ontime-types';\n\nimport useViewSettings from '../../hooks-query/useViewSettings';\nimport Button from '../buttons/Button';\nimport IconButton from '../buttons/IconButton';\nimport Info from '../info/Info';\n\nimport { ViewOption } from './viewParams.types';\nimport { getURLSearchParamsFromObj } from './viewParams.utils';\nimport { useViewParamsEditorStore } from './viewParamsEditor.store';\nimport { ViewParamsPresets } from './ViewParamsPresets';\nimport ViewParamsSection from './ViewParamsSection';\n\nimport style from './ViewParamsEditor.module.scss';\n\ninterface EditFormDrawerProps {\n target: OntimeView;\n viewOptions: ViewOption[];\n}\n\nexport default memo(ViewParamsEditor);\nfunction ViewParamsEditor({ target, viewOptions }: EditFormDrawerProps) {\n const [_, setSearchParams] = useSearchParams();\n const { data: viewSettings } = useViewSettings();\n const { isOpen, close } = useViewParamsEditorStore();\n\n const handleClose = () => {\n close();\n };\n\n const resetParams = () => {\n setSearchParams();\n };\n\n const onParamsFormSubmit = (formEvent: FormEvent<HTMLFormElement>) => {\n formEvent.preventDefault();\n\n const newParamsObject = Object.fromEntries(new FormData(formEvent.currentTarget));\n const newSearchParams = getURLSearchParamsFromObj(newParamsObject, viewOptions);\n setSearchParams(newSearchParams);\n };\n\n return (\n <Dialog.Root\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) {\n handleClose();\n }\n }}\n >\n <Dialog.Portal>\n <Dialog.Backdrop className={style.backdrop} />\n <Dialog.Popup className={style.drawer}>\n <div className={style.header}>\n <Dialog.Title>Customise</Dialog.Title>\n <IconButton variant='subtle-white' size='large' data-testid='close-view-params' onClick={handleClose}>\n <IoClose />\n </IconButton>\n </div>\n <div className={style.body}>\n {viewSettings.overrideStyles && (\n <Info className={style.info}>This view style is being modified by a custom CSS file.</Info>\n )}\n <ViewParamsPresets target={target} />\n <form id='edit-params-form' onSubmit={onParamsFormSubmit} className={style.sectionList}>\n {viewOptions.map((section) => (\n <ViewParamsSection\n key={section.title}\n title={section.title}\n collapsible={section.collapsible}\n options={section.options}\n />\n ))}\n </form>\n </div>\n <div className={style.footer}>\n <Button variant='subtle' size='large' onClick={resetParams} type='reset'>\n Reset to default\n </Button>\n <Button\n variant='primary'\n size='large'\n form='edit-params-form'\n type='submit'\n data-testid='apply-view-params'\n >\n Apply\n </Button>\n </div>\n </Dialog.Popup>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n"],"names":["makeOptionsFromCustomFields","customFields","additionalOptions","filterImageType","options","key","value","makeCustomFieldSelectOptions","makeProjectDataOptions","projectData","generatedOptions","entry","index","sanitiseColour","colour","collectFieldMetadata","paramFields","metadata","section","option","getURLSearchParamsFromObj","paramsObj","newSearchParams","addedPairs","addUniqueParam","id","pair","values","v","processedValue","ViewParamsPresets","target","viewPresets","useViewUrlPresets","searchParams","setSearchParams","useSearchParams","handleRecall","preset","newSearch","jsx","style","active","jsxs","cx","Button","OptionTitle","getTimerByType","freezeEnd","timerTypeNow","countToEndNow","clock","timerObject","timerTypeOverride","viewTimerType","TimerType","isStringBoolean","text","makeColourString","hex","getPropertyValue","event","property","field","_a","getFormattedTimer","timer","timerType","localisedMinutes","timerPlaceholderMin","timerPlaceholder","formatTime","timeToParse","MILLIS_PER_MINUTE","display","millisToString","removeLeadingZero","formatDisplayWithMinutes","removeSeconds","ensureHex","InlineColourPicker","name","setColour","useState","useEffect","SwatchPicker","ParamInput","paramField","type","defaultValue","defaultOptionValue","ControlledSelect","optionFromParams","MultiOption","ControlledSwitch","placeholder","defaultNumberValue","Input","defaultStringValue","ControlledInput","paramState","setParamState","toggleValue","checked","prev","Fragment","Checkbox","initialValue","setChecked","Switch","selected","setSelected","Select","inputProps","setValue","ViewParamsSection","title","collapsible","collapsed","setCollapsed","useLocalStorage","handleCollapse","HiddenContents","IoChevronDown","SectionContents","memo","ViewParamsEditor","viewOptions","_","viewSettings","useViewSettings","isOpen","close","useViewParamsEditorStore","handleClose","resetParams","onParamsFormSubmit","formEvent","newParamsObject","Dialog.Root","open","Dialog.Portal","Dialog.Backdrop","Dialog.Popup","Dialog.Title","IconButton","IoClose","Info"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{O as ie,h as v,P as b}from"./vendor-CCiSQ9k9.js";import{j as D,i as h,v as ae,w as oe,x as se,y as de,z as ue,A as ce,B as le,C as fe,D as ye,E as Ee,S as we,F as pe}from"./useRundown-BfpjcCEJ.js";import{T as _}from"./validateEvent-P9sf7C10.js";import{ax as o,b8 as me,by as g,r as ve,be as ge,M as B,bz as R,H as be}from"./index-BQEUaoAf.js";import{u as Ie}from"./editorSettings-BU0pTMSY.js";import{p as M}from"./parseUserTime-BeTKj08M.js";import{s as he}from"./rundownUtils-BZHazkXR.js";(function(){try{var n=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},y=new n.Error().stack;y&&(n._sentryDebugIds=n._sentryDebugIds||{},n._sentryDebugIds[y]="fbe5a3e4-0992-4074-a64d-e72b9a44df5d",n._sentryDebugIdIdentifier="sentry-dbid-fbe5a3e4-0992-4074-a64d-e72b9a44df5d")}catch{}})();function Re(n,y){const c=[];for(let s=0;s<n.length;s++){const E=y[n[s]];E&&(D(E)?(c.push(E.id),c.push(...E.entries),c.push(`end-${E.id}`)):c.push(E.id))}return c}function Fe(n,y,c,s){return n==="end-group"?c==="after":n==="group"?!(c!==void 0&&c==="after"&&!s):y===null}function De(n,y,c){const s=c[n],E=y.indexOf(n),f=y[E-1];if(!f)return"parent"in s&&s.parent!==null?{destinationId:s.parent,order:"before"}:{destinationId:null,order:"before"};if(D(s)){const d=c[f];return"parent"in d&&d.parent!==null?{destinationId:d.parent,order:"before"}:{destinationId:f,order:"before"}}const l=c[f],p=s.parent;return D(l)?p===null?{destinationId:f,order:"insert"}:{destinationId:f,order:"before"}:h(l)&&l.parent!==null&&p===null?{destinationId:f,order:"after"}:{destinationId:f,order:"before"}}function Qe(n,y,c){const s=c[n],E=y.indexOf(n),f=y[E+1];if("parent"in s&&s.parent!==null){const I=c[s.parent];if(D(I)&&I.entries[I.entries.length-1]===n)return{destinationId:s.parent,order:"after"}}if(!f)return{destinationId:null,order:"after"};if(D(s)){if(s.entries.includes(f)){const I=E+s.entries.length+1,Q=y[I];return Q?{destinationId:Q,order:"after"}:{destinationId:null,order:"after"}}return{destinationId:f,order:"after"}}const l=c[f],p=s.parent;return D(l)&&p===null?l.entries.length===0?{destinationId:f,order:"insert"}:{destinationId:l.entries[0],order:"before"}:(h(l)?l.parent:null)!==null&&p===null?{destinationId:f,order:"after"}:{destinationId:f,order:"after"}}function Se(n,y){const c=[];for(const s of y)n.includes(s)&&c.push(s);return c}const Te=()=>{const n=ie(),{linkPrevious:y,defaultTimeStrategy:c,defaultDuration:s,defaultWarnTime:E,defaultDangerTime:f,defaultTimerType:l,defaultEndAction:p}=Ie(),d=v.useCallback(()=>n.getQueryData(o),[n]),I=v.useCallback(r=>{const t=d();if(t!=null&&t.entries)return t.entries[r]},[d]),{mutateAsync:Q}=b({mutationFn:([r,t])=>ae(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>n.invalidateQueries({queryKey:o})}),j=v.useCallback(async(r,t)=>{const e=d(),i=e==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");const a={...r,id:me()};if(h(a)){if(t!=null&&t.lastEventId){const u=e.entries[t==null?void 0:t.lastEventId];h(u)&&(a.timeStart=u.timeEnd)}a.linkStart=(t==null?void 0:t.linkPrevious)??y,a.duration===void 0&&a.timeEnd===void 0&&(a.duration=M(s)),a.timeDanger===void 0&&(a.timeDanger=M(f)),a.timeWarning===void 0&&(a.timeWarning=M(E)),a.timerType===void 0&&(a.timerType=l),a.endAction===void 0&&(a.endAction=p),a.timeStrategy===void 0&&(a.timeStrategy=c)}t!=null&&t.after&&(a.after=t.after),t!=null&&t.before&&(a.before=t.before);try{await Q([i,a])}catch(u){g("Failed adding event",u)}},[d,y,s,f,E,l,p,c,Q]),{mutateAsync:F}=b({mutationFn:([r,t])=>oe(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>n.invalidateQueries({queryKey:o})}),H=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await F([e,r])}catch(e){g("Error cloning entry",e)}},[F,d]),{mutateAsync:q}=b({mutationFn:([r,t])=>se(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o),i=t.id;if(e&&i){const a={...e.entries};a[i]={...a[i],...t},n.setQueryData(o,{id:e.id,title:e.title,order:e.order,flatOrder:e.flatOrder,entries:a,revision:-1})}return{previousData:e,newEvent:t}},onError:(r,t,e)=>{e!=null&&e.previousData&&n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:async()=>{await n.invalidateQueries({queryKey:o})}}),z=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await q([e,r])}catch(e){g("Error updating event",e)}},[d,q]),V=v.useCallback(async(r,t,e,i)=>{var k;const a=(k=d())==null?void 0:k.id;if(!a)throw new Error("Rundown not initialised");if(!i&&e==="")return;const u={id:r};i?t==="timeEnd"?(u.timeStrategy=e===""?_.LockDuration:_.LockEnd,u.timeEnd=e===""?void 0:w()):t==="duration"?(u.timeStrategy=e===""?_.LockEnd:_.LockDuration,u.duration=e===""?void 0:w()):t==="timeStart"&&(u.linkStart=e==="",u.timeStart=e===""?void 0:w()):u[t]=w();try{await q([a,u])}catch(m){g("Error updating event",m)}function w(){let m=0;if(e==="p"||e==="prev"||e==="previous")m=S();else if(e.startsWith("+")||e.startsWith("p+")||e.startsWith("p +")){const A=e.substring(1);m=S()+M(A)}else m=M(e);return Math.min(m,ve-ge)}function S(){const m=n.getQueryData(o);if(!(m!=null&&m.order)||!(m!=null&&m.entries))return 0;const A=m.order.indexOf(r);if(A===0)return 0;let $=0;for(let K=A-1;K>=0;K--){const N=m.entries[m.order[K]];if(h(N)){$=N.timeEnd;break}}return $}},[d,q,n]),{mutateAsync:T}=b({mutationFn:([r,t])=>de(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o);if(e){const i=new Set(t.ids),a={...e.entries};i.forEach(u=>{if(Object.hasOwn(a,u)){const w=a[u];h(w)&&(a[u]={...w,...t})}}),n.setQueryData(o,{id:e.id,title:e.title,order:e.order,flatOrder:e.flatOrder,entries:a,revision:-1})}return{previousRundown:e}},onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousRundown)}}),J=v.useCallback(async(r,t)=>{var e;try{const i=(e=d())==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");await T([i,{data:r,ids:t}])}catch(i){g("Error updating events",i)}},[T,d]),{mutateAsync:L}=b({mutationFn:([r,t])=>ue(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o);if(e){const{entries:i,order:a,flatOrder:u}=Me(t,e);n.setQueryData(o,{id:e.id,title:e.title,order:a,flatOrder:u,entries:i,revision:-1})}return{previousData:e}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),X=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await L([e,r])}catch(e){g("Error deleting event",e)}},[L,d]),{mutateAsync:P}=b({mutationFn:([r])=>ce(r),onMutate:async()=>{await n.cancelQueries({queryKey:o});const r=n.getQueryData(o);return n.setQueryData(o,{id:(r==null?void 0:r.id)??"default",title:(r==null?void 0:r.title)??"",order:[],flatOrder:[],entries:{},revision:-1}),{previousData:r}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),Y=v.useCallback(async()=>{var r;try{const t=(r=d())==null?void 0:r.id;if(!t)throw new Error("Rundown not initialised");await P([t])}catch(t){g("Error deleting events",t)}},[P,d]),{mutateAsync:G}=b({mutationFn:([r,t])=>le(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),Z=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await G([e,r])}catch(e){g("Error applying delay",e)}},[G,d]),{mutateAsync:U}=b({mutationFn:([r,t])=>fe(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>n.invalidateQueries({queryKey:o})}),x=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await U([e,r])}catch(e){g("Error dissolving group",e)}},[d,U]),{mutateAsync:C}=b({mutationFn:([r,t])=>ye(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>n.invalidateQueries({queryKey:o})}),ee=v.useCallback(async r=>{if(r.length!==0)try{const t=d(),e=t==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");if(r.length===1)await C([e,r]);else{const i=Se(r,t.flatOrder);await C([e,i])}}catch(t){g("Error grouping entries",t)}},[d,C]),{mutateAsync:O}=b({mutationFn:([r,t])=>Ee(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>{n.invalidateQueries({queryKey:o})}}),te=v.useCallback(async(r,t)=>{var e;try{const i=d(),a=i==null?void 0:i.id;if(!a)throw new Error("Rundown not initialised");const{destinationId:u,order:w}=t==="up"?De(r,i.flatOrder,i.entries):Qe(r,i.flatOrder,i.entries);return u?(await O([a,{entryId:r,destinationId:u,order:w}]),((e=i.entries[u])==null?void 0:e.type)===we.Group?u:void 0):void 0}catch(i){g("Error re-ordering event",i)}},[d,O]),re=v.useCallback(async(r,t,e)=>{var i;try{const a=(i=d())==null?void 0:i.id;if(!a)throw new Error("Rundown not initialised");await O([a,{entryId:r,destinationId:t,order:e}])}catch(a){throw g("Error re-ordering event",a),a}},[d,O]),{mutateAsync:W}=b({mutationFn:([r,t,e])=>pe(r,t,e),onMutate:async([r,t,e])=>{await n.cancelQueries({queryKey:o});const i=n.getQueryData(o);if(i){const a={...i.entries},u=i.entries[t],w=i.entries[e];if(!h(u)||!h(w))return;const[S,k]=he(u,w);a[t]=S,a[e]=k,n.setQueryData(o,{id:i.id,title:i.title,order:i.order,flatOrder:i.flatOrder,entries:a,revision:-1})}return{previousData:i}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),ne=v.useCallback(async(r,t)=>{var e;try{const i=(e=d())==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");await W([i,r,t])}catch(i){g("Error re-ordering event",i)}},[d,W]);return{addEntry:j,applyDelay:Z,batchUpdateEvents:J,clone:H,deleteEntry:X,deleteAllEntries:Y,ungroup:x,getEntryById:I,groupEntries:ee,move:te,reorderEntry:re,swapEvents:ne,updateEntry:z,updateTimer:V}};function Me(n,y){const c={...y.entries};let s=[...y.order],E=[...y.flatOrder];for(let l=0;l<n.length;l++){const p=c[n[l]];f(p)}function f(l){if(D(l)||!l.parent)s=s.filter(p=>p!==l.id);else{const p=c[l.parent];p&&D(p)&&(p.entries=p.entries.filter(d=>d!==l.id))}delete c[l.id],E=E.filter(p=>p!==l.id)}return{entries:c,order:s,flatOrder:E}}function Le(n,y="compact"){if(n==null||n===0)return"";const c=n<0,s=Math.abs(n),E=y==="compact",f=E?"+":"delayed by ",l=E?"-":"ahead by ";return s<B?`${c?l:f}${R(s,"s")} sec`:s<be&&s%B===0?`${c?l:f}${R(s,"m")} min`:`${c?l:f}${R(s,"HH:mm:ss")}`}export{Re as a,Fe as c,Le as m,Te as u};
|
|
2
|
-
//# sourceMappingURL=dateConfig-
|
|
1
|
+
import{O as ie,h as v,P as b}from"./vendor-9UkPSc5K.js";import{j as D,i as h,x as ae,y as oe,z as se,A as de,B as ue,C as ce,D as le,E as fe,F as ye,G as Ee,S as we,H as pe}from"./useRundown-ihoU8qBi.js";import{T as _}from"./validateEvent-BJMwP_mq.js";import{ax as o,b8 as me,by as g,r as ve,be as ge,M as B,bz as R,H as be}from"./index-njXwwjfn.js";import{u as Ie}from"./editorSettings-CCHx-wCx.js";import{p as M}from"./parseUserTime-Bc1pSJR2.js";import{s as he}from"./rundownUtils-H6xvQyre.js";(function(){try{var n=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},y=new n.Error().stack;y&&(n._sentryDebugIds=n._sentryDebugIds||{},n._sentryDebugIds[y]="19640836-50b5-40b3-8859-8741d96a0630",n._sentryDebugIdIdentifier="sentry-dbid-19640836-50b5-40b3-8859-8741d96a0630")}catch{}})();function Re(n,y){const c=[];for(let s=0;s<n.length;s++){const E=y[n[s]];E&&(D(E)?(c.push(E.id),c.push(...E.entries),c.push(`end-${E.id}`)):c.push(E.id))}return c}function Fe(n,y,c,s){return n==="end-group"?c==="after":n==="group"?!(c!==void 0&&c==="after"&&!s):y===null}function De(n,y,c){const s=c[n],E=y.indexOf(n),f=y[E-1];if(!f)return"parent"in s&&s.parent!==null?{destinationId:s.parent,order:"before"}:{destinationId:null,order:"before"};if(D(s)){const d=c[f];return"parent"in d&&d.parent!==null?{destinationId:d.parent,order:"before"}:{destinationId:f,order:"before"}}const l=c[f],p=s.parent;return D(l)?p===null?{destinationId:f,order:"insert"}:{destinationId:f,order:"before"}:h(l)&&l.parent!==null&&p===null?{destinationId:f,order:"after"}:{destinationId:f,order:"before"}}function Qe(n,y,c){const s=c[n],E=y.indexOf(n),f=y[E+1];if("parent"in s&&s.parent!==null){const I=c[s.parent];if(D(I)&&I.entries[I.entries.length-1]===n)return{destinationId:s.parent,order:"after"}}if(!f)return{destinationId:null,order:"after"};if(D(s)){if(s.entries.includes(f)){const I=E+s.entries.length+1,Q=y[I];return Q?{destinationId:Q,order:"after"}:{destinationId:null,order:"after"}}return{destinationId:f,order:"after"}}const l=c[f],p=s.parent;return D(l)&&p===null?l.entries.length===0?{destinationId:f,order:"insert"}:{destinationId:l.entries[0],order:"before"}:(h(l)?l.parent:null)!==null&&p===null?{destinationId:f,order:"after"}:{destinationId:f,order:"after"}}function Se(n,y){const c=[];for(const s of y)n.includes(s)&&c.push(s);return c}const Te=()=>{const n=ie(),{linkPrevious:y,defaultTimeStrategy:c,defaultDuration:s,defaultWarnTime:E,defaultDangerTime:f,defaultTimerType:l,defaultEndAction:p}=Ie(),d=v.useCallback(()=>n.getQueryData(o),[n]),I=v.useCallback(r=>{const t=d();if(t!=null&&t.entries)return t.entries[r]},[d]),{mutateAsync:Q}=b({mutationFn:([r,t])=>ae(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>n.invalidateQueries({queryKey:o})}),H=v.useCallback(async(r,t)=>{const e=d(),i=e==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");const a={...r,id:me()};if(h(a)){if(t!=null&&t.lastEventId){const u=e.entries[t==null?void 0:t.lastEventId];h(u)&&(a.timeStart=u.timeEnd)}a.linkStart=(t==null?void 0:t.linkPrevious)??y,a.duration===void 0&&a.timeEnd===void 0&&(a.duration=M(s)),a.timeDanger===void 0&&(a.timeDanger=M(f)),a.timeWarning===void 0&&(a.timeWarning=M(E)),a.timerType===void 0&&(a.timerType=l),a.endAction===void 0&&(a.endAction=p),a.timeStrategy===void 0&&(a.timeStrategy=c)}t!=null&&t.after&&(a.after=t.after),t!=null&&t.before&&(a.before=t.before);try{await Q([i,a])}catch(u){g("Failed adding event",u)}},[d,y,s,f,E,l,p,c,Q]),{mutateAsync:F}=b({mutationFn:([r,t])=>oe(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>n.invalidateQueries({queryKey:o})}),j=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await F([e,r])}catch(e){g("Error cloning entry",e)}},[F,d]),{mutateAsync:q}=b({mutationFn:([r,t])=>se(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o),i=t.id;if(e&&i){const a={...e.entries};a[i]={...a[i],...t},n.setQueryData(o,{id:e.id,title:e.title,order:e.order,flatOrder:e.flatOrder,entries:a,revision:-1})}return{previousData:e,newEvent:t}},onError:(r,t,e)=>{e!=null&&e.previousData&&n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:async()=>{await n.invalidateQueries({queryKey:o})}}),z=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await q([e,r])}catch(e){g("Error updating event",e)}},[d,q]),V=v.useCallback(async(r,t,e,i)=>{var k;const a=(k=d())==null?void 0:k.id;if(!a)throw new Error("Rundown not initialised");if(!i&&e==="")return;const u={id:r};i?t==="timeEnd"?(u.timeStrategy=e===""?_.LockDuration:_.LockEnd,u.timeEnd=e===""?void 0:w()):t==="duration"?(u.timeStrategy=e===""?_.LockEnd:_.LockDuration,u.duration=e===""?void 0:w()):t==="timeStart"&&(u.linkStart=e==="",u.timeStart=e===""?void 0:w()):u[t]=w();try{await q([a,u])}catch(m){g("Error updating event",m)}function w(){let m=0;if(e==="p"||e==="prev"||e==="previous")m=S();else if(e.startsWith("+")||e.startsWith("p+")||e.startsWith("p +")){const A=e.substring(1);m=S()+M(A)}else m=M(e);return Math.min(m,ve-ge)}function S(){const m=n.getQueryData(o);if(!(m!=null&&m.order)||!(m!=null&&m.entries))return 0;const A=m.order.indexOf(r);if(A===0)return 0;let $=0;for(let K=A-1;K>=0;K--){const N=m.entries[m.order[K]];if(h(N)){$=N.timeEnd;break}}return $}},[d,q,n]),{mutateAsync:T}=b({mutationFn:([r,t])=>de(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o);if(e){const i=new Set(t.ids),a={...e.entries};i.forEach(u=>{if(Object.hasOwn(a,u)){const w=a[u];h(w)&&(a[u]={...w,...t})}}),n.setQueryData(o,{id:e.id,title:e.title,order:e.order,flatOrder:e.flatOrder,entries:a,revision:-1})}return{previousRundown:e}},onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousRundown)}}),J=v.useCallback(async(r,t)=>{var e;try{const i=(e=d())==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");await T([i,{data:r,ids:t}])}catch(i){g("Error updating events",i)}},[T,d]),{mutateAsync:L}=b({mutationFn:([r,t])=>ue(r,t),onMutate:async([r,t])=>{await n.cancelQueries({queryKey:o});const e=n.getQueryData(o);if(e){const{entries:i,order:a,flatOrder:u}=Me(t,e);n.setQueryData(o,{id:e.id,title:e.title,order:a,flatOrder:u,entries:i,revision:-1})}return{previousData:e}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),X=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await L([e,r])}catch(e){g("Error deleting event",e)}},[L,d]),{mutateAsync:P}=b({mutationFn:([r])=>ce(r),onMutate:async()=>{await n.cancelQueries({queryKey:o});const r=n.getQueryData(o);return n.setQueryData(o,{id:(r==null?void 0:r.id)??"default",title:(r==null?void 0:r.title)??"",order:[],flatOrder:[],entries:{},revision:-1}),{previousData:r}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),Y=v.useCallback(async()=>{var r;try{const t=(r=d())==null?void 0:r.id;if(!t)throw new Error("Rundown not initialised");await P([t])}catch(t){g("Error deleting events",t)}},[P,d]),{mutateAsync:G}=b({mutationFn:([r,t])=>le(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),Z=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await G([e,r])}catch(e){g("Error applying delay",e)}},[G,d]),{mutateAsync:U}=b({mutationFn:([r,t])=>fe(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>n.invalidateQueries({queryKey:o})}),x=v.useCallback(async r=>{var t;try{const e=(t=d())==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");await U([e,r])}catch(e){g("Error dissolving group",e)}},[d,U]),{mutateAsync:C}=b({mutationFn:([r,t])=>ye(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSuccess:r=>{if(!r.data)return;const{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w}=r.data;n.setQueryData(o,{id:t,title:e,order:i,flatOrder:a,entries:u,revision:w})},onSettled:()=>n.invalidateQueries({queryKey:o})}),ee=v.useCallback(async r=>{if(r.length!==0)try{const t=d(),e=t==null?void 0:t.id;if(!e)throw new Error("Rundown not initialised");if(r.length===1)await C([e,r]);else{const i=Se(r,t.flatOrder);await C([e,i])}}catch(t){g("Error grouping entries",t)}},[d,C]),{mutateAsync:O}=b({mutationFn:([r,t])=>Ee(r,t),onMutate:()=>n.cancelQueries({queryKey:o}),onSettled:()=>{n.invalidateQueries({queryKey:o})}}),te=v.useCallback(async(r,t)=>{var e;try{const i=d(),a=i==null?void 0:i.id;if(!a)throw new Error("Rundown not initialised");const{destinationId:u,order:w}=t==="up"?De(r,i.flatOrder,i.entries):Qe(r,i.flatOrder,i.entries);return u?(await O([a,{entryId:r,destinationId:u,order:w}]),((e=i.entries[u])==null?void 0:e.type)===we.Group?u:void 0):void 0}catch(i){g("Error re-ordering event",i)}},[d,O]),re=v.useCallback(async(r,t,e)=>{var i;try{const a=(i=d())==null?void 0:i.id;if(!a)throw new Error("Rundown not initialised");await O([a,{entryId:r,destinationId:t,order:e}])}catch(a){throw g("Error re-ordering event",a),a}},[d,O]),{mutateAsync:W}=b({mutationFn:([r,t,e])=>pe(r,t,e),onMutate:async([r,t,e])=>{await n.cancelQueries({queryKey:o});const i=n.getQueryData(o);if(i){const a={...i.entries},u=i.entries[t],w=i.entries[e];if(!h(u)||!h(w))return;const[S,k]=he(u,w);a[t]=S,a[e]=k,n.setQueryData(o,{id:i.id,title:i.title,order:i.order,flatOrder:i.flatOrder,entries:a,revision:-1})}return{previousData:i}},onError:(r,t,e)=>{n.setQueryData(o,e==null?void 0:e.previousData)},onSettled:()=>{n.invalidateQueries({queryKey:o})}}),ne=v.useCallback(async(r,t)=>{var e;try{const i=(e=d())==null?void 0:e.id;if(!i)throw new Error("Rundown not initialised");await W([i,r,t])}catch(i){g("Error re-ordering event",i)}},[d,W]);return{addEntry:H,applyDelay:Z,batchUpdateEvents:J,clone:j,deleteEntry:X,deleteAllEntries:Y,ungroup:x,getEntryById:I,groupEntries:ee,move:te,reorderEntry:re,swapEvents:ne,updateEntry:z,updateTimer:V}};function Me(n,y){const c={...y.entries};let s=[...y.order],E=[...y.flatOrder];for(let l=0;l<n.length;l++){const p=c[n[l]];f(p)}function f(l){if(D(l)||!l.parent)s=s.filter(p=>p!==l.id);else{const p=c[l.parent];p&&D(p)&&(p.entries=p.entries.filter(d=>d!==l.id))}delete c[l.id],E=E.filter(p=>p!==l.id)}return{entries:c,order:s,flatOrder:E}}function Le(n,y="compact"){if(n==null||n===0)return"";const c=n<0,s=Math.abs(n),E=y==="compact",f=E?"+":"delayed by ",l=E?"-":"ahead by ";return s<B?`${c?l:f}${R(s,"s")} sec`:s<be&&s%B===0?`${c?l:f}${R(s,"m")} min`:`${c?l:f}${R(s,"HH:mm:ss")}`}export{Re as a,Fe as c,Le as m,Te as u};
|
|
2
|
+
//# sourceMappingURL=dateConfig-WYqMzV9D.js.map
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dateConfig-DRQGMWDF.js","sources":["../../src/features/rundown/rundown.utils.ts","../../src/common/hooks/useEntryAction.ts","../../src/common/utils/dateConfig.ts"],"sourcesContent":["import { EntryId, isOntimeEvent, isOntimeGroup, RundownEntries, SupportedEntry } from 'ontime-types';\n\n/**\n * Creates a sortable list of entries\n * ------------------------------------\n * Due to limitations in dnd-kit we need to flatten the list of entries\n * This list should also be aware of any elements that are sortable (ie: group ends)\n */\nexport function makeSortableList(order: EntryId[], entries: RundownEntries): EntryId[] {\n const flatIds: EntryId[] = [];\n\n for (let i = 0; i < order.length; i++) {\n const entry = entries[order[i]];\n\n if (!entry) {\n continue;\n }\n\n if (isOntimeGroup(entry)) {\n // inside a group there are delays and events\n // there is no need for special handling\n flatIds.push(entry.id);\n flatIds.push(...entry.entries);\n\n // close the group\n flatIds.push(`end-${entry.id}`);\n } else {\n flatIds.push(entry.id);\n }\n }\n return flatIds;\n}\n\n/**\n * Checks whether a drop operation is valid\n * Currently only used for validating dropping groups\n */\nexport function canDrop(\n targetType: SupportedEntry | 'end-group',\n targetParent: EntryId | null,\n order?: 'after' | 'before',\n isTargetCollapsed?: boolean,\n): boolean {\n // inserting before would mean adding a group inside another\n if (targetType === 'end-group') {\n return order === 'after';\n }\n\n // this means swapping places with another group\n // !!! if the user is dragging down, they could be inserting into a group depending on whether the group is collapsed\n if (targetType === 'group') {\n if (order !== undefined && order === 'after' && !isTargetCollapsed) {\n return false;\n }\n return true;\n }\n\n // for all other cases, we just need to check if we are inside a group\n return targetParent === null;\n}\n\n/**\n * calculates destinations for an entry moving one position up in the rundown\n * @returns An object describing how to move the entry:\n * - destinationId: The target entry ID (null if no movement possible)\n * - order: How to position relative to the destination:\n * - 'before': Place before the destination\n * - 'after': Place after the destination\n * - 'insert': Insert into the destination (for groups)\n */\nexport function moveUp(\n entryId: EntryId,\n flatOrder: EntryId[],\n entries: RundownEntries,\n): { destinationId: EntryId | null; order: 'before' | 'after' | 'insert' } {\n const currentEntry = entries[entryId];\n const currentIndex = flatOrder.indexOf(entryId);\n const previousEntryId = flatOrder[currentIndex - 1];\n\n // 1. moving at the top of the list\n if (!previousEntryId) {\n // 1a. we are in a group and need to move outside of it\n if ('parent' in currentEntry && currentEntry.parent !== null) {\n return { destinationId: currentEntry.parent, order: 'before' };\n }\n // 1b. we are at the start of the rundown, no movement possible\n return { destinationId: null, order: 'before' };\n }\n\n // 2. moving a group (always moves at top level)\n if (isOntimeGroup(currentEntry)) {\n // 21. if previous entry is inside a group, swap with parent\n const previousEntry = entries[previousEntryId];\n if ('parent' in previousEntry && previousEntry.parent !== null) {\n return { destinationId: previousEntry.parent, order: 'before' };\n }\n\n // 2b. previous entry is at top level, we just swap places\n return { destinationId: previousEntryId, order: 'before' };\n }\n\n const previousEntry = entries[previousEntryId];\n const currentEntryParent = currentEntry.parent;\n\n // 3. moving in and out of a group\n if (isOntimeGroup(previousEntry)) {\n // 3a. if we're not already in the group, move into it\n if (currentEntryParent === null) {\n return { destinationId: previousEntryId, order: 'insert' };\n }\n // 3b. otherwise, move before the group\n return { destinationId: previousEntryId, order: 'before' };\n }\n\n // 4. moving into the same group as previous entry\n if (isOntimeEvent(previousEntry) && previousEntry.parent !== null && currentEntryParent === null) {\n return { destinationId: previousEntryId, order: 'after' };\n }\n\n // default - swap positions with previous entry\n return { destinationId: previousEntryId, order: 'before' };\n}\n\n/**\n * calculates destinations for an entry moving one position down in the rundown\n * @returns An object describing how to move the entry:\n * - destinationId: The target entry ID (null if no movement possible)\n * - order: How to position relative to the destination:\n * - 'before': Place before the destination\n * - 'after': Place after the destination\n * - 'insert': Insert into the destination (for groups)\n */\nexport function moveDown(\n entryId: EntryId,\n flatOrder: EntryId[],\n entries: RundownEntries,\n): { destinationId: EntryId | null; order: 'before' | 'after' | 'insert' } {\n const currentEntry = entries[entryId];\n const currentIndex = flatOrder.indexOf(entryId);\n const nextEntryId = flatOrder[currentIndex + 1];\n\n // 1. check if we're the last entry in a group\n if ('parent' in currentEntry && currentEntry.parent !== null) {\n const parentGroup = entries[currentEntry.parent];\n if (isOntimeGroup(parentGroup) && parentGroup.entries[parentGroup.entries.length - 1] === entryId) {\n return { destinationId: currentEntry.parent, order: 'after' };\n }\n }\n\n // 2. moving at the end of the list\n if (!nextEntryId) {\n return { destinationId: null, order: 'after' };\n }\n\n // 3. moving a group (always moves at top level)\n if (isOntimeGroup(currentEntry)) {\n // if next entry is inside this group, skip past all children\n if (currentEntry.entries.includes(nextEntryId)) {\n const afterGroupIndex = currentIndex + currentEntry.entries.length + 1;\n const afterGroupId = flatOrder[afterGroupIndex];\n\n // 2a. group is the last top level entry\n if (!afterGroupId) {\n return { destinationId: null, order: 'after' };\n }\n // 2b. move after the next top level event\n return { destinationId: afterGroupId, order: 'after' };\n }\n // 2c. empty group move after the next entry\n return { destinationId: nextEntryId, order: 'after' };\n }\n\n const nextEntry = entries[nextEntryId];\n const currentEntryParent = currentEntry.parent;\n\n // 4. handle moving relative to groups\n if (isOntimeGroup(nextEntry)) {\n if (currentEntryParent === null) {\n // we are entering a group\n if (nextEntry.entries.length === 0) {\n // 3a. if the group is empty, insert into it\n return { destinationId: nextEntryId, order: 'insert' };\n }\n // 3b. otherwise, add before the first entry in the group\n const firstGroupEntryId = nextEntry.entries[0];\n return { destinationId: firstGroupEntryId, order: 'before' };\n }\n }\n\n // 5. handle moving between group and top level\n const nextEntryParent = isOntimeEvent(nextEntry) ? nextEntry.parent : null;\n if (nextEntryParent !== null && currentEntryParent === null) {\n return { destinationId: nextEntryId, order: 'after' };\n }\n\n // default - swap positions with next entry\n return { destinationId: nextEntryId, order: 'after' };\n}\n\n/**\n * Reorders unorderedArray to match the flatOrder entries\n * Useful for operations that convert selections (out of order) to rundown\n */\nexport function orderEntries(unorderedArray: EntryId[], flatOrder: EntryId[]): EntryId[] {\n const orderedArray: EntryId[] = [];\n for (const id of flatOrder) {\n if (unorderedArray.includes(id)) {\n orderedArray.push(id);\n }\n }\n return orderedArray;\n}\n","import { useCallback } from 'react';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport {\n EntryId,\n isOntimeEvent,\n isOntimeGroup,\n MaybeString,\n OntimeEntry,\n OntimeEvent,\n Rundown,\n SupportedEntry,\n TimeField,\n TimeStrategy,\n TransientEventPayload,\n} from 'ontime-types';\nimport { dayInMs, generateId, MILLIS_PER_SECOND, parseUserTime, swapEventData } from 'ontime-utils';\n\nimport { moveDown, moveUp, orderEntries } from '../../features/rundown/rundown.utils';\nimport { RUNDOWN } from '../api/constants';\nimport {\n deleteEntries,\n patchReorderEntry,\n postAddEntry,\n postCloneEntry,\n putBatchEditEvents,\n putEditEntry,\n ReorderEntry,\n requestApplyDelay,\n requestDeleteAll,\n requestEventSwap,\n requestGroupEntries,\n requestUngroup,\n} from '../api/rundown';\nimport { logAxiosError } from '../api/utils';\nimport { useEditorSettings } from '../stores/editorSettings';\n\nexport type EventOptions = Partial<{\n // options of any new entries (event / delay / group)\n after: MaybeString;\n before: MaybeString;\n // options of entries of type OntimeEvent\n linkPrevious: boolean;\n lastEventId: MaybeString;\n}>;\n\n/**\n * Gather utilities for actions on entries\n */\nexport const useEntryActions = () => {\n const queryClient = useQueryClient();\n const {\n linkPrevious,\n defaultTimeStrategy,\n defaultDuration,\n defaultWarnTime,\n defaultDangerTime,\n defaultTimerType,\n defaultEndAction,\n } = useEditorSettings();\n\n /**\n * Returns the currently loaded rundown\n */\n const getCurrentRundownData = useCallback(() => {\n return queryClient.getQueryData<Rundown>(RUNDOWN);\n }, [queryClient]);\n\n /**\n * Looks for an entry with a given ID in the currently loaded rundown\n */\n const getEntryById = useCallback(\n (eventId: EntryId): OntimeEntry | undefined => {\n const cachedRundown = getCurrentRundownData();\n if (!cachedRundown?.entries) {\n return;\n }\n return cachedRundown.entries[eventId];\n },\n [getCurrentRundownData],\n );\n\n /**\n * Calls mutation to add new entry\n * @private\n */\n const { mutateAsync: addEntryMutation } = useMutation({\n mutationFn: ([rundownId, entry]: Parameters<typeof postAddEntry>) => postAddEntry(rundownId, entry),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Adds an entry to rundown\n */\n const addEntry = useCallback(\n async (entry: Partial<OntimeEntry>, options?: EventOptions) => {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n const newEntry: TransientEventPayload = { ...entry, id: generateId() };\n\n // ************* CHECK OPTIONS specific to events\n if (isOntimeEvent(newEntry)) {\n if (options?.lastEventId) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know this is a value\n const previousEvent = rundownData.entries[options?.lastEventId];\n if (isOntimeEvent(previousEvent)) {\n newEntry.timeStart = previousEvent.timeEnd;\n }\n }\n\n // Override event with options from editor settings\n newEntry.linkStart = options?.linkPrevious ?? linkPrevious;\n\n if (newEntry.duration === undefined && newEntry.timeEnd === undefined) {\n newEntry.duration = parseUserTime(defaultDuration);\n }\n\n if (newEntry.timeDanger === undefined) {\n newEntry.timeDanger = parseUserTime(defaultDangerTime);\n }\n\n if (newEntry.timeWarning === undefined) {\n newEntry.timeWarning = parseUserTime(defaultWarnTime);\n }\n\n if (newEntry.timerType === undefined) {\n newEntry.timerType = defaultTimerType;\n }\n\n if (newEntry.endAction === undefined) {\n newEntry.endAction = defaultEndAction;\n }\n\n if (newEntry.timeStrategy === undefined) {\n newEntry.timeStrategy = defaultTimeStrategy;\n }\n }\n\n // handle adding options that concern all event type\n if (options?.after) {\n (newEntry as TransientEventPayload).after = options.after;\n }\n if (options?.before) {\n (newEntry as TransientEventPayload).before = options.before;\n }\n\n try {\n await addEntryMutation([rundownId, newEntry]);\n } catch (error) {\n logAxiosError('Failed adding event', error);\n }\n },\n [\n getCurrentRundownData,\n linkPrevious,\n defaultDuration,\n defaultDangerTime,\n defaultWarnTime,\n defaultTimerType,\n defaultEndAction,\n defaultTimeStrategy,\n addEntryMutation,\n ],\n );\n\n /**\n * Calls mutation to clone a selection\n * @private\n */\n const { mutateAsync: cloneEntryMutation } = useMutation({\n mutationFn: ([rundownId, entryId]: Parameters<typeof postCloneEntry>) => postCloneEntry(rundownId, entryId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Clone an entry\n */\n const clone = useCallback(\n async (entryId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await cloneEntryMutation([rundownId, entryId]);\n } catch (error) {\n logAxiosError('Error cloning entry', error);\n }\n },\n [cloneEntryMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to update existing entry\n * @private\n */\n const { mutateAsync: updateEntryMutation } = useMutation({\n mutationFn: ([rundownId, newEvent]: Parameters<typeof putEditEntry>) => putEditEntry(rundownId, newEvent),\n // we optimistically update here\n onMutate: async ([_rundownId, newEvent]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n const eventId = newEvent.id;\n\n if (previousData && eventId) {\n // optimistically update object\n const newRundown = { ...previousData.entries };\n // @ts-expect-error -- we expect the events to be of same type\n newRundown[eventId] = { ...newRundown[eventId], ...newEvent };\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order: previousData.order,\n flatOrder: previousData.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous and new events\n return { previousData, newEvent };\n },\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _newEvent, context) => {\n if (context?.previousData) {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n }\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: async () => {\n await queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Updates existing entry\n */\n const updateEntry = useCallback(\n async (entry: Partial<OntimeEntry>) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await updateEntryMutation([rundownId, entry]);\n } catch (error) {\n logAxiosError('Error updating event', error);\n }\n },\n [getCurrentRundownData, updateEntryMutation],\n );\n\n /**\n * Updates time of existing event\n * @param eventId {EntryId} - id of the event\n * @param field {TimeField} - field to update\n * @param value {string} - new value string to be parsed\n * @param lockOnUpdate {boolean} - whether we will apply the lock / release on update\n */\n const updateTimer = useCallback(\n async (eventId: EntryId, field: TimeField, value: string, lockOnUpdate?: boolean) => {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n // an empty value with no lock has no domain validity\n if (!lockOnUpdate && value === '') {\n return;\n }\n\n const newEvent: Partial<OntimeEvent> = {\n id: eventId,\n };\n\n // check if we should lock the field\n if (lockOnUpdate) {\n if (field === 'timeEnd') {\n // an empty value indicates that we should unlock the field\n newEvent.timeStrategy = value === '' ? TimeStrategy.LockDuration : TimeStrategy.LockEnd;\n newEvent.timeEnd = value === '' ? undefined : calculateNewValue();\n } else if (field === 'duration') {\n // an empty value indicates that we should unlock the field\n newEvent.timeStrategy = value === '' ? TimeStrategy.LockEnd : TimeStrategy.LockDuration;\n newEvent.duration = value === '' ? undefined : calculateNewValue();\n } else if (field === 'timeStart') {\n // an empty values means we should link to the previous\n newEvent.linkStart = value === '';\n newEvent.timeStart = value === '' ? undefined : calculateNewValue();\n }\n } else {\n newEvent[field] = calculateNewValue();\n }\n\n try {\n await updateEntryMutation([rundownId, newEvent]);\n } catch (error) {\n logAxiosError('Error updating event', error);\n }\n\n /**\n * Utility function to calculate the new time value\n */\n function calculateNewValue(): number {\n let newValMillis = 0;\n\n // check for previous keyword\n if (value === 'p' || value === 'prev' || value === 'previous') {\n newValMillis = getPreviousEnd();\n\n // check for adding time keyword\n } else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {\n // TODO: is this logic solid?\n const remainingString = value.substring(1);\n newValMillis = getPreviousEnd() + parseUserTime(remainingString);\n } else {\n newValMillis = parseUserTime(value);\n }\n // dont allow timer values over 23:59:59\n return Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);\n }\n\n /**\n * Utility function to get the previous event end time\n */\n function getPreviousEnd(): number {\n const cachedRundown = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (!cachedRundown?.order || !cachedRundown?.entries) {\n return 0;\n }\n\n const index = cachedRundown.order.indexOf(eventId);\n if (index === 0) {\n return 0;\n }\n let previousEnd = 0;\n for (let i = index - 1; i >= 0; i--) {\n const event = cachedRundown.entries[cachedRundown.order[i]];\n if (isOntimeEvent(event)) {\n previousEnd = event.timeEnd;\n break;\n }\n }\n return previousEnd;\n }\n },\n [getCurrentRundownData, updateEntryMutation, queryClient],\n );\n\n /**\n * Calls mutation to edit multiple events\n * @private\n */\n const { mutateAsync: batchUpdateEventsMutation } = useMutation({\n mutationFn: ([rundownId, data]: Parameters<typeof putBatchEditEvents>) => putBatchEditEvents(rundownId, data),\n onMutate: async ([_rundownId, data]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousRundown = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (previousRundown) {\n const eventIds = new Set(data.ids);\n const newRundown = { ...previousRundown.entries };\n\n eventIds.forEach((eventId) => {\n if (Object.hasOwn(newRundown, eventId)) {\n const event = newRundown[eventId];\n if (isOntimeEvent(event)) {\n newRundown[eventId] = {\n ...event,\n ...data,\n };\n }\n }\n });\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousRundown.id,\n title: previousRundown.title,\n order: previousRundown.order,\n flatOrder: previousRundown.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous rundown\n return { previousRundown };\n },\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onError: (_error, _newEvent, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousRundown);\n },\n });\n\n const batchUpdateEvents = useCallback(\n async (data: Partial<OntimeEvent>, eventIds: EntryId[]) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await batchUpdateEventsMutation([rundownId, { data, ids: eventIds }]);\n } catch (error) {\n logAxiosError('Error updating events', error);\n }\n },\n [batchUpdateEventsMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to delete an entry\n * @private\n */\n const { mutateAsync: deleteEntryMutation } = useMutation({\n mutationFn: ([rundownId, entryIds]: Parameters<typeof deleteEntries>) => deleteEntries(rundownId, entryIds),\n // we optimistically update here\n onMutate: async ([_rundownId, entryIds]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (previousData) {\n // optimistically update object\n const { entries, order, flatOrder } = optimisticDeleteEntries(entryIds, previousData);\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order,\n flatOrder,\n entries,\n revision: -1,\n });\n }\n\n // Return a context with the previous and new events\n return { previousData };\n },\n\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _entryIds, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Deletes an event entry from the rundown\n */\n const deleteEntry = useCallback(\n async (entryIds: EntryId[]) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await deleteEntryMutation([rundownId, entryIds]);\n } catch (error) {\n logAxiosError('Error deleting event', error);\n }\n },\n [deleteEntryMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to delete all events\n * @private\n */\n const { mutateAsync: deleteAllEntriesMutation } = useMutation({\n mutationFn: ([rundownId]: Parameters<typeof requestDeleteAll>) => requestDeleteAll(rundownId),\n // we optimistically update here\n onMutate: async () => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n // optimistically update object\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData?.id ?? 'default',\n title: previousData?.title ?? '',\n order: [],\n flatOrder: [],\n entries: {},\n revision: -1,\n });\n\n // Return a context with the previous and new events\n return { previousData };\n },\n\n // Mutation fails, rollback optimist update\n onError: (_error, _, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Deletes all entries in the rundown\n */\n const deleteAllEntries = useCallback(async () => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await deleteAllEntriesMutation([rundownId]);\n } catch (error) {\n logAxiosError('Error deleting events', error);\n }\n }, [deleteAllEntriesMutation, getCurrentRundownData]);\n\n /**\n * Calls mutation to apply a delay\n * @private\n */\n const { mutateAsync: applyDelayMutation } = useMutation({\n mutationFn: ([rundownId, delayId]: Parameters<typeof requestApplyDelay>) => requestApplyDelay(rundownId, delayId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n // Mutation finished, failed or successful\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Applies a given delay\n */\n const applyDelay = useCallback(\n async (delayEventId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await applyDelayMutation([rundownId, delayEventId]);\n } catch (error) {\n logAxiosError('Error applying delay', error);\n }\n },\n [applyDelayMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to dissolve a group\n * @private\n */\n const { mutateAsync: ungroupMutation } = useMutation({\n mutationFn: ([rundownId, groupId]: Parameters<typeof requestUngroup>) => requestUngroup(rundownId, groupId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Deletes a group and moves its events to the top level\n */\n const ungroup = useCallback(\n async (groupId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await ungroupMutation([rundownId, groupId]);\n } catch (error) {\n logAxiosError('Error dissolving group', error);\n }\n },\n [getCurrentRundownData, ungroupMutation],\n );\n\n /**\n * Calls mutation to create a group with a selection\n * @private\n */\n const { mutateAsync: groupEntriesMutation } = useMutation({\n mutationFn: ([rundownId, entryIds]: Parameters<typeof requestGroupEntries>) =>\n requestGroupEntries(rundownId, entryIds),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Create a group with a selection\n */\n const groupEntries = useCallback(\n async (entryIds: EntryId[]) => {\n if (entryIds.length === 0) return;\n\n try {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n if (entryIds.length === 1) {\n await groupEntriesMutation([rundownId, entryIds]);\n } else {\n // the user selection may be out of order\n const orderedIds = orderEntries(entryIds, rundownData.flatOrder);\n await groupEntriesMutation([rundownId, orderedIds]);\n }\n } catch (error) {\n logAxiosError('Error grouping entries', error);\n }\n },\n [getCurrentRundownData, groupEntriesMutation],\n );\n\n /**\n * Calls mutation to reorder an entry\n * @private\n */\n const { mutateAsync: reorderEntryMutation } = useMutation({\n mutationFn: ([rundownId, data]: Parameters<typeof patchReorderEntry>) => patchReorderEntry(rundownId, data),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Reorders a given entry one step up or down in the timeline\n */\n const move = useCallback(\n async (entryId: EntryId, direction: 'up' | 'down') => {\n try {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n const { destinationId, order } =\n direction === 'up'\n ? moveUp(entryId, rundownData.flatOrder, rundownData.entries)\n : moveDown(entryId, rundownData.flatOrder, rundownData.entries);\n\n if (!destinationId) {\n return; // noop\n }\n\n const reorderObject: ReorderEntry = {\n entryId,\n destinationId,\n order,\n };\n await reorderEntryMutation([rundownId, reorderObject]);\n // the rundown needs to know whether we moved into a group\n return rundownData.entries[destinationId]?.type === SupportedEntry.Group ? destinationId : undefined;\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n }\n return undefined;\n },\n [getCurrentRundownData, reorderEntryMutation],\n );\n /**\n * Reorders a given entry\n */\n const reorderEntry = useCallback(\n async (entryId: EntryId, destinationId: EntryId, order: 'before' | 'after' | 'insert') => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await reorderEntryMutation([\n rundownId,\n {\n entryId,\n destinationId,\n order,\n },\n ]);\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n throw error; // rethrow to handle in the component\n }\n },\n [getCurrentRundownData, reorderEntryMutation],\n );\n\n /**\n * Calls mutation to swap events\n * @private\n */\n const { mutateAsync: swapEventsMutation } = useMutation({\n mutationFn: ([rundownId, from, to]: Parameters<typeof requestEventSwap>) => requestEventSwap(rundownId, from, to),\n // we optimistically update here\n onMutate: async ([_rundownId, from, to]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n if (previousData) {\n // optimistically update object\n const newRundown = { ...previousData.entries };\n const eventA = previousData.entries[from];\n const eventB = previousData.entries[to];\n\n if (!isOntimeEvent(eventA) || !isOntimeEvent(eventB)) {\n return;\n }\n\n const [newA, newB] = swapEventData(eventA, eventB);\n newRundown[from] = newA;\n newRundown[to] = newB;\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order: previousData.order,\n flatOrder: previousData.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous events\n return { previousData };\n },\n\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _eventId, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Swaps the schedule of two events\n */\n const swapEvents = useCallback(\n async (from: EntryId, to: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await swapEventsMutation([rundownId, from, to]);\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n }\n },\n [getCurrentRundownData, swapEventsMutation],\n );\n\n return {\n addEntry,\n applyDelay,\n batchUpdateEvents,\n clone,\n deleteEntry,\n deleteAllEntries,\n ungroup,\n getEntryById,\n groupEntries,\n move,\n reorderEntry,\n swapEvents,\n updateEntry,\n updateTimer,\n };\n};\n\n/**\n * Utility to optimistically delete entries from client cache\n */\nfunction optimisticDeleteEntries(entryIds: EntryId[], rundown: Rundown) {\n const entries = { ...rundown.entries };\n let order = [...rundown.order];\n let flatOrder = [...rundown.flatOrder];\n\n for (let i = 0; i < entryIds.length; i++) {\n const entry = entries[entryIds[i]];\n deleteEntry(entry);\n }\n\n function deleteEntry(entry: OntimeEntry) {\n if (isOntimeGroup(entry) || !entry.parent) {\n order = order.filter((id) => id !== entry.id);\n } else {\n const parent = entries[entry.parent];\n if (parent && isOntimeGroup(parent)) {\n parent.entries = parent.entries.filter((parentEntry) => parentEntry !== entry.id);\n }\n }\n\n delete entries[entry.id];\n flatOrder = flatOrder.filter((id) => id !== entry.id);\n }\n\n return { entries, order, flatOrder };\n}\n","import { MaybeNumber } from 'ontime-types';\nimport { formatFromMillis, MILLIS_PER_HOUR, MILLIS_PER_MINUTE } from 'ontime-utils';\n\n/**\n * Parses a value in millis to a string which encodes a delay\n * @param millis\n * @param format\n */\nexport function millisToDelayString(millis: MaybeNumber, format: 'compact' | 'expanded' = 'compact'): string {\n if (millis == null || millis === 0) {\n return '';\n }\n\n const isNegative = millis < 0;\n const absMillis = Math.abs(millis);\n const isCompact = format === 'compact';\n const delayed = isCompact ? '+' : 'delayed by ';\n const ahead = isCompact ? '-' : 'ahead by ';\n\n if (absMillis < MILLIS_PER_MINUTE) {\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 's')} sec`;\n } else if (absMillis < MILLIS_PER_HOUR && absMillis % MILLIS_PER_MINUTE === 0) {\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 'm')} min`;\n }\n\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 'HH:mm:ss')}`;\n}\n"],"names":["makeSortableList","order","entries","flatIds","i","entry","isOntimeGroup","canDrop","targetType","targetParent","isTargetCollapsed","moveUp","entryId","flatOrder","currentEntry","currentIndex","previousEntryId","previousEntry","currentEntryParent","isOntimeEvent","moveDown","nextEntryId","parentGroup","afterGroupIndex","afterGroupId","nextEntry","orderEntries","unorderedArray","orderedArray","id","useEntryActions","queryClient","useQueryClient","linkPrevious","defaultTimeStrategy","defaultDuration","defaultWarnTime","defaultDangerTime","defaultTimerType","defaultEndAction","useEditorSettings","getCurrentRundownData","useCallback","RUNDOWN","getEntryById","eventId","cachedRundown","addEntryMutation","useMutation","rundownId","postAddEntry","addEntry","options","rundownData","newEntry","generateId","previousEvent","parseUserTime","error","logAxiosError","cloneEntryMutation","postCloneEntry","clone","_a","updateEntryMutation","newEvent","putEditEntry","_rundownId","previousData","newRundown","_error","_newEvent","context","updateEntry","updateTimer","field","value","lockOnUpdate","TimeStrategy","calculateNewValue","newValMillis","getPreviousEnd","remainingString","dayInMs","MILLIS_PER_SECOND","index","previousEnd","event","batchUpdateEventsMutation","data","putBatchEditEvents","previousRundown","eventIds","response","title","revision","batchUpdateEvents","deleteEntryMutation","entryIds","deleteEntries","optimisticDeleteEntries","_entryIds","deleteEntry","deleteAllEntriesMutation","requestDeleteAll","_","deleteAllEntries","applyDelayMutation","delayId","requestApplyDelay","applyDelay","delayEventId","ungroupMutation","groupId","requestUngroup","ungroup","groupEntriesMutation","requestGroupEntries","groupEntries","orderedIds","reorderEntryMutation","patchReorderEntry","move","direction","destinationId","SupportedEntry","reorderEntry","swapEventsMutation","from","to","requestEventSwap","eventA","eventB","newA","newB","swapEventData","_eventId","swapEvents","rundown","parent","parentEntry","millisToDelayString","millis","format","isNegative","absMillis","isCompact","delayed","ahead","MILLIS_PER_MINUTE","formatFromMillis","MILLIS_PER_HOUR"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dateConfig-WYqMzV9D.js","sources":["../../src/features/rundown/rundown.utils.ts","../../src/common/hooks/useEntryAction.ts","../../src/common/utils/dateConfig.ts"],"sourcesContent":["import { EntryId, isOntimeEvent, isOntimeGroup, RundownEntries, SupportedEntry } from 'ontime-types';\n\n/**\n * Creates a sortable list of entries\n * ------------------------------------\n * Due to limitations in dnd-kit we need to flatten the list of entries\n * This list should also be aware of any elements that are sortable (ie: group ends)\n */\nexport function makeSortableList(order: EntryId[], entries: RundownEntries): EntryId[] {\n const flatIds: EntryId[] = [];\n\n for (let i = 0; i < order.length; i++) {\n const entry = entries[order[i]];\n\n if (!entry) {\n continue;\n }\n\n if (isOntimeGroup(entry)) {\n // inside a group there are delays and events\n // there is no need for special handling\n flatIds.push(entry.id);\n flatIds.push(...entry.entries);\n\n // close the group\n flatIds.push(`end-${entry.id}`);\n } else {\n flatIds.push(entry.id);\n }\n }\n return flatIds;\n}\n\n/**\n * Checks whether a drop operation is valid\n * Currently only used for validating dropping groups\n */\nexport function canDrop(\n targetType: SupportedEntry | 'end-group',\n targetParent: EntryId | null,\n order?: 'after' | 'before',\n isTargetCollapsed?: boolean,\n): boolean {\n // inserting before would mean adding a group inside another\n if (targetType === 'end-group') {\n return order === 'after';\n }\n\n // this means swapping places with another group\n // !!! if the user is dragging down, they could be inserting into a group depending on whether the group is collapsed\n if (targetType === 'group') {\n if (order !== undefined && order === 'after' && !isTargetCollapsed) {\n return false;\n }\n return true;\n }\n\n // for all other cases, we just need to check if we are inside a group\n return targetParent === null;\n}\n\n/**\n * calculates destinations for an entry moving one position up in the rundown\n * @returns An object describing how to move the entry:\n * - destinationId: The target entry ID (null if no movement possible)\n * - order: How to position relative to the destination:\n * - 'before': Place before the destination\n * - 'after': Place after the destination\n * - 'insert': Insert into the destination (for groups)\n */\nexport function moveUp(\n entryId: EntryId,\n flatOrder: EntryId[],\n entries: RundownEntries,\n): { destinationId: EntryId | null; order: 'before' | 'after' | 'insert' } {\n const currentEntry = entries[entryId];\n const currentIndex = flatOrder.indexOf(entryId);\n const previousEntryId = flatOrder[currentIndex - 1];\n\n // 1. moving at the top of the list\n if (!previousEntryId) {\n // 1a. we are in a group and need to move outside of it\n if ('parent' in currentEntry && currentEntry.parent !== null) {\n return { destinationId: currentEntry.parent, order: 'before' };\n }\n // 1b. we are at the start of the rundown, no movement possible\n return { destinationId: null, order: 'before' };\n }\n\n // 2. moving a group (always moves at top level)\n if (isOntimeGroup(currentEntry)) {\n // 21. if previous entry is inside a group, swap with parent\n const previousEntry = entries[previousEntryId];\n if ('parent' in previousEntry && previousEntry.parent !== null) {\n return { destinationId: previousEntry.parent, order: 'before' };\n }\n\n // 2b. previous entry is at top level, we just swap places\n return { destinationId: previousEntryId, order: 'before' };\n }\n\n const previousEntry = entries[previousEntryId];\n const currentEntryParent = currentEntry.parent;\n\n // 3. moving in and out of a group\n if (isOntimeGroup(previousEntry)) {\n // 3a. if we're not already in the group, move into it\n if (currentEntryParent === null) {\n return { destinationId: previousEntryId, order: 'insert' };\n }\n // 3b. otherwise, move before the group\n return { destinationId: previousEntryId, order: 'before' };\n }\n\n // 4. moving into the same group as previous entry\n if (isOntimeEvent(previousEntry) && previousEntry.parent !== null && currentEntryParent === null) {\n return { destinationId: previousEntryId, order: 'after' };\n }\n\n // default - swap positions with previous entry\n return { destinationId: previousEntryId, order: 'before' };\n}\n\n/**\n * calculates destinations for an entry moving one position down in the rundown\n * @returns An object describing how to move the entry:\n * - destinationId: The target entry ID (null if no movement possible)\n * - order: How to position relative to the destination:\n * - 'before': Place before the destination\n * - 'after': Place after the destination\n * - 'insert': Insert into the destination (for groups)\n */\nexport function moveDown(\n entryId: EntryId,\n flatOrder: EntryId[],\n entries: RundownEntries,\n): { destinationId: EntryId | null; order: 'before' | 'after' | 'insert' } {\n const currentEntry = entries[entryId];\n const currentIndex = flatOrder.indexOf(entryId);\n const nextEntryId = flatOrder[currentIndex + 1];\n\n // 1. check if we're the last entry in a group\n if ('parent' in currentEntry && currentEntry.parent !== null) {\n const parentGroup = entries[currentEntry.parent];\n if (isOntimeGroup(parentGroup) && parentGroup.entries[parentGroup.entries.length - 1] === entryId) {\n return { destinationId: currentEntry.parent, order: 'after' };\n }\n }\n\n // 2. moving at the end of the list\n if (!nextEntryId) {\n return { destinationId: null, order: 'after' };\n }\n\n // 3. moving a group (always moves at top level)\n if (isOntimeGroup(currentEntry)) {\n // if next entry is inside this group, skip past all children\n if (currentEntry.entries.includes(nextEntryId)) {\n const afterGroupIndex = currentIndex + currentEntry.entries.length + 1;\n const afterGroupId = flatOrder[afterGroupIndex];\n\n // 2a. group is the last top level entry\n if (!afterGroupId) {\n return { destinationId: null, order: 'after' };\n }\n // 2b. move after the next top level event\n return { destinationId: afterGroupId, order: 'after' };\n }\n // 2c. empty group move after the next entry\n return { destinationId: nextEntryId, order: 'after' };\n }\n\n const nextEntry = entries[nextEntryId];\n const currentEntryParent = currentEntry.parent;\n\n // 4. handle moving relative to groups\n if (isOntimeGroup(nextEntry)) {\n if (currentEntryParent === null) {\n // we are entering a group\n if (nextEntry.entries.length === 0) {\n // 3a. if the group is empty, insert into it\n return { destinationId: nextEntryId, order: 'insert' };\n }\n // 3b. otherwise, add before the first entry in the group\n const firstGroupEntryId = nextEntry.entries[0];\n return { destinationId: firstGroupEntryId, order: 'before' };\n }\n }\n\n // 5. handle moving between group and top level\n const nextEntryParent = isOntimeEvent(nextEntry) ? nextEntry.parent : null;\n if (nextEntryParent !== null && currentEntryParent === null) {\n return { destinationId: nextEntryId, order: 'after' };\n }\n\n // default - swap positions with next entry\n return { destinationId: nextEntryId, order: 'after' };\n}\n\n/**\n * Reorders unorderedArray to match the flatOrder entries\n * Useful for operations that convert selections (out of order) to rundown\n */\nexport function orderEntries(unorderedArray: EntryId[], flatOrder: EntryId[]): EntryId[] {\n const orderedArray: EntryId[] = [];\n for (const id of flatOrder) {\n if (unorderedArray.includes(id)) {\n orderedArray.push(id);\n }\n }\n return orderedArray;\n}\n","import { useCallback } from 'react';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport {\n EntryId,\n isOntimeEvent,\n isOntimeGroup,\n MaybeString,\n OntimeEntry,\n OntimeEvent,\n Rundown,\n SupportedEntry,\n TimeField,\n TimeStrategy,\n TransientEventPayload,\n} from 'ontime-types';\nimport { dayInMs, generateId, MILLIS_PER_SECOND, parseUserTime, swapEventData } from 'ontime-utils';\n\nimport { moveDown, moveUp, orderEntries } from '../../features/rundown/rundown.utils';\nimport { RUNDOWN } from '../api/constants';\nimport {\n deleteEntries,\n patchReorderEntry,\n postAddEntry,\n postCloneEntry,\n putBatchEditEvents,\n putEditEntry,\n ReorderEntry,\n requestApplyDelay,\n requestDeleteAll,\n requestEventSwap,\n requestGroupEntries,\n requestUngroup,\n} from '../api/rundown';\nimport { logAxiosError } from '../api/utils';\nimport { useEditorSettings } from '../stores/editorSettings';\n\nexport type EventOptions = Partial<{\n // options of any new entries (event / delay / group)\n after: MaybeString;\n before: MaybeString;\n // options of entries of type OntimeEvent\n linkPrevious: boolean;\n lastEventId: MaybeString;\n}>;\n\n/**\n * Gather utilities for actions on entries\n */\nexport const useEntryActions = () => {\n const queryClient = useQueryClient();\n const {\n linkPrevious,\n defaultTimeStrategy,\n defaultDuration,\n defaultWarnTime,\n defaultDangerTime,\n defaultTimerType,\n defaultEndAction,\n } = useEditorSettings();\n\n /**\n * Returns the currently loaded rundown\n */\n const getCurrentRundownData = useCallback(() => {\n return queryClient.getQueryData<Rundown>(RUNDOWN);\n }, [queryClient]);\n\n /**\n * Looks for an entry with a given ID in the currently loaded rundown\n */\n const getEntryById = useCallback(\n (eventId: EntryId): OntimeEntry | undefined => {\n const cachedRundown = getCurrentRundownData();\n if (!cachedRundown?.entries) {\n return;\n }\n return cachedRundown.entries[eventId];\n },\n [getCurrentRundownData],\n );\n\n /**\n * Calls mutation to add new entry\n * @private\n */\n const { mutateAsync: addEntryMutation } = useMutation({\n mutationFn: ([rundownId, entry]: Parameters<typeof postAddEntry>) => postAddEntry(rundownId, entry),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Adds an entry to rundown\n */\n const addEntry = useCallback(\n async (entry: Partial<OntimeEntry>, options?: EventOptions) => {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n const newEntry: TransientEventPayload = { ...entry, id: generateId() };\n\n // ************* CHECK OPTIONS specific to events\n if (isOntimeEvent(newEntry)) {\n if (options?.lastEventId) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we know this is a value\n const previousEvent = rundownData.entries[options?.lastEventId];\n if (isOntimeEvent(previousEvent)) {\n newEntry.timeStart = previousEvent.timeEnd;\n }\n }\n\n // Override event with options from editor settings\n newEntry.linkStart = options?.linkPrevious ?? linkPrevious;\n\n if (newEntry.duration === undefined && newEntry.timeEnd === undefined) {\n newEntry.duration = parseUserTime(defaultDuration);\n }\n\n if (newEntry.timeDanger === undefined) {\n newEntry.timeDanger = parseUserTime(defaultDangerTime);\n }\n\n if (newEntry.timeWarning === undefined) {\n newEntry.timeWarning = parseUserTime(defaultWarnTime);\n }\n\n if (newEntry.timerType === undefined) {\n newEntry.timerType = defaultTimerType;\n }\n\n if (newEntry.endAction === undefined) {\n newEntry.endAction = defaultEndAction;\n }\n\n if (newEntry.timeStrategy === undefined) {\n newEntry.timeStrategy = defaultTimeStrategy;\n }\n }\n\n // handle adding options that concern all event type\n if (options?.after) {\n (newEntry as TransientEventPayload).after = options.after;\n }\n if (options?.before) {\n (newEntry as TransientEventPayload).before = options.before;\n }\n\n try {\n await addEntryMutation([rundownId, newEntry]);\n } catch (error) {\n logAxiosError('Failed adding event', error);\n }\n },\n [\n getCurrentRundownData,\n linkPrevious,\n defaultDuration,\n defaultDangerTime,\n defaultWarnTime,\n defaultTimerType,\n defaultEndAction,\n defaultTimeStrategy,\n addEntryMutation,\n ],\n );\n\n /**\n * Calls mutation to clone a selection\n * @private\n */\n const { mutateAsync: cloneEntryMutation } = useMutation({\n mutationFn: ([rundownId, entryId]: Parameters<typeof postCloneEntry>) => postCloneEntry(rundownId, entryId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Clone an entry\n */\n const clone = useCallback(\n async (entryId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await cloneEntryMutation([rundownId, entryId]);\n } catch (error) {\n logAxiosError('Error cloning entry', error);\n }\n },\n [cloneEntryMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to update existing entry\n * @private\n */\n const { mutateAsync: updateEntryMutation } = useMutation({\n mutationFn: ([rundownId, newEvent]: Parameters<typeof putEditEntry>) => putEditEntry(rundownId, newEvent),\n // we optimistically update here\n onMutate: async ([_rundownId, newEvent]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n const eventId = newEvent.id;\n\n if (previousData && eventId) {\n // optimistically update object\n const newRundown = { ...previousData.entries };\n // @ts-expect-error -- we expect the events to be of same type\n newRundown[eventId] = { ...newRundown[eventId], ...newEvent };\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order: previousData.order,\n flatOrder: previousData.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous and new events\n return { previousData, newEvent };\n },\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _newEvent, context) => {\n if (context?.previousData) {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n }\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: async () => {\n await queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Updates existing entry\n */\n const updateEntry = useCallback(\n async (entry: Partial<OntimeEntry>) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await updateEntryMutation([rundownId, entry]);\n } catch (error) {\n logAxiosError('Error updating event', error);\n }\n },\n [getCurrentRundownData, updateEntryMutation],\n );\n\n /**\n * Updates time of existing event\n * @param eventId {EntryId} - id of the event\n * @param field {TimeField} - field to update\n * @param value {string} - new value string to be parsed\n * @param lockOnUpdate {boolean} - whether we will apply the lock / release on update\n */\n const updateTimer = useCallback(\n async (eventId: EntryId, field: TimeField, value: string, lockOnUpdate?: boolean) => {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n // an empty value with no lock has no domain validity\n if (!lockOnUpdate && value === '') {\n return;\n }\n\n const newEvent: Partial<OntimeEvent> = {\n id: eventId,\n };\n\n // check if we should lock the field\n if (lockOnUpdate) {\n if (field === 'timeEnd') {\n // an empty value indicates that we should unlock the field\n newEvent.timeStrategy = value === '' ? TimeStrategy.LockDuration : TimeStrategy.LockEnd;\n newEvent.timeEnd = value === '' ? undefined : calculateNewValue();\n } else if (field === 'duration') {\n // an empty value indicates that we should unlock the field\n newEvent.timeStrategy = value === '' ? TimeStrategy.LockEnd : TimeStrategy.LockDuration;\n newEvent.duration = value === '' ? undefined : calculateNewValue();\n } else if (field === 'timeStart') {\n // an empty values means we should link to the previous\n newEvent.linkStart = value === '';\n newEvent.timeStart = value === '' ? undefined : calculateNewValue();\n }\n } else {\n newEvent[field] = calculateNewValue();\n }\n\n try {\n await updateEntryMutation([rundownId, newEvent]);\n } catch (error) {\n logAxiosError('Error updating event', error);\n }\n\n /**\n * Utility function to calculate the new time value\n */\n function calculateNewValue(): number {\n let newValMillis = 0;\n\n // check for previous keyword\n if (value === 'p' || value === 'prev' || value === 'previous') {\n newValMillis = getPreviousEnd();\n\n // check for adding time keyword\n } else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {\n // TODO: is this logic solid?\n const remainingString = value.substring(1);\n newValMillis = getPreviousEnd() + parseUserTime(remainingString);\n } else {\n newValMillis = parseUserTime(value);\n }\n // dont allow timer values over 23:59:59\n return Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);\n }\n\n /**\n * Utility function to get the previous event end time\n */\n function getPreviousEnd(): number {\n const cachedRundown = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (!cachedRundown?.order || !cachedRundown?.entries) {\n return 0;\n }\n\n const index = cachedRundown.order.indexOf(eventId);\n if (index === 0) {\n return 0;\n }\n let previousEnd = 0;\n for (let i = index - 1; i >= 0; i--) {\n const event = cachedRundown.entries[cachedRundown.order[i]];\n if (isOntimeEvent(event)) {\n previousEnd = event.timeEnd;\n break;\n }\n }\n return previousEnd;\n }\n },\n [getCurrentRundownData, updateEntryMutation, queryClient],\n );\n\n /**\n * Calls mutation to edit multiple events\n * @private\n */\n const { mutateAsync: batchUpdateEventsMutation } = useMutation({\n mutationFn: ([rundownId, data]: Parameters<typeof putBatchEditEvents>) => putBatchEditEvents(rundownId, data),\n onMutate: async ([_rundownId, data]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousRundown = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (previousRundown) {\n const eventIds = new Set(data.ids);\n const newRundown = { ...previousRundown.entries };\n\n eventIds.forEach((eventId) => {\n if (Object.hasOwn(newRundown, eventId)) {\n const event = newRundown[eventId];\n if (isOntimeEvent(event)) {\n newRundown[eventId] = {\n ...event,\n ...data,\n };\n }\n }\n });\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousRundown.id,\n title: previousRundown.title,\n order: previousRundown.order,\n flatOrder: previousRundown.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous rundown\n return { previousRundown };\n },\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onError: (_error, _newEvent, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousRundown);\n },\n });\n\n const batchUpdateEvents = useCallback(\n async (data: Partial<OntimeEvent>, eventIds: EntryId[]) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await batchUpdateEventsMutation([rundownId, { data, ids: eventIds }]);\n } catch (error) {\n logAxiosError('Error updating events', error);\n }\n },\n [batchUpdateEventsMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to delete an entry\n * @private\n */\n const { mutateAsync: deleteEntryMutation } = useMutation({\n mutationFn: ([rundownId, entryIds]: Parameters<typeof deleteEntries>) => deleteEntries(rundownId, entryIds),\n // we optimistically update here\n onMutate: async ([_rundownId, entryIds]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n if (previousData) {\n // optimistically update object\n const { entries, order, flatOrder } = optimisticDeleteEntries(entryIds, previousData);\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order,\n flatOrder,\n entries,\n revision: -1,\n });\n }\n\n // Return a context with the previous and new events\n return { previousData };\n },\n\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _entryIds, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Deletes an event entry from the rundown\n */\n const deleteEntry = useCallback(\n async (entryIds: EntryId[]) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await deleteEntryMutation([rundownId, entryIds]);\n } catch (error) {\n logAxiosError('Error deleting event', error);\n }\n },\n [deleteEntryMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to delete all events\n * @private\n */\n const { mutateAsync: deleteAllEntriesMutation } = useMutation({\n mutationFn: ([rundownId]: Parameters<typeof requestDeleteAll>) => requestDeleteAll(rundownId),\n // we optimistically update here\n onMutate: async () => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n\n // optimistically update object\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData?.id ?? 'default',\n title: previousData?.title ?? '',\n order: [],\n flatOrder: [],\n entries: {},\n revision: -1,\n });\n\n // Return a context with the previous and new events\n return { previousData };\n },\n\n // Mutation fails, rollback optimist update\n onError: (_error, _, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Deletes all entries in the rundown\n */\n const deleteAllEntries = useCallback(async () => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await deleteAllEntriesMutation([rundownId]);\n } catch (error) {\n logAxiosError('Error deleting events', error);\n }\n }, [deleteAllEntriesMutation, getCurrentRundownData]);\n\n /**\n * Calls mutation to apply a delay\n * @private\n */\n const { mutateAsync: applyDelayMutation } = useMutation({\n mutationFn: ([rundownId, delayId]: Parameters<typeof requestApplyDelay>) => requestApplyDelay(rundownId, delayId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n // Mutation finished, failed or successful\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Applies a given delay\n */\n const applyDelay = useCallback(\n async (delayEventId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await applyDelayMutation([rundownId, delayEventId]);\n } catch (error) {\n logAxiosError('Error applying delay', error);\n }\n },\n [applyDelayMutation, getCurrentRundownData],\n );\n\n /**\n * Calls mutation to dissolve a group\n * @private\n */\n const { mutateAsync: ungroupMutation } = useMutation({\n mutationFn: ([rundownId, groupId]: Parameters<typeof requestUngroup>) => requestUngroup(rundownId, groupId),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Deletes a group and moves its events to the top level\n */\n const ungroup = useCallback(\n async (groupId: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await ungroupMutation([rundownId, groupId]);\n } catch (error) {\n logAxiosError('Error dissolving group', error);\n }\n },\n [getCurrentRundownData, ungroupMutation],\n );\n\n /**\n * Calls mutation to create a group with a selection\n * @private\n */\n const { mutateAsync: groupEntriesMutation } = useMutation({\n mutationFn: ([rundownId, entryIds]: Parameters<typeof requestGroupEntries>) =>\n requestGroupEntries(rundownId, entryIds),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSuccess: (response) => {\n if (!response.data) return;\n\n const { id, title, order, flatOrder, entries, revision } = response.data;\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id,\n title,\n order,\n flatOrder,\n entries,\n revision,\n });\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: RUNDOWN }),\n });\n\n /**\n * Create a group with a selection\n */\n const groupEntries = useCallback(\n async (entryIds: EntryId[]) => {\n if (entryIds.length === 0) return;\n\n try {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n if (entryIds.length === 1) {\n await groupEntriesMutation([rundownId, entryIds]);\n } else {\n // the user selection may be out of order\n const orderedIds = orderEntries(entryIds, rundownData.flatOrder);\n await groupEntriesMutation([rundownId, orderedIds]);\n }\n } catch (error) {\n logAxiosError('Error grouping entries', error);\n }\n },\n [getCurrentRundownData, groupEntriesMutation],\n );\n\n /**\n * Calls mutation to reorder an entry\n * @private\n */\n const { mutateAsync: reorderEntryMutation } = useMutation({\n mutationFn: ([rundownId, data]: Parameters<typeof patchReorderEntry>) => patchReorderEntry(rundownId, data),\n onMutate: () => queryClient.cancelQueries({ queryKey: RUNDOWN }),\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Reorders a given entry one step up or down in the timeline\n */\n const move = useCallback(\n async (entryId: EntryId, direction: 'up' | 'down') => {\n try {\n const rundownData = getCurrentRundownData();\n const rundownId = rundownData?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n const { destinationId, order } =\n direction === 'up'\n ? moveUp(entryId, rundownData.flatOrder, rundownData.entries)\n : moveDown(entryId, rundownData.flatOrder, rundownData.entries);\n\n if (!destinationId) {\n return; // noop\n }\n\n const reorderObject: ReorderEntry = {\n entryId,\n destinationId,\n order,\n };\n await reorderEntryMutation([rundownId, reorderObject]);\n // the rundown needs to know whether we moved into a group\n return rundownData.entries[destinationId]?.type === SupportedEntry.Group ? destinationId : undefined;\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n }\n return undefined;\n },\n [getCurrentRundownData, reorderEntryMutation],\n );\n /**\n * Reorders a given entry\n */\n const reorderEntry = useCallback(\n async (entryId: EntryId, destinationId: EntryId, order: 'before' | 'after' | 'insert') => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await reorderEntryMutation([\n rundownId,\n {\n entryId,\n destinationId,\n order,\n },\n ]);\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n throw error; // rethrow to handle in the component\n }\n },\n [getCurrentRundownData, reorderEntryMutation],\n );\n\n /**\n * Calls mutation to swap events\n * @private\n */\n const { mutateAsync: swapEventsMutation } = useMutation({\n mutationFn: ([rundownId, from, to]: Parameters<typeof requestEventSwap>) => requestEventSwap(rundownId, from, to),\n // we optimistically update here\n onMutate: async ([_rundownId, from, to]) => {\n // cancel ongoing queries\n await queryClient.cancelQueries({ queryKey: RUNDOWN });\n\n // Snapshot the previous value\n const previousData = queryClient.getQueryData<Rundown>(RUNDOWN);\n if (previousData) {\n // optimistically update object\n const newRundown = { ...previousData.entries };\n const eventA = previousData.entries[from];\n const eventB = previousData.entries[to];\n\n if (!isOntimeEvent(eventA) || !isOntimeEvent(eventB)) {\n return;\n }\n\n const [newA, newB] = swapEventData(eventA, eventB);\n newRundown[from] = newA;\n newRundown[to] = newB;\n\n queryClient.setQueryData<Rundown>(RUNDOWN, {\n id: previousData.id,\n title: previousData.title,\n order: previousData.order,\n flatOrder: previousData.flatOrder,\n entries: newRundown,\n revision: -1,\n });\n }\n\n // Return a context with the previous events\n return { previousData };\n },\n\n // Mutation fails, rollback undoes optimist update\n onError: (_error, _eventId, context) => {\n queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);\n },\n // Mutation finished, failed or successful\n // Fetch anyway, just to be sure\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: RUNDOWN });\n },\n });\n\n /**\n * Swaps the schedule of two events\n */\n const swapEvents = useCallback(\n async (from: EntryId, to: EntryId) => {\n try {\n const rundownId = getCurrentRundownData()?.id;\n if (!rundownId) {\n throw new Error('Rundown not initialised');\n }\n\n await swapEventsMutation([rundownId, from, to]);\n } catch (error) {\n logAxiosError('Error re-ordering event', error);\n }\n },\n [getCurrentRundownData, swapEventsMutation],\n );\n\n return {\n addEntry,\n applyDelay,\n batchUpdateEvents,\n clone,\n deleteEntry,\n deleteAllEntries,\n ungroup,\n getEntryById,\n groupEntries,\n move,\n reorderEntry,\n swapEvents,\n updateEntry,\n updateTimer,\n };\n};\n\n/**\n * Utility to optimistically delete entries from client cache\n */\nfunction optimisticDeleteEntries(entryIds: EntryId[], rundown: Rundown) {\n const entries = { ...rundown.entries };\n let order = [...rundown.order];\n let flatOrder = [...rundown.flatOrder];\n\n for (let i = 0; i < entryIds.length; i++) {\n const entry = entries[entryIds[i]];\n deleteEntry(entry);\n }\n\n function deleteEntry(entry: OntimeEntry) {\n if (isOntimeGroup(entry) || !entry.parent) {\n order = order.filter((id) => id !== entry.id);\n } else {\n const parent = entries[entry.parent];\n if (parent && isOntimeGroup(parent)) {\n parent.entries = parent.entries.filter((parentEntry) => parentEntry !== entry.id);\n }\n }\n\n delete entries[entry.id];\n flatOrder = flatOrder.filter((id) => id !== entry.id);\n }\n\n return { entries, order, flatOrder };\n}\n","import { MaybeNumber } from 'ontime-types';\nimport { formatFromMillis, MILLIS_PER_HOUR, MILLIS_PER_MINUTE } from 'ontime-utils';\n\n/**\n * Parses a value in millis to a string which encodes a delay\n * @param millis\n * @param format\n */\nexport function millisToDelayString(millis: MaybeNumber, format: 'compact' | 'expanded' = 'compact'): string {\n if (millis == null || millis === 0) {\n return '';\n }\n\n const isNegative = millis < 0;\n const absMillis = Math.abs(millis);\n const isCompact = format === 'compact';\n const delayed = isCompact ? '+' : 'delayed by ';\n const ahead = isCompact ? '-' : 'ahead by ';\n\n if (absMillis < MILLIS_PER_MINUTE) {\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 's')} sec`;\n } else if (absMillis < MILLIS_PER_HOUR && absMillis % MILLIS_PER_MINUTE === 0) {\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 'm')} min`;\n }\n\n return `${isNegative ? ahead : delayed}${formatFromMillis(absMillis, 'HH:mm:ss')}`;\n}\n"],"names":["makeSortableList","order","entries","flatIds","i","entry","isOntimeGroup","canDrop","targetType","targetParent","isTargetCollapsed","moveUp","entryId","flatOrder","currentEntry","currentIndex","previousEntryId","previousEntry","currentEntryParent","isOntimeEvent","moveDown","nextEntryId","parentGroup","afterGroupIndex","afterGroupId","nextEntry","orderEntries","unorderedArray","orderedArray","id","useEntryActions","queryClient","useQueryClient","linkPrevious","defaultTimeStrategy","defaultDuration","defaultWarnTime","defaultDangerTime","defaultTimerType","defaultEndAction","useEditorSettings","getCurrentRundownData","useCallback","RUNDOWN","getEntryById","eventId","cachedRundown","addEntryMutation","useMutation","rundownId","postAddEntry","addEntry","options","rundownData","newEntry","generateId","previousEvent","parseUserTime","error","logAxiosError","cloneEntryMutation","postCloneEntry","clone","_a","updateEntryMutation","newEvent","putEditEntry","_rundownId","previousData","newRundown","_error","_newEvent","context","updateEntry","updateTimer","field","value","lockOnUpdate","TimeStrategy","calculateNewValue","newValMillis","getPreviousEnd","remainingString","dayInMs","MILLIS_PER_SECOND","index","previousEnd","event","batchUpdateEventsMutation","data","putBatchEditEvents","previousRundown","eventIds","response","title","revision","batchUpdateEvents","deleteEntryMutation","entryIds","deleteEntries","optimisticDeleteEntries","_entryIds","deleteEntry","deleteAllEntriesMutation","requestDeleteAll","_","deleteAllEntries","applyDelayMutation","delayId","requestApplyDelay","applyDelay","delayEventId","ungroupMutation","groupId","requestUngroup","ungroup","groupEntriesMutation","requestGroupEntries","groupEntries","orderedIds","reorderEntryMutation","patchReorderEntry","move","direction","destinationId","SupportedEntry","reorderEntry","swapEventsMutation","from","to","requestEventSwap","eventA","eventB","newA","newB","swapEventData","_eventId","swapEvents","rundown","parent","parentEntry","millisToDelayString","millis","format","isNegative","absMillis","isCompact","delayed","ahead","MILLIS_PER_MINUTE","formatFromMillis","MILLIS_PER_HOUR"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as f,j as d,f as g}from"./vendor-
|
|
2
|
-
//# sourceMappingURL=editorSettings-
|
|
1
|
+
import{h as f,j as d,f as g}from"./vendor-9UkPSc5K.js";import{i as c,bA as y,T as S}from"./index-njXwwjfn.js";import{a as b,v as T,b as _,E as p,T as I}from"./validateEvent-BJMwP_mq.js";(function(){try{var t=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},e=new t.Error().stack;e&&(t._sentryDebugIds=t._sentryDebugIds||{},t._sentryDebugIds[e]="1bf2f693-f45b-4508-8eb2-1196d55423cb",t._sentryDebugIdIdentifier="sentry-dbid-1bf2f693-f45b-4508-8eb2-1196d55423cb")}catch{}})();const h="_blink_19ahf_1",v="_fourtyfive_19ahf_13",x="_textarea_19ahf_17",D="_subtle_19ahf_47",k="_ghosted_19ahf_53",w="_fluid_19ahf_59",o={blink:h,fourtyfive:v,textarea:x,subtle:D,ghosted:k,fluid:w},j=f.forwardRef(function({className:e,variant:r="subtle",fluid:n,rows:i=5,resize:l="none",style:s,...u},m){return d.jsx("textarea",{ref:m,autoCorrect:"off",autoComplete:"off",spellCheck:"false",rows:i,style:{...s,resize:l},className:c([o.textarea,o[r],n&&o.fluid,e]),...u})}),a={duration:"00:10:00",linkPrevious:!0,timeStrategy:I.LockDuration,warnTime:"00:02:00",dangerTime:"00:01:00",timerType:S.CountDown,endAction:p.None},L=g(t=>({defaultDuration:localStorage.getItem("ontime-default-duration")??a.duration,linkPrevious:y("ontime-link-previous",a.linkPrevious),defaultTimeStrategy:_(localStorage.getItem("ontime-time-strategy"),a.timeStrategy),defaultWarnTime:localStorage.getItem("ontime-default-warn-time")??a.warnTime,defaultDangerTime:localStorage.getItem("ontime-default-danger-time")??a.dangerTime,defaultTimerType:T(localStorage.getItem("ontime-default-timer-type"),a.timerType),defaultEndAction:b(localStorage.getItem("ontime-default-end-action"),a.endAction),setDefaultDuration:e=>t(()=>(localStorage.setItem("ontime-default-duration",String(e)),{defaultDuration:e})),setLinkPrevious:e=>t(()=>(localStorage.setItem("ontime-link-previous",String(e)),{linkPrevious:e})),setTimeStrategy:e=>t(()=>(localStorage.setItem("ontime-time-strategy",String(e)),{defaultTimeStrategy:e})),setWarnTime:e=>t(()=>(localStorage.setItem("ontime-default-warn-time",String(e)),{defaultWarnTime:e})),setDangerTime:e=>t(()=>(localStorage.setItem("ontime-default-danger-time",String(e)),{defaultDangerTime:e})),setDefaultTimerType:e=>t(()=>(localStorage.setItem("ontime-default-timer-type",String(e)),{defaultTimerType:e})),setDefaultEndAction:e=>t(()=>(localStorage.setItem("ontime-default-end-action",String(e)),{defaultEndAction:e}))}));export{j as T,a as e,L as u};
|
|
2
|
+
//# sourceMappingURL=editorSettings-CCHx-wCx.js.map
|
|
Binary file
|
|
Binary file
|