update
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -7149,6 +7149,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tslint-config-prettier": {
|
||||||
|
"version": "1.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz",
|
||||||
|
"integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"tslint-react": {
|
"tslint-react": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslint-react/-/tslint-react-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslint-react/-/tslint-react-4.2.0.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,11 @@
|
|||||||
"start": "webpack-dev-server --mode development",
|
"start": "webpack-dev-server --mode development",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
"prettier": {
|
||||||
|
"tabWidth": 4,
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"printWidth": 100
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.8.4",
|
"@babel/cli": "^7.8.4",
|
||||||
"@babel/core": "^7.9.6",
|
"@babel/core": "^7.9.6",
|
||||||
@@ -34,6 +39,7 @@
|
|||||||
"style-loader": "^1.2.1",
|
"style-loader": "^1.2.1",
|
||||||
"ts-loader": "^7.0.3",
|
"ts-loader": "^7.0.3",
|
||||||
"tslint": "^6.1.1",
|
"tslint": "^6.1.1",
|
||||||
|
"tslint-config-prettier": "^1.18.0",
|
||||||
"tslint-react": "^4.2.0",
|
"tslint-react": "^4.2.0",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.43.0",
|
||||||
|
|||||||
@@ -1,138 +1,228 @@
|
|||||||
import React, {useContext, useState} from "react";
|
import React, {useContext, useState} from "react";
|
||||||
import {CellDef, RulesetSchemaDto} from "../Services/RulesetSchemaDto";
|
|
||||||
import {
|
import {
|
||||||
Button,
|
BlockDef,
|
||||||
Checkbox,
|
BonusBlockDef,
|
||||||
Form,
|
CellDef,
|
||||||
Header,
|
NoBonusBlockDef,
|
||||||
Segment,
|
RulesetSchemaDto,
|
||||||
Table
|
} from "../Services/RulesetSchemaDto";
|
||||||
} from "semantic-ui-react";
|
import {Button, Container, Grid, Header, Segment} from "semantic-ui-react";
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import RulesetBlockTable from "./RulesetBlockTable";
|
|
||||||
import RulesetDisplayPanel from "./RulesetDisplayPanel";
|
import RulesetDisplayPanel from "./RulesetDisplayPanel";
|
||||||
|
import NewBlockForm from "./NewBlockForm";
|
||||||
|
import axios from "axios";
|
||||||
|
import {SERVER_BASE_NAME} from "../index";
|
||||||
|
import EditableHeader from "./EditableHeader";
|
||||||
|
|
||||||
interface RulesetDisplayPanelProps {
|
interface RulesetDisplayPanelProps {
|
||||||
onSubmitRuleset: (ruleset: RulesetSchemaDto) => any;
|
onRulesetSave: () => any;
|
||||||
|
onRulesetChange: () => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateRulesetPanel: React.FunctionComponent<RulesetDisplayPanelProps> = (props) => {
|
interface RulesetDisplayPanelState {
|
||||||
const {onSubmitRuleset} = props;
|
saving: boolean;
|
||||||
const {strings: Locale} = useContext(UserContext);
|
currentRulesetBuild: RulesetSchemaDto;
|
||||||
const [currentRulesetBuild, updateCurrentRulesetBuild] = useState<RulesetSchemaDto>({
|
newBlockInput: {
|
||||||
id: "",
|
label: string;
|
||||||
label: Locale.rulesetsPage.newRuleset,
|
hasBonus: boolean;
|
||||||
blocks: {},
|
bonusFor: number;
|
||||||
});
|
bonusScore: number;
|
||||||
const [newBlockInput, updateNewBlockInput] = useState({
|
};
|
||||||
label: "",
|
}
|
||||||
hasBonus: false,
|
|
||||||
bonusScore: 35,
|
|
||||||
bonusFor: 63,
|
|
||||||
cells: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleAddBlock = () => {
|
class CreateRulesetPanel extends React.Component<
|
||||||
if (newBlockInput.label) {
|
RulesetDisplayPanelProps,
|
||||||
updateCurrentRulesetBuild({
|
RulesetDisplayPanelState
|
||||||
...currentRulesetBuild,
|
> {
|
||||||
blocks: {
|
constructor(props: RulesetDisplayPanelProps) {
|
||||||
...currentRulesetBuild.blocks,
|
super(props);
|
||||||
[newBlockInput.label]: {
|
this.state = {
|
||||||
...newBlockInput,
|
saving: false,
|
||||||
bonusFor: newBlockInput.hasBonus ? newBlockInput.bonusFor : undefined,
|
currentRulesetBuild: {
|
||||||
bonusScore: newBlockInput.hasBonus ? newBlockInput.bonusScore : undefined,
|
id: "",
|
||||||
},
|
label: "",
|
||||||
}
|
blocks: {},
|
||||||
|
},
|
||||||
|
newBlockInput: {
|
||||||
|
label: "",
|
||||||
|
hasBonus: false,
|
||||||
|
bonusFor: 0,
|
||||||
|
bonusScore: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
if (this.state.currentRulesetBuild.label === "") {
|
||||||
|
this.setState({
|
||||||
|
currentRulesetBuild: {
|
||||||
|
...this.state.currentRulesetBuild,
|
||||||
|
id: this.context.strings.rulesetsPage.newRuleset,
|
||||||
|
label: this.context.strings.rulesetsPage.newRuleset,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleAddCell = (cellDef: CellDef, blockId: string) => {
|
handleAddBlock() {
|
||||||
if (cellDef.label) {
|
if (this.state.newBlockInput.label) {
|
||||||
updateCurrentRulesetBuild({
|
const blockToSave = {
|
||||||
...currentRulesetBuild,
|
...this.state.newBlockInput,
|
||||||
blocks: {
|
cells: {},
|
||||||
...currentRulesetBuild.blocks,
|
};
|
||||||
[blockId]: {
|
if (!this.state.newBlockInput.hasBonus) {
|
||||||
...currentRulesetBuild.blocks[blockId],
|
delete blockToSave.bonusScore;
|
||||||
cells: {
|
delete blockToSave.bonusFor;
|
||||||
...currentRulesetBuild.blocks[blockId].cells,
|
}
|
||||||
[cellDef.label]: cellDef
|
this.state.currentRulesetBuild.blocks[blockToSave.label] = blockToSave;
|
||||||
}
|
this.forceUpdate();
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
this.props.onRulesetChange();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
handleAddCell(cellDef: CellDef, blockId: string) {
|
||||||
<>
|
if (cellDef.label) {
|
||||||
<Header size={"tiny"}>
|
this.state.currentRulesetBuild.blocks[blockId].cells[cellDef.label] = cellDef;
|
||||||
{Locale.rulesetsPage.newRuleset}
|
this.forceUpdate();
|
||||||
</Header>
|
}
|
||||||
<RulesetDisplayPanel
|
this.props.onRulesetChange();
|
||||||
ruleset={currentRulesetBuild}
|
}
|
||||||
editable={true}
|
|
||||||
loading={false}
|
|
||||||
onAddCell={handleAddCell}
|
|
||||||
/>
|
|
||||||
<Header size={"tiny"}>
|
|
||||||
{Locale.rulesetsPage.newBlock}
|
|
||||||
</Header>
|
|
||||||
<Segment>
|
|
||||||
<Form>
|
|
||||||
<Form.Field>
|
|
||||||
<label>{Locale.rulesetsPage.blockName + ": "}</label>
|
|
||||||
<input
|
|
||||||
placeholder={Locale.rulesetsPage.blockNamePlaceholder}
|
|
||||||
onChange={(e) => updateNewBlockInput({...newBlockInput, label: e.target.value})}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
<Form.Field>
|
|
||||||
<Checkbox
|
|
||||||
toggle={true}
|
|
||||||
onChange={(e, c) => updateNewBlockInput({...newBlockInput, hasBonus: c.checked ?? false})}
|
|
||||||
label={Locale.rulesetsPage.bonus}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
{newBlockInput.hasBonus && (
|
|
||||||
<>
|
|
||||||
<Form.Field width={4}>
|
|
||||||
<label>{Locale.rulesetsPage.bonusScore + ": "}</label>
|
|
||||||
<input
|
|
||||||
type={"number"}
|
|
||||||
value={newBlockInput.bonusScore}
|
|
||||||
onChange={(e) => updateNewBlockInput({...newBlockInput, bonusScore: Number(e.target.value)})}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
<Form.Field width={4}>
|
|
||||||
<label>{Locale.rulesetsPage.bonusThreshold + ": "}</label>
|
|
||||||
<input
|
|
||||||
type={"number"}
|
|
||||||
value={newBlockInput.bonusFor}
|
|
||||||
onChange={(e) => updateNewBlockInput({...newBlockInput, bonusFor: Number(e.target.value)})}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Form.Field>
|
|
||||||
<Button
|
|
||||||
onClick={handleAddBlock}
|
|
||||||
>
|
|
||||||
{Locale.rulesetsPage.addBlock}
|
|
||||||
</Button>
|
|
||||||
</Form.Field>
|
|
||||||
</Form>
|
|
||||||
</Segment>
|
|
||||||
<Button
|
|
||||||
fluid={true}
|
|
||||||
onClick={() => onSubmitRuleset(currentRulesetBuild)}
|
|
||||||
>
|
|
||||||
{Locale.rulesetsPage.submit}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CreateRulesetPanel;
|
handleRulesetNameChange(newLabel: string) {
|
||||||
|
this.setState({
|
||||||
|
currentRulesetBuild: {
|
||||||
|
...this.state.currentRulesetBuild,
|
||||||
|
label: newLabel,
|
||||||
|
id: newLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlockNameChange(newName: string) {
|
||||||
|
this.setState({
|
||||||
|
newBlockInput: {
|
||||||
|
...this.state.newBlockInput,
|
||||||
|
label: newName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToggleBlockBonus(newHasBonus: boolean) {
|
||||||
|
this.setState({
|
||||||
|
newBlockInput: {
|
||||||
|
...this.state.newBlockInput,
|
||||||
|
hasBonus: newHasBonus,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBonusScoreChange(newBonusScore: number) {
|
||||||
|
this.setState({
|
||||||
|
newBlockInput: {
|
||||||
|
...this.state.newBlockInput,
|
||||||
|
bonusScore: newBonusScore,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBonusForChange(newBonusFor: number) {
|
||||||
|
this.setState({
|
||||||
|
newBlockInput: {
|
||||||
|
...this.state.newBlockInput,
|
||||||
|
bonusFor: newBonusFor,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
blocksExistAndAllHaveCells(): boolean {
|
||||||
|
return (
|
||||||
|
Object.values(this.state.currentRulesetBuild.blocks).length > 0 &&
|
||||||
|
Object.values(this.state.currentRulesetBuild.blocks).reduce(
|
||||||
|
(prev: boolean, blockDef: BlockDef) =>
|
||||||
|
Object.values(blockDef.cells).length > 0 && prev,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBlock(blockId: string) {
|
||||||
|
this.props.onRulesetChange();
|
||||||
|
delete this.state.currentRulesetBuild.blocks[blockId];
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCell(cellId: string, blockId: string) {
|
||||||
|
this.props.onRulesetChange();
|
||||||
|
delete this.state.currentRulesetBuild.blocks[blockId].cells[cellId];
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
async submitNewRuleset() {
|
||||||
|
this.setState({saving: true}, async () => {
|
||||||
|
const response = await axios.post(
|
||||||
|
SERVER_BASE_NAME + "/api/ruleset",
|
||||||
|
this.state.currentRulesetBuild
|
||||||
|
);
|
||||||
|
console.log(response);
|
||||||
|
this.setState({saving: false}, () => {
|
||||||
|
this.props.onRulesetSave();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const Locale = this.context.strings;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid>
|
||||||
|
<Grid.Column>
|
||||||
|
<Grid.Row>
|
||||||
|
<Segment basic={true}>
|
||||||
|
<EditableHeader
|
||||||
|
onTextEdit={(t) => this.handleRulesetNameChange(t)}
|
||||||
|
text={this.state.currentRulesetBuild.label}
|
||||||
|
headerProps={{size: "small"}}
|
||||||
|
/>
|
||||||
|
<RulesetDisplayPanel
|
||||||
|
ruleset={this.state.currentRulesetBuild}
|
||||||
|
editable={true}
|
||||||
|
loading={false}
|
||||||
|
removeBlock={(id) => this.removeBlock(id)}
|
||||||
|
removeCell={(cid, bid) => this.removeCell(cid, bid)}
|
||||||
|
onAddCell={(c, b) => this.handleAddCell(c, b)}
|
||||||
|
/>
|
||||||
|
</Segment>
|
||||||
|
</Grid.Row>
|
||||||
|
<Grid.Row>
|
||||||
|
<Segment basic={true}>
|
||||||
|
<Header size={"tiny"}>{Locale.rulesetsPage.newBlock}</Header>
|
||||||
|
<NewBlockForm
|
||||||
|
newBlockInput={this.state.newBlockInput}
|
||||||
|
onNameChange={(x) => this.handleBlockNameChange(x)}
|
||||||
|
onBonusToggle={(x) => this.handleToggleBlockBonus(x)}
|
||||||
|
onBonusScoreChange={(x) => this.handleBonusScoreChange(x)}
|
||||||
|
onBonusForChange={(x) => this.handleBonusForChange(x)}
|
||||||
|
onSubmitClick={() => this.handleAddBlock()}
|
||||||
|
/>
|
||||||
|
</Segment>
|
||||||
|
</Grid.Row>
|
||||||
|
<Grid.Column>
|
||||||
|
<Segment textAlign={"center"} basic={true}>
|
||||||
|
<Button
|
||||||
|
loading={this.state.saving}
|
||||||
|
primary={true}
|
||||||
|
disabled={!this.blocksExistAndAllHaveCells()}
|
||||||
|
onClick={() => this.submitNewRuleset()}
|
||||||
|
>
|
||||||
|
{Locale.rulesetsPage.save}
|
||||||
|
</Button>
|
||||||
|
</Segment>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CreateRulesetPanel.contextType = UserContext;
|
||||||
|
|
||||||
|
export default CreateRulesetPanel;
|
||||||
|
|||||||
39
src/Components/EditableHeader.tsx
Normal file
39
src/Components/EditableHeader.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import React, {useState, KeyboardEvent} from "react";
|
||||||
|
import {Header, Icon, Input, StrictHeaderProps} from "semantic-ui-react";
|
||||||
|
|
||||||
|
interface EditableHeaderProps {
|
||||||
|
onTextEdit: (newText: string) => any;
|
||||||
|
headerProps: StrictHeaderProps;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditableHeader: React.FunctionComponent<EditableHeaderProps> = (props) => {
|
||||||
|
const {text, onTextEdit, headerProps} = props;
|
||||||
|
const [isEditing, updateIsEditing] = useState(false);
|
||||||
|
|
||||||
|
const handleKeyUp = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
onTextEdit(e.currentTarget.value);
|
||||||
|
updateIsEditing(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return isEditing ? (
|
||||||
|
<Header {...headerProps}>
|
||||||
|
<Input
|
||||||
|
onBlur={() => updateIsEditing(false)}
|
||||||
|
autoFocus={true}
|
||||||
|
onChange={(e) => onTextEdit(e.target.value)}
|
||||||
|
value={text}
|
||||||
|
onKeyUp={(e: KeyboardEvent<HTMLInputElement>) => handleKeyUp(e)}
|
||||||
|
/>
|
||||||
|
</Header>
|
||||||
|
) : (
|
||||||
|
<Header style={{cursor: "pointer"}} onClick={() => updateIsEditing(true)} {...headerProps}>
|
||||||
|
{text + " "}
|
||||||
|
<Icon name={"edit"} size={"tiny"} disabled={true}/>
|
||||||
|
</Header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditableHeader;
|
||||||
69
src/Components/NewBlockForm.tsx
Normal file
69
src/Components/NewBlockForm.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import React, {useContext} from "react";
|
||||||
|
import UserContext from "../Contexts/UserContext";
|
||||||
|
import {Button, Checkbox, Form, Segment} from "semantic-ui-react";
|
||||||
|
|
||||||
|
function NewBlockForm(props: {
|
||||||
|
newBlockInput: {
|
||||||
|
bonusScore: number;
|
||||||
|
bonusFor: number;
|
||||||
|
label: string;
|
||||||
|
hasBonus: boolean;
|
||||||
|
};
|
||||||
|
onNameChange: (newName: string) => void;
|
||||||
|
onBonusToggle: (newHasBonus: boolean) => void;
|
||||||
|
onBonusScoreChange: (newBonusScore: number) => void;
|
||||||
|
onBonusForChange: (newBonusFor: number) => void;
|
||||||
|
onSubmitClick: () => void;
|
||||||
|
}) {
|
||||||
|
const {strings: Locale} = useContext(UserContext);
|
||||||
|
return (
|
||||||
|
<Segment>
|
||||||
|
<Form>
|
||||||
|
<Form.Field>
|
||||||
|
<label>{Locale.rulesetsPage.blockName + ": "}</label>
|
||||||
|
<input
|
||||||
|
placeholder={Locale.rulesetsPage.blockNamePlaceholder}
|
||||||
|
onChange={(e) => props.onNameChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
<Form.Field>
|
||||||
|
<Checkbox
|
||||||
|
toggle={true}
|
||||||
|
onChange={(e, c) => props.onBonusToggle(c.checked ?? false)}
|
||||||
|
label={Locale.rulesetsPage.bonus}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
{props.newBlockInput.hasBonus && (
|
||||||
|
<>
|
||||||
|
<Form.Field width={4}>
|
||||||
|
<label>{Locale.rulesetsPage.bonusScore + ": "}</label>
|
||||||
|
<input
|
||||||
|
type={"number"}
|
||||||
|
value={props.newBlockInput.bonusScore}
|
||||||
|
onChange={(e) => props.onBonusScoreChange(Number(e.target.value))}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
<Form.Field width={4}>
|
||||||
|
<label>{Locale.rulesetsPage.bonusThreshold + ": "}</label>
|
||||||
|
<input
|
||||||
|
type={"number"}
|
||||||
|
value={props.newBlockInput.bonusFor}
|
||||||
|
onChange={(e) => props.onBonusForChange(Number(e.target.value))}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Form.Field>
|
||||||
|
<Button
|
||||||
|
disabled={props.newBlockInput.label === ""}
|
||||||
|
onClick={props.onSubmitClick}
|
||||||
|
>
|
||||||
|
{Locale.rulesetsPage.addBlock}
|
||||||
|
</Button>
|
||||||
|
</Form.Field>
|
||||||
|
</Form>
|
||||||
|
</Segment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewBlockForm;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import {BlockDef, CellDef} from "../Services/RulesetSchemaDto";
|
import {BlockDef, CellDef} from "../Services/RulesetSchemaDto";
|
||||||
import React, {useContext, useState} from "react";
|
import React, {useContext, useState} from "react";
|
||||||
import RulesetCellTableRow from "./RulesetCellTableRow";
|
import RulesetCellTableRow from "./RulesetCellTableRow";
|
||||||
import {Button, Dropdown, DropdownItemProps, Grid, Input, Table} from "semantic-ui-react";
|
import {Button, Dropdown, DropdownItemProps, Grid, Input, List, Table} from "semantic-ui-react";
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import {FieldType} from "../enums";
|
import {FieldType} from "../enums";
|
||||||
|
|
||||||
@@ -10,32 +10,28 @@ interface RulesetBlockTableProps {
|
|||||||
blockDef: BlockDef | null;
|
blockDef: BlockDef | null;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
onAddCell?: (cellDef: CellDef, blockId: string) => any;
|
onAddCell?: (cellDef: CellDef, blockId: string) => any;
|
||||||
|
removeBlock?: (blockId: string) => any;
|
||||||
|
removeCell?: (cellId: string, blockId: string) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RulesetBlockTable: React.FunctionComponent<RulesetBlockTableProps> = (props) => {
|
const RulesetBlockTable: React.FunctionComponent<RulesetBlockTableProps> = (props) => {
|
||||||
const {id, blockDef, editable, onAddCell} = props;
|
const {id, blockDef, editable, onAddCell, removeCell} = props;
|
||||||
const [currentCellInput, updateCurrentCellInput] = useState({
|
const [currentCellInput, updateCurrentCellInput] = useState({
|
||||||
label: "",
|
label: "",
|
||||||
maxMultiples: 0,
|
maxMultiples: 1,
|
||||||
multiplier: 0,
|
multiplier: 1,
|
||||||
fieldType: FieldType.number,
|
fieldType: undefined,
|
||||||
score: 0,
|
score: 25,
|
||||||
|
maxSuperkadis: 5,
|
||||||
});
|
});
|
||||||
const {strings: Locale} = useContext(UserContext);
|
const {strings: Locale} = useContext(UserContext);
|
||||||
|
|
||||||
if (!blockDef) {
|
if (!blockDef) {
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table attached={true} fixed={true} celled={true}>
|
||||||
attached={true}
|
|
||||||
fixed={true}
|
|
||||||
celled={true}
|
|
||||||
>
|
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell colSpan={"3"} textAlign={"center"}>
|
||||||
colSpan={"3"}
|
|
||||||
textAlign={"center"}
|
|
||||||
>
|
|
||||||
{Locale.rulesetsPage.noBlocks}
|
{Locale.rulesetsPage.noBlocks}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
@@ -51,151 +47,200 @@ const RulesetBlockTable: React.FunctionComponent<RulesetBlockTableProps> = (prop
|
|||||||
subText += `${Locale.general.yes},
|
subText += `${Locale.general.yes},
|
||||||
${Locale.rulesetsPage.bonusScore}: ${blockDef.bonusScore},
|
${Locale.rulesetsPage.bonusScore}: ${blockDef.bonusScore},
|
||||||
${Locale.rulesetsPage.bonusThreshold}: ${blockDef.bonusFor}`;
|
${Locale.rulesetsPage.bonusThreshold}: ${blockDef.bonusFor}`;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
subText += Locale.general.no;
|
subText += Locale.general.no;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldTypeOptions: DropdownItemProps[] = [
|
const fieldTypeOptions: DropdownItemProps[] = [
|
||||||
{value: FieldType.bool, key: FieldType.bool, text: Locale.rulesetsPage[FieldType.bool]},
|
{value: FieldType.bool, key: FieldType.bool, text: Locale.rulesetsPage[FieldType.bool]},
|
||||||
{value: FieldType.multiplier, key: FieldType.multiplier, text: Locale.rulesetsPage[FieldType.multiplier]},
|
{
|
||||||
{value: FieldType.number, key: FieldType.number, text: Locale.rulesetsPage[FieldType.number]},
|
value: FieldType.multiplier,
|
||||||
{value: FieldType.superkadi, key: FieldType.superkadi, text: Locale.rulesetsPage[FieldType.superkadi]},
|
key: FieldType.multiplier,
|
||||||
|
text: Locale.rulesetsPage[FieldType.multiplier],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: FieldType.number,
|
||||||
|
key: FieldType.number,
|
||||||
|
text: Locale.rulesetsPage[FieldType.number],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: FieldType.superkadi,
|
||||||
|
key: FieldType.superkadi,
|
||||||
|
text: Locale.rulesetsPage[FieldType.superkadi],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onChangeDropdown = (value: FieldType) => {
|
const onChangeFieldTypeDropdown = (newFieldType: FieldType) => {
|
||||||
const newCell = {
|
const newCell: any = Object.assign({}, currentCellInput);
|
||||||
...currentCellInput,
|
newCell.fieldType = newFieldType;
|
||||||
fieldType: value,
|
|
||||||
};
|
|
||||||
if (value === FieldType.bool) {
|
|
||||||
newCell.score = 0;
|
|
||||||
}
|
|
||||||
else if (value === FieldType.multiplier) {
|
|
||||||
newCell.multiplier = 0;
|
|
||||||
newCell.maxMultiples = 5;
|
|
||||||
}
|
|
||||||
else if (value === FieldType.superkadi) {
|
|
||||||
newCell.maxMultiples = 5;
|
|
||||||
newCell.score = 50;
|
|
||||||
}
|
|
||||||
updateCurrentCellInput(newCell);
|
updateCurrentCellInput(newCell);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAddCell = () => {
|
||||||
|
if (onAddCell) {
|
||||||
|
const newCell: any = Object.assign({}, currentCellInput);
|
||||||
|
if (newCell.fieldType === FieldType.bool) {
|
||||||
|
delete newCell.maxMultiples;
|
||||||
|
delete newCell.maxSuperkadis;
|
||||||
|
delete newCell.multiplier;
|
||||||
|
} else if (newCell.fieldType === FieldType.multiplier) {
|
||||||
|
delete newCell.score;
|
||||||
|
delete newCell.maxSuperkadis;
|
||||||
|
} else if (newCell.fieldType === FieldType.superkadi) {
|
||||||
|
delete newCell.multiplier;
|
||||||
|
delete newCell.maxMultiples;
|
||||||
|
} else if (newCell.fieldType === FieldType.number) {
|
||||||
|
delete newCell.multiplier;
|
||||||
|
delete newCell.maxMultiples;
|
||||||
|
delete newCell.maxSuperkadis;
|
||||||
|
delete newCell.score;
|
||||||
|
}
|
||||||
|
onAddCell(newCell, id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table attached={true} fixed={true} celled={true}>
|
||||||
attached={true}
|
|
||||||
fixed={true}
|
|
||||||
celled={true}
|
|
||||||
>
|
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.HeaderCell
|
<Table.HeaderCell verticalAlign={"middle"} colSpan={"3"} textAlign={"center"}>
|
||||||
colSpan={"3"}
|
|
||||||
textAlign={"center"}
|
|
||||||
>
|
|
||||||
{blockDef.label}
|
{blockDef.label}
|
||||||
|
{editable && (
|
||||||
|
<Button
|
||||||
|
floated={"right"}
|
||||||
|
color={"red"}
|
||||||
|
icon={"minus"}
|
||||||
|
size={"mini"}
|
||||||
|
onClick={() => props.removeBlock?.(id)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{idAndCellList.map(idAndCell => (
|
{idAndCellList.map((idAndCell) => (
|
||||||
<RulesetCellTableRow
|
<RulesetCellTableRow
|
||||||
key={idAndCell[0]}
|
key={idAndCell[0]}
|
||||||
id={idAndCell[0]}
|
blockId={id}
|
||||||
cellDef={idAndCell[1]}
|
cellDef={idAndCell[1]}
|
||||||
|
editable={editable}
|
||||||
|
removeCell={removeCell}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{editable && (
|
{editable && (
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell
|
<Table.Cell>
|
||||||
style={{overflow: "visible"}}
|
<Input
|
||||||
colSpan={"3"}
|
fluid={true}
|
||||||
>
|
value={currentCellInput.label}
|
||||||
<Grid>
|
placeholder={Locale.rulesetsPage.cellNamePlaceholder}
|
||||||
<Grid.Row
|
onChange={(e) =>
|
||||||
columns={3}
|
updateCurrentCellInput({
|
||||||
verticalAlign={"middle"}
|
...currentCellInput,
|
||||||
>
|
label: e.target.value,
|
||||||
<Grid.Column width={4}>
|
})
|
||||||
<Input
|
}
|
||||||
fluid={true}
|
/>
|
||||||
value={currentCellInput.label}
|
</Table.Cell>
|
||||||
label={Locale.rulesetsPage.cellName}
|
<Table.Cell style={{overflow: "visible"}}>
|
||||||
placeholder={Locale.rulesetsPage.cellNamePlaceholder}
|
<Dropdown
|
||||||
onChange={(e) => updateCurrentCellInput({...currentCellInput, label: e.target.value})}
|
basic={true}
|
||||||
/>
|
placeholder={Locale.rulesetsPage.fieldTypePlaceholder}
|
||||||
</Grid.Column>
|
onChange={(e, c) => onChangeFieldTypeDropdown(c.value as FieldType)}
|
||||||
<Grid.Column width={4}>
|
options={fieldTypeOptions}
|
||||||
<Dropdown
|
button={true}
|
||||||
selectedLabel={currentCellInput.fieldType}
|
/>
|
||||||
placeholder={Locale.rulesetsPage.fieldTypePlaceholder}
|
</Table.Cell>
|
||||||
onChange={(e, c) => onChangeDropdown(c.value as FieldType)}
|
<Table.Cell>
|
||||||
options={fieldTypeOptions}
|
<Grid divided={true}>
|
||||||
button={true}
|
<Grid.Column width={12}>
|
||||||
/>
|
{currentCellInput.fieldType === undefined ||
|
||||||
</Grid.Column>
|
currentCellInput.fieldType === FieldType.number ? (
|
||||||
<Grid.Column width={4}>
|
Locale.rulesetsPage.extraCellSettingsInfo
|
||||||
{currentCellInput.fieldType === FieldType.multiplier && (
|
) : (
|
||||||
<Input
|
<List>
|
||||||
label={Locale.rulesetsPage.multiplierPlaceholder}
|
{(currentCellInput.fieldType === FieldType.bool ||
|
||||||
fluid={true}
|
currentCellInput.fieldType ===
|
||||||
type={"number"}
|
FieldType.superkadi) && (
|
||||||
value={currentCellInput.multiplier}
|
<List.Item>
|
||||||
onChange={(e) => updateCurrentCellInput(
|
<Input
|
||||||
{...currentCellInput, multiplier: Number(e.target.value)})}
|
label={Locale.rulesetsPage.valuePlaceholder}
|
||||||
/>
|
fluid={true}
|
||||||
)}
|
type={"number"}
|
||||||
{(currentCellInput.fieldType === FieldType.superkadi
|
value={currentCellInput.score}
|
||||||
|| currentCellInput.fieldType === FieldType.multiplier) && (
|
onChange={(e) =>
|
||||||
<Input
|
updateCurrentCellInput({
|
||||||
label={Locale.rulesetsPage.maxMultiplesPlaceholder}
|
...currentCellInput,
|
||||||
fluid={true}
|
score: Number(e.target.value),
|
||||||
type={"number"}
|
})
|
||||||
value={currentCellInput.maxMultiples}
|
}
|
||||||
onChange={(e) => updateCurrentCellInput({
|
/>
|
||||||
...currentCellInput,
|
</List.Item>
|
||||||
maxMultiples: Number(e.target.value),
|
)}
|
||||||
})}
|
{currentCellInput.fieldType ===
|
||||||
/>
|
FieldType.multiplier && (
|
||||||
)}
|
<List.Item>
|
||||||
{(currentCellInput.fieldType === FieldType.bool
|
<Input
|
||||||
|| currentCellInput.fieldType === FieldType.superkadi
|
label={
|
||||||
|| currentCellInput.fieldType === FieldType.number) && (
|
Locale.rulesetsPage
|
||||||
<Input
|
.multiplierPlaceholder
|
||||||
label={Locale.rulesetsPage.valuePlaceholder}
|
}
|
||||||
fluid={true}
|
fluid={true}
|
||||||
type={"number"}
|
type={"number"}
|
||||||
value={currentCellInput.score}
|
value={currentCellInput.multiplier}
|
||||||
onChange={(e) => updateCurrentCellInput(
|
onChange={(e) =>
|
||||||
{...currentCellInput, score: Number(e.target.value)})}
|
updateCurrentCellInput({
|
||||||
/>
|
...currentCellInput,
|
||||||
)}
|
multiplier: Number(e.target.value),
|
||||||
</Grid.Column>
|
})
|
||||||
<Grid.Column
|
}
|
||||||
width={4}
|
/>
|
||||||
textAlign={"right"}
|
</List.Item>
|
||||||
>
|
)}
|
||||||
<Button
|
{(currentCellInput.fieldType === FieldType.superkadi ||
|
||||||
onClick={() => {
|
currentCellInput.fieldType ===
|
||||||
if (onAddCell) {
|
FieldType.multiplier) && (
|
||||||
onAddCell(currentCellInput, id)
|
<List.Item>
|
||||||
}
|
<Input
|
||||||
}}
|
label={
|
||||||
>
|
Locale.rulesetsPage
|
||||||
{Locale.rulesetsPage.addCell}
|
.maxMultiplesPlaceholder
|
||||||
</Button>
|
}
|
||||||
</Grid.Column>
|
fluid={true}
|
||||||
</Grid.Row>
|
type={"number"}
|
||||||
|
value={currentCellInput.maxMultiples}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateCurrentCellInput({
|
||||||
|
...currentCellInput,
|
||||||
|
maxMultiples: Number(
|
||||||
|
e.target.value
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
</Grid.Column>
|
||||||
|
<Grid.Column width={4}>
|
||||||
|
<Button
|
||||||
|
basic={true}
|
||||||
|
floated={"right"}
|
||||||
|
disabled={
|
||||||
|
currentCellInput.label === "" ||
|
||||||
|
!currentCellInput.fieldType
|
||||||
|
}
|
||||||
|
icon={"add"}
|
||||||
|
onClick={handleAddCell}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
)}
|
)}
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell
|
<Table.Cell colSpan={"3"} textAlign={"center"}>
|
||||||
colSpan={"3"}
|
|
||||||
textAlign={"center"}
|
|
||||||
>
|
|
||||||
{subText}
|
{subText}
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
@@ -204,4 +249,4 @@ const RulesetBlockTable: React.FunctionComponent<RulesetBlockTableProps> = (prop
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RulesetBlockTable;
|
export default RulesetBlockTable;
|
||||||
|
|||||||
@@ -1,31 +1,82 @@
|
|||||||
import {BoolCellDef, CellDef, MultiplierCellDef, SuperkadiCellDef} from "../Services/RulesetSchemaDto";
|
import {
|
||||||
|
BoolCellDef,
|
||||||
|
CellDef,
|
||||||
|
MultiplierCellDef,
|
||||||
|
NumberCellDef,
|
||||||
|
SuperkadiCellDef,
|
||||||
|
} from "../Services/RulesetSchemaDto";
|
||||||
import React, {useContext} from "react";
|
import React, {useContext} from "react";
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import {Table} from "semantic-ui-react";
|
import {Button, Grid, List, Table} from "semantic-ui-react";
|
||||||
|
import {FieldType} from "../enums";
|
||||||
|
|
||||||
interface TableCellRowProps {
|
interface TableCellRowProps {
|
||||||
id: string;
|
blockId: string;
|
||||||
cellDef: CellDef;
|
cellDef: CellDef;
|
||||||
|
editable?: boolean;
|
||||||
|
removeCell?: (cellId: string, blockId: string) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RulesetCellTableRow: React.FunctionComponent<TableCellRowProps> = (props) => {
|
const RulesetCellTableRow: React.FunctionComponent<TableCellRowProps> = (props) => {
|
||||||
const {id, cellDef} = props;
|
const {blockId, cellDef, editable} = props;
|
||||||
const {strings: Locale} = useContext(UserContext);
|
const {strings: Locale} = useContext(UserContext);
|
||||||
const displayValue = (cellDef as MultiplierCellDef).multiplier ??
|
|
||||||
(cellDef as SuperkadiCellDef | BoolCellDef).score ?? Locale.general.nA;
|
|
||||||
return (
|
return (
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell key={id}>
|
<Table.Cell key={cellDef.label}>{cellDef.label}</Table.Cell>
|
||||||
{cellDef.label}
|
<Table.Cell>{Locale.rulesetsPage[cellDef.fieldType]}</Table.Cell>
|
||||||
</Table.Cell>
|
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
{Locale.rulesetsPage[cellDef.fieldType]}
|
<Grid>
|
||||||
</Table.Cell>
|
<Grid.Column width={12}>
|
||||||
<Table.Cell disabled={displayValue === Locale.general.nA}>
|
<List>
|
||||||
{displayValue}
|
{(cellDef as MultiplierCellDef).multiplier && (
|
||||||
|
<List.Item>
|
||||||
|
{Locale.rulesetsPage.multiplierPlaceholder +
|
||||||
|
": " +
|
||||||
|
(cellDef as MultiplierCellDef).multiplier}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
{(cellDef as BoolCellDef | SuperkadiCellDef).score && (
|
||||||
|
<List.Item>
|
||||||
|
{Locale.rulesetsPage.valuePlaceholder +
|
||||||
|
": " +
|
||||||
|
(cellDef as BoolCellDef | SuperkadiCellDef).score}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
{(cellDef as MultiplierCellDef).maxMultiples && (
|
||||||
|
<List.Item>
|
||||||
|
{Locale.rulesetsPage.maxMultiplesPlaceholder +
|
||||||
|
": " +
|
||||||
|
(cellDef as MultiplierCellDef).maxMultiples}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
{(cellDef as SuperkadiCellDef).maxSuperkadis && (
|
||||||
|
<List.Item>
|
||||||
|
{Locale.rulesetsPage.maxSuperkadisPlaceholder +
|
||||||
|
": " +
|
||||||
|
(cellDef as SuperkadiCellDef).maxSuperkadis}
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
<List.Item disabled={true}>
|
||||||
|
{cellDef.fieldType === FieldType.number && (
|
||||||
|
<p>{Locale.general.nA}</p>
|
||||||
|
)}
|
||||||
|
</List.Item>
|
||||||
|
</List>
|
||||||
|
</Grid.Column>
|
||||||
|
{editable && (
|
||||||
|
<Grid.Column textAlign={"right"}>
|
||||||
|
<Button
|
||||||
|
size={"mini"}
|
||||||
|
color={"red"}
|
||||||
|
icon={"minus"}
|
||||||
|
onClick={() => props.removeCell?.(cellDef.label, blockId)}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RulesetCellTableRow;
|
export default RulesetCellTableRow;
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import React, {useContext} from "react";
|
import React, {useContext} from "react";
|
||||||
import {
|
import {CellDef, RulesetSchemaDto} from "../Services/RulesetSchemaDto";
|
||||||
BlockDef,
|
import {Table} from "semantic-ui-react";
|
||||||
BoolCellDef,
|
|
||||||
CellDef,
|
|
||||||
MultiplierCellDef,
|
|
||||||
RulesetSchemaDto,
|
|
||||||
SuperkadiCellDef
|
|
||||||
} from "../Services/RulesetSchemaDto";
|
|
||||||
import {Header, List, Table, TableBody} from "semantic-ui-react";
|
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import Loading from "./Loading";
|
import Loading from "./Loading";
|
||||||
import RulesetBlockTable from "./RulesetBlockTable";
|
import RulesetBlockTable from "./RulesetBlockTable";
|
||||||
@@ -17,19 +10,20 @@ interface RulesetDisplayPanelProps {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
onAddCell?: (cellDef: CellDef, blockId: string) => any;
|
onAddCell?: (cellDef: CellDef, blockId: string) => any;
|
||||||
|
removeBlock?: (blockId: string) => any;
|
||||||
|
removeCell?: (cellId: string, blockId: string) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RulesetDisplayPanel: React.FunctionComponent<RulesetDisplayPanelProps> = (props) => {
|
const RulesetDisplayPanel: React.FunctionComponent<RulesetDisplayPanelProps> = (props) => {
|
||||||
const {ruleset, loading, editable, onAddCell} = props;
|
const {ruleset, loading, editable, onAddCell, removeBlock, removeCell} = props;
|
||||||
const {strings: Locale} = useContext(UserContext);
|
const {strings: Locale} = useContext(UserContext);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading/>;
|
return <Loading />;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table attached={true} celled={true}>
|
<Table fixed={true} attached={true} celled={true}>
|
||||||
<Table.Header>
|
<Table.Header>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.HeaderCell>
|
<Table.HeaderCell>
|
||||||
@@ -39,29 +33,29 @@ const RulesetDisplayPanel: React.FunctionComponent<RulesetDisplayPanelProps> = (
|
|||||||
{Locale.rulesetsPage.fieldTypeHeader}
|
{Locale.rulesetsPage.fieldTypeHeader}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
<Table.HeaderCell>
|
<Table.HeaderCell>
|
||||||
{Locale.rulesetsPage.fieldValueHeader}
|
{Locale.rulesetsPage.fieldAttributesHeader}
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
</Table>
|
</Table>
|
||||||
{Object.entries(ruleset.blocks).length > 0 ?
|
{Object.entries(ruleset.blocks).length > 0 ? (
|
||||||
Object.entries(ruleset.blocks).map(idAndBlock => (
|
Object.entries(ruleset.blocks).map((idAndBlock) => (
|
||||||
<RulesetBlockTable
|
<RulesetBlockTable
|
||||||
key={idAndBlock[0]}
|
key={idAndBlock[0]}
|
||||||
id={idAndBlock[0]}
|
id={idAndBlock[0]}
|
||||||
blockDef={idAndBlock[1]}
|
blockDef={idAndBlock[1]}
|
||||||
editable={editable}
|
editable={editable}
|
||||||
onAddCell={onAddCell}
|
onAddCell={onAddCell}
|
||||||
|
removeBlock={removeBlock}
|
||||||
|
removeCell={removeCell}
|
||||||
/>
|
/>
|
||||||
)) : (
|
))
|
||||||
<RulesetBlockTable
|
) : (
|
||||||
id={"noBlocks"}
|
<RulesetBlockTable id={"noBlocks"} blockDef={null} />
|
||||||
blockDef={null}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RulesetDisplayPanel;
|
export default RulesetDisplayPanel;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, {ReactElement} from "react";
|
import React, {ReactElement} from "react";
|
||||||
import {Container, Grid, Header, List, Segment} from "semantic-ui-react";
|
import {Button, Grid, Header, Modal} from "semantic-ui-react";
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import KadiStatsService from "../Services/KadiStatsService";
|
import KadiStatsService from "../Services/KadiStatsService";
|
||||||
import RulesetList from "./RulesetList";
|
import RulesetList from "./RulesetList";
|
||||||
@@ -10,10 +10,13 @@ import CreateRulesetPanel from "./CreateRulesetPanel";
|
|||||||
interface RulesetsPageProps {}
|
interface RulesetsPageProps {}
|
||||||
|
|
||||||
interface RulesetsPageState {
|
interface RulesetsPageState {
|
||||||
|
unsavedChanges: boolean;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
addingNewRuleset: boolean;
|
addingNewRuleset: boolean;
|
||||||
rulesets: RulesetSchemaDto[];
|
rulesets: RulesetSchemaDto[];
|
||||||
selectedRulesetIndex: number;
|
selectedRulesetIndex: number;
|
||||||
|
modalContinueCallback: () => any;
|
||||||
|
showWarningModal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState> {
|
class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState> {
|
||||||
@@ -21,6 +24,9 @@ class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState>
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
modalContinueCallback: () => {},
|
||||||
|
showWarningModal: false,
|
||||||
|
unsavedChanges: false,
|
||||||
loading: true,
|
loading: true,
|
||||||
addingNewRuleset: false,
|
addingNewRuleset: false,
|
||||||
rulesets: [],
|
rulesets: [],
|
||||||
@@ -38,28 +44,48 @@ class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState>
|
|||||||
}
|
}
|
||||||
|
|
||||||
onRulesetSelect(newRulesetId: string | "addNewRuleset") {
|
onRulesetSelect(newRulesetId: string | "addNewRuleset") {
|
||||||
|
if (newRulesetId === "addNewRuleset" || !this.state.unsavedChanges) {
|
||||||
|
this.selectRuleset(newRulesetId);
|
||||||
|
}
|
||||||
|
else if (this.state.unsavedChanges) {
|
||||||
|
this.warn(() => this.selectRuleset(newRulesetId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
warn(callback: () => any) {
|
||||||
|
this.setState({showWarningModal: true, modalContinueCallback: callback});
|
||||||
|
}
|
||||||
|
|
||||||
|
selectRuleset(newRulesetId: string | "addNewRuleset") {
|
||||||
if (newRulesetId === "addNewRuleset") {
|
if (newRulesetId === "addNewRuleset") {
|
||||||
this.setState({addingNewRuleset: true});
|
this.setState({addingNewRuleset: true});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
unsavedChanges: false,
|
||||||
addingNewRuleset: false,
|
addingNewRuleset: false,
|
||||||
selectedRulesetIndex: this.state.rulesets.findIndex(item => item.label === newRulesetId)
|
selectedRulesetIndex: this.state.rulesets.findIndex(
|
||||||
|
(item) => item.label === newRulesetId
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
submitNewRuleset(ruleset: RulesetSchemaDto) {
|
onWarningModalActionClick() {
|
||||||
|
const oldContinueCallback = this.state.modalContinueCallback;
|
||||||
|
this.setState({showWarningModal: false, modalContinueCallback: () => {}}, () =>
|
||||||
|
oldContinueCallback()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onWarningModalClose() {
|
||||||
|
this.setState({showWarningModal: false, modalContinueCallback: () => {}});
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): ReactElement {
|
render(): ReactElement {
|
||||||
const Locale = this.context.strings;
|
const Locale = this.context.strings;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header size={"huge"}>
|
<Header size={"huge"}>{Locale.rulesetsPage.title}</Header>
|
||||||
{Locale.rulesetsPage.title}
|
|
||||||
</Header>
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Row>
|
<Grid.Row>
|
||||||
<Grid.Column width={4}>
|
<Grid.Column width={4}>
|
||||||
@@ -67,13 +93,14 @@ class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState>
|
|||||||
onItemChange={(r) => this.onRulesetSelect(r)}
|
onItemChange={(r) => this.onRulesetSelect(r)}
|
||||||
selectedItemIndex={this.state.selectedRulesetIndex}
|
selectedItemIndex={this.state.selectedRulesetIndex}
|
||||||
creatingRuleset={this.state.addingNewRuleset}
|
creatingRuleset={this.state.addingNewRuleset}
|
||||||
rulesetNames={this.state.rulesets.map(ruleset => ruleset.label)}
|
rulesetNames={this.state.rulesets.map((ruleset) => ruleset.label)}
|
||||||
/>
|
/>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column width={12}>
|
<Grid.Column width={12}>
|
||||||
{this.state.addingNewRuleset ? (
|
{this.state.addingNewRuleset ? (
|
||||||
<CreateRulesetPanel
|
<CreateRulesetPanel
|
||||||
onSubmitRuleset={(r) => this.submitNewRuleset(r)}
|
onRulesetSave={() => this.setState({unsavedChanges: false})}
|
||||||
|
onRulesetChange={() => this.setState({unsavedChanges: true})}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<RulesetDisplayPanel
|
<RulesetDisplayPanel
|
||||||
@@ -84,10 +111,30 @@ class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState>
|
|||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Modal
|
||||||
|
open={this.state.showWarningModal}
|
||||||
|
dimmer={"inverted"}
|
||||||
|
size={"tiny"}
|
||||||
|
onClose={() => this.onWarningModalClose()}
|
||||||
|
>
|
||||||
|
<Modal.Header>Discard ruleset?</Modal.Header>
|
||||||
|
<Modal.Content>Are you sure you want to discard the current ruleset? Any changes you've made will be lost.</Modal.Content>
|
||||||
|
<Modal.Actions>
|
||||||
|
<Button color="black" onClick={() => this.onWarningModalClose()}>
|
||||||
|
Return to editing
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => this.onWarningModalActionClick()}
|
||||||
|
negative={true}
|
||||||
|
>
|
||||||
|
Discard ruleset
|
||||||
|
</Button>
|
||||||
|
</Modal.Actions>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RulesetsPage.contextType = UserContext;
|
RulesetsPage.contextType = UserContext;
|
||||||
|
|
||||||
export default RulesetsPage;
|
export default RulesetsPage;
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
import React, {ReactNode} from "react";
|
import React, {ReactNode} from "react";
|
||||||
import {
|
import {
|
||||||
Container,
|
Dropdown,
|
||||||
Dropdown, DropdownItemProps, DropdownMenuProps,
|
DropdownItemProps,
|
||||||
Grid,
|
Grid,
|
||||||
GridColumn,
|
GridColumn,
|
||||||
GridRow,
|
GridRow,
|
||||||
Header, Segment,
|
Header,
|
||||||
} from "semantic-ui-react";
|
} from "semantic-ui-react";
|
||||||
import UserContext from "../Contexts/UserContext";
|
import UserContext from "../Contexts/UserContext";
|
||||||
import {StatsTable} from "./StatsTable";
|
import {StatsTable} from "./StatsTable";
|
||||||
import KadiStatsService from "../Services/KadiStatsService";
|
import KadiStatsService from "../Services/KadiStatsService";
|
||||||
import {ServiceError} from "../errors";
|
import {ServiceError} from "../errors";
|
||||||
import Loading from "./Loading";
|
import Loading from "./Loading";
|
||||||
import KadiStatsServiceSingleton from "../Services/KadiStatsService";
|
|
||||||
import {RulesetSchemaDto} from "../Services/RulesetSchemaDto";
|
import {RulesetSchemaDto} from "../Services/RulesetSchemaDto";
|
||||||
import {StatsDto} from "../Services/StatsDto";
|
|
||||||
|
|
||||||
interface StatsPageProps {}
|
interface StatsPageProps {}
|
||||||
|
|
||||||
@@ -49,17 +47,14 @@ class StatsPage extends React.Component<StatsPageProps, StatsPageState> {
|
|||||||
this.setState({loadingStats: true}, async () => {
|
this.setState({loadingStats: true}, async () => {
|
||||||
try {
|
try {
|
||||||
await this.loadStatsAndRulesetChoices();
|
await this.loadStatsAndRulesetChoices();
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
if (e instanceof ServiceError) {
|
if (e instanceof ServiceError) {
|
||||||
this.setState({error: true});
|
this.setState({error: true});
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
this.setState({loadingStats: false});
|
this.setState({loadingStats: false});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -70,11 +65,21 @@ class StatsPage extends React.Component<StatsPageProps, StatsPageState> {
|
|||||||
const rulesetIds = Object.keys(stats.pStats[0].stats.statsByRuleset);
|
const rulesetIds = Object.keys(stats.pStats[0].stats.statsByRuleset);
|
||||||
const schemas: Record<string, RulesetSchemaDto> = {};
|
const schemas: Record<string, RulesetSchemaDto> = {};
|
||||||
for (const rulesetId of rulesetIds) {
|
for (const rulesetId of rulesetIds) {
|
||||||
schemas[rulesetId] = await KadiStatsService.getRulesetById(rulesetId);
|
schemas[rulesetId] = await KadiStatsService.getRulesetById(
|
||||||
|
rulesetId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const rulesetChoices = rulesetIds.map(rulesetId =>
|
const rulesetChoices = rulesetIds.map((rulesetId) => ({
|
||||||
({key: rulesetId, value: rulesetId, text: schemas[rulesetId].label}));
|
key: rulesetId,
|
||||||
this.setState({stats, rulesetChoices, rulesetSchemas: schemas, selectedRulesetId: rulesetIds[0]});
|
value: rulesetId,
|
||||||
|
text: schemas[rulesetId].label,
|
||||||
|
}));
|
||||||
|
this.setState({
|
||||||
|
stats,
|
||||||
|
rulesetChoices,
|
||||||
|
rulesetSchemas: schemas,
|
||||||
|
selectedRulesetId: rulesetIds[0],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleError(error: any): void {
|
handleError(error: any): void {
|
||||||
@@ -102,23 +107,33 @@ class StatsPage extends React.Component<StatsPageProps, StatsPageState> {
|
|||||||
loading={this.state.loadingStats}
|
loading={this.state.loadingStats}
|
||||||
selection={true}
|
selection={true}
|
||||||
options={this.state.rulesetChoices}
|
options={this.state.rulesetChoices}
|
||||||
defaultValue={this.state.rulesetChoices[0]?.value}
|
defaultValue={
|
||||||
onChange={(e, choice) => this.changeRulesetSelection(choice.value as string)}
|
this.state.rulesetChoices[0]?.value
|
||||||
|
}
|
||||||
|
onChange={(e, choice) =>
|
||||||
|
this.changeRulesetSelection(
|
||||||
|
choice.value as string
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</GridColumn>
|
</GridColumn>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
<GridRow columns={1} style={{overflow: "auto"}}>
|
<GridRow columns={1} style={{overflow: "auto"}}>
|
||||||
<GridColumn>
|
<GridColumn>
|
||||||
{this.state.error ?
|
{this.state.error ? (
|
||||||
<p>{Locale.general.databaseError}</p> :
|
<p>{Locale.general.databaseError}</p>
|
||||||
this.state.loadingStats ?
|
) : this.state.loadingStats ? (
|
||||||
<Loading/> : (
|
<Loading />
|
||||||
<StatsTable
|
) : (
|
||||||
data={this.state.stats}
|
<StatsTable
|
||||||
displayedRulesetSchema={this.state.rulesetSchemas[this.state.selectedRulesetId]}
|
data={this.state.stats}
|
||||||
/>
|
displayedRulesetSchema={
|
||||||
)
|
this.state.rulesetSchemas[
|
||||||
}
|
this.state.selectedRulesetId
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</GridColumn>
|
</GridColumn>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -128,4 +143,4 @@ class StatsPage extends React.Component<StatsPageProps, StatsPageState> {
|
|||||||
}
|
}
|
||||||
StatsPage.contextType = UserContext;
|
StatsPage.contextType = UserContext;
|
||||||
|
|
||||||
export default StatsPage;
|
export default StatsPage;
|
||||||
|
|||||||
28
src/Services/KadiPlayerService.ts
Normal file
28
src/Services/KadiPlayerService.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import {RulesetSchemaDto} from "./RulesetSchemaDto";
|
||||||
|
|
||||||
|
class KadiPlayerService {
|
||||||
|
private readonly players: PlayerDto[] = [];
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
async getPlayerById(id: string): Promise<PlayerDto> {
|
||||||
|
if (!this.rulesets[id]) {
|
||||||
|
await this.loadRulesetById(id);
|
||||||
|
}
|
||||||
|
return this.rulesets[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshStats(): Promise<void> {
|
||||||
|
await this.loadStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllRulesets(): Promise<RulesetSchemaDto[]> {
|
||||||
|
if (!this.allRulesetsLoaded) {
|
||||||
|
await this.loadAllRulesets();
|
||||||
|
}
|
||||||
|
return Object.values(this.rulesets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KadiStatsServiceSingleton = new KadiStatsService();
|
||||||
|
|
||||||
|
export default KadiStatsServiceSingleton;
|
||||||
@@ -3,10 +3,6 @@ import {SERVER_BASE_NAME} from "../index";
|
|||||||
import {StatsDto} from "./StatsDto";
|
import {StatsDto} from "./StatsDto";
|
||||||
import {RulesetSchemaDto} from "./RulesetSchemaDto";
|
import {RulesetSchemaDto} from "./RulesetSchemaDto";
|
||||||
|
|
||||||
const dummyRulesets = [
|
|
||||||
{"id":"DEFAULT_RULESET","label":"Standard Kadi Rules (en)","blocks":{"top":{"label":"Upper","hasBonus":true,"bonusScore":35,"bonusFor":63,"cells":{"aces":{"fieldType":"multiplierField","label":"Aces","multiplier":1,"maxMultiples":5},"twos":{"fieldType":"multiplierField","label":"Twos","multiplier":2,"maxMultiples":5},"threes":{"fieldType":"multiplierField","label":"Threes","multiplier":3,"maxMultiples":5},"fours":{"fieldType":"multiplierField","label":"Fours","multiplier":4,"maxMultiples":5},"fives":{"fieldType":"multiplierField","label":"Fives","multiplier":5,"maxMultiples":5},"sixes":{"fieldType":"multiplierField","label":"Sixes","multiplier":6,"maxMultiples":5}}},"bottom":{"label":"Lower","hasBonus":false,"cells":{"threeKind":{"fieldType":"numberField","label":"Three of a Kind"},"fourKind":{"fieldType":"numberField","label":"Four of a Kind"},"fullHouse":{"fieldType":"boolField","label":"Full House","score":25},"smlStraight":{"fieldType":"boolField","label":"Small Straight","score":30},"lgSraight":{"fieldType":"boolField","label":"Large Straight","score":40},"superkadi":{"fieldType":"superkadiField","label":"Super Kadis","score":50,"maxSuperkadis":5},"chance":{"fieldType":"numberField","label":"Chance"}}}}}
|
|
||||||
];
|
|
||||||
|
|
||||||
class KadiStatsService {
|
class KadiStatsService {
|
||||||
private userStats: StatsDto | null = null;
|
private userStats: StatsDto | null = null;
|
||||||
private rulesets: Record<string, RulesetSchemaDto> = {};
|
private rulesets: Record<string, RulesetSchemaDto> = {};
|
||||||
@@ -19,6 +15,18 @@ class KadiStatsService {
|
|||||||
return this.userStats;
|
return this.userStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async loadAllRulesets(): Promise<void> {
|
||||||
|
const rulesetSchemas = (await axios.get(SERVER_BASE_NAME + "/api/rulesets/")).data.rulesets as RulesetSchemaDto[];
|
||||||
|
console.log(rulesetSchemas);
|
||||||
|
rulesetSchemas.forEach(schema => this.rulesets[schema.id] = schema);
|
||||||
|
this.allRulesetsLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async loadRulesetById(id: string): Promise<void> {
|
||||||
|
const rulesetSchema = (await axios.get(SERVER_BASE_NAME + "/api/ruleset/" + id)).data as RulesetSchemaDto;
|
||||||
|
this.rulesets[rulesetSchema.id] = rulesetSchema;
|
||||||
|
}
|
||||||
|
|
||||||
async getStats(): Promise<StatsDto> {
|
async getStats(): Promise<StatsDto> {
|
||||||
if (this.userStats) {
|
if (this.userStats) {
|
||||||
return this.userStats;
|
return this.userStats;
|
||||||
@@ -29,14 +37,10 @@ class KadiStatsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRulesetById(id: string): Promise<RulesetSchemaDto> {
|
async getRulesetById(id: string): Promise<RulesetSchemaDto> {
|
||||||
if (this.rulesets[id]) {
|
if (!this.rulesets[id]) {
|
||||||
return this.rulesets[id];
|
await this.loadRulesetById(id);
|
||||||
}
|
|
||||||
else {
|
|
||||||
const rulesetSchema = (await axios.get(SERVER_BASE_NAME + "/api/ruleset/" + id)).data as RulesetSchemaDto;
|
|
||||||
this.rulesets[rulesetSchema.id] = rulesetSchema;
|
|
||||||
return this.rulesets[rulesetSchema.id];
|
|
||||||
}
|
}
|
||||||
|
return this.rulesets[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshStats(): Promise<void> {
|
async refreshStats(): Promise<void> {
|
||||||
@@ -44,16 +48,10 @@ class KadiStatsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAllRulesets(): Promise<RulesetSchemaDto[]> {
|
async getAllRulesets(): Promise<RulesetSchemaDto[]> {
|
||||||
return dummyRulesets as RulesetSchemaDto[];
|
if (!this.allRulesetsLoaded) {
|
||||||
if (this.allRulesetsLoaded) {
|
await this.loadAllRulesets();
|
||||||
return Object.values(this.rulesets);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const rulesetSchemas = (await axios.get(SERVER_BASE_NAME + "/api/rulesets/")).data as RulesetSchemaDto[];
|
|
||||||
rulesetSchemas.forEach(schema => this.rulesets[schema.id] = schema);
|
|
||||||
this.allRulesetsLoaded = true;
|
|
||||||
return rulesetSchemas;
|
|
||||||
}
|
}
|
||||||
|
return Object.values(this.rulesets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
src/Services/PlayerDto.ts
Normal file
6
src/Services/PlayerDto.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
interface PlayerMongoData {
|
||||||
|
id: string;
|
||||||
|
nick: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlayerDto;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import {FieldType} from "../enums";
|
||||||
|
|
||||||
export interface RulesetSchemaDto {
|
export interface RulesetSchemaDto {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export const IntlStrings = {
|
|||||||
blocksHeader: "Blocks",
|
blocksHeader: "Blocks",
|
||||||
fieldLabelHeader: "Label",
|
fieldLabelHeader: "Label",
|
||||||
fieldTypeHeader: "Type",
|
fieldTypeHeader: "Type",
|
||||||
fieldValueHeader: "Value",
|
fieldAttributesHeader: "Attributes",
|
||||||
superkadiField: "Superkadi",
|
superkadiField: "Superkadi",
|
||||||
multiplierField: "Multiplier Cell",
|
multiplierField: "Multiplier Cell",
|
||||||
boolField: "Boolean Cell",
|
boolField: "Boolean Cell",
|
||||||
@@ -84,9 +84,12 @@ export const IntlStrings = {
|
|||||||
cellNamePlaceholder: "My New Cell",
|
cellNamePlaceholder: "My New Cell",
|
||||||
fieldTypePlaceholder: "Select a field type",
|
fieldTypePlaceholder: "Select a field type",
|
||||||
multiplierPlaceholder: "Multiplier",
|
multiplierPlaceholder: "Multiplier",
|
||||||
maxMultiplesPlaceholder: "Max of kind",
|
maxMultiplesPlaceholder: "Max Multiples",
|
||||||
|
maxSuperkadisPlaceholder: "Max Superkadis",
|
||||||
valuePlaceholder: "Value",
|
valuePlaceholder: "Value",
|
||||||
submit: "Submit",
|
save: "Save",
|
||||||
|
extraCellSettingsInfo: "No attributes available",
|
||||||
|
newCell: "New Cell",
|
||||||
},
|
},
|
||||||
friendsPage: {
|
friendsPage: {
|
||||||
title: "Friends",
|
title: "Friends",
|
||||||
@@ -135,7 +138,7 @@ export const IntlStrings = {
|
|||||||
blocksHeader: "Blöcke",
|
blocksHeader: "Blöcke",
|
||||||
fieldLabelHeader: "Name",
|
fieldLabelHeader: "Name",
|
||||||
fieldTypeHeader: "Typ",
|
fieldTypeHeader: "Typ",
|
||||||
fieldValueHeader: "Wert",
|
fieldAttributesHeader: "Eigenschaften",
|
||||||
superkadiField: "Superkadi",
|
superkadiField: "Superkadi",
|
||||||
multiplierField: "Multiplikator-Feld",
|
multiplierField: "Multiplikator-Feld",
|
||||||
boolField: "Bool'sches Feld",
|
boolField: "Bool'sches Feld",
|
||||||
@@ -155,8 +158,11 @@ export const IntlStrings = {
|
|||||||
fieldTypePlaceholder: "Feldtyp auswählen",
|
fieldTypePlaceholder: "Feldtyp auswählen",
|
||||||
multiplierPlaceholder: "Multiplikator",
|
multiplierPlaceholder: "Multiplikator",
|
||||||
maxMultiplesPlaceholder: "Max. Anzahl",
|
maxMultiplesPlaceholder: "Max. Anzahl",
|
||||||
|
maxSuperkadisPlaceholder: "Max. Anzahl",
|
||||||
valuePlaceholder: "Wert",
|
valuePlaceholder: "Wert",
|
||||||
submit: "Fertig",
|
save: "Speichern",
|
||||||
|
extraCellSettingsInfo: "Keine Eigenschaften vorhanden",
|
||||||
|
newCell: "Neues Feld",
|
||||||
},
|
},
|
||||||
friendsPage: {
|
friendsPage: {
|
||||||
title: "Freunde",
|
title: "Freunde",
|
||||||
@@ -205,7 +211,7 @@ export const IntlStrings = {
|
|||||||
blocksHeader: "===TRANSLATE ME===",
|
blocksHeader: "===TRANSLATE ME===",
|
||||||
fieldLabelHeader: "===TRANSLATE ME===",
|
fieldLabelHeader: "===TRANSLATE ME===",
|
||||||
fieldTypeHeader: "===TRANSLATE ME===",
|
fieldTypeHeader: "===TRANSLATE ME===",
|
||||||
fieldValueHeader: "===TRANSLATE ME===",
|
fieldAttributesHeader: "===TRANSLATE ME===",
|
||||||
superkadiField: "===TRANSLATE ME===",
|
superkadiField: "===TRANSLATE ME===",
|
||||||
multiplierField: "===TRANSLATE ME===",
|
multiplierField: "===TRANSLATE ME===",
|
||||||
boolField: "===TRANSLATE ME===",
|
boolField: "===TRANSLATE ME===",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"defaultSeverity": "error",
|
"defaultSeverity": "error",
|
||||||
"extends": [
|
"extends": [
|
||||||
"tslint-react"
|
"tslint-react",
|
||||||
|
"tslint-config-prettier"
|
||||||
],
|
],
|
||||||
"jsRules": {
|
"jsRules": {
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user