lodash#differenceBy TypeScript Examples
The following examples show how to use
lodash#differenceBy.
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: assetsDbService.ts From nautilus-wallet with MIT License | 6 votes |
public async sync(assets: IDbAsset[], walletId: number): Promise<void> {
const groups = groupBy(assets, (a) => a.address);
const dbGroups = groupBy(await this.getByWalletId(walletId), (a) => a.address);
const groupKeys = union(keys(dbGroups), keys(groups));
for (const key of groupKeys) {
const group = groups[key];
const dbGroup = dbGroups[key];
if (isEmpty(dbGroup) && isEmpty(groups)) {
continue;
} else if (isEmpty(group) && !isEmpty(dbGroup)) {
await dbContext.assets.bulkDelete(this.primaryKeysFrom(dbGroup));
continue;
} else if (isEmpty(dbGroup)) {
await dbContext.assets.bulkPut(group);
continue;
}
const remove = this.primaryKeysFrom(differenceBy(dbGroup, group, (a) => a.tokenId));
const put = this.newOrChanged(dbGroup, group);
if (remove.length > 0) {
await dbContext.assets.bulkDelete(remove);
}
if (put.length > 0) {
await dbContext.assets.bulkPut(put);
}
}
}
Example #2
Source File: CompareView.tsx From hub with Apache License 2.0 | 4 votes |
CompareView = (props: Props) => {
const [diffTemplates, setDiffTemplates] = useState<ChartTemplate[] | null | undefined>();
const [activeTemplate, setActiveTemplate] = useState<CompareChartTemplate | null>(null);
const [isChangingTemplate, setIsChangingTemplate] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [visibleTemplates, setVisibleTemplates] = useState<CompareChartTemplate[] | undefined>();
const [expanded, setExpanded] = useState<boolean>(false);
const onTemplateChange = (template: CompareChartTemplate | null) => {
setIsChangingTemplate(true);
setExpanded(false);
setActiveTemplate(template);
props.updateUrl({ template: template ? template.name : undefined, compareTo: props.comparedVersion });
};
useEffect(() => {
async function getDiffCompareChartTemplates(version: string) {
try {
setIsChangingTemplate(true);
setIsLoading(true);
const data = await API.getChartTemplates(props.packageId, version);
if (data && data.templates) {
const formattedTemplates: ChartTemplate[] = props.formatTemplates(data.templates);
if (formattedTemplates.length > 0) {
setDiffTemplates(formattedTemplates);
} else {
setDiffTemplates([]);
}
}
} catch {
setDiffTemplates(null);
setIsChangingTemplate(false);
} finally {
setIsLoading(false);
}
}
if (props.comparedVersion !== '') {
getDiffCompareChartTemplates(props.comparedVersion);
} else {
setDiffTemplates([]);
}
}, [props.comparedVersion]); /* eslint-disable-line react-hooks/exhaustive-deps */
useEffect(() => {
const prepareVisibleTemplates = () => {
let tmpls: CompareChartTemplate[] = [];
props.templates!.forEach((tmpl: ChartTemplate) => {
const diffTmpl = diffTemplates!.find((t: ChartTemplate) => t.name === tmpl.name);
if (diffTmpl) {
if (diffTmpl.data !== tmpl.data) {
tmpls.push({ ...tmpl, compareData: diffTmpl.data, status: CompareChartTemplateStatus.Modified });
}
} else {
tmpls.push({
...tmpl,
compareData: '',
status: CompareChartTemplateStatus.Added,
});
}
});
const others = differenceBy(diffTemplates!, props.templates!, 'name');
others.forEach((tmpl: ChartTemplate) => {
tmpls.push({
...tmpl,
data: '',
compareData: tmpl.data,
status: CompareChartTemplateStatus.Deleted,
});
});
const sortedTmpls: CompareChartTemplate[] = sortBy(tmpls, ['type', 'name']);
setVisibleTemplates(sortedTmpls);
if (sortedTmpls.length === 0) {
setActiveTemplate(null);
} else {
if (props.visibleTemplate) {
const selectedTmpl = sortedTmpls.find((tmpl: CompareChartTemplate) => props.visibleTemplate === tmpl.name);
if (selectedTmpl) {
setActiveTemplate(selectedTmpl);
} else {
setActiveTemplate(sortedTmpls[0]);
}
} else {
setActiveTemplate(sortedTmpls[0]);
}
}
};
if (diffTemplates && !isNull(props.templates)) {
prepareVisibleTemplates();
setIsChangingTemplate(false);
}
}, [diffTemplates]); /* eslint-disable-line react-hooks/exhaustive-deps */
return (
<div className="d-flex flex-row align-items-stretch g-0 h-100 mh-100">
<div className="col-3 h-100">
<CompareTemplatesList
templates={visibleTemplates}
activeTemplateName={activeTemplate ? activeTemplate.name : undefined}
onTemplateChange={onTemplateChange}
/>
</div>
<div className="col-9 ps-3 h-100">
<div className={`position-relative h-100 mh-100 border ${styles.templateWrapper}`}>
{((isChangingTemplate && activeTemplate) || isLoading) && <Loading />}
<div className={`position-absolute d-flex ${styles.wrapper}`}>
<div className="position-relative">
<button
className={`btn btn-sm btn-primary rounded-circle fs-5 ${styles.btn}`}
onClick={() => {
setExpanded(!expanded);
}}
aria-label={`${expanded ? 'Collapse' : 'Expand'} code`}
disabled={!isUndefined(visibleTemplates) && visibleTemplates.length === 0}
>
{expanded ? <BsArrowsCollapse /> : <BsArrowsExpand />}
</button>
</div>
</div>
<pre className={`text-muted h-100 mh-100 mb-0 overflow-hidden position-relative diffTemplate ${styles.pre}`}>
{!isUndefined(visibleTemplates) && visibleTemplates.length === 0 && (
<div className="d-flex align-items-center justify-content-center h-100 w-100 p-5">
<div className={`alert alert-dark px-5 py-4 text-center ${styles.alert}`}>
<span className="text-muted">
No changes found when comparing version <span className="fw-bold">{props.currentVersion}</span> to{' '}
<span className="fw-bold">{props.comparedVersion}</span>
</span>
</div>
</div>
)}
{activeTemplate && (
<ErrorBoundary className={styles.errorAlert} message="Something went wrong rendering the template.">
<DiffTemplate
currentVersion={props.currentVersion}
diffVersion={props.comparedVersion}
template={activeTemplate!}
expanded={expanded}
setIsChangingTemplate={setIsChangingTemplate}
/>
</ErrorBoundary>
)}
</pre>
</div>
</div>
</div>
);
}
Example #3
Source File: BrickTag.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function BrickTag(props: BrickTagProps): React.ReactElement {
const {
componentType,
tagList,
configProps,
defaultCheckedTag,
showTagCircle,
color,
closable,
cancelable,
tooltipProps,
} = props;
const [checkedTag, setCheckedTag] = useState([]);
const [closedTag, setClosedTag] = useState(tagList);
useEffect(() => {
setCheckedTag(
defaultCheckedTag
? isArray(defaultCheckedTag)
? defaultCheckedTag
: [defaultCheckedTag]
: []
);
}, [defaultCheckedTag]);
const [hoverTag, setHoverTag] = useState(null);
const onChange = (item, checked) => {
const key = item.key;
let nextCheckedTag: string[];
if (props.multipleCheck) {
nextCheckedTag = checked
? [...checkedTag, key]
: checkedTag.filter((t) => t !== key);
} else {
if (!cancelable && !checked) {
return;
}
nextCheckedTag = checked ? [key] : [];
}
const nextCheckedItems = tagList?.filter((item) =>
nextCheckedTag?.includes(item.key)
);
props.handleOnChange(nextCheckedItems);
};
const onClose = (item) => {
const newClosedTag = differenceBy(closedTag, [item], "key");
setClosedTag(newClosedTag);
props?.handleOnClose(item, newClosedTag);
};
const onClick = (item) => {
props?.handleOnClick(item);
};
const onMouseEnter = (item, e) => {
setHoverTag(item.key);
};
const onMouseLeave = (item, e) => {
setHoverTag(null);
};
const renderTag = (TypeComponent: any, tagList: TagListType[]) =>
tagList.map((item) => {
const {
key,
label,
tooltip,
icon,
color: itemColor,
disabled,
disabledTooltip,
} = item;
let restProps: any = {};
const hover = hoverTag === key;
if (TypeComponent === Tag) {
restProps = {
style: {
...props.tagStyle,
...(hover ? props.tagHoverStyle : {}),
},
onClick: () => {
onClick(item);
},
};
} else {
const checked = checkedTag.includes(key);
restProps = {
style: {
...props.tagStyle,
...(checked ? props.tagCheckedStyle : {}),
...(hover ? props.tagHoverStyle : {}),
},
checked,
onChange: (c) => onChange(item, c),
};
}
const specificColor = itemColor || color;
const tagNode = (
<TypeComponent
key={key}
className={classNames({
[style.grayTag]: specificColor === "gray" || disabled,
[style.grayInverseTag]: specificColor === "gray-inverse",
[style.round]: props.shape === "round",
[style.closableTag]: closable && TypeComponent === Tag,
[style.tagCircleIcon]: showTagCircle,
[style.colorTag]:
specificColor && !closable && TypeComponent === Tag,
[style.disabledTag]: disabled,
})}
closable={closable}
{...(closable ? { onClose: () => onClose(item) } : {})}
color={!closable && specificColor}
{...configProps}
{...restProps}
onMouseEnter={(e) => onMouseEnter(item, e)}
onMouseLeave={(e) => onMouseLeave(item, e)}
>
{!showTagCircle &&
icon &&
(typeof icon === "string" ? (
<LegacyIcon
type={icon}
style={{ marginRight: "7px", marginLeft: 0 }}
/>
) : (
typeof icon === "object" && (
<GeneralIcon
icon={icon}
style={{ marginRight: "7px", marginLeft: 0 }}
/>
)
))}
{showTagCircle && (
<GeneralIcon
icon={circleIcon}
style={{ marginRight: "7px", marginLeft: 0 }}
/>
)}
{label}
</TypeComponent>
);
return tooltip ||
(disabled && (props.disabledTooltip || disabledTooltip)) ? (
<Tooltip
key={key}
title={disabled ? disabledTooltip || props.disabledTooltip : tooltip}
{...tooltipProps}
>
{tagNode}
</Tooltip>
) : (
tagNode
);
});
return (
<div
className={classNames(style.brickTag, {
[style.tagTextOverflow]: props.textEllipsis,
})}
>
{props.label && <span className={style.tagsLabel}>{props.label}</span>}
{componentType === TagTypeProps.CheckableTag
? renderTag(Tag.CheckableTag, tagList)
: renderTag(Tag, tagList)}
</div>
);
}
Example #4
Source File: TicketAssignments.tsx From condo with MIT License | 4 votes |
TicketAssignments = ({
validations,
organizationId,
propertyId,
disableUserInteraction,
autoAssign,
categoryClassifier,
form,
}: TicketAssignmentsProps) => {
const intl = useIntl()
const TicketAssignmentTitle = intl.formatMessage({ id: 'TicketAssignment' })
const ExecutorLabel = intl.formatMessage({ id: 'field.Executor' })
const ResponsibleLabel = intl.formatMessage({ id: 'field.Responsible' })
const ExecutorExtra = intl.formatMessage({ id: 'field.Executor.description' })
const ResponsibleExtra = intl.formatMessage({ id: 'field.Responsible.description' })
const ExecutorsOnThisDivisionLabel = intl.formatMessage({ id: 'ticket.assignments.executor.OnThisDivision' })
const ExecutorsOnOtherDivisionsLabel = intl.formatMessage({ id: 'ticket.assignments.executor.OnOtherDivisions' })
const OtherExecutors = intl.formatMessage({ id: 'ticket.assignments.executor.Other' })
const { isSmall } = useLayoutContext()
const [divisions, setDivisions] = useState([])
const formatUserFieldLabel = ({ text, value, data: employee }) => {
if (!employee) {
return null
}
const matchedSpecialization = find(employee.specializations, { id: categoryClassifier })
return (
<UserNameField user={{ name: text, id: value }}>
{({ name, postfix }) => (
<>
<Typography.Text>
{name} {postfix}
</Typography.Text>
{matchedSpecialization && (
<Typography.Text type="secondary">
{`(${matchedSpecialization.name.toLowerCase()})`}
</Typography.Text>
)}
</>
)}
</UserNameField>
)
}
const getTechniciansFrom = (division) => (
division.executors.filter(({ specializations }) => (
specializations.some(({ id }) => id === categoryClassifier)
))
)
const convertToOption = (employee) => ({
text: employee.name,
value: employee.user.id,
data: employee,
})
/**
* Employees are grouped by following rules:
* 1. Technicians with matched specialization, belonging to matched division;
* 2. Technicians with matched specialization, belonging to other matched divisions;
* 3. Rest of employees.
*/
const renderOptionGroups = (employeeOptions, renderOption) => {
const [currentDivision, ...otherDivisions] = divisions
let techniciansOnDivisionOptions = []
let techniciansOnOtherDivisionsOptions = []
if (currentDivision) {
const techniciansOnDivision = getTechniciansFrom(currentDivision)
techniciansOnDivisionOptions = techniciansOnDivision.map(convertToOption)
const techniciansOnOtherDivisions =
differenceBy(
uniqBy(
otherDivisions.reduce((acc, otherDivision) => ([
...acc,
...getTechniciansFrom(otherDivision),
]), []),
'id',
),
techniciansOnDivision,
'id',
)
techniciansOnOtherDivisionsOptions = techniciansOnOtherDivisions.map(convertToOption)
}
const otherTechniciansOptions = differenceBy(employeeOptions, [
...techniciansOnDivisionOptions,
...techniciansOnOtherDivisionsOptions,
], 'value')
const result = []
if (!currentDivision || techniciansOnDivisionOptions.length === 0 && techniciansOnOtherDivisionsOptions.length === 0) {
result.push(otherTechniciansOptions.map(renderOption))
} else {
if (techniciansOnDivisionOptions.length > 0) {
result.push(
<Select.OptGroup label={ExecutorsOnThisDivisionLabel}>
{techniciansOnDivisionOptions.map(renderOption)}
</Select.OptGroup>
)
}
if (techniciansOnOtherDivisionsOptions.length > 0) {
result.push(
<Select.OptGroup label={ExecutorsOnOtherDivisionsLabel}>
{techniciansOnOtherDivisionsOptions.map(renderOption)}
</Select.OptGroup>
)
}
if (otherTechniciansOptions.length > 0) {
result.push(
<Select.OptGroup label={OtherExecutors}>
{otherTechniciansOptions.map(renderOption)}
</Select.OptGroup>
)
}
}
return result
}
return (
<Col span={24}>
<Row gutter={[0, 8]}>
<Col span={24}>
<Typography.Title level={3}>{TicketAssignmentTitle}</Typography.Title>
</Col>
<Col span={isSmall ? 24 : 18}>
<Row justify={'space-between'}>
{autoAssign && propertyId && (
<Col span={24}>
<AutoAssignerByDivisions
organizationId={organizationId}
propertyId={propertyId}
categoryClassifier={categoryClassifier}
onDivisionsFound={setDivisions}
form={form}
/>
</Col>
)}
<Col span={11}>
<TicketFormItem
name={'executor'}
rules={validations.executor}
label={<LabelWithInfo title={ExecutorExtra} message={ExecutorLabel}/>}
>
<GraphQlSearchInput
showArrow={false}
disabled={disableUserInteraction}
formatLabel={formatUserFieldLabel}
renderOptions={renderOptionGroups}
search={searchEmployeeUser(organizationId, ({ role }) => (
get(role, 'canBeAssignedAsExecutor', false)
))}
/>
</TicketFormItem>
</Col>
<Col span={11}>
<TicketFormItem
data-cy={'ticket__assignee-item'}
name={'assignee'}
rules={validations.assignee}
label={<LabelWithInfo title={ResponsibleExtra} message={ResponsibleLabel}/>}
>
<GraphQlSearchInput
formatLabel={formatUserFieldLabel}
showArrow={false}
disabled={disableUserInteraction}
search={searchEmployeeUser(organizationId, ({ role }) => (
get(role, 'canBeAssignedAsResponsible', false)
))}
/>
</TicketFormItem>
</Col>
</Row>
</Col>
</Row>
</Col>
)
}