Skip to content

Commit 32c796c

Browse files
authored
Merged PR 298: v1.26.0 - Rename teams, black pronuncation guides, styling fixes (#272)
- Let readers rename teams - Rename "Player Management" menu section to "Team Management" - Add black as a pronunciation guide color - Use text-decoration-skip-ink: none to make required parts more clear - Code refactoring around dialogs - Bump version to 1.26.0
1 parent 4bb8aa1 commit 32c796c

27 files changed

+722
-436
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "modaq",
3-
"version": "1.25.0",
3+
"version": "1.26.0",
44
"description": "Quiz Bowl Reader using TypeScript, React, and MobX",
55
"repository": {
66
"type": "git",

src/components/FormattedText.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const useStyles = memoizeFunction(
7272
mergeStyleSets({
7373
text: {
7474
display: "inline",
75+
textDecorationSkipInk: "none",
7576
},
7677
pronunciationGuide: {
7778
// Don't override the color if it's disabled; the container has that responsibility

src/components/GameBar.tsx

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ export const GameBar = observer(function GameBar(): JSX.Element {
9595
uiState.dialogState.showReorderPlayersDialog(game.players);
9696
}, [uiState, game]);
9797

98+
const renameTeamHandler = React.useCallback(() => {
99+
if (game.players.length === 0) {
100+
return;
101+
}
102+
103+
uiState.dialogState.showRenameTeamDialog(game.players[0].teamName);
104+
}, [uiState, game]);
105+
98106
const items: ICommandBarItemProps[] = appState.uiState.hideNewGame
99107
? []
100108
: [
@@ -147,6 +155,7 @@ export const GameBar = observer(function GameBar(): JSX.Element {
147155
addPlayerHandler,
148156
protestBonusHandler,
149157
reorderPlayersHandler,
158+
renameTeamHandler,
150159
addQuestionsHandler
151160
);
152161
items.push({
@@ -219,6 +228,7 @@ function getActionSubMenuItems(
219228
addPlayerHandler: () => void,
220229
protestBonusHandler: () => void,
221230
reorderPlayersHandler: () => void,
231+
renameTeamHandler: () => void,
222232
addQuestionsHandler: () => void
223233
): ICommandBarItemProps[] {
224234
const items: ICommandBarItemProps[] = [];
@@ -230,7 +240,8 @@ function getActionSubMenuItems(
230240
game,
231241
uiState,
232242
addPlayerHandler,
233-
reorderPlayersHandler
243+
reorderPlayersHandler,
244+
renameTeamHandler
234245
);
235246
items.push(playerManagementSection);
236247

@@ -420,10 +431,11 @@ function getPlayerManagementSubMenuItems(
420431
game: GameState,
421432
uiState: UIState,
422433
addPlayerHandler: () => void,
423-
reorderPlayersHandler: () => void
434+
reorderPlayersHandler: () => void,
435+
renameTeamHandler: () => void
424436
): ICommandBarItemProps {
425437
const teamNames: string[] = game.teamNames;
426-
const swapActivePlayerMenus: ICommandBarItemProps[] = [];
438+
const playerActionsMenus: ICommandBarItemProps[] = [];
427439
for (const teamName of teamNames) {
428440
const players: Player[] = game.getPlayers(teamName);
429441
const activePlayers: Set<Player> = game.getActivePlayers(teamName, uiState.cycleIndex);
@@ -502,7 +514,7 @@ function getPlayerManagementSubMenuItems(
502514
});
503515
}
504516

505-
swapActivePlayerMenus.push({
517+
playerActionsMenus.push({
506518
key: `active_${teamName}`,
507519
itemType: ContextualMenuItemType.Section,
508520
sectionProps: {
@@ -514,13 +526,13 @@ function getPlayerManagementSubMenuItems(
514526
}
515527

516528
// TODO: This should be under a section for player management (add player, subs)
517-
const swapPlayerItem: ICommandBarItemProps = {
518-
key: "swapPlayer",
519-
text: "Substitute/Remove",
529+
const playerActionsItem: ICommandBarItemProps = {
530+
key: "player",
531+
text: "Player",
520532
subMenuProps: {
521-
items: swapActivePlayerMenus,
533+
items: playerActionsMenus,
522534
},
523-
disabled: swapActivePlayerMenus.length === 0,
535+
disabled: playerActionsMenus.length === 0,
524536
// This needs its own submenu, with all the starters, then all the possible subs
525537
// We should disable this if there are no subs available
526538
};
@@ -549,13 +561,20 @@ function getPlayerManagementSubMenuItems(
549561
disabled: appState.game.cycles.length === 0,
550562
};
551563

564+
const renameTeamItem: ICommandBarItemProps = {
565+
key: "renameTeam",
566+
text: "Rename team...",
567+
onClick: renameTeamHandler,
568+
disabled: appState.game.cycles.length === 0,
569+
};
570+
552571
return {
553-
key: "playerManagement",
572+
key: "teamManagement",
554573
itemType: ContextualMenuItemType.Section,
555574
sectionProps: {
556575
bottomDivider: true,
557-
title: "Player Management",
558-
items: [swapPlayerItem, addPlayerItem, reorderPlayersItem],
576+
title: "Team Management",
577+
items: [playerActionsItem, addPlayerItem, reorderPlayersItem, renameTeamItem],
559578
},
560579
};
561580
}
@@ -766,7 +785,7 @@ function onSwapPlayerClick(
766785

767786
const additionalHint: string =
768787
Math.abs(cycleIndex - halftimeIndex) <= 1
769-
? ` If you want to substitue a player at halftime, do it on question ${Math.floor(halftimeIndex + 1)}.`
788+
? ` If you want to substitute a player at halftime, do it on question ${Math.floor(halftimeIndex + 1)}.`
770789
: "";
771790
item.data.appState.uiState.dialogState.showOKCancelMessageDialog(
772791
"Substitute Player",

src/components/ModalDialogContainer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ScoresheetDialog } from "./dialogs/ScoresheetDialog";
1717
import { StateContext } from "../contexts/StateContext";
1818
import { AppState } from "../state/AppState";
1919
import { ModalVisibilityStatus } from "../state/ModalVisibilityStatus";
20+
import { RenameTeamDialog } from "./dialogs/RenameTeamDialog";
2021

2122
export const ModalDialogContainer = observer(function ModalDialogContainer() {
2223
// The Protest dialogs aren't here because they require extra information
@@ -38,6 +39,7 @@ export const ModalDialogContainer = observer(function ModalDialogContainer() {
3839
<MessageDialog />
3940
<NewGameDialog />
4041
<RenamePlayerDialog />
42+
<RenameTeamDialog />
4143
<ReorderPlayerDialog />
4244
<ScoresheetDialog />
4345
</>

src/components/dialogs/AddPlayerDialog.tsx

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,28 @@
11
import * as React from "react";
22
import { observer } from "mobx-react-lite";
3-
import {
4-
Dropdown,
5-
TextField,
6-
IDropdownOption,
7-
IDialogContentProps,
8-
DialogType,
9-
IModalProps,
10-
ContextualMenu,
11-
Dialog,
12-
DialogFooter,
13-
PrimaryButton,
14-
DefaultButton,
15-
} from "@fluentui/react";
3+
import { Dropdown, TextField, IDropdownOption, DialogFooter, PrimaryButton, DefaultButton } from "@fluentui/react";
164

175
import * as AddPlayerDialogController from "../../components/dialogs/AddPlayerDialogController";
186
import { IPlayer } from "../../state/TeamState";
197
import { AppState } from "../../state/AppState";
208
import { StateContext } from "../../contexts/StateContext";
219
import { ModalVisibilityStatus } from "../../state/ModalVisibilityStatus";
22-
23-
const content: IDialogContentProps = {
24-
type: DialogType.normal,
25-
title: "Add Player",
26-
closeButtonAriaLabel: "Close",
27-
showCloseButton: true,
28-
styles: {
29-
innerContent: {
30-
display: "flex",
31-
flexDirection: "column",
32-
},
33-
},
34-
};
35-
36-
const modalProps: IModalProps = {
37-
isBlocking: false,
38-
dragOptions: {
39-
moveMenuItemText: "Move",
40-
closeMenuItemText: "Close",
41-
menu: ContextualMenu,
42-
},
43-
topOffsetFixed: true,
44-
};
10+
import { ModalDialog } from "./ModalDialog";
4511

4612
// TODO: Look into making a DefaultDialog, which handles the footers and default props
4713
export const AddPlayerDialog = observer(function AddPlayerDialog(): JSX.Element {
48-
const appState: AppState = React.useContext(StateContext);
49-
5014
return (
51-
<Dialog
52-
hidden={appState.uiState.dialogState.visibleDialog !== ModalVisibilityStatus.AddPlayer}
53-
dialogContentProps={content}
54-
modalProps={modalProps}
15+
<ModalDialog
16+
title="Add Player"
17+
visibilityStatus={ModalVisibilityStatus.AddPlayer}
5518
onDismiss={AddPlayerDialogController.hideDialog}
5619
>
5720
<AddPlayerDialogBody />
5821
<DialogFooter>
5922
<PrimaryButton text="Add" onClick={AddPlayerDialogController.addPlayer} />
6023
<DefaultButton text="Cancel" onClick={AddPlayerDialogController.hideDialog} />
6124
</DialogFooter>
62-
</Dialog>
25+
</ModalDialog>
6326
);
6427
});
6528

src/components/dialogs/AddQuestionsDialog.tsx

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,28 @@
11
import * as React from "react";
22
import { observer } from "mobx-react-lite";
3-
import {
4-
IDialogContentProps,
5-
DialogType,
6-
IModalProps,
7-
ContextualMenu,
8-
Dialog,
9-
DialogFooter,
10-
PrimaryButton,
11-
DefaultButton,
12-
} from "@fluentui/react";
3+
import { DialogFooter, PrimaryButton, DefaultButton } from "@fluentui/react";
134

145
import * as AddQuestionsDialogController from "./AddQuestionsDialogController";
156
import { AppState } from "../../state/AppState";
167
import { PacketLoader } from "../PacketLoader";
178
import { StateContext } from "../../contexts/StateContext";
189
import { ModalVisibilityStatus } from "../../state/ModalVisibilityStatus";
19-
20-
const content: IDialogContentProps = {
21-
type: DialogType.normal,
22-
title: "Add Questions",
23-
closeButtonAriaLabel: "Close",
24-
showCloseButton: true,
25-
styles: {
26-
innerContent: {
27-
display: "flex",
28-
flexDirection: "column",
29-
},
30-
},
31-
};
32-
33-
const modalProps: IModalProps = {
34-
isBlocking: false,
35-
dragOptions: {
36-
moveMenuItemText: "Move",
37-
closeMenuItemText: "Close",
38-
menu: ContextualMenu,
39-
},
40-
topOffsetFixed: true,
41-
};
10+
import { ModalDialog } from "./ModalDialog";
4211

4312
// TODO: Look into making a DefaultDialog, which handles the footers and default props
4413
export const AddQuestionsDialog = observer(function AddQuestionsDialog(): JSX.Element {
45-
const appState: AppState = React.useContext(StateContext);
4614
return (
47-
<Dialog
48-
hidden={appState.uiState.dialogState.visibleDialog !== ModalVisibilityStatus.AddQuestions}
49-
dialogContentProps={content}
50-
modalProps={modalProps}
15+
<ModalDialog
16+
title="Add Questions"
17+
visibilityStatus={ModalVisibilityStatus.AddQuestions}
5118
onDismiss={AddQuestionsDialogController.cancel}
5219
>
5320
<AddQuestionsDialogBody />
5421
<DialogFooter>
5522
<PrimaryButton text="Load" onClick={AddQuestionsDialogController.commit} />
5623
<DefaultButton text="Cancel" onClick={AddQuestionsDialogController.cancel} />
5724
</DialogFooter>
58-
</Dialog>
25+
</ModalDialog>
5926
);
6027
});
6128

src/components/dialogs/BonusProtestDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ export const BonusProtestDialog = observer(function BonusProtestDialog(props: IB
3636
<ProtestDialogBase
3737
appState={props.appState}
3838
givenAnswer={protestEvent.givenAnswer}
39-
hidden={props.appState.uiState.dialogState.visibleDialog !== ModalVisibilityStatus.BonusProtest}
4039
hideDialog={BonusProtestDialogController.cancel}
4140
onSubmit={submitHandler}
4241
reason={protestEvent.reason}
42+
visibilityStatus={ModalVisibilityStatus.BonusProtest}
4343
>
4444
{children}
4545
</ProtestDialogBase>

src/components/dialogs/CustomizeGameFormatDialog.tsx

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import { observer } from "mobx-react-lite";
33
import {
44
IDialogContentProps,
55
DialogType,
6-
IModalProps,
7-
ContextualMenu,
8-
Dialog,
96
DialogFooter,
107
PrimaryButton,
118
DefaultButton,
@@ -28,6 +25,7 @@ import { StateContext } from "../../contexts/StateContext";
2825
import { GameFormatPicker } from "../GameFormatPicker";
2926
import { SheetType } from "../../state/SheetState";
3027
import { ModalVisibilityStatus } from "../../state/ModalVisibilityStatus";
28+
import { ModalDialog } from "./ModalDialog";
3129

3230
const content: IDialogContentProps = {
3331
type: DialogType.normal,
@@ -43,24 +41,6 @@ const content: IDialogContentProps = {
4341
},
4442
};
4543

46-
const modalProps: IModalProps = {
47-
isBlocking: false,
48-
dragOptions: {
49-
moveMenuItemText: "Move",
50-
closeMenuItemText: "Close",
51-
menu: ContextualMenu,
52-
},
53-
styles: {
54-
main: {
55-
// To have max width respected normally, we'd need to pass in an IDialogStyleProps, but it ridiculously
56-
// requires you to pass in an entire theme to modify the max width. We could also use a modal, but that
57-
// requires building much of what Dialogs offer easily (close buttons, footer for buttons)
58-
minWidth: "30vw !important",
59-
},
60-
},
61-
topOffsetFixed: true,
62-
};
63-
6444
const pivotStyles: Partial<IPivotStyles> = {
6545
root: {
6646
marginBottom: 10,
@@ -76,18 +56,18 @@ export const CustomizeGameFormatDialog = observer(function CustomizeGameFormatDi
7656
const cancelHandler = React.useCallback(() => CustomizeGameFormatDialogController.cancel(appState), [appState]);
7757

7858
return (
79-
<Dialog
80-
hidden={appState.uiState.dialogState.visibleDialog !== ModalVisibilityStatus.CustomizeGameFormat}
59+
<ModalDialog
60+
title="Customize Game Format"
61+
visibilityStatus={ModalVisibilityStatus.CustomizeGameFormat}
8162
dialogContentProps={content}
82-
modalProps={modalProps}
8363
onDismiss={cancelHandler}
8464
>
8565
<CustomizeGameFormatDialogBody />
8666
<DialogFooter>
8767
<PrimaryButton text="Save" onClick={submitHandler} />
8868
<DefaultButton text="Cancel" onClick={cancelHandler} />
8969
</DialogFooter>
90-
</Dialog>
70+
</ModalDialog>
9171
);
9272
});
9373

0 commit comments

Comments
 (0)