lodash#includes TypeScript Examples
The following examples show how to use
lodash#includes.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BOArea.tsx From sc2-planner with MIT License | 6 votes |
getClass(barType: IBarTypes, index: number): string {
const classes: string[] = []
if (index === this.props.hoverIndex) {
classes.push(`${CLASSES.boElementContainer} ${CLASSES.hoverColor[barType]}`)
} else {
classes.push(
`${CLASSES.boElementContainer} ${CLASSES.typeColor[barType]} hover:${CLASSES.hoverColor[barType]}`
)
}
if (includes(this.props.highlightedIndexes, index)) {
classes.push(CLASSES.boItemDim)
}
return classes.join(" ")
}
Example #2
Source File: ItemsTypeModify.tsx From yforms with MIT License | 6 votes |
checkboxGroupModify: YFormFieldBaseProps<YCheckGroupProps>['modifyProps'] = ({
itemProps,
componentProps,
}) => {
const { options } = componentProps;
return {
itemProps: {
viewProps: {
format: (value, pureValue) => {
if (value && isArray(value)) {
const list = [];
forEach(options, (item) => {
if (includes(value, item.id)) {
list.push(item.name);
}
});
if (pureValue) {
if (isArray(value)) {
return map(value, (item) => item).join('-');
}
return value;
}
return map(list, (item, index) => <Tag key={index}>{item}</Tag>);
}
},
},
...itemProps,
},
};
}
Example #3
Source File: sort-action.ts From S2 with MIT License | 6 votes |
getSortByMeasureValues = (
params: SortActionParams,
): DataType[] => {
const { dataSet, sortParam, originValues } = params;
const { fields } = dataSet;
const { sortByMeasure, query, sortFieldId } = sortParam;
if (sortByMeasure !== TOTAL_VALUE) {
// 按指标只排序 - 最内侧的行列不需要汇总后排序
return dataSet.getMultiData(query);
}
const isRow =
fields?.columns?.includes(sortFieldId) &&
keys(query)?.length === 1 &&
has(query, EXTRA_FIELD);
// 按 data 数据中的小计,总计排序
const measureValues = dataSet.getMultiData(query, true, isRow);
if (measureValues && !isEmpty(measureValues)) {
return measureValues;
}
// 按前端的小计,总计排序
return map(originValues, (originValue) => {
const totalParams = createTotalParams(originValue, fields, sortFieldId);
return (dataSet as PivotDataSet).getTotalValue({
...query,
...totalParams,
});
});
}
Example #4
Source File: brickTableHelper.ts From next-basics with GNU General Public License v3.0 | 6 votes |
compareFunMap: Record<string, any> = {
$eq: isEqual,
$lt: lt,
$lte: lte,
$gt: gt,
$gte: gte,
$ne: (value: any, fieldValue: any): boolean => !isEqual(value, fieldValue),
$isEqual: isEqual,
$notEqual: (value: any, fieldValue: any): boolean =>
!isEqual(value, fieldValue),
$in: includes,
$nin: (value: any, fieldValue: any): boolean => !includes(value, fieldValue),
$exists: (value: any, fieldValue: any): boolean =>
value ? !isUndefined(fieldValue) : isUndefined(fieldValue),
}
Example #5
Source File: table-data-set.ts From S2 with MIT License | 6 votes |
handleDimensionValueFilter = () => {
each(this.filterParams, ({ filterKey, filteredValues, customFilter }) => {
const defaultFilterFunc = (row: DataType) =>
row[filterKey] && !includes(filteredValues, row[filterKey]);
this.displayData = [
...this.getStartRows(),
...filter(this.getMovableRows(), (row) => {
if (customFilter) {
return customFilter(row) && defaultFilterFunc(row);
}
return defaultFilterFunc(row);
}),
...this.getEndRows(),
];
});
};
Example #6
Source File: trace-detail.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
findChildren = (_ispanId: any, children: any, spans: any) => {
const tree: any[] = [];
this.findChildren.bind(this);
each(spans, (i) => {
if (includes(children, i.spanId)) {
tree.push(i.spanId);
if (i.children) {
tree.push(this.findChildren(i.spanId, i.children, spans));
}
}
});
return tree;
};
Example #7
Source File: header-cell.ts From S2 with MIT License | 6 votes |
protected handleSelect(cells: CellMeta[], nodes: Node[]) {
if (includeCell(cells, this)) {
this.updateByState(InteractionStateName.SELECTED);
}
const selectedNodeIds = map(nodes, 'id');
if (includes(selectedNodeIds, this.meta.id)) {
this.updateByState(InteractionStateName.SELECTED);
}
}
Example #8
Source File: fy-select-modal.component.ts From fyle-mobile-app with MIT License | 6 votes |
getRecentlyUsedItems() {
// Check if recently items exists from api and set, else, set the recent items from the localStorage
if (this.recentlyUsed) {
return of(this.recentlyUsed);
} else {
return from(this.recentLocalStorageItemsService.get(this.cacheName)).pipe(
map((options: any) =>
options
.filter((option) => option.custom || this.options.map((op) => op.label).includes(option.label))
.map((option) => {
option.selected = isEqual(option.value, this.currentSelection);
return option;
})
)
);
}
}
Example #9
Source File: index.ts From vue3-ts-base with MIT License | 6 votes |
/**
* @description 自动加载 antd-vue 需要的语言模版
*/
function loadAtdLocales() {
const files = require.context('../../node_modules/ant-design-vue/es/locale-provider', true, /\.js$/)
files.keys().forEach(key => {
const fileName = key.slice(2, key.lastIndexOf('.'))
if (includes(TranslateTable, fileName)) {
const localeKey = findKeyByValue(TranslateTable, fileName)
if (localeKey) {
Locales[localeKey] = files(key).default
}
}
})
}
Example #10
Source File: properties-file.ts From relate with GNU General Public License v3.0 | 6 votes |
private setEntry(key: string, val: string | boolean): void {
const configEntries: PropertyEntries = [...this.config];
const entryIndex = findIndex(configEntries, (configEntry) => includes([`#${key}`, key], configEntry[0]));
if (entryIndex >= 0) {
const entry = configEntries[entryIndex];
if (includes(entry[0], '#')) {
entry[0] = key;
}
entry[1] = `${val}`;
this.config = configEntries;
return;
}
this.config = [...configEntries, [key, `${val}`]];
}
Example #11
Source File: documentation.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
export function getDeprecationPlainTextSnippet({
title,
deprecatedInfo,
model,
}: {
title?: string;
deprecatedInfo: UI5DeprecatedInfo;
model: UI5SemanticModel;
}): string {
let text = deprecatedInfo.text;
if (text !== undefined) {
text = convertJSDocToPlainText(text, model);
// Only take the first line.
// Multi-line problems are displayed open in the problem view which makes less problems visible unless the user
// explicitly closes them.
// For the full deprecation message the user can hover over the tag/attribute.
// Note: long lines are displayed with "..." in the problems view and the user can hover over the problem to see
// the full text.
if (includes(text, "\n")) {
text = text.substring(0, text.indexOf("\n")) + " ...";
}
}
const doc = getDeprecationMessage({
title,
since: deprecatedInfo.since,
text,
});
return doc;
}
Example #12
Source File: competition.service.ts From wise-old-man with MIT License | 6 votes |
/**
* Set the participants of a competition.
*
* This will replace any existing participants.
*/
async function setParticipants(competition: Competition, usernames: string[]) {
if (!competition) throw new BadRequestError(`Invalid competition.`);
const uniqueUsernames = uniqBy(usernames, u => playerService.standardize(u));
const existingParticipants = await competition.$get('participants');
const existingUsernames = existingParticipants.map(e => e.username);
const usernamesToAdd = uniqueUsernames.filter(
u => !existingUsernames.includes(playerService.standardize(u))
);
const playersToRemove = existingParticipants.filter(
p => !uniqueUsernames.map(playerService.standardize).includes(p.username)
);
const playersToAdd = await playerService.findAllOrCreate(usernamesToAdd);
if (playersToRemove && playersToRemove.length > 0) {
await competition.$remove('participants', playersToRemove);
}
if (playersToAdd && playersToAdd.length > 0) {
await competition.$add('participants', playersToAdd);
}
const participants = await competition.$get('participants');
return participants.map(p => omit(p.toJSON(), ['participations']));
}
Example #13
Source File: non-stable-id.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
function isAllowedListedTag(xmlElement: XMLElement): boolean {
const rootAllowedListedExceptions: Record<string, string[]> = {
"sap.ui.core.mvc": ["View"],
"sap.ui.core": ["View", "FragmentDefinition"],
};
// The class is in the root level
if (xmlElement.parent.type === "XMLDocument") {
const resolvedXMLNS = resolveXMLNS(xmlElement);
const exceptionsForResolvedXMLNS =
// @ts-expect-error - it's fine to use undefined in member access
rootAllowedListedExceptions[resolvedXMLNS];
if (includes(exceptionsForResolvedXMLNS, xmlElement.name)) {
return true;
}
}
const coreNsAllowedListedExceptions = [
"Fragment",
"CustomData",
"ExtensionPoint",
];
const isCoreNsAllowedListed =
resolveXMLNS(xmlElement) === CORE_NS &&
includes(coreNsAllowedListedExceptions, xmlElement.name);
return isCoreNsAllowedListed;
}
Example #14
Source File: competition.service.ts From wise-old-man with MIT License | 6 votes |
function validateParticipantsList(participants: string[]) {
if (!participants || participants.length === 0) {
throw new BadRequestError('Invalid or empty participants list.');
}
const invalidUsernames = participants.filter(username => !playerService.isValidUsername(username));
if (invalidUsernames.length > 0) {
throw new BadRequestError(
`Found ${invalidUsernames.length} invalid usernames: Names must be 1-12 characters long,
contain no special characters, and/or contain no space at the beginning or end of the name.`,
invalidUsernames
);
}
const allUsernames = participants.map(playerService.standardize);
const duplicateUsernames = filter(allUsernames, (val, i, it) => includes(it, val, i + 1));
if (duplicateUsernames && duplicateUsernames.length > 0) {
throw new BadRequestError(`Found repeated usernames: [${duplicateUsernames.join(', ')}]`);
}
}
Example #15
Source File: api.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
export function getXMLViewCompletions(
opts: GetXMLViewCompletionsOpts
): UI5XMLViewCompletion[] {
const suggestions = getSuggestions({
offset: opts.offset,
cst: opts.cst,
ast: opts.ast,
tokenVector: opts.tokenVector,
context: opts.model,
providers: {
elementContent: [],
elementName: elementNameProviders,
attributeName: attributeNameProviders,
attributeValue: attributeValueProviders,
},
});
const allowedVisibility: UI5Visibility[] = ["public", "protected"];
const publicAndProtectedSuggestions = filter(
suggestions,
(_) =>
!isUI5NodeXMLViewCompletion(_) ||
includes(allowedVisibility, _.ui5Node.visibility)
);
const filteredSuggestions = filterBySettings(
publicAndProtectedSuggestions,
opts.settings
);
return filteredSuggestions;
}
Example #16
Source File: competition.service.ts From wise-old-man with MIT License | 5 votes |
function validateTeamsList(teams: Team[]) {
if (!teams || teams.length === 0) {
throw new BadRequestError('Invalid or empty teams list.');
}
if (teams.some(t => !t.name || typeof t.name !== 'string' || t.name.length === 0)) {
throw new BadRequestError('All teams must have a name property.');
}
// Sanitize each team's name
teams.forEach(t => {
t.name = sanitizeTitle(t.name);
});
// Find duplicate team names
const teamNames = teams.map(t => t.name.toLowerCase());
const invalidTeams = teamNames.filter(t => t.length > 30);
if (invalidTeams.length > 0) {
throw new BadRequestError(
`Team names can only be 30 characters max. The following are invalid: [${invalidTeams.join(', ')}]`
);
}
const duplicateTeams = filter(teamNames, (val, i, it) => includes(it, val, i + 1));
if (duplicateTeams && duplicateTeams.length > 0) {
throw new BadRequestError(`Found repeated team names: [${duplicateTeams.join(', ')}]`);
}
if (teams.some(t => !t.participants || t.participants.length === 0)) {
throw new BadRequestError('All teams must have a valid (non-empty) array of participants.');
}
// standardize each player's username
teams.forEach(t => {
t.participants = t.participants.map(playerService.standardize);
});
const allUsernames = teams.map(t => t.participants).flat();
if (allUsernames.some(username => !username || typeof username !== 'string')) {
throw new BadRequestError('All participant names must be valid strings.');
}
// Find duplicate usernames across all teams
const duplicateUsernames = filter(allUsernames, (val, i, it) => includes(it, val, i + 1));
if (duplicateUsernames && duplicateUsernames.length > 0) {
throw new BadRequestError(`Found repeated usernames: [${duplicateUsernames.join(', ')}]`);
}
validateParticipantsList(allUsernames);
}
Example #17
Source File: GetStatistics.ts From next-basics with GNU General Public License v3.0 | 5 votes |
ifCommon = (item: string, commonList: string[]) => {
return (
includes(commonList, item) ||
startsWith(item, "providers-of") ||
!item.includes(".")
);
}
Example #18
Source File: competition.service.ts From wise-old-man with MIT License | 5 votes |
/**
* Returns a list of all competitions that
* match the query parameters (title, status, metric).
*/
async function getList(filter: CompetitionListFilter, pagination: Pagination) {
const { title, status, metric, type } = filter;
// The status is optional, however if present, should be valid
if (status && !COMPETITION_STATUSES.includes(status.toLowerCase() as CompetitionStatus)) {
throw new BadRequestError(`Invalid status.`);
}
// The metric is optional, however if present, should be valid
if (metric && !METRICS.includes(metric.toLowerCase() as Metric)) {
throw new BadRequestError(`Invalid metric.`);
}
// The type is optional, however if present, should be valid
if (type && !COMPETITION_TYPES.includes(type.toLowerCase() as CompetitionType)) {
throw new BadRequestError(`Invalid type.`);
}
const query = buildQuery({
title: title && { [Op.iLike]: `%${sanitizeTitle(title)}%` },
metric: metric?.toLowerCase(),
type: type?.toLowerCase()
});
if (status) {
const formattedStatus = status.toLowerCase();
const now = new Date();
if (formattedStatus === CompetitionStatus.FINISHED) {
query.endsAt = { [Op.lt]: now };
} else if (formattedStatus === CompetitionStatus.UPCOMING) {
query.startsAt = { [Op.gt]: now };
} else if (formattedStatus === CompetitionStatus.ONGOING) {
query.startsAt = { [Op.lt]: now };
query.endsAt = { [Op.gt]: now };
}
}
const competitions = await Competition.findAll({
where: query,
order: [
['score', 'DESC'],
['createdAt', 'DESC']
],
limit: pagination.limit,
offset: pagination.offset
});
const extendedCompetitions = await extendCompetitions(competitions);
return extendedCompetitions;
}
Example #19
Source File: pure-edit-list.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
getDuplicateValue = (arr: string[]) =>
filter(arr, (value, index, iteratee) => includes(iteratee, value, index + 1))
Example #20
Source File: str.monad.ts From relate with GNU General Public License v3.0 | 5 votes |
includes(other: string | Str): boolean {
return includes(`${this}`, `${other}`);
}
Example #21
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
getCaseCheckedStatus = (id: any, { isAll, exclude, primaryKeys }: TEST_CASE.ChoosenInfo) => {
if (!isAll) {
// 未全选时
return includes(primaryKeys, id);
}
return !includes(exclude, id);
}
Example #22
Source File: fy-select-modal.component.ts From fyle-mobile-app with MIT License | 5 votes |
ngAfterViewInit() {
if (this.searchBarRef && this.searchBarRef.nativeElement) {
this.filteredOptions$ = fromEvent(this.searchBarRef.nativeElement, 'keyup').pipe(
map((event: any) => event.srcElement.value),
startWith(''),
distinctUntilChanged(),
map((searchText) => {
const initial = [];
if (this.nullOption && this.currentSelection) {
initial.push({ label: 'None', value: null });
}
if (this.customInput) {
initial.push({ label: searchText, value: searchText, selected: false });
}
let extraOption = [];
if (this.currentSelection && this.defaultLabelProp) {
const selectedOption = this.options.find((option) => isEqual(option.value, this.currentSelection));
if (!selectedOption) {
extraOption = extraOption.concat({
label: this.currentSelection[this.defaultLabelProp],
value: this.currentSelection,
selected: false,
});
}
}
return initial.concat(
this.options
.concat(extraOption)
.filter((option) => option.label.toLowerCase().includes(searchText.toLowerCase()))
.sort((element1, element2) => element1.label.localeCompare(element2.label))
.map((option) => {
option.selected = isEqual(option.value, this.currentSelection);
return option;
})
);
})
);
this.recentrecentlyUsedItems$ = fromEvent(this.searchBarRef.nativeElement, 'keyup').pipe(
map((event: any) => event.srcElement.value),
startWith(''),
distinctUntilChanged(),
switchMap((searchText) =>
this.getRecentlyUsedItems().pipe(
// filtering of recently used items wrt searchText is taken care in service method
this.utilityService.searchArrayStream(searchText)
)
)
);
} else {
const initial = [];
if (this.nullOption && this.currentSelection) {
initial.push({ label: 'None', value: null });
}
this.filteredOptions$ = of(
initial.concat(
this.options.map((option) => {
option.selected = isEqual(option.value, this.currentSelection);
return option;
})
)
);
}
this.cdr.detectChanges();
}
Example #23
Source File: related-content.tsx From nyxo-website with MIT License | 5 votes |
getArticles() {
const { category, tags, articles, maxArticles } = this
// (5.) We use an Identity Map to keep track of score
interface Identity {
[index: string]: {
article: BlogPostNode
points: number
}
}
const identityMap: Identity = {}
if (!!tags && tags.length === 0) {
console.error("SimilarArticlesFactory: Tags not provided, use setTags().")
return []
}
// if (!!category === false) {
// console.error(
// "SimilarArticlesFactory: Category not provided, use setCategory()."
// )
// return []
// }
function getSlug(article: BlogPostNode) {
return article.frontmatter.slug as string
}
function addToMap(article: BlogPostNode) {
const slug = getSlug(article)
const exists = Object.prototype.hasOwnProperty.call(identityMap, slug)
if (!exists) {
identityMap[slug] = {
article: article,
points: 0,
}
}
}
// (7.) For category matches, we add 2 points
function addCategoryPoints(article: BlogPostNode, category: string) {
// const categoryPoints = 2
// const slug = getSlug(article)
// if (article.category === category) {
// identityMap[slug].points += categoryPoints
// }
}
// (8.) For tags matches, we add 1 point
function addTagsPoints(article: BlogPostNode, tags?: string[] | null[]) {
const tagPoint = 1
const slug = getSlug(article)
article?.frontmatter?.tags?.forEach((aTag) => {
if (includes(tags, aTag)) {
identityMap[slug].points += tagPoint
}
})
}
function getIdentityMapAsArray() {
return Object.keys(identityMap).map((slug) => identityMap[slug])
}
// (6.) Map over all articles, add to map and add points
articles.forEach((article) => {
addToMap(article)
// addCategoryPoints(article, category) // We don't (yet) have categories
addTagsPoints(article, tags)
})
// (9.) Convert the identity map to an array
const arrayIdentityMap = getIdentityMapAsArray()
// (10.) Use a lodash utility function to sort them
// by points, from greatest to least
const similarArticles = orderBy(arrayIdentityMap, ["points"], ["desc"])
// (11. Take the max number articles requested)
return similarArticles.splice(0, maxArticles)
}
Example #24
Source File: namespace.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
/**
* Suggests Namespaces inside Element
* For example xmlns:m should provide list of namespaces ending with .m.. (like "sap.m", "sap.ui.core.mvc")
* attribute is namespace attribute if it's equal to "xmlns" or starts with "xmlns:"
* in first case all possible namespaces of semantic module will be provided excluding pre-existing ones
*/
export function namespaceKeysSuggestions(
opts: UI5AttributeNameCompletionOptions
): UI5NamespacesInXMLAttributeKeyCompletion[] {
const ui5Model = opts.context;
const xmlElement = opts.element;
if (opts.prefix === undefined) {
return [];
}
const xmlnsPrefix = getXMLNamespaceKeyPrefix(opts.prefix);
if (xmlnsPrefix === undefined) {
return [];
}
const existingNamespacesAttributes: XMLAttribute[] = filter(
xmlElement.attributes,
isExistingNamespaceAttribute
);
const existingNamespacesNames = compact(
map(existingNamespacesAttributes, (_) => _.value)
);
const applicableNamespaces = filter(ui5Model.namespaces, (_) =>
isNamespaceApplicable(_, xmlnsPrefix)
);
const suggestedNamespaces = reject(applicableNamespaces, (_) =>
includes(existingNamespacesNames, ui5NodeToFQN(_))
);
return map(suggestedNamespaces, (_) => ({
type: "UI5NamespacesInXMLAttributeKey",
ui5Node: _,
astNode: opts.attribute as XMLAttribute,
}));
}
Example #25
Source File: base-cell.ts From S2 with MIT License | 5 votes |
// 根据当前state来更新cell的样式
public updateByState(stateName: InteractionStateName, cell: S2CellType) {
this.spreadsheet.interaction.setInteractedCells(cell);
const stateStyles = get(
this.theme,
`${this.cellType}.cell.interactionState.${stateName}`,
);
const { x, y, height, width } = this.getCellArea();
each(stateStyles, (style, styleKey) => {
const targetShapeNames = keys(
pickBy(SHAPE_ATTRS_MAP, (attrs) => includes(attrs, styleKey)),
);
targetShapeNames.forEach((shapeName: StateShapeLayer) => {
const isStateShape = this.stateShapes.has(shapeName);
const shape = isStateShape
? this.stateShapes.get(shapeName)
: this[shapeName];
// stateShape 默认 visible 为 false
if (isStateShape && !shape.get('visible')) {
shape.set('visible', true);
}
// 根据borderWidth更新borderShape大小 https://github.com/antvis/S2/pull/705
if (
shapeName === 'interactiveBorderShape' &&
styleKey === 'borderWidth'
) {
if (isNumber(style)) {
const marginStyle = {
x: x + style / 2,
y: y + style / 2,
width: width - style - 1,
height: height - style - 1,
};
each(marginStyle, (currentStyle, currentStyleKey) => {
updateShapeAttr(shape, currentStyleKey, currentStyle);
});
}
}
updateShapeAttr(shape, SHAPE_STYLE_MAP[styleKey], style);
});
});
}
Example #26
Source File: filter-members.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
export function filterMembersByNames<T extends WithName>(
members: T[],
preExistingNames: string[]
): T[] {
return reject(members, (_) => includes(preExistingNames, _.name));
}
Example #27
Source File: header-cell.ts From S2 with MIT License | 5 votes |
public isMeasureField() {
return [EXTRA_FIELD, EXTRA_COLUMN_FIELD].includes(this.meta.field);
}
Example #28
Source File: search.ts From dyngoose with ISC License | 5 votes |
private checkFilters(hash: Attribute<any>, range?: Attribute<any>): boolean {
// cannot filter by a key without a value for the hash key
for (const filters of this.filters) {
if (!has(filters, hash.name)) {
continue
}
const hashFilter: Filter<any> = get(filters, hash.name)
// if there is an operator, ensure it is allowed as a key expression
if (isArray(hashFilter)) {
const operator = hashFilter[0]
if (!includes(keyConditionAllowedOperators, operator)) {
continue
}
}
// if it has no range, then we're all done
if (range == null) {
return true
}
// check for the range now
if (!has(filters, range.name)) {
continue
}
const rangeFilter: Filter<any> = get(filters, range.name)
// if there is an operator, ensure it is allowed as a key expression
if (isArray(rangeFilter)) {
const operator = rangeFilter[0]
if (!includes(keyConditionAllowedOperators, operator)) {
continue
}
}
return true
}
return false
}
Example #29
Source File: BuildOrder.tsx From sc2-planner with MIT License | 4 votes |
render(): JSX.Element {
// Convert build order items to div elements
// Hide element if no build order items are present
if (this.props.gamelogic.bo.length === 0) {
return <div />
}
const buildOrder = this.props.gamelogic.bo.map((item, index) => {
const image = getImageOfItem(item)
return <img key={`${item.name}_${index}`} src={image} alt={item.name} />
})
const getItemClass = (dragging: boolean, index: number) => {
// Build order is invalid after this index, mark background or border red
// Set color based on if it is dragging
const classes: string[] = []
if (dragging) {
if (index >= this.props.gamelogic.boIndex) {
classes.push(CLASSES.boItemInvalidDragging)
} else {
classes.push(CLASSES.boItemDragging)
}
} else if (index === this.props.hoverIndex) {
classes.push(CLASSES.boItemHighlighting)
} else {
if (index >= this.props.gamelogic.boIndex) {
classes.push(CLASSES.boItemInvalid)
}
classes.push(CLASSES.boItem)
}
if (includes(this.props.highlightedIndexes, index)) {
classes.push(CLASSES.boItemDim)
}
return classes.join(" ")
}
const buildOrderItems: JSX.Element[] = []
let separatorClass =
this.props.insertIndex === 0 ? CLASSES.boItemSeparatorSelected : CLASSES.boItemSeparator
buildOrderItems.push(
<div
id={"separator_0"}
key={"separator0"}
className={separatorClass}
onClick={(_e) => {
this.props.changeInsertIndex(0)
}}
/>
)
this.props.gamelogic.bo.forEach((item, index) => {
buildOrderItems.push(
<Draggable key={`${index}`} draggableId={`${index}`} index={index}>
{(provided, snapshot) => (
<div
id={`bo_${item.name}_${index}`}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={getItemClass(snapshot.isDragging, index)}
onMouseEnter={(_e) => this.onMouseEnter(index)}
onMouseLeave={(_e) => this.onMouseLeave()}
onClick={(e) => {
this.props.removeClick(e, index)
}}
>
{buildOrder[index]}
</div>
)}
</Draggable>
)
separatorClass =
this.props.insertIndex === index + 1
? CLASSES.boItemSeparatorSelected
: CLASSES.boItemSeparator
buildOrderItems.push(
<div
id={`separator_${index + 1}`}
key={`separator${index + 1}`}
className={separatorClass}
onClick={(_e) => {
this.props.changeInsertIndex(index + 1)
}}
/>
)
})
return (
<div id={"buildorder"} className={CLASSES.bo}>
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable" direction="horizontal">
{(provided, _snapshot) => (
<div
className={
(this.props.multilineBuildOrder ? "flex-wrap flex-row" : "") +
" flex"
}
ref={provided.innerRef}
{...provided.droppableProps}
>
{buildOrderItems}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
)
}