Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 205x 205x 25133x 25133x 25133x 25133x 25133x 50280x 50280x 50280x 50280x 25133x 50275x 50275x 50275x 9x 9x 4x 50271x 50271x 50271x 50271x 50271x 50271x 24x 50247x 50247x 25133x 25133x | import { utils } from '@ohif/core';
const { formatValue } = utils;
export type ThumbnailDetail = {
id: string;
label: string;
title: string;
value: string;
iconName?: string;
};
type ResolveOptions = {
/** `studyBrowser.thumbnailDetails` - the items to include. */
items;
displaySet;
/** `studyBrowser.thumbnailDetailSources` - named value sources. */
sources?: Record<string, (props) => unknown>;
/** `studyBrowser.thumbnailDetailTests` - named `condition` tests. */
tests?: Record<string, (props) => boolean>;
formatters;
};
/**
* The `<kind> "<value>"` names already reported by {@link resolveThumbnailDetails}.
*
* A broken customization is broken for every item of every thumbnail, and the
* details are re-resolved on each re-map, so the same name would otherwise be
* reported thousands of times while a large study loads. One report per name
* says everything the developer needs, so the rest are dropped.
*/
const reportedNames = new Set<string>();
/**
* Builds the detail line of a study browser thumbnail from the
* `studyBrowser.thumbnailDetails` items, in the order they are declared.
*
* Each item contributes its value, taken from its own `contentF`, from a named
* `source`, or from an `attribute` of the instance the display set shows - the
* same three ways the viewport overlay items get theirs. An item whose
* `condition` says no, or which has no value to show, is left out.
*
* Returns `undefined` when there are no items to resolve at all, which leaves
* the thumbnail showing the default detail line it stands alone with. An empty
* `items` is a customization asking for an empty line, and is honoured as one.
*
* A line that came out empty only because the names it used could not be
* resolved is a broken customization rather than a request for an empty line -
* an override of `studyBrowser.thumbnailDetailSources` written with `$set`
* removes the sources the default items name - so that too is returned as
* `undefined`, leaving every thumbnail its default detail line instead of
* blanking the series number and instance count on all of them.
*/
export function resolveThumbnailDetails({
items,
displaySet,
sources,
tests,
formatters,
}: ResolveOptions): ThumbnailDetail[] | undefined {
Iif (!Array.isArray(items)) {
return undefined;
}
const props = { displaySet, instance: displaySet?.instance, formatters };
const details: ThumbnailDetail[] = [];
let hasUnresolvedName = false;
/** A `condition` / `source` that is a name resolves against a registry. */
const resolveNamed = (value, registry, kind: string, id: string) => {
Iif (typeof value !== 'string') {
return value;
}
const named = registry?.[value];
Iif (!named) {
const reportKey = `${id}|${kind}|${value}`;
Iif (!reportedNames.has(reportKey)) {
reportedNames.add(reportKey);
console.warn(`Thumbnail detail item "${id}" names an unknown ${kind} "${value}"`);
}
hasUnresolvedName = true;
}
return named;
};
for (const item of items) {
Iif (!item) {
continue;
}
const { id, condition, contentF, source, attribute, iconName } = item;
if (condition !== undefined) {
const test = resolveNamed(condition, tests, 'condition', id);
if (typeof test !== 'function' || !test(props)) {
continue;
}
}
let value;
Iif (typeof contentF === 'function') {
value = contentF(props);
} else if (source !== undefined) {
const sourceF = resolveNamed(source, sources, 'source', id);
value = typeof sourceF === 'function' ? sourceF(props) : undefined;
} else IEif (attribute) {
value = props.instance?.[attribute];
}
const displayValue = formatValue(value);
if (!displayValue) {
continue;
}
const icon = typeof iconName === 'function' ? iconName(props) : iconName;
details.push({
id,
label: item.label ?? '',
title: item.title ?? '',
value: displayValue,
iconName: icon || undefined,
});
}
Iif (!details.length && hasUnresolvedName) {
return undefined;
}
return details;
}
export default resolveThumbnailDetails;
|