Migrate react-contextmenu to react-contexify
This commit is contained in:
parent
1e5aae0b51
commit
feccb3155e
6 changed files with 82 additions and 48 deletions
|
@ -76,7 +76,7 @@
|
||||||
"react-app-polyfill": "^1.0.4",
|
"react-app-polyfill": "^1.0.4",
|
||||||
"react-beautiful-dnd": "^12.1.1",
|
"react-beautiful-dnd": "^12.1.1",
|
||||||
"react-beforeunload": "^2.1.0",
|
"react-beforeunload": "^2.1.0",
|
||||||
"react-contextmenu": "^2.13.0",
|
"react-contexify": "^4.1.1",
|
||||||
"react-dev-utils": "^9.1.0",
|
"react-dev-utils": "^9.1.0",
|
||||||
"react-dnd": "^9.4.0",
|
"react-dnd": "^9.4.0",
|
||||||
"react-dnd-html5-backend": "^9.4.0",
|
"react-dnd-html5-backend": "^9.4.0",
|
||||||
|
|
|
@ -77,7 +77,7 @@ interface Album {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TimeslotItemBase {
|
export interface TimeslotItemBase {
|
||||||
timeslotitemid: string;
|
timeslotitemid: string;
|
||||||
channel: number;
|
channel: number;
|
||||||
weight: number;
|
weight: number;
|
||||||
|
@ -88,7 +88,7 @@ interface TimeslotItemBase {
|
||||||
cue: number;
|
cue: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TimeslotItemCentral {
|
export interface TimeslotItemCentral {
|
||||||
type: "central";
|
type: "central";
|
||||||
artist: string;
|
artist: string;
|
||||||
intro: number;
|
intro: number;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import React, { memo } from "react";
|
import React, { memo } from "react";
|
||||||
import { PlanItem, itemId } from "./state";
|
import { PlanItem, itemId, isTrack, isAux } from "./state";
|
||||||
import { Track, AuxItem } from "../api";
|
import { Track, AuxItem } from "../api";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { RootState } from "../rootReducer";
|
import { RootState } from "../rootReducer";
|
||||||
|
|
||||||
import * as MixerState from "../mixer/state";
|
import * as MixerState from "../mixer/state";
|
||||||
import { Draggable } from "react-beautiful-dnd";
|
import { Draggable } from "react-beautiful-dnd";
|
||||||
import { ContextMenuTrigger } from "react-contextmenu";
|
import { contextMenu } from "react-contexify";
|
||||||
import "./item.scss";
|
import "./item.scss";
|
||||||
|
|
||||||
export const TS_ITEM_MENU_ID = "SongMenu";
|
export const TS_ITEM_MENU_ID = "SongMenu";
|
||||||
|
export const TS_ITEM_AUX_ID = "AuxMenu";
|
||||||
|
|
||||||
export const Item = memo(function Item({
|
export const Item = memo(function Item({
|
||||||
item: x,
|
item: x,
|
||||||
|
@ -22,7 +23,6 @@ export const Item = memo(function Item({
|
||||||
}) {
|
}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const id = itemId(x);
|
const id = itemId(x);
|
||||||
const isReal = "timeslotitemid" in x;
|
|
||||||
const isGhost = "ghostid" in x;
|
const isGhost = "ghostid" in x;
|
||||||
|
|
||||||
const playerState = useSelector((state: RootState) =>
|
const playerState = useSelector((state: RootState) =>
|
||||||
|
@ -44,6 +44,30 @@ export const Item = memo(function Item({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openContextMenu(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (isTrack(x)) {
|
||||||
|
contextMenu.show({
|
||||||
|
id: TS_ITEM_MENU_ID,
|
||||||
|
event: e,
|
||||||
|
props: {
|
||||||
|
id,
|
||||||
|
title: x.title,
|
||||||
|
artist: x.artist,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (isAux(x)) {
|
||||||
|
contextMenu.show({
|
||||||
|
id: TS_ITEM_MENU_ID,
|
||||||
|
event: e,
|
||||||
|
props: {
|
||||||
|
id,
|
||||||
|
title: x.title,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable
|
<Draggable
|
||||||
draggableId={id}
|
draggableId={id}
|
||||||
|
@ -69,31 +93,27 @@ export const Item = memo(function Item({
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={triggerClick}
|
onClick={triggerClick}
|
||||||
|
onContextMenu={openContextMenu}
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
>
|
>
|
||||||
<ContextMenuTrigger
|
<span className={"icon " + x.type} />
|
||||||
id={isReal ? TS_ITEM_MENU_ID : ""}
|
|
||||||
collect={() => ({ id })}
|
{x.title.toString()}
|
||||||
|
{"artist" in x && x.artist !== "" && " - " + x.artist}
|
||||||
|
<small
|
||||||
|
className={
|
||||||
|
"border rounded border-danger text-danger p-1 m-1" +
|
||||||
|
("clean" in x && x.clean === false ? "" : " d-none")
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span className={"icon " + x.type} />
|
Explicit
|
||||||
|
</small>
|
||||||
{x.title.toString()}
|
{showDebug && (
|
||||||
{"artist" in x && x.artist !== "" && " - " + x.artist}
|
<code>
|
||||||
<small
|
{itemId(x)} {"channel" in x && x.channel + "/" + x.weight}
|
||||||
className={
|
</code>
|
||||||
"border rounded border-danger text-danger p-1 m-1" +
|
)}
|
||||||
("clean" in x && x.clean === false ? "" : " d-none")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Explicit
|
|
||||||
</small>
|
|
||||||
{showDebug && (
|
|
||||||
<code>
|
|
||||||
{itemId(x)} {"channel" in x && x.channel + "/" + x.weight}
|
|
||||||
</code>
|
|
||||||
)}
|
|
||||||
</ContextMenuTrigger>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useReducer, useEffect } from "react";
|
import React, { useState, useReducer, useEffect } from "react";
|
||||||
import { ContextMenu, MenuItem } from "react-contextmenu";
|
import { Menu, Item as CtxMenuItem } from "react-contexify";
|
||||||
|
import "react-contexify/dist/ReactContexify.min.css";
|
||||||
import { useBeforeunload } from "react-beforeunload";
|
import { useBeforeunload } from "react-beforeunload";
|
||||||
import {
|
import {
|
||||||
FaBookOpen,
|
FaBookOpen,
|
||||||
|
@ -379,13 +380,6 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onCtxRemoveClick(e: any, data: { id: string }) {
|
|
||||||
dispatch(removeItem(timeslotId, data.id));
|
|
||||||
}
|
|
||||||
async function onCtxUnPlayedClick(e: any, data: { id: string }) {
|
|
||||||
dispatch(setItemPlayed({ itemId: data.id, played: false }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(() => {
|
||||||
|
@ -440,14 +434,24 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
||||||
</div>
|
</div>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</div>
|
</div>
|
||||||
<ContextMenu id={TS_ITEM_MENU_ID}>
|
<Menu id={TS_ITEM_MENU_ID}>
|
||||||
<MenuItem onClick={onCtxRemoveClick}>
|
<CtxMenuItem
|
||||||
|
onClick={(args) =>
|
||||||
|
dispatch(removeItem(timeslotId, (args.props as any).id))
|
||||||
|
}
|
||||||
|
>
|
||||||
<FaTrash /> Remove
|
<FaTrash /> Remove
|
||||||
</MenuItem>
|
</CtxMenuItem>
|
||||||
<MenuItem onClick={onCtxUnPlayedClick}>
|
<CtxMenuItem
|
||||||
|
onClick={(args) =>
|
||||||
|
dispatch(
|
||||||
|
setItemPlayed({ itemId: (args.props as any).id, played: false })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
<FaCircleNotch /> Mark Unplayed
|
<FaCircleNotch /> Mark Unplayed
|
||||||
</MenuItem>
|
</CtxMenuItem>
|
||||||
</ContextMenu>
|
</Menu>
|
||||||
<OptionsMenu />
|
<OptionsMenu />
|
||||||
<WelcomeModal
|
<WelcomeModal
|
||||||
isOpen={showWelcomeModal}
|
isOpen={showWelcomeModal}
|
||||||
|
|
|
@ -47,6 +47,16 @@ export function itemId(
|
||||||
throw new Error("Can't get id of unknown item.");
|
throw new Error("Can't get id of unknown item.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isTrack(
|
||||||
|
item: PlanItem | Track | AuxItem
|
||||||
|
): item is (api.TimeslotItemBase & api.TimeslotItemCentral) | Track {
|
||||||
|
return "trackid" in item;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isAux(item: PlanItem | Track | AuxItem): item is AuxItem {
|
||||||
|
return "auxid" in item;
|
||||||
|
}
|
||||||
|
|
||||||
interface ShowplanState {
|
interface ShowplanState {
|
||||||
planLoading: boolean;
|
planLoading: boolean;
|
||||||
planLoadError: string | null;
|
planLoadError: string | null;
|
||||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -3299,7 +3299,7 @@ class-utils@^0.3.5:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
static-extend "^0.1.1"
|
static-extend "^0.1.1"
|
||||||
|
|
||||||
classnames@^2.2.3, classnames@^2.2.5:
|
classnames@^2.2.3, classnames@^2.2.6:
|
||||||
version "2.2.6"
|
version "2.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||||
|
@ -10100,13 +10100,13 @@ react-beforeunload@^2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
react-contextmenu@^2.13.0:
|
react-contexify@^4.1.1:
|
||||||
version "2.13.0"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-contextmenu/-/react-contextmenu-2.13.0.tgz#dabaea63124e30c85f1b4245c095b7045d013459"
|
resolved "https://registry.yarnpkg.com/react-contexify/-/react-contexify-4.1.1.tgz#f5eba1ad82a923c033c91d0abcea1da0a71ebaa1"
|
||||||
integrity sha512-hhFuJX4di0zGV7H7pXPn42U70OZbGpQD+PxcdmKStNT5mebSjI+inhOuFESDmDbqVsN/f99hI5/nw95oXTVRXQ==
|
integrity sha512-WJeRI4ohHEOmNiH0xb62a/eV+5ae168FB7H6pfbeEVJkf0UN7D5H99l6b89poc2LHKN1gOimFjREyY8quGVsXA==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.6"
|
||||||
object-assign "^4.1.0"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
react-dev-utils@^10.2.1:
|
react-dev-utils@^10.2.1:
|
||||||
version "10.2.1"
|
version "10.2.1"
|
||||||
|
|
Loading…
Reference in a new issue