Skip to content

Commit

Permalink
Alopezlago/public 1 16 0 (#217)
Browse files Browse the repository at this point in the history
* Merged PR 278: Remove LifSheets and copy buzz menu items

Remove LifSheets and copy buzz menu items

* Merged PR 279: v1.16.0 - more discoverable protests, font dialog improvement, throw out Qs in game bar

- Make protests more discoverable by always showing it in the buzz menu
- Show checkmark and X in buzz menu to make finding the right action easier
- Add actions for throwing out questions in the top menu
- Show sample text in Font dialog to show how the question text will look like
- Bump version to 1.16.0
  • Loading branch information
alopezlago authored May 14, 2023
1 parent ee10547 commit aa79153
Show file tree
Hide file tree
Showing 20 changed files with 151 additions and 222 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Introduction

MODAQ (**MOD**erator **A**ssistant for **Q**uizbowl) is an application for assisting moderators with reading and scorekeeping quiz bowl matches. It helps track all the events that occur during the match, such as buzzes, substituions, protests, and more. It also tracks buzz point data, and can export it to Lifsheets or a JSON file.
MODAQ (**MOD**erator **A**ssistant for **Q**uizbowl) is an application for assisting moderators with reading and scorekeeping quiz bowl matches. It helps track all the events that occur during the match, such as buzzes, substituions, protests, and more. It also tracks buzz point data, and can export it to TJ/UCSDSheets or a JSON file.

See [the wiki](https://github.com/alopezlago/MODAQ/wiki) to learn how to use the reader.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "modaq",
"version": "1.15.0",
"version": "1.16.0",
"description": "Quiz Bowl Reader using TypeScript, React, and MobX",
"repository": {
"type": "git",
Expand Down
15 changes: 0 additions & 15 deletions server.js

This file was deleted.

11 changes: 3 additions & 8 deletions src/components/BonusQuestion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,23 @@ import * as React from "react";
import { observer } from "mobx-react-lite";
import { FocusZone, FocusZoneDirection, ITheme, mergeStyleSets, Stack, StackItem, ThemeContext } from "@fluentui/react";

import * as BonusQuestionController from "./BonusQuestionController";
import * as PacketState from "../state/PacketState";
import { BonusQuestionPart } from "./BonusQuestionPart";
import { Bonus } from "../state/PacketState";
import { Cycle } from "../state/Cycle";
import { CancelButton, ICancelButtonPrompt } from "./CancelButton";
import { CancelButton } from "./CancelButton";
import { BonusProtestDialog } from "./dialogs/BonusProtestDialog";
import { AppState } from "../state/AppState";
import { FormattedText } from "./FormattedText";
import { IFormattedText } from "../parser/IFormattedText";
import { PostQuestionMetadata } from "./PostQuestionMetadata";

const throwOutQuestionPrompt: ICancelButtonPrompt = {
title: "Throw out Bonus",
message: "Click OK to throw out the bonus. To undo this, click on the X next to its event in the Event Log.",
};

let bonusQuestionTextIdCounter = 0;

export const BonusQuestion = observer(function BonusQuestion(props: IBonusQuestionProps) {
const throwOutClickHandler: () => void = React.useCallback(() => {
props.cycle.addThrownOutBonus(props.bonusIndex);
BonusQuestionController.throwOutBonus(props.cycle, props.bonusIndex);
}, [props]);
const formattedLeadin: IFormattedText[] = React.useMemo(
() => PacketState.getBonusWords(props.bonus.leadin, props.appState.game.gameFormat),
Expand Down Expand Up @@ -93,7 +89,6 @@ export const BonusQuestion = observer(function BonusQuestion(props: IBonusQuesti
<StackItem>
<CancelButton
disabled={!props.inPlay}
prompt={throwOutQuestionPrompt}
tooltip="Throw out bonus"
onClick={throwOutClickHandler}
/>
Expand Down
16 changes: 16 additions & 0 deletions src/components/BonusQuestionController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AppState } from "../state/AppState";
import { Cycle } from "../state/Cycle";

export function throwOutBonus(cycle: Cycle, bonusIndex: number): void {
const appState: AppState = AppState.instance;

appState.uiState.dialogState.showOKCancelMessageDialog(
"Throw out Bonus",
"Click OK to throw out the bonus. To undo this, click on the X next to its event in the Event Log.",
() => onConfirmThrowOutBonus(cycle, bonusIndex)
);
}

function onConfirmThrowOutBonus(cycle: Cycle, bonusIndex: number) {
cycle.addThrownOutBonus(bonusIndex);
}
18 changes: 10 additions & 8 deletions src/components/BuzzMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,32 +85,34 @@ function getPlayerMenuItems(props: IBuzzMenuProps, theme: Theme | undefined, tea
const subMenuItems: IContextualMenuItem[] = [
{
key: `${topLevelKey}_correct`,
text: "Correct",
text: "Correct",
data: buzzMenuItemData,
canCheck: true,
checked: isCorrectChecked,
onClick: onCorrectClicked,
},
{
key: `${topLevelKey}_wrong`,
text: "Wrong",
text: "Wrong",
data: buzzMenuItemData,
canCheck: true,
checked: isWrongChecked,
onClick: onWrongClicked,
},
];

if (isWrongChecked || isCorrectChecked) {
subMenuItems.push({
{
key: `${topLevelKey}_Divider`,
itemType: ContextualMenuItemType.Divider,
},
{
key: `${topLevelKey}_protest`,
text: "Protest",
data: buzzMenuItemData,
disabled: !(isWrongChecked || isCorrectChecked),
canCheck: true,
checked: isProtestChecked,
onClick: onProtestClicked,
});
}
},
];

// TODO: See if we can improve the style, since the background doesn't change on hover. We can look into
// tagging this with a class name and using react-jss, or using a style on the parent component (much harder to
Expand Down
35 changes: 34 additions & 1 deletion src/components/GameBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
CommandBar,
} from "@fluentui/react";

import * as BonusQuestionController from "./BonusQuestionController";
import * as TossupQuestionController from "./TossupQuestionController";
import { GameState } from "../state/GameState";
import { UIState } from "../state/UIState";
import { Cycle } from "../state/Cycle";
Expand Down Expand Up @@ -228,6 +230,38 @@ function getActionSubMenuItems(
const protestsSection: ICommandBarItemProps = getProtestSubMenuItems(appState, game, uiState, protestBonusHandler);
items.push(protestsSection);

const removeQuestionSection: ICommandBarItemProps = {
key: "removeQuestionSection",
itemType: ContextualMenuItemType.Section,
sectionProps: {
bottomDivider: true,
title: "Remove Question",
items: [
{
key: "removeTossup",
text: "Throw out tossup",
onClick: () =>
TossupQuestionController.throwOutTossup(
appState.game.cycles[appState.uiState.cycleIndex],
appState.game.getTossupIndex(appState.uiState.cycleIndex) + 1
),
disabled: appState.game.cycles.length === 0,
},
{
key: "removeBonus",
text: "Throw out bonus",
onClick: () =>
BonusQuestionController.throwOutBonus(
appState.game.cycles[appState.uiState.cycleIndex],
appState.game.getBonusIndex(appState.uiState.cycleIndex)
),
disabled: appState.game.cycles.length === 0,
},
],
},
};
items.push(removeQuestionSection);

const packetSection: ICommandBarItemProps = {
key: "packetSection",
itemType: ContextualMenuItemType.Section,
Expand All @@ -251,7 +285,6 @@ function getActionSubMenuItems(

function getExportSubMenuItems(appState: AppState): ICommandBarItemProps[] {
const items: ICommandBarItemProps[] = [];
const game: GameState = appState.game;
const disabled: boolean = appState.game.cycles.length === 0;

items.push({
Expand Down
13 changes: 2 additions & 11 deletions src/components/TossupQuestion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,10 @@ import { BuzzMenu } from "./BuzzMenu";
import { Answer } from "./Answer";
import { IFormattedText } from "../parser/IFormattedText";
import { TossupProtestDialog } from "./dialogs/TossupProtestDialog";
import { CancelButton, ICancelButtonPrompt } from "./CancelButton";
import { CancelButton } from "./CancelButton";
import { AppState } from "../state/AppState";
import { PostQuestionMetadata } from "./PostQuestionMetadata";

const throwOutQuestionPrompt: ICancelButtonPrompt = {
title: "Throw out Tossup",
message: "Click OK to throw out the tossup. To undo this, click on the X next to its event in the Event Log.",
};

export const TossupQuestion = observer(function TossupQuestion(props: IQuestionProps): JSX.Element {
const classes: ITossupQuestionClassNames = getClassNames();

Expand Down Expand Up @@ -78,11 +73,7 @@ export const TossupQuestion = observer(function TossupQuestion(props: IQuestionP
<PostQuestionMetadata metadata={props.tossup.metadata} />
</div>
<div>
<CancelButton
prompt={throwOutQuestionPrompt}
tooltip="Throw out tossup"
onClick={throwOutClickHandler}
/>
<CancelButton tooltip="Throw out tossup" onClick={throwOutClickHandler} />
</div>
</div>
);
Expand Down
10 changes: 10 additions & 0 deletions src/components/TossupQuestionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ export function selectWordFromKeyboardEvent(event: React.KeyboardEvent<HTMLDivEl

export function throwOutTossup(cycle: Cycle, tossupNumber: number): void {
const appState: AppState = AppState.instance;

appState.uiState.dialogState.showOKCancelMessageDialog(
"Throw out Tossup",
"Click OK to throw out the tossup. To undo this, click on the X next to its event in the Event Log.",
() => onConfirmThrowOutTossup(cycle, tossupNumber)
);
}

function onConfirmThrowOutTossup(cycle: Cycle, tossupNumber: number) {
const appState: AppState = AppState.instance;
cycle.addThrownOutTossup(tossupNumber - 1);
appState.uiState.setSelectedWordIndex(-1);
}
6 changes: 1 addition & 5 deletions src/components/dialogs/ExportToSheetsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ const warningIconStyles: IIconStyles = {
};

const typeOptions: IDropdownOption[] = [
{
key: SheetType.Lifsheets,
text: "Lifsheets",
},
{
key: SheetType.TJSheets,
text: "TJ Sheets",
Expand Down Expand Up @@ -164,7 +160,7 @@ const ExportSettingsDialogBody = observer(function ExportSettingsDialogBody(): J
return <></>;
}

const selectedType: number = uiState.sheetsState.sheetType ?? SheetType.Lifsheets;
const selectedType: number = uiState.sheetsState.sheetType ?? SheetType.TJSheets;
const roundNumber: number = sheet.roundNumber ?? 1;

let warningIconName: string | undefined;
Expand Down
10 changes: 10 additions & 0 deletions src/components/dialogs/FontDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ const FontDialogBody = observer(function FontDialogBody(): JSX.Element {
decrementButtonAriaLabel={"Decrease font size by 1"}
/>
</StackItem>
<StackItem>
<span
style={{
fontFamily: appState.uiState.pendingFontFamily ?? appState.uiState.fontFamily,
fontSize: appState.uiState.pendingFontSize ?? appState.uiState.questionFontSize,
}}
>
Sample text.
</span>
</StackItem>
</Stack>
);
});
Expand Down
17 changes: 1 addition & 16 deletions src/components/dialogs/NewGameDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const playerListHeight = "20vh";

const enum PivotKey {
Manual = "M",
Lifsheets = "L",
TJSheets = "T",
UCSDSheets = "U",
QBJRegistration = "R",
Expand Down Expand Up @@ -128,9 +127,6 @@ const NewGameDialogBody = observer(function NewGameDialogBody(): JSX.Element {
case undefined:
newGameType = PendingGameType.Manual;
break;
case PivotKey.Lifsheets:
newGameType = PendingGameType.Lifsheets;
break;
case PivotKey.TJSheets:
newGameType = PendingGameType.TJSheets;
break;
Expand Down Expand Up @@ -169,9 +165,6 @@ const NewGameDialogBody = observer(function NewGameDialogBody(): JSX.Element {
<PivotItem headerText="Manual" itemKey={PivotKey.Manual}>
<ManualNewGamePivotBody appState={appState} classes={classes} />
</PivotItem>
<PivotItem headerText="From Lifsheets" itemKey={PivotKey.Lifsheets}>
<FromSheetsNewGameBody appState={appState} classes={classes} />
</PivotItem>
<PivotItem headerText="From TJ Sheets" itemKey={PivotKey.TJSheets}>
<FromSheetsNewGameBody appState={appState} classes={classes} />
</PivotItem>
Expand All @@ -187,10 +180,7 @@ const NewGameDialogBody = observer(function NewGameDialogBody(): JSX.Element {
<Separator />
<GameFormatPicker
gameFormat={uiState.pendingNewGame.gameFormat}
exportFormatSupportsBouncebacks={
uiState.pendingNewGame.type !== PendingGameType.Lifsheets &&
uiState.pendingNewGame.type !== PendingGameType.UCSDSheets
}
exportFormatSupportsBouncebacks={uiState.pendingNewGame.type !== PendingGameType.UCSDSheets}
updateGameFormat={updateGameFormat}
/>
</>
Expand Down Expand Up @@ -299,9 +289,6 @@ const FromSheetsNewGameBody = observer(function FromSheetsNewGameBody(props: INe
const pendingNewGameType: PendingGameType = uiState.pendingNewGame.type;
switch (pendingNewGameType) {
case undefined:
case PendingGameType.Lifsheets:
sheetType = SheetType.Lifsheets;
break;
case PendingGameType.TJSheets:
sheetType = SheetType.TJSheets;
break;
Expand Down Expand Up @@ -498,8 +485,6 @@ function getDefaultPivotKey(pendingGameType: PendingGameType | undefined): Pivot
case PendingGameType.Manual:
case undefined:
return PivotKey.Manual;
case PendingGameType.Lifsheets:
return PivotKey.Lifsheets;
case PendingGameType.TJSheets:
return PivotKey.TJSheets;
case PendingGameType.UCSDSheets:
Expand Down
3 changes: 1 addition & 2 deletions src/state/IPendingNewGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface IPendingManualNewGame extends IBasePendingNewGame {

export const enum PendingGameType {
Manual,
Lifsheets,
TJSheets,
UCSDSheets,
QBJRegistration,
Expand All @@ -25,7 +24,7 @@ export interface IPendingFromSheetsNewGame extends IBasePendingNewGame {
playersFromRosters: Player[] | undefined;
firstTeamPlayersFromRosters: Player[] | undefined;
secondTeamPlayersFromRosters: Player[] | undefined;
type: PendingGameType.Lifsheets | PendingGameType.TJSheets | PendingGameType.UCSDSheets;
type: PendingGameType.TJSheets | PendingGameType.UCSDSheets;
}

export interface IPendingQBJRegistrationNewGame extends IBasePendingNewGame {
Expand Down
3 changes: 3 additions & 0 deletions src/state/SheetState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ export const enum ExportState {
}

export const enum SheetType {
/**
* DEPRECATED
*/
Lifsheets = 0,
TJSheets = 1,
UCSDSheets = 2,
Expand Down
4 changes: 0 additions & 4 deletions src/state/UIState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ export class UIState {
secondTeamPlayers,
};
break;
case PendingGameType.Lifsheets:
case PendingGameType.TJSheets:
case PendingGameType.UCSDSheets:
break;
Expand Down Expand Up @@ -327,7 +326,6 @@ export class UIState {
}

switch (this.pendingNewGame.type) {
case PendingGameType.Lifsheets:
case PendingGameType.TJSheets:
case PendingGameType.UCSDSheets:
this.pendingNewGame.firstTeamPlayersFromRosters = players;
Expand All @@ -347,7 +345,6 @@ export class UIState {
}

switch (this.pendingNewGame.type) {
case PendingGameType.Lifsheets:
case PendingGameType.TJSheets:
case PendingGameType.UCSDSheets:
this.pendingNewGame.secondTeamPlayersFromRosters = players;
Expand Down Expand Up @@ -516,7 +513,6 @@ export class UIState {
this.pendingNewGame.secondTeamPlayers = [];
break;
case undefined:
case PendingGameType.Lifsheets:
case PendingGameType.TJSheets:
case PendingGameType.UCSDSheets:
// Don't clear the sheets URL or the players
Expand Down
Loading

0 comments on commit aa79153

Please sign in to comment.