Merge fixes / tidies from BAPS3 to Webstudio
This commit is contained in:
parent
1e53edea2c
commit
fede677bb5
13 changed files with 128 additions and 109 deletions
1
.env
1
.env
|
@ -4,5 +4,4 @@ REACT_APP_MYRADIO_NONAPI_BASE=https://ury.org.uk/myradio-staging
|
||||||
REACT_APP_MYRADIO_BASE=https://ury.org.uk/api-staging/v2
|
REACT_APP_MYRADIO_BASE=https://ury.org.uk/api-staging/v2
|
||||||
REACT_APP_BROADCAST_API_BASE=https://ury.org.uk/webstudio/api/v1
|
REACT_APP_BROADCAST_API_BASE=https://ury.org.uk/webstudio/api/v1
|
||||||
REACT_APP_WS_URL=wss://ury.org.uk/webstudio/api/stream
|
REACT_APP_WS_URL=wss://ury.org.uk/webstudio/api/stream
|
||||||
REACT_APP_BAPSICLE_INTERFACE=true
|
|
||||||
REACT_APP_SENTRY_PUBLIC_DSN=https://7bdc2a7a1eb24ae080eb1d3af75e6307@o578586.ingest.sentry.io/5734903
|
REACT_APP_SENTRY_PUBLIC_DSN=https://7bdc2a7a1eb24ae080eb1d3af75e6307@o578586.ingest.sentry.io/5734903
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
|
||||||
|
TODO: Ideally we shouldn't rely on CDN's during runtime.
|
||||||
-->
|
-->
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
|
||||||
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||||
|
|
|
@ -17,7 +17,7 @@ $number-of-channels: 3;
|
||||||
.logo {
|
.logo {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
.logo-big {
|
.logo-big-bapsicle {
|
||||||
height: 30vh;
|
height: 30vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ export function searchForTracks(
|
||||||
artist,
|
artist,
|
||||||
title,
|
title,
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
return myradioApiRequest("/track/search", "GET", {
|
return myradioApiRequest("/track/search", "GET", {
|
||||||
artist,
|
artist,
|
||||||
title,
|
title,
|
||||||
|
@ -213,7 +213,6 @@ export function searchForTracks(
|
||||||
digitised: true,
|
digitised: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export function getTimeslots(): Promise<Array<Timeslot>> {
|
export function getTimeslots(): Promise<Array<Timeslot>> {
|
||||||
return bapsicleApiRequest("/plan/list", "GET", {});
|
return bapsicleApiRequest("/plan/list", "GET", {});
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function ConnectionDialogue({ error }: { error: String | null }) {
|
||||||
return (
|
return (
|
||||||
<div className="loading-dialogue">
|
<div className="loading-dialogue">
|
||||||
<div className="logo-container">
|
<div className="logo-container">
|
||||||
<img className="logo-big mb-2" src={appLogo} alt="BAPS Logo" />
|
<img className="logo-big-bapsicle mb-2" src={appLogo} alt="BAPS Logo" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className="inner">
|
<span className="inner">
|
||||||
|
|
|
@ -4,7 +4,6 @@ import "./index.css";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import * as serviceWorker from "./serviceWorkerLoader";
|
import * as serviceWorker from "./serviceWorkerLoader";
|
||||||
|
|
||||||
|
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
import { Integrations } from "@sentry/tracing";
|
import { Integrations } from "@sentry/tracing";
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,8 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) {
|
||||||
instance.emit("pause");
|
instance.emit("pause");
|
||||||
});
|
});
|
||||||
wavesurfer.on("seek", () => {
|
wavesurfer.on("seek", () => {
|
||||||
|
// This is used to prevent infinite loops when bapsicle tells wavesurfer to change position,
|
||||||
|
// since otherwise it would send an change update back to the bapsicle server again (as if the user seeked intentionally).
|
||||||
if (instance.ignore_next_seek) {
|
if (instance.ignore_next_seek) {
|
||||||
instance.ignore_next_seek = false;
|
instance.ignore_next_seek = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -379,6 +379,7 @@ export const setLoadedItemOutro = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const seek = (player: number, time_s: number): AppThunk => async () => {
|
export const seek = (player: number, time_s: number): AppThunk => async () => {
|
||||||
|
// Used only by Bapsicle to update the wavesurfer seek position.
|
||||||
const playerInstance = await audioEngine.getPlayer(player);
|
const playerInstance = await audioEngine.getPlayer(player);
|
||||||
|
|
||||||
if (playerInstance) {
|
if (playerInstance) {
|
||||||
|
@ -426,6 +427,7 @@ export const load = (
|
||||||
const currentItem = getState().mixer.players[player].loadedItem;
|
const currentItem = getState().mixer.players[player].loadedItem;
|
||||||
if (currentItem !== null && itemId(currentItem) === itemId(item)) {
|
if (currentItem !== null && itemId(currentItem) === itemId(item)) {
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// In BAPS, another client could have updated the audio markers etc, so we have to still check and update them.
|
||||||
// The cue/intro/outro point(s) have changed.
|
// The cue/intro/outro point(s) have changed.
|
||||||
if (
|
if (
|
||||||
"cue" in currentItem &&
|
"cue" in currentItem &&
|
||||||
|
@ -567,6 +569,7 @@ export const load = (
|
||||||
dispatch(mixerState.actions.itemLoadComplete({ player }));
|
dispatch(mixerState.actions.itemLoadComplete({ player }));
|
||||||
|
|
||||||
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// BAPS server will give these values already on load based on it's own calculation, not wavesurfer's.
|
||||||
dispatch(
|
dispatch(
|
||||||
mixerState.actions.setTimeLength({
|
mixerState.actions.setTimeLength({
|
||||||
player,
|
player,
|
||||||
|
@ -585,6 +588,7 @@ export const load = (
|
||||||
const state = getState().mixer.players[player];
|
const state = getState().mixer.players[player];
|
||||||
|
|
||||||
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// Client doesn't do any audio playing in BAPS.
|
||||||
if (state.playOnLoad) {
|
if (state.playOnLoad) {
|
||||||
playerInstance.play();
|
playerInstance.play();
|
||||||
}
|
}
|
||||||
|
@ -603,16 +607,18 @@ export const load = (
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// If user manually seeks on the waveform, just direct that to the webserver.
|
||||||
playerInstance.on("timeChangeSeek", (time) => {
|
playerInstance.on("timeChangeSeek", (time) => {
|
||||||
if (
|
// Limit
|
||||||
Math.abs(time - getState().mixer.players[player].timeCurrent) > 0.5
|
//if (
|
||||||
) {
|
// Math.abs(time - getState().mixer.players[player].timeCurrent) > 0.5
|
||||||
|
//) {
|
||||||
sendBAPSicleChannel({
|
sendBAPSicleChannel({
|
||||||
channel: player,
|
channel: player,
|
||||||
command: "SEEK",
|
command: "SEEK",
|
||||||
time: time,
|
time: time,
|
||||||
});
|
});
|
||||||
}
|
//}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
playerInstance.on("play", () => {
|
playerInstance.on("play", () => {
|
||||||
|
@ -1261,10 +1267,40 @@ export const mixerKeyboardShortcutsMiddleware: Middleware<
|
||||||
store.dispatch(handleKeyboardShortcut(store, 2, "STOP"));
|
store.dispatch(handleKeyboardShortcut(store, 2, "STOP"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
Keys("a", () => {
|
||||||
|
store.dispatch(setVolume(0, "off"));
|
||||||
|
});
|
||||||
|
Keys("s", () => {
|
||||||
|
store.dispatch(setVolume(0, "bed"));
|
||||||
|
});
|
||||||
|
Keys("d", () => {
|
||||||
|
store.dispatch(setVolume(0, "full"));
|
||||||
|
});
|
||||||
|
Keys("f", () => {
|
||||||
|
store.dispatch(setVolume(1, "off"));
|
||||||
|
});
|
||||||
|
Keys("g", () => {
|
||||||
|
store.dispatch(setVolume(1, "bed"));
|
||||||
|
});
|
||||||
|
Keys("h", () => {
|
||||||
|
store.dispatch(setVolume(1, "full"));
|
||||||
|
});
|
||||||
|
Keys("j", () => {
|
||||||
|
store.dispatch(setVolume(2, "off"));
|
||||||
|
});
|
||||||
|
Keys("k", () => {
|
||||||
|
store.dispatch(setVolume(2, "bed"));
|
||||||
|
});
|
||||||
|
Keys("l", () => {
|
||||||
|
store.dispatch(setVolume(2, "full"));
|
||||||
|
});
|
||||||
|
|
||||||
Keys("x", () => {
|
Keys("x", () => {
|
||||||
const state = store.getState().mixer.mic;
|
const state = store.getState().mixer.mic;
|
||||||
store.dispatch(setMicVolume(state.volume === 1 ? "off" : "full"));
|
store.dispatch(setMicVolume(state.volume === 1 ? "off" : "full"));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (next) => (action) => next(action);
|
return (next) => (action) => next(action);
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,8 +50,7 @@ export const Item = memo(function Item({
|
||||||
|
|
||||||
function triggerClick() {
|
function triggerClick() {
|
||||||
if (column > -1) {
|
if (column > -1) {
|
||||||
console.log("Clicking to load:", x);
|
// TODO: move this into mixer state if we can.
|
||||||
|
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
sendBAPSicleChannel({
|
sendBAPSicleChannel({
|
||||||
channel: column,
|
channel: column,
|
||||||
|
|
|
@ -81,6 +81,7 @@ const setTrackIntro = (
|
||||||
secs: number,
|
secs: number,
|
||||||
player: number
|
player: number
|
||||||
): AppThunk => async (dispatch, getState) => {
|
): AppThunk => async (dispatch, getState) => {
|
||||||
|
// TODO Move into MixerState
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
let marker = {
|
let marker = {
|
||||||
name: "Intro",
|
name: "Intro",
|
||||||
|
|
|
@ -50,8 +50,6 @@ import Modal from "react-modal";
|
||||||
import { Sidebar } from "./sidebar";
|
import { Sidebar } from "./sidebar";
|
||||||
import { PLAYER_ID_PREVIEW } from "../mixer/audio";
|
import { PLAYER_ID_PREVIEW } from "../mixer/audio";
|
||||||
|
|
||||||
import { sendBAPSicleChannel } from "../bapsicle";
|
|
||||||
|
|
||||||
function Channel({ id, data }: { id: number; data: PlanItem[] }) {
|
function Channel({ id, data }: { id: number; data: PlanItem[] }) {
|
||||||
return (
|
return (
|
||||||
<div className="channel" id={"channel-" + id}>
|
<div className="channel" id={"channel-" + id}>
|
||||||
|
@ -112,6 +110,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// In BAPS, we'll load in the show plan from a async message from server.
|
||||||
dispatch(getShowplan(timeslotId));
|
dispatch(getShowplan(timeslotId));
|
||||||
}
|
}
|
||||||
}, [dispatch, timeslotId]);
|
}, [dispatch, timeslotId]);
|
||||||
|
@ -148,15 +147,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
cue: 0,
|
cue: 0,
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
|
||||||
sendBAPSicleChannel({
|
|
||||||
channel: newItem.channel,
|
|
||||||
command: "ADD",
|
|
||||||
newItem: newItem,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(addItem(timeslotId, newItem));
|
dispatch(addItem(timeslotId, newItem));
|
||||||
}
|
|
||||||
increment(null);
|
increment(null);
|
||||||
} else if (result.draggableId[0] === "A") {
|
} else if (result.draggableId[0] === "A") {
|
||||||
// this is an aux resource
|
// this is an aux resource
|
||||||
|
@ -171,15 +162,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
cue: 0,
|
cue: 0,
|
||||||
...data,
|
...data,
|
||||||
} as any;
|
} as any;
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
|
||||||
sendBAPSicleChannel({
|
|
||||||
channel: newItem.channel,
|
|
||||||
command: "ADD",
|
|
||||||
newItem: newItem,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(addItem(timeslotId, newItem));
|
dispatch(addItem(timeslotId, newItem));
|
||||||
}
|
|
||||||
increment(null);
|
increment(null);
|
||||||
} else {
|
} else {
|
||||||
// this is a normal move (ghosts aren't draggable)
|
// this is a normal move (ghosts aren't draggable)
|
||||||
|
@ -204,28 +187,6 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onCtxRemoveClick(
|
|
||||||
e: any,
|
|
||||||
data: { id: string; column: number; index: number }
|
|
||||||
) {
|
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
|
||||||
sendBAPSicleChannel({
|
|
||||||
channel: data.column,
|
|
||||||
command: "REMOVE",
|
|
||||||
weight: data.index,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(removeItem(timeslotId, data.id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onCtxUnPlayedClick(
|
|
||||||
e: any,
|
|
||||||
data: { id: string; column: number; index: number }
|
|
||||||
) {
|
|
||||||
dispatch(setItemPlayed(data.id.toString(), false, data.column));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add support for reloading the show plan from the iFrames.
|
// Add support for reloading the show plan from the iFrames.
|
||||||
// There is a similar listener in showplanner/ImporterModal.tsx to handle closing the iframe.
|
// There is a similar listener in showplanner/ImporterModal.tsx to handle closing the iframe.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -275,9 +236,9 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
<FaTrash /> Remove
|
<FaTrash /> Remove
|
||||||
</CtxMenuItem>
|
</CtxMenuItem>
|
||||||
<CtxMenuItem
|
<CtxMenuItem
|
||||||
onClick={(args) =>
|
onClick={(args) => {
|
||||||
dispatch(setItemPlayed((args.props as any).id, false))
|
dispatch(setItemPlayed((args.props as any).id, false));
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<FaCircleNotch /> Mark Unplayed
|
<FaCircleNotch /> Mark Unplayed
|
||||||
</CtxMenuItem>
|
</CtxMenuItem>
|
||||||
|
|
|
@ -99,6 +99,8 @@ const showplan = createSlice({
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{ channel: Number; planItems: PlanItem[] }>
|
action: PayloadAction<{ channel: Number; planItems: PlanItem[] }>
|
||||||
) {
|
) {
|
||||||
|
// This is used for BAPSicle only to read in individual channels of show plan into the show state from the server.
|
||||||
|
// TODO: Does this need to be this complicated?
|
||||||
var newItems = state.plan?.filter(
|
var newItems = state.plan?.filter(
|
||||||
(item) => item.channel !== action.payload.channel
|
(item) => item.channel !== action.payload.channel
|
||||||
);
|
);
|
||||||
|
@ -263,11 +265,7 @@ export const setItemPlayed = (
|
||||||
played: boolean
|
played: boolean
|
||||||
): AppThunk => async (dispatch, getState) => {
|
): AppThunk => async (dispatch, getState) => {
|
||||||
// The server handles marking things played
|
// The server handles marking things played
|
||||||
// TODO: Add support in BAPSicle for marking things played
|
|
||||||
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
if (played) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var weight = -1;
|
var weight = -1;
|
||||||
var player = null;
|
var player = null;
|
||||||
|
|
||||||
|
@ -282,13 +280,15 @@ export const setItemPlayed = (
|
||||||
if (player) {
|
if (player) {
|
||||||
sendBAPSicleChannel({
|
sendBAPSicleChannel({
|
||||||
channel: player,
|
channel: player,
|
||||||
command: "RESETPLAYED",
|
command: "SETPLAYED",
|
||||||
weight: weight,
|
weight: weight,
|
||||||
|
played: played,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sendBAPSicleChannel({
|
sendBAPSicleChannel({
|
||||||
command: "RESETPLAYED",
|
command: "SETPLAYED",
|
||||||
weight: weight,
|
weight: weight,
|
||||||
|
played: played,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -448,6 +448,15 @@ export const addItem = (
|
||||||
timeslotId: number,
|
timeslotId: number,
|
||||||
newItemData: TimeslotItem
|
newItemData: TimeslotItem
|
||||||
): AppThunk => async (dispatch, getState) => {
|
): AppThunk => async (dispatch, getState) => {
|
||||||
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
sendBAPSicleChannel({
|
||||||
|
channel: newItemData.channel,
|
||||||
|
command: "ADD",
|
||||||
|
newItem: newItemData,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(showplan.actions.setPlanSaving(true));
|
dispatch(showplan.actions.setPlanSaving(true));
|
||||||
console.log("New Weight: " + newItemData.weight);
|
console.log("New Weight: " + newItemData.weight);
|
||||||
const plan = cloneDeep(getState().showplan.plan!);
|
const plan = cloneDeep(getState().showplan.plan!);
|
||||||
|
@ -527,7 +536,9 @@ export const addItem = (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
dispatch(showplan.actions.planSaveError("Failed to update show plan."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const lastResult = result[result.length - 1]; // this is the add op
|
const lastResult = result[result.length - 1]; // this is the add op
|
||||||
const newItemId = lastResult.timeslotitemid!;
|
const newItemId = lastResult.timeslotitemid!;
|
||||||
|
|
||||||
|
@ -538,7 +549,6 @@ export const addItem = (
|
||||||
newItemData,
|
newItemData,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Just add it straight to the show plan without updating the server.
|
// Just add it straight to the show plan without updating the server.
|
||||||
dispatch(showplan.actions.addItem(newItemData));
|
dispatch(showplan.actions.addItem(newItemData));
|
||||||
|
@ -551,10 +561,24 @@ export const removeItem = (
|
||||||
timeslotId: number,
|
timeslotId: number,
|
||||||
itemid: string
|
itemid: string
|
||||||
): AppThunk => async (dispatch, getState) => {
|
): AppThunk => async (dispatch, getState) => {
|
||||||
dispatch(showplan.actions.setPlanSaving(true));
|
|
||||||
// This is a simplified version of the second case of moveItem
|
// This is a simplified version of the second case of moveItem
|
||||||
const plan = cloneDeep(getState().showplan.plan!);
|
const plan = cloneDeep(getState().showplan.plan!);
|
||||||
const item = plan.find((x) => itemId(x) === itemid)!;
|
const item = plan.find((x) => itemId(x) === itemid)!;
|
||||||
|
|
||||||
|
if (process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
|
// Server handles deletion, short circuit.
|
||||||
|
if (item) {
|
||||||
|
sendBAPSicleChannel({
|
||||||
|
channel: item.channel,
|
||||||
|
command: "REMOVE",
|
||||||
|
weight: item.weight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(showplan.actions.setPlanSaving(true));
|
||||||
|
|
||||||
const planColumn = plan
|
const planColumn = plan
|
||||||
.filter((x) => x.channel === item.channel)
|
.filter((x) => x.channel === item.channel)
|
||||||
.sort((a, b) => a.weight - b.weight);
|
.sort((a, b) => a.weight - b.weight);
|
||||||
|
@ -578,6 +602,7 @@ export const removeItem = (
|
||||||
weight: movingItem.weight - 1,
|
weight: movingItem.weight - 1,
|
||||||
});
|
});
|
||||||
movingItem.weight -= 1;
|
movingItem.weight -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
if (!process.env.REACT_APP_BAPSICLE_INTERFACE) {
|
||||||
if (getState().settings.saveShowPlanChanges) {
|
if (getState().settings.saveShowPlanChanges) {
|
||||||
|
@ -594,14 +619,11 @@ export const removeItem = (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dispatch(
|
dispatch(showplan.actions.planSaveError("Failed to update show plan."));
|
||||||
showplan.actions.planSaveError("Failed to update show plan.")
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(showplan.actions.applyOps(ops));
|
dispatch(showplan.actions.applyOps(ops));
|
||||||
dispatch(showplan.actions.setPlanSaving(false));
|
dispatch(showplan.actions.setPlanSaving(false));
|
||||||
|
|
|
@ -20,7 +20,6 @@ import { bapsicleMiddleware } from "./bapsicle";
|
||||||
|
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
|
|
||||||
// const ACTION_HISTORY_MAX_SIZE = 20;
|
// const ACTION_HISTORY_MAX_SIZE = 20;
|
||||||
|
|
||||||
// const actionHistory: Array<Action> = [];
|
// const actionHistory: Array<Action> = [];
|
||||||
|
|
Loading…
Reference in a new issue