Grabbed dndbeyond's source code
``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+6
@@ -0,0 +1,6 @@
|
||||
import * as React from "react";
|
||||
|
||||
import InfusionChoicePaneStore from "../InfusionChoicePaneStore";
|
||||
import withAvailableItems from "../withAvailableItems";
|
||||
|
||||
export default withAvailableItems(InfusionChoicePaneStore);
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import InfusionChoicePaneNewStore from "./InfusionChoicePaneNewStore";
|
||||
|
||||
export default InfusionChoicePaneNewStore;
|
||||
export { InfusionChoicePaneNewStore };
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import * as React from "react";
|
||||
|
||||
interface Props {
|
||||
header: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
}
|
||||
export class InfusionChoicePaneStep extends React.PureComponent<Props> {
|
||||
handleClick = (evt: React.MouseEvent): void => {
|
||||
const { onClick } = this.props;
|
||||
|
||||
if (onClick) {
|
||||
evt.stopPropagation();
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
|
||||
onClick();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { header, extra, children } = this.props;
|
||||
|
||||
return (
|
||||
<div className="ct-infusion-choice-pane__step" onClick={this.handleClick}>
|
||||
<div className="ct-infusion-choice-pane__step-primary">
|
||||
<div className="ct-infusion-choice-pane__step-header">{header}</div>
|
||||
<div className="ct-infusion-choice-pane__step-content">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
{extra && (
|
||||
<div className="ct-infusion-choice-pane__step-extra">{extra}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default InfusionChoicePaneStep;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import InfusionChoicePaneStep from "./InfusionChoicePaneStep";
|
||||
|
||||
export default InfusionChoicePaneStep;
|
||||
export { InfusionChoicePaneStep };
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
import { orderBy } from "lodash";
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleHeaderContent,
|
||||
LoadingPlaceholder,
|
||||
} from "@dndbeyond/character-components/es";
|
||||
import {
|
||||
CharacterTheme,
|
||||
InfusionChoice,
|
||||
InfusionChoiceUtils,
|
||||
InfusionUtils,
|
||||
Item,
|
||||
ItemUtils,
|
||||
KnownInfusionUtils,
|
||||
RuleData,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { ItemName } from "~/components/ItemName";
|
||||
|
||||
import ItemDetail from "../../../../components/ItemDetail";
|
||||
import { ThemeButton } from "../../../../components/common/Button";
|
||||
import DataLoadingStatusEnum from "../../../../constants/DataLoadingStatusEnum";
|
||||
|
||||
interface Props {
|
||||
itemLoadingStatus: DataLoadingStatusEnum;
|
||||
items: Array<Item>;
|
||||
itemCanBeAddedLookup: Record<number, boolean>;
|
||||
infusionChoice: InfusionChoice;
|
||||
onItemSelected: (item: Item) => void;
|
||||
ruleData: RuleData;
|
||||
proficiencyBonus: number;
|
||||
theme: CharacterTheme;
|
||||
}
|
||||
export class InfusionChoicePaneStore extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
items: [],
|
||||
itemLoadingStatus: DataLoadingStatusEnum.NOT_INITIALIZED,
|
||||
itemCanBeAddedLookup: {},
|
||||
};
|
||||
|
||||
renderLoading = (): React.ReactNode => {
|
||||
return <LoadingPlaceholder />;
|
||||
};
|
||||
|
||||
renderEmpty = (): React.ReactNode => {
|
||||
return (
|
||||
<div className="ct-infusion-choice-pane__inventory-empty">
|
||||
There are no items that match the requirements for infusion.
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
infusionChoice,
|
||||
itemCanBeAddedLookup,
|
||||
itemLoadingStatus,
|
||||
items,
|
||||
onItemSelected,
|
||||
ruleData,
|
||||
proficiencyBonus,
|
||||
theme,
|
||||
} = this.props;
|
||||
|
||||
if (
|
||||
itemLoadingStatus !== DataLoadingStatusEnum.NOT_INITIALIZED &&
|
||||
itemLoadingStatus !== DataLoadingStatusEnum.LOADED
|
||||
) {
|
||||
return this.renderLoading();
|
||||
}
|
||||
|
||||
const knownInfusion = InfusionChoiceUtils.getKnownInfusion(infusionChoice);
|
||||
if (knownInfusion === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const simulatedInfusion =
|
||||
KnownInfusionUtils.getSimulatedInfusion(knownInfusion);
|
||||
if (simulatedInfusion === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const availableItems = InfusionUtils.filterAvailableItems(
|
||||
items,
|
||||
simulatedInfusion,
|
||||
KnownInfusionUtils.getItemId(knownInfusion),
|
||||
itemCanBeAddedLookup
|
||||
);
|
||||
const orderedItems = orderBy(availableItems, (item) =>
|
||||
ItemUtils.getName(item)
|
||||
);
|
||||
|
||||
if (!orderedItems.length) {
|
||||
return this.renderEmpty();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ct-infusion-choice-pane__inventory">
|
||||
{orderedItems.map((item) => {
|
||||
let headerNode = (
|
||||
<CollapsibleHeaderContent
|
||||
heading={<ItemName item={item} showLegacy={true} />}
|
||||
callout={
|
||||
<ThemeButton
|
||||
onClick={onItemSelected.bind(this, item)}
|
||||
size="small"
|
||||
data-testid={`infusion-choose-item-button-${ItemUtils.getName(
|
||||
item
|
||||
)}`
|
||||
.toLowerCase()
|
||||
.replace(/\s/g, "-")}
|
||||
>
|
||||
Choose
|
||||
</ThemeButton>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Collapsible
|
||||
key={ItemUtils.getId(item)}
|
||||
layoutType="minimal"
|
||||
header={headerNode}
|
||||
className="ct-infusion-choice-pane__item"
|
||||
>
|
||||
<ItemDetail
|
||||
theme={theme}
|
||||
item={item}
|
||||
ruleData={ruleData}
|
||||
showCustomize={false}
|
||||
showActions={false}
|
||||
showImage={false}
|
||||
showAbilities={false}
|
||||
proficiencyBonus={proficiencyBonus}
|
||||
/>
|
||||
</Collapsible>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default InfusionChoicePaneStore;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import InfusionChoicePaneStore from "./InfusionChoicePaneStore";
|
||||
|
||||
export default InfusionChoicePaneStore;
|
||||
export { InfusionChoicePaneStore };
|
||||
@@ -0,0 +1,14 @@
|
||||
import InfusionChoicePane from "./InfusionChoicePane";
|
||||
import InfusionChoicePaneNewStore from "./InfusionChoicePaneNewStore";
|
||||
import InfusionChoicePaneStep from "./InfusionChoicePaneStep";
|
||||
import InfusionChoicePaneStore from "./InfusionChoicePaneStore";
|
||||
import withAvailableItems from "./withAvailableItems";
|
||||
|
||||
export default InfusionChoicePane;
|
||||
export {
|
||||
InfusionChoicePane,
|
||||
InfusionChoicePaneNewStore,
|
||||
InfusionChoicePaneStep,
|
||||
InfusionChoicePaneStore,
|
||||
withAvailableItems,
|
||||
};
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
import axios, { Canceler } from "axios";
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
CharacterTheme,
|
||||
ContainerManager,
|
||||
InfusionChoice,
|
||||
InventoryManager,
|
||||
Item,
|
||||
ItemUtils,
|
||||
RuleData,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import DataLoadingStatusEnum from "../../../../constants/DataLoadingStatusEnum";
|
||||
import { AppLoggerUtils } from "../../../../utils";
|
||||
|
||||
function getDisplayName(WrappedComponent: React.ComponentType) {
|
||||
return WrappedComponent.displayName || WrappedComponent.name || "Component";
|
||||
}
|
||||
|
||||
export interface RequiredWithAvailableItemsProps {
|
||||
inventoryManager: InventoryManager;
|
||||
theme?: CharacterTheme;
|
||||
infusionChoice: InfusionChoice;
|
||||
onItemSelected: (item: Item) => void;
|
||||
ruleData: RuleData;
|
||||
}
|
||||
interface State {
|
||||
loadingStatus: DataLoadingStatusEnum;
|
||||
availableItems: Array<Item>;
|
||||
}
|
||||
export function withAvailableItems<
|
||||
C extends React.ComponentType<React.ComponentProps<C>>,
|
||||
ResolvedProps = JSX.LibraryManagedAttributes<C, React.ComponentProps<C>>
|
||||
>(WrappedComponent) {
|
||||
return class withAvailableItems extends React.PureComponent<
|
||||
ResolvedProps & RequiredWithAvailableItemsProps,
|
||||
State
|
||||
> {
|
||||
static displayName = `withAvailableItems(${getDisplayName(
|
||||
WrappedComponent
|
||||
)})`;
|
||||
|
||||
loadAvailableItemsCanceler: null | Canceler = null;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loadingStatus: DataLoadingStatusEnum.NOT_LOADED,
|
||||
availableItems: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { loadingStatus } = this.state;
|
||||
const { inventoryManager } = this.props;
|
||||
|
||||
if (loadingStatus === DataLoadingStatusEnum.NOT_LOADED) {
|
||||
this.setState({
|
||||
loadingStatus: DataLoadingStatusEnum.LOADING,
|
||||
});
|
||||
|
||||
inventoryManager
|
||||
.getInventoryShoppe({
|
||||
onSuccess: (shoppeContainer: ContainerManager) => {
|
||||
const storeItems = shoppeContainer
|
||||
.getInventoryItems()
|
||||
.items.map((item) => item.getItem());
|
||||
|
||||
this.setState({
|
||||
availableItems: storeItems,
|
||||
loadingStatus: DataLoadingStatusEnum.LOADED,
|
||||
});
|
||||
},
|
||||
additionalApiConfig: {
|
||||
cancelToken: new axios.CancelToken((c) => {
|
||||
this.loadAvailableItemsCanceler = c;
|
||||
}),
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
this.loadAvailableItemsCanceler = null;
|
||||
return res;
|
||||
})
|
||||
.catch(AppLoggerUtils.handleAdhocApiError);
|
||||
} else {
|
||||
this.setState({
|
||||
loadingStatus: DataLoadingStatusEnum.LOADED,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
if (this.loadAvailableItemsCanceler !== null) {
|
||||
this.loadAvailableItemsCanceler();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loadingStatus, availableItems } = this.state;
|
||||
|
||||
let itemCanBeAddedLookup: Record<number, boolean> = availableItems.reduce(
|
||||
(acc, item) => {
|
||||
acc[ItemUtils.getId(item)] = ItemUtils.canBeAddedToInventory(item);
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
return (
|
||||
<WrappedComponent
|
||||
items={availableItems}
|
||||
itemCanBeAddedLookup={itemCanBeAddedLookup}
|
||||
itemLoadingStatus={loadingStatus}
|
||||
{...(this.props as JSX.LibraryManagedAttributes<
|
||||
C,
|
||||
React.ComponentProps<C>
|
||||
>)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default withAvailableItems;
|
||||
Reference in New Issue
Block a user