|
@@ -11,13 +11,64 @@ export function csv(value?: string): string[] {
|
|
|
return String(value).split(',').map((s) => s.trim()).filter(Boolean);
|
|
return String(value).split(',').map((s) => s.trim()).filter(Boolean);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-export function chipPreview(value?: string): string {
|
|
|
|
|
- const parts = csv(value);
|
|
|
|
|
|
|
+export function chipPreviewParts(parts: string[]): string {
|
|
|
if (parts.length === 0) return '';
|
|
if (parts.length === 0) return '';
|
|
|
if (parts.length === 1) return parts[0];
|
|
if (parts.length === 1) return parts[0];
|
|
|
return `${parts[0]} +${parts.length - 1}`;
|
|
return `${parts[0]} +${parts.length - 1}`;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+export function chipPreview(value?: string): string {
|
|
|
|
|
+ return chipPreviewParts(csv(value));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** Same lookup as RuleFormModal inbound select: remark first, else tag. */
|
|
|
|
|
+export function buildRemarkByTag(
|
|
|
|
|
+ options: Array<{ tag?: string; remark?: string }>,
|
|
|
|
|
+): Record<string, string> {
|
|
|
|
|
+ const map: Record<string, string> = {};
|
|
|
|
|
+ for (const ib of options) {
|
|
|
|
|
+ if (ib.tag) map[ib.tag] = ib.remark?.trim() || ib.tag;
|
|
|
|
|
+ }
|
|
|
|
|
+ return map;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** Format a single inbound tag as `tag (remark)`, or just `tag` when no distinct remark. */
|
|
|
|
|
+export function formatInboundTag(
|
|
|
|
|
+ tag: string,
|
|
|
|
|
+ remarkByTag: Record<string, string> = {},
|
|
|
|
|
+): string {
|
|
|
|
|
+ const label = remarkByTag[tag]?.trim();
|
|
|
|
|
+ if (!label || label === tag) return tag;
|
|
|
|
|
+ return `${tag} (${label})`;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Formatted inbound entries — `tag (remark)` when a distinct remark exists, else
|
|
|
|
|
+ * `tag`. Returns an array (not a joined string) so callers never have to re-split
|
|
|
|
|
+ * on commas, which a remark may legitimately contain.
|
|
|
|
|
+ */
|
|
|
|
|
+export function formatInboundTagList(
|
|
|
|
|
+ tags?: string,
|
|
|
|
|
+ remarkByTag: Record<string, string> = {},
|
|
|
|
|
+): string[] {
|
|
|
|
|
+ return csv(tags).map((tag) => formatInboundTag(tag, remarkByTag));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function inboundTagsDisplayTitle(
|
|
|
|
|
+ tags?: string,
|
|
|
|
|
+ remarkByTag: Record<string, string> = {},
|
|
|
|
|
+): string | undefined {
|
|
|
|
|
+ const list = formatInboundTagList(tags, remarkByTag);
|
|
|
|
|
+ return list.length > 0 ? list.join(', ') : undefined;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function inboundTagChipPreview(
|
|
|
|
|
+ tags?: string,
|
|
|
|
|
+ remarkByTag: Record<string, string> = {},
|
|
|
|
|
+): string {
|
|
|
|
|
+ return chipPreviewParts(formatInboundTagList(tags, remarkByTag));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export function ruleCriteriaChips(rule: RuleRow) {
|
|
export function ruleCriteriaChips(rule: RuleRow) {
|
|
|
const chips: { label: string; value?: string }[] = [];
|
|
const chips: { label: string; value?: string }[] = [];
|
|
|
if (rule.domain) chips.push({ label: 'Domain', value: rule.domain });
|
|
if (rule.domain) chips.push({ label: 'Domain', value: rule.domain });
|